21#include <wx/zipstrm.h>
22#include <wx/txtstrm.h>
23#include <wx/wfstream.h>
27#include <wx/encconv.h>
29#define COMPRESSIONLEVEL 6
31#include "../kernel/core/utils/stringtools.hpp"
42 wxFileName::Mkdir(
m_revisionPath.GetPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
57 std::vector<wxString> vVectorizedFile;
61 while (fileContent.length())
64 vVectorizedFile.push_back(fileContent.substr(0, fileContent.find(
'\n')));
67 if (fileContent.find(
'\n') != std::string::npos)
68 fileContent.erase(0, fileContent.find(
'\n')+1);
74 return vVectorizedFile;
91 wxString target = content;
93 while (target.find(
"\r\n") != std::string::npos)
94 target.erase(target.find(
"\r\n"), 1);
114 wxZipInputStream zip(in);
115 wxTextInputStream txt(zip,
" \t", wxConvUTF8);
117 std::unique_ptr<wxZipEntry> entry;
121 while (entry.reset(zip.GetNextEntry()), entry.get() !=
nullptr)
124 if (entry->GetName() == revString)
132 revision += wxString(txt.ReadLine()) +
"\r\n";
135 revision.erase(revision.length()-2);
140 if (entry->GetComment() ==
"DIFF")
165 bool revFound =
false;
169 for (
int i = revisionList.size()-1; i >= 0; i--)
172 if (!revFound && revisionList[i].substr(0, revisionList[i].find(
'\t')) == revString)
178 && revisionList[i].find(
"\tMOVE:") == std::string::npos
179 && revisionList[i].find(
"\tRENAME:") == std::string::npos
180 && revisionList[i].find(
"\tTAG:") == std::string::npos)
181 return revisionList[i].substr(0, revisionList[i].find(
'\t'));
206 bool revFound =
false;
210 for (
int i = revisionList.size()-1; i >= 0; i--)
213 if (!revFound && revisionList[i].substr(0, revisionList[i].find(
'\t')) == revString)
218 && (revisionList[i].find(
"\tInitial revision") != std::string::npos
219 || revisionList[i].substr(revisionList[i].length()-1) ==
"\t"))
220 return revisionList[i].substr(0, revisionList[i].find(
'\t'));
241wxString
FileRevisions::diff(
const wxString& revision1,
const wxString& revisionID1,
const wxString& revision2,
const wxString& revisionID2)
255 std::ostringstream uniDiff;
258 if (revisionID1.length() && revisionID2.length())
259 uniDiff <<
"--- " << revisionID1 <<
"\n+++ " << revisionID2 <<
"\n";
264 return uniDiff.str();
304 int nCurrentInputLine = 0;
308 for (
size_t i = 2; i < vVectorizedDiff.size(); i++)
313 if (vVectorizedDiff[i].substr(0, 4) ==
"@@ -")
315 nCurrentInputLine = atoi(vVectorizedDiff[i].substr(vVectorizedDiff[i].find(
'+')+1, vVectorizedDiff[i].find(
',', vVectorizedDiff[i].find(
'+') - vVectorizedDiff[i].find(
'+')-1)).c_str())-1;
321 if (vVectorizedDiff[i][0] ==
'-')
323 vVectorizedRoot.erase(vVectorizedRoot.begin()+nCurrentInputLine);
328 if (vVectorizedDiff[i][0] ==
'+')
329 vVectorizedRoot.insert(vVectorizedRoot.begin()+nCurrentInputLine, vVectorizedDiff[i].substr(1));
338 for (
size_t i = 0; i < vVectorizedRoot.size(); i++)
339 mergedFile += vVectorizedRoot[i] +
"\r\n";
343 return mergedFile.substr(0, mergedFile.length()-2);
359 std::ifstream file_in;
360 wxString sFileContents;
364 file_in.open(filePath.ToStdString().c_str());
366 while (file_in.good() && !file_in.eof())
368 std::getline(file_in, sLine);
369 sFileContents += sLine +
"\r\n";
372 sFileContents.erase(sFileContents.length()-2);
374 return sFileContents;
393 std::unique_ptr<wxFFileInputStream> in(
new wxFFileInputStream(
m_revisionPath.GetFullPath()));
396 wxZipInputStream inzip(*in);
398 wxTextOutputStream txt(outzip);
400 std::unique_ptr<wxZipEntry> entry;
402 outzip.CopyArchiveMetaData(inzip);
405 while (entry.reset(inzip.GetNextEntry()), entry.get() !=
nullptr)
407 outzip.CopyEntry(entry.release(), inzip);
411 wxZipEntry* currentRev =
new wxZipEntry(
"rev" +
toString(revisionNo));
412 currentRev->SetComment(comment);
414 outzip.PutNextEntry(currentRev);
442 wxString revision =
"TAG FOR " + revString;
444 wxZipEntry* taggedRevision =
new wxZipEntry(
"tag" + revString.substr(3) +
"-rev" +
toString(revisionNo));
445 taggedRevision->SetComment(
"TAG: " + comment);
447 std::unique_ptr<wxFFileInputStream> in(
new wxFFileInputStream(
m_revisionPath.GetFullPath()));
450 wxZipInputStream inzip(*in);
452 wxTextOutputStream txt(outzip);
454 std::unique_ptr<wxZipEntry> entry;
456 outzip.CopyArchiveMetaData(inzip);
459 while (entry.reset(inzip.GetNextEntry()), entry.get() !=
nullptr)
462 if (entry->GetName() == revString)
464 outzip.CopyEntry(entry.release(), inzip);
468 outzip.PutNextEntry(taggedRevision);
473 outzip.CopyEntry(entry.release(), inzip);
502 wxFileName newPath(newRevPath);
504 if (!newPath.DirExists())
505 wxFileName::Mkdir(newPath.GetPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
521 const size_t MINFILESIZE = 1024;
522 double dOffset = nFileSize > MINFILESIZE ? ((double)MINFILESIZE / (
double)nFileSize) : 0.5;
523 size_t nTargetFileSize = ((1.0 - dOffset) * 0.8 * exp(-(
double)
getRevisionCount() / 40.0) + dOffset) * nFileSize;
524 return nTargetFileSize > (MINFILESIZE / 2) ? nTargetFileSize : (MINFILESIZE / 2);
540 wxZipInputStream zip(in);
542 return zip.GetTotalEntries();
559 wxArrayString stringArray;
564 wxZipInputStream zip(in);
566 std::unique_ptr<wxZipEntry> entry;
570 while (entry.reset(zip.GetNextEntry()), entry.get() !=
nullptr)
572 stringArray.Add(entry->GetName() +
"\t" + entry->GetDateTime().FormatISOCombined(
' ') +
"\t" + entry->GetComment());
592 for (
int i = revList.size()-1; i >= 0; i--)
594 if (revList[i].substr(0, 3) ==
"rev")
595 return revList[i].substr(0, revList[i].find(
'\t'));
636 if (revString.substr(0, 3) ==
"tag")
638 revString.replace(0, 3,
"rev");
639 revString.erase(revString.find(
'-'));
679 restoredFile.Open(targetFile, wxFile::write);
680 restoredFile.Write(revision);
701 restoredFile.Open(targetFile, wxFile::write);
702 restoredFile.Write(revision);
756 wxTextOutputStream txt(zip);
758 wxZipEntry* rev0 =
new wxZipEntry(
"rev0");
759 rev0->SetComment(
"Initial revision");
761 zip.PutNextEntry(rev0);
773 wxString diffFile =
createDiff(revisionContent);
799 if (!revContent.length())
800 revContent =
"Other error";
805 if (currRev == revContent)
809 if (!
diff(currRev,
"", revContent,
"").length())
830 std::unique_ptr<wxFFileInputStream> in(
new wxFFileInputStream(
m_revisionPath.GetFullPath()));
833 wxZipInputStream inzip(*in);
835 wxTextOutputStream txt(outzip);
837 std::unique_ptr<wxZipEntry> entry;
839 outzip.CopyArchiveMetaData(inzip);
841 while (entry.reset(inzip.GetNextEntry()), entry.get() !=
nullptr)
843 if (entry->GetName() !=
"rev" + wxString(
toString(revisionNo-1)))
844 outzip.CopyEntry(entry.release(), inzip);
870 fileMove(newRevPath,
"RENAME: " + oldName +
" -> " + newName);
887 fileMove(newRevPath,
"MOVE: " + oldPath +
" -> " + newPath);
wxString getRevision(size_t nRevision)
Returns the contents of the selected revision.
size_t addRevision(const wxString &revisionContent)
This method adds a new revision.
void renameFile(const wxString &oldName, const wxString &newName, const wxString &newRevPath)
This method handles renames of the corresponding file.
size_t getRevisionCount()
Returns the number of available revisions.
void restoreRevision(size_t nRevision, const wxString &targetFile)
This method will restore the contents of the selected revision.
wxArrayString getRevisionList()
This method returns a log-like list of revisions.
wxString createMerge(const wxString &diffFile)
This method merges the diff file into the current revision root.
FileRevisions(const wxString &revisionPath)
Constructor. Will try to create the missing folders on-the-fly.
size_t createNewTag(const wxString &revString, const wxString &comment)
This method creates a new tag for the passed revision.
wxString convertLineEndings(const wxString &content)
This method converts line end characters.
size_t createNewRevision(const wxString &revContent, const wxString &comment)
This method creates a new revision.
wxFileName m_revisionPath
size_t tagRevision(size_t nRevision, const wxString &tagComment)
Allows the user to tag a selected revision with the passed comment.
wxString diff(const wxString &revision1, const wxString &revisionID1, const wxString &revision2, const wxString &revisionID2)
This method calculates the differences between two files.
wxString readRevision(const wxString &revString)
This method returns the contents of the selected revision.
wxString getLastContentModification(const wxString &revString)
This method returns the last modification revision identifier.
void undoRevision()
This method removes the last added revision.
wxString compareRevisions(const wxString &rev1, const wxString &rev2)
This member function compares two revisions with each other and returns the differnces as unified dif...
wxString getLastRevisionRoot(const wxString &revString)
This method returns the revision identifier of the last revision root.
void moveFile(const wxString &oldPath, const wxString &newPath, const wxString &newRevPath)
This method handles moves of the corresponding file.
wxString readExternalFile(const wxString &filePath)
This method reads an external file into a string.
std::vector< wxString > vectorize(wxString fileContent)
Converts a single-string file into a vector of strings.
void fileMove(const wxString &newRevPath, const wxString &comment)
This method handles all file move operations.
size_t addExternalRevision(const wxString &filePath)
This method adds an external modification as new revision.
wxString createDiff(const wxString &revisionContent)
This method creates the file differences between the file contents and the current revision root.
wxString getCurrentRevision()
This method returns the revision identifier of the current revision.
size_t getMaxDiffFileSize(size_t nFileSize)
This member function returns the maximal Diff file size.
void printUnifiedFormat(stream &out) const
void composeUnifiedHunks()
std::string toString(int)
Converts an integer to a string without the Settings bloat.