summaryrefslogtreecommitdiff
path: root/lib/versioning.h
blob: 3e0dd33ce8d415a9844fb71dc227700b17919ea9 (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
86
87
// **************************************************************************
// * 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>
#include "../structures.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
	- replaces already existing target files/dirs (supports retry)
		=> (unlikely) risk of data loss for naming convention "versioning":
		race-condition if two FFS instances start at the very same second OR multiple folder pairs process the same filename!!
*/

class FileVersioner
{
public:
    FileVersioner(const Zstring& versioningDirectory, //throw FileError
                  VersioningStyle versioningStyle,
                  const TimeComp& timeStamp) : //max versions per file; < 0 := no limit
        versioningStyle_(versioningStyle),
        versioningDirectory_(versioningDirectory),
        timeStamp_(formatTime<Zstring>(Zstr("%Y-%m-%d %H%M%S"), timeStamp)) //e.g. "2012-05-15 131513"
    {
        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 VersioningStyle versioningStyle_;
    const Zstring versioningDirectory_;
    const Zstring timeStamp_;

    //std::vector<Zstring> fileRelNames; //store list of revisioned file and symlink relative names 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