summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Wilhelm <shieldwed@outlook.com>2017-01-09 10:54:11 +0100
committerDaniel Wilhelm <shieldwed@outlook.com>2017-01-09 10:54:11 +0100
commit6011596a2f247bde24095e985f6e2547e4b191ef (patch)
tree296003a2c8952f41b2998653ba02911ba2b83b0a
parent8.7 (diff)
downloadFreeFileSync-6011596a2f247bde24095e985f6e2547e4b191ef.tar.gz
FreeFileSync-6011596a2f247bde24095e985f6e2547e4b191ef.tar.bz2
FreeFileSync-6011596a2f247bde24095e985f6e2547e4b191ef.zip
8.8
-rw-r--r--FreeFileSync/Build/Changelog.txt17
-rw-r--r--FreeFileSync/Build/Languages/dutch.lng2
-rw-r--r--FreeFileSync/Build/Languages/german.lng49
-rw-r--r--FreeFileSync/Source/RealTimeSync/application.cpp6
-rw-r--r--FreeFileSync/Source/RealTimeSync/grep0
-rw-r--r--FreeFileSync/Source/RealTimeSync/gui_generated.cpp16
-rw-r--r--FreeFileSync/Source/RealTimeSync/gui_generated.h4
-rw-r--r--FreeFileSync/Source/RealTimeSync/main_dlg.cpp4
-rw-r--r--FreeFileSync/Source/RealTimeSync/monitor.cpp66
-rw-r--r--FreeFileSync/Source/algorithm.cpp88
-rw-r--r--FreeFileSync/Source/application.cpp24
-rw-r--r--FreeFileSync/Source/comparison.cpp41
-rw-r--r--FreeFileSync/Source/file_hierarchy.h136
-rw-r--r--FreeFileSync/Source/fs/abstract.cpp260
-rw-r--r--FreeFileSync/Source/fs/abstract.h125
-rw-r--r--FreeFileSync/Source/fs/native.cpp210
-rw-r--r--FreeFileSync/Source/fs/native_traverser_impl.h6
-rw-r--r--FreeFileSync/Source/lib/db_file.cpp32
-rw-r--r--FreeFileSync/Source/lib/dir_exist_async.h7
-rw-r--r--FreeFileSync/Source/lib/dir_lock.cpp18
-rw-r--r--FreeFileSync/Source/lib/ffs_paths.cpp6
-rw-r--r--FreeFileSync/Source/lib/icon_buffer.cpp6
-rw-r--r--FreeFileSync/Source/lib/parallel_scan.cpp22
-rw-r--r--FreeFileSync/Source/lib/parallel_scan.h2
-rw-r--r--FreeFileSync/Source/lib/parse_plural.h18
-rw-r--r--FreeFileSync/Source/lib/process_xml.cpp64
-rw-r--r--FreeFileSync/Source/lib/status_handler.h6
-rw-r--r--FreeFileSync/Source/lib/versioning.cpp305
-rw-r--r--FreeFileSync/Source/lib/versioning.h8
-rw-r--r--FreeFileSync/Source/synchronization.cpp137
-rw-r--r--FreeFileSync/Source/ui/batch_status_handler.cpp10
-rw-r--r--FreeFileSync/Source/ui/custom_grid.cpp2
-rw-r--r--FreeFileSync/Source/ui/folder_selector.cpp27
-rw-r--r--FreeFileSync/Source/ui/gui_generated.cpp334
-rw-r--r--FreeFileSync/Source/ui/gui_generated.h16
-rw-r--r--FreeFileSync/Source/ui/main_dlg.cpp143
-rw-r--r--FreeFileSync/Source/ui/main_dlg.h4
-rw-r--r--FreeFileSync/Source/ui/progress_indicator.cpp2
-rw-r--r--FreeFileSync/Source/ui/small_dlgs.cpp6
-rw-r--r--FreeFileSync/Source/ui/sorting.h2
-rw-r--r--FreeFileSync/Source/ui/sync_cfg.cpp16
-rw-r--r--FreeFileSync/Source/ui/tree_view.cpp32
-rw-r--r--FreeFileSync/Source/ui/version_check.cpp10
-rw-r--r--FreeFileSync/Source/ui/version_check_impl.h8
-rw-r--r--FreeFileSync/Source/version/version.h2
-rw-r--r--wx+/graph.cpp2
-rw-r--r--wx+/popup_dlg_generated.cpp10
-rw-r--r--zen/dir_watcher.cpp2
-rw-r--r--zen/file_access.cpp620
-rw-r--r--zen/file_access.h42
-rw-r--r--zen/file_error.h2
-rw-r--r--zen/file_traverser.cpp42
-rw-r--r--zen/file_traverser.h15
-rw-r--r--zen/fixed_list.h6
-rw-r--r--zen/recycler.cpp104
-rw-r--r--zen/recycler.h6
-rw-r--r--zen/serialize.h2
-rw-r--r--zen/shell_execute.h2
-rw-r--r--zen/thread.h4
59 files changed, 1819 insertions, 1339 deletions
diff --git a/FreeFileSync/Build/Changelog.txt b/FreeFileSync/Build/Changelog.txt
index 2831c26d..7bffa391 100644
--- a/FreeFileSync/Build/Changelog.txt
+++ b/FreeFileSync/Build/Changelog.txt
@@ -1,3 +1,20 @@
+FreeFileSync 8.8 [2017-01-08]
+-----------------------------
+Distinguish file access failure from not existing during sync
+Further optimized number of file I/O operations via file system abstraction
+Report unexpected prompts for keyboard-interactive SFTP authentication
+Mark followed directory symlinks on grid
+Fixed parent path determination for UNC
+Don't skip source files that cannot be accessed
+Don't consider a symlink type for SFTP when comparing by content
+Fixed invalid parameter error when setting file times on exFAT file system
+Don't allow overwriting folder with equally named file when copying from main dialog
+Fixed failure to create intermediate directories for Cryptomator/Webdav
+Refactored file system abstraction layer for future FTP support
+Fixed failure to change file name case on MTP devices
+Fixed late failure for batch recycling when parsing of single item fails
+
+
FreeFileSync 8.7 [2016-12-06]
-----------------------------
New auto-updater feature for FreeFileSync Donation Edition
diff --git a/FreeFileSync/Build/Languages/dutch.lng b/FreeFileSync/Build/Languages/dutch.lng
index 80b2e795..ff73514a 100644
--- a/FreeFileSync/Build/Languages/dutch.lng
+++ b/FreeFileSync/Build/Languages/dutch.lng
@@ -603,7 +603,7 @@ De opdracht wordt geactiveerd als:
<target>Verwijderen van oude versies...</target>
<source>Updating file %x</source>
-<target>File %x bijwerken</target>
+<target>Bestand %x bijwerken</target>
<source>Updating symbolic link %x</source>
<target>Symbolische link %x bijwerken</target>
diff --git a/FreeFileSync/Build/Languages/german.lng b/FreeFileSync/Build/Languages/german.lng
index a3cff38c..803b0bd3 100644
--- a/FreeFileSync/Build/Languages/german.lng
+++ b/FreeFileSync/Build/Languages/german.lng
@@ -7,11 +7,8 @@
<plural_definition>n == 1 ? 0 : 1</plural_definition>
</header>
-<source>Installation was registered on a different operating system.</source>
-<target>Die Installation wurde auf einem anderen Betriebssystem registriert.</target>
-
-<source>The server does not support authentication via %x.</source>
-<target>Der Server unterstützt keine Authentifizierung über %x.</target>
+<source>Cannot delete symbolic link %x.</source>
+<target>Die symbolischen Verknüpfung %x kann nicht gelöscht werden.</target>
<source>Both sides have changed since last synchronization.</source>
<target>Beide Seiten wurden seit der letzten Synchronisation verändert.</target>
@@ -28,12 +25,12 @@
<source>Setting default synchronization directions: Old files will be overwritten with newer files.</source>
<target>Setze Standardwerte für Synchronisationsrichtungen: Alte Dateien werden durch neuere überschrieben.</target>
-<source>Creating folder %x</source>
-<target>Erstelle Ordner %x</target>
-
<source>Creating file %x</source>
<target>Erstelle Datei %x</target>
+<source>Creating folder %x</source>
+<target>Erstelle Ordner %x</target>
+
<source>Creating symbolic link %x</source>
<target>Erstelle symbolische Verknüpfung %x</target>
@@ -288,30 +285,33 @@ Tatsächlich: %y bytes
<source>Cannot read directory %x.</source>
<target>Das Verzeichnis %x kann nicht gelesen werden.</target>
+<source>Cannot read file %x.</source>
+<target>Die Datei %x kann nicht gelesen werden.</target>
+
<source>Cannot read file attributes of %x.</source>
<target>Die Dateiattribute von %x können nicht gelesen werden.</target>
-<source>Cannot find %x.</source>
-<target>%x wurde nicht gefunden.</target>
-
<source>Cannot open file %x.</source>
<target>Die Datei %x kann nicht geöffnet werden.</target>
-<source>Cannot read file %x.</source>
-<target>Die Datei %x kann nicht gelesen werden.</target>
-
<source>Cannot find device %x.</source>
<target>Das Gerät %x wurde nicht gefunden.</target>
+<source>Cannot find %x.</source>
+<target>%x wurde nicht gefunden.</target>
+
+<source>Type of item %x is not supported:</source>
+<target>Der Typ des Elements %x wird nicht unterstützt:</target>
+
<source>Cannot create directory %x.</source>
<target>Das Verzeichnis %x kann nicht erstellt werden.</target>
-<source>Cannot delete directory %x.</source>
-<target>Das Verzeichnis %x kann nicht gelöscht werden.</target>
-
<source>Cannot delete file %x.</source>
<target>Die Datei %x kann nicht gelöscht werden.</target>
+<source>Cannot delete directory %x.</source>
+<target>Das Verzeichnis %x kann nicht gelöscht werden.</target>
+
<source>Cannot write modification time of %x.</source>
<target>Die Änderungszeit von %x kann nicht geschrieben werden.</target>
@@ -330,6 +330,12 @@ Tatsächlich: %y bytes
<source>Incorrect command line:</source>
<target>Ungültige Befehlszeile:</target>
+<source>The server does not support authentication via %x.</source>
+<target>Der Server unterstützt keine Authentifizierung über %x.</target>
+
+<source>Required:</source>
+<target>Benötigt:</target>
+
<source>Unable to access %x.</source>
<target>Auf %x kann nicht zugegriffen werden.</target>
@@ -677,9 +683,6 @@ Die Befehlszeile wird ausgelöst, wenn:
<source>Not enough free disk space available in:</source>
<target>Nicht genügend freier Speicher verfügbar für:</target>
-<source>Required:</source>
-<target>Benötigt:</target>
-
<source>Available:</source>
<target>Verfügbar:</target>
@@ -1777,6 +1780,9 @@ Dadurch wird ein konsistenter Datenstand auch bei schweren Fehlern garantiert.
<source>Consistency check failed for %x.</source>
<target>Die Konsistenzprüfung für %x ist fehlgeschlagen.</target>
+<source>Installation was registered on a different operating system.</source>
+<target>Die Installation wurde auf einem anderen Betriebssystem registriert.</target>
+
<source>Failed to activate FreeFileSync Donation Edition.</source>
<target>Die Aktivierung der FreeFileSync Spendenversion ist fehlgeschlagen.</target>
@@ -1819,9 +1825,6 @@ Dadurch wird ein konsistenter Datenstand auch bei schweren Fehlern garantiert.
<source>Cannot copy attributes from %x to %y.</source>
<target>Die Attribute können nicht von %x nach %y kopiert werden.</target>
-<source>Type of item %x is not supported:</source>
-<target>Der Typ des Elements %x wird nicht unterstützt:</target>
-
<source>%x TB</source>
<target>%x TB</target>
diff --git a/FreeFileSync/Source/RealTimeSync/application.cpp b/FreeFileSync/Source/RealTimeSync/application.cpp
index cc127249..a6edef0e 100644
--- a/FreeFileSync/Source/RealTimeSync/application.cpp
+++ b/FreeFileSync/Source/RealTimeSync/application.cpp
@@ -119,11 +119,11 @@ void Application::onEnterEventLoop(wxEvent& event)
{
Zstring filePath = getResolvedFilePath(toZ(argv[i]));
- if (!fileExists(filePath)) //be a little tolerant
+ if (!fileAvailable(filePath)) //be a little tolerant
{
- if (fileExists(filePath + Zstr(".ffs_real")))
+ if (fileAvailable(filePath + Zstr(".ffs_real")))
filePath += Zstr(".ffs_real");
- else if (fileExists(filePath + Zstr(".ffs_batch")))
+ else if (fileAvailable(filePath + Zstr(".ffs_batch")))
filePath += Zstr(".ffs_batch");
else
{
diff --git a/FreeFileSync/Source/RealTimeSync/grep b/FreeFileSync/Source/RealTimeSync/grep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/FreeFileSync/Source/RealTimeSync/grep
diff --git a/FreeFileSync/Source/RealTimeSync/gui_generated.cpp b/FreeFileSync/Source/RealTimeSync/gui_generated.cpp
index 1b025037..cc5dbb99 100644
--- a/FreeFileSync/Source/RealTimeSync/gui_generated.cpp
+++ b/FreeFileSync/Source/RealTimeSync/gui_generated.cpp
@@ -13,7 +13,7 @@
MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
- this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
+ this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize );
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
m_menubar1 = new wxMenuBar( 0 );
@@ -23,13 +23,13 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
m_menuFile->Append( m_menuItem13 );
wxMenuItem* m_menuItem14;
- m_menuItem14 = new wxMenuItem( m_menuFile, wxID_SAVEAS, wxString( _("Save &as...") ) , wxEmptyString, wxITEM_NORMAL );
+ m_menuItem14 = new wxMenuItem( m_menuFile, wxID_SAVEAS, wxString( _("Save &as...") ), wxEmptyString, wxITEM_NORMAL );
m_menuFile->Append( m_menuItem14 );
m_menuFile->AppendSeparator();
wxMenuItem* m_menuItem4;
- m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ) , wxEmptyString, wxITEM_NORMAL );
+ m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ), wxEmptyString, wxITEM_NORMAL );
m_menuFile->Append( m_menuItem4 );
m_menubar1->Append( m_menuFile, _("&File") );
@@ -127,12 +127,12 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
wxBoxSizer* bSizer20;
bSizer20 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonAddFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW );
+ m_bpButtonAddFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25, 25 ), wxBU_AUTODRAW );
m_bpButtonAddFolder->SetToolTip( _("Add folder") );
bSizer20->Add( m_bpButtonAddFolder, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonRemoveTopFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW );
+ m_bpButtonRemoveTopFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25, 25 ), wxBU_AUTODRAW );
m_bpButtonRemoveTopFolder->SetToolTip( _("Remove folder") );
bSizer20->Add( m_bpButtonRemoveTopFolder, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -143,7 +143,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
wxBoxSizer* bSizer19;
bSizer19 = new wxBoxSizer( wxHORIZONTAL );
- m_txtCtrlDirectoryMain = new wxTextCtrl( m_panelMainFolder, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 300,-1 ), 0 );
+ m_txtCtrlDirectoryMain = new wxTextCtrl( m_panelMainFolder, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 300, -1 ), 0 );
m_txtCtrlDirectoryMain->SetMaxLength( 0 );
bSizer19->Add( m_txtCtrlDirectoryMain, 1, wxALIGN_CENTER_VERTICAL, 5 );
@@ -222,7 +222,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
m_staticline5 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizerMain->Add( m_staticline5, 0, wxEXPAND, 5 );
- m_buttonStart = new zen::BitmapTextButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonStart = new zen::BitmapTextButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonStart->SetDefault();
m_buttonStart->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
@@ -258,7 +258,7 @@ FolderGenerated::FolderGenerated( wxWindow* parent, wxWindowID id, const wxPoint
wxBoxSizer* bSizer114;
bSizer114 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonRemoveFolder = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW );
+ m_bpButtonRemoveFolder = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25, 25 ), wxBU_AUTODRAW );
m_bpButtonRemoveFolder->SetToolTip( _("Remove folder") );
bSizer114->Add( m_bpButtonRemoveFolder, 0, wxALIGN_CENTER_VERTICAL, 5 );
diff --git a/FreeFileSync/Source/RealTimeSync/gui_generated.h b/FreeFileSync/Source/RealTimeSync/gui_generated.h
index f3018d48..b16f1a97 100644
--- a/FreeFileSync/Source/RealTimeSync/gui_generated.h
+++ b/FreeFileSync/Source/RealTimeSync/gui_generated.h
@@ -89,7 +89,7 @@ protected:
public:
- MainDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
+ MainDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
~MainDlgGenerated();
@@ -109,7 +109,7 @@ public:
wxBitmapButton* m_bpButtonRemoveFolder;
wxTextCtrl* m_txtCtrlDirectory;
- FolderGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = 0 );
+ FolderGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = 0 );
~FolderGenerated();
};
diff --git a/FreeFileSync/Source/RealTimeSync/main_dlg.cpp b/FreeFileSync/Source/RealTimeSync/main_dlg.cpp
index 4bb61add..61c7d255 100644
--- a/FreeFileSync/Source/RealTimeSync/main_dlg.cpp
+++ b/FreeFileSync/Source/RealTimeSync/main_dlg.cpp
@@ -100,7 +100,7 @@ MainDialog::MainDialog(wxDialog* dlg, const Zstring& cfgFileName)
//--------------------------- load config values ------------------------------------
xmlAccess::XmlRealConfig newConfig;
- const Zstring currentConfigFile = cfgFileName.empty() ? lastRunConfigPath_ : cfgFileName;
+ const Zstring currentConfigFile = !cfgFileName.empty() ? cfgFileName : lastRunConfigPath_;
bool loadCfgSuccess = false;
if (!cfgFileName.empty() || fileExists(lastRunConfigPath_))
try
@@ -324,7 +324,7 @@ void MainDialog::OnConfigLoad(wxCommandEvent& event)
wxFileDialog filePicker(this,
wxString(),
utfCvrtTo<wxString>(beforeLast(currentConfigFileName_, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE)), //default dir
- wxString(),
+ wxString(), //default file
wxString(L"RealTimeSync (*.ffs_real; *.ffs_batch)|*.ffs_real;*.ffs_batch") + L"|" +_("All files") + L" (*.*)|*",
wxFD_OPEN);
if (filePicker.ShowModal() == wxID_OK)
diff --git a/FreeFileSync/Source/RealTimeSync/monitor.cpp b/FreeFileSync/Source/RealTimeSync/monitor.cpp
index a7902eb6..87c7e5e1 100644
--- a/FreeFileSync/Source/RealTimeSync/monitor.cpp
+++ b/FreeFileSync/Source/RealTimeSync/monitor.cpp
@@ -50,46 +50,47 @@ struct WaitResult
enum ChangeType
{
CHANGE_DETECTED,
- CHANGE_DIR_MISSING
+ CHANGE_DIR_UNAVAILABLE //not existing or can't access
};
WaitResult(const zen::DirWatcher::Entry& changedItem) : type(CHANGE_DETECTED), changedItem_(changedItem) {}
- WaitResult(const Zstring& folderPath) : type(CHANGE_DIR_MISSING), folderPath_(folderPath) {}
+ WaitResult(const Zstring& folderPath) : type(CHANGE_DIR_UNAVAILABLE), folderPath_(folderPath) {}
ChangeType type;
zen::DirWatcher::Entry changedItem_; //for type == CHANGE_DETECTED: file or directory
- Zstring folderPath_; //for type == CHANGE_DIR_MISSING
+ Zstring folderPath_; //for type == CHANGE_DIR_UNAVAILABLE
};
WaitResult waitForChanges(const std::vector<Zstring>& folderPathPhrases, //throw FileError
const std::function<void(bool readyForSync)>& onRefreshGui)
{
- const std::vector<Zstring> folderPathsFmt = getFormattedDirs(folderPathPhrases); //throw FileError
- if (folderPathsFmt.empty()) //pathological case, but we have to check else this function will wait endlessly
+ const std::vector<Zstring> folderPaths = getFormattedDirs(folderPathPhrases); //throw FileError
+ if (folderPaths.empty()) //pathological case, but we have to check else this function will wait endlessly
throw FileError(_("A folder input field is empty.")); //should have been checked by caller!
//detect when volumes are removed/are not available anymore
std::vector<std::pair<Zstring, std::shared_ptr<DirWatcher>>> watches;
- for (const Zstring& folderPathFmt : folderPathsFmt)
+ for (const Zstring& folderPath : folderPaths)
{
try
{
//a non-existent network path may block, so check existence asynchronously!
- auto ftDirExists = runAsync([=] { return zen::dirExists(folderPathFmt); });
- //we need to check dirExists(), not somethingExists(): it's not clear if DirWatcher detects a type clash (file instead of directory!)
- while (ftDirExists.wait_for(std::chrono::milliseconds(rts::UI_UPDATE_INTERVAL_MS / 2)) != std::future_status::ready)
+ auto ftDirAvailable = runAsync([=] { return dirAvailable(folderPath); });
+
+ while (ftDirAvailable.wait_for(std::chrono::milliseconds(rts::UI_UPDATE_INTERVAL_MS / 2)) != std::future_status::ready)
onRefreshGui(false /*readyForSync*/); //may throw!
- if (!ftDirExists.get())
- return WaitResult(folderPathFmt);
- watches.emplace_back(folderPathFmt, std::make_shared<DirWatcher>(folderPathFmt)); //throw FileError
+ if (!ftDirAvailable.get()) //folder not existing or can't access
+ return WaitResult(folderPath);
+
+ watches.emplace_back(folderPath, std::make_shared<DirWatcher>(folderPath)); //throw FileError
}
catch (FileError&)
{
- if (!somethingExists(folderPathFmt)) //a benign(?) race condition with FileError
- return WaitResult(folderPathFmt);
+ if (!dirAvailable(folderPath)) //folder not existing or can't access
+ return WaitResult(folderPath);
throw;
}
}
@@ -97,7 +98,7 @@ WaitResult waitForChanges(const std::vector<Zstring>& folderPathPhrases, //throw
auto lastCheckTime = std::chrono::steady_clock::now();
for (;;)
{
- const bool checkDirExistNow = [&]() -> bool //checking once per sec should suffice
+ const bool checkDirNow = [&]() -> bool //checking once per sec should suffice
{
const auto now = std::chrono::steady_clock::now();
@@ -116,8 +117,8 @@ WaitResult waitForChanges(const std::vector<Zstring>& folderPathPhrases, //throw
DirWatcher& watcher = *(it->second);
//IMPORTANT CHECK: dirwatcher has problems detecting removal of top watched directories!
- if (checkDirExistNow)
- if (!dirExists(folderPath)) //catch errors related to directory removal, e.g. ERROR_NETNAME_DELETED -> somethingExists() is NOT sufficient here!
+ if (checkDirNow)
+ if (!dirAvailable(folderPath)) //catch errors related to directory removal, e.g. ERROR_NETNAME_DELETED
return WaitResult(folderPath);
try
{
@@ -141,7 +142,7 @@ WaitResult waitForChanges(const std::vector<Zstring>& folderPathPhrases, //throw
}
catch (FileError&)
{
- if (!somethingExists(folderPath)) //a benign(?) race condition with FileError
+ if (!dirAvailable(folderPath)) //a benign(?) race condition with FileError
return WaitResult(folderPath);
throw;
}
@@ -159,41 +160,42 @@ void waitForMissingDirs(const std::vector<Zstring>& folderPathPhrases, //throw F
{
for (;;)
{
- bool allExisting = true;
+ bool allAvailable = true;
//support specifying volume by name => call getResolvedFilePath() repeatedly
- for (const Zstring& folderPathFmt : getFormattedDirs(folderPathPhrases)) //throw FileError
+ for (const Zstring& folderPath : getFormattedDirs(folderPathPhrases)) //throw FileError
{
- auto ftDirExisting = runAsync([=]
+ auto ftDirAvailable = runAsync([=]
{
#ifdef ZEN_WIN
//1. login to network share, if necessary -> we probably do NOT want multiple concurrent runs: GUI!?
- try{
- connectNetworkShare(folderPathFmt, false /*allowUserInteraction*/); //throw FileError
+ try
+ {
+ connectNetworkShare(folderPath, false /*allowUserInteraction*/); //throw FileError
//is this really RTS's job?
}
catch (FileError&) {}
#endif
- //2. check dir existence
- return zen::dirExists(folderPathFmt);
+ //2. check dir availability
+ return dirAvailable(folderPath);
});
- while (ftDirExisting.wait_for(std::chrono::milliseconds(rts::UI_UPDATE_INTERVAL_MS / 2)) != std::future_status::ready)
- onRefreshGui(folderPathFmt); //may throw!
+ while (ftDirAvailable.wait_for(std::chrono::milliseconds(rts::UI_UPDATE_INTERVAL_MS / 2)) != std::future_status::ready)
+ onRefreshGui(folderPath); //may throw!
- if (!ftDirExisting.get())
+ if (!ftDirAvailable.get())
{
- allExisting = false;
+ allAvailable = false;
//wait some time...
const int refreshInterval = rts::UI_UPDATE_INTERVAL_MS / 2;
static_assert(FOLDER_EXISTENCE_CHECK_INTERVAL_SEC * 1000 % refreshInterval == 0, "");
for (int i = 0; i < FOLDER_EXISTENCE_CHECK_INTERVAL_SEC * 1000 / refreshInterval; ++i)
{
- onRefreshGui(folderPathFmt); //may throw!
+ onRefreshGui(folderPath); //may throw!
std::this_thread::sleep_for(std::chrono::milliseconds(refreshInterval));
}
break;
}
}
- if (allExisting)
+ if (allAvailable)
return;
}
}
@@ -252,7 +254,7 @@ void rts::monitorDirectories(const std::vector<Zstring>& folderPathPhrases, unsi
});
switch (res.type)
{
- case WaitResult::CHANGE_DIR_MISSING: //don't execute the command before all directories are available!
+ case WaitResult::CHANGE_DIR_UNAVAILABLE: //don't execute the command before all directories are available!
callback.setPhase(MonitorCallback::MONITOR_PHASE_WAITING);
waitForMissingDirs(folderPathPhrases, [&](const Zstring& folderPath) { callback.requestUiRefresh(); }); //throw FileError
callback.setPhase(MonitorCallback::MONITOR_PHASE_ACTIVE);
diff --git a/FreeFileSync/Source/algorithm.cpp b/FreeFileSync/Source/algorithm.cpp
index 1def34af..1dbc2f5c 100644
--- a/FreeFileSync/Source/algorithm.cpp
+++ b/FreeFileSync/Source/algorithm.cpp
@@ -1153,26 +1153,36 @@ void copyToAlternateFolderFrom(const std::vector<const FileSystemObject*>& rowsT
callback.reportInfo(replaceCpy(statusText, L"%x", fmtPath(displayPath)));
};
- const std::wstring txtCreatingFolder(_("Creating folder %x" ));
const std::wstring txtCreatingFile (_("Creating file %x" ));
+ const std::wstring txtCreatingFolder(_("Creating folder %x" ));
const std::wstring txtCreatingLink (_("Creating symbolic link %x"));
auto copyItem = [&](const FileSystemObject& fsObj, const AbstractPath& targetPath) //throw FileError
{
- const std::function<void()> deleteTargetItem = [&]
+ const std::function<void()> removeTargetItem = [&]
{
if (overwriteIfExists)
try
{
//file or (broken) file-symlink:
- AFS::removeFile(targetPath); //throw FileError
+ AFS::removeFilePlain(targetPath); //throw FileError
}
catch (FileError&)
{
- //folder or folder-symlink:
- if (AFS::folderExists(targetPath)) //directory or dir-symlink
- AFS::removeFolderRecursively(targetPath, nullptr /*onBeforeFileDeletion*/, nullptr /*onBeforeFolderDeletion*/); //throw FileError
- else
+ //(folder-)symlink:
+ bool symlinkExists = false;
+ try
+ {
+ if (Opt<AFS::ItemType> type = AFS::getItemTypeIfExists(targetPath)) //throw FileError
+ symlinkExists = *type == AFS::ItemType::SYMLINK;
+ else
+ return;
+ }
+ catch (FileError&) {} //previous exception is more relevant
+
+ if (symlinkExists)
+ AFS::removeSymlinkPlain(targetPath); //throw FileError
+ else //overwrite AFS::ItemType::FOLDER with FILE? => highly dubious, do not allow
throw;
}
};
@@ -1181,13 +1191,20 @@ void copyToAlternateFolderFrom(const std::vector<const FileSystemObject*>& rowsT
{
StatisticsReporter statReporter(1, 0, callback);
notifyItemCopy(txtCreatingFolder, AFS::getDisplayPath(targetPath));
-
try
{
- //deleteTargetItem(); -> never delete pre-existing folders!!! => might delete child items we just copied!
+ //removeTargetItem(); -> never delete pre-existing folders!!! => might delete child items we just copied before!
AFS::copyNewFolder(folder.getAbstractPath<side>(), targetPath, false /*copyFilePermissions*/); //throw FileError
}
- catch (const FileError&) { if (!AFS::folderExists(targetPath)) throw; } //might already exist: see creation of intermediate directories below
+ catch (FileError&)
+ {
+ bool folderAlreadyExists = false;
+ try { folderAlreadyExists = AFS::getItemType(targetPath) == AFS::ItemType::FOLDER; } /*throw FileError*/ catch (FileError&) {} //previous exception is more relevant
+
+ if (!folderAlreadyExists)
+ throw;
+ //folder might already exist: see creation of intermediate directories below
+ }
statReporter.reportDelta(1, 0);
},
@@ -1198,7 +1215,7 @@ void copyToAlternateFolderFrom(const std::vector<const FileSystemObject*>& rowsT
auto onNotifyCopyStatus = [&](std::int64_t bytesDelta) { statReporter.reportDelta(0, bytesDelta); };
AFS::copyFileTransactional(file.getAbstractPath<side>(), targetPath, //throw FileError, ErrorFileLocked
- false /*copyFilePermissions*/, true /*transactionalCopy*/, deleteTargetItem, onNotifyCopyStatus);
+ false /*copyFilePermissions*/, true /*transactionalCopy*/, removeTargetItem, onNotifyCopyStatus);
statReporter.reportDelta(1, 0);
},
@@ -1207,7 +1224,7 @@ void copyToAlternateFolderFrom(const std::vector<const FileSystemObject*>& rowsT
StatisticsReporter statReporter(1, 0, callback);
notifyItemCopy(txtCreatingLink, AFS::getDisplayPath(targetPath));
- deleteTargetItem();
+ removeTargetItem();
AFS::copySymlink(symlink.getAbstractPath<side>(), targetPath, false /*copyFilePermissions*/); //throw FileError
statReporter.reportDelta(1, 0);
});
@@ -1225,16 +1242,26 @@ void copyToAlternateFolderFrom(const std::vector<const FileSystemObject*>& rowsT
}
catch (FileError&)
{
+ warn_static("perf: combine with removeTargetItem!!!")
//create intermediate directories if missing
- const AbstractPath targetParentPath = AFS::appendRelPath(targetFolderPath, beforeLast(relPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE));
- if (!AFS::somethingExists(targetParentPath)) //->(minor) file system race condition!
+ if (Opt<AbstractPath> parentPath = AFS::getParentFolderPath(targetItemPath))
{
- AFS::createFolderRecursively(targetParentPath); //throw FileError
- //retry: this should work now!
- copyItem(*fsObj, targetItemPath); //throw FileError
+ Opt<AFS::PathDetails> pd;
+ try { pd = AFS::getPathDetails(*parentPath); /*throw FileError*/ }
+ catch (FileError&) {} //previous exception is more relevant
+
+ if (pd && !pd->relPath.empty()) //parent folder not existing
+ {
+ AbstractPath intermediatePath = pd->existingPath;
+ for (const Zstring& itemName : pd->relPath)
+ AFS::createFolderPlain(intermediatePath = AFS::appendRelPath(intermediatePath, itemName)); //throw FileError
+
+ //retry: this should work now!
+ copyItem(*fsObj, targetItemPath); //throw FileError
+ return;
+ }
}
- else
- throw;
+ throw;
}
}, callback); //throw X?
}
@@ -1319,7 +1346,7 @@ void deleteFromGridAndHDOneSide(std::vector<FileSystemObject*>& rowsToDelete,
if (useRecycleBin)
{
notifyItemDeletion(txtRemovingDirectory, AFS::getDisplayPath(folder.getAbstractPath<side>()));
- AFS::recycleItemDirectly(folder.getAbstractPath<side>()); //throw FileError
+ AFS::recycleItemIfExists(folder.getAbstractPath<side>()); //throw FileError
statReporter.reportDelta(1, 0);
}
else
@@ -1335,7 +1362,7 @@ void deleteFromGridAndHDOneSide(std::vector<FileSystemObject*>& rowsToDelete,
notifyItemDeletion(txtRemovingDirectory, displayPath);
};
- AFS::removeFolderRecursively(folder.getAbstractPath<side>(), onBeforeFileDeletion, onBeforeDirDeletion); //throw FileError
+ AFS::removeFolderIfExistsRecursion(folder.getAbstractPath<side>(), onBeforeFileDeletion, onBeforeDirDeletion); //throw FileError
}
},
@@ -1344,9 +1371,9 @@ void deleteFromGridAndHDOneSide(std::vector<FileSystemObject*>& rowsToDelete,
notifyItemDeletion(txtRemovingFile, AFS::getDisplayPath(file.getAbstractPath<side>()));
if (useRecycleBin)
- AFS::recycleItemDirectly(file.getAbstractPath<side>()); //throw FileError
+ AFS::recycleItemIfExists(file.getAbstractPath<side>()); //throw FileError
else
- AFS::removeFile(file.getAbstractPath<side>()); //throw FileError
+ AFS::removeFileIfExists(file.getAbstractPath<side>()); //throw FileError
statReporter.reportDelta(1, 0);
},
@@ -1355,14 +1382,9 @@ void deleteFromGridAndHDOneSide(std::vector<FileSystemObject*>& rowsToDelete,
notifyItemDeletion(txtRemovingSymlink, AFS::getDisplayPath(symlink.getAbstractPath<side>()));
if (useRecycleBin)
- AFS::recycleItemDirectly(symlink.getAbstractPath<side>()); //throw FileError
+ AFS::recycleItemIfExists(symlink.getAbstractPath<side>()); //throw FileError
else
- {
- if (AFS::folderExists(symlink.getAbstractPath<side>())) //dir symlink
- AFS::removeFolderSimple(symlink.getAbstractPath<side>()); //throw FileError
- else //file symlink, broken symlink
- AFS::removeFile(symlink.getAbstractPath<side>()); //throw FileError
- }
+ AFS::removeSymlinkIfExists(symlink.getAbstractPath<side>()); //throw FileError
statReporter.reportDelta(1, 0);
});
@@ -1532,7 +1554,7 @@ TempFileBuffer::~TempFileBuffer()
if (!tempFolderPath.empty())
try
{
- removeDirectoryRecursively(tempFolderPath); //throw FileError
+ removeDirectoryPlainRecursion(tempFolderPath); //throw FileError
}
catch (FileError&) { assert(false); }
}
@@ -1572,7 +1594,7 @@ void TempFileBuffer::createTempFiles(const std::set<FileDetails>& workLoad, Proc
const uint32_t crc32 = getCrc32(guid);
tempPathTmp += printNumber<Zstring>(Zstr("%08x"), static_cast<unsigned int>(crc32));
- makeDirectoryRecursively(tempPathTmp); //throw FileError
+ createDirectoryIfMissingRecursion(tempPathTmp); //throw FileError
tempFolderPath = tempPathTmp;
}, callback); //throw X?
@@ -1593,7 +1615,7 @@ void TempFileBuffer::createTempFiles(const std::set<FileDetails>& workLoad, Proc
const uint16_t crc16 = getCrc16(cookie.ref());
const Zstring detailsHash = printNumber<Zstring>(Zstr("%04x"), static_cast<unsigned int>(crc16));
- const Zstring fileName = AFS::getFileShortName(details.path);
+ const Zstring fileName = AFS::getItemName(details.path);
auto it = std::find(fileName.begin(), fileName.end(), Zchar('.')); //gracefully handle case of missing "."
const Zstring tempFileName = Zstring(fileName.begin(), it) + Zchar('-') + detailsHash + Zstring(it, fileName.end());
diff --git a/FreeFileSync/Source/application.cpp b/FreeFileSync/Source/application.cpp
index 15aa04a0..66d70579 100644
--- a/FreeFileSync/Source/application.cpp
+++ b/FreeFileSync/Source/application.cpp
@@ -325,13 +325,13 @@ void Application::launch(const std::vector<Zstring>& commandArgs)
{
Zstring filePath = getResolvedFilePath(*it);
- if (!fileExists(filePath)) //...be a little tolerant
+ if (!fileAvailable(filePath)) //...be a little tolerant
{
- if (fileExists(filePath + Zstr(".ffs_batch")))
+ if (fileAvailable(filePath + Zstr(".ffs_batch")))
filePath += Zstr(".ffs_batch");
- else if (fileExists(filePath + Zstr(".ffs_gui")))
+ else if (fileAvailable(filePath + Zstr(".ffs_gui")))
filePath += Zstr(".ffs_gui");
- else if (fileExists(filePath + Zstr(".xml")))
+ else if (fileAvailable(filePath + Zstr(".xml")))
filePath += Zstr(".xml");
else
{
@@ -549,7 +549,7 @@ void showSyntaxHelp()
}
-void runBatchMode(const Zstring& globalConfigFile, const XmlBatchConfig& batchCfg, const Zstring& referenceFile, FfsReturnCode& returnCode)
+void runBatchMode(const Zstring& globalConfigFilePath, const XmlBatchConfig& batchCfg, const Zstring& referenceFile, FfsReturnCode& returnCode)
{
auto notifyError = [&](const std::wstring& msg, FfsReturnCode rc)
{
@@ -562,17 +562,21 @@ void runBatchMode(const Zstring& globalConfigFile, const XmlBatchConfig& batchCf
};
XmlGlobalSettings globalCfg;
- if (fileExists(globalConfigFile)) //else: globalCfg already has default values
try
{
std::wstring warningMsg;
- readConfig(globalConfigFile, globalCfg, warningMsg); //throw FileError
+ readConfig(globalConfigFilePath, globalCfg, warningMsg); //throw FileError
assert(warningMsg.empty()); //ignore parsing errors: should be migration problems only *cross-fingers*
}
catch (const FileError& e)
{
- return notifyError(e.toString(), FFS_RC_ABORTED); //abort sync!
+ bool notExisting = false;
+ try { notExisting = !getItemTypeIfExists(globalConfigFilePath); /*throw FileError*/ }
+ catch (FileError&) {} //previous exception is more relevant
+
+ if (!notExisting) //existing or access error
+ return notifyError(e.toString(), FFS_RC_ABORTED); //abort sync!
}
try
@@ -661,12 +665,12 @@ void runBatchMode(const Zstring& globalConfigFile, const XmlBatchConfig& batchCf
catch (BatchRequestSwitchToMainDialog&)
{
//open new toplevel window *after* progress dialog is gone => run on main event loop
- return MainDialog::create(globalConfigFile, &globalCfg, xmlAccess::convertBatchToGui(batchCfg), { referenceFile }, true /*startComparison*/);
+ return MainDialog::create(globalConfigFilePath, &globalCfg, xmlAccess::convertBatchToGui(batchCfg), { referenceFile }, true /*startComparison*/);
}
try //save global settings to XML: e.g. ignored warnings
{
- xmlAccess::writeConfig(globalCfg, globalConfigFile); //FileError
+ xmlAccess::writeConfig(globalCfg, globalConfigFilePath); //FileError
}
catch (const FileError& e)
{
diff --git a/FreeFileSync/Source/comparison.cpp b/FreeFileSync/Source/comparison.cpp
index 36318542..dadfd83e 100644
--- a/FreeFileSync/Source/comparison.cpp
+++ b/FreeFileSync/Source/comparison.cpp
@@ -84,11 +84,11 @@ ResolvedBaseFolders initializeBaseFolders(const std::vector<FolderPairCfg>& cfgL
const FolderStatus status = getFolderStatusNonBlocking(uniqueBaseFolders, folderAccessTimeout, allowUserInteraction, callback); //re-check *all* directories on each try!
output.existingBaseFolders = status.existing;
- if (!status.missing.empty() || !status.failedChecks.empty())
+ if (!status.notExisting.empty() || !status.failedChecks.empty())
{
std::wstring errorMsg = _("Cannot find the following folders:") + L"\n";
- for (const AbstractPath& folderPath : status.missing)
+ for (const AbstractPath& folderPath : status.notExisting)
errorMsg += L"\n" + AFS::getDisplayPath(folderPath);
for (const auto& fc : status.failedChecks)
@@ -202,14 +202,14 @@ ComparisonBuffer::ComparisonBuffer(const std::set<DirectoryKey>& keysToRead, int
switch (callback_.reportError(msg, retryNumber))
{
case ProcessCallback::IGNORE_ERROR:
- return ON_ERROR_IGNORE;
+ return ON_ERROR_CONTINUE;
case ProcessCallback::RETRY:
return ON_ERROR_RETRY;
}
assert(false);
- return ON_ERROR_IGNORE;
+ return ON_ERROR_CONTINUE;
}
private:
@@ -367,29 +367,22 @@ std::shared_ptr<BaseFolderPair> ComparisonBuffer::compareByTimeSize(const Resolv
void categorizeSymlinkByContent(SymlinkPair& symlink, ProcessCallback& callback)
{
//categorize symlinks that exist on both sides
- Zstring targetPathRawL;
- Zstring targetPathRawR;
+ std::string binaryContentL;
+ std::string binaryContentR;
Opt<std::wstring> errMsg = tryReportingError([&]
{
callback.reportStatus(replaceCpy(_("Resolving symbolic link %x"), L"%x", fmtPath(AFS::getDisplayPath(symlink.getAbstractPath<LEFT_SIDE>()))));
-
- targetPathRawL = AFS::getSymlinkContentBuffer(symlink.getAbstractPath<LEFT_SIDE>()); //throw FileError
+ binaryContentL = AFS::getSymlinkBinaryContent(symlink.getAbstractPath<LEFT_SIDE>()); //throw FileError
callback.reportStatus(replaceCpy(_("Resolving symbolic link %x"), L"%x", fmtPath(AFS::getDisplayPath(symlink.getAbstractPath<RIGHT_SIDE>()))));
- targetPathRawR = AFS::getSymlinkContentBuffer(symlink.getAbstractPath<RIGHT_SIDE>()); //throw FileError
+ binaryContentR = AFS::getSymlinkBinaryContent(symlink.getAbstractPath<RIGHT_SIDE>()); //throw FileError
}, callback); //throw X?
if (errMsg)
symlink.setCategoryConflict(*errMsg);
else
{
- if (targetPathRawL == targetPathRawR
-#ifdef ZEN_WIN //type of symbolic link is relevant for Windows only
- &&
- AFS::folderExists(symlink.getAbstractPath< LEFT_SIDE>()) == //check if dir-symlink
- AFS::folderExists(symlink.getAbstractPath<RIGHT_SIDE>()) //
-#endif
- )
+ if (binaryContentL == binaryContentR)
{
//Caveat:
//1. SYMLINK_EQUAL may only be set if short names match in case: InSyncFolder's mapping tables use short name as a key! see db_file.cpp
@@ -612,9 +605,9 @@ void MergeSides::fillOneSide(const FolderContainer& folderCont, const std::wstri
for (const auto& dir : folderCont.folders)
{
- FolderPair& newFolder = output.addSubFolder<side>(dir.first);
+ FolderPair& newFolder = output.addSubFolder<side>(dir.first, dir.second.first);
const std::wstring* errorMsgNew = checkFailedRead(newFolder, errorMsg);
- fillOneSide<side>(dir.second, errorMsgNew, newFolder); //recurse
+ fillOneSide<side>(dir.second.second, errorMsgNew, newFolder); //recurse
}
}
@@ -704,27 +697,27 @@ void MergeSides::mergeTwoSides(const FolderContainer& lhs, const FolderContainer
linearMerge(lhs.folders, rhs.folders,
[&](const FolderData& dirLeft) //left only
{
- FolderPair& newFolder = output.addSubFolder<LEFT_SIDE>(dirLeft.first);
+ FolderPair& newFolder = output.addSubFolder<LEFT_SIDE>(dirLeft.first, dirLeft.second.first);
const std::wstring* errorMsgNew = checkFailedRead(newFolder, errorMsg);
- this->fillOneSide<LEFT_SIDE>(dirLeft.second, errorMsgNew, newFolder); //recurse
+ this->fillOneSide<LEFT_SIDE>(dirLeft.second.second, errorMsgNew, newFolder); //recurse
},
[&](const FolderData& dirRight) //right only
{
- FolderPair& newFolder = output.addSubFolder<RIGHT_SIDE>(dirRight.first);
+ FolderPair& newFolder = output.addSubFolder<RIGHT_SIDE>(dirRight.first, dirRight.second.first);
const std::wstring* errorMsgNew = checkFailedRead(newFolder, errorMsg);
- this->fillOneSide<RIGHT_SIDE>(dirRight.second, errorMsgNew, newFolder); //recurse
+ this->fillOneSide<RIGHT_SIDE>(dirRight.second.second, errorMsgNew, newFolder); //recurse
},
[&](const FolderData& dirLeft, const FolderData& dirRight) //both sides
{
- FolderPair& newFolder = output.addSubFolder(dirLeft.first, dirRight.first, DIR_EQUAL);
+ FolderPair& newFolder = output.addSubFolder(dirLeft.first, dirLeft.second.first, DIR_EQUAL, dirRight.first, dirRight.second.first);
const std::wstring* errorMsgNew = checkFailedRead(newFolder, errorMsg);
if (!errorMsgNew)
if (dirLeft.first != dirRight.first)
newFolder.setCategoryDiffMetadata(getDescrDiffMetaShortnameCase(newFolder));
- mergeTwoSides(dirLeft.second, dirRight.second, errorMsgNew, newFolder); //recurse
+ mergeTwoSides(dirLeft.second.second, dirRight.second.second, errorMsgNew, newFolder); //recurse
});
}
diff --git a/FreeFileSync/Source/file_hierarchy.h b/FreeFileSync/Source/file_hierarchy.h
index 401c921b..6a41af2d 100644
--- a/FreeFileSync/Source/file_hierarchy.h
+++ b/FreeFileSync/Source/file_hierarchy.h
@@ -57,6 +57,16 @@ struct LinkDescriptor
};
+struct FolderDescriptor
+{
+ FolderDescriptor() {}
+ FolderDescriptor(bool isSymlink) :
+ isFollowedSymlink(isSymlink) {}
+
+ bool isFollowedSymlink = false;
+};
+
+
enum SelectedSide
{
LEFT_SIDE,
@@ -95,7 +105,7 @@ struct SelectParam<RIGHT_SIDE>
struct FolderContainer
{
//------------------------------------------------------------------
- using FolderList = std::map<Zstring, FolderContainer, LessFilePath>; //
+ using FolderList = std::map<Zstring, std::pair<FolderDescriptor, FolderContainer>, LessFilePath>; //
using FileList = std::map<Zstring, FileDescriptor, LessFilePath>; //key: file name
using SymlinkList = std::map<Zstring, LinkDescriptor, LessFilePath>; //
//------------------------------------------------------------------
@@ -104,29 +114,34 @@ struct FolderContainer
FolderContainer (const FolderContainer&) = delete; //catch accidental (and unnecessary) copying
FolderContainer& operator=(const FolderContainer&) = delete; //
- FolderList folders;
FileList files;
SymlinkList symlinks; //non-followed symlinks
+ FolderList folders;
- //convenience
- FolderContainer& addSubFolder(const Zstring& itemName)
+ void addSubFile(const Zstring& itemName, const FileDescriptor& descr)
{
- return folders[itemName]; //value default-construction is okay here
- //return dirs.emplace(itemName, FolderContainer()).first->second;
+ auto rv = files.emplace(itemName, descr);
+ if (!rv.second) //update entry if already existing (e.g. during folder traverser "retry") => does not handle different item name case (irrelvant!..)
+ rv.first->second = descr;
}
- void addSubFile(const Zstring& itemName, const FileDescriptor& fileData)
+ void addSubLink(const Zstring& itemName, const LinkDescriptor& descr)
{
- auto rv = files.emplace(itemName, fileData);
- if (!rv.second) //update entry if already existing (e.g. during folder traverser "retry") => does not handle different item name case (irrelvant!..)
- rv.first->second = fileData;
+ auto rv = symlinks.emplace(itemName, descr);
+ if (!rv.second)
+ rv.first->second = descr;
}
- void addSubLink(const Zstring& itemName, const LinkDescriptor& linkData)
+ FolderContainer& addSubFolder(const Zstring& itemName, const FolderDescriptor& descr)
{
- auto rv = symlinks.emplace(itemName, linkData);
- if (!rv.second)
- rv.first->second = linkData;
+ auto& p = folders[itemName]; //value default-construction is okay here
+ p.first = descr;
+ return p.second;
+
+ //auto rv = folders.emplace(itemName, std::pair<FolderDescriptor, FolderContainer>(descr, FolderContainer()));
+ //if (!rv.second)
+ // rv.first->second.first = descr;
+ //return rv.first->second.second;
}
};
@@ -161,12 +176,14 @@ public:
using FolderList = FixedList<FolderPair>;
FolderPair& addSubFolder(const Zstring& itemNameLeft,
+ const FolderDescriptor& left, //file exists on both sides
+ CompareDirResult defaultCmpResult,
const Zstring& itemNameRight,
- CompareDirResult defaultCmpResult);
+ const FolderDescriptor& right);
template <SelectedSide side>
- FolderPair& addSubFolder(const Zstring& itemName); //dir exists on one side only
-
+ FolderPair& addSubFolder(const Zstring& itemName, //dir exists on one side only
+ const FolderDescriptor& descr);
FilePair& addSubFile(const Zstring& itemNameLeft,
const FileDescriptor& left, //file exists on both sides
@@ -233,17 +250,17 @@ class BaseFolderPair : public HierarchyObject //synchronization base directory
{
public:
BaseFolderPair(const AbstractPath& folderPathLeft,
- bool dirExistsLeft,
+ bool folderAvailableLeft,
const AbstractPath& folderPathRight,
- bool dirExistsRight,
+ bool folderAvailableRight,
const HardFilter::FilterRef& filter,
CompareVariant cmpVar,
int fileTimeTolerance,
const std::vector<unsigned int>& ignoreTimeShiftMinutes) :
HierarchyObject(Zstring(), *this),
filter_(filter), cmpVar_(cmpVar), fileTimeTolerance_(fileTimeTolerance), ignoreTimeShiftMinutes_(ignoreTimeShiftMinutes),
- dirExistsLeft_ (dirExistsLeft),
- dirExistsRight_(dirExistsRight),
+ folderAvailableLeft_ (folderAvailableLeft),
+ folderAvailableRight_(folderAvailableRight),
folderPathLeft_(folderPathLeft),
folderPathRight_(folderPathRight) {}
@@ -251,8 +268,8 @@ public:
static void removeEmpty(BaseFolderPair& baseFolder) { baseFolder.removeEmptyRec(); } //physically remove all invalid entries (where both sides are empty) recursively
- template <SelectedSide side> bool isExisting() const; //status of directory existence at the time of comparison!
- template <SelectedSide side> void setExisting(bool value); //update after creating the directory in FFS
+ template <SelectedSide side> bool isAvailable() const; //base folder status at the time of comparison!
+ template <SelectedSide side> void setAvailable(bool value); //update after creating the directory in FFS
//get settings which were used while creating BaseFolderPair
const HardFilter& getFilter() const { return *filter_; }
@@ -268,8 +285,8 @@ private:
const int fileTimeTolerance_;
const std::vector<unsigned int> ignoreTimeShiftMinutes_;
- bool dirExistsLeft_;
- bool dirExistsRight_;
+ bool folderAvailableLeft_;
+ bool folderAvailableRight_;
AbstractPath folderPathLeft_;
AbstractPath folderPathRight_;
@@ -469,15 +486,22 @@ public:
CompareDirResult getDirCategory() const; //returns actually used subset of CompareFilesResult
FolderPair(const Zstring& itemNameLeft, //use empty itemName if "not existing"
- const Zstring& itemNameRight, //
- HierarchyObject& parentObj,
- CompareDirResult defaultCmpResult) :
+ const FolderDescriptor& left,
+ CompareDirResult defaultCmpResult,
+ const Zstring& itemNameRight,
+ const FolderDescriptor& right,
+ HierarchyObject& parentObj) :
FileSystemObject(itemNameLeft, itemNameRight, parentObj, static_cast<CompareFilesResult>(defaultCmpResult)),
- HierarchyObject(getPairRelativePath() + FILE_NAME_SEPARATOR, parentObj.getBase()) {}
+ HierarchyObject(getPairRelativePath() + FILE_NAME_SEPARATOR, parentObj.getBase()),
+ dataLeft_(left),
+ dataRight_(right) {}
+
+ template <SelectedSide side> bool isFollowedSymlink() const;
SyncOperation getSyncOperation() const override;
- void setSyncedTo(const Zstring& itemName); //call after sync, sets DIR_EQUAL
+ template <SelectedSide sideTrg>
+ void setSyncedTo(const Zstring& itemName, bool isSymlinkTrg, bool isSymlinkSrc); //call after sync, sets DIR_EQUAL
private:
void flip () override;
@@ -487,6 +511,9 @@ private:
mutable SyncOperation syncOpBuffered_ = SO_DO_NOTHING; //determining sync-op for directory may be expensive as it depends on child-objects -> buffer it
mutable bool haveBufferedSyncOp_ = false; //
+
+ FolderDescriptor dataLeft_;
+ FolderDescriptor dataRight_;
};
//------------------------------------------------------------------
@@ -859,26 +886,28 @@ void HierarchyObject::flip()
inline
FolderPair& HierarchyObject::addSubFolder(const Zstring& itemNameLeft,
+ const FolderDescriptor& left,
+ CompareDirResult defaultCmpResult,
const Zstring& itemNameRight,
- CompareDirResult defaultCmpResult)
+ const FolderDescriptor& right)
{
- subFolders_.emplace_back(itemNameLeft, itemNameRight, *this, defaultCmpResult);
+ subFolders_.emplace_back(itemNameLeft, left, defaultCmpResult, itemNameRight, right, *this);
return subFolders_.back();
}
template <> inline
-FolderPair& HierarchyObject::addSubFolder<LEFT_SIDE>(const Zstring& itemName)
+FolderPair& HierarchyObject::addSubFolder<LEFT_SIDE>(const Zstring& itemName, const FolderDescriptor& descr)
{
- subFolders_.emplace_back(itemName, Zstring(), *this, DIR_LEFT_SIDE_ONLY);
+ subFolders_.emplace_back(itemName, descr, DIR_LEFT_SIDE_ONLY, Zstring(), FolderDescriptor(), *this);
return subFolders_.back();
}
template <> inline
-FolderPair& HierarchyObject::addSubFolder<RIGHT_SIDE>(const Zstring& itemName)
+FolderPair& HierarchyObject::addSubFolder<RIGHT_SIDE>(const Zstring& itemName, const FolderDescriptor& descr)
{
- subFolders_.emplace_back(Zstring(), itemName, *this, DIR_RIGHT_SIDE_ONLY);
+ subFolders_.emplace_back(Zstring(), FolderDescriptor(), DIR_RIGHT_SIDE_ONLY, itemName, descr, *this);
return subFolders_.back();
}
@@ -943,8 +972,8 @@ inline
void BaseFolderPair::flip()
{
HierarchyObject::flip();
- std::swap(dirExistsLeft_, dirExistsRight_);
- std::swap(folderPathLeft_, folderPathRight_);
+ std::swap(folderAvailableLeft_, folderAvailableRight_);
+ std::swap(folderPathLeft_, folderPathRight_);
}
@@ -953,6 +982,7 @@ void FolderPair::flip()
{
HierarchyObject ::flip(); //call base class versions
FileSystemObject::flip(); //
+ std::swap(dataLeft_, dataRight_);
}
@@ -965,6 +995,8 @@ void FolderPair::removeObjectL()
link.removeObject<LEFT_SIDE>();
for (FolderPair& folder : refSubFolders())
folder.removeObject<LEFT_SIDE>();
+
+ dataLeft_ = FolderDescriptor();
}
@@ -977,20 +1009,22 @@ void FolderPair::removeObjectR()
link.removeObject<RIGHT_SIDE>();
for (FolderPair& folder : refSubFolders())
folder.removeObject<RIGHT_SIDE>();
+
+ dataRight_ = FolderDescriptor();
}
template <SelectedSide side> inline
-bool BaseFolderPair::isExisting() const
+bool BaseFolderPair::isAvailable() const
{
- return SelectParam<side>::ref(dirExistsLeft_, dirExistsRight_);
+ return SelectParam<side>::ref(folderAvailableLeft_, folderAvailableRight_);
}
template <SelectedSide side> inline
-void BaseFolderPair::setExisting(bool value)
+void BaseFolderPair::setAvailable(bool value)
{
- SelectParam<side>::ref(dirExistsLeft_, dirExistsRight_) = value;
+ SelectParam<side>::ref(folderAvailableLeft_, folderAvailableRight_) = value;
}
@@ -1030,6 +1064,13 @@ bool FilePair::isFollowedSymlink() const
}
+template <SelectedSide side> inline
+bool FolderPair::isFollowedSymlink() const
+{
+ return SelectParam<side>::ref(dataLeft_, dataRight_).isFollowedSymlink;
+}
+
+
template <SelectedSide sideTrg> inline
void FilePair::setSyncedTo(const Zstring& itemName,
std::uint64_t fileSize,
@@ -1065,9 +1106,16 @@ void SymlinkPair::setSyncedTo(const Zstring& itemName,
}
-inline
-void FolderPair::setSyncedTo(const Zstring& itemName)
+template <SelectedSide sideTrg> inline
+void FolderPair::setSyncedTo(const Zstring& itemName,
+ bool isSymlinkTrg,
+ bool isSymlinkSrc)
{
+ static const SelectedSide sideSrc = OtherSide<sideTrg>::result;
+
+ SelectParam<sideTrg>::ref(dataLeft_, dataRight_) = FolderDescriptor(isSymlinkTrg);
+ SelectParam<sideSrc>::ref(dataLeft_, dataRight_) = FolderDescriptor(isSymlinkSrc);
+
FileSystemObject::setSynced(itemName); //set FileSystemObject specific part
}
diff --git a/FreeFileSync/Source/fs/abstract.cpp b/FreeFileSync/Source/fs/abstract.cpp
index 26ac4445..fa2caf91 100644
--- a/FreeFileSync/Source/fs/abstract.cpp
+++ b/FreeFileSync/Source/fs/abstract.cpp
@@ -58,7 +58,7 @@ AFS::FileAttribAfterCopy AFS::copyFileTransactional(const AbstractPath& apSource
throw FileError(replaceCpy(_("Cannot write permissions of %x."), L"%x", fmtPath(AFS::getDisplayPath(apTargetTmp))),
_("Operation not supported for different base folder types."));
- return AFS::copyFileAsStream(apSource, apTargetTmp, notifyProgress); //throw FileError, ErrorTargetExisting, ErrorFileLocked
+ return apSource.afs->copyFileAsStream(apSource.itemPathImpl, apTargetTmp, notifyProgress); //throw FileError, ErrorTargetExisting, ErrorFileLocked
};
if (transactionalCopy)
@@ -79,7 +79,7 @@ AFS::FileAttribAfterCopy AFS::copyFileTransactional(const AbstractPath& apSource
}
//transactional behavior: ensure cleanup; not needed before copyFileBestEffort() which is already transactional
- ZEN_ON_SCOPE_FAIL( try { AFS::removeFile(apTargetTmp); }
+ ZEN_ON_SCOPE_FAIL( try { AFS::removeFilePlain(apTargetTmp); }
catch (FileError&) {} );
//have target file deleted (after read access on source and target has been confirmed) => allow for almost transactional overwrite
@@ -115,22 +115,26 @@ AFS::FileAttribAfterCopy AFS::copyFileTransactional(const AbstractPath& apSource
}
-void AFS::createFolderRecursively(const AbstractPath& ap) //throw FileError
+void AFS::createFolderIfMissingRecursion(const AbstractPath& ap) //throw FileError
{
+ if (!getParentFolderPath(ap)) //device root
+ return static_cast<void>(/*ItemType =*/ getItemType(ap)); //throw FileError
+
try
{
- AFS::createFolderSimple(ap); //throw FileError, ErrorTargetExisting, ErrorTargetPathMissing
+ createFolderPlain(ap); //throw FileError
}
- catch (ErrorTargetExisting&) {}
- catch (ErrorTargetPathMissing&)
+ catch (FileError&)
{
- if (Opt<AbstractPath> parentPath = AFS::getParentFolderPath(ap))
- {
- //recurse...
- createFolderRecursively(*parentPath); //throw FileError
+ Opt<PathDetails> pd;
+ try { pd = getPathDetails(ap); /*throw FileError*/ }
+ catch (FileError&) {} //previous exception is more relevant
- //now try again...
- AFS::createFolderSimple(ap); //throw FileError, (ErrorTargetExisting), (ErrorTargetPathMissing)
+ if (pd && pd->existingType != ItemType::FILE)
+ {
+ AbstractPath intermediatePath = pd->existingPath;
+ for (const Zstring& itemName : pd->relPath)
+ createFolderPlain(intermediatePath = appendRelPath(intermediatePath, itemName)); //throw FileError
return;
}
throw;
@@ -140,41 +144,149 @@ void AFS::createFolderRecursively(const AbstractPath& ap) //throw FileError
namespace
{
-struct FlatTraverserCallback: public AFS::TraverserCallback
+struct ItemSearchCallback: public AFS::TraverserCallback
{
- FlatTraverserCallback(const AbstractPath& folderPath) : folderPath_(folderPath) {}
+ ItemSearchCallback(const Zstring& itemName) : itemName_(itemName) {}
+
+ void onFile (const FileInfo& fi) override { if (equalFilePath(fi.itemName, itemName_)) throw AFS::ItemType::FILE; }
+ std::unique_ptr<TraverserCallback> onFolder (const FolderInfo& fi) override { if (equalFilePath(fi.itemName, itemName_)) throw AFS::ItemType::FOLDER; return nullptr; }
+ HandleLink onSymlink(const SymlinkInfo& si) override { if (equalFilePath(si.itemName, itemName_)) throw AFS::ItemType::SYMLINK; return TraverserCallback::LINK_SKIP; }
+ HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override { throw FileError(msg); }
+ HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zstring& itemName) override { throw FileError(msg); }
+
+private:
+ const Zstring itemName_;
+};
+}
+
+
+AFS::PathDetailsImpl AFS::getPathDetailsViaFolderTraversal(const Zstring& itemPathImpl) const //throw FileError
+{
+ const Opt<Zstring> parentPathImpl = getParentFolderPathImpl(itemPathImpl);
+ try
+ {
+ return { getItemType(itemPathImpl), itemPathImpl, {} }; //throw FileError
+ }
+ catch (FileError&)
+ {
+ if (!parentPathImpl) //device root
+ throw;
+ //else: let's dig deeper... don't bother checking Win32 codes; e.g. not existing item may have the codes:
+ // ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, ERROR_INVALID_NAME, ERROR_INVALID_DRIVE,
+ // ERROR_NOT_READY, ERROR_INVALID_PARAMETER, ERROR_BAD_PATHNAME, ERROR_BAD_NETPATH => not reliable
+ }
+ const Zstring itemName = getItemName(itemPathImpl);
+ assert(!itemName.empty());
- void onFile (const FileInfo& fi) override { fileNames_ .push_back(fi.itemName); }
- std::unique_ptr<TraverserCallback> onDir (const DirInfo& di) override { folderNames_.push_back(di.itemName); return nullptr; }
- HandleLink onSymlink(const SymlinkInfo& si) override
+ PathDetailsImpl pd = getPathDetailsViaFolderTraversal(*parentPathImpl); //throw FileError
+ if (!pd.relPath.empty())
{
- if (AFS::folderExists(AFS::appendRelPath(folderPath_, si.itemName))) //dir symlink
- folderLinkNames_.push_back(si.itemName);
- else //file symlink, broken symlink
- fileNames_.push_back(si.itemName);
- return TraverserCallback::LINK_SKIP;
+ pd.relPath.push_back(itemName);
+ return { pd.existingType, pd.existingPathImpl, pd.relPath };
}
+
+ try
+ {
+ ItemSearchCallback iscb(itemName);
+ traverseFolder(*parentPathImpl, iscb); //throw FileError, ItemType
+
+ return { pd.existingType, *parentPathImpl, { itemName } }; //throw FileError
+ }
+ catch (const ItemType& type) { return { type, itemPathImpl, {} }; } //yes, exceptions for control-flow are bad design... but, but...
+ //we're not CPU-bound here and finding the item after getItemType() previously failed is exceptional (even C:\pagefile.sys should be found)
+}
+
+
+Opt<AFS::ItemType> AFS::getItemTypeIfExists(const AbstractPath& ap) //throw FileError
+{
+ const PathDetails pd = getPathDetails(ap); //throw FileError
+#ifndef NDEBUG
+ AbstractPath reconstructedPath = pd.existingPath;
+ for (const Zstring& itemName : pd.relPath)
+ reconstructedPath = appendRelPath(reconstructedPath, itemName);
+ assert(equalAbstractPath(ap, reconstructedPath));
+#endif
+ if (pd.relPath.empty())
+ return pd.existingType;
+ return NoValue();
+}
+
+
+AFS::PathDetails AFS::getPathDetails(const AbstractPath& ap) //throw FileError
+{
+ const PathDetailsImpl pdi = ap.afs->getPathDetails(ap.itemPathImpl); //throw FileError
+ return { pdi.existingType, AbstractPath(ap.afs, pdi.existingPathImpl), pdi.relPath };
+}
+
+
+//boost::variant<AFS::ItemType, AFS::NotExistType> AFS::getItemTypeIfExistsByFolderTraversal(const Zstring& itemPathImpl) const //throw FileError
+//{
+// const Opt<Zstring> parentPathImpl = getParentFolderPathImpl(itemPathImpl);
+// try
+// {
+// return getItemType(itemPathImpl); //throw FileError
+// //bonus: still find intermediate hidden/access-denied SFTP folders
+// }
+// catch (FileError&)
+// {
+// if (!parentPathImpl)
+// throw;
+// //else: let's dig deeper... don't bother checking Win32 codes; e.g. not existing item may have the codes:
+// // ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, ERROR_INVALID_NAME, ERROR_INVALID_DRIVE,
+// // ERROR_NOT_READY, ERROR_INVALID_PARAMETER, ERROR_BAD_PATHNAME, ERROR_BAD_NETPATH => not reliable
+// }
+// const Zstring itemName = getItemName(itemPathImpl);
+// assert(!itemName.empty());
+// try
+// {
+// ItemSearchCallback iscb(itemName);
+// traverseFolder(*parentPathImpl, iscb); //throw FileError, ItemType
+// return NotExistType::PARENT_EXISTING;
+// }
+// catch (const ItemType& type) { return type; } //yes, exceptions for control-flow are bad design... but, but...
+// //we're not CPU-bound here and finding the item after getItemType() previously failed is exceptional (even C:\pagefile.sys should be found)
+// catch (FileError&)
+// {
+// const auto var = getItemTypeIfExistsByFolderTraversal(*parentPathImpl); //throw FileError
+// if (boost::get<NotExistType>(&var))
+// return NotExistType::PARENT_NOT_EXISTING;
+// throw;
+// }
+//}
+
+
+namespace
+{
+struct FlatTraverserCallback: public AFS::TraverserCallback
+{
+ FlatTraverserCallback(const AbstractPath& folderPath) : folderPath_(folderPath) {}
+
+ void onFile (const FileInfo& fi) override { fileNames_ .push_back(fi.itemName); }
+ std::unique_ptr<TraverserCallback> onFolder (const FolderInfo& fi) override { folderNames_ .push_back(fi.itemName); return nullptr; }
+ HandleLink onSymlink(const SymlinkInfo& si) override { symlinkNames_.push_back(si.itemName); return TraverserCallback::LINK_SKIP; }
HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override { throw FileError(msg); }
HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zstring& itemName) override { throw FileError(msg); }
- const std::vector<Zstring>& refFileNames () const { return fileNames_; }
- const std::vector<Zstring>& refFolderNames () const { return folderNames_; }
- const std::vector<Zstring>& refFolderLinkNames() const { return folderLinkNames_; }
+ const std::vector<Zstring>& refFileNames () const { return fileNames_; }
+ const std::vector<Zstring>& refFolderNames () const { return folderNames_; }
+ const std::vector<Zstring>& refSymlinkNames() const { return symlinkNames_; }
private:
const AbstractPath folderPath_;
std::vector<Zstring> fileNames_;
std::vector<Zstring> folderNames_;
- std::vector<Zstring> folderLinkNames_;
+ std::vector<Zstring> symlinkNames_;
};
-void removeFolderRecursivelyImpl(const AbstractPath& folderPath, //throw FileError
- const std::function<void (const std::wstring& displayPath)>& onBeforeFileDeletion, //optional
- const std::function<void (const std::wstring& displayPath)>& onBeforeFolderDeletion) //one call for each *existing* object!
+void removeFolderIfExistsRecursionImpl(const AbstractPath& folderPath, //throw FileError
+ const std::function<void (const std::wstring& displayPath)>& onBeforeFileDeletion, //optional
+ const std::function<void (const std::wstring& displayPath)>& onBeforeFolderDeletion) //one call for each *existing* object!
{
- assert(!AFS::symlinkExists(folderPath)); //[!] no symlinks in this context!!!
- assert(AFS::folderExists(folderPath)); //Do NOT traverse into it deleting contained files!!!
+#ifndef NDEBUG //[!] no symlinks in this context!!! Do NOT traverse into it deleting contained files!!!
+ try { assert(AFS::getItemType(folderPath) != AFS::ItemType::SYMLINK); /*throw FileError*/ }
+ catch (FileError&) {}
+#endif
FlatTraverserCallback ft(folderPath); //deferred recursion => save stack space and allow deletion of extremely deep hierarchies!
AFS::traverseFolder(folderPath, ft); //throw FileError
@@ -185,45 +297,91 @@ void removeFolderRecursivelyImpl(const AbstractPath& folderPath, //throw FileErr
if (onBeforeFileDeletion)
onBeforeFileDeletion(AFS::getDisplayPath(filePath));
- AFS::removeFile(filePath); //throw FileError
+ AFS::removeFilePlain(filePath); //throw FileError
}
- for (const Zstring& folderLinkName : ft.refFolderLinkNames())
+ for (const Zstring& symlinkName : ft.refSymlinkNames())
{
- const AbstractPath linkPath = AFS::appendRelPath(folderPath, folderLinkName);
- if (onBeforeFolderDeletion)
- onBeforeFolderDeletion(AFS::getDisplayPath(linkPath));
+ const AbstractPath linkPath = AFS::appendRelPath(folderPath, symlinkName);
+ if (onBeforeFileDeletion)
+ onBeforeFileDeletion(AFS::getDisplayPath(linkPath));
- AFS::removeFolderSimple(linkPath); //throw FileError
+ AFS::removeSymlinkPlain(linkPath); //throw FileError
}
for (const Zstring& folderName : ft.refFolderNames())
- removeFolderRecursivelyImpl(AFS::appendRelPath(folderPath, folderName), //throw FileError
- onBeforeFileDeletion, onBeforeFolderDeletion);
+ removeFolderIfExistsRecursionImpl(AFS::appendRelPath(folderPath, folderName), //throw FileError
+ onBeforeFileDeletion, onBeforeFolderDeletion);
if (onBeforeFolderDeletion)
onBeforeFolderDeletion(AFS::getDisplayPath(folderPath));
- AFS::removeFolderSimple(folderPath); //throw FileError
+ AFS::removeFolderPlain(folderPath); //throw FileError
}
}
-void AFS::removeFolderRecursively(const AbstractPath& ap, //throw FileError
- const std::function<void (const std::wstring& displayPath)>& onBeforeFileDeletion, //optional
- const std::function<void (const std::wstring& displayPath)>& onBeforeFolderDeletion) //one call for each *existing* object!
+void AFS::removeFolderIfExistsRecursion(const AbstractPath& ap, //throw FileError
+ const std::function<void (const std::wstring& displayPath)>& onBeforeFileDeletion, //optional
+ const std::function<void (const std::wstring& displayPath)>& onBeforeFolderDeletion) //one call for each *existing* object!
{
- if (AFS::symlinkExists(ap))
+ if (Opt<ItemType> type = AFS::getItemTypeIfExists(ap)) //throw FileError
{
- if (onBeforeFolderDeletion)
- onBeforeFolderDeletion(AFS::getDisplayPath(ap));
+ if (*type == AFS::ItemType::SYMLINK)
+ {
+ if (onBeforeFileDeletion)
+ onBeforeFileDeletion(AFS::getDisplayPath(ap));
- AFS::removeFolderSimple(ap); //throw FileError
+ AFS::removeSymlinkPlain(ap); //throw FileError
+ }
+ else
+ removeFolderIfExistsRecursionImpl(ap, onBeforeFileDeletion, onBeforeFolderDeletion); //throw FileError
}
- else
+ //no error situation if directory is not existing! manual deletion relies on it!
+}
+
+
+bool AFS::removeFileIfExists(const AbstractPath& ap) //throw FileError
+{
+ try
+ {
+ removeFilePlain(ap); //throw FileError
+ return true;
+ }
+ catch (FileError&)
+ {
+ bool itemNotExisting = false;
+ try
+ {
+ itemNotExisting = !getItemTypeIfExists(ap); //throw FileError
+ }
+ catch (FileError&) {} //previous exception is more relevant
+
+ if (itemNotExisting)
+ return false;
+ throw;
+ }
+}
+
+
+bool AFS::removeSymlinkIfExists(const AbstractPath& ap) //throw FileError
+{
+ try
+ {
+ AFS::removeSymlinkPlain(ap); //throw FileError
+ return true;
+ }
+ catch (FileError&)
{
- //no error situation if directory is not existing! manual deletion relies on it!
- if (AFS::somethingExists(ap))
- removeFolderRecursivelyImpl(ap, onBeforeFileDeletion, onBeforeFolderDeletion); //throw FileError
+ bool itemNotExisting = false;
+ try
+ {
+ itemNotExisting = !getItemTypeIfExists(ap); //throw FileError
+ }
+ catch (FileError&) {} //previous exception is more relevant
+
+ if (itemNotExisting)
+ return false;
+ throw;
}
}
diff --git a/FreeFileSync/Source/fs/abstract.h b/FreeFileSync/Source/fs/abstract.h
index 86688543..b6b3142a 100644
--- a/FreeFileSync/Source/fs/abstract.h
+++ b/FreeFileSync/Source/fs/abstract.h
@@ -53,7 +53,7 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
};
static Opt<PathComplement> getPathComplement(const AbstractPath& lhs, const AbstractPath& rhs);
- static Zstring getFileShortName(const AbstractPath& ap) { return ap.afs->getFileShortName(ap.itemPathImpl); }
+ static Zstring getItemName(const AbstractPath& ap) { assert(getParentFolderPath(ap)); return ap.afs->getItemName(ap.itemPathImpl); }
static bool havePathDependency(const AbstractPath& lhs, const AbstractPath& rhs)
{
@@ -71,43 +71,53 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
}
//----------------------------------------------------------------------------------------------------------------
- static bool fileExists (const AbstractPath& ap) { return ap.afs->fileExists (ap.itemPathImpl); } //noexcept; check whether file or file-symlink exists
- static bool folderExists (const AbstractPath& ap) { return ap.afs->folderExists (ap.itemPathImpl); } //noexcept; check whether directory or dir-symlink exists
- static bool symlinkExists (const AbstractPath& ap) { return ap.afs->symlinkExists (ap.itemPathImpl); } //noexcept; check whether a symbolic link exists
- static bool somethingExists(const AbstractPath& ap) { return ap.afs->somethingExists(ap.itemPathImpl); } //noexcept; check whether any object with this name exists
+ enum class ItemType
+ {
+ FILE,
+ FOLDER,
+ SYMLINK,
+ };
+ struct PathDetails
+ {
+ ItemType existingType;
+ AbstractPath existingPath; //itemPath =: existingPath + relPath
+ std::vector<Zstring> relPath; //
+ };
+ //(hopefully) fast: does not distinguish between error/not existing
+ static ItemType getItemType(const AbstractPath& ap) { return ap.afs->getItemType(ap.itemPathImpl); } //throw FileError
+ //execute potentially SLOW folder traversal but distinguish error/not existing
+ static Opt<ItemType> getItemTypeIfExists(const AbstractPath& ap); //throw FileError
+ static PathDetails getPathDetails(const AbstractPath& ap); //throw FileError
//----------------------------------------------------------------------------------------------------------------
- //should provide for single ATOMIC folder creation!
- static void createFolderSimple(const AbstractPath& ap) { ap.afs->createFolderSimple(ap.itemPathImpl); } //throw FileError, ErrorTargetExisting, ErrorTargetPathMissing
-
- //non-recursive folder deletion:
- static void removeFolderSimple(const AbstractPath& ap) { ap.afs->removeFolderSimple(ap.itemPathImpl); } //throw FileError
+ //- error if already existing
+ //- does NOT create parent directories recursively if not existing
+ static void createFolderPlain(const AbstractPath& ap) { ap.afs->createFolderPlain(ap.itemPathImpl); } //throw FileError
//- no error if already existing
- //- create recursively if parent directory is not existing
- static void createFolderRecursively(const AbstractPath& ap); //throw FileError
-
- static void removeFolderRecursively(const AbstractPath& ap, //throw FileError
- const std::function<void (const std::wstring& displayPath)>& onBeforeFileDeletion, //optional
- const std::function<void (const std::wstring& displayPath)>& onBeforeFolderDeletion); //one call for each *existing* object!
-
- static bool removeFile(const AbstractPath& ap) { return ap.afs->removeFile(ap.itemPathImpl); } //throw FileError; return "false" if file is not existing
-
+ //- creates parent directories recursively if not existing
+ static void createFolderIfMissingRecursion(const AbstractPath& ap); //throw FileError
+
+ static bool removeFileIfExists (const AbstractPath& ap); //throw FileError; return "false" if file is not existing
+ static bool removeSymlinkIfExists(const AbstractPath& ap); //
+ static void removeFolderIfExistsRecursion(const AbstractPath& ap, //throw FileError
+ const std::function<void (const std::wstring& displayPath)>& onBeforeFileDeletion, //optional
+ const std::function<void (const std::wstring& displayPath)>& onBeforeFolderDeletion); //one call for each *existing* object!
+
+ static void removeFilePlain (const AbstractPath& ap) { ap.afs->removeFilePlain (ap.itemPathImpl); } //throw FileError
+ static void removeSymlinkPlain(const AbstractPath& ap) { ap.afs->removeSymlinkPlain(ap.itemPathImpl); } //throw FileError
+ static void removeFolderPlain (const AbstractPath& ap) { ap.afs->removeFolderPlain (ap.itemPathImpl); } //throw FileError
//----------------------------------------------------------------------------------------------------------------
-
static void setModTime (const AbstractPath& ap, std::int64_t modificationTime) { ap.afs->setModTime (ap.itemPathImpl, modificationTime); } //throw FileError, follows symlinks
static void setModTimeSymlink(const AbstractPath& ap, std::int64_t modificationTime) { ap.afs->setModTimeSymlink(ap.itemPathImpl, modificationTime); } //throw FileError
static AbstractPath getResolvedSymlinkPath(const AbstractPath& ap) { return AbstractPath(ap.afs, ap.afs->getResolvedSymlinkPath(ap.itemPathImpl)); } //throw FileError
-
- static Zstring getSymlinkContentBuffer(const AbstractPath& ap) { return ap.afs->getSymlinkContentBuffer(ap.itemPathImpl); } //throw FileError
-
+ static std::string getSymlinkBinaryContent(const AbstractPath& ap) { return ap.afs->getSymlinkBinaryContent(ap.itemPathImpl); } //throw FileError
//----------------------------------------------------------------------------------------------------------------
//noexcept; optional return value:
static ImageHolder getFileIcon (const AbstractPath& ap, int pixelSize) { return ap.afs->getFileIcon (ap.itemPathImpl, pixelSize); }
static ImageHolder getThumbnailImage(const AbstractPath& ap, int pixelSize) { return ap.afs->getThumbnailImage(ap.itemPathImpl, pixelSize); }
- static bool folderExistsThrowing(const AbstractPath& ap) { return ap.afs->folderExistsThrowing(ap.itemPathImpl); } //throw FileError
static void connectNetworkFolder(const AbstractPath& ap, bool allowUserInteraction) { return ap.afs->connectNetworkFolder(ap.itemPathImpl, allowUserInteraction); } //throw FileError
//----------------------------------------------------------------------------------------------------------------
@@ -128,7 +138,7 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
{
virtual ~OutputStreamImpl() {}
virtual size_t getBlockSize() const = 0; //non-zero block size is AFS contract!
- virtual size_t tryWrite(const void* data, size_t len) = 0; //throw FileError; may return short! CONTRACT: bytesToWrite > 0
+ virtual size_t tryWrite(const void* buffer, size_t bytesToWrite) = 0; //throw FileError; may return short! CONTRACT: bytesToWrite > 0
virtual FileId finalize(const std::function<void()>& onUpdateStatus) = 0; //throw FileError
};
@@ -163,39 +173,40 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
struct SymlinkInfo
{
- const Zstring itemName;
+ Zstring itemName;
std::int64_t lastWriteTime; //number of seconds since Jan. 1st 1970 UTC
};
struct FileInfo
{
- const Zstring itemName;
+ Zstring itemName;
std::uint64_t fileSize; //unit: bytes!
std::int64_t lastWriteTime; //number of seconds since Jan. 1st 1970 UTC
- const FileId id; //optional: empty if not supported!
+ FileId id; //optional: empty if not supported!
const SymlinkInfo* symlinkInfo; //only filled if file is a followed symlink
};
- struct DirInfo
+ struct FolderInfo
{
- const Zstring itemName;
+ Zstring itemName;
+ const SymlinkInfo* symlinkInfo; //only filled if folder is a followed symlink
};
enum HandleLink
{
- LINK_FOLLOW, //dereferences link, then calls "onDir()" or "onFile()"
+ LINK_FOLLOW, //dereferences link, then calls "onFolder()" or "onFile()"
LINK_SKIP
};
enum HandleError
{
ON_ERROR_RETRY,
- ON_ERROR_IGNORE
+ ON_ERROR_CONTINUE
};
virtual void onFile (const FileInfo& fi) = 0; //
virtual HandleLink onSymlink(const SymlinkInfo& si) = 0; //throw X
- virtual std::unique_ptr<TraverserCallback> onDir (const DirInfo& di) = 0; //
+ virtual std::unique_ptr<TraverserCallback> onFolder (const FolderInfo& fi) = 0; //
//nullptr: ignore directory, non-nullptr: traverse into, using the (new) callback
virtual HandleError reportDirError (const std::wstring& msg, size_t retryNumber) = 0; //failed directory traversal -> consider directory data at current level as incomplete!
@@ -217,11 +228,6 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
};
//return current attributes at the time of copy
//symlink handling: dereference source
- static FileAttribAfterCopy copyFileAsStream(const AbstractPath& apSource, const AbstractPath& apTarget, //throw FileError, ErrorTargetExisting, ErrorFileLocked
- //accummulated delta != file size! consider ADS, sparse, compressed files
- const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //may be nullptr; throw X!
- { return apSource.afs->copyFileAsStream(apSource.itemPathImpl, apTarget, notifyProgress); }
-
//Note: it MAY happen that copyFileTransactional() leaves temp files behind, e.g. temporary network drop.
// => clean them up at an appropriate time (automatically set sync directions to delete them). They have the following ending:
@@ -233,6 +239,7 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
//if target is existing user needs to implement deletion: copyFile() NEVER overwrites target if already existing!
//if transactionalCopy == true, full read access on source had been proven at this point, so it's safe to delete it.
const std::function<void()>& onDeleteTargetFile,
+ //accummulated delta != file size! consider ADS, sparse, compressed files
const std::function<void(std::int64_t bytesDelta)>& notifyProgress);
static void copyNewFolder(const AbstractPath& apSource, const AbstractPath& apTarget, bool copyFilePermissions); //throw FileError
@@ -255,7 +262,7 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
//precondition: supportsRecycleBin() must return true!
static std::unique_ptr<RecycleSession> createRecyclerSession(const AbstractPath& ap) { return ap.afs->createRecyclerSession(ap.itemPathImpl); } //throw FileError, return value must be bound!
- static void recycleItemDirectly(const AbstractPath& ap) { ap.afs->recycleItemDirectly(ap.itemPathImpl); } //throw FileError
+ static void recycleItemIfExists(const AbstractPath& ap) { ap.afs->recycleItemIfExists(ap.itemPathImpl); } //throw FileError
//================================================================================================================
@@ -268,6 +275,14 @@ protected: //grant derived classes access to AbstractPath:
static const AbstractFileSystem& getAfs (const AbstractPath& ap) { return *ap.afs; }
static Zstring getItemPathImpl(const AbstractPath& ap) { return ap.itemPathImpl; }
+ struct PathDetailsImpl
+ {
+ ItemType existingType;
+ Zstring existingPathImpl; //itemPathImpl =: existingPathImpl + relPath
+ std::vector<Zstring> relPath; //
+ };
+ PathDetailsImpl getPathDetailsViaFolderTraversal(const Zstring& itemPathImpl) const; //throw FileError
+
FileAttribAfterCopy copyFileAsStream(const Zstring& itemPathImplSource, const AbstractPath& apTarget, //throw FileError, ErrorTargetExisting, ErrorFileLocked
const std::function<void(std::int64_t bytesDelta)>& notifyProgress) const; //may be nullptr; throw X!
@@ -286,35 +301,30 @@ private:
virtual bool lessItemPathSameAfsType(const Zstring& itemPathImplLhs, const AbstractPath& apRhs) const = 0;
- //used during folder creation if parent folder is missing
virtual Opt<Zstring> getParentFolderPathImpl(const Zstring& itemPathImpl) const = 0;
- virtual Zstring getFileShortName(const Zstring& itemPathImpl) const = 0;
+ virtual Zstring getItemName(const Zstring& itemPathImpl) const = 0;
virtual bool havePathDependencySameAfsType(const Zstring& itemPathImplLhs, const AbstractPath& apRhs) const = 0;
//----------------------------------------------------------------------------------------------------------------
- virtual bool fileExists (const Zstring& itemPathImpl) const = 0; //noexcept
- virtual bool folderExists (const Zstring& itemPathImpl) const = 0; //noexcept
- virtual bool symlinkExists (const Zstring& itemPathImpl) const = 0; //noexcept
- virtual bool somethingExists(const Zstring& itemPathImpl) const = 0; //noexcept
+ virtual ItemType getItemType(const Zstring& itemPathImpl) const = 0; //throw FileError
+ virtual PathDetailsImpl getPathDetails(const Zstring& itemPathImpl) const = 0; //throw FileError
//----------------------------------------------------------------------------------------------------------------
- //should provide for single ATOMIC folder creation!
- virtual void createFolderSimple(const Zstring& itemPathImpl) const = 0; //throw FileError, ErrorTargetExisting, ErrorTargetPathMissing
+ virtual void createFolderPlain(const Zstring& itemPathImpl) const = 0; //throw FileError
//non-recursive folder deletion:
- virtual void removeFolderSimple(const Zstring& itemPathImpl) const = 0; //throw FileError
-
- virtual bool removeFile(const Zstring& itemPathImpl) const = 0; //throw FileError
-
+ virtual void removeFilePlain (const Zstring& itemPathImpl) const = 0; //throw FileError
+ virtual void removeSymlinkPlain(const Zstring& itemPathImpl) const = 0; //throw FileError
+ virtual void removeFolderPlain (const Zstring& itemPathImpl) const = 0; //throw FileError
//----------------------------------------------------------------------------------------------------------------
virtual void setModTime (const Zstring& itemPathImpl, std::int64_t modificationTime) const = 0; //throw FileError, follows symlinks
virtual void setModTimeSymlink(const Zstring& itemPathImpl, std::int64_t modificationTime) const = 0; //throw FileError
virtual Zstring getResolvedSymlinkPath(const Zstring& itemPathImpl) const = 0; //throw FileError
- virtual Zstring getSymlinkContentBuffer(const Zstring& itemPathImpl) const = 0; //throw FileError
+ virtual std::string getSymlinkBinaryContent(const Zstring& itemPathImpl) const = 0; //throw FileError
//----------------------------------------------------------------------------------------------------------------
virtual std::unique_ptr<InputStream > getInputStream (const Zstring& itemPathImpl) const = 0; //throw FileError, ErrorFileLocked
@@ -340,14 +350,13 @@ private:
virtual ImageHolder getFileIcon (const Zstring& itemPathImpl, int pixelSize) const = 0; //noexcept; optional return value
virtual ImageHolder getThumbnailImage(const Zstring& itemPathImpl, int pixelSize) const = 0; //
- virtual bool folderExistsThrowing(const Zstring& itemPathImpl) const = 0; //throw FileError
virtual void connectNetworkFolder(const Zstring& itemPathImpl, bool allowUserInteraction) const = 0; //throw FileError
//----------------------------------------------------------------------------------------------------------------
virtual std::uint64_t getFreeDiskSpace(const Zstring& itemPathImpl) const = 0; //throw FileError, returns 0 if not available
virtual bool supportsRecycleBin(const Zstring& itemPathImpl, const std::function<void ()>& onUpdateGui) const = 0; //throw FileError
virtual std::unique_ptr<RecycleSession> createRecyclerSession(const Zstring& itemPathImpl) const = 0; //throw FileError, return value must be bound!
- virtual void recycleItemDirectly(const Zstring& itemPathImpl) const = 0; //throw FileError
+ virtual void recycleItemIfExists(const Zstring& itemPathImpl) const = 0; //throw FileError
};
@@ -367,7 +376,7 @@ bool tryReportingDirError(Command cmd, AbstractFileSystem::TraverserCallback& ca
{
case AbstractFileSystem::TraverserCallback::ON_ERROR_RETRY:
break;
- case AbstractFileSystem::TraverserCallback::ON_ERROR_IGNORE:
+ case AbstractFileSystem::TraverserCallback::ON_ERROR_CONTINUE:
return false;
}
}
@@ -389,7 +398,7 @@ bool tryReportingItemError(Command cmd, AbstractFileSystem::TraverserCallback& c
{
case AbstractFileSystem::TraverserCallback::ON_ERROR_RETRY:
break;
- case AbstractFileSystem::TraverserCallback::ON_ERROR_IGNORE:
+ case AbstractFileSystem::TraverserCallback::ON_ERROR_CONTINUE:
return false;
}
}
@@ -497,7 +506,7 @@ AbstractFileSystem::OutputStream::~OutputStream()
outStream_.reset(); //close file handle *before* remove!
if (!finalizeSucceeded_) //transactional output stream! => clean up!
- try { AbstractFileSystem::removeFile(filePath_); /*throw FileError*/ }
+ try { AbstractFileSystem::removeFilePlain(filePath_); /*throw FileError*/ }
catch (FileError& e) { (void)e; assert(false); }
}
@@ -545,7 +554,7 @@ void AbstractFileSystem::copyNewFolder(const AbstractPath& apSource, const Abstr
throw FileError(replaceCpy(_("Cannot write permissions of %x."), L"%x", fmtPath(getDisplayPath(apTarget))),
_("Operation not supported for different base folder types."));
- createFolderSimple(apTarget); //throw FileError, ErrorTargetExisting, ErrorTargetPathMissing
+ createFolderPlain(apTarget); //throw FileError
}
diff --git a/FreeFileSync/Source/fs/native.cpp b/FreeFileSync/Source/fs/native.cpp
index 9c341769..61d9e0f2 100644
--- a/FreeFileSync/Source/fs/native.cpp
+++ b/FreeFileSync/Source/fs/native.cpp
@@ -143,10 +143,10 @@ FileAttribs getFileAttributes(FileHandle fh, const Zstring& filePath) //throw Fi
struct InputStreamNative : public AbstractFileSystem::InputStream
{
- InputStreamNative(const Zstring& filePath) : fi(filePath) {} //throw FileError, ErrorFileLocked
+ InputStreamNative(const Zstring& filePath) : fi_(filePath) {} //throw FileError, ErrorFileLocked
- size_t getBlockSize() const override { return fi.getBlockSize(); } //non-zero block size is AFS contract!
- size_t tryRead(void* buffer, size_t bytesToRead) override { return fi.tryRead(buffer, bytesToRead); } //throw FileError; may return short, only 0 means EOF! => CONTRACT: bytesToRead > 0
+ size_t getBlockSize() const override { return fi_.getBlockSize(); } //non-zero block size is AFS contract!
+ size_t tryRead(void* buffer, size_t bytesToRead) override { return fi_.tryRead(buffer, bytesToRead); } //throw FileError; may return short, only 0 means EOF! => CONTRACT: bytesToRead > 0
AFS::FileId getFileId () override; //throw FileError
std::int64_t getModificationTime() override; //throw FileError
std::uint64_t getFileSize () override; //throw FileError
@@ -154,13 +154,13 @@ struct InputStreamNative : public AbstractFileSystem::InputStream
private:
const FileAttribs& getBufferedAttributes() //throw FileError
{
- if (!fileAttr)
- fileAttr = getFileAttributes(fi.getHandle(), fi.getFilePath()); //throw FileError
- return *fileAttr;
+ if (!fileAttr_)
+ fileAttr_ = getFileAttributes(fi_.getHandle(), fi_.getFilePath()); //throw FileError
+ return *fileAttr_;
}
- FileInput fi;
- Opt<FileAttribs> fileAttr;
+ FileInput fi_;
+ Opt<FileAttribs> fileAttr_;
};
@@ -198,31 +198,31 @@ std::uint64_t InputStreamNative::getFileSize()
struct OutputStreamNative : public AbstractFileSystem::OutputStreamImpl
{
OutputStreamNative(const Zstring& filePath, const std::uint64_t* streamSize, const std::int64_t* modTime) :
- fo(filePath, FileOutput::ACC_CREATE_NEW) //throw FileError, ErrorTargetExisting
+ fo_(filePath, FileOutput::ACC_CREATE_NEW) //throw FileError, ErrorTargetExisting
{
if (modTime)
modTime_ = *modTime;
if (streamSize) //pre-allocate file space, because we can
- preAllocateSpaceBestEffort(fo.getHandle(), *streamSize, fo.getFilePath()); //throw FileError
+ preAllocateSpaceBestEffort(fo_.getHandle(), *streamSize, fo_.getFilePath()); //throw FileError
}
- size_t getBlockSize() const override { return fo.getBlockSize(); } //non-zero block size is AFS contract!
+ size_t getBlockSize() const override { return fo_.getBlockSize(); } //non-zero block size is AFS contract!
- size_t tryWrite(const void* buffer, size_t bytesToWrite) override { return fo.tryWrite(buffer, bytesToWrite); } //throw FileError; may return short! CONTRACT: bytesToWrite > 0
+ size_t tryWrite(const void* buffer, size_t bytesToWrite) override { return fo_.tryWrite(buffer, bytesToWrite); } //throw FileError; may return short! CONTRACT: bytesToWrite > 0
AFS::FileId finalize(const std::function<void()>& onUpdateStatus) override //throw FileError
{
- const AFS::FileId fileId = convertToAbstractFileId(extractFileId(getFileAttributes(fo.getHandle(), fo.getFilePath()))); //throw FileError
+ const AFS::FileId fileId = convertToAbstractFileId(extractFileId(getFileAttributes(fo_.getHandle(), fo_.getFilePath()))); //throw FileError
if (onUpdateStatus) onUpdateStatus(); //throw X!
- fo.close(); //throw FileError
+ fo_.close(); //throw FileError
if (onUpdateStatus) onUpdateStatus(); //throw X!
try
{
if (modTime_)
- zen::setFileTime(fo.getFilePath(), *modTime_, ProcSymlink::FOLLOW); //throw FileError
+ zen::setFileTime(fo_.getFilePath(), *modTime_, ProcSymlink::FOLLOW); //throw FileError
}
catch (FileError&)
{
@@ -235,7 +235,7 @@ struct OutputStreamNative : public AbstractFileSystem::OutputStreamImpl
}
private:
- FileOutput fo;
+ FileOutput fo_;
Opt<std::int64_t> modTime_;
};
@@ -243,16 +243,8 @@ private:
class NativeFileSystem : public AbstractFileSystem
{
-public:
//itemPathImpl := native full item path as used by OS APIs
- static Zstring getItemPathImplForRecycler(const AbstractPath& ap)
- {
- if (typeid(getAfs(ap)) != typeid(NativeFileSystem))
- throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
- return getItemPathImpl(ap);
- }
-
private:
bool isNativeFileSystem() const override { return true; }
@@ -282,33 +274,12 @@ private:
bool lessItemPathSameAfsType(const Zstring& itemPathImplLhs, const AbstractPath& apRhs) const override { return LessFilePath()(itemPathImplLhs, getItemPathImpl(apRhs)); }
- //used during folder creation if parent folder is missing
Opt<Zstring> getParentFolderPathImpl(const Zstring& itemPathImpl) const override
{
-#ifdef ZEN_WIN
- //remove trailing separator (even for C:\ root directories)
- const Zstring itemPathFmt = endsWith(itemPathImpl, FILE_NAME_SEPARATOR) ?
- beforeLast(itemPathImpl, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE) :
- itemPathImpl;
-
- const Zstring parentDir = beforeLast(itemPathFmt, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE);
- if (parentDir.empty())
- return NoValue();
- if (parentDir.size() == 2 && isAlpha(parentDir[0]) && parentDir[1] == L':')
- return appendSeparator(parentDir);
-
-#elif defined ZEN_LINUX || defined ZEN_MAC
- if (itemPathImpl == "/")
- return NoValue();
-
- const Zstring parentDir = beforeLast(itemPathImpl, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE);
- if (parentDir.empty())
- return Zstring("/");
-#endif
- return parentDir;
+ return zen::getParentFolderPath(itemPathImpl);
}
- Zstring getFileShortName(const Zstring& itemPathImpl) const override { return afterLast(itemPathImpl, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL); }
+ Zstring getItemName(const Zstring& itemPathImpl) const override { return afterLast(itemPathImpl, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL); }
bool havePathDependencySameAfsType(const Zstring& itemPathImplLhs, const AbstractPath& apRhs) const override
{
@@ -321,29 +292,51 @@ private:
}
//----------------------------------------------------------------------------------------------------------------
- bool fileExists (const Zstring& itemPathImpl) const override { return zen::fileExists (itemPathImpl); } //noexcept
- bool folderExists (const Zstring& itemPathImpl) const override { return zen::dirExists (itemPathImpl); } //noexcept
- bool symlinkExists (const Zstring& itemPathImpl) const override { return zen::symlinkExists (itemPathImpl); } //noexcept
- bool somethingExists(const Zstring& itemPathImpl) const override { return zen::somethingExists(itemPathImpl); } //noexcept
+ ItemType getItemType(const Zstring& itemPathImpl) const override //throw FileError
+ {
+ initComForThread(); //throw FileError
+ switch (zen::getItemType(itemPathImpl)) //throw FileError
+ {
+ case zen::ItemType::FILE:
+ return AFS::ItemType::FILE;
+ case zen::ItemType::FOLDER:
+ return AFS::ItemType::FOLDER;
+ case zen::ItemType::SYMLINK:
+ return AFS::ItemType::SYMLINK;
+ }
+ assert(false);
+ return AFS::ItemType::FILE;
+ }
+
+ PathDetailsImpl getPathDetails(const Zstring& itemPathImpl) const override //throw FileError
+ {
+ return getPathDetailsViaFolderTraversal(itemPathImpl); //throw FileError
+ }
//----------------------------------------------------------------------------------------------------------------
//should provide for single ATOMIC folder creation!
- void createFolderSimple(const Zstring& itemPathImpl) const override //throw FileError, ErrorTargetExisting, ErrorTargetPathMissing
+ void createFolderPlain(const Zstring& itemPathImpl) const override //throw FileError
{
initComForThread(); //throw FileError
- copyNewDirectory(Zstring(), itemPathImpl, false /*copyFilePermissions*/);
+ copyNewDirectory(Zstring(), itemPathImpl, false /*copyFilePermissions*/); //throw FileError, ErrorTargetExisting
}
- void removeFolderSimple(const Zstring& itemPathImpl) const override //throw FileError
+ void removeFilePlain(const Zstring& itemPathImpl) const override //throw FileError
{
initComForThread(); //throw FileError
- zen::removeDirectorySimple(itemPathImpl); //throw FileError
+ zen::removeFilePlain(itemPathImpl); //throw FileError
}
- bool removeFile(const Zstring& itemPathImpl) const override //throw FileError
+ void removeSymlinkPlain(const Zstring& itemPathImpl) const override //throw FileError
{
initComForThread(); //throw FileError
- return zen::removeFile(itemPathImpl); //throw FileError
+ zen::removeSymlinkPlain(itemPathImpl); //throw FileError
+ }
+
+ void removeFolderPlain(const Zstring& itemPathImpl) const override //throw FileError
+ {
+ initComForThread(); //throw FileError
+ zen::removeDirectoryPlain(itemPathImpl); //throw FileError
}
//----------------------------------------------------------------------------------------------------------------
@@ -366,10 +359,20 @@ private:
return zen::getResolvedSymlinkPath(itemPathImpl); //throw FileError
}
- Zstring getSymlinkContentBuffer(const Zstring& itemPathImpl) const override //throw FileError
+ std::string getSymlinkBinaryContent(const Zstring& itemPathImpl) const override //throw FileError
{
initComForThread(); //throw FileError
- return getSymlinkTargetRaw(itemPathImpl); //throw FileError
+
+ std::string content = utfCvrtTo<std::string>(getSymlinkTargetRaw(itemPathImpl)); //throw FileError
+#ifdef ZEN_WIN
+ const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(itemPathImpl).c_str());
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPathImpl)), L"GetFileAttributes");
+
+ const bool isDirSymlink = (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ content += static_cast<char>(isDirSymlink); //on Windows there are file and folder symlinks => info belongs to content!
+#endif
+ return content;
}
//----------------------------------------------------------------------------------------------------------------
@@ -461,14 +464,6 @@ private:
catch (FileError&) { assert(false); return ImageHolder(); }
}
- bool folderExistsThrowing(const Zstring& itemPathImpl) const override //throw FileError
- {
- //TODO: finish file error detection
-
- initComForThread(); //throw FileError
- return zen::dirExists(itemPathImpl);
- }
-
void connectNetworkFolder(const Zstring& itemPathImpl, bool allowUserInteraction) const override //throw FileError
{
//TODO: clean-up/remove/re-think connectNetworkFolder()
@@ -507,10 +502,10 @@ private:
return std::make_unique<RecycleSessionNative>(appendSeparator(itemPathImpl));
}
- void recycleItemDirectly(const Zstring& itemPathImpl) const override //throw FileError
+ void recycleItemIfExists(const Zstring& itemPathImpl) const override //throw FileError
{
initComForThread(); //throw FileError
- zen::recycleOrDelete(itemPathImpl); //throw FileError
+ zen::recycleOrDeleteIfExists(itemPathImpl); //throw FileError
}
};
@@ -551,19 +546,14 @@ Zstring RecycleSessionNative::getOrCreateRecyclerTempDirPf() //throw FileError
};
*/
- //ensure unique ownership:
+ //ensure unique ownership; base directory should have been created already!
Zstring dirpath = baseFolderPathPf_ + Zstr("RecycleBin") + AFS::TEMP_FILE_ENDING;
for (int i = 0;; ++i)
try
{
- copyNewDirectory(Zstring(), dirpath, false /*copyFilePermissions*/); //throw FileError, ErrorTargetExisting, ErrorTargetPathMissing
+ copyNewDirectory(Zstring(), dirpath, false /*copyFilePermissions*/); //throw FileError, ErrorTargetExisting
return dirpath;
}
- catch (ErrorTargetPathMissing&)
- {
- assert(false); //unexpected: base directory should have been created already!
- throw;
- }
catch (ErrorTargetExisting&)
{
if (i == 10) throw; //avoid endless recursion in pathological cases
@@ -579,69 +569,85 @@ Zstring RecycleSessionNative::getOrCreateRecyclerTempDirPf() //throw FileError
bool RecycleSessionNative::recycleItem(const AbstractPath& itemPath, const Zstring& logicalRelPath) //throw FileError
{
- const Zstring itemPathImpl = NativeFileSystem::getItemPathImplForRecycler(itemPath);
assert(!startsWith(logicalRelPath, FILE_NAME_SEPARATOR));
+ Opt<Zstring> itemPathNative = AFS::getNativeItemPath(itemPath);
+ if (!itemPathNative)
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+
#ifdef ZEN_WIN
- const bool isRemnantRecyclerItem = [&itemPathImpl] //clean-up of recycler temp directory failed during last sync
+ const bool isRemnantRecyclerItem = [&itemPath] //clean-up of recycler temp directory failed during last sync
{
//search for path component named "RecycleBin.ffs_tmp" or "RecycleBin_<num>.ffs_tmp":
- const size_t pos = itemPathImpl.find(L"\\RecycleBin");
- if (pos == Zstring::npos)
- return false;
+ for (AbstractPath path = itemPath;;)
+ {
+ Opt<AbstractPath> parentPath = AFS::getParentFolderPath(path);
+ if (!parentPath) //device root
+ return false;
- auto itEnd = std::find(itemPathImpl.begin() + pos + 1, itemPathImpl.end(), L'\\');
- return endsWith(StringRef<const Zchar>(itemPathImpl.begin(), itEnd), AFS::TEMP_FILE_ENDING);
+ const Zstring itemName = AFS::getItemName(path);
+ if (startsWith(itemName, L"RecycleBin") && endsWith(itemName, AFS::TEMP_FILE_ENDING))
+ return true;
+
+ path = *parentPath;
+ }
}();
//do not create RecycleBin.ffs_tmp directories recursively if recycling a particular item fails forever!
//=> 1. stack overflow crashes 2. paths longer than 260 chars, undeletable/viewable with Explorer
if (isRemnantRecyclerItem)
- return recycleOrDelete(itemPathImpl); //throw FileError
+ return recycleOrDeleteIfExists(*itemPathNative); //throw FileError
const Zstring tmpPath = getOrCreateRecyclerTempDirPf() + logicalRelPath; //throw FileError
- bool deleted = false;
auto moveToTempDir = [&]
{
//perf: Instead of recycling each object separately, we rename them one by one
// into a temporary directory and batch-recycle all at once after sync
- renameFile(itemPathImpl, tmpPath); //throw FileError, ErrorDifferentVolume
+ renameFile(*itemPathNative, tmpPath); //throw FileError, ErrorDifferentVolume, ErrorTargetExisting
this->toBeRecycled.push_back(tmpPath);
- deleted = true;
};
try
{
try
{
- moveToTempDir(); //throw FileError, ErrorDifferentVolume
+ moveToTempDir(); //throw FileError, ErrorDifferentVolume, (ErrorTargetExisting)
+ return true;
}
catch (ErrorDifferentVolume&) { throw; }
catch (FileError&)
{
- if (somethingExists(itemPathImpl))
+ if (!getItemTypeIfExists(*itemPathNative)) //throw FileError
+ return false;
+
+ if (Opt<Zstring> parentPath = getParentFolderPath(tmpPath))
{
- const Zstring tmpParentDir = beforeLast(tmpPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE); //what if C:\ ?
- if (!somethingExists(tmpParentDir))
+ Opt<PathDetails> pd;
+ try { pd = getPathDetails(*parentPath); /*throw FileError*/ }
+ catch (FileError&) {} //previous exception is more relevant
+
+ if (pd && !pd->relPath.empty()) //parent folder not existing
{
- makeDirectoryRecursively(tmpParentDir); //throw FileError
- moveToTempDir(); //throw FileError, ErrorDifferentVolume -> this should work now!
+ Zstring intermediatePath = pd->existingPath;
+ for (const Zstring& itemName : pd->relPath)
+ copyNewDirectory(Zstring(), intermediatePath = appendSeparator(intermediatePath) + itemName, false /*copyFilePermissions*/); //throw FileError, (ErrorTargetExisting)
+
+ //retry: this should work now!
+ moveToTempDir(); //throw FileError, ErrorDifferentVolume, (ErrorTargetExisting) -> this should work now!
+ return true;
}
- else
- throw;
}
+ throw;
}
}
- catch (ErrorDifferentVolume&) //MoveFileEx() returns ERROR_PATH_NOT_FOUND *before* considering ERROR_NOT_SAME_DEVICE! => we have to create tmpParentDir to find out!
+ catch (ErrorDifferentVolume&) //MoveFileEx() returns ERROR_PATH_NOT_FOUND *before* considering ERROR_NOT_SAME_DEVICE! => we have to create tmp parent folder to find out!
{
- return recycleOrDelete(itemPathImpl); //throw FileError
+ return recycleOrDeleteIfExists(*itemPathNative); //throw FileError
}
- return deleted;
-
#elif defined ZEN_LINUX || defined ZEN_MAC
- return recycleOrDelete(itemPathImpl); //throw FileError
+ return recycleOrDeleteIfExists(*itemPathNative); //throw FileError
#endif
}
@@ -652,14 +658,14 @@ void RecycleSessionNative::tryCleanup(const std::function<void (const std::wstri
if (!toBeRecycled.empty())
{
//move content of temporary directory to recycle bin in a single call
- recycleOrDelete(toBeRecycled, notifyDeletionStatus); //throw FileError
+ recycleOrDeleteIfExists(toBeRecycled, notifyDeletionStatus); //throw FileError
toBeRecycled.clear();
}
//clean up temp directory itself (should contain remnant empty directories only)
if (!recyclerTmpDir.empty())
{
- removeDirectoryRecursively(recyclerTmpDir); //throw FileError
+ removeDirectoryPlainRecursion(recyclerTmpDir); //throw FileError
recyclerTmpDir.clear();
}
#endif
diff --git a/FreeFileSync/Source/fs/native_traverser_impl.h b/FreeFileSync/Source/fs/native_traverser_impl.h
index 35891c8a..d88ffce6 100644
--- a/FreeFileSync/Source/fs/native_traverser_impl.h
+++ b/FreeFileSync/Source/fs/native_traverser_impl.h
@@ -91,7 +91,7 @@ private:
(itemName[1] == 0 || (itemName[1] == '.' && itemName[2] == 0)))
continue;
- const Zstring& itemPath = appendSeparator(dirPath) + itemName;
+ const Zstring& itemPath = appendSeparator(dirPath) + itemName;
struct ::stat statData = {};
if (!tryReportingItemError([&]
@@ -122,7 +122,7 @@ private:
{
if (S_ISDIR(statDataTrg.st_mode)) //a directory
{
- if (std::unique_ptr<AFS::TraverserCallback> trav = sink.onDir({ itemName }))
+ if (std::unique_ptr<AFS::TraverserCallback> trav = sink.onFolder({ itemName, &linkInfo }))
traverse(itemPath, *trav);
}
else //a file or named pipe, ect.
@@ -141,7 +141,7 @@ private:
}
else if (S_ISDIR(statData.st_mode)) //a directory
{
- if (std::unique_ptr<AFS::TraverserCallback> trav = sink.onDir({ itemName }))
+ if (std::unique_ptr<AFS::TraverserCallback> trav = sink.onFolder({ itemName, nullptr }))
traverse(itemPath, *trav);
}
else //a file or named pipe, ect.
diff --git a/FreeFileSync/Source/lib/db_file.cpp b/FreeFileSync/Source/lib/db_file.cpp
index ea679635..c3d1a8cb 100644
--- a/FreeFileSync/Source/lib/db_file.cpp
+++ b/FreeFileSync/Source/lib/db_file.cpp
@@ -74,7 +74,10 @@ void saveStreams(const DbStreams& streamList, const AbstractPath& dbPath, const
writeContainer<ByteArray> (memStreamOut, stream.second);
}
- assert(!AFS::somethingExists(dbPath)); //orphan tmp files should have been cleaned up at this point!
+#ifndef NDEBUG
+ try { assert(!AFS::getItemTypeIfExists(dbPath)); /*throw FileError*/ }
+ catch (FileError&) {} //orphan tmp files should have been cleaned up at this point!
+#endif
//save memory stream to file (as a transaction!)
{
@@ -134,10 +137,15 @@ DbStreams loadStreams(const AbstractPath& dbPath, const std::function<void(std::
}
catch (FileError&)
{
- if (!AFS::somethingExists(dbPath)) //a benign(?) race condition with FileError
+ bool dbNotYetExisting = false;
+ try { dbNotYetExisting = !AFS::getItemTypeIfExists(dbPath); /*throw FileError*/ }
+ catch (FileError&) {} //previous exception is more relevant
+
+ if (dbNotYetExisting) //throw FileError
throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n" +
replaceCpy(_("Database file %x does not yet exist."), L"%x", fmtPath(AFS::getDisplayPath(dbPath))));
- throw;
+ else
+ throw;
}
catch (UnexpectedEndOfStreamError&)
{
@@ -679,12 +687,12 @@ std::shared_ptr<InSyncFolder> zen::loadLastSynchronousState(const BaseFolderPair
const AbstractPath dbPathLeft = getDatabaseFilePath< LEFT_SIDE>(baseFolder);
const AbstractPath dbPathRight = getDatabaseFilePath<RIGHT_SIDE>(baseFolder);
- if (!baseFolder.isExisting< LEFT_SIDE>() ||
- !baseFolder.isExisting<RIGHT_SIDE>())
+ if (!baseFolder.isAvailable< LEFT_SIDE>() ||
+ !baseFolder.isAvailable<RIGHT_SIDE>())
{
//avoid race condition with directory existence check: reading sync.ffs_db may succeed although first dir check had failed => conflicts!
//https://sourceforge.net/tracker/?func=detail&atid=1093080&aid=3531351&group_id=234430
- const AbstractPath filePath = !baseFolder.isExisting<LEFT_SIDE>() ? dbPathLeft : dbPathRight;
+ const AbstractPath filePath = !baseFolder.isAvailable<LEFT_SIDE>() ? dbPathLeft : dbPathRight;
throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n" + //it could be due to a to-be-created target directory not yet existing => FileErrorDatabaseNotExisting
replaceCpy(_("Database file %x does not yet exist."), L"%x", fmtPath(AFS::getDisplayPath(filePath))));
}
@@ -719,10 +727,6 @@ void zen::saveLastSynchronousState(const BaseFolderPair& baseFolder, const std::
const AbstractPath dbPathLeftTmp = getDatabaseFilePath< LEFT_SIDE>(baseFolder, true);
const AbstractPath dbPathRightTmp = getDatabaseFilePath<RIGHT_SIDE>(baseFolder, true);
- //delete old tmp file, if necessary -> throws if deletion fails!
- AFS::removeFile(dbPathLeftTmp); //
- AFS::removeFile(dbPathRightTmp); //throw FileError
-
//(try to) load old database files...
DbStreams streamsLeft; //list of session ID + DirInfo-stream
DbStreams streamsRight;
@@ -793,15 +797,19 @@ void zen::saveLastSynchronousState(const BaseFolderPair& baseFolder, const std::
streamsLeft [sessionID] = std::move(updatedStreamLeft);
streamsRight[sessionID] = std::move(updatedStreamRight);
+ //delete old tmp file, if necessary -> throws if deletion fails!
+ AFS::removeFileIfExists(dbPathLeftTmp); //
+ AFS::removeFileIfExists(dbPathRightTmp); //throw FileError
+
//write (temp-) files as a transaction
saveStreams(streamsLeft, dbPathLeftTmp, notifyProgress); //throw FileError
saveStreams(streamsRight, dbPathRightTmp, notifyProgress); //
//operation finished: rename temp files -> this should work (almost) transactionally:
//if there were no write access, creation of temp files would have failed
- AFS::removeFile(dbPathLeft); //throw FileError
+ AFS::removeFileIfExists(dbPathLeft); //throw FileError
AFS::renameItem(dbPathLeftTmp, dbPathLeft); //throw FileError, (ErrorTargetExisting, ErrorDifferentVolume)
- AFS::removeFile(dbPathRight); //
+ AFS::removeFileIfExists(dbPathRight); //
AFS::renameItem(dbPathRightTmp, dbPathRight); //
}
diff --git a/FreeFileSync/Source/lib/dir_exist_async.h b/FreeFileSync/Source/lib/dir_exist_async.h
index d790404e..891ff8aa 100644
--- a/FreeFileSync/Source/lib/dir_exist_async.h
+++ b/FreeFileSync/Source/lib/dir_exist_async.h
@@ -26,7 +26,7 @@ namespace
struct FolderStatus
{
std::set<AbstractPath, AFS::LessAbstractPath> existing;
- std::set<AbstractPath, AFS::LessAbstractPath> missing;
+ std::set<AbstractPath, AFS::LessAbstractPath> notExisting;
std::map<AbstractPath, FileError, AFS::LessAbstractPath> failedChecks;
};
@@ -46,7 +46,8 @@ FolderStatus getFolderStatusNonBlocking(const std::set<AbstractPath, AFS::LessAb
AFS::connectNetworkFolder(folderPath, allowUserInteraction); //throw FileError
//2. check dir existence
- return AFS::folderExistsThrowing(folderPath); //throw FileError
+ return static_cast<bool>(AFS::getItemTypeIfExists(folderPath)); //throw FileError
+ //TODO: consider ItemType:FILE a failure instead? In any case: return "false" IFF nothing (of any type) exists
}));
//don't wait (almost) endlessly like Win32 would on non-existing network shares:
@@ -70,7 +71,7 @@ FolderStatus getFolderStatusNonBlocking(const std::set<AbstractPath, AFS::LessAb
if (fi.second.get()) //throw FileError
output.existing.insert(fi.first);
else
- output.missing.insert(fi.first);
+ output.notExisting.insert(fi.first);
}
catch (const FileError& e) { output.failedChecks.emplace(fi.first, e); }
}
diff --git a/FreeFileSync/Source/lib/dir_lock.cpp b/FreeFileSync/Source/lib/dir_lock.cpp
index e2184781..879fe607 100644
--- a/FreeFileSync/Source/lib/dir_lock.cpp
+++ b/FreeFileSync/Source/lib/dir_lock.cpp
@@ -451,7 +451,7 @@ void waitOnDirLock(const Zstring& lockFilePath, DirLockCallback* callback) //thr
if (getFilesize(lockFilePath) != fileSizeOld) //throw FileError
continue; //late life sign
- removeFile(lockFilePath); //throw FileError
+ removeFilePlain(lockFilePath); //throw FileError
return;
}
@@ -479,18 +479,23 @@ void waitOnDirLock(const Zstring& lockFilePath, DirLockCallback* callback) //thr
}
catch (FileError&)
{
- if (!somethingExists(lockFilePath)) //a benign(?) race condition with FileError
- return; //what we are waiting for...
+ try
+ {
+ if (!getItemTypeIfExists(lockFilePath)) //throw FileError
+ return; //what we are waiting for...
+ }
+ catch (FileError&) {} //previous exception is more relevant
+
throw;
}
}
-void releaseLock(const Zstring& lockFilePath) //throw ()
+void releaseLock(const Zstring& lockFilePath) //noexcept
{
try
{
- removeFile(lockFilePath); //throw FileError
+ removeFilePlain(lockFilePath); //throw FileError
}
catch (FileError&) {}
}
@@ -540,7 +545,8 @@ bool tryLock(const Zstring& lockFilePath) //throw FileError
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(lockFilePath)), L"open");
}
#endif
- ZEN_ON_SCOPE_FAIL( removeFile(lockFilePath); );
+ ZEN_ON_SCOPE_FAIL(try { removeFilePlain(lockFilePath); }
+ catch (FileError&) {});
FileOutput fileOut(fileHandle, lockFilePath); //pass handle ownership
//write housekeeping info: user, process info, lock GUID
diff --git a/FreeFileSync/Source/lib/ffs_paths.cpp b/FreeFileSync/Source/lib/ffs_paths.cpp
index f57409d8..f6d90e58 100644
--- a/FreeFileSync/Source/lib/ffs_paths.cpp
+++ b/FreeFileSync/Source/lib/ffs_paths.cpp
@@ -44,8 +44,8 @@ Zstring zen::getInstallDirPath() //root install directory WITHOUT path separator
bool zen::isPortableVersion()
{
#ifdef ZEN_WIN
- return !fileExists(appendSeparator(getInstallDirPath()) + L"uninstall.exe") && //created by NSIS
- !dirExists (appendSeparator(getInstallDirPath()) + L"Uninstall"); //created by Inno Setup
+ return !fileAvailable(appendSeparator(getInstallDirPath()) + L"uninstall.exe") && //created by NSIS
+ !dirAvailable (appendSeparator(getInstallDirPath()) + L"Uninstall"); //created by Inno Setup
#elif defined ZEN_LINUX
return !endsWith(getExecutablePathPf(), "/bin/"); //this check is a bit lame...
@@ -96,7 +96,7 @@ Zstring zen::getConfigDirPathPf()
Zstring configDirPath = toZ(wxStandardPathsBase::Get().GetUserDataDir());
try
{
- makeDirectoryRecursively(configDirPath); //throw FileError
+ createDirectoryIfMissingRecursion(configDirPath); //throw FileError
}
catch (const FileError&) { assert(false); }
diff --git a/FreeFileSync/Source/lib/icon_buffer.cpp b/FreeFileSync/Source/lib/icon_buffer.cpp
index 10965397..0e669841 100644
--- a/FreeFileSync/Source/lib/icon_buffer.cpp
+++ b/FreeFileSync/Source/lib/icon_buffer.cpp
@@ -97,7 +97,7 @@ ImageHolder getDisplayIcon(const AbstractPath& itemPath, IconBuffer::IconSize sz
break;
}
- const Zstring& templateName = AFS::getFileShortName(itemPath);
+ const Zstring& templateName = AFS::getItemName(itemPath);
//2. retrieve file icons
#ifdef ZEN_WIN
@@ -445,7 +445,7 @@ bool IconBuffer::readyForRetrieval(const AbstractPath& filePath)
{
#ifdef ZEN_WIN
if (iconSizeType == IconBuffer::SIZE_SMALL)
- if (hasStandardIconExtension(AFS::getFileShortName(filePath)))
+ if (hasStandardIconExtension(AFS::getItemName(filePath)))
return true;
#endif
return pimpl->buffer->hasIcon(filePath);
@@ -456,7 +456,7 @@ Opt<wxBitmap> IconBuffer::retrieveFileIcon(const AbstractPath& filePath)
{
#ifdef ZEN_WIN
//perf: let's read icons which don't need file access right away! No async delay justified!
- const Zstring fileName = AFS::getFileShortName(filePath);
+ const Zstring fileName = AFS::getItemName(filePath);
if (iconSizeType == IconBuffer::SIZE_SMALL) //non-thumbnail view, we need file type icons only!
if (hasStandardIconExtension(fileName))
return this->getIconByExtension(fileName); //buffered!!!
diff --git a/FreeFileSync/Source/lib/parallel_scan.cpp b/FreeFileSync/Source/lib/parallel_scan.cpp
index 0c34b534..a0996a9f 100644
--- a/FreeFileSync/Source/lib/parallel_scan.cpp
+++ b/FreeFileSync/Source/lib/parallel_scan.cpp
@@ -316,7 +316,7 @@ public:
level_(level) {}
virtual void onFile (const FileInfo& fi) override; //
- virtual std::unique_ptr<TraverserCallback> onDir (const DirInfo& di) override; //throw ThreadInterruption
+ virtual std::unique_ptr<TraverserCallback> onFolder (const FolderInfo& fi) override; //throw ThreadInterruption
virtual HandleLink onSymlink(const SymlinkInfo& li) override; //
HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override; //throw ThreadInterruption
@@ -367,11 +367,11 @@ void DirCallback::onFile(const FileInfo& fi) //throw ThreadInterruption
}
-std::unique_ptr<AFS::TraverserCallback> DirCallback::onDir(const DirInfo& di) //throw ThreadInterruption
+std::unique_ptr<AFS::TraverserCallback> DirCallback::onFolder(const FolderInfo& fi) //throw ThreadInterruption
{
interruptionPoint(); //throw ThreadInterruption
- const Zstring& folderRelPath = parentRelPathPf_ + di.itemName;
+ const Zstring& folderRelPath = parentRelPathPf_ + fi.itemName;
//update status information no matter whether item is excluded or not!
if (cfg.acb_.mayReportCurrentFile(cfg.threadID_, cfg.lastReportTime_))
@@ -385,7 +385,7 @@ std::unique_ptr<AFS::TraverserCallback> DirCallback::onDir(const DirInfo& di) //
return nullptr; //do NOT traverse subdirs
//else: attention! ensure directory filtering is applied later to exclude actually filtered directories
- FolderContainer& subFolder = output_.addSubFolder(di.itemName);
+ FolderContainer& subFolder = output_.addSubFolder(fi.itemName, fi.symlinkInfo != nullptr);
if (passFilter)
cfg.acb_.incItemsScanned(); //add 1 element to the progress indicator
@@ -394,7 +394,7 @@ std::unique_ptr<AFS::TraverserCallback> DirCallback::onDir(const DirInfo& di) //
if (!tryReportingItemError([&] //check after FolderContainer::addSubFolder()
{
throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", AFS::getDisplayPath(AFS::appendRelPath(cfg.baseFolderPath_, folderRelPath))), L"Endless recursion.");
- }, *this, di.itemName))
+ }, *this, fi.itemName))
return nullptr;
return std::make_unique<DirCallback>(cfg, folderRelPath + FILE_NAME_SEPARATOR, subFolder, level_ + 1);
@@ -446,15 +446,15 @@ DirCallback::HandleError DirCallback::reportDirError(const std::wstring& msg, si
{
switch (cfg.acb_.reportError(msg, retryNumber)) //throw ThreadInterruption
{
- case FillBufferCallback::ON_ERROR_IGNORE:
+ case FillBufferCallback::ON_ERROR_CONTINUE:
cfg.failedDirReads_[beforeLast(parentRelPathPf_, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE)] = msg;
- return ON_ERROR_IGNORE;
+ return ON_ERROR_CONTINUE;
case FillBufferCallback::ON_ERROR_RETRY:
return ON_ERROR_RETRY;
}
assert(false);
- return ON_ERROR_IGNORE;
+ return ON_ERROR_CONTINUE;
}
@@ -462,15 +462,15 @@ DirCallback::HandleError DirCallback::reportItemError(const std::wstring& msg, s
{
switch (cfg.acb_.reportError(msg, retryNumber)) //throw ThreadInterruption
{
- case FillBufferCallback::ON_ERROR_IGNORE:
+ case FillBufferCallback::ON_ERROR_CONTINUE:
cfg.failedItemReads_[parentRelPathPf_ + itemName] = msg;
- return ON_ERROR_IGNORE;
+ return ON_ERROR_CONTINUE;
case FillBufferCallback::ON_ERROR_RETRY:
return ON_ERROR_RETRY;
}
assert(false);
- return ON_ERROR_IGNORE;
+ return ON_ERROR_CONTINUE;
}
//------------------------------------------------------------------------------------------
diff --git a/FreeFileSync/Source/lib/parallel_scan.h b/FreeFileSync/Source/lib/parallel_scan.h
index dd720472..901e9037 100644
--- a/FreeFileSync/Source/lib/parallel_scan.h
+++ b/FreeFileSync/Source/lib/parallel_scan.h
@@ -64,7 +64,7 @@ struct FillBufferCallback
enum HandleError
{
ON_ERROR_RETRY,
- ON_ERROR_IGNORE
+ ON_ERROR_CONTINUE
};
virtual HandleError reportError (const std::wstring& msg, size_t retryNumber) = 0; //may throw!
virtual void reportStatus(const std::wstring& msg, int itemsTotal ) = 0; //
diff --git a/FreeFileSync/Source/lib/parse_plural.h b/FreeFileSync/Source/lib/parse_plural.h
index 069a20f9..8c137b0d 100644
--- a/FreeFileSync/Source/lib/parse_plural.h
+++ b/FreeFileSync/Source/lib/parse_plural.h
@@ -245,21 +245,21 @@ private:
using TokenList = std::vector<std::pair<std::string, Token::Type>>;
const TokenList tokens
{
- { "?" , Token::TK_TERNARY_QUEST },
- { ":" , Token::TK_TERNARY_COLON },
+ { "?", Token::TK_TERNARY_QUEST },
+ { ":", Token::TK_TERNARY_COLON },
{ "||", Token::TK_OR },
{ "&&", Token::TK_AND },
{ "==", Token::TK_EQUAL },
{ "!=", Token::TK_NOT_EQUAL },
{ "<=", Token::TK_LESS_EQUAL },
- { "<" , Token::TK_LESS },
+ { "<", Token::TK_LESS },
{ ">=", Token::TK_GREATER_EQUAL },
- { ">" , Token::TK_GREATER },
- { "%" , Token::TK_MODULUS },
- { "n" , Token::TK_VARIABLE_N },
- { "N" , Token::TK_VARIABLE_N },
- { "(" , Token::TK_BRACKET_LEFT },
- { ")" , Token::TK_BRACKET_RIGHT },
+ { ">", Token::TK_GREATER },
+ { "%", Token::TK_MODULUS },
+ { "n", Token::TK_VARIABLE_N },
+ { "N", Token::TK_VARIABLE_N },
+ { "(", Token::TK_BRACKET_LEFT },
+ { ")", Token::TK_BRACKET_RIGHT },
};
const std::string stream_;
diff --git a/FreeFileSync/Source/lib/process_xml.cpp b/FreeFileSync/Source/lib/process_xml.cpp
index 1e31cabf..13918cb9 100644
--- a/FreeFileSync/Source/lib/process_xml.cpp
+++ b/FreeFileSync/Source/lib/process_xml.cpp
@@ -85,7 +85,7 @@ XmlGlobalSettings::XmlGlobalSettings()
static const wchar_t* winMergeExePath = running64BitWindows() ?
L"C:\\Program Files (x86)\\WinMerge\\WinMergeU.exe" :
L"C:\\Program Files\\WinMerge\\WinMergeU.exe";
- static const bool winMergeInstalled = fileExists(winMergeExePath); //magic statics!
+ static const bool winMergeInstalled = fileAvailable(winMergeExePath); //magic statics!
if (winMergeInstalled)
gui.externelApplications.emplace_back(L"WinMerge", Zstring(L"\"") + winMergeExePath + L"\" \"%local_path%\" \"%local_path2%\"");
@@ -722,25 +722,25 @@ bool readStruc(const XmlElement& input, ViewFilterDefault& value)
};
XmlIn sharedView = in["Shared"];
- readAttr(sharedView, "Equal" , value.equal);
+ readAttr(sharedView, "Equal", value.equal);
readAttr(sharedView, "Conflict", value.conflict);
readAttr(sharedView, "Excluded", value.excluded);
XmlIn catView = in["CategoryView"];
- readAttr(catView, "LeftOnly" , value.leftOnly);
- readAttr(catView, "RightOnly" , value.rightOnly);
- readAttr(catView, "LeftNewer" , value.leftNewer);
+ readAttr(catView, "LeftOnly", value.leftOnly);
+ readAttr(catView, "RightOnly", value.rightOnly);
+ readAttr(catView, "LeftNewer", value.leftNewer);
readAttr(catView, "RightNewer", value.rightNewer);
- readAttr(catView, "Different" , value.different);
+ readAttr(catView, "Different", value.different);
XmlIn actView = in["ActionView"];
- readAttr(actView, "CreateLeft" , value.createLeft);
+ readAttr(actView, "CreateLeft", value.createLeft);
readAttr(actView, "CreateRight", value.createRight);
- readAttr(actView, "UpdateLeft" , value.updateLeft);
+ readAttr(actView, "UpdateLeft", value.updateLeft);
readAttr(actView, "UpdateRight", value.updateRight);
- readAttr(actView, "DeleteLeft" , value.deleteLeft);
+ readAttr(actView, "DeleteLeft", value.deleteLeft);
readAttr(actView, "DeleteRight", value.deleteRight);
- readAttr(actView, "DoNothing" , value.doNothing);
+ readAttr(actView, "DoNothing", value.doNothing);
return success; //[!] avoid short-circuit evaluation above
}
@@ -751,25 +751,25 @@ void writeStruc(const ViewFilterDefault& value, XmlElement& output)
XmlOut out(output);
XmlOut sharedView = out["Shared"];
- sharedView.attribute("Equal" , value.equal);
+ sharedView.attribute("Equal", value.equal);
sharedView.attribute("Conflict", value.conflict);
sharedView.attribute("Excluded", value.excluded);
XmlOut catView = out["CategoryView"];
- catView.attribute("LeftOnly" , value.leftOnly);
- catView.attribute("RightOnly" , value.rightOnly);
- catView.attribute("LeftNewer" , value.leftNewer);
+ catView.attribute("LeftOnly", value.leftOnly);
+ catView.attribute("RightOnly", value.rightOnly);
+ catView.attribute("LeftNewer", value.leftNewer);
catView.attribute("RightNewer", value.rightNewer);
- catView.attribute("Different" , value.different);
+ catView.attribute("Different", value.different);
XmlOut actView = out["ActionView"];
- actView.attribute("CreateLeft" , value.createLeft);
+ actView.attribute("CreateLeft", value.createLeft);
actView.attribute("CreateRight", value.createRight);
- actView.attribute("UpdateLeft" , value.updateLeft);
+ actView.attribute("UpdateLeft", value.updateLeft);
actView.attribute("UpdateRight", value.updateRight);
- actView.attribute("DeleteLeft" , value.deleteLeft);
+ actView.attribute("DeleteLeft", value.deleteLeft);
actView.attribute("DeleteRight", value.deleteRight);
- actView.attribute("DoNothing" , value.doNothing);
+ actView.attribute("DoNothing", value.doNothing);
}
}
@@ -1046,16 +1046,16 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config, int formatVer)
inGeneral["FailSafeFileCopy" ].attribute("Enabled", config.failSafeFileCopy);
inGeneral["CopyLockedFiles" ].attribute("Enabled", config.copyLockedFiles);
inGeneral["CopyFilePermissions" ].attribute("Enabled", config.copyFilePermissions);
- inGeneral["AutomaticRetry" ].attribute("Count" , config.automaticRetryCount);
- inGeneral["AutomaticRetry" ].attribute("Delay" , config.automaticRetryDelay);
+ inGeneral["AutomaticRetry" ].attribute("Count", config.automaticRetryCount);
+ inGeneral["AutomaticRetry" ].attribute("Delay", config.automaticRetryDelay);
inGeneral["FileTimeTolerance" ].attribute("Seconds", config.fileTimeTolerance);
inGeneral["FolderAccessTimeout" ].attribute("Seconds", config.folderAccessTimeout);
inGeneral["RunWithBackgroundPriority"].attribute("Enabled", config.runWithBackgroundPriority);
inGeneral["LockDirectoriesDuringSync"].attribute("Enabled", config.createLockFile);
inGeneral["VerifyCopiedFiles" ].attribute("Enabled", config.verifyFileCopy);
- inGeneral["LastSyncsLogSizeMax" ].attribute("Bytes" , config.lastSyncsLogFileSizeMax);
+ inGeneral["LastSyncsLogSizeMax" ].attribute("Bytes", config.lastSyncsLogFileSizeMax);
inGeneral["NotificationSound" ].attribute("CompareFinished", config.soundFileCompareFinished);
- inGeneral["NotificationSound" ].attribute("SyncFinished" , config.soundFileSyncFinished);
+ inGeneral["NotificationSound" ].attribute("SyncFinished", config.soundFileSyncFinished);
XmlIn inOpt = inGeneral["OptionalDialogs"];
inOpt["WarnUnresolvedConflicts" ].attribute("Enabled", config.optDialogs.warningUnresolvedConflicts);
@@ -1088,8 +1088,8 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config, int formatVer)
XmlIn inCopyToHistory = inCopyTo["FolderHistory"];
inCopyToHistory(config.gui.mainDlg.copyToCfg.folderHistory);
- inCopyToHistory.attribute("LastUsedPath" , config.gui.mainDlg.copyToCfg.lastUsedPath);
- inCopyToHistory.attribute("MaxSize" , config.gui.mainDlg.copyToCfg.historySizeMax);
+ inCopyToHistory.attribute("LastUsedPath", config.gui.mainDlg.copyToCfg.lastUsedPath);
+ inCopyToHistory.attribute("MaxSize", config.gui.mainDlg.copyToCfg.historySizeMax);
XmlIn inManualDel = inWnd["ManualDeletion"];
inManualDel.attribute("UseRecycler", config.gui.mainDlg.manualDeletionUseRecycler);
@@ -1164,7 +1164,7 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config, int formatVer)
static const wchar_t* winMergeExePath = running64BitWindows() ?
L"C:\\Program Files (x86)\\WinMerge\\WinMergeU.exe" :
L"C:\\Program Files\\WinMerge\\WinMergeU.exe";
- static const bool winMergeInstalled = fileExists(winMergeExePath); //magic statics!
+ static const bool winMergeInstalled = fileAvailable(winMergeExePath); //magic statics!
if (winMergeInstalled)
config.gui.externelApplications.emplace_back(L"WinMerge", Zstring(L"\"") + winMergeExePath + L"\" \"%local_path%\" \"%local_path2%\"");
}
@@ -1496,16 +1496,16 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out)
outGeneral["FailSafeFileCopy" ].attribute("Enabled", config.failSafeFileCopy);
outGeneral["CopyLockedFiles" ].attribute("Enabled", config.copyLockedFiles);
outGeneral["CopyFilePermissions" ].attribute("Enabled", config.copyFilePermissions);
- outGeneral["AutomaticRetry" ].attribute("Count" , config.automaticRetryCount);
- outGeneral["AutomaticRetry" ].attribute("Delay" , config.automaticRetryDelay);
+ outGeneral["AutomaticRetry" ].attribute("Count", config.automaticRetryCount);
+ outGeneral["AutomaticRetry" ].attribute("Delay", config.automaticRetryDelay);
outGeneral["FileTimeTolerance" ].attribute("Seconds", config.fileTimeTolerance);
outGeneral["FolderAccessTimeout" ].attribute("Seconds", config.folderAccessTimeout);
outGeneral["RunWithBackgroundPriority"].attribute("Enabled", config.runWithBackgroundPriority);
outGeneral["LockDirectoriesDuringSync"].attribute("Enabled", config.createLockFile);
outGeneral["VerifyCopiedFiles" ].attribute("Enabled", config.verifyFileCopy);
- outGeneral["LastSyncsLogSizeMax" ].attribute("Bytes" , config.lastSyncsLogFileSizeMax);
+ outGeneral["LastSyncsLogSizeMax" ].attribute("Bytes", config.lastSyncsLogFileSizeMax);
outGeneral["NotificationSound" ].attribute("CompareFinished", config.soundFileCompareFinished);
- outGeneral["NotificationSound" ].attribute("SyncFinished" , config.soundFileSyncFinished);
+ outGeneral["NotificationSound" ].attribute("SyncFinished", config.soundFileSyncFinished);
XmlOut outOpt = outGeneral["OptionalDialogs"];
outOpt["WarnUnresolvedConflicts" ].attribute("Enabled", config.optDialogs.warningUnresolvedConflicts);
@@ -1538,8 +1538,8 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out)
XmlOut outCopyToHistory = outCopyTo["FolderHistory"];
outCopyToHistory(config.gui.mainDlg.copyToCfg.folderHistory);
- outCopyToHistory.attribute("LastUsedPath" , config.gui.mainDlg.copyToCfg.lastUsedPath);
- outCopyToHistory.attribute("MaxSize" , config.gui.mainDlg.copyToCfg.historySizeMax);
+ outCopyToHistory.attribute("LastUsedPath", config.gui.mainDlg.copyToCfg.lastUsedPath);
+ outCopyToHistory.attribute("MaxSize", config.gui.mainDlg.copyToCfg.historySizeMax);
XmlOut outManualDel = outWnd["ManualDeletion"];
outManualDel.attribute("UseRecycler", config.gui.mainDlg.manualDeletionUseRecycler);
diff --git a/FreeFileSync/Source/lib/status_handler.h b/FreeFileSync/Source/lib/status_handler.h
index a3616f2c..e050f7fa 100644
--- a/FreeFileSync/Source/lib/status_handler.h
+++ b/FreeFileSync/Source/lib/status_handler.h
@@ -65,7 +65,7 @@ protected:
}
void updateProcessedData(int itemsDelta, std::int64_t bytesDelta) override { updateData(numbersCurrent_, itemsDelta, bytesDelta); } //note: these methods MUST NOT throw in order
- void updateTotalData (int itemsDelta, std::int64_t bytesDelta) override { updateData(numbersTotal_ , itemsDelta, bytesDelta); } //to properly allow undoing setting of statistics!
+ void updateTotalData (int itemsDelta, std::int64_t bytesDelta) override { updateData(numbersTotal_, itemsDelta, bytesDelta); } //to properly allow undoing setting of statistics!
void requestUiRefresh() override //throw X
{
@@ -97,10 +97,10 @@ protected:
Phase currentPhase() const override { return currentPhase_; }
int getItemsCurrent(Phase phaseId) const override { return refNumbers(numbersCurrent_, phaseId).first; }
- int getItemsTotal (Phase phaseId) const override { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersTotal_ , phaseId).first; }
+ int getItemsTotal (Phase phaseId) const override { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersTotal_, phaseId).first; }
std::int64_t getBytesCurrent(Phase phaseId) const override { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersCurrent_, phaseId).second; }
- std::int64_t getBytesTotal (Phase phaseId) const override { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersTotal_ , phaseId).second; }
+ std::int64_t getBytesTotal (Phase phaseId) const override { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersTotal_, phaseId).second; }
const std::wstring& currentStatusText() const override { return statusText_; }
diff --git a/FreeFileSync/Source/lib/versioning.cpp b/FreeFileSync/Source/lib/versioning.cpp
index 02b3eca1..df23cb30 100644
--- a/FreeFileSync/Source/lib/versioning.cpp
+++ b/FreeFileSync/Source/lib/versioning.cpp
@@ -65,8 +65,8 @@ bool impl::isMatchingVersion(const Zstring& shortname, const Zstring& shortnameV
/*
create target super directories if missing
*/
-void FileVersioner::moveItemToVersioning(const AbstractPath& itemPath, const Zstring& relativePath, //throw FileError
- const std::function<void(const AbstractPath& sourcePath, const AbstractPath& targetPath)>& moveItem) //move source -> target; may throw FileError
+void FileVersioner::moveItemToVersioning(const Zstring& relativePath, //throw FileError
+ const std::function<void(const AbstractPath& targetPath)>& moveExistingItem) //move source -> target; may throw FileError
{
assert(!startsWith(relativePath, FILE_NAME_SEPARATOR));
assert(!endsWith (relativePath, FILE_NAME_SEPARATOR));
@@ -88,18 +88,29 @@ void FileVersioner::moveItemToVersioning(const AbstractPath& itemPath, const Zst
const AbstractPath versionedItemPath = AFS::appendRelPath(versioningFolderPath_, versionedRelPath);
try
{
- moveItem(itemPath, versionedItemPath); //throw FileError
+ moveExistingItem(versionedItemPath); //throw FileError
}
catch (const FileError&) //expected to fail if target directory is not yet existing!
{
+ warn_static("perf: combine with removeTarget!!!")
+
//create intermediate directories if missing
- const AbstractPath versionedParentPath = AFS::appendRelPath(versioningFolderPath_, beforeLast(versionedRelPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE));
- if (!AFS::somethingExists(versionedParentPath)) //->(minor) file system race condition!
+ if (Opt<AbstractPath> parentPath = AFS::getParentFolderPath(versionedItemPath))
{
- AFS::createFolderRecursively(versionedParentPath); //throw FileError
- //retry: this should work now!
- moveItem(itemPath, versionedItemPath); //throw FileError
- return;
+ Opt<AFS::PathDetails> pd;
+ try { pd = AFS::getPathDetails(*parentPath); /*throw FileError*/ }
+ catch (FileError&) {} //previous exception is more relevant
+
+ if (pd && !pd->relPath.empty()) //parent folder not existing
+ {
+ AbstractPath intermediatePath = pd->existingPath;
+ for (const Zstring& itemName : pd->relPath)
+ AFS::createFolderPlain(intermediatePath = AFS::appendRelPath(intermediatePath, itemName)); //throw FileError
+
+ //retry: this should work now!
+ moveExistingItem(versionedItemPath); //throw FileError
+ return;
+ }
}
throw;
}
@@ -112,122 +123,101 @@ namespace
//no need to check if super-directories of target exist: done by moveItemToVersioning()
//if target already exists, it is overwritten, even if it is a different type, e.g. a directory!
template <class Function>
-void moveItem(const AbstractPath& sourcePath, //throw FileError
- const AbstractPath& targetPath,
- Function copyDelete) //throw FileError; fallback if move failed
+void moveExistingItem(const AbstractPath& sourcePath, //throw FileError
+ const AbstractPath& targetPath,
+ Function copyDelete) //throw FileError; fallback if move failed
{
- assert(AFS::fileExists(sourcePath) || AFS::symlinkExists(sourcePath) || !AFS::somethingExists(sourcePath)); //we process files and symlinks only
-
- //first try to move directly without copying
- try
- {
- AFS::renameItem(sourcePath, targetPath); //throw FileError, ErrorTargetExisting, ErrorDifferentVolume
- return; //great, we get away cheaply!
- }
- catch (const FileError&)
+#ifndef NDEBUG
+ try { assert(AFS::getItemType(sourcePath) != AFS::ItemType::FOLDER); /*throw FileError*/ }
+ catch (FileError&) {} //we process files and symlinks only
+#endif
+ auto removeTarget = [&](bool expectExisting)
{
- //missing source item is not an error => check BEFORE calling removeTarget()!
- if (!AFS::somethingExists(sourcePath))
- return; //object *not* processed
-
- auto removeTarget = [&]
+ try
+ {
+ //file or (broken) file-symlink:
+ AFS::removeFilePlain(targetPath); //throw FileError
+ }
+ catch (FileError&)
{
+ //(folder-)symlink:
+ bool symlinkExists = false;
try
{
- //file or (broken) file-symlink:
- AFS::removeFile(targetPath); //throw FileError
- }
- catch (FileError&)
- {
- //folder or folder-symlink:
- if (AFS::folderExists(targetPath)) //directory or dir-symlink
+ if (expectExisting) //perf, perf, perf, every file access counts!
+ symlinkExists = AFS::getItemType(targetPath) == AFS::ItemType::SYMLINK; //throw FileError
+ else
{
- assert(AFS::symlinkExists(targetPath)); //we do not expect targetPath to be a directory in general (but possible!)
- AFS::removeFolderRecursively(targetPath, nullptr /*onBeforeFileDeletion*/, nullptr /*onBeforeFolderDeletion*/); //throw FileError
+ if (Opt<AFS::ItemType> type = AFS::getItemTypeIfExists(targetPath)) //throw FileError
+ symlinkExists = *type == AFS::ItemType::SYMLINK;
+ else
+ return;
}
- else
- throw;
}
- };
+ catch (FileError&) {} //previous exception is more relevant
- try { throw; }
- catch (const ErrorDifferentVolume&)
+ if (symlinkExists)
+ AFS::removeSymlinkPlain(targetPath); //throw FileError
+ else //overwrite AFS::ItemType::FOLDER with FILE? => highly dubious, do not allow
+ throw;
+ }
+ };
+
+ try //first try to move directly without copying
+ {
+ AFS::renameItem(sourcePath, targetPath); //throw FileError, ErrorTargetExisting, ErrorDifferentVolume
+ //great, we get away cheaply!
+ }
+ catch (const ErrorDifferentVolume&)
+ {
+ removeTarget(false /*expectExisting*/); //throw FileError
+ copyDelete(); //
+ }
+ catch (const ErrorTargetExisting&)
+ {
+ removeTarget(true /*expectExisting*/); //throw FileError
+ try
{
- removeTarget(); //throw FileError
- copyDelete(); //
+ AFS::renameItem(sourcePath, targetPath); //throw FileError, (ErrorTargetExisting), ErrorDifferentVolume
}
- catch (const ErrorTargetExisting&)
+ catch (const ErrorDifferentVolume&)
{
- removeTarget(); //throw FileError
- try
- {
- AFS::renameItem(sourcePath, targetPath); //throw FileError, (ErrorTargetExisting), ErrorDifferentVolume
- }
- catch (const ErrorDifferentVolume&)
- {
- copyDelete(); //throw FileError
- }
+ copyDelete(); //throw FileError
}
}
}
-void moveFileOrSymlink(const AbstractPath& sourcePath, //throw FileError
- const AbstractPath& targetPath,
- const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus) //may be nullptr
-{
- auto copyDelete = [&]
- {
- assert(!AFS::somethingExists(targetPath));
- if (AFS::symlinkExists(sourcePath))
- AFS::copySymlink(sourcePath, targetPath, false /*copy filesystem permissions*/); //throw FileError
- else
- AFS::copyFileTransactional(sourcePath, targetPath, //throw FileError, ErrorFileLocked
- false /*copyFilePermissions*/, true /*transactionalCopy*/, nullptr /*onDeleteTargetFile*/, onNotifyCopyStatus);
-
- AFS::removeFile(sourcePath); //throw FileError; newly copied file is NOT deleted if exception is thrown here!
- };
-
- moveItem(sourcePath, targetPath, copyDelete); //throw FileError
-}
-
-
-void moveFile(const AbstractPath& sourcePath, //throw FileError
- const AbstractPath& targetPath,
- const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus) //may be nullptr
+void moveExistingFile(const AbstractPath& sourcePath, //throw FileError
+ const AbstractPath& targetPath,
+ const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus) //may be nullptr
{
auto copyDelete = [&]
{
- assert(!AFS::somethingExists(targetPath));
+#ifndef NDEBUG
+ try { assert(!AFS::getItemTypeIfExists(targetPath)); /*throw FileError*/ }
+ catch (FileError&) {}
+#endif
AFS::copyFileTransactional(sourcePath, targetPath, //throw FileError, ErrorFileLocked
false /*copyFilePermissions*/, true /*transactionalCopy*/, nullptr /*onDeleteTargetFile*/, onNotifyCopyStatus);
- AFS::removeFile(sourcePath); //throw FileError; newly copied file is NOT deleted if exception is thrown here!
+ AFS::removeFilePlain(sourcePath); //throw FileError; newly copied item is NOT deleted if exception is thrown here!
};
- moveItem(sourcePath, targetPath, copyDelete); //throw FileError
+ moveExistingItem(sourcePath, targetPath, copyDelete); //throw FileError
}
-void moveFileSymlink(const AbstractPath& sourcePath, const AbstractPath& targetPath) //throw FileError
+void moveExistingSymlink(const AbstractPath& sourcePath, const AbstractPath& targetPath) //throw FileError
{
auto copyDelete = [&]
{
- assert(!AFS::somethingExists(targetPath));
- AFS::copySymlink(sourcePath, targetPath, false /*copy filesystem permissions*/); //throw FileError
- AFS::removeFile(sourcePath); //throw FileError; newly copied file is NOT deleted if exception is thrown here!
- };
- moveItem(sourcePath, targetPath, copyDelete); //throw FileError
-}
-
-
-void moveFolderSymlink(const AbstractPath& sourcePath, const AbstractPath& targetPath) //throw FileError
-{
- auto copyDelete = [&] //throw FileError
- {
- assert(!AFS::somethingExists(targetPath));
+#ifndef NDEBUG
+ try { assert(!AFS::getItemTypeIfExists(targetPath)); /*throw FileError*/ }
+ catch (FileError&) {}
+#endif
AFS::copySymlink(sourcePath, targetPath, false /*copy filesystem permissions*/); //throw FileError
- AFS::removeFolderSimple(sourcePath); //throw FileError; newly copied link is NOT deleted if exception is thrown here!
+ AFS::removeSymlinkPlain(sourcePath); //throw FileError; newly copied item is NOT deleted if exception is thrown here!
};
- moveItem(sourcePath, targetPath, copyDelete);
+ moveExistingItem(sourcePath, targetPath, copyDelete); //throw FileError
}
@@ -235,45 +225,65 @@ struct FlatTraverserCallback: public AFS::TraverserCallback
{
FlatTraverserCallback(const AbstractPath& folderPath) : folderPath_(folderPath) {}
- const std::vector<Zstring>& refFileNames () const { return fileNames_; }
- const std::vector<Zstring>& refFolderNames () const { return folderNames_; }
- const std::vector<Zstring>& refFileLinkNames () const { return fileLinkNames_; }
- const std::vector<Zstring>& refFolderLinkNames() const { return folderLinkNames_; }
+ const std::vector<Zstring>& refFileNames () const { return fileNames_; }
+ const std::vector<Zstring>& refFolderNames () const { return folderNames_; }
+ const std::vector<Zstring>& refSymlinkNames() const { return symlinkNames_; }
private:
- void onFile (const FileInfo& fi) override { fileNames_ .push_back(fi.itemName); }
- std::unique_ptr<TraverserCallback> onDir (const DirInfo& di) override { folderNames_.push_back(di.itemName); return nullptr; }
- HandleLink onSymlink(const SymlinkInfo& si) override
- {
- if (AFS::folderExists(AFS::appendRelPath(folderPath_, si.itemName))) //dir symlink
- folderLinkNames_.push_back(si.itemName);
- else //file symlink, broken symlink
- fileLinkNames_.push_back(si.itemName);
- return TraverserCallback::LINK_SKIP;
- }
+ void onFile (const FileInfo& fi) override { fileNames_ .push_back(fi.itemName); }
+ std::unique_ptr<TraverserCallback> onFolder (const FolderInfo& fi) override { folderNames_ .push_back(fi.itemName); return nullptr; }
+ HandleLink onSymlink(const SymlinkInfo& si) override { symlinkNames_.push_back(si.itemName); return TraverserCallback::LINK_SKIP; }
+
HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override { throw FileError(msg); }
HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zstring& itemName) override { throw FileError(msg); }
const AbstractPath folderPath_;
std::vector<Zstring> fileNames_;
std::vector<Zstring> folderNames_;
- std::vector<Zstring> fileLinkNames_;
- std::vector<Zstring> folderLinkNames_;
+ std::vector<Zstring> symlinkNames_;
};
}
bool FileVersioner::revisionFile(const AbstractPath& filePath, const Zstring& relativePath, const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus) //throw FileError
{
- bool moveSuccessful = false;
+ if (Opt<AFS::ItemType> type = AFS::getItemTypeIfExists(filePath)) //throw FileError
+ {
+ bool moveSuccessful = false;
- moveItemToVersioning(filePath, relativePath, //throw FileError
- [&](const AbstractPath& sourcePath, const AbstractPath& targetPath)
+ moveItemToVersioning(relativePath, //throw FileError
+ [&](const AbstractPath& targetPath)
+ {
+ if (*type == AFS::ItemType::SYMLINK)
+ moveExistingSymlink(filePath, targetPath); //throw FileError
+ else
+ moveExistingFile(filePath, targetPath, onNotifyCopyStatus); //throw FileError
+
+ moveSuccessful = true;
+ });
+ return moveSuccessful;
+ }
+ else
+ return false; //missing source item is not an error => check BEFORE oerwriting target
+}
+
+
+bool FileVersioner::revisionSymlink(const AbstractPath& linkPath, const Zstring& relativePath) //throw FileError
+{
+ if (AFS::getItemTypeIfExists(linkPath)) //throw FileError
{
- moveFileOrSymlink(sourcePath, targetPath, onNotifyCopyStatus); //throw FileError
- moveSuccessful = true;
- });
- return moveSuccessful;
+ bool moveSuccessful = false;
+
+ moveItemToVersioning(relativePath, //throw FileError
+ [&](const AbstractPath& targetPath)
+ {
+ moveExistingSymlink(linkPath, targetPath); //throw FileError
+ moveSuccessful = true;
+ });
+ return moveSuccessful;
+ }
+ else
+ return false;
}
@@ -282,22 +292,22 @@ void FileVersioner::revisionFolder(const AbstractPath& folderPath, const Zstring
const std::function<void(const std::wstring& displayPathFrom, const std::wstring& displayPathTo)>& onBeforeFolderMove,
const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus)
{
- if (AFS::symlinkExists(folderPath)) //on Linux there is just one type of symlink, and since we do revision file symlinks, we should revision dir symlinks as well!
+ if (Opt<AFS::ItemType> type = AFS::getItemTypeIfExists(folderPath)) //throw FileError
{
- moveItemToVersioning(folderPath, relativePath, //throw FileError
- [&](const AbstractPath& sourcePath, const AbstractPath& targetPath)
+ if (*type == AFS::ItemType::SYMLINK) //on Linux there is just one type of symlink, and since we do revision file symlinks, we should revision dir symlinks as well!
{
- if (onBeforeFolderMove)
- onBeforeFolderMove(AFS::getDisplayPath(sourcePath), AFS::getDisplayPath(targetPath));
- moveFolderSymlink(sourcePath, targetPath); //throw FileError
- });
- }
- else
- {
- //no error situation if directory is not existing! manual deletion relies on it!
- if (AFS::somethingExists(folderPath))
+ moveItemToVersioning(relativePath, //throw FileError
+ [&](const AbstractPath& targetPath)
+ {
+ if (onBeforeFileMove)
+ onBeforeFileMove(AFS::getDisplayPath(folderPath), AFS::getDisplayPath(targetPath));
+ moveExistingSymlink(folderPath, targetPath); //throw FileError
+ });
+ }
+ else
revisionFolderImpl(folderPath, relativePath, onBeforeFileMove, onBeforeFolderMove, onNotifyCopyStatus); //throw FileError
}
+ //no error situation if directory is not existing! manual deletion relies on it!
}
@@ -306,8 +316,10 @@ void FileVersioner::revisionFolderImpl(const AbstractPath& folderPath, const Zst
const std::function<void(const std::wstring& displayPathFrom, const std::wstring& displayPathTo)>& onBeforeFolderMove,
const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus)
{
- assert(!AFS::symlinkExists(folderPath)); //[!] no symlinks in this context!!!
- assert(AFS::folderExists(folderPath)); //Do NOT traverse into it deleting contained files!!!
+#ifndef NDEBUG //[!] no symlinks in this context!!! Do NOT traverse into it deleting contained files!!!
+ try { assert(AFS::getItemType(folderPath) != AFS::ItemType::SYMLINK); /*throw FileError*/ }
+ catch (FileError&) {}
+#endif
//create target directories only when needed in moveFileToVersioning(): avoid empty directories!
@@ -317,34 +329,23 @@ void FileVersioner::revisionFolderImpl(const AbstractPath& folderPath, const Zst
const Zstring relPathPf = appendSeparator(relativePath);
for (const Zstring& fileName : ft.refFileNames())
- moveItemToVersioning(AFS::appendRelPath(folderPath, fileName), //throw FileError
- relPathPf + fileName,
- [&](const AbstractPath& sourcePath, const AbstractPath& targetPath)
+ moveItemToVersioning(relPathPf + fileName, //throw FileError
+ [&](const AbstractPath& targetPath)
{
+ const AbstractPath sourcePath = AFS::appendRelPath(folderPath, fileName);
if (onBeforeFileMove)
onBeforeFileMove(AFS::getDisplayPath(sourcePath), AFS::getDisplayPath(targetPath));
- moveFile(sourcePath, targetPath, onNotifyCopyStatus); //throw FileError
+ moveExistingFile(sourcePath, targetPath, onNotifyCopyStatus); //throw FileError
});
- for (const Zstring& fileLinkName : ft.refFileLinkNames())
- moveItemToVersioning(AFS::appendRelPath(folderPath, fileLinkName), //throw FileError
- relPathPf + fileLinkName,
- [&](const AbstractPath& sourcePath, const AbstractPath& targetPath)
+ for (const Zstring& symlinkName : ft.refSymlinkNames())
+ moveItemToVersioning(relPathPf + symlinkName, //throw FileError
+ [&](const AbstractPath& targetPath)
{
+ const AbstractPath sourcePath = AFS::appendRelPath(folderPath, symlinkName);
if (onBeforeFileMove)
onBeforeFileMove(AFS::getDisplayPath(sourcePath), AFS::getDisplayPath(targetPath));
- moveFileSymlink(sourcePath, targetPath); //throw FileError
- });
-
- //on Linux there is just one type of symlink, and since we do revision file symlinks, we should revision dir symlinks as well!
- for (const Zstring& folderLinkName : ft.refFolderLinkNames())
- moveItemToVersioning(AFS::appendRelPath(folderPath, folderLinkName), //throw FileError
- relPathPf + folderLinkName,
- [&](const AbstractPath& sourcePath, const AbstractPath& targetPath)
- {
- if (onBeforeFolderMove)
- onBeforeFolderMove(AFS::getDisplayPath(sourcePath), AFS::getDisplayPath(targetPath));
- moveFolderSymlink(sourcePath, targetPath); //throw FileError
+ moveExistingSymlink(sourcePath, targetPath); //throw FileError
});
//move folders recursively
@@ -356,7 +357,7 @@ void FileVersioner::revisionFolderImpl(const AbstractPath& folderPath, const Zst
if (onBeforeFolderMove)
onBeforeFolderMove(AFS::getDisplayPath(folderPath), AFS::getDisplayPath(AFS::appendRelPath(versioningFolderPath_, relativePath)));
- AFS::removeFolderSimple(folderPath); //throw FileError
+ AFS::removeFolderPlain(folderPath); //throw FileError
}
diff --git a/FreeFileSync/Source/lib/versioning.h b/FreeFileSync/Source/lib/versioning.h
index 82bf9531..821c3b18 100644
--- a/FreeFileSync/Source/lib/versioning.h
+++ b/FreeFileSync/Source/lib/versioning.h
@@ -47,10 +47,11 @@ public:
bool revisionFile(const AbstractPath& filePath, //throw FileError; return "false" if file is not existing
const Zstring& relativePath,
-
//called frequently if move has to revert to copy + delete => see zen::copyFile for limitations when throwing exceptions!
const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus); //may be nullptr
+ bool revisionSymlink(const AbstractPath& linkPath, const Zstring& relativePath); //throw FileError; return "false" if file is not existing
+
void revisionFolder(const AbstractPath& folderPath, const Zstring& relativePath, //throw FileError
//optional callbacks: may be nullptr
@@ -67,9 +68,8 @@ private:
const std::function<void(const std::wstring& displayPathFrom, const std::wstring& displayPathTo)>& onBeforeFolderMove,
const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus); //throw FileError
- void moveItemToVersioning(const AbstractPath& itemPath, //throw FileError
- const Zstring& relativePath,
- const std::function<void(const AbstractPath& sourcePath, const AbstractPath& targetPath)>& moveItem); //may throw FileError
+ void moveItemToVersioning(const Zstring& relativePath, //throw FileError
+ const std::function<void(const AbstractPath& targetPath)>& moveItem); //may throw FileError
const AbstractPath versioningFolderPath_;
const VersioningStyle versioningStyle_;
diff --git a/FreeFileSync/Source/synchronization.cpp b/FreeFileSync/Source/synchronization.cpp
index 4f36ded1..bc8fc6fd 100644
--- a/FreeFileSync/Source/synchronization.cpp
+++ b/FreeFileSync/Source/synchronization.cpp
@@ -353,7 +353,7 @@ public:
template <class Function> void removeFileWithCallback (const AbstractPath& filePath, const Zstring& relativePath, Function onNotifyItemDeletion, const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus); //
template <class Function> void removeDirWithCallback (const AbstractPath& dirPath, const Zstring& relativePath, Function onNotifyItemDeletion, const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus); //throw FileError
- template <class Function> void removeLinkWithCallback (const AbstractPath& linkPath, const Zstring& relativePath, Function onNotifyItemDeletion, const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus); //
+ template <class Function> void removeLinkWithCallback (const AbstractPath& linkPath, const Zstring& relativePath, Function onNotifyItemDeletion); //
const std::wstring& getTxtRemovingFile () const { return txtRemovingFile_; } //
const std::wstring& getTxtRemovingFolder () const { return txtRemovingFolder_; } //buffered status texts
@@ -500,12 +500,12 @@ void DeletionHandling::removeDirWithCallback(const AbstractPath& folderPath,
auto onBeforeFileDeletion = [&](const std::wstring& displayPath) { notifyDeletion(txtRemovingFile_, displayPath); };
auto onBeforeDirDeletion = [&](const std::wstring& displayPath) { notifyDeletion(txtRemovingFolder_, displayPath); };
- AFS::removeFolderRecursively(folderPath, onBeforeFileDeletion, onBeforeDirDeletion); //throw FileError
+ AFS::removeFolderIfExistsRecursion(folderPath, onBeforeFileDeletion, onBeforeDirDeletion); //throw FileError
}
break;
case DeletionPolicy::RECYCLER:
- if (getOrCreateRecyclerSession().recycleItem(folderPath, relativePath)) //throw FileError; return true if item existed
+ if (getOrCreateRecyclerSession().recycleItem(folderPath, relativePath)) //throw FileError
onNotifyItemDeletion(); //moving to recycler is ONE logical operation, irrespective of the number of child elements!
break;
@@ -535,18 +535,16 @@ void DeletionHandling::removeFileWithCallback(const AbstractPath& filePath,
bool deleted = false;
if (endsWith(relativePath, AFS::TEMP_FILE_ENDING)) //special rule for .ffs_tmp files: always delete permanently!
- deleted = AFS::removeFile(filePath); //throw FileError
+ deleted = AFS::removeFileIfExists(filePath); //throw FileError
else
switch (deletionPolicy_)
{
case DeletionPolicy::PERMANENT:
- deleted = AFS::removeFile(filePath); //throw FileError
+ deleted = AFS::removeFileIfExists(filePath); //throw FileError
break;
-
case DeletionPolicy::RECYCLER:
- deleted = getOrCreateRecyclerSession().recycleItem(filePath, relativePath); //throw FileError; return true if item existed
+ deleted = getOrCreateRecyclerSession().recycleItem(filePath, relativePath); //throw FileError
break;
-
case DeletionPolicy::VERSIONING:
deleted = getOrCreateVersioner().revisionFile(filePath, relativePath, onNotifyCopyStatus); //throw FileError
break;
@@ -557,12 +555,24 @@ void DeletionHandling::removeFileWithCallback(const AbstractPath& filePath,
template <class Function> inline
-void DeletionHandling::removeLinkWithCallback(const AbstractPath& linkPath, const Zstring& relativePath, Function onNotifyItemDeletion, const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus) //throw FileError
+void DeletionHandling::removeLinkWithCallback(const AbstractPath& linkPath, const Zstring& relativePath, Function onNotifyItemDeletion) //throw FileError
{
- if (AFS::folderExists(linkPath)) //dir symlink
- return removeDirWithCallback(linkPath, relativePath, onNotifyItemDeletion, onNotifyCopyStatus); //throw FileError
- else //file symlink, broken symlink
- return removeFileWithCallback(linkPath, relativePath, onNotifyItemDeletion, onNotifyCopyStatus); //throw FileError
+ bool deleted = false;
+
+ switch (deletionPolicy_)
+ {
+ case DeletionPolicy::PERMANENT:
+ deleted = AFS::removeSymlinkIfExists(linkPath); //throw FileError
+ break;
+ case DeletionPolicy::RECYCLER:
+ deleted = getOrCreateRecyclerSession().recycleItem(linkPath, relativePath); //throw FileError
+ break;
+ case DeletionPolicy::VERSIONING:
+ deleted = getOrCreateVersioner().revisionSymlink(linkPath, relativePath); //throw FileError
+ break;
+ }
+ if (deleted)
+ onNotifyItemDeletion();
}
//------------------------------------------------------------------------------------------------------------
@@ -1183,13 +1193,14 @@ void SynchronizeFolderPair::synchronizeFileInt(FilePair& file, SyncOperation syn
}
catch (FileError&)
{
- if (AFS::somethingExists(file.getAbstractPath<sideSrc>())) //do not check on type (symlink, file, folder) -> if there is a type change, FFS should error out!
- throw;
-
- //TODO: failure to access base dir is incorrectly considered an empty dir
+ bool sourceWasDeleted = false;
+ try { sourceWasDeleted = !AFS::getItemTypeIfExists(file.getAbstractPath<sideSrc>()); /*throw FileError*/ }
+ catch (FileError&) {} //previous exception is more relevant
- //source deleted meanwhile...nothing was done (logical point of view!)
- file.removeObject<sideSrc>(); //remove only *after* evaluating "file, sideSrc"!
+ if (sourceWasDeleted)
+ file.removeObject<sideSrc>(); //source deleted meanwhile...nothing was done (logical point of view!)
+ else
+ throw; //do not check on type (symlink, file, folder) -> if there is a type change, FFS should not be quiet about it!
}
}
break;
@@ -1394,13 +1405,14 @@ void SynchronizeFolderPair::synchronizeLinkInt(SymlinkPair& symlink, SyncOperati
}
catch (FileError&)
{
- if (AFS::somethingExists(symlink.getAbstractPath<sideSrc>())) //do not check on type (symlink, file, folder) -> if there is a type change, FFS should not be quiet about it!
- throw;
-
- //TODO: failure to access base dir is incorrectly considered an empty dir
+ bool sourceWasDeleted = false;
+ try { sourceWasDeleted = !AFS::getItemTypeIfExists(symlink.getAbstractPath<sideSrc>()); /*throw FileError*/ }
+ catch (FileError&) {} //previous exception is more relevant
- //source deleted meanwhile...nothing was done (logical point of view!)
- symlink.removeObject<sideSrc>();
+ if (sourceWasDeleted)
+ symlink.removeObject<sideSrc>(); //source deleted meanwhile...nothing was done (logical point of view!)
+ else
+ throw; //do not check on type (symlink, file, folder) -> if there is a type change, FFS should not be quiet about it!
}
}
break;
@@ -1412,9 +1424,8 @@ void SynchronizeFolderPair::synchronizeLinkInt(SymlinkPair& symlink, SyncOperati
StatisticsReporter statReporter(1, 0, procCallback_);
auto onNotifyItemDeletion = [&] { statReporter.reportDelta(1, 0); };
- auto onNotifyCopyStatus = [&](std::int64_t bytesDelta) { statReporter.reportDelta(0, bytesDelta); };
- getDelHandling<sideTrg>().removeLinkWithCallback(symlink.getAbstractPath<sideTrg>(), symlink.getPairRelativePath(), onNotifyItemDeletion, onNotifyCopyStatus); //throw FileError
+ getDelHandling<sideTrg>().removeLinkWithCallback(symlink.getAbstractPath<sideTrg>(), symlink.getPairRelativePath(), onNotifyItemDeletion); //throw FileError
//TODO: failure to access item during deletion is an error and should not be ignored!
@@ -1428,10 +1439,8 @@ void SynchronizeFolderPair::synchronizeLinkInt(SymlinkPair& symlink, SyncOperati
{
StatisticsReporter statReporter(1, 0, procCallback_);
- auto onNotifyCopyStatus = [&](std::int64_t bytesDelta) { statReporter.reportDelta(0, bytesDelta); };
-
//reportStatus(getDelHandling<sideTrg>().getTxtRemovingSymLink(), AFS::getDisplayPath(symlink.getAbstractPath<sideTrg>()));
- getDelHandling<sideTrg>().removeLinkWithCallback(symlink.getAbstractPath<sideTrg>(), symlink.getPairRelativePath(), [] {}, onNotifyCopyStatus); //throw FileError
+ getDelHandling<sideTrg>().removeLinkWithCallback(symlink.getAbstractPath<sideTrg>(), symlink.getPairRelativePath(), [] {}); //throw FileError
//symlink.removeObject<sideTrg>(); -> "symlink, sideTrg" evaluated below!
@@ -1522,24 +1531,32 @@ void SynchronizeFolderPair::synchronizeFolderInt(FolderPair& folder, SyncOperati
const AbstractPath targetPath = AFS::appendRelPath(folder.base().getAbstractPath<sideTrg>(), folder.getRelativePath<sideSrc>());
reportInfo(txtCreatingFolder, AFS::getDisplayPath(targetPath));
- if (AFS::somethingExists(folder.getAbstractPath<sideSrc>())) //do not check on type (symlink, file, folder) -> if there is a type change, FFS should error out!
+ //shallow-"copying" a folder might not fail if source is missing, so we need to check this first:
+ if (AFS::getItemTypeIfExists(folder.getAbstractPath<sideSrc>())) //throw FileError
{
StatisticsReporter statReporter(1, 0, procCallback_);
try
{
AFS::copyNewFolder(folder.getAbstractPath<sideSrc>(), targetPath, copyFilePermissions_); //throw FileError
}
- catch (const FileError&) { if (!AFS::folderExists(targetPath)) throw; }
+ catch (FileError&)
+ {
+ bool folderAlreadyExists = false;
+ try { folderAlreadyExists = AFS::getItemType(targetPath) == AFS::ItemType::FOLDER; } /*throw FileError*/ catch (FileError&) {} //previous exception is more relevant
+
+ if (!folderAlreadyExists)
+ throw;
+ }
statReporter.reportDelta(1, 0);
//update FolderPair
- folder.setSyncedTo(folder.getItemName<sideSrc>());
+ folder.setSyncedTo<sideTrg>(folder.getItemName<sideSrc>(),
+ false, //isSymlinkTrg
+ folder.isFollowedSymlink<sideSrc>());
}
- else //source deleted meanwhile...nothing was done (logical point of view!) -> uh....what about a temporary network drop???
+ else //source deleted meanwhile...nothing was done (logical point of view!)
{
- //TODO: failure to access base dir is incorrectly considered an empty dir
-
const SyncStatistics subStats(folder);
StatisticsReporter statReporter(1 + getCUD(subStats), subStats.getBytesToProcess(), procCallback_);
@@ -1590,7 +1607,9 @@ void SynchronizeFolderPair::synchronizeFolderInt(FolderPair& folder, SyncOperati
statReporter.reportDelta(1, 0);
//-> both sides *should* be completely equal now...
- folder.setSyncedTo(folder.getItemName<sideSrc>());
+ folder.setSyncedTo<sideTrg>(folder.getItemName<sideSrc>(),
+ folder.isFollowedSymlink<sideTrg>(),
+ folder.isFollowedSymlink<sideSrc>());
}
break;
@@ -1711,7 +1730,8 @@ AFS::FileAttribAfterCopy SynchronizeFolderPair::copyFileWithCallback(const Abstr
//#################### Verification #############################
if (verifyCopiedFiles_)
{
- ZEN_ON_SCOPE_FAIL( AFS::removeFile(targetPath); ); //delete target if verification fails
+ ZEN_ON_SCOPE_FAIL(try { AFS::removeFilePlain(targetPath); }
+ catch (FileError&) {}); //delete target if verification fails
procCallback_.reportInfo(replaceCpy(txtVerifying, L"%x", fmtPath(AFS::getDisplayPath(targetPath))));
verifyFiles(sourcePathTmp, targetPath, [&](std::int64_t bytesDelta) { procCallback_.requestUiRefresh(); }); //throw FileError
@@ -1763,7 +1783,7 @@ bool baseFolderDrop(BaseFolderPair& baseFolder, int folderAccessTimeout, Process
{
const AbstractPath folderPath = baseFolder.getAbstractPath<side>();
- if (baseFolder.isExisting<side>())
+ if (baseFolder.isAvailable<side>())
if (Opt<std::wstring> errMsg = tryReportingError([&]
{
const FolderStatus status = getFolderStatusNonBlocking({ folderPath }, folderAccessTimeout, false /*allowUserInteraction*/, callback);
@@ -1783,30 +1803,30 @@ bool baseFolderDrop(BaseFolderPair& baseFolder, int folderAccessTimeout, Process
template <SelectedSide side> //create base directories first (if not yet existing) -> no symlink or attribute copying!
-bool createBaseFolder(BaseFolderPair& baseFolder, ProcessCallback& callback) //nothrow; return false if fatal error occurred
+bool createBaseFolder(BaseFolderPair& baseFolder, int folderAccessTimeout, ProcessCallback& callback) //nothrow; return false if fatal error occurred
{
const AbstractPath baseFolderPath = baseFolder.getAbstractPath<side>();
if (AFS::isNullPath(baseFolderPath))
return true;
- if (!baseFolder.isExisting<side>()) //create target directory: user presumably ignored error "dir existing" in order to have it created automatically
+ if (!baseFolder.isAvailable<side>()) //create target directory: user presumably ignored error "dir existing" in order to have it created automatically
{
bool temporaryNetworkDrop = false;
zen::Opt<std::wstring> errMsg = tryReportingError([&]
{
- try
- {
- //a nice race-free check and set operation:
- AFS::createFolderSimple(baseFolderPath); //throw FileError, ErrorTargetExisting, ErrorTargetPathMissing
- baseFolder.setExisting<side>(true); //update our model!
- }
- catch (ErrorTargetPathMissing&)
+ const FolderStatus status = getFolderStatusNonBlocking({ baseFolderPath }, folderAccessTimeout, false /*allowUserInteraction*/, callback);
+
+ static_assert(IsSameType<decltype(status.failedChecks.begin()->second), FileError>::value, "");
+ if (!status.failedChecks.empty())
+ throw status.failedChecks.begin()->second;
+
+ if (status.notExisting.find(baseFolderPath) != status.notExisting.end())
{
- AFS::createFolderRecursively(baseFolderPath); //throw FileError
- baseFolder.setExisting<side>(true); //update our model!
+ AFS::createFolderIfMissingRecursion(baseFolderPath); //throw FileError
+ baseFolder.setAvailable<side>(true); //update our model!
}
- catch (ErrorTargetExisting&)
+ else
{
//TEMPORARY network drop! base directory not found during comparison, but reappears during synchronization
//=> sync-directions are based on false assumptions! Abort.
@@ -1821,7 +1841,6 @@ bool createBaseFolder(BaseFolderPair& baseFolder, ProcessCallback& callback) //n
}, callback); //throw X?
return !errMsg && !temporaryNetworkDrop;
}
-
return true;
}
@@ -2021,22 +2040,22 @@ void zen::synchronize(const TimeComp& timeStamp,
}
//allow propagation of deletions only from *null-* or *existing* source folder:
- auto sourceFolderMissing = [&](const AbstractPath& baseFolderPath, bool wasExisting) //we need to evaluate existence status from time of comparison!
+ auto sourceFolderMissing = [&](const AbstractPath& baseFolderPath, bool wasAvailable) //we need to evaluate existence status from time of comparison!
{
if (!AFS::isNullPath(baseFolderPath))
//PERMANENT network drop: avoid data loss when source directory is not found AND user chose to ignore errors (else we wouldn't arrive here)
if (folderPairStat.deleteCount() > 0) //check deletions only... (respect filtered items!)
//folderPairStat.conflictCount() == 0 && -> there COULD be conflicts for <Two way> variant if directory existence check fails, but loading sync.ffs_db succeeds
//https://sourceforge.net/tracker/?func=detail&atid=1093080&aid=3531351&group_id=234430 -> fixed, but still better not consider conflicts!
- if (!wasExisting) //avoid race-condition: we need to evaluate existence status from time of comparison!
+ if (!wasAvailable) //avoid race-condition: we need to evaluate existence status from time of comparison!
{
callback.reportFatalError(replaceCpy(_("Source folder %x not found."), L"%x", fmtPath(AFS::getDisplayPath(baseFolderPath))));
return true;
}
return false;
};
- if (sourceFolderMissing(baseFolder.getAbstractPath< LEFT_SIDE>(), baseFolder.isExisting< LEFT_SIDE>()) ||
- sourceFolderMissing(baseFolder.getAbstractPath<RIGHT_SIDE>(), baseFolder.isExisting<RIGHT_SIDE>()))
+ if (sourceFolderMissing(baseFolder.getAbstractPath< LEFT_SIDE>(), baseFolder.isAvailable< LEFT_SIDE>()) ||
+ sourceFolderMissing(baseFolder.getAbstractPath<RIGHT_SIDE>(), baseFolder.isAvailable<RIGHT_SIDE>()))
{
jobType[folderIndex] = FolderPairJobType::SKIP;
continue;
@@ -2202,15 +2221,15 @@ void zen::synchronize(const TimeComp& timeStamp,
L" " + AFS::getDisplayPath(baseFolder.getAbstractPath<RIGHT_SIDE>()));
//------------------------------------------------------------------------------------------
- //checking a second time: (a long time may have passed since the intro checks!)
+ //checking a second time: (a long time may have passed since folder comparison!)
if (baseFolderDrop< LEFT_SIDE>(baseFolder, folderAccessTimeout, callback) ||
baseFolderDrop<RIGHT_SIDE>(baseFolder, folderAccessTimeout, callback))
continue;
//create base folders if not yet existing
if (folderPairStat.createCount() > 0 || folderPairCfg.saveSyncDB_) //else: temporary network drop leading to deletions already caught by "sourceFolderMissing" check!
- if (!createBaseFolder< LEFT_SIDE>(baseFolder, callback) || //+ detect temporary network drop!!
- !createBaseFolder<RIGHT_SIDE>(baseFolder, callback)) //
+ if (!createBaseFolder< LEFT_SIDE>(baseFolder, folderAccessTimeout, callback) || //+ detect temporary network drop!!
+ !createBaseFolder<RIGHT_SIDE>(baseFolder, folderAccessTimeout, callback)) //
continue;
//------------------------------------------------------------------------------------------
diff --git a/FreeFileSync/Source/ui/batch_status_handler.cpp b/FreeFileSync/Source/ui/batch_status_handler.cpp
index 76fe7b10..3d56ad7c 100644
--- a/FreeFileSync/Source/ui/batch_status_handler.cpp
+++ b/FreeFileSync/Source/ui/batch_status_handler.cpp
@@ -33,7 +33,7 @@ std::pair<std::unique_ptr<AFS::OutputStream>, AbstractPath> prepareNewLogfile(co
assert(!jobName.empty());
//create logfile folder if required
- AFS::createFolderRecursively(logFolderPath); //throw FileError
+ AFS::createFolderIfMissingRecursion(logFolderPath); //throw FileError
//const std::string colon = "\xcb\xb8"; //="modifier letter raised colon" => regular colon is forbidden in file names on Windows and OS X
//=> too many issues, most notably cmd.exe is not Unicode-awere: http://www.freefilesync.org/forum/viewtopic.php?t=1679
@@ -76,11 +76,11 @@ struct LogTraverserCallback: public AFS::TraverserCallback
if (onUpdateStatus_)
onUpdateStatus_();
}
- std::unique_ptr<TraverserCallback> onDir (const DirInfo& di) override { return nullptr; }
+ std::unique_ptr<TraverserCallback> onFolder (const FolderInfo& fi) override { return nullptr; }
HandleLink onSymlink(const SymlinkInfo& si) override { return TraverserCallback::LINK_SKIP; }
- HandleError reportDirError (const std::wstring& msg, size_t retryNumber ) override { setError(msg); return ON_ERROR_IGNORE; }
- HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zstring& itemName) override { setError(msg); return ON_ERROR_IGNORE; }
+ HandleError reportDirError (const std::wstring& msg, size_t retryNumber ) override { setError(msg); return ON_ERROR_CONTINUE; }
+ HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zstring& itemName) override { setError(msg); return ON_ERROR_CONTINUE; }
const std::vector<Zstring>& refFileNames() const { return logFileNames_; }
const Opt<FileError>& getLastError() const { return lastError_; }
@@ -118,7 +118,7 @@ void limitLogfileCount(const AbstractPath& logFolderPath, const std::wstring& jo
{
try
{
- AFS::removeFile(AFS::appendRelPath(logFolderPath, logFileName)); //throw FileError
+ AFS::removeFilePlain(AFS::appendRelPath(logFolderPath, logFileName)); //throw FileError
}
catch (const FileError& e) { if (!lastError) lastError = e; };
diff --git a/FreeFileSync/Source/ui/custom_grid.cpp b/FreeFileSync/Source/ui/custom_grid.cpp
index b47e6de9..d1f0cf77 100644
--- a/FreeFileSync/Source/ui/custom_grid.cpp
+++ b/FreeFileSync/Source/ui/custom_grid.cpp
@@ -707,7 +707,7 @@ private:
visitFSObject(*fsObj, [&](const FolderPair& folder)
{
out.type = IconInfo::FOLDER;
- //todo: if ("is followed symlink") out.drawAsLink = true;
+ out.drawAsLink = folder.isFollowedSymlink<side>();
},
[&](const FilePair& file)
diff --git a/FreeFileSync/Source/ui/folder_selector.cpp b/FreeFileSync/Source/ui/folder_selector.cpp
index 1e14634d..f567de42 100644
--- a/FreeFileSync/Source/ui/folder_selector.cpp
+++ b/FreeFileSync/Source/ui/folder_selector.cpp
@@ -178,21 +178,13 @@ void FolderSelector::onFilesDropped(FileDropEvent& event)
auto fmtShellPath = [](const Zstring& shellItemPath)
{
const AbstractPath itemPath = createAbstractPath(shellItemPath);
- if (!AFS::folderExists(itemPath))
+ try
{
- Zstring parentShellPath = beforeLast(shellItemPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE);
- if (!parentShellPath.empty())
- {
-#ifdef ZEN_WIN
- if (endsWith(parentShellPath, L":")) //volume root
- parentShellPath += FILE_NAME_SEPARATOR;
-#endif
- const AbstractPath parentPath = createAbstractPath(parentShellPath);
- if (AFS::folderExists(parentPath))
- return AFS::getInitPathPhrase(parentPath);
- //else: keep original name unconditionally: usecase: inactive mapped network shares
- }
+ if (AFS::getItemType(itemPath) == AFS::ItemType::FILE) //throw FileError
+ if (Opt<AbstractPath> parentPath = AFS::getParentFolderPath(itemPath))
+ return AFS::getInitPathPhrase(*parentPath);
}
+ catch (FileError&) {} //e.g. good for inactive mapped network shares, not so nice for C:\pagefile.sys
//make sure FFS-specific explicit MTP-syntax is applied!
return AFS::getInitPathPhrase(itemPath);
};
@@ -231,7 +223,14 @@ void FolderSelector::onSelectFolder(wxCommandEvent& event)
{
auto folderExistsTimed = [](const AbstractPath& folderPath)
{
- auto ft = runAsync([folderPath] { return AFS::folderExists(folderPath); });
+ auto ft = runAsync([folderPath]
+ {
+ try
+ {
+ return AFS::getItemType(folderPath) != AFS::ItemType::FILE; //throw FileError
+ }
+ catch (FileError&) { return false; }
+ });
return ft.wait_for(std::chrono::milliseconds(200)) == std::future_status::ready && ft.get(); //potentially slow network access: wait 200ms at most
};
diff --git a/FreeFileSync/Source/ui/gui_generated.cpp b/FreeFileSync/Source/ui/gui_generated.cpp
index 2683f6a4..6db4dbad 100644
--- a/FreeFileSync/Source/ui/gui_generated.cpp
+++ b/FreeFileSync/Source/ui/gui_generated.cpp
@@ -19,7 +19,7 @@
MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
- this->SetSizeHints( wxSize( 640,400 ), wxDefaultSize );
+ this->SetSizeHints( wxSize( 640, 400 ), wxDefaultSize );
m_menubar1 = new wxMenuBar( 0 );
m_menuFile = new wxMenu();
@@ -34,16 +34,16 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_menuItemSave = new wxMenuItem( m_menuFile, wxID_SAVE, wxString( _("&Save") ) + wxT('\t') + wxT("Ctrl+S"), wxEmptyString, wxITEM_NORMAL );
m_menuFile->Append( m_menuItemSave );
- m_menuItemSaveAs = new wxMenuItem( m_menuFile, wxID_SAVEAS, wxString( _("Save &as...") ) , wxEmptyString, wxITEM_NORMAL );
+ m_menuItemSaveAs = new wxMenuItem( m_menuFile, wxID_SAVEAS, wxString( _("Save &as...") ), wxEmptyString, wxITEM_NORMAL );
m_menuFile->Append( m_menuItemSaveAs );
- m_menuItemSaveAsBatch = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("Save as &batch job...") ) , wxEmptyString, wxITEM_NORMAL );
+ m_menuItemSaveAsBatch = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("Save as &batch job...") ), wxEmptyString, wxITEM_NORMAL );
m_menuFile->Append( m_menuItemSaveAsBatch );
m_menuFile->AppendSeparator();
wxMenuItem* m_menuItem4;
- m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ) , wxEmptyString, wxITEM_NORMAL );
+ m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ), wxEmptyString, wxITEM_NORMAL );
m_menuFile->Append( m_menuItem4 );
m_menubar1->Append( m_menuFile, _("&File") );
@@ -84,11 +84,11 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_menuTools->Append( m_menuItemFind );
wxMenuItem* m_menuItem51;
- m_menuItem51 = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("&Reset layout") ) , wxEmptyString, wxITEM_NORMAL );
+ m_menuItem51 = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("&Reset layout") ), wxEmptyString, wxITEM_NORMAL );
m_menuTools->Append( m_menuItem51 );
wxMenuItem* m_menuItem5;
- m_menuItem5 = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("&Export file list...") ) , wxEmptyString, wxITEM_NORMAL );
+ m_menuItem5 = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("&Export file list...") ), wxEmptyString, wxITEM_NORMAL );
m_menuTools->Append( m_menuItem5 );
m_menubar1->Append( m_menuTools, _("&Tools") );
@@ -99,10 +99,10 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_menuHelp->AppendSeparator();
- m_menuItemCheckVersionNow = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("&Check for updates now") ) , wxEmptyString, wxITEM_NORMAL );
+ m_menuItemCheckVersionNow = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("&Check for updates now") ), wxEmptyString, wxITEM_NORMAL );
m_menuHelp->Append( m_menuItemCheckVersionNow );
- m_menuItemCheckVersionAuto = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("Check &automatically once a week") ) , wxEmptyString, wxITEM_CHECK );
+ m_menuItemCheckVersionAuto = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("Check &automatically once a week") ), wxEmptyString, wxITEM_CHECK );
m_menuHelp->Append( m_menuItemCheckVersionAuto );
m_menuItemCheckVersionAuto->Check( true );
@@ -126,14 +126,14 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizerTopButtons->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 );
- m_buttonCancel = new zen::BitmapTextButton( m_panelTopButtons, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new zen::BitmapTextButton( m_panelTopButtons, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonCancel->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
m_buttonCancel->Enable( false );
m_buttonCancel->Hide();
bSizerTopButtons->Add( m_buttonCancel, 0, wxEXPAND, 5 );
- m_buttonCompare = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Compare"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCompare = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Compare"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonCompare->SetDefault();
m_buttonCompare->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
m_buttonCompare->SetToolTip( _("dummy") );
@@ -146,12 +146,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer198;
bSizer198 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonCmpConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW );
+ m_bpButtonCmpConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
m_bpButtonCmpConfig->SetToolTip( _("dummy") );
bSizer198->Add( m_bpButtonCmpConfig, 1, wxEXPAND, 5 );
- m_bpButtonCmpContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 17,-1 ), wxBU_AUTODRAW );
+ m_bpButtonCmpContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 17, -1 ), wxBU_AUTODRAW );
m_bpButtonCmpContext->SetToolTip( _("dummy") );
bSizer198->Add( m_bpButtonCmpContext, 0, wxEXPAND, 5 );
@@ -168,10 +168,10 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer199;
bSizer199 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonFilter = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 60,-1 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE );
+ m_bpButtonFilter = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 60, -1 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE );
bSizer199->Add( m_bpButtonFilter, 1, wxEXPAND, 5 );
- m_bpButtonFilterContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 17,-1 ), wxBU_AUTODRAW );
+ m_bpButtonFilterContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 17, -1 ), wxBU_AUTODRAW );
m_bpButtonFilterContext->SetToolTip( _("dummy") );
bSizer199->Add( m_bpButtonFilterContext, 0, wxEXPAND, 5 );
@@ -188,12 +188,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer200;
bSizer200 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonSyncConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW );
+ m_bpButtonSyncConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
m_bpButtonSyncConfig->SetToolTip( _("dummy") );
bSizer200->Add( m_bpButtonSyncConfig, 1, wxEXPAND, 5 );
- m_bpButtonSyncContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 17,-1 ), wxBU_AUTODRAW );
+ m_bpButtonSyncContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 17, -1 ), wxBU_AUTODRAW );
m_bpButtonSyncContext->SetToolTip( _("dummy") );
bSizer200->Add( m_bpButtonSyncContext, 0, wxEXPAND, 5 );
@@ -204,7 +204,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizerTopButtons->Add( 4, 0, 0, 0, 5 );
- m_buttonSync = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Synchronize"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonSync = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Synchronize"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
m_buttonSync->SetToolTip( _("dummy") );
@@ -230,7 +230,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer91 = new wxBoxSizer( wxHORIZONTAL );
m_panelTopLeft = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
- m_panelTopLeft->SetMinSize( wxSize( 1,-1 ) );
+ m_panelTopLeft->SetMinSize( wxSize( 1, -1 ) );
wxFlexGridSizer* fgSizer8;
fgSizer8 = new wxFlexGridSizer( 0, 2, 0, 0 );
@@ -248,12 +248,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer159;
bSizer159 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonAddPair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW );
+ m_bpButtonAddPair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25, 25 ), wxBU_AUTODRAW );
m_bpButtonAddPair->SetToolTip( _("Add folder pair") );
bSizer159->Add( m_bpButtonAddPair, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonRemovePair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW );
+ m_bpButtonRemovePair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25, 25 ), wxBU_AUTODRAW );
m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") );
bSizer159->Add( m_bpButtonRemovePair, 0, wxALIGN_CENTER_VERTICAL, 5 );
@@ -272,7 +272,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer182->Add( m_buttonSelectFolderLeft, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, -1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltFolderLeft->SetToolTip( _("Select SFTP folder") );
bSizer182->Add( m_bpButtonSelectAltFolderLeft, 0, wxEXPAND, 5 );
@@ -293,7 +293,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer1771->Add( 0, 0, 1, wxEXPAND, 5 );
- m_bpButtonSwapSides = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW );
+ m_bpButtonSwapSides = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
m_bpButtonSwapSides->SetToolTip( _("Swap sides") );
bSizer1771->Add( m_bpButtonSwapSides, 0, wxEXPAND, 5 );
@@ -301,13 +301,13 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer160;
bSizer160 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonAltCompCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,25 ), wxBU_AUTODRAW );
+ m_bpButtonAltCompCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, 25 ), wxBU_AUTODRAW );
bSizer160->Add( m_bpButtonAltCompCfg, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonLocalFilter = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,25 ), wxBU_AUTODRAW );
+ m_bpButtonLocalFilter = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, 25 ), wxBU_AUTODRAW );
bSizer160->Add( m_bpButtonLocalFilter, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonAltSyncCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,25 ), wxBU_AUTODRAW );
+ m_bpButtonAltSyncCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, 25 ), wxBU_AUTODRAW );
bSizer160->Add( m_bpButtonAltSyncCfg, 0, wxALIGN_CENTER_VERTICAL, 5 );
@@ -323,7 +323,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer91->Add( m_panelTopCenter, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 );
m_panelTopRight = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
- m_panelTopRight->SetMinSize( wxSize( 1,-1 ) );
+ m_panelTopRight->SetMinSize( wxSize( 1, -1 ) );
wxBoxSizer* bSizer183;
bSizer183 = new wxBoxSizer( wxVERTICAL );
@@ -343,7 +343,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer179->Add( m_buttonSelectFolderRight, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, -1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltFolderRight->SetToolTip( _("Select SFTP folder") );
bSizer179->Add( m_bpButtonSelectAltFolderRight, 0, wxEXPAND, 5 );
@@ -360,9 +360,9 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer1601->Add( bSizer91, 0, wxEXPAND, 5 );
- m_scrolledWindowFolderPairs = new wxScrolledWindow( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxHSCROLL|wxVSCROLL );
+ m_scrolledWindowFolderPairs = new wxScrolledWindow( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxHSCROLL|wxVSCROLL );
m_scrolledWindowFolderPairs->SetScrollRate( 10, 10 );
- m_scrolledWindowFolderPairs->SetMinSize( wxSize( -1,0 ) );
+ m_scrolledWindowFolderPairs->SetMinSize( wxSize( -1, 0 ) );
bSizerAddFolderPairs = new wxBoxSizer( wxVERTICAL );
@@ -412,7 +412,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer451;
bSizer451 = new wxBoxSizer( wxHORIZONTAL );
- bSizer451->SetMinSize( wxSize( -1,22 ) );
+ bSizer451->SetMinSize( wxSize( -1, 22 ) );
bSizerFileStatus = new wxBoxSizer( wxHORIZONTAL );
bSizerStatusLeft = new wxBoxSizer( wxHORIZONTAL );
@@ -570,7 +570,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer1713;
bSizer1713 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonHideSearch = new wxBitmapButton( m_panelSearch, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW );
+ m_bpButtonHideSearch = new wxBitmapButton( m_panelSearch, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25, 25 ), wxBU_AUTODRAW );
m_bpButtonHideSearch->SetToolTip( _("Close search bar") );
bSizer1713->Add( m_bpButtonHideSearch, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
@@ -579,7 +579,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_staticText101->Wrap( -1 );
bSizer1713->Add( m_staticText101, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_textCtrlSearchTxt = new wxTextCtrl( m_panelSearch, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 220,-1 ), wxTE_PROCESS_ENTER|wxWANTS_CHARS );
+ m_textCtrlSearchTxt = new wxTextCtrl( m_panelSearch, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 220, -1 ), wxTE_PROCESS_ENTER|wxWANTS_CHARS );
m_textCtrlSearchTxt->SetMaxLength( 0 );
bSizer1713->Add( m_textCtrlSearchTxt, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
@@ -601,7 +601,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer17611;
bSizer17611 = new wxBoxSizer( wxVERTICAL );
- m_bpButtonNew = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonNew = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
m_bpButtonNew->SetToolTip( _("dummy") );
bSizer17611->Add( m_bpButtonNew, 0, wxEXPAND, 5 );
@@ -616,7 +616,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer1761;
bSizer1761 = new wxBoxSizer( wxVERTICAL );
- m_bpButtonOpen = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonOpen = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
m_bpButtonOpen->SetToolTip( _("dummy") );
bSizer1761->Add( m_bpButtonOpen, 0, wxEXPAND, 5 );
@@ -631,7 +631,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer175;
bSizer175 = new wxBoxSizer( wxVERTICAL );
- m_bpButtonSave = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonSave = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
m_bpButtonSave->SetToolTip( _("dummy") );
bSizer175->Add( m_bpButtonSave, 0, wxEXPAND, 5 );
@@ -649,12 +649,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer1772;
bSizer1772 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonSaveAs = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonSaveAs = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
m_bpButtonSaveAs->SetToolTip( _("dummy") );
bSizer1772->Add( m_bpButtonSaveAs, 1, 0, 5 );
- m_bpButtonSaveAsBatch = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonSaveAsBatch = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
m_bpButtonSaveAsBatch->SetToolTip( _("dummy") );
bSizer1772->Add( m_bpButtonSaveAsBatch, 1, 0, 5 );
@@ -673,7 +673,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizerConfig->Add( bSizer151, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
m_listBoxHistory = new wxListBox( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_EXTENDED|wxLB_NEEDED_SB );
- m_listBoxHistory->SetMinSize( wxSize( -1,40 ) );
+ m_listBoxHistory->SetMinSize( wxSize( -1, 40 ) );
bSizerConfig->Add( m_listBoxHistory, 1, wxEXPAND, 5 );
@@ -690,10 +690,10 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_staticTextViewType->Wrap( -1 );
bSizerViewFilter->Add( m_staticTextViewType, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonViewTypeSyncAction = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 82,42 ), wxBU_AUTODRAW );
+ m_bpButtonViewTypeSyncAction = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 82, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonViewTypeSyncAction, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxRIGHT, 5 );
- m_bpButtonShowExcluded = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowExcluded = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowExcluded, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -703,46 +703,46 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_staticTextSelectView->Wrap( -1 );
bSizerViewFilter->Add( m_staticTextSelectView, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowDeleteLeft = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowDeleteLeft = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowDeleteLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowUpdateLeft = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowUpdateLeft = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowCreateLeft = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowCreateLeft = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowLeftOnly = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowLeftOnly = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowLeftOnly, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowLeftNewer = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowLeftNewer = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowLeftNewer, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowEqual = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowEqual = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowEqual, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowDoNothing = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowDoNothing = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowDoNothing, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowDifferent = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowDifferent = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowDifferent, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowRightNewer = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowRightNewer = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowRightNewer, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowRightOnly = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowRightOnly = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowRightOnly, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowCreateRight = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowCreateRight = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowUpdateRight = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowUpdateRight = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowDeleteRight = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowDeleteRight = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowDeleteRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowConflict = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonShowConflict = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42, 42 ), wxBU_AUTODRAW );
bSizerViewFilter->Add( m_bpButtonShowConflict, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -1117,7 +1117,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_bitmapByTimeSize = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer16->Add( m_bitmapByTimeSize, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_toggleBtnByTimeSize = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File time and size"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_toggleBtnByTimeSize = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File time and size"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_toggleBtnByTimeSize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
fgSizer16->Add( m_toggleBtnByTimeSize, 0, wxEXPAND, 5 );
@@ -1125,7 +1125,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_bitmapByContent = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer16->Add( m_bitmapByContent, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_toggleBtnByContent = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File content"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_toggleBtnByContent = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File content"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_toggleBtnByContent->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
fgSizer16->Add( m_toggleBtnByContent, 0, wxEXPAND, 5 );
@@ -1133,7 +1133,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_bitmapBySize = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer16->Add( m_bitmapBySize, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_toggleBtnBySize = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File size"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_toggleBtnBySize = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File size"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_toggleBtnBySize->SetValue( true );
m_toggleBtnBySize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
@@ -1281,7 +1281,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
wxBoxSizer* bSizer1661;
bSizer1661 = new wxBoxSizer( wxHORIZONTAL );
- m_bitmapInclude = new wxStaticBitmap( m_panelFilterSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 );
+ m_bitmapInclude = new wxStaticBitmap( m_panelFilterSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30, 30 ), 0 );
bSizer1661->Add( m_bitmapInclude, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
wxBoxSizer* bSizer1731;
@@ -1291,8 +1291,8 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticText78->Wrap( -1 );
bSizer1731->Add( m_staticText78, 0, 0, 5 );
- m_textCtrlInclude = new wxTextCtrl( m_panelFilterSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE );
- m_textCtrlInclude->SetMinSize( wxSize( 280,-1 ) );
+ m_textCtrlInclude = new wxTextCtrl( m_panelFilterSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_MULTILINE );
+ m_textCtrlInclude->SetMinSize( wxSize( 280, -1 ) );
bSizer1731->Add( m_textCtrlInclude, 1, wxEXPAND|wxTOP, 5 );
@@ -1311,7 +1311,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
wxBoxSizer* bSizer1651;
bSizer1651 = new wxBoxSizer( wxHORIZONTAL );
- m_bitmapExclude = new wxStaticBitmap( m_panelFilterSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 );
+ m_bitmapExclude = new wxStaticBitmap( m_panelFilterSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30, 30 ), 0 );
bSizer1651->Add( m_bitmapExclude, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
wxBoxSizer* bSizer1742;
@@ -1333,7 +1333,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer1742->Add( bSizer189, 0, wxEXPAND, 5 );
- m_textCtrlExclude = new wxTextCtrl( m_panelFilterSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE );
+ m_textCtrlExclude = new wxTextCtrl( m_panelFilterSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_MULTILINE );
bSizer1742->Add( m_textCtrlExclude, 1, wxEXPAND|wxTOP, 5 );
@@ -1354,7 +1354,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
wxBoxSizer* bSizer167;
bSizer167 = new wxBoxSizer( wxHORIZONTAL );
- m_bitmapFilterDate = new wxStaticBitmap( m_panelFilterSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 34,34 ), 0 );
+ m_bitmapFilterDate = new wxStaticBitmap( m_panelFilterSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 34, 34 ), 0 );
bSizer167->Add( m_bitmapFilterDate, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
wxBoxSizer* bSizer165;
@@ -1384,7 +1384,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
wxBoxSizer* bSizer168;
bSizer168 = new wxBoxSizer( wxHORIZONTAL );
- m_bitmapFilterSize = new wxStaticBitmap( m_panelFilterSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32,32 ), 0 );
+ m_bitmapFilterSize = new wxStaticBitmap( m_panelFilterSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32, 32 ), 0 );
bSizer168->Add( m_bitmapFilterSize, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
wxBoxSizer* bSizer158;
@@ -1451,7 +1451,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
wxBoxSizer* bSizer280;
bSizer280 = new wxBoxSizer( wxHORIZONTAL );
- m_staticText44 = new wxStaticText( m_panelFilterSettingsHolder, wxID_ANY, _("Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair."), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_staticText44 = new wxStaticText( m_panelFilterSettingsHolder, wxID_ANY, _("Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair."), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_staticText44->Wrap( 590 );
bSizer280->Add( m_staticText44, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 );
@@ -1461,7 +1461,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticline46 = new wxStaticLine( m_panelFilterSettingsHolder, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
bSizer280->Add( m_staticline46, 0, wxEXPAND, 5 );
- m_buttonClear = new wxButton( m_panelFilterSettingsHolder, wxID_ANY, _("C&lear"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonClear = new wxButton( m_panelFilterSettingsHolder, wxID_ANY, _("C&lear"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizer280->Add( m_buttonClear, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 );
@@ -1512,22 +1512,22 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
wxBoxSizer* bSizer236;
bSizer236 = new wxBoxSizer( wxVERTICAL );
- m_toggleBtnTwoWay = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_toggleBtnTwoWay = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, 30 ), 0 );
m_toggleBtnTwoWay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizer236->Add( m_toggleBtnTwoWay, 0, wxEXPAND|wxBOTTOM, 5 );
- m_toggleBtnMirror = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_toggleBtnMirror = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, 30 ), 0 );
m_toggleBtnMirror->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizer236->Add( m_toggleBtnMirror, 0, wxEXPAND|wxBOTTOM, 5 );
- m_toggleBtnUpdate = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_toggleBtnUpdate = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, 30 ), 0 );
m_toggleBtnUpdate->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizer236->Add( m_toggleBtnUpdate, 0, wxEXPAND|wxBOTTOM, 5 );
- m_toggleBtnCustom = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_toggleBtnCustom = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, 30 ), 0 );
m_toggleBtnCustom->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizer236->Add( m_toggleBtnCustom, 0, wxEXPAND, 5 );
@@ -1579,58 +1579,58 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
fgSizerSyncDirections->SetFlexibleDirection( wxBOTH );
fgSizerSyncDirections->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
- m_bitmapLeftOnly = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 );
+ m_bitmapLeftOnly = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45, 45 ), 0 );
m_bitmapLeftOnly->SetToolTip( _("Item exists on left side only") );
fgSizerSyncDirections->Add( m_bitmapLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bitmapLeftNewer = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 );
+ m_bitmapLeftNewer = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45, 45 ), 0 );
m_bitmapLeftNewer->SetToolTip( _("Left side is newer") );
fgSizerSyncDirections->Add( m_bitmapLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bitmapDifferent = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 );
+ m_bitmapDifferent = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45, 45 ), 0 );
m_bitmapDifferent->SetToolTip( _("Items have different content") );
fgSizerSyncDirections->Add( m_bitmapDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bitmapConflict = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 );
+ m_bitmapConflict = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45, 45 ), 0 );
m_bitmapConflict->SetToolTip( _("Conflict/item cannot be categorized") );
fgSizerSyncDirections->Add( m_bitmapConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bitmapRightNewer = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 );
+ m_bitmapRightNewer = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45, 45 ), 0 );
m_bitmapRightNewer->SetToolTip( _("Right side is newer") );
fgSizerSyncDirections->Add( m_bitmapRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bitmapRightOnly = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 );
+ m_bitmapRightOnly = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45, 45 ), 0 );
m_bitmapRightOnly->SetToolTip( _("Item exists on right side only") );
fgSizerSyncDirections->Add( m_bitmapRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonLeftOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW );
+ m_bpButtonLeftOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46, 46 ), wxBU_AUTODRAW );
fgSizerSyncDirections->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonLeftNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW );
+ m_bpButtonLeftNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46, 46 ), wxBU_AUTODRAW );
fgSizerSyncDirections->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonDifferent = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW );
+ m_bpButtonDifferent = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46, 46 ), wxBU_AUTODRAW );
fgSizerSyncDirections->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonConflict = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW );
+ m_bpButtonConflict = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46, 46 ), wxBU_AUTODRAW );
fgSizerSyncDirections->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonRightNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW );
+ m_bpButtonRightNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46, 46 ), wxBU_AUTODRAW );
fgSizerSyncDirections->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonRightOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW );
+ m_bpButtonRightOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46, 46 ), wxBU_AUTODRAW );
fgSizerSyncDirections->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
bSizerSyncConfig->Add( fgSizerSyncDirections, 0, 0, 5 );
- m_bitmapDatabase = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_bitmapDatabase = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_bitmapDatabase->SetToolTip( _("Detect synchronization directions with the help of database files") );
bSizerSyncConfig->Add( m_bitmapDatabase, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxALIGN_CENTER_VERTICAL, 10 );
@@ -1698,7 +1698,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticText87->Wrap( -1 );
bSizer202->Add( m_staticText87, 0, wxALL, 5 );
- m_bpButtonDeletionType = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW );
+ m_bpButtonDeletionType = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46, 46 ), wxBU_AUTODRAW );
bSizer202->Add( m_bpButtonDeletionType, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
@@ -1743,7 +1743,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer156->Add( m_buttonSelectVersioningFolder, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonSelectAltFolder = new wxBitmapButton( m_panelVersioning, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltFolder = new wxBitmapButton( m_panelVersioning, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, -1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltFolder->SetToolTip( _("Select SFTP folder") );
bSizer156->Add( m_bpButtonSelectAltFolder, 0, wxEXPAND, 5 );
@@ -1868,13 +1868,13 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -1948,17 +1948,17 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
bSizer74 = new wxBoxSizer( wxHORIZONTAL );
m_panelLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
- m_panelLeft->SetMinSize( wxSize( 1,-1 ) );
+ m_panelLeft->SetMinSize( wxSize( 1, -1 ) );
wxBoxSizer* bSizer134;
bSizer134 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonFolderPairOptions = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW );
+ m_bpButtonFolderPairOptions = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25, 25 ), wxBU_AUTODRAW );
m_bpButtonFolderPairOptions->SetToolTip( _("Arrange folder pair") );
bSizer134->Add( m_bpButtonFolderPairOptions, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonRemovePair = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW );
+ m_bpButtonRemovePair = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25, 25 ), wxBU_AUTODRAW );
m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") );
bSizer134->Add( m_bpButtonRemovePair, 0, wxALIGN_CENTER_VERTICAL, 5 );
@@ -1971,7 +1971,7 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
bSizer134->Add( m_buttonSelectFolderLeft, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, -1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltFolderLeft->SetToolTip( _("Select SFTP folder") );
bSizer134->Add( m_bpButtonSelectAltFolderLeft, 0, wxEXPAND, 5 );
@@ -1989,13 +1989,13 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
bSizer95->Add( 0, 0, 1, wxEXPAND, 5 );
- m_bpButtonAltCompCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,25 ), wxBU_AUTODRAW );
+ m_bpButtonAltCompCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, 25 ), wxBU_AUTODRAW );
bSizer95->Add( m_bpButtonAltCompCfg, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonLocalFilter = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,25 ), wxBU_AUTODRAW );
+ m_bpButtonLocalFilter = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, 25 ), wxBU_AUTODRAW );
bSizer95->Add( m_bpButtonLocalFilter, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonAltSyncCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,25 ), wxBU_AUTODRAW );
+ m_bpButtonAltSyncCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, 25 ), wxBU_AUTODRAW );
bSizer95->Add( m_bpButtonAltSyncCfg, 0, wxALIGN_CENTER_VERTICAL, 5 );
@@ -2008,7 +2008,7 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
bSizer74->Add( m_panel20, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 );
m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
- m_panelRight->SetMinSize( wxSize( 1,-1 ) );
+ m_panelRight->SetMinSize( wxSize( 1, -1 ) );
wxBoxSizer* bSizer135;
bSizer135 = new wxBoxSizer( wxHORIZONTAL );
@@ -2021,7 +2021,7 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
bSizer135->Add( m_buttonSelectFolderRight, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, -1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltFolderRight->SetToolTip( _("Select SFTP folder") );
bSizer135->Add( m_bpButtonSelectAltFolderRight, 0, wxEXPAND, 5 );
@@ -2063,7 +2063,7 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c
bSizer134->Add( bSizer72, 0, 0, 5 );
- m_staticline371 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxLI_HORIZONTAL );
+ m_staticline371 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxLI_HORIZONTAL );
bSizer134->Add( m_staticline371, 0, wxEXPAND, 5 );
m_panel41 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
@@ -2085,14 +2085,14 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c
wxBoxSizer* bSizer183;
bSizer183 = new wxBoxSizer( wxHORIZONTAL );
- m_textCtrlServer = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 260,-1 ), 0 );
+ m_textCtrlServer = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 260, -1 ), 0 );
bSizer183->Add( m_textCtrlServer, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
m_staticText1233 = new wxStaticText( m_panel41, wxID_ANY, _("Port:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText1233->Wrap( -1 );
bSizer183->Add( m_staticText1233, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
- m_textCtrlPort = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60,-1 ), 0 );
+ m_textCtrlPort = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60, -1 ), 0 );
bSizer183->Add( m_textCtrlPort, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -2294,7 +2294,7 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c
m_staticText12341->Wrap( -1 );
fgSizer1611->Add( m_staticText12341, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 );
- m_spinCtrlConnectionCount = new wxSpinCtrl( m_panel411, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 70,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 );
+ m_spinCtrlConnectionCount = new wxSpinCtrl( m_panel411, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 70, -1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 );
fgSizer1611->Add( m_spinCtrlConnectionCount, 0, wxALL, 5 );
m_staticText138111 = new wxStaticText( m_panel411, wxID_ANY, _("Suggested range: [1 - 10]"), wxDefaultPosition, wxDefaultSize, 0 );
@@ -2307,7 +2307,7 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c
m_staticText1231111->Wrap( -1 );
fgSizer1611->Add( m_staticText1231111, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 );
- m_spinCtrlChannelCount = new wxSpinCtrl( m_panel411, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 70,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 );
+ m_spinCtrlChannelCount = new wxSpinCtrl( m_panel411, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 70, -1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 );
fgSizer1611->Add( m_spinCtrlChannelCount, 0, wxALL, 5 );
m_button42 = new wxButton( m_panel411, wxID_ANY, _("Detect server limit"), wxDefaultPosition, wxDefaultSize, 0 );
@@ -2345,13 +2345,13 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizerStdButtons->Add( m_buttonOkay, 0, wxALL, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -2402,7 +2402,7 @@ SftpFolderPickerGenerated::SftpFolderPickerGenerated( wxWindow* parent, wxWindow
bSizer134->Add( bSizer72, 0, 0, 5 );
- m_staticline371 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxLI_HORIZONTAL );
+ m_staticline371 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxLI_HORIZONTAL );
bSizer134->Add( m_staticline371, 0, wxEXPAND, 5 );
m_panel41 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
@@ -2411,7 +2411,7 @@ SftpFolderPickerGenerated::SftpFolderPickerGenerated( wxWindow* parent, wxWindow
wxBoxSizer* bSizer185;
bSizer185 = new wxBoxSizer( wxVERTICAL );
- m_treeCtrlFileSystem = new wxTreeCtrl( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( 350,400 ), wxTR_FULL_ROW_HIGHLIGHT|wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT|wxTR_NO_LINES|wxNO_BORDER );
+ m_treeCtrlFileSystem = new wxTreeCtrl( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( 350, 400 ), wxTR_FULL_ROW_HIGHLIGHT|wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT|wxTR_NO_LINES|wxNO_BORDER );
bSizer185->Add( m_treeCtrlFileSystem, 1, wxEXPAND, 5 );
@@ -2425,13 +2425,13 @@ SftpFolderPickerGenerated::SftpFolderPickerGenerated( wxWindow* parent, wxWindow
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonOkay = new wxButton( this, wxID_OK, _("Select Folder"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonOkay = new wxButton( this, wxID_OK, _("Select Folder"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizerStdButtons->Add( m_buttonOkay, 0, wxALL, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -2646,13 +2646,13 @@ SyncConfirmationDlgGenerated::SyncConfirmationDlgGenerated( wxWindow* parent, wx
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonStartSync = new wxButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonStartSync = new wxButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonStartSync->SetDefault();
m_buttonStartSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizerStdButtons->Add( m_buttonStartSync, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
@@ -2793,7 +2793,7 @@ CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWi
bSizer201->Fit( m_panelProgressLabel );
bSizer199->Add( m_panelProgressLabel, 0, 0, 5 );
- m_panelGraphProgress = new zen::Graph2D( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_panelGraphProgress = new zen::Graph2D( this, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_panelGraphProgress->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
bSizer199->Add( m_panelGraphProgress, 1, wxEXPAND, 5 );
@@ -2826,7 +2826,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizer42->Add( 0, 0, 1, wxEXPAND, 5 );
- m_bitmapStatus = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32,32 ), 0 );
+ m_bitmapStatus = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32, 32 ), 0 );
bSizer42->Add( m_bitmapStatus, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 );
m_staticTextPhase = new wxStaticText( this, wxID_ANY, _("Synchronizing..."), wxDefaultPosition, wxDefaultSize, 0 );
@@ -2835,13 +2835,13 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizer42->Add( m_staticTextPhase, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 );
- m_animCtrlSyncing = new wxAnimationCtrl( this, wxID_ANY, wxNullAnimation, wxDefaultPosition, wxSize( 32,32 ), wxAC_DEFAULT_STYLE );
+ m_animCtrlSyncing = new wxAnimationCtrl( this, wxID_ANY, wxNullAnimation, wxDefaultPosition, wxSize( 32, 32 ), wxAC_DEFAULT_STYLE );
bSizer42->Add( m_animCtrlSyncing, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 );
bSizer42->Add( 0, 0, 1, wxEXPAND, 5 );
- m_bpButtonMinimizeToTray = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32,32 ), wxBU_AUTODRAW );
+ m_bpButtonMinimizeToTray = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32, 32 ), wxBU_AUTODRAW );
m_bpButtonMinimizeToTray->SetToolTip( _("Minimize to notification area") );
bSizer42->Add( m_bpButtonMinimizeToTray, 0, wxALIGN_CENTER_VERTICAL, 5 );
@@ -2896,7 +2896,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
wxBoxSizer* bSizer169;
bSizer169 = new wxBoxSizer( wxHORIZONTAL );
- m_staticTextItemsProcessed = new wxStaticText( m_panelItemsProcessed, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_staticTextItemsProcessed = new wxStaticText( m_panelItemsProcessed, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_staticTextItemsProcessed->Wrap( -1 );
m_staticTextItemsProcessed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
@@ -2935,7 +2935,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
wxBoxSizer* bSizer170;
bSizer170 = new wxBoxSizer( wxHORIZONTAL );
- m_staticTextItemsRemaining = new wxStaticText( m_panelItemsRemaining, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_staticTextItemsRemaining = new wxStaticText( m_panelItemsRemaining, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_staticTextItemsRemaining->Wrap( -1 );
m_staticTextItemsRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
@@ -3039,7 +3039,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizer161->Add( bSizer175, 0, 0, 5 );
- m_panelGraphBytes = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_panelGraphBytes = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_panelGraphBytes->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
bSizer161->Add( m_panelGraphBytes, 1, wxEXPAND, 15 );
@@ -3058,7 +3058,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizer161->Add( bSizer174, 0, 0, 5 );
- m_panelGraphItems = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_panelGraphItems = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_panelGraphItems->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
bSizer161->Add( m_panelGraphItems, 1, wxEXPAND, 15 );
@@ -3111,16 +3111,16 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizerStdButtons->Add( bSizer160, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
- m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonClose->SetDefault();
m_buttonClose->Enable( false );
bSizerStdButtons->Add( m_buttonClose, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
- m_buttonPause = new wxButton( this, wxID_ANY, _("&Pause"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonPause = new wxButton( this, wxID_ANY, _("&Pause"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonPause, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
- m_buttonStop = new wxButton( this, wxID_CANCEL, _("Stop"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonStop = new wxButton( this, wxID_CANCEL, _("Stop"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonStop, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -3149,13 +3149,13 @@ LogPanelGenerated::LogPanelGenerated( wxWindow* parent, wxWindowID id, const wxP
wxBoxSizer* bSizer154;
bSizer154 = new wxBoxSizer( wxVERTICAL );
- m_bpButtonErrors = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49,49 ), wxBU_AUTODRAW );
+ m_bpButtonErrors = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49, 49 ), wxBU_AUTODRAW );
bSizer154->Add( m_bpButtonErrors, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonWarnings = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49,49 ), wxBU_AUTODRAW );
+ m_bpButtonWarnings = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49, 49 ), wxBU_AUTODRAW );
bSizer154->Add( m_bpButtonWarnings, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonInfo = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49,49 ), wxBU_AUTODRAW );
+ m_bpButtonInfo = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49, 49 ), wxBU_AUTODRAW );
bSizer154->Add( m_bpButtonInfo, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -3188,7 +3188,7 @@ LogPanelGenerated::~LogPanelGenerated()
BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
- this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
+ this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize );
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
wxBoxSizer* bSizer54;
@@ -3197,7 +3197,7 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
wxBoxSizer* bSizer72;
bSizer72 = new wxBoxSizer( wxHORIZONTAL );
- m_bitmapBatchJob = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_bitmapBatchJob = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizer72->Add( m_bitmapBatchJob, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 );
m_staticTextDescr = new wxStaticText( this, wxID_ANY, _("Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x"), wxDefaultPosition, wxDefaultSize, 0 );
@@ -3290,7 +3290,7 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer1721->Add( m_buttonSelectLogFolder, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonSelectAltLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, -1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltLogFolder->SetToolTip( _("Select SFTP folder") );
bSizer1721->Add( m_bpButtonSelectAltLogFolder, 0, wxEXPAND, 5 );
@@ -3300,7 +3300,7 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer1721->Add( m_checkBoxLogfilesLimit, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
- m_spinCtrlLogfileLimit = new wxSpinCtrl( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 70,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 );
+ m_spinCtrlLogfileLimit = new wxSpinCtrl( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 70, -1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 );
m_spinCtrlLogfileLimit->SetToolTip( _("Limit maximum number of log files") );
bSizer1721->Add( m_spinCtrlLogfileLimit, 0, wxALIGN_CENTER_VERTICAL, 5 );
@@ -3328,13 +3328,13 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonSaveAs = new wxButton( this, wxID_SAVE, _("Save &as..."), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonSaveAs = new wxButton( this, wxID_SAVE, _("Save &as..."), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonSaveAs->SetDefault();
m_buttonSaveAs->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizerStdButtons->Add( m_buttonSaveAs, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -3365,7 +3365,7 @@ BatchDlgGenerated::~BatchDlgGenerated()
DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
- this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
+ this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize );
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
wxBoxSizer* bSizer24;
@@ -3399,7 +3399,7 @@ DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticline42 = new wxStaticLine( m_panel31, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 );
- m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 500,200 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
+ m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 500, 200 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND, 5 );
@@ -3416,13 +3416,13 @@ DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_checkBoxUseRecycler = new wxCheckBox( this, wxID_ANY, _("&Recycle bin"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerStdButtons->Add( m_checkBoxUseRecycler, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
- m_buttonOK = new wxButton( this, wxID_OK, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonOK = new wxButton( this, wxID_OK, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonOK->SetDefault();
m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizerStdButtons->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -3448,7 +3448,7 @@ DeleteDlgGenerated::~DeleteDlgGenerated()
CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
- this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
+ this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize );
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
wxBoxSizer* bSizer24;
@@ -3482,7 +3482,7 @@ CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticline42 = new wxStaticLine( m_panel31, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 );
- m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 500,200 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
+ m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 500, 200 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND, 5 );
@@ -3502,7 +3502,7 @@ CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer182->Add( m_buttonSelectTargetFolder, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonSelectAltTargetFolder = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltTargetFolder = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26, -1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltTargetFolder->SetToolTip( _("Select SFTP folder") );
bSizer182->Add( m_bpButtonSelectAltTargetFolder, 0, wxEXPAND, 5 );
@@ -3529,13 +3529,13 @@ CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizerStdButtons->Add( bSizer189, 1, wxALIGN_CENTER_VERTICAL, 5 );
- m_buttonOK = new wxButton( this, wxID_OK, _("Copy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonOK = new wxButton( this, wxID_OK, _("Copy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonOK->SetDefault();
m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizerStdButtons->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -3562,7 +3562,7 @@ CopyToDlgGenerated::~CopyToDlgGenerated()
OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
- this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
+ this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize );
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
wxBoxSizer* bSizer95;
@@ -3571,10 +3571,10 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer72;
bSizer72 = new wxBoxSizer( wxHORIZONTAL );
- m_bitmapSettings = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_bitmapSettings = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizer72->Add( m_bitmapSettings, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 );
- m_staticText44 = new wxStaticText( this, wxID_ANY, _("The following settings are used for all synchronization jobs."), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_staticText44 = new wxStaticText( this, wxID_ANY, _("The following settings are used for all synchronization jobs."), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_staticText44->Wrap( 500 );
bSizer72->Add( m_staticText44, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 );
@@ -3671,14 +3671,14 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
m_staticText96->Wrap( -1 );
fgSizer6->Add( m_staticText96, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_spinCtrlAutoRetryCount = new wxSpinCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60,-1 ), wxSP_ARROW_KEYS, 0, 2000000000, 4 );
+ m_spinCtrlAutoRetryCount = new wxSpinCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60, -1 ), wxSP_ARROW_KEYS, 0, 2000000000, 4 );
fgSizer6->Add( m_spinCtrlAutoRetryCount, 0, wxALIGN_CENTER_VERTICAL, 5 );
m_staticTextAutoRetryDelay = new wxStaticText( m_panel39, wxID_ANY, _("Delay (in seconds):"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextAutoRetryDelay->Wrap( -1 );
fgSizer6->Add( m_staticTextAutoRetryDelay, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_spinCtrlAutoRetryDelay = new wxSpinCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60,-1 ), wxSP_ARROW_KEYS, 0, 2000000000, 0 );
+ m_spinCtrlAutoRetryDelay = new wxSpinCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60, -1 ), wxSP_ARROW_KEYS, 0, 2000000000, 0 );
fgSizer6->Add( m_spinCtrlAutoRetryDelay, 0, wxALIGN_CENTER_VERTICAL, 5 );
@@ -3733,10 +3733,10 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer193;
bSizer193 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonAddRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW );
+ m_bpButtonAddRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25, 25 ), wxBU_AUTODRAW );
bSizer193->Add( m_bpButtonAddRow, 0, 0, 5 );
- m_bpButtonRemoveRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW );
+ m_bpButtonRemoveRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25, 25 ), wxBU_AUTODRAW );
bSizer193->Add( m_bpButtonRemoveRow, 0, 0, 5 );
@@ -3757,7 +3757,7 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer1881;
bSizer1881 = new wxBoxSizer( wxHORIZONTAL );
- m_buttonResetDialogs = new zen::BitmapTextButton( m_panel39, wxID_ANY, _("Show hidden dialogs again"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonResetDialogs = new zen::BitmapTextButton( m_panel39, wxID_ANY, _("Show hidden dialogs again"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonResetDialogs->SetToolTip( _("Show all permanently hidden dialogs and warning messages again") );
bSizer1881->Add( m_buttonResetDialogs, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 );
@@ -3779,19 +3779,19 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonDefault = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonDefault = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonDefault, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
bSizerStdButtons->Add( 0, 0, 1, 0, 5 );
- m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -3875,13 +3875,13 @@ SelectTimespanDlgGenerated::SelectTimespanDlgGenerated( wxWindow* parent, wxWind
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -3920,7 +3920,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
wxBoxSizer* bSizer162;
bSizer162 = new wxBoxSizer( wxVERTICAL );
- m_bitmapLogo = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_bitmapLogo = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizer162->Add( m_bitmapLogo, 0, 0, 5 );
m_staticline341 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
@@ -4130,7 +4130,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer166->Add( 0, 0, 1, wxEXPAND, 5 );
- m_bitmapHomepage = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_bitmapHomepage = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_bitmapHomepage->SetToolTip( _("Home page") );
bSizer166->Add( m_bitmapHomepage, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
@@ -4145,7 +4145,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer166->Add( 0, 0, 1, wxEXPAND, 5 );
- m_bitmapEmail = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_bitmapEmail = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_bitmapEmail->SetToolTip( _("Email") );
bSizer166->Add( m_bitmapEmail, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
@@ -4179,7 +4179,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
wxBoxSizer* bSizer1671;
bSizer1671 = new wxBoxSizer( wxHORIZONTAL );
- m_bitmapGpl = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_bitmapGpl = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizer1671->Add( m_bitmapGpl, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_hyperlink5 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("http://www.gnu.org/licenses/gpl-3.0"), wxT("http://www.gnu.org/licenses/gpl-3.0"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
@@ -4211,10 +4211,10 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer177->Add( 0, 5, 0, 0, 5 );
- m_scrolledWindowTranslators = new wxScrolledWindow( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxVSCROLL );
+ m_scrolledWindowTranslators = new wxScrolledWindow( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxVSCROLL );
m_scrolledWindowTranslators->SetScrollRate( 10, 10 );
m_scrolledWindowTranslators->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_scrolledWindowTranslators->SetMinSize( wxSize( 220,-1 ) );
+ m_scrolledWindowTranslators->SetMinSize( wxSize( 220, -1 ) );
fgSizerTranslators = new wxFlexGridSizer( 0, 2, 2, 10 );
fgSizerTranslators->SetFlexibleDirection( wxBOTH );
@@ -4243,7 +4243,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonClose->SetDefault();
bSizerStdButtons->Add( m_buttonClose, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -4310,7 +4310,7 @@ DownloadProgressDlgGenerated::DownloadProgressDlgGenerated( wxWindow* parent, wx
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonCancel->SetDefault();
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
@@ -4332,7 +4332,7 @@ DownloadProgressDlgGenerated::~DownloadProgressDlgGenerated()
ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
- this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
+ this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize );
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
wxBoxSizer* bSizer54;
@@ -4347,7 +4347,7 @@ ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id,
wxBoxSizer* bSizer165;
bSizer165 = new wxBoxSizer( wxHORIZONTAL );
- m_bitmapActivation = new wxStaticBitmap( m_panel35, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_bitmapActivation = new wxStaticBitmap( m_panel35, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizer165->Add( m_bitmapActivation, 0, wxALL, 10 );
@@ -4400,7 +4400,7 @@ ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id,
m_staticText136->Wrap( -1 );
bSizer234->Add( m_staticText136, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
- m_buttonActivateOnline = new wxButton( m_panel3511, wxID_ANY, _("Activate online"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonActivateOnline = new wxButton( m_panel3511, wxID_ANY, _("Activate online"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonActivateOnline->SetDefault();
m_buttonActivateOnline->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
@@ -4437,7 +4437,7 @@ ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id,
m_staticText1361->Wrap( -1 );
bSizer236->Add( m_staticText1361, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
- m_buttonCopyUrl = new wxButton( m_panel351, wxID_ANY, _("&Copy to clipboard"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCopyUrl = new wxButton( m_panel351, wxID_ANY, _("&Copy to clipboard"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonCopyUrl->SetDefault();
m_buttonCopyUrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) );
@@ -4446,7 +4446,7 @@ ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id,
bSizer237->Add( bSizer236, 0, wxEXPAND, 5 );
- m_textCtrlManualActivationUrl = new wxTextCtrl( m_panel351, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 220,-1 ), wxTE_MULTILINE|wxTE_READONLY|wxWANTS_CHARS );
+ m_textCtrlManualActivationUrl = new wxTextCtrl( m_panel351, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 220, -1 ), wxTE_MULTILINE|wxTE_READONLY|wxWANTS_CHARS );
m_textCtrlManualActivationUrl->SetMaxLength( 0 );
bSizer237->Add( m_textCtrlManualActivationUrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
@@ -4457,11 +4457,11 @@ ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id,
m_staticText13611->Wrap( -1 );
bSizer235->Add( m_staticText13611, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
- m_textCtrlOfflineActivationKey = new wxTextCtrl( m_panel351, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 220,-1 ), wxTE_PROCESS_ENTER|wxWANTS_CHARS );
+ m_textCtrlOfflineActivationKey = new wxTextCtrl( m_panel351, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 220, -1 ), wxTE_PROCESS_ENTER|wxWANTS_CHARS );
m_textCtrlOfflineActivationKey->SetMaxLength( 0 );
bSizer235->Add( m_textCtrlOfflineActivationKey, 1, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
- m_buttonActivateOffline = new wxButton( m_panel351, wxID_ANY, _("Activate offline"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonActivateOffline = new wxButton( m_panel351, wxID_ANY, _("Activate offline"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_buttonActivateOffline->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
bSizer235->Add( m_buttonActivateOffline, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -4483,7 +4483,7 @@ ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id,
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
diff --git a/FreeFileSync/Source/ui/gui_generated.h b/FreeFileSync/Source/ui/gui_generated.h
index ac691409..eab74a04 100644
--- a/FreeFileSync/Source/ui/gui_generated.h
+++ b/FreeFileSync/Source/ui/gui_generated.h
@@ -252,7 +252,7 @@ public:
wxBoxSizer* bSizerStatistics;
wxBoxSizer* bSizerData;
- MainDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 900,600 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
+ MainDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 900, 600 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
~MainDialogGenerated();
@@ -443,7 +443,7 @@ protected:
public:
wxBitmapButton* m_bpButtonSelectAltFolder;
- ConfigDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
+ ConfigDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
~ConfigDlgGenerated();
};
@@ -552,7 +552,7 @@ protected:
public:
- SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("SSH File Transfer Protocol"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
+ SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("SSH File Transfer Protocol"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
~SftpSetupDlgGenerated();
};
@@ -584,7 +584,7 @@ protected:
public:
- SftpFolderPickerGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("SSH File Transfer Protocol"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
+ SftpFolderPickerGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("SSH File Transfer Protocol"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
~SftpFolderPickerGenerated();
};
@@ -664,7 +664,7 @@ protected:
public:
zen::Graph2D* m_panelGraphProgress;
- CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxRAISED_BORDER );
+ CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxRAISED_BORDER );
~CompareProgressDlgGenerated();
};
@@ -712,7 +712,7 @@ public:
wxButton* m_buttonPause;
wxButton* m_buttonStop;
- SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL );
+ SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxTAB_TRAVERSAL );
~SyncProgressPanelGenerated();
};
@@ -826,7 +826,7 @@ protected:
public:
- DeleteDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Delete Items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
+ DeleteDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Delete Items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
~DeleteDlgGenerated();
};
@@ -864,7 +864,7 @@ public:
FolderHistoryBox* m_targetFolderPath;
wxBitmapButton* m_bpButtonSelectAltTargetFolder;
- CopyToDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Copy items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
+ CopyToDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Copy items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
~CopyToDlgGenerated();
};
diff --git a/FreeFileSync/Source/ui/main_dlg.cpp b/FreeFileSync/Source/ui/main_dlg.cpp
index 4d56a4f7..a8891d82 100644
--- a/FreeFileSync/Source/ui/main_dlg.cpp
+++ b/FreeFileSync/Source/ui/main_dlg.cpp
@@ -323,21 +323,26 @@ void updateTopButton(wxBitmapButton& btn, const wxBitmap& bmp, const wxString& v
//##################################################################################################################################
-xmlAccess::XmlGlobalSettings loadGlobalConfig(const Zstring& globalConfigFile) //blocks on GUI on errors!
+xmlAccess::XmlGlobalSettings loadGlobalConfig(const Zstring& globalConfigFilePath) //blocks on GUI on errors!
{
using namespace xmlAccess;
- XmlGlobalSettings globalCfg;
+ XmlGlobalSettings globalCfg;
try
- {
- std::wstring warningMsg;
- readConfig(globalConfigFile, globalCfg, warningMsg); //throw FileError
+ {
+ std::wstring warningMsg;
+ readConfig(globalConfigFilePath, globalCfg, warningMsg); //throw FileError
- assert(warningMsg.empty()); //ignore parsing errors: should be migration problems only *cross-fingers*
+ assert(warningMsg.empty()); //ignore parsing errors: should be migration problems only *cross-fingers*
}
catch (const FileError& e)
{
- showNotificationDialog(nullptr, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); //no parent window: main dialog not yet created!
+ bool notExisting = false;
+ try { notExisting = !getItemTypeIfExists(globalConfigFilePath); /*throw FileError*/ }
+ catch (FileError&) {} //previous exception is more relevant
+
+ if (!notExisting) //existing or access error
+ showNotificationDialog(nullptr, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); //no parent window: main dialog not yet created!
}
return globalCfg;
}
@@ -350,13 +355,11 @@ Zstring MainDialog::getLastRunConfigPath()
}
-void MainDialog::create(const Zstring& globalConfigFile)
+void MainDialog::create(const Zstring& globalConfigFilePath)
{
using namespace xmlAccess;
- XmlGlobalSettings globalSettings;
- if (fileExists(globalConfigFile)) //else: globalCfg already has default values
- globalSettings = loadGlobalConfig(globalConfigFile);
+ const XmlGlobalSettings globalSettings = loadGlobalConfig(globalConfigFilePath);
std::vector<Zstring> cfgFilePaths;
for (const ConfigFileItem& item : globalSettings.gui.lastUsedConfigFiles)
@@ -364,10 +367,10 @@ void MainDialog::create(const Zstring& globalConfigFile)
//------------------------------------------------------------------------------------------
//check existence of all files in parallel:
- GetFirstResult<FalseType> firstMissingDir;
+ GetFirstResult<FalseType> firstUnavailableFile;
for (const Zstring& filePath : cfgFilePaths)
- firstMissingDir.addJob([filePath] () -> Opt<FalseType>
+ firstUnavailableFile.addJob([filePath]() -> Opt<FalseType>
{
assert(!filePath.empty());
if (filePath.empty() /*ever empty??*/ || !fileExists(filePath))
@@ -376,16 +379,16 @@ void MainDialog::create(const Zstring& globalConfigFile)
});
//potentially slow network access: give all checks 500ms to finish
- const bool allFilesExist = firstMissingDir.timedWait(std::chrono::milliseconds(500)) && //false: time elapsed
- !firstMissingDir.get(); //no missing
- if (!allFilesExist)
+ const bool allFilesAvailable = firstUnavailableFile.timedWait(std::chrono::milliseconds(500)) && //false: time elapsed
+ !firstUnavailableFile.get(); //no missing
+ if (!allFilesAvailable)
cfgFilePaths.clear(); //we do NOT want to show an error due to last config file missing on application start!
//------------------------------------------------------------------------------------------
if (cfgFilePaths.empty())
{
const Zstring lastRunConfigFilePath = getLastRunConfigPath();
- if (zen::fileExists(lastRunConfigFilePath)) //3. try to load auto-save config
+ if (fileExists(lastRunConfigFilePath)) //3. try to load auto-save config
cfgFilePaths.push_back(lastRunConfigFilePath);
}
@@ -417,11 +420,11 @@ void MainDialog::create(const Zstring& globalConfigFile)
//------------------------------------------------------------------------------------------
- create(globalConfigFile, &globalSettings, guiCfg, cfgFilePaths, false);
+ create(globalConfigFilePath, &globalSettings, guiCfg, cfgFilePaths, false);
}
-void MainDialog::create(const Zstring& globalConfigFile,
+void MainDialog::create(const Zstring& globalConfigFilePath,
const xmlAccess::XmlGlobalSettings* globalSettings,
const xmlAccess::XmlGuiConfig& guiCfg,
const std::vector<Zstring>& referenceFiles,
@@ -430,8 +433,8 @@ void MainDialog::create(const Zstring& globalConfigFile,
xmlAccess::XmlGlobalSettings globSett;
if (globalSettings)
globSett = *globalSettings;
- else if (fileExists(globalConfigFile))
- globSett = loadGlobalConfig(globalConfigFile);
+ else
+ globSett = loadGlobalConfig(globalConfigFilePath);
//else: globalCfg already has default values
try
@@ -445,7 +448,7 @@ void MainDialog::create(const Zstring& globalConfigFile,
//continue!
}
- MainDialog* frame = new MainDialog(globalConfigFile, guiCfg, referenceFiles, globSett, startComparison);
+ MainDialog* frame = new MainDialog(globalConfigFilePath, guiCfg, referenceFiles, globSett, startComparison);
frame->Show();
#ifdef ZEN_MAC
ProcessSerialNumber psn = { 0, kCurrentProcess };
@@ -803,12 +806,16 @@ MainDialog::MainDialog(const Zstring& globalConfigFile,
for (const AbstractPath& folderPath : folderPathsToCheck)
firstMissingDir.addJob([folderPath]() -> Opt<FalseType>
{
- if (!AFS::folderExists(folderPath))
- return FalseType();
- return NoValue();
+ try
+ {
+ if (AFS::getItemType(folderPath) != AFS::ItemType::FILE) //throw FileError
+ return NoValue();
+ }
+ catch (FileError&) {}
+ return FalseType();
});
- const bool startComparisonNow = !firstMissingDir.timedWait(std::chrono::milliseconds(500)) || //= no result yet => start comparison anyway!
+ const bool startComparisonNow = !firstMissingDir.timedWait(std::chrono::milliseconds(500)) || //= no result yet => start comparison anyway!
!firstMissingDir.get(); //= all directories exist
if (startComparisonNow)
@@ -2794,7 +2801,7 @@ void MainDialog::removeObsoleteCfgHistoryItems(const std::vector<Zstring>& fileP
std::list<std::future<bool>> fileEx;
for (const Zstring& filePath : filePaths)
- fileEx.push_back(zen::runAsync([=] { return somethingExists(filePath); }));
+ fileEx.push_back(zen::runAsync([=] { return fileExists(filePath); }));
//potentially slow network access => limit maximum wait time!
wait_for_all_timed(fileEx.begin(), fileEx.end(), std::chrono::milliseconds(1000));
@@ -3118,8 +3125,8 @@ void MainDialog::OnConfigLoad(wxCommandEvent& event)
wxFileDialog filePicker(this,
wxString(),
- utfCvrtTo<wxString>(beforeLast(activeCfgFilename, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE)), //set default dir
- wxString(),
+ utfCvrtTo<wxString>(beforeLast(activeCfgFilename, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE)), //default dir
+ wxString(), //default file
wxString(L"FreeFileSync (*.ffs_gui; *.ffs_batch)|*.ffs_gui;*.ffs_batch") + L"|" +_("All files") + L" (*.*)|*",
wxFD_OPEN | wxFD_MULTIPLE);
if (filePicker.ShowModal() == wxID_OK)
@@ -3660,13 +3667,13 @@ void MainDialog::setViewFilterDefault()
setButton(m_bpButtonShowRightNewer, def.rightNewer);
setButton(m_bpButtonShowDifferent, def.different);
- setButton(m_bpButtonShowCreateLeft, def.createLeft);
- setButton(m_bpButtonShowCreateRight,def.createRight);
- setButton(m_bpButtonShowUpdateLeft, def.updateLeft);
- setButton(m_bpButtonShowUpdateRight,def.updateRight);
- setButton(m_bpButtonShowDeleteLeft, def.deleteLeft);
- setButton(m_bpButtonShowDeleteRight,def.deleteRight);
- setButton(m_bpButtonShowDoNothing, def.doNothing);
+ setButton(m_bpButtonShowCreateLeft, def.createLeft);
+ setButton(m_bpButtonShowCreateRight, def.createRight);
+ setButton(m_bpButtonShowUpdateLeft, def.updateLeft);
+ setButton(m_bpButtonShowUpdateRight, def.updateRight);
+ setButton(m_bpButtonShowDeleteLeft, def.deleteLeft);
+ setButton(m_bpButtonShowDeleteRight, def.deleteRight);
+ setButton(m_bpButtonShowDoNothing, def.doNothing);
}
@@ -3788,7 +3795,7 @@ void MainDialog::OnCompare(wxCommandEvent& event)
if (!globalCfg.soundFileCompareFinished.empty())
{
const Zstring soundFile = getResourceDirPf() + globalCfg.soundFileCompareFinished;
- if (fileExists(soundFile))
+ if (fileAvailable(soundFile))
wxSound::Play(utfCvrtTo<wxString>(soundFile), wxSOUND_ASYNC); //warning: this may fail and show a wxWidgets error message! => must not play when running FFS as batch!
}
@@ -3959,18 +3966,18 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
std::unique_ptr<LockHolder> dirLocks;
if (globalCfg.createLockFile)
{
- std::set<Zstring, LessFilePath> dirPathsExisting;
+ std::set<Zstring, LessFilePath> availableDirPaths;
for (auto it = begin(folderCmp); it != end(folderCmp); ++it)
{
- if (it->isExisting<LEFT_SIDE>()) //do NOT check directory existence again!
+ if (it->isAvailable<LEFT_SIDE>()) //do NOT check directory existence again!
if (Opt<Zstring> nativeFolderPath = AFS::getNativeItemPath(it->getAbstractPath<LEFT_SIDE>())) //restrict directory locking to native paths until further
- dirPathsExisting.insert(*nativeFolderPath);
+ availableDirPaths.insert(*nativeFolderPath);
- if (it->isExisting<RIGHT_SIDE>())
+ if (it->isAvailable<RIGHT_SIDE>())
if (Opt<Zstring> nativeFolderPath = AFS::getNativeItemPath(it->getAbstractPath<RIGHT_SIDE>()))
- dirPathsExisting.insert(*nativeFolderPath);
+ availableDirPaths.insert(*nativeFolderPath);
}
- dirLocks = std::make_unique<LockHolder>(dirPathsExisting, globalCfg.optDialogs.warningDirectoryLockFailed, statusHandler);
+ dirLocks = std::make_unique<LockHolder>(availableDirPaths, globalCfg.optDialogs.warningDirectoryLockFailed, statusHandler);
}
//START SYNCHRONIZATION
@@ -4146,23 +4153,23 @@ void MainDialog::updateGridViewData()
filesizeRightView = result.filesizeRightView;
//sync preview buttons
- updateVisibility(m_bpButtonShowExcluded , result.existsExcluded);
- updateVisibility(m_bpButtonShowEqual , result.existsEqual);
- updateVisibility(m_bpButtonShowConflict , result.existsConflict);
+ updateVisibility(m_bpButtonShowExcluded, result.existsExcluded);
+ updateVisibility(m_bpButtonShowEqual, result.existsEqual);
+ updateVisibility(m_bpButtonShowConflict, result.existsConflict);
- updateVisibility(m_bpButtonShowCreateLeft , result.existsSyncCreateLeft);
+ updateVisibility(m_bpButtonShowCreateLeft, result.existsSyncCreateLeft);
updateVisibility(m_bpButtonShowCreateRight, result.existsSyncCreateRight);
- updateVisibility(m_bpButtonShowDeleteLeft , result.existsSyncDeleteLeft);
+ updateVisibility(m_bpButtonShowDeleteLeft, result.existsSyncDeleteLeft);
updateVisibility(m_bpButtonShowDeleteRight, result.existsSyncDeleteRight);
- updateVisibility(m_bpButtonShowUpdateLeft , result.existsSyncDirLeft);
+ updateVisibility(m_bpButtonShowUpdateLeft, result.existsSyncDirLeft);
updateVisibility(m_bpButtonShowUpdateRight, result.existsSyncDirRight);
- updateVisibility(m_bpButtonShowDoNothing , result.existsSyncDirNone);
+ updateVisibility(m_bpButtonShowDoNothing, result.existsSyncDirNone);
- updateVisibility(m_bpButtonShowLeftOnly , false);
- updateVisibility(m_bpButtonShowRightOnly , false);
- updateVisibility(m_bpButtonShowLeftNewer , false);
+ updateVisibility(m_bpButtonShowLeftOnly, false);
+ updateVisibility(m_bpButtonShowRightOnly, false);
+ updateVisibility(m_bpButtonShowLeftNewer, false);
updateVisibility(m_bpButtonShowRightNewer, false);
- updateVisibility(m_bpButtonShowDifferent , false);
+ updateVisibility(m_bpButtonShowDifferent, false);
}
else
{
@@ -4182,23 +4189,23 @@ void MainDialog::updateGridViewData()
filesizeRightView = result.filesizeRightView;
//comparison result view buttons
- updateVisibility(m_bpButtonShowExcluded , result.existsExcluded);
- updateVisibility(m_bpButtonShowEqual , result.existsEqual);
- updateVisibility(m_bpButtonShowConflict , result.existsConflict);
+ updateVisibility(m_bpButtonShowExcluded, result.existsExcluded);
+ updateVisibility(m_bpButtonShowEqual, result.existsEqual);
+ updateVisibility(m_bpButtonShowConflict, result.existsConflict);
- updateVisibility(m_bpButtonShowCreateLeft , false);
+ updateVisibility(m_bpButtonShowCreateLeft, false);
updateVisibility(m_bpButtonShowCreateRight, false);
- updateVisibility(m_bpButtonShowDeleteLeft , false);
+ updateVisibility(m_bpButtonShowDeleteLeft, false);
updateVisibility(m_bpButtonShowDeleteRight, false);
- updateVisibility(m_bpButtonShowUpdateLeft , false);
+ updateVisibility(m_bpButtonShowUpdateLeft, false);
updateVisibility(m_bpButtonShowUpdateRight, false);
- updateVisibility(m_bpButtonShowDoNothing , false);
+ updateVisibility(m_bpButtonShowDoNothing, false);
- updateVisibility(m_bpButtonShowLeftOnly , result.existsLeftOnly);
- updateVisibility(m_bpButtonShowRightOnly , result.existsRightOnly);
- updateVisibility(m_bpButtonShowLeftNewer , result.existsLeftNewer);
+ updateVisibility(m_bpButtonShowLeftOnly, result.existsLeftOnly);
+ updateVisibility(m_bpButtonShowRightOnly, result.existsRightOnly);
+ updateVisibility(m_bpButtonShowLeftNewer, result.existsLeftNewer);
updateVisibility(m_bpButtonShowRightNewer, result.existsRightNewer);
- updateVisibility(m_bpButtonShowDifferent , result.existsDifferent);
+ updateVisibility(m_bpButtonShowDifferent, result.existsDifferent);
}
const bool anySelectViewButtonShown = m_bpButtonShowEqual ->IsShown() ||
@@ -4497,7 +4504,7 @@ void MainDialog::OnShowFolderPairOptions(wxEvent& event)
ContextMenu menu;
menu.addItem(_("Add folder pair"), [this, pos] { insertAddFolderPair({ FolderPairEnh() }, pos); }, &getResourceImage(L"item_add_small"));
menu.addSeparator();
- menu.addItem(_("Move up" ) + L"\tAlt+Page Up" , [this, pos] { moveAddFolderPairUp(pos); }, &getResourceImage(L"move_up_small"));
+ menu.addItem(_("Move up" ) + L"\tAlt+Page Up", [this, pos] { moveAddFolderPairUp(pos); }, &getResourceImage(L"move_up_small"));
menu.addItem(_("Move down") + L"\tAlt+Page Down", [this, pos] { moveAddFolderPairUp(pos + 1); }, &getResourceImage(L"move_down_small"), pos + 1 < makeSigned(additionalFolderPairs.size()));
wxPoint ctxPos = (*it)->m_bpButtonFolderPairOptions->GetPosition();
@@ -4801,9 +4808,9 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
auto colAttrCenter = m_gridMainC->getColumnConfig();
auto colAttrRight = m_gridMainR->getColumnConfig();
- erase_if(colAttrLeft , [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
+ erase_if(colAttrLeft, [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
erase_if(colAttrCenter, [](const Grid::ColumnAttribute& ca) { return !ca.visible_ || static_cast<ColumnTypeCenter>(ca.type_) == ColumnTypeCenter::CHECKBOX; });
- erase_if(colAttrRight , [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
+ erase_if(colAttrRight, [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
if (provLeft && provCenter && provRight)
{
diff --git a/FreeFileSync/Source/ui/main_dlg.h b/FreeFileSync/Source/ui/main_dlg.h
index 0aace163..43727211 100644
--- a/FreeFileSync/Source/ui/main_dlg.h
+++ b/FreeFileSync/Source/ui/main_dlg.h
@@ -217,8 +217,8 @@ private:
void OnClose (wxCloseEvent& event) override;
void OnCmpSettings (wxCommandEvent& event) override { showConfigDialog(zen::SyncConfigPanel::COMPARISON, -1); }
- void OnConfigureFilter(wxCommandEvent& event) override { showConfigDialog(zen::SyncConfigPanel::FILTER , -1); }
- void OnSyncSettings (wxCommandEvent& event) override { showConfigDialog(zen::SyncConfigPanel::SYNC , -1); }
+ void OnConfigureFilter(wxCommandEvent& event) override { showConfigDialog(zen::SyncConfigPanel::FILTER, -1); }
+ void OnSyncSettings (wxCommandEvent& event) override { showConfigDialog(zen::SyncConfigPanel::SYNC, -1); }
void showConfigDialog(zen::SyncConfigPanel panelToShow, int localPairIndexToShow);
diff --git a/FreeFileSync/Source/ui/progress_indicator.cpp b/FreeFileSync/Source/ui/progress_indicator.cpp
index 93e721ea..d87b5343 100644
--- a/FreeFileSync/Source/ui/progress_indicator.cpp
+++ b/FreeFileSync/Source/ui/progress_indicator.cpp
@@ -2050,7 +2050,7 @@ void SyncProgressDialogImpl<TopLevelDialog>::processHasFinished(SyncResult resul
if (!soundFileSyncComplete_.empty())
{
const Zstring soundFile = getResourceDirPf() + soundFileSyncComplete_;
- if (fileExists(soundFile))
+ if (fileAvailable(soundFile))
wxSound::Play(utfCvrtTo<wxString>(soundFile), wxSOUND_ASYNC); //warning: this may fail and show a wxWidgets error message! => must not play when running FFS as batch!
}
break;
diff --git a/FreeFileSync/Source/ui/small_dlgs.cpp b/FreeFileSync/Source/ui/small_dlgs.cpp
index fdc28196..175aaf31 100644
--- a/FreeFileSync/Source/ui/small_dlgs.cpp
+++ b/FreeFileSync/Source/ui/small_dlgs.cpp
@@ -209,7 +209,7 @@ private:
void OnAuthPassword(wxCommandEvent& event) override { autType_ = AuthType::PASSWORD; updateGui(); }
void OnAuthKeyfile (wxCommandEvent& event) override { autType_ = AuthType::KEYFILE; updateGui(); }
- void OnSelectKeyfile (wxCommandEvent& event) override;
+ void OnSelectKeyfile(wxCommandEvent& event) override;
void updateGui();
@@ -327,8 +327,8 @@ void SftpSetupDlg::OnSelectKeyfile (wxCommandEvent& event)
{
wxFileDialog filePicker(this,
wxString(),
- beforeLast(m_textCtrlKeyfilePath->GetValue(), utfCvrtTo<wxString>(FILE_NAME_SEPARATOR), IF_MISSING_RETURN_NONE), //set default dir
- wxString(),
+ beforeLast(m_textCtrlKeyfilePath->GetValue(), utfCvrtTo<wxString>(FILE_NAME_SEPARATOR), IF_MISSING_RETURN_NONE), //default dir
+ wxString(), //default file
wxString(L"OpenSSL PEM (*.pem)|*.pem") + L"|" +_("All files") + L" (*.*)|*",
wxFD_OPEN);
if (filePicker.ShowModal() == wxID_OK)
diff --git a/FreeFileSync/Source/ui/sorting.h b/FreeFileSync/Source/ui/sorting.h
index fe842745..b5deb2bc 100644
--- a/FreeFileSync/Source/ui/sorting.h
+++ b/FreeFileSync/Source/ui/sorting.h
@@ -81,7 +81,7 @@ bool lessRelativeFolder(const FileSystemObject& a, const FileSystemObject& b)
const bool isDirectoryB = isDirectoryPair(b);
const Zstring& relFolderB = isDirectoryB ?
b.getPairRelativePath() : //directory
- beforeLast(b.getPairRelativePath(), FILE_NAME_SEPARATOR ,IF_MISSING_RETURN_NONE);
+ beforeLast(b.getPairRelativePath(), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE);
//compare relative names without filepaths first
const int rv = cmpFilePath(relFolderA.c_str(), relFolderA.size(),
diff --git a/FreeFileSync/Source/ui/sync_cfg.cpp b/FreeFileSync/Source/ui/sync_cfg.cpp
index 9bac8df3..4020c4cc 100644
--- a/FreeFileSync/Source/ui/sync_cfg.cpp
+++ b/FreeFileSync/Source/ui/sync_cfg.cpp
@@ -68,7 +68,7 @@ private:
};
//------------- comparison panel ----------------------
- void OnHelpComparisonSettings(wxHyperlinkEvent& event) override { displayHelpEntry(L"comparison-settings" , this); }
+ void OnHelpComparisonSettings(wxHyperlinkEvent& event) override { displayHelpEntry(L"comparison-settings", this); }
void OnHelpTimeShift (wxHyperlinkEvent& event) override { displayHelpEntry(L"daylight-saving-time", this); }
void OnToggleLocalCompSettings(wxCommandEvent& event) override { updateCompGui(); updateSyncGui(); /*affects sync settings, too!*/ }
@@ -131,8 +131,8 @@ private:
void OnToggleDeletionType(wxCommandEvent& event) override { toggleDeletionPolicy(handleDeletion_); updateSyncGui(); }
- void OnHelpDetectMovedFiles(wxHyperlinkEvent& event) override { displayHelpEntry(L"synchronization-settings" , this); }
- void OnHelpVersioning (wxHyperlinkEvent& event) override { displayHelpEntry(L"versioning", this); }
+ void OnHelpDetectMovedFiles(wxHyperlinkEvent& event) override { displayHelpEntry(L"synchronization-settings", this); }
+ void OnHelpVersioning (wxHyperlinkEvent& event) override { displayHelpEntry(L"versioning", this); }
std::shared_ptr<const SyncConfig> getSyncConfig() const;
void setSyncConfig(std::shared_ptr<const SyncConfig> syncCfg);
@@ -829,11 +829,11 @@ void updateSyncDirectionIcons(const DirectionConfig& directionCfg,
const DirectionSet dirCfg = extractDirections(directionCfg);
- updateButton(buttonLeftOnly , dirCfg.exLeftSideOnly , L"so_delete_left", L"so_none", L"so_create_right", SO_DELETE_LEFT , SO_DO_NOTHING, SO_CREATE_NEW_RIGHT);
- updateButton(buttonRightOnly , dirCfg.exRightSideOnly, L"so_create_left", L"so_none", L"so_delete_right", SO_CREATE_NEW_LEFT, SO_DO_NOTHING, SO_DELETE_RIGHT );
- updateButton(buttonLeftNewer , dirCfg.leftNewer , L"so_update_left", L"so_none", L"so_update_right", SO_OVERWRITE_LEFT , SO_DO_NOTHING, SO_OVERWRITE_RIGHT );
- updateButton(buttonRightNewer, dirCfg.rightNewer , L"so_update_left", L"so_none", L"so_update_right", SO_OVERWRITE_LEFT , SO_DO_NOTHING, SO_OVERWRITE_RIGHT );
- updateButton(buttonDifferent , dirCfg.different , L"so_update_left", L"so_none", L"so_update_right", SO_OVERWRITE_LEFT , SO_DO_NOTHING, SO_OVERWRITE_RIGHT );
+ updateButton(buttonLeftOnly, dirCfg.exLeftSideOnly, L"so_delete_left", L"so_none", L"so_create_right", SO_DELETE_LEFT, SO_DO_NOTHING, SO_CREATE_NEW_RIGHT);
+ updateButton(buttonRightOnly, dirCfg.exRightSideOnly, L"so_create_left", L"so_none", L"so_delete_right", SO_CREATE_NEW_LEFT, SO_DO_NOTHING, SO_DELETE_RIGHT );
+ updateButton(buttonLeftNewer, dirCfg.leftNewer, L"so_update_left", L"so_none", L"so_update_right", SO_OVERWRITE_LEFT, SO_DO_NOTHING, SO_OVERWRITE_RIGHT );
+ updateButton(buttonRightNewer, dirCfg.rightNewer, L"so_update_left", L"so_none", L"so_update_right", SO_OVERWRITE_LEFT, SO_DO_NOTHING, SO_OVERWRITE_RIGHT );
+ updateButton(buttonDifferent, dirCfg.different, L"so_update_left", L"so_none", L"so_update_right", SO_OVERWRITE_LEFT, SO_DO_NOTHING, SO_OVERWRITE_RIGHT );
switch (dirCfg.conflict)
{
diff --git a/FreeFileSync/Source/ui/tree_view.cpp b/FreeFileSync/Source/ui/tree_view.cpp
index cbfb5305..0db294f1 100644
--- a/FreeFileSync/Source/ui/tree_view.cpp
+++ b/FreeFileSync/Source/ui/tree_view.cpp
@@ -573,13 +573,13 @@ void TreeView::updateCmpResult(bool showExcluded,
bool conflictFilesActive)
{
updateView([showExcluded, //make sure the predicate can be stored safely!
- leftOnlyFilesActive,
- rightOnlyFilesActive,
- leftNewerFilesActive,
- rightNewerFilesActive,
- differentFilesActive,
- equalFilesActive,
- conflictFilesActive](const FileSystemObject& fsObj) -> bool
+ leftOnlyFilesActive,
+ rightOnlyFilesActive,
+ leftNewerFilesActive,
+ rightNewerFilesActive,
+ differentFilesActive,
+ equalFilesActive,
+ conflictFilesActive](const FileSystemObject& fsObj) -> bool
{
if (!fsObj.isActive() && !showExcluded)
return false;
@@ -620,15 +620,15 @@ void TreeView::updateSyncPreview(bool showExcluded,
bool conflictFilesActive)
{
updateView([showExcluded, //make sure the predicate can be stored safely!
- syncCreateLeftActive,
- syncCreateRightActive,
- syncDeleteLeftActive,
- syncDeleteRightActive,
- syncDirOverwLeftActive,
- syncDirOverwRightActive,
- syncDirNoneActive,
- syncEqualActive,
- conflictFilesActive](const FileSystemObject& fsObj) -> bool
+ syncCreateLeftActive,
+ syncCreateRightActive,
+ syncDeleteLeftActive,
+ syncDeleteRightActive,
+ syncDirOverwLeftActive,
+ syncDirOverwRightActive,
+ syncDirNoneActive,
+ syncEqualActive,
+ conflictFilesActive](const FileSystemObject& fsObj) -> bool
{
if (!fsObj.isActive() && !showExcluded)
return false;
diff --git a/FreeFileSync/Source/ui/version_check.cpp b/FreeFileSync/Source/ui/version_check.cpp
index da7b0e08..8783130c 100644
--- a/FreeFileSync/Source/ui/version_check.cpp
+++ b/FreeFileSync/Source/ui/version_check.cpp
@@ -143,7 +143,7 @@ std::vector<std::pair<std::string, std::string>> geHttpPostParameters()
#endif
params.emplace_back("language", utfCvrtTo<std::string>(getIso639Language()));
- params.emplace_back("country" , utfCvrtTo<std::string>(getIso3166Country()));
+ params.emplace_back("country", utfCvrtTo<std::string>(getIso3166Country()));
return params;
}
@@ -174,10 +174,10 @@ void runFreeFileSyncAutoUpdate(wxWindow* parent, const std::wstring& directDownl
const Zstring installerLocalPath = dirPath.empty() ? fileName : appendSeparator(dirPath) + fileName;
const Zstring installerLocalPathTmp = installerLocalPath + L".tmp";
-
- if (!fileExists(installerLocalPath))
+
+if (!getItemTypeIfExists(installerLocalPath)) //throw FileError
{
- ZEN_ON_SCOPE_FAIL(try { removeFile(installerLocalPathTmp); }
+ ZEN_ON_SCOPE_FAIL(try { removeFilePlain(installerLocalPathTmp); }
catch (FileError&) {});
{
@@ -297,7 +297,7 @@ void showUpdateAvailableDialog(wxWindow* parent, const std::string& onlineVersio
}
catch (const FileError& e) //fall back to regular update info dialog:
{
- updateDetailsMsg = e.toString() + L"\n\n" + updateDetailsMsg;
+ updateDetailsMsg = e.toString() + L"\n\n\n" + updateDetailsMsg;
}
switch (showConfirmationDialog(parent, DialogInfoType::INFO, PopupDialogCfg().
diff --git a/FreeFileSync/Source/ui/version_check_impl.h b/FreeFileSync/Source/ui/version_check_impl.h
index 58412517..e408d7a1 100644
--- a/FreeFileSync/Source/ui/version_check_impl.h
+++ b/FreeFileSync/Source/ui/version_check_impl.h
@@ -7,6 +7,8 @@
#ifndef VERSION_ID_HEADER_2348769284769242
#define VERSION_ID_HEADER_2348769284769242
+#include <ctime>
+#include <zen/basic_math.h>
#include "../version/version.h"
@@ -38,14 +40,14 @@ time_t getVersionCheckInactiveId()
inline
time_t getVersionCheckCurrentTime()
{
- return std::time(nullptr);
+ return std::time(nullptr);
}
bool shouldRunPeriodicUpdateCheck(time_t lastUpdateCheck)
{
- if (lastUpdateCheck == getVersionCheckInactiveId())
- return false;
+ if (lastUpdateCheck == getVersionCheckInactiveId())
+ return false;
const time_t now = std::time(nullptr);
return numeric::dist(now, lastUpdateCheck) >= 7 * 24 * 3600; //check weekly
diff --git a/FreeFileSync/Source/version/version.h b/FreeFileSync/Source/version/version.h
index f34673b8..dce88009 100644
--- a/FreeFileSync/Source/version/version.h
+++ b/FreeFileSync/Source/version/version.h
@@ -3,7 +3,7 @@
namespace zen
{
-const char ffsVersion[] = "8.7"; //internal linkage!
+const char ffsVersion[] = "8.8"; //internal linkage!
const char FFS_VERSION_SEPARATOR = '.';
}
diff --git a/wx+/graph.cpp b/wx+/graph.cpp
index 192e5513..d45a0e85 100644
--- a/wx+/graph.cpp
+++ b/wx+/graph.cpp
@@ -91,7 +91,7 @@ public:
int realToScreenRound(double realPos) const //returns -1 and screenSize + 1 if out of bounds!
{
//catch large double values: if double is larger than what int can represent => undefined behavior!
- numeric::clamp(realPos , outOfBoundsLow, outOfBoundsHigh);
+ numeric::clamp(realPos, outOfBoundsLow, outOfBoundsHigh);
return numeric::round(realToScreen(realPos));
}
diff --git a/wx+/popup_dlg_generated.cpp b/wx+/popup_dlg_generated.cpp
index 6df18dce..a79ffa52 100644
--- a/wx+/popup_dlg_generated.cpp
+++ b/wx+/popup_dlg_generated.cpp
@@ -11,7 +11,7 @@
PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
- this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
+ this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize );
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
wxBoxSizer* bSizer24;
@@ -23,7 +23,7 @@ PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, con
wxBoxSizer* bSizer165;
bSizer165 = new wxBoxSizer( wxHORIZONTAL );
- m_bitmapMsgType = new wxStaticBitmap( m_panel33, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_bitmapMsgType = new wxStaticBitmap( m_panel33, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizer165->Add( m_bitmapMsgType, 0, wxALL, 10 );
wxBoxSizer* bSizer16;
@@ -62,13 +62,13 @@ PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, con
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonAffirmative = new wxButton( this, wxID_YES, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonAffirmative = new wxButton( this, wxID_YES, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonAffirmative, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
- m_buttonNegative = new wxButton( this, wxID_NO, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonNegative = new wxButton( this, wxID_NO, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonNegative, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp
index 98190bba..79e8aeb7 100644
--- a/zen/dir_watcher.cpp
+++ b/zen/dir_watcher.cpp
@@ -396,7 +396,7 @@ DirWatcher::DirWatcher(const Zstring& dirPath) : //throw FileError
traverse = [&traverse, &fullFolderList](const Zstring& path)
{
traverseFolder(path, nullptr,
- [&](const DirInfo& di ) { fullFolderList.push_back(di.fullPath); traverse(di.fullPath); },
+ [&](const FolderInfo& fi ) { fullFolderList.push_back(fi.fullPath); traverse(fi.fullPath); },
nullptr, //don't traverse into symlinks (analog to windows build)
[&](const std::wstring& errorMsg) { throw FileError(errorMsg); });
};
diff --git a/zen/file_access.cpp b/zen/file_access.cpp
index bad1b60d..ac68330e 100644
--- a/zen/file_access.cpp
+++ b/zen/file_access.cpp
@@ -44,7 +44,140 @@
using namespace zen;
-bool zen::fileExists(const Zstring& filePath)
+Opt<Zstring> zen::getParentFolderPath(const Zstring& itemPath)
+{
+#ifdef ZEN_WIN
+ assert(startsWith(itemPath, L"\\\\") || //we do NOT support relative paths!
+ (itemPath.size() >= 3 && isAlpha(itemPath[0]) && itemPath[1] == L':' && itemPath[2] == L'\\'));
+
+ //remove trailing separator (even for C:\ root directories)
+ const Zstring itemPathFmt = endsWith(itemPath, FILE_NAME_SEPARATOR) ?
+ beforeLast(itemPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE) :
+ itemPath;
+
+ if (startsWith(itemPathFmt, L"\\\\")) //UNC-name, e.g. \\server-name\share
+ if (std::count(itemPathFmt.begin(), itemPathFmt.end(), FILE_NAME_SEPARATOR) <= 3)
+ return NoValue();
+
+ const Zstring parentDir = beforeLast(itemPathFmt, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE);
+ if (parentDir.empty())
+ return NoValue();
+ if (parentDir.size() == 2 && isAlpha(parentDir[0]) && parentDir[1] == L':')
+ return appendSeparator(parentDir);
+
+#elif defined ZEN_LINUX || defined ZEN_MAC
+ assert(startsWith(itemPath, L"/")); //we do NOT support relative paths!
+
+ if (itemPath == "/")
+ return NoValue();
+
+ const Zstring parentDir = beforeLast(itemPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE);
+ if (parentDir.empty())
+ return Zstring("/");
+#endif
+ return parentDir;
+}
+
+
+ItemType zen::getItemType(const Zstring& itemPath) //throw FileError
+{
+#ifdef ZEN_WIN
+ const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(itemPath).c_str());
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ {
+ const DWORD ec = ::GetLastError(); //copy before directly/indirectly making other system calls!
+ if (ec == ERROR_PATH_NOT_FOUND || //
+ ec == ERROR_FILE_NOT_FOUND || //perf: short circuit for common "not existing" error codes
+ ec == ERROR_BAD_NETPATH || //
+ ec == ERROR_BAD_NET_NAME) //
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), L"GetFileAttributes");
+ }
+
+ if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
+ return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0 ? ItemType::FOLDER : ItemType::FILE;
+
+ //handle obscure file permission problem where ::GetFileAttributes() fails with ERROR_ACCESS_DENIED or ERROR_SHARING_VIOLATION
+ //while parent directory traversal is successful: e.g. "C:\pagefile.sys"
+ WIN32_FIND_DATA itemInfo = {};
+ const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(itemPath).c_str(), &itemInfo);
+ if (searchHandle == INVALID_HANDLE_VALUE)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), L"FindFirstFile");
+ ::FindClose(searchHandle);
+
+ if (isSymlink(itemInfo)) //not every FILE_ATTRIBUTE_REPARSE_POINT is a symlink!!!
+ return ItemType::SYMLINK;
+ return (itemInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ? ItemType::FOLDER : ItemType::FILE;
+
+#elif defined ZEN_LINUX || defined ZEN_MAC
+ struct ::stat itemInfo = {};
+ if (::lstat(itemPath.c_str(), &itemInfo) != 0)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), L"lstat");
+
+ if (S_ISLNK(itemInfo.st_mode))
+ return ItemType::SYMLINK;
+ if (S_ISDIR(itemInfo.st_mode))
+ return ItemType::FOLDER;
+ return ItemType::FILE; //S_ISREG || S_ISCHR || S_ISBLK || S_ISFIFO || S_ISSOCK
+#endif
+}
+
+
+PathDetails zen::getPathDetails(const Zstring& itemPath) //throw FileError
+{
+ const Opt<Zstring> parentPath = getParentFolderPath(itemPath);
+ try
+ {
+ return { getItemType(itemPath), itemPath, {} }; //throw FileError
+ }
+ catch (FileError&)
+ {
+ if (!parentPath) //device root
+ throw;
+ //else: let's dig deeper... don't bother checking Win32 codes; e.g. not existing item may have the codes:
+ // ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, ERROR_INVALID_NAME, ERROR_INVALID_DRIVE,
+ // ERROR_NOT_READY, ERROR_INVALID_PARAMETER, ERROR_BAD_PATHNAME, ERROR_BAD_NETPATH => not reliable
+ }
+ const Zstring itemName = afterLast(itemPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL);
+ assert(!itemName.empty());
+
+ PathDetails pd = getPathDetails(*parentPath); //throw FileError
+ if (!pd.relPath.empty())
+ {
+ pd.relPath.push_back(itemName);
+ return { pd.existingType, pd.existingPath, pd.relPath };
+ }
+
+ try
+ {
+ traverseFolder(*parentPath,
+ [&](const FileInfo& fi) { if (equalFilePath(fi.itemName, itemName)) throw ItemType::FILE; },
+ [&](const FolderInfo& fi) { if (equalFilePath(fi.itemName, itemName)) throw ItemType::FOLDER; },
+ [&](const SymlinkInfo& si) { if (equalFilePath(si.itemName, itemName)) throw ItemType::SYMLINK; },
+ [](const std::wstring& errorMsg) { throw FileError(errorMsg); });
+
+ return { pd.existingType, *parentPath, { itemName } }; //throw FileError
+ }
+ catch (const ItemType& type) { return { type, itemPath, {} }; } //yes, exceptions for control-flow are bad design... but, but...
+ //we're not CPU-bound here and finding the item after getItemType() previously failed is exceptional (even C:\pagefile.sys should be found)
+}
+
+
+Opt<ItemType> zen::getItemTypeIfExists(const Zstring& itemPath) //throw FileError
+{
+ const PathDetails pd = getPathDetails(itemPath); //throw FileError
+#ifndef NDEBUG
+ Zstring reconstructedPath = pd.existingPath;
+ for (const Zstring& itemName : pd.relPath)
+ reconstructedPath += endsWith(reconstructedPath, FILE_NAME_SEPARATOR) ? itemName : FILE_NAME_SEPARATOR + itemName;
+ assert(itemPath == reconstructedPath);
+#endif
+ if (pd.relPath.empty())
+ return pd.existingType;
+ return NoValue();
+}
+
+
+bool zen::fileAvailable(const Zstring& filePath) //noexcept
{
//symbolic links (broken or not) are also treated as existing files!
#ifdef ZEN_WIN
@@ -61,13 +194,13 @@ bool zen::fileExists(const Zstring& filePath)
}
-bool zen::dirExists(const Zstring& dirPath)
+bool zen::dirAvailable(const Zstring& dirPath) //noexcept
{
//symbolic links (broken or not) are also treated as existing directories!
#ifdef ZEN_WIN
const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(dirPath).c_str());
if (attr != INVALID_FILE_ATTRIBUTES)
- return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; //returns true for (dir-)symlinks also
+ return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; //returns true for ((broken) dir-)symlinks also
#elif defined ZEN_LINUX || defined ZEN_MAC
struct ::stat dirInfo = {};
@@ -78,54 +211,39 @@ bool zen::dirExists(const Zstring& dirPath)
}
-bool zen::symlinkExists(const Zstring& linkPath)
+warn_static("remove following test functions after refactoring")
+
+
+
+bool zen::fileExists(const Zstring& filePath)
{
+ //symbolic links (broken or not) are also treated as existing files!
#ifdef ZEN_WIN
- WIN32_FIND_DATA linkInfo = {};
- const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(linkPath).c_str(), &linkInfo);
- if (searchHandle != INVALID_HANDLE_VALUE)
- {
- ::FindClose(searchHandle);
- return isSymlink(linkInfo);
- }
+ const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(filePath).c_str());
+ if (attr != INVALID_FILE_ATTRIBUTES)
+ return (attr & FILE_ATTRIBUTE_DIRECTORY) == 0; //returns true for (file-)symlinks also
#elif defined ZEN_LINUX || defined ZEN_MAC
- struct ::stat linkInfo = {};
- if (::lstat(linkPath.c_str(), &linkInfo) == 0)
- return S_ISLNK(linkInfo.st_mode);
+ struct ::stat fileInfo = {};
+ if (::stat(filePath.c_str(), &fileInfo) == 0) //follow symlinks!
+ return S_ISREG(fileInfo.st_mode);
#endif
return false;
}
-bool zen::somethingExists(const Zstring& itemPath)
+bool zen::dirExists(const Zstring& dirPath)
{
+ //symbolic links (broken or not) are also treated as existing directories!
#ifdef ZEN_WIN
- const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(itemPath).c_str());
+ const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(dirPath).c_str());
if (attr != INVALID_FILE_ATTRIBUTES)
- return true;
- const DWORD ec = ::GetLastError(); //copy before directly/indirectly making other system calls!
-
- //handle obscure file permission problem where ::GetFileAttributes() fails with ERROR_ACCESS_DENIED or ERROR_SHARING_VIOLATION
- //while parent directory traversal is successful: e.g. "C:\pagefile.sys"
- if (ec != ERROR_PATH_NOT_FOUND && //perf: short circuit for common "not existing" error codes
- ec != ERROR_FILE_NOT_FOUND && //
- ec != ERROR_BAD_NETPATH && //
- ec != ERROR_BAD_NET_NAME) //
- {
- WIN32_FIND_DATA fileInfo = {};
- const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(itemPath).c_str(), &fileInfo);
- if (searchHandle != INVALID_HANDLE_VALUE)
- {
- ::FindClose(searchHandle);
- return true;
- }
- }
+ return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; //returns true for ((broken) dir-)symlinks also
#elif defined ZEN_LINUX || defined ZEN_MAC
- struct ::stat fileInfo = {};
- if (::lstat(itemPath.c_str(), &fileInfo) == 0)
- return true;
+ struct ::stat dirInfo = {};
+ if (::stat(dirPath.c_str(), &dirInfo) == 0) //follow symlinks!
+ return S_ISDIR(dirInfo.st_mode);
#endif
return false;
}
@@ -134,7 +252,15 @@ bool zen::somethingExists(const Zstring& itemPath)
namespace
{
#ifdef ZEN_WIN
-bool isFatDrive(const Zstring& filePath) //noexcept
+enum class FatType
+{
+ NONE,
+ FAT,
+ FAT32,
+ EXFAT,
+};
+
+FatType getFatType(const Zstring& filePath) //noexcept
{
const DWORD bufferSize = MAX_PATH + 1;
std::vector<wchar_t> buffer(bufferSize);
@@ -145,7 +271,7 @@ bool isFatDrive(const Zstring& filePath) //noexcept
bufferSize)) //__in DWORD cchBufferLength
{
assert(false);
- return false;
+ return FatType::NONE;
}
const Zstring volumePath = appendSeparator(&buffer[0]);
@@ -161,16 +287,21 @@ bool isFatDrive(const Zstring& filePath) //noexcept
bufferSize)) //__in DWORD nFileSystemNameSize
{
assert(false);
- return false;
+ return FatType::NONE;
}
- return &buffer[0] == Zstring(L"FAT") ||
- &buffer[0] == Zstring(L"FAT32");
+ if (&buffer[0] == Zstring(L"FAT"))
+ return FatType::FAT;
+ if (&buffer[0] == Zstring(L"FAT32"))
+ return FatType::FAT32;
+ if (&buffer[0] == Zstring(L"exFAT"))
+ return FatType::EXFAT;
+ return FatType::NONE;
}
#ifdef ZEN_WIN_VISTA_AND_LATER
-bool isFatDrive(HANDLE hFile) //noexcept
+FatType getFatType(HANDLE hFile) //noexcept
{
const DWORD bufferSize = MAX_PATH + 1; //"The length of the file system name buffer, in TCHARs. The maximum buffer size is MAX_PATH + 1"
std::vector<wchar_t> buffer(bufferSize);
@@ -185,11 +316,16 @@ bool isFatDrive(HANDLE hFile) //noexcept
bufferSize)) //_In_ DWORD nFileSystemNameSize
{
assert(false);
- return false;
+ return FatType::NONE;
}
- return &buffer[0] == Zstring(L"FAT") ||
- &buffer[0] == Zstring(L"FAT32");
+ if (&buffer[0] == Zstring(L"FAT"))
+ return FatType::FAT;
+ if (&buffer[0] == Zstring(L"FAT32"))
+ return FatType::FAT32;
+ if (&buffer[0] == Zstring(L"exFAT"))
+ return FatType::EXFAT;
+ return FatType::NONE;
}
#endif
#endif
@@ -331,7 +467,7 @@ Zstring zen::getTempFolderPath() //throw FileError
}
-bool zen::removeFile(const Zstring& filePath) //throw FileError
+void zen::removeFilePlain(const Zstring& filePath) //throw FileError
{
#ifdef ZEN_WIN
const wchar_t functionName[] = L"DeleteFile";
@@ -345,19 +481,14 @@ bool zen::removeFile(const Zstring& filePath) //throw FileError
ErrorCode ec = getLastError(); //copy before directly/indirectly making other system calls!
#ifdef ZEN_WIN
if (ec == ERROR_ACCESS_DENIED) //function fails if file is read-only
- {
- ::SetFileAttributes(applyLongPathPrefix(filePath).c_str(), FILE_ATTRIBUTE_NORMAL); //(try to) normalize file attributes
-
- if (::DeleteFile(applyLongPathPrefix(filePath).c_str())) //now try again...
- return true;
- ec = ::GetLastError();
- }
+ if (::SetFileAttributes(applyLongPathPrefix(filePath).c_str(), FILE_ATTRIBUTE_NORMAL)) //(try to) normalize file attributes
+ {
+ if (::DeleteFile(applyLongPathPrefix(filePath).c_str())) //now try again...
+ return;
+ ec = ::GetLastError();
+ }
#endif
- if (!somethingExists(filePath)) //warning: changes global error code!!
- return false; //neither file nor any other object (e.g. broken symlink) with that name existing - caveat: what if "access is denied"!?!??!?!?
-
//begin of "regular" error reporting
- const std::wstring errorMsg = replaceCpy(_("Cannot delete file %x."), L"%x", fmtPath(filePath));
std::wstring errorDescr = formatSystemError(functionName, ec);
#ifdef ZEN_WIN_VISTA_AND_LATER
@@ -369,18 +500,29 @@ bool zen::removeFile(const Zstring& filePath) //throw FileError
errorDescr = _("The file is locked by another process:") + L"\n" + procList;
}
#endif
- throw FileError(errorMsg, errorDescr);
+ throw FileError(replaceCpy(_("Cannot delete file %x."), L"%x", fmtPath(filePath)), errorDescr);
}
- return true;
}
-void zen::removeDirectorySimple(const Zstring& dirPath) //throw FileError
+void zen::removeSymlinkPlain(const Zstring& linkPath) //throw FileError
{
#ifdef ZEN_WIN
- //(try to) normalize file attributes: actually NEEDED for symbolic links also!
- ::SetFileAttributes(applyLongPathPrefix(dirPath).c_str(), FILE_ATTRIBUTE_NORMAL);
+ const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(linkPath).c_str());
+ if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
+ removeDirectoryPlain(linkPath); //throw FileError
+ else
+ removeFilePlain(linkPath); //throw FileError
+#elif defined ZEN_LINUX || defined ZEN_MAC
+ removeFilePlain(linkPath); //throw FileError
+#endif
+}
+
+
+void zen::removeDirectoryPlain(const Zstring& dirPath) //throw FileError
+{
+#ifdef ZEN_WIN
const wchar_t functionName[] = L"RemoveDirectory";
if (!::RemoveDirectory(applyLongPathPrefix(dirPath).c_str()))
#elif defined ZEN_LINUX || defined ZEN_MAC
@@ -388,13 +530,20 @@ void zen::removeDirectorySimple(const Zstring& dirPath) //throw FileError
if (::rmdir(dirPath.c_str()) != 0)
#endif
{
- const ErrorCode ec = getLastError(); //copy before making other system calls!
-
- if (!somethingExists(dirPath)) //warning: changes global error code!!
- return;
+ ErrorCode ec = getLastError(); //copy before making other system calls!
+#ifdef ZEN_WIN
+ if (ec == ERROR_ACCESS_DENIED) //(try to) normalize file attributes: NEEDED! even folders and symlinks can have FILE_ATTRIBUTE_READONLY set!
+ if (::SetFileAttributes(applyLongPathPrefix(dirPath).c_str(), FILE_ATTRIBUTE_NORMAL))
+ {
+ if (::RemoveDirectory(applyLongPathPrefix(dirPath).c_str())) //now try again...
+ return;
+ ec = ::GetLastError();
+ }
+#elif defined ZEN_LINUX || defined ZEN_MAC
+ bool symlinkExists = false;
+ try { symlinkExists = getItemType(dirPath) == ItemType::SYMLINK; } /*throw FileError*/ catch (FileError&) {} //previous exception is more relevant
-#if defined ZEN_LINUX || defined ZEN_MAC
- if (symlinkExists(dirPath))
+ if (symlinkExists)
{
if (::unlink(dirPath.c_str()) != 0)
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot delete directory %x."), L"%x", fmtPath(dirPath)), L"unlink");
@@ -418,48 +567,41 @@ namespace
{
void removeDirectoryImpl(const Zstring& folderPath) //throw FileError
{
- assert(dirExists(folderPath)); //[!] no symlinks in this context!!!
- //attention: check if folderPath is a symlink! Do NOT traverse into it deleting contained files!!!
-
+#ifndef NDEBUG //[!] no symlinks in this context!!! Do NOT traverse into it deleting contained files!!!
+ try { assert(getItemType(folderPath) != ItemType::SYMLINK); /*throw FileError*/ }
+ catch (FileError&) {}
+#endif
std::vector<Zstring> filePaths;
- std::vector<Zstring> folderSymlinkPaths;
+ std::vector<Zstring> symlinkPaths;
std::vector<Zstring> folderPaths;
//get all files and directories from current directory (WITHOUT subdirectories!)
traverseFolder(folderPath,
- [&](const FileInfo& fi) { filePaths.push_back(fi.fullPath); },
- [&](const DirInfo& di) { folderPaths .push_back(di.fullPath); }, //defer recursion => save stack space and allow deletion of extremely deep hierarchies!
- [&](const SymlinkInfo& si)
- {
-#ifdef ZEN_WIN
- if (dirExists(si.fullPath)) //dir symlink
- folderSymlinkPaths.push_back(si.fullPath);
- else //file symlink, broken symlink
-#endif
- filePaths.push_back(si.fullPath);
- },
+ [&](const FileInfo& fi) { filePaths .push_back(fi.fullPath); },
+ [&](const FolderInfo& fi) { folderPaths .push_back(fi.fullPath); }, //defer recursion => save stack space and allow deletion of extremely deep hierarchies!
+ [&](const SymlinkInfo& si) { symlinkPaths.push_back(si.fullPath); },
[](const std::wstring& errorMsg) { throw FileError(errorMsg); });
for (const Zstring& filePath : filePaths)
- removeFile(filePath); //throw FileError
+ removeFilePlain(filePath); //throw FileError
- for (const Zstring& symlinkPath : folderSymlinkPaths)
- removeDirectorySimple(symlinkPath); //throw FileError
+ for (const Zstring& symlinkPath : symlinkPaths)
+ removeSymlinkPlain(symlinkPath); //throw FileError
//delete directories recursively
for (const Zstring& subFolderPath : folderPaths)
removeDirectoryImpl(subFolderPath); //throw FileError; call recursively to correctly handle symbolic links
- removeDirectorySimple(folderPath); //throw FileError
+ removeDirectoryPlain(folderPath); //throw FileError
}
}
-void zen::removeDirectoryRecursively(const Zstring& dirPath) //throw FileError
+void zen::removeDirectoryPlainRecursion(const Zstring& dirPath) //throw FileError
{
- if (symlinkExists(dirPath))
- removeDirectorySimple(dirPath); //throw FileError
- else if (somethingExists(dirPath))
+ if (getItemType(dirPath) == ItemType::SYMLINK) //throw FileError
+ removeSymlinkPlain(dirPath); //throw FileError
+ else
removeDirectoryImpl(dirPath); //throw FileError
}
@@ -524,7 +666,6 @@ void renameFile_sub(const Zstring& pathSource, const Zstring& pathTarget) //thro
errorDescr = _("The file is locked by another process:") + L"\n" + procList;
}
#endif
-
if (ec == ERROR_NOT_SAME_DEVICE)
throw ErrorDifferentVolume(errorMsg, errorDescr);
if (ec == ERROR_ALREADY_EXISTS || //-> used on Win7 x64
@@ -534,7 +675,8 @@ void renameFile_sub(const Zstring& pathSource, const Zstring& pathTarget) //thro
}
#elif defined ZEN_LINUX || defined ZEN_MAC
- //rename() will never fail with EEXIST, but always (atomically) overwrite! => equivalent to SetFileInformationByHandle() + FILE_RENAME_INFO::ReplaceIfExists
+ //rename() will never fail with EEXIST, but always (atomically) overwrite!
+ //=> equivalent to SetFileInformationByHandle() + FILE_RENAME_INFO::ReplaceIfExists or ::MoveFileEx + MOVEFILE_REPLACE_EXISTING
//=> Linux: renameat2() with RENAME_NOREPLACE -> still new, probably buggy
//=> OS X: no solution
@@ -550,9 +692,15 @@ void renameFile_sub(const Zstring& pathSource, const Zstring& pathTarget) //thro
throw FileError(errorMsg, errorDescr);
};
- if (!equalFilePath(pathSource, pathTarget)) //OS X: changing file name case is not an "already exists" error!
- if (somethingExists(pathTarget))
+ if (!equalFilePath(pathSource, pathTarget)) //exception for OS X: changing file name case is not an "already exists" situation!
+ {
+ bool alreadyExists = true;
+ try { /*ItemType type = */getItemType(pathTarget); } /*throw FileError*/ catch (FileError&) { alreadyExists = false; }
+
+ if (alreadyExists)
throwException(EEXIST);
+ //else: nothing exists or other error (hopefully ::rename will also fail!)
+ }
if (::rename(pathSource.c_str(), pathTarget.c_str()) != 0)
throwException(errno);
@@ -585,10 +733,11 @@ Zstring getFilenameFmt(const Zstring& filePath, Function fun) //throw(); returns
}
-Zstring findUnused8Dot3Name(const Zstring& filePath) //find a unique 8.3 short name
+Zstring findUnused8Dot3Name(const Zstring& filePath) //throw FileError
{
- const Zstring pathPrefix = contains(filePath, FILE_NAME_SEPARATOR) ?
- (beforeLast(filePath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE) + FILE_NAME_SEPARATOR) : Zstring();
+ Opt<Zstring> parentPath = getParentFolderPath(filePath);
+ assert(parentPath);
+ const Zstring pathPrefix = parentPath ? appendSeparator(*parentPath) : Zstring();
//extension needn't contain reasonable data
Zstring extension = getFileExtension(filePath);
@@ -599,35 +748,35 @@ Zstring findUnused8Dot3Name(const Zstring& filePath) //find a unique 8.3 short n
for (int index = 0; index < 100000000; ++index) //filePath must be representable by <= 8 characters
{
- const Zstring output = pathPrefix + numberTo<Zstring>(index) + Zchar('.') + extension;
- if (!somethingExists(output)) //ensure uniqueness
- return output;
+ const Zstring testPath = pathPrefix + numberTo<Zstring>(index) + Zchar('.') + extension;
+ if (!getItemTypeIfExists(testPath)) //throw FileError
+ return testPath;
}
throw std::runtime_error(std::string("100,000,000 files, one for each number, exist in this directory? You're kidding...") + utfCvrtTo<std::string>(pathPrefix) +
"\n" + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
}
-bool have8dot3NameClash(const Zstring& filePath)
+bool have8dot3NameClash(const Zstring& itemPath)
{
- if (!contains(filePath, FILE_NAME_SEPARATOR))
- return false;
+ try
+ {
+ /*ItemType type =*/ getItemType(itemPath); //throw FileError
+ }
+ catch (FileError&) { return false; }
- if (somethingExists(filePath)) //name OR directory!
+ const Zstring nameOrig = afterLast(itemPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL);
+ const Zstring nameShort = afterLast(getFilenameFmt(itemPath, ::GetShortPathName), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL); //throw() returns empty string on error
+ const Zstring nameLong = afterLast(getFilenameFmt(itemPath, ::GetLongPathName ), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL); //
+
+ if (!nameShort.empty() &&
+ !nameLong .empty() &&
+ equalFilePath(nameOrig, nameShort) &&
+ !equalFilePath(nameShort, nameLong))
{
- const Zstring origName = afterLast(filePath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL);
- const Zstring shortName = afterLast(getFilenameFmt(filePath, ::GetShortPathName), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL); //throw() returns empty string on error
- const Zstring longName = afterLast(getFilenameFmt(filePath, ::GetLongPathName ), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL); //
-
- if (!shortName.empty() &&
- !longName .empty() &&
- equalFilePath(origName, shortName) &&
- !equalFilePath(shortName, longName))
- {
- //for filePath short and long file name are equal and another unrelated file happens to have the same short name
- //e.g. filePath == "TESTWE~1", but another file is existing named "TestWeb" with short name ""TESTWE~1"
- return true;
- }
+ //for itemPath short and long file name are equal and another unrelated file happens to have the same short name
+ //e.g. itemPath == "TESTWE~1", but another file is existing named "TestWeb" with short name ""TESTWE~1"
+ return true;
}
return false;
}
@@ -639,16 +788,16 @@ public:
{
const Zstring longName = afterLast(getFilenameFmt(filePath, ::GetLongPathName), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL); //throw() returns empty string on error
- unrelatedFile = beforeLast(filePath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE);
- if (!unrelatedFile.empty())
- unrelatedFile += FILE_NAME_SEPARATOR;
- unrelatedFile += longName;
+ Opt<Zstring> parentPath = getParentFolderPath(filePath);
+ assert(parentPath);
+ unrelatedFilePath_ = parentPath ? appendSeparator(*parentPath) : Zstring();
+ unrelatedFilePath_ += longName;
//find another name in short format: this ensures the actual short name WILL be renamed as well!
- unrelatedFileParked = findUnused8Dot3Name(filePath);
+ parkedFilePath_ = findUnused8Dot3Name(filePath); //throw FileError
//move already existing short name out of the way for now
- renameFile_sub(unrelatedFile, unrelatedFileParked); //throw FileError, ErrorDifferentVolume
+ renameFile_sub(unrelatedFilePath_, parkedFilePath_); //throw FileError, ErrorDifferentVolume
//DON'T call renameFile() to avoid reentrance!
}
@@ -657,13 +806,13 @@ public:
//the file system should assign this unrelated file a new (unique) short name
try
{
- renameFile_sub(unrelatedFileParked, unrelatedFile); //throw FileError, ErrorDifferentVolume
+ renameFile_sub(parkedFilePath_, unrelatedFilePath_); //throw FileError, ErrorDifferentVolume
}
catch (FileError&) {}
}
private:
- Zstring unrelatedFile;
- Zstring unrelatedFileParked;
+ Zstring unrelatedFilePath_;
+ Zstring parkedFilePath_;
};
#endif
}
@@ -752,51 +901,52 @@ void setFileTimeByHandle(HANDLE hFile, //throw FileError
std::wstring errorMsg = replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(filePath));
//add more meaningful message: FAT accepts only a subset of the NTFS date range
+ if (ec == ERROR_INVALID_PARAMETER)
#ifdef ZEN_WIN_VISTA_AND_LATER
- if (ec == ERROR_INVALID_PARAMETER && isFatDrive(hFile))
+ if (getFatType(hFile) != FatType::NONE) //exFAT has the same date range like FAT/FAT32: http://www.freefilesync.org/forum/viewtopic.php?t=4051
#else
- if (ec == ERROR_INVALID_PARAMETER && isFatDrive(filePath))
+ if (getFatType(filePath) != FatType::NONE)
#endif
- {
- //let's not fail due to an invalid creation time on FAT: http://www.freefilesync.org/forum/viewtopic.php?t=2278
- if (creationTime) //retry (single-level recursion at most!)
- return setFileTimeByHandle(hFile, nullptr, lastWriteTime, filePath); //throw FileError
-
- //if the ERROR_INVALID_PARAMETER is due to an invalid date, enhance message:
- const LARGE_INTEGER writeTimeInt = toLargeInteger(lastWriteTime);
- if (writeTimeInt.QuadPart < 0x01a8e79fe1d58000 || //1980-01-01 https://en.wikipedia.org/wiki/Time_formatting_and_storage_bugs#Year_2100
- writeTimeInt.QuadPart >= 0x022f716377640000) //2100-01-01
{
- errorMsg += L"\nA FAT volume can only store dates from 1980 to 2099:\n" "\twrite time (UTC):";
- SYSTEMTIME st = {};
- if (::FileTimeToSystemTime(&lastWriteTime, //__in const FILETIME *lpFileTime,
- &st)) //__out LPSYSTEMTIME lpSystemTime
+ //let's not fail due to an invalid creation time on FAT: http://www.freefilesync.org/forum/viewtopic.php?t=2278
+ if (creationTime) //retry (single-level recursion at most!)
+ return setFileTimeByHandle(hFile, nullptr, lastWriteTime, filePath); //throw FileError
+
+ //if the ERROR_INVALID_PARAMETER is due to an invalid date, enhance message:
+ const LARGE_INTEGER writeTimeInt = toLargeInteger(lastWriteTime);
+ if (writeTimeInt.QuadPart < 0x01a8e79fe1d58000 || //1980-01-01 https://en.wikipedia.org/wiki/Time_formatting_and_storage_bugs#Year_2100
+ writeTimeInt.QuadPart >= 0x022f716377640000) //2100-01-01
{
- //we need a low-level reliable routine to format a potentially invalid date => don't use strftime!!!
- int bufferSize = ::GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, nullptr, 0);
- if (bufferSize > 0)
- {
- std::vector<wchar_t> buffer(bufferSize);
- if (::GetDateFormat(LOCALE_USER_DEFAULT, //_In_ LCID Locale,
- 0, //_In_ DWORD dwFlags,
- &st, //_In_opt_ const SYSTEMTIME *lpDate,
- nullptr, //_In_opt_ LPCTSTR lpFormat,
- &buffer[0], //_Out_opt_ LPTSTR lpDateStr,
- bufferSize) > 0) //_In_ int cchDate
- errorMsg += std::wstring(L" ") + &buffer[0]; //GetDateFormat() returns char count *including* 0-termination!
- }
-
- bufferSize = ::GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, nullptr, 0);
- if (bufferSize > 0)
+ errorMsg += L"\nA FAT volume can only store dates from 1980 to 2099:\n" "\twrite time (UTC):";
+ SYSTEMTIME st = {};
+ if (::FileTimeToSystemTime(&lastWriteTime, //__in const FILETIME *lpFileTime,
+ &st)) //__out LPSYSTEMTIME lpSystemTime
{
- std::vector<wchar_t> buffer(bufferSize);
- if (::GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, &buffer[0], bufferSize) > 0)
- errorMsg += std::wstring(L" ") + &buffer[0]; //GetDateFormat() returns char count *including* 0-termination!
+ //we need a low-level reliable routine to format a potentially invalid date => don't use strftime!!!
+ int bufferSize = ::GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, nullptr, 0);
+ if (bufferSize > 0)
+ {
+ std::vector<wchar_t> buffer(bufferSize);
+ if (::GetDateFormat(LOCALE_USER_DEFAULT, //_In_ LCID Locale,
+ 0, //_In_ DWORD dwFlags,
+ &st, //_In_opt_ const SYSTEMTIME *lpDate,
+ nullptr, //_In_opt_ LPCTSTR lpFormat,
+ &buffer[0], //_Out_opt_ LPTSTR lpDateStr,
+ bufferSize) > 0) //_In_ int cchDate
+ errorMsg += std::wstring(L" ") + &buffer[0]; //GetDateFormat() returns char count *including* 0-termination!
+ }
+
+ bufferSize = ::GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, nullptr, 0);
+ if (bufferSize > 0)
+ {
+ std::vector<wchar_t> buffer(bufferSize);
+ if (::GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, &buffer[0], bufferSize) > 0)
+ errorMsg += std::wstring(L" ") + &buffer[0]; //GetDateFormat() returns char count *including* 0-termination!
+ }
}
+ errorMsg += L" (" + numberTo<std::wstring>(writeTimeInt.QuadPart) + L")"; //just in case the above date formatting fails
}
- errorMsg += L" (" + numberTo<std::wstring>(writeTimeInt.QuadPart) + L")"; //just in case the above date formatting fails
}
- }
throw FileError(errorMsg, formatSystemError(L"SetFileTime", ec));
}
@@ -1200,9 +1350,12 @@ void copyItemPermissions(const Zstring& sourcePath, const Zstring& targetPath, P
//in contrast to ::SetSecurityInfo(), ::SetFileSecurity() seems to honor the "inherit DACL/SACL" flags
//CAVEAT: if a file system does not support ACLs, GetFileSecurity() will return successfully with a *valid* security descriptor containing *no* ACL entries!
+ const bool isSymlinkSource = getItemType(sourcePath) == ItemType::SYMLINK; //throw FileError
+ const bool isSymlinkTarget = getItemType(targetPath) == ItemType::SYMLINK; //throw FileError
+
//NOTE: ::GetFileSecurity()/::SetFileSecurity() do NOT follow Symlinks! getResolvedSymlinkPath() requires Vista or later!
- const Zstring sourceResolved = procSl == ProcSymlink::FOLLOW && symlinkExists(sourcePath) ? getResolvedSymlinkPath(sourcePath) : sourcePath; //throw FileError
- const Zstring targetResolved = procSl == ProcSymlink::FOLLOW && symlinkExists(targetPath) ? getResolvedSymlinkPath(targetPath) : targetPath; //
+ const Zstring sourceResolved = procSl == ProcSymlink::FOLLOW && isSymlinkSource ? getResolvedSymlinkPath(sourcePath) : sourcePath; //throw FileError
+ const Zstring targetResolved = procSl == ProcSymlink::FOLLOW && isSymlinkTarget ? getResolvedSymlinkPath(targetPath) : targetPath; //
//setting privileges requires admin rights!
try
@@ -1371,7 +1524,8 @@ void copyItemPermissions(const Zstring& sourcePath, const Zstring& targetPath, P
if (::lchown(targetPath.c_str(), fileInfo.st_uid, fileInfo.st_gid) != 0) // may require admin rights!
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write permissions of %x."), L"%x", fmtPath(targetPath)), L"lchown");
- if (!symlinkExists(targetPath) && //setting access permissions doesn't make sense for symlinks on Linux: there is no lchmod()
+ const bool isSymlinkTarget = getItemType(targetPath) == ItemType::SYMLINK; //throw FileError
+ if (!isSymlinkTarget && //setting access permissions doesn't make sense for symlinks on Linux: there is no lchmod()
::chmod(targetPath.c_str(), fileInfo.st_mode) != 0)
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write permissions of %x."), L"%x", fmtPath(targetPath)), L"chmod");
}
@@ -1405,66 +1559,46 @@ void copyItemPermissions(const Zstring& sourcePath, const Zstring& targetPath, P
}
#endif
}
+}
-void makeDirectoryRecursivelyImpl(const Zstring& dirPath) //FileError
+void zen::createDirectoryIfMissingRecursion(const Zstring& dirPath) //throw FileError
{
- assert(!endsWith(dirPath, FILE_NAME_SEPARATOR)); //even "C:\" should be "C:" as input!
+ if (!getParentFolderPath(dirPath)) //device root
+ return static_cast<void>(/*ItemType =*/ getItemType(dirPath)); //throw FileError
try
{
- copyNewDirectory(Zstring(), dirPath, false /*copyFilePermissions*/); //throw FileError, ErrorTargetExisting, ErrorTargetPathMissing
+ copyNewDirectory(Zstring(), dirPath, false /*copyFilePermissions*/); //throw FileError, ErrorTargetExisting
}
- catch (const ErrorTargetExisting&) {} //*something* existing: folder or FILE!
- catch (const ErrorTargetPathMissing&)
+ catch (FileError&)
{
- //we need to create parent directories first
- const Zstring parentPath = beforeLast(dirPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE);
- if (!parentPath.empty())
- {
- //recurse...
- makeDirectoryRecursivelyImpl(parentPath); //throw FileError
+ Opt<PathDetails> pd;
+ try { pd = getPathDetails(dirPath); /*throw FileError*/ }
+ catch (FileError&) {} //previous exception is more relevant
- //now try again...
- copyNewDirectory(Zstring(), dirPath, false /*copyFilePermissions*/); //throw FileError, (ErrorTargetExisting), (ErrorTargetPathMissing)
+ if (pd && pd->existingType != ItemType::FILE)
+ {
+ Zstring intermediatePath = pd->existingPath;
+ for (const Zstring& itemName : pd->relPath)
+ {
+ intermediatePath = appendSeparator(intermediatePath) + itemName;
+ copyNewDirectory(Zstring(), intermediatePath, false /*copyFilePermissions*/); //throw FileError, (ErrorTargetExisting)
+ }
return;
}
throw;
}
}
-}
-
-
-void zen::makeDirectoryRecursively(const Zstring& dirPath) //throw FileError
-{
- //remove trailing separator (even for C:\ root directories)
- const Zstring dirFormatted = endsWith(dirPath, FILE_NAME_SEPARATOR) ?
- beforeLast(dirPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE) :
- dirPath;
- makeDirectoryRecursivelyImpl(dirFormatted); //FileError
-}
//source path is optional (may be empty)
-void zen::copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath, //throw FileError, ErrorTargetExisting, ErrorTargetPathMissing
+void zen::copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath, //throw FileError, ErrorTargetExisting
bool copyFilePermissions)
{
#ifdef ZEN_WIN
auto getErrorMsg = [](const Zstring& path) { return replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(path)); };
- //special handling for volume root: trying to create existing root directory results in ERROR_ACCESS_DENIED rather than ERROR_ALREADY_EXISTS!
- const Zstring pathPf = appendSeparator(targetPath); //we do not support "C:" to represent a relative path!
- if (pathPf.size() == 3 &&
- isAlpha(pathPf[0]) && pathPf[1] == L':')
- {
- const DWORD ec = somethingExists(pathPf) ? ERROR_ALREADY_EXISTS : ERROR_PATH_NOT_FOUND; //don't use dirExists() => harmonize with ErrorTargetExisting!
- const std::wstring errorDescr = formatSystemError(L"CreateDirectory", ec);
-
- if (ec == ERROR_ALREADY_EXISTS)
- throw ErrorTargetExisting(getErrorMsg(pathPf), errorDescr);
- throw FileError(getErrorMsg(pathPf), errorDescr); //[!] this is NOT a ErrorTargetPathMissing case!
- }
-
//deliberately don't support creating irregular folders like "...." https://social.technet.microsoft.com/Forums/windows/en-US/ffee2322-bb6b-4fdf-86f9-8f93cf1fa6cb/
if (endsWith(targetPath, L' ') ||
endsWith(targetPath, L'.'))
@@ -1498,8 +1632,9 @@ void zen::copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath,
if (ec == ERROR_ALREADY_EXISTS)
throw ErrorTargetExisting(getErrorMsg(targetPath), errorDescr);
- else if (ec == ERROR_PATH_NOT_FOUND)
- throw ErrorTargetPathMissing(getErrorMsg(targetPath), errorDescr);
+ //else if (ec == ERROR_PATH_NOT_FOUND || //the ususal suspect
+ // ec == ERROR_FILE_NOT_FOUND) //Webdav incorrectly returns this one: http://www.freefilesync.org/forum/viewtopic.php?t=4053
+ // throw ErrorTargetPathMissing(getErrorMsg(targetPath), errorDescr);
throw FileError(getErrorMsg(targetPath), errorDescr);
}
}
@@ -1524,8 +1659,8 @@ void zen::copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath,
if (lastError == EEXIST)
throw ErrorTargetExisting(errorMsg, errorDescr);
- else if (lastError == ENOENT)
- throw ErrorTargetPathMissing(errorMsg, errorDescr);
+ //else if (lastError == ENOENT)
+ // throw ErrorTargetPathMissing(errorMsg, errorDescr);
throw FileError(errorMsg, errorDescr);
}
#endif
@@ -1610,7 +1745,7 @@ void zen::copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath,
catch (FileError&) {}
#endif
- ZEN_ON_SCOPE_FAIL(try { removeDirectorySimple(targetPath); }
+ ZEN_ON_SCOPE_FAIL(try { removeDirectoryPlain(targetPath); }
catch (FileError&) {}); //ensure cleanup:
//enforce copying file permissions: it's advertized on GUI...
@@ -1625,11 +1760,13 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool
const Zstring linkPath = getSymlinkTargetRaw(sourceLink); //throw FileError; accept broken symlinks
#ifdef ZEN_WIN
- const bool isDirLink = [&]() -> bool
- {
- const DWORD ret = ::GetFileAttributes(applyLongPathPrefix(sourceLink).c_str());
- return ret != INVALID_FILE_ATTRIBUTES && (ret & FILE_ATTRIBUTE_DIRECTORY);
- }();
+ WIN32_FILE_ATTRIBUTE_DATA sourceAttr = {};
+ if (!::GetFileAttributesEx(applyLongPathPrefix(sourceLink).c_str(), //__in LPCTSTR lpFileName,
+ GetFileExInfoStandard, //__in GET_FILEEX_INFO_LEVELS fInfoLevelId,
+ &sourceAttr)) //__out LPVOID lpFileInformation
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(sourceLink)), L"GetFileAttributesEx");
+
+ const bool isDirLink = (sourceAttr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
using CreateSymbolicLinkFunc = BOOLEAN (WINAPI*)(LPCTSTR lpSymlinkFileName, LPCTSTR lpTargetFileName, DWORD dwFlags);
const SysDllFun<CreateSymbolicLinkFunc> createSymbolicLink(L"kernel32.dll", "CreateSymbolicLinkW");
@@ -1649,30 +1786,11 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool
THROW_LAST_FILE_ERROR(replaceCpy(replaceCpy(_("Cannot copy symbolic link %x to %y."), L"%x", L"\n" + fmtPath(sourceLink)), L"%y", L"\n" + fmtPath(targetLink)), functionName);
//allow only consistent objects to be created -> don't place before ::symlink, targetLink may already exist!
-
- auto cleanUp = [&]
- {
- try
- {
-#ifdef ZEN_WIN
- if (isDirLink)
- removeDirectorySimple(targetLink); //throw FileError
- else
-#endif
- removeFile(targetLink); //throw FileError
- }
- catch (FileError&) {}
- };
- ZEN_ON_SCOPE_FAIL(cleanUp());
+ ZEN_ON_SCOPE_FAIL(try { removeSymlinkPlain(targetLink); /*throw FileError*/ }
+ catch (FileError&) {});
//file times: essential for sync'ing a symlink: enforce this! (don't just try!)
#ifdef ZEN_WIN
- WIN32_FILE_ATTRIBUTE_DATA sourceAttr = {};
- if (!::GetFileAttributesEx(applyLongPathPrefix(sourceLink).c_str(), //__in LPCTSTR lpFileName,
- GetFileExInfoStandard, //__in GET_FILEEX_INFO_LEVELS fInfoLevelId,
- &sourceAttr)) //__out LPVOID lpFileInformation
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(sourceLink)), L"GetFileAttributesEx");
-
setWriteTimeNative(targetLink, sourceAttr.ftLastWriteTime, &sourceAttr.ftCreationTime, ProcSymlink::DIRECT); //throw FileError
#else
@@ -1924,8 +2042,6 @@ InSyncAttributes copyFileWindowsStream(const Zstring& sourceFile, //throw FileEr
ec == ERROR_ALREADY_EXISTS) //comment on msdn claims, this one is used on Windows Mobile 6
throw ErrorTargetExisting(errorMsg, errorDescr);
- //if (ec == ERROR_PATH_NOT_FOUND) throw ErrorTargetPathMissing(errorMsg, errorDescr);
-
throw FileError(errorMsg, errorDescr);
}
#ifdef ZEN_WIN_VISTA_AND_LATER
@@ -1943,8 +2059,8 @@ InSyncAttributes copyFileWindowsStream(const Zstring& sourceFile, //throw FileEr
assert(false);
);
#else
- ZEN_ON_SCOPE_FAIL(try { removeFile(targetFile); }
- catch (FileError&) {} ); //transactional behavior: guard just after opening target and before managing hFileTarget
+ ZEN_ON_SCOPE_FAIL(try { removeFilePlain(targetFile); }
+ catch (FileError&) {} ); //transactional behavior: guard just after opening target and before managing hFileTarget
FileOutput fileOut(hFileTarget, targetFile); //pass ownership
#endif
@@ -2071,7 +2187,7 @@ InSyncAttributes copyFileWindowsStream(const Zstring& sourceFile, //throw FileEr
}
//time needs to be set at the end: WriteFile/BackupWrite() change modification time
- setFileTimeByHandle(fileOut.getHandle(), &sourceInfo.ftCreationTime,sourceInfo.ftLastWriteTime, targetFile); //throw FileError
+ setFileTimeByHandle(fileOut.getHandle(), &sourceInfo.ftCreationTime, sourceInfo.ftLastWriteTime, targetFile); //throw FileError
return newAttrib;
}
@@ -2206,7 +2322,7 @@ InSyncAttributes copyFileWindowsDefault(const Zstring& sourceFile, //throw FileE
try { activatePrivilege(PrivilegeName::RESTORE); }
catch (const FileError&) { backupPrivilegesActive = false; }
- auto guardTarget = zen::makeGuard<ScopeGuardRunMode::ON_FAIL>([&] { try { removeFile(targetFile); } catch (FileError&) {} });
+ auto guardTarget = zen::makeGuard<ScopeGuardRunMode::ON_FAIL>([&] { try { removeFilePlain(targetFile); } catch (FileError&) {} });
//transactional behavior: guard just before starting copy, we don't trust ::CopyFileEx(), do we? ;)
DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS;
@@ -2277,16 +2393,20 @@ InSyncAttributes copyFileWindowsDefault(const Zstring& sourceFile, //throw FileE
throw ErrorTargetExisting(errorMsg, errorDescr);
}
- //if (lastError == ERROR_PATH_NOT_FOUND) throw ErrorTargetPathMissing(errorMsg, errorDescr); //could this also be source path missing!?
+ //lastError == ERROR_PATH_NOT_FOUND: could this also be source path missing!?
try //add more meaningful message
{
//trying to copy > 4GB file to FAT/FAT32 volume gives obscure ERROR_INVALID_PARAMETER (FAT can indeed handle files up to 4 Gig, tested!)
- if (ec == ERROR_INVALID_PARAMETER &&
- isFatDrive(targetFile) &&
- getFilesize(sourceFile) >= 4U * std::uint64_t(1024U * 1024 * 1024)) //throw FileError
- errorDescr += L"\nFAT volumes cannot store files larger than 4 gigabytes.";
- //see "Limitations of the FAT32 File System": http://support.microsoft.com/kb/314463/en-us
+ if (ec == ERROR_INVALID_PARAMETER)
+ {
+ const FatType fatType = getFatType(targetFile);
+ if ((fatType == FatType::FAT ||
+ fatType == FatType::FAT32) && //no problem for exFAT (limit ca. 128 PB)
+ getFilesize(sourceFile) >= 4U * std::uint64_t(1024U * 1024 * 1024)) //throw FileError
+ errorDescr += L"\nFAT volumes cannot store files larger than 4 gigabytes.";
+ //see "Limitations of the FAT32 File System": http://support.microsoft.com/kb/314463/en-us
+ }
//note: ERROR_INVALID_PARAMETER can also occur when copying to a SharePoint server or MS SkyDrive and the target file path is of a restricted type.
}
@@ -2378,7 +2498,7 @@ InSyncAttributes copyFileOsSpecific(const Zstring& sourceFile, //throw FileError
throw FileError(errorMsg, errorDescr);
}
- ZEN_ON_SCOPE_FAIL( try { removeFile(targetFile); }
+ ZEN_ON_SCOPE_FAIL( try { removeFilePlain(targetFile); }
catch (FileError&) {} );
//transactional behavior: place guard after ::open() and before lifetime of FileOutput:
//=> don't delete file that existed previously!!!
@@ -2459,7 +2579,7 @@ InSyncAttributes zen::copyNewFile(const Zstring& sourceFile, const Zstring& targ
const InSyncAttributes attr = copyFileOsSpecific(sourceFile, targetFile, notifyProgress); //throw FileError, ErrorTargetExisting, ErrorFileLocked
//at this point we know we created a new file, so it's fine to delete it for cleanup!
- ZEN_ON_SCOPE_FAIL(try { removeFile(targetFile); }
+ ZEN_ON_SCOPE_FAIL(try { removeFilePlain(targetFile); }
catch (FileError&) {});
if (copyFilePermissions)
diff --git a/zen/file_access.h b/zen/file_access.h
index fdb787bd..0586ea8f 100644
--- a/zen/file_access.h
+++ b/zen/file_access.h
@@ -17,17 +17,40 @@ namespace zen
{
//note: certain functions require COM initialization! (vista_file_op.h)
+Opt<Zstring> getParentFolderPath(const Zstring& itemPath);
+
+//POSITIVE existence checks; if negative: 1. item not existing 2. different type 3.access error or similar
+bool fileAvailable(const Zstring& filePath); //noexcept
+bool dirAvailable (const Zstring& dirPath ); //
+
+
bool fileExists (const Zstring& filePath); //noexcept; check whether file or file-symlink exists
bool dirExists (const Zstring& dirPath ); //noexcept; check whether directory or dir-symlink exists
-bool symlinkExists (const Zstring& linkPath); //noexcept; check whether a symbolic link exists
-bool somethingExists(const Zstring& itemPath); //noexcept; check whether any object with this name exists
+
+enum class ItemType
+{
+ FILE,
+ FOLDER,
+ SYMLINK,
+};
+//(hopefully) fast: does not distinguish between error/not existing
+ItemType getItemType (const Zstring& itemPath); //throw FileError
+//execute potentially SLOW folder traversal but distinguish error/not existing
+Opt<ItemType> getItemTypeIfExists(const Zstring& itemPath); //throw FileError
+
+struct PathDetails
+{
+ ItemType existingType;
+ Zstring existingPath; //itemPath =: existingPath + relPath
+ std::vector<Zstring> relPath; //
+};
+PathDetails getPathDetails(const Zstring& itemPath); //throw FileError
enum class ProcSymlink
{
DIRECT,
FOLLOW
};
-
void setFileTime(const Zstring& filePath, std::int64_t modificationTime, ProcSymlink procSl); //throw FileError
//symlink handling: always evaluate target
@@ -37,11 +60,10 @@ VolumeId getVolumeId(const Zstring& itemPath); //throw FileError
//get per-user directory designated for temporary files:
Zstring getTempFolderPath(); //throw FileError
-bool removeFile(const Zstring& filePath); //throw FileError; return "false" if file is not existing
-
-void removeDirectorySimple(const Zstring& dirPath); //throw FileError
-
-void removeDirectoryRecursively(const Zstring& dirPath); //throw FileError
+void removeFilePlain (const Zstring& filePath); //throw FileError; ERROR if not existing
+void removeSymlinkPlain (const Zstring& linkPath); //throw FileError; ERROR if not existing
+void removeDirectoryPlain(const Zstring& dirPath ); //throw FileError; ERROR if not existing
+void removeDirectoryPlainRecursion(const Zstring& dirPath); //throw FileError; ERROR if not existing
//rename file or directory: no copying!!!
void renameFile(const Zstring& itemPathOld, const Zstring& itemPathNew); //throw FileError, ErrorDifferentVolume, ErrorTargetExisting
@@ -50,11 +72,11 @@ bool supportsPermissions(const Zstring& dirPath); //throw FileError, dereference
//- no error if already existing
//- create recursively if parent directory is not existing
-void makeDirectoryRecursively(const Zstring& dirPath); //throw FileError
+void createDirectoryIfMissingRecursion(const Zstring& dirPath); //throw FileError
//fail if already existing or parent directory not existing:
//source path is optional (may be empty)
-void copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath, bool copyFilePermissions); //throw FileError, ErrorTargetExisting, ErrorTargetPathMissing
+void copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath, bool copyFilePermissions); //throw FileError, ErrorTargetExisting
void copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool copyFilePermissions); //throw FileError
diff --git a/zen/file_error.h b/zen/file_error.h
index 374d0b2c..aa41040d 100644
--- a/zen/file_error.h
+++ b/zen/file_error.h
@@ -31,7 +31,7 @@ private:
#define DEFINE_NEW_FILE_ERROR(X) struct X : public FileError { X(const std::wstring& msg) : FileError(msg) {} X(const std::wstring& msg, const std::wstring& descr) : FileError(msg, descr) {} };
DEFINE_NEW_FILE_ERROR(ErrorTargetExisting);
-DEFINE_NEW_FILE_ERROR(ErrorTargetPathMissing);
+//DEFINE_NEW_FILE_ERROR(ErrorTargetPathMissing);
DEFINE_NEW_FILE_ERROR(ErrorFileLocked);
DEFINE_NEW_FILE_ERROR(ErrorDifferentVolume);
diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp
index 3eb284e1..ef6d255c 100644
--- a/zen/file_traverser.cpp
+++ b/zen/file_traverser.cpp
@@ -28,8 +28,8 @@ using namespace zen;
void zen::traverseFolder(const Zstring& dirPath,
const std::function<void (const FileInfo& fi)>& onFile,
- const std::function<void (const DirInfo& di)>& onDir,
- const std::function<void (const SymlinkInfo& si)>& onLink,
+ const std::function<void (const FolderInfo& fi)>& onFolder,
+ const std::function<void (const SymlinkInfo& si)>& onSymlink,
const std::function<void (const std::wstring& errorMsg)>& onError)
{
try
@@ -41,12 +41,15 @@ void zen::traverseFolder(const Zstring& dirPath,
{
const DWORD ec = ::GetLastError(); //copy before directly/indirectly making other system calls!
if (ec == ERROR_FILE_NOT_FOUND)
- {
- //1. directory may not exist *or* 2. it is completely empty: not all directories contain "., .." entries, e.g. a drive's root directory; NetDrive
- // -> FindFirstFile() is a nice example of violation of API design principle of single responsibility
- if (dirExists(dirPath)) //yes, a race-condition, still the best we can do
- return;
- }
+ try
+ {
+ //1. directory may not exist *or* 2. it is completely empty: not all directories contain "., .." entries, e.g. a drive's root directory; NetDrive
+ // -> FindFirstFile() is a nice example of violating the API design principle of single responsibility
+ if (getItemType(dirPath) == ItemType::FOLDER) //throw FileError
+ return;
+ }
+ catch (FileError&) {} //previous exception is more relevant
+
throw FileError(replaceCpy(_("Cannot open directory %x."), L"%x", fmtPath(dirPath)), formatSystemError(L"FindFirstFile", ec));
}
ZEN_ON_SCOPE_EXIT(::FindClose(hDir));
@@ -75,22 +78,23 @@ void zen::traverseFolder(const Zstring& dirPath,
if (itemNameRaw[0] == 0)
throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), L"FindNextFile: Data corruption; item with empty name.");
- const Zstring& itemPath = appendSeparator(dirPath) + itemNameRaw;
+ const Zstring& itemName = itemNameRaw;
+ const Zstring& itemPath = appendSeparator(dirPath) + itemName;
if (zen::isSymlink(findData)) //check first!
{
- if (onLink)
- onLink({ itemPath, filetimeToTimeT(findData.ftLastWriteTime) });
+ if (onSymlink)
+ onSymlink({ itemName, itemPath, filetimeToTimeT(findData.ftLastWriteTime) });
}
else if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
- if (onDir)
- onDir({ itemPath });
+ if (onFolder)
+ onFolder({ itemName, itemPath });
}
else //a file
{
if (onFile)
- onFile({ itemPath, get64BitUInt(findData.nFileSizeLow, findData.nFileSizeHigh), filetimeToTimeT(findData.ftLastWriteTime) });
+ onFile({ itemName, itemPath, get64BitUInt(findData.nFileSizeLow, findData.nFileSizeHigh), filetimeToTimeT(findData.ftLastWriteTime) });
}
}
@@ -159,18 +163,18 @@ void zen::traverseFolder(const Zstring& dirPath,
if (S_ISLNK(statData.st_mode)) //on Linux there is no distinction between file and directory symlinks!
{
- if (onLink)
- onLink({ itemPath, statData.st_mtime});
+ if (onSymlink)
+ onSymlink({ itemName, itemPath, statData.st_mtime});
}
else if (S_ISDIR(statData.st_mode)) //a directory
{
- if (onDir)
- onDir({ itemPath });
+ if (onFolder)
+ onFolder({ itemName, itemPath });
}
else //a file or named pipe, ect.
{
if (onFile)
- onFile({ itemPath, makeUnsigned(statData.st_size), statData.st_mtime });
+ onFile({ itemName, itemPath, makeUnsigned(statData.st_size), statData.st_mtime });
}
/*
It may be a good idea to not check "S_ISREG(statData.st_mode)" explicitly and to not issue an error message on other types to support these scenarios:
diff --git a/zen/file_traverser.h b/zen/file_traverser.h
index 5fffe0e2..1badddf9 100644
--- a/zen/file_traverser.h
+++ b/zen/file_traverser.h
@@ -16,19 +16,22 @@ namespace zen
{
struct FileInfo
{
- const Zstring& fullPath;
+ Zstring itemName;
+ Zstring fullPath;
std::uint64_t fileSize; //[bytes]
std::int64_t lastWriteTime; //number of seconds since Jan. 1st 1970 UTC
};
-struct DirInfo
+struct FolderInfo
{
- const Zstring& fullPath;
+ Zstring itemName;
+ Zstring fullPath;
};
struct SymlinkInfo
{
- const Zstring& fullPath;
+ Zstring itemName;
+ Zstring fullPath;
std::int64_t lastWriteTime; //number of seconds since Jan. 1st 1970 UTC
};
@@ -36,8 +39,8 @@ struct SymlinkInfo
//- directory path may end with PATH_SEPARATOR
void traverseFolder(const Zstring& dirPath, //noexcept
const std::function<void (const FileInfo& fi)>& onFile, //
- const std::function<void (const DirInfo& di)>& onDir, //optional
- const std::function<void (const SymlinkInfo& si)>& onLink, //
+ const std::function<void (const FolderInfo& fi)>& onFolder, //optional
+ const std::function<void (const SymlinkInfo& si)>& onSymlink, //
const std::function<void (const std::wstring& errorMsg)>& onError); //
}
diff --git a/zen/fixed_list.h b/zen/fixed_list.h
index 81197eb4..27eb488c 100644
--- a/zen/fixed_list.h
+++ b/zen/fixed_list.h
@@ -139,8 +139,8 @@ public:
void swap(FixedList& other)
{
std::swap(firstInsert_, other.firstInsert_);
- std::swap(lastInsert_ , other.lastInsert_);
- std::swap(sz_ , other.sz_);
+ std::swap(lastInsert_, other.lastInsert_);
+ std::swap(sz_, other.sz_);
}
private:
@@ -194,7 +194,7 @@ public:
};
using value_type = T;
- using iterator = FixedIterator<typename std::vector<std::unique_ptr<T>>::iterator , T>;
+ using iterator = FixedIterator<typename std::vector<std::unique_ptr<T>>::iterator, T>;
using const_iterator = FixedIterator<typename std::vector<std::unique_ptr<T>>::const_iterator, const T>;
using reference = T&;
using const_reference = const T&;
diff --git a/zen/recycler.cpp b/zen/recycler.cpp
index 7f9e0a01..d8ee58c4 100644
--- a/zen/recycler.cpp
+++ b/zen/recycler.cpp
@@ -29,9 +29,8 @@ using namespace zen;
#ifdef ZEN_WIN
-void zen::recycleOrDelete(const std::vector<Zstring>& itempaths, const std::function<void (const std::wstring& displayPath)>& onRecycleItem)
+void zen::recycleOrDeleteIfExists(const std::vector<Zstring>& itemPaths, const std::function<void (const std::wstring& displayPath)>& onRecycleItem)
{
- if (itempaths.empty()) return;
//warning: moving long file paths to recycler does not work!
//both ::SHFileOperation() and ::IFileOperation cannot delete a folder named "System Volume Information" with normal attributes but shamelessly report success
//both ::SHFileOperation() and ::IFileOperation can't handle \\?\-prefix!
@@ -48,21 +47,25 @@ void zen::recycleOrDelete(const std::vector<Zstring>& itempaths, const std::func
Nevertheless, let's use IFileOperation for better error reporting (including details on locked files)!
*/
-#ifdef ZEN_WIN_VISTA_AND_LATER
- vista::moveToRecycleBin(itempaths, onRecycleItem); //throw FileError
+
+#ifdef ZEN_WIN_VISTA_AND_LATER //Win Vista recycle bin usage: 1. good error reporting 2. late failure
+ vista::moveToRecycleBinIfExists(itemPaths, onRecycleItem); //throw FileError
#else //regular recycle bin usage: available since XP: 1. bad error reporting 2. early failure
- Zstring itempathsDoubleNull;
- for (const Zstring& itempath : itempaths)
+ //TODO: this XP version fails if any item is not existing violating this function's API
+ if (itemPaths.empty()) return;
+
+ Zstring itemPathsDoubleNull;
+ for (const Zstring& itemPath : itemPaths)
{
- itempathsDoubleNull += itempath;
- itempathsDoubleNull += L'\0';
+ itemPathsDoubleNull += itemPath;
+ itemPathsDoubleNull += L'\0';
}
SHFILEOPSTRUCT fileOp = {};
fileOp.hwnd = nullptr;
fileOp.wFunc = FO_DELETE;
- fileOp.pFrom = itempathsDoubleNull.c_str();
+ fileOp.pFrom = itemPathsDoubleNull.c_str();
fileOp.pTo = nullptr;
fileOp.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
fileOp.fAnyOperationsAborted = false;
@@ -70,10 +73,10 @@ void zen::recycleOrDelete(const std::vector<Zstring>& itempaths, const std::func
fileOp.lpszProgressTitle = nullptr;
//"You should use fully-qualified path names with this function. Using it with relative path names is not thread safe."
- if (::SHFileOperation(&fileOp) != 0 || fileOp.fAnyOperationsAborted)
+ if (::SHFileOperation(&fileOp) != 0 || fileOp.fAnyOperationsAborted) //fails if items are not existing!
{
- std::wstring itempathFmt = fmtPath(itempaths[0]); //probably not the correct file name for file lists larger than 1!
- if (itempaths.size() > 1)
+ std::wstring itempathFmt = fmtPath(itemPaths[0]); //probably not the correct file name for file lists larger than 1!
+ if (itemPaths.size() > 1)
itempathFmt += L", ..."; //give at least some hint that there are multiple files, and the error need not be related to the first one
throw FileError(replaceCpy(_("Unable to move %x to the recycle bin."), L"%x", itempathFmt));
}
@@ -82,16 +85,37 @@ void zen::recycleOrDelete(const std::vector<Zstring>& itempaths, const std::func
#endif
-bool zen::recycleOrDelete(const Zstring& itempath) //throw FileError
+bool zen::recycleOrDeleteIfExists(const Zstring& itemPath) //throw FileError
{
- if (!somethingExists(itempath)) //[!] do not optimize away, OS X needs this for reliable detection of "recycle bin missing"
- return false; //neither file nor any other object with that name existing: no error situation, manual deletion relies on it!
-
#ifdef ZEN_WIN
- recycleOrDelete({ itempath }, nullptr); //throw FileError
+#ifdef ZEN_WIN_VISTA_AND_LATER
+ return vista::moveToRecycleBinIfExists({ itemPath }, nullptr) != 0; //throw FileError
+
+#else
+ Zstring itemPathDoubleNull = itemPath;
+ itemPathDoubleNull += L'\0';
+
+ SHFILEOPSTRUCT fileOp = {};
+ fileOp.wFunc = FO_DELETE;
+ fileOp.pFrom = itemPathDoubleNull.c_str();
+ fileOp.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
+
+ if (::SHFileOperation(&fileOp) != 0 || fileOp.fAnyOperationsAborted) //fails if item is not existing!
+ {
+ try
+ {
+ if (!getItemTypeIfExists(itemPath)) //throw FileError
+ return false;
+ }
+ catch (FileError&) {} //previous exception is more relevant
+
+ throw FileError(replaceCpy(_("Unable to move %x to the recycle bin."), L"%x", fmtPath(itemPath)));
+ }
+ return true;
+#endif
#elif defined ZEN_LINUX
- GFile* file = ::g_file_new_for_path(itempath.c_str()); //never fails according to docu
+ GFile* file = ::g_file_new_for_path(itemPath.c_str()); //never fails according to docu
ZEN_ON_SCOPE_EXIT(g_object_unref(file);)
GError* error = nullptr;
@@ -99,38 +123,38 @@ bool zen::recycleOrDelete(const Zstring& itempath) //throw FileError
if (!::g_file_trash(file, nullptr, &error))
{
- const std::wstring errorMsg = replaceCpy(_("Unable to move %x to the recycle bin."), L"%x", fmtPath(itempath));
+ const Opt<ItemType> type = getItemTypeIfExists(itemPath); //throw FileError
+ if (!type)
+ return false;
+ const std::wstring errorMsg = replaceCpy(_("Unable to move %x to the recycle bin."), L"%x", fmtPath(itemPath));
if (!error)
throw FileError(errorMsg, L"g_file_trash: unknown error."); //user should never see this
//implement same behavior as in Windows: if recycler is not existing, delete permanently
if (error->code == G_IO_ERROR_NOT_SUPPORTED)
{
- struct ::stat fileInfo = {};
- if (::lstat(itempath.c_str(), &fileInfo) != 0)
- return false;
-
- if (S_ISLNK(fileInfo.st_mode) || S_ISREG(fileInfo.st_mode))
- removeFile(itempath); //throw FileError
- else if (S_ISDIR(fileInfo.st_mode))
- removeDirectoryRecursively(itempath); //throw FileError
+ if (*type == ItemType::FOLDER)
+ removeDirectoryPlainRecursion(itemPath); //throw FileError
+ else
+ removeFilePlain(itemPath); //throw FileError
return true;
}
throw FileError(errorMsg, replaceCpy<std::wstring>(L"Glib Error Code %x:", L"%x", numberTo<std::wstring>(error->code)) + L" " + utfCvrtTo<std::wstring>(error->message));
//g_quark_to_string(error->domain)
}
+ return true;
#elif defined ZEN_MAC
//we cannot use FSPathMoveObjectToTrashSync directly since it follows symlinks!
static_assert(sizeof(Zchar) == sizeof(char), "");
- const UInt8* itempathUtf8 = reinterpret_cast<const UInt8*>(itempath.c_str());
+ const UInt8* itemPathUtf8 = reinterpret_cast<const UInt8*>(itemPath.c_str());
auto throwFileError = [&](OSStatus oss)
{
- const std::wstring errorMsg = replaceCpy(_("Unable to move %x to the recycle bin."), L"%x", fmtPath(itempath));
+ const std::wstring errorMsg = replaceCpy(_("Unable to move %x to the recycle bin."), L"%x", fmtPath(itemPath));
std::wstring errorDescr = L"OSStatus Code " + numberTo<std::wstring>(oss);
if (const char* description = ::GetMacOSStatusCommentString(oss)) //found no documentation for proper use of GetMacOSStatusCommentString
@@ -138,8 +162,14 @@ bool zen::recycleOrDelete(const Zstring& itempath) //throw FileError
throw FileError(errorMsg, errorDescr);
};
+ //[!] do not optimize away, OS X needs this for reliable detection of "recycle bin unsupported"
+ //both "not supported" and "item missing" let FSMoveObjectToTrashSync fail with -120
+ const Opt<ItemType> type = getItemTypeIfExists(itemPath); //throw FileError
+ if (!type)
+ return false;
+
FSRef objectRef = {}; //= POD structure not a pointer type!
- OSStatus rv = ::FSPathMakeRefWithOptions(itempathUtf8, //const UInt8 *path,
+ OSStatus rv = ::FSPathMakeRefWithOptions(itemPathUtf8, //const UInt8 *path,
kFSPathMakeRefDoNotFollowLeafSymlink, //OptionBits options,
&objectRef, //FSRef *ref,
nullptr); //Boolean *isDirectory
@@ -155,21 +185,17 @@ bool zen::recycleOrDelete(const Zstring& itempath) //throw FileError
//implement same behavior as in Windows: if recycler is not existing, delete permanently
if (rv2 == -120) //=="Directory not found or incomplete pathname." but should really be "recycle bin directory not found"!
{
- struct ::stat fileInfo = {};
- if (::lstat(itempath.c_str(), &fileInfo) != 0)
- return false;
-
- if (S_ISLNK(fileInfo.st_mode) || S_ISREG(fileInfo.st_mode))
- removeFile(itempath); //throw FileError
- else if (S_ISDIR(fileInfo.st_mode))
- removeDirectoryRecursively(itempath); //throw FileError
+ if (*type == ItemType::FOLDER)
+ removeDirectoryPlainRecursion(itemPath); //throw FileError
+ else
+ removeFilePlain(itemPath); //throw FileError
return true;
}
throwFileError(rv2);
}
-#endif
return true;
+#endif
}
diff --git a/zen/recycler.h b/zen/recycler.h
index 4a5f4b2b..ec2a8672 100644
--- a/zen/recycler.h
+++ b/zen/recycler.h
@@ -35,7 +35,7 @@ Already included in package "gtk+-2.0"!
//move a file or folder to Recycle Bin (deletes permanently if recycler is not available) -> crappy semantics, but we have no choice thanks to Windows' design
-bool recycleOrDelete(const Zstring& itemPath); //throw FileError, return "true" if file/dir was actually deleted
+bool recycleOrDeleteIfExists(const Zstring& itemPath); //throw FileError, return "true" if file/dir was actually deleted
#ifdef ZEN_WIN
@@ -43,8 +43,8 @@ bool recycleOrDelete(const Zstring& itemPath); //throw FileError, return "true"
//Vista and later: dirPath must exist for a valid check!
bool recycleBinExists(const Zstring& dirPath, const std::function<void ()>& onUpdateGui); //throw FileError
-void recycleOrDelete(const std::vector<Zstring>& filePaths, //throw FileError, return "true" if file/dir was actually deleted
- const std::function<void (const std::wstring& displayPath)>& onRecycleItem); //optional; currentItem may be empty
+void recycleOrDeleteIfExists(const std::vector<Zstring>& filePaths, //throw FileError
+ const std::function<void (const std::wstring& displayPath)>& onRecycleItem); //optional; currentItem may be empty
#endif
}
diff --git a/zen/serialize.h b/zen/serialize.h
index 7322cb07..290d9200 100644
--- a/zen/serialize.h
+++ b/zen/serialize.h
@@ -126,7 +126,7 @@ struct MemoryStreamIn
return bytesRead;
}
- size_t pos() const { return pos_; }
+ size_t pos() const { return pos_; }
private:
const BinContainer buffer_;
diff --git a/zen/shell_execute.h b/zen/shell_execute.h
index 2f73fc38..b5e04469 100644
--- a/zen/shell_execute.h
+++ b/zen/shell_execute.h
@@ -68,7 +68,7 @@ void shellExecute(const void* /*PCIDLIST_ABSOLUTE*/ shellItemPidl, const std::ws
execInfo.lpIDList = const_cast<void*>(shellItemPidl); //lpIDList is documented as PCIDLIST_ABSOLUTE!
};
- if (!shellExecuteImpl(fillExecInfo , type)) //throw FileError
+ if (!shellExecuteImpl(fillExecInfo, type)) //throw FileError
THROW_LAST_FILE_ERROR(_("Incorrect command line:") + L"\n" + fmtPath(displayPath), L"ShellExecuteEx");
}
#endif
diff --git a/zen/thread.h b/zen/thread.h
index 5bb02a0e..f6c3ae01 100644
--- a/zen/thread.h
+++ b/zen/thread.h
@@ -398,8 +398,8 @@ InterruptibleThread::InterruptibleThread(Function&& f) : intStatus_(std::make_sh
threadCompleted = pFinished.get_future();
stdThread = std::thread([f = std::forward<Function>(f),
- intStatus = this->intStatus_,
- pFinished = std::move(pFinished)]() mutable
+ intStatus = this->intStatus_,
+ pFinished = std::move(pFinished)]() mutable
{
assert(!impl::refThreadLocalInterruptionStatus());
impl::refThreadLocalInterruptionStatus() = intStatus.get();
bgstack15