summaryrefslogtreecommitdiff
path: root/lib/versioning.h
blob: 36721edb0ce29dd0183ce719e04dde354ec7330b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// **************************************************************************
// * This file is part of the FreeFileSync project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html       *
// * Copyright (C) ZenJu (zenju AT gmx DOT de) - All Rights Reserved        *
// **************************************************************************

#ifndef VERSIONING_HEADER_8760247652438056
#define VERSIONING_HEADER_8760247652438056

#include <vector>
#include <functional>
#include <zen/time.h>
#include <zen/zstring.h>
#include <zen/int64.h>
#include <zen/file_error.h>

namespace zen
{
struct CallbackMoveFile;

//e.g. move C:\Source\subdir\Sample.txt -> D:\Revisions\subdir\Sample.txt 2012-05-15 131513.txt
//scheme: <revisions directory>\<relpath>\<filename>.<ext> YYYY-MM-DD HHMMSS.<ext>
/*
	- ignores missing source files/dirs
	- creates missing intermediate directories
	- does not create empty directories
	- handles symlinks
	- ignores already existing target files/dirs (support retry)
		=> (unlikely) risk of data loss: race-condition if two FFS instances start at the very same second and process the same filename!!
*/

class FileVersioner
{
public:
    FileVersioner(const Zstring& versioningDirectory, //throw FileError
                  const TimeComp& timeStamp,
                  int versionCountLimit) : //max versions per file; < 0 := no limit
        versioningDirectory_(versioningDirectory),
        timeStamp_(formatTime<Zstring>(Zstr("%Y-%m-%d %H%M%S"), timeStamp)), //e.g. "2012-05-15 131513"
        versionCountLimit_(versionCountLimit)
    {
        if (timeStamp_.size() != 17) //formatTime() returns empty string on error; unexpected length: e.g. problem in year 10000!
            throw FileError(_("Failure to create time stamp for versioning:") + L" \'" + timeStamp_ + L"\'");
    }

    void revisionFile(const Zstring& sourceFile, const Zstring& relativeName, CallbackMoveFile& callback); //throw FileError
    void revisionDir (const Zstring& sourceDir,  const Zstring& relativeName, CallbackMoveFile& callback); //throw FileError

    void limitVersions(std::function<void()> updateUI); //throw FileError; call when done revisioning!

private:
    const Zstring versioningDirectory_;
    const Zstring timeStamp_;
    const int versionCountLimit_;

    std::vector<Zstring> fileRelnames; //store list of revisioned files and symlinks (relativeName) for limitVersions()
};


struct CallbackMoveFile
{
    virtual ~CallbackMoveFile() {} //see CallbackCopyFile for limitations when throwing exceptions!

    virtual void onBeforeFileMove(const Zstring& fileFrom, const Zstring& fileTo) = 0; //one call before each (planned) move
    virtual void onBeforeDirMove (const Zstring& dirFrom,  const Zstring& dirTo ) = 0; //
    virtual void objectProcessed() = 0; //one call after each completed move (count objects total)

    //called frequently if move has to revert to copy + delete:
    virtual void updateStatus(Int64 bytesDelta) = 0;
};








namespace impl //declare for unit tests:
{
bool isMatchingVersion(const Zstring& shortname, const Zstring& shortnameVersion);
}
}

#endif //VERSIONING_HEADER_8760247652438056
bgstack15