From a778763851f73ff2b3b9dff222bfddceb33fded1 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Fri, 12 Jun 2015 13:04:00 +0200 Subject: [PATCH] Add trash can file versioning (fixes #1931) --- cmd/syncthing/main.go | 1 + gui/index.html | 41 ++-- .../core/controllers/syncthingController.js | 24 ++- internal/auto/gui.files.go | 6 +- internal/model/model.go | 19 +- internal/versioner/.gitignore | 1 + internal/versioner/trashcan.go | 187 ++++++++++++++++++ internal/versioner/trashcan_test.go | 69 +++++++ 8 files changed, 320 insertions(+), 28 deletions(-) create mode 100644 internal/versioner/.gitignore create mode 100644 internal/versioner/trashcan.go create mode 100644 internal/versioner/trashcan_test.go diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 6ceb60f19..cc472ac88 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -589,6 +589,7 @@ func syncthingMain() { m := model.NewModel(cfg, myID, myName, "syncthing", Version, ldb) cfg.Subscribe(m) + mainSvc.Add(m) if t := os.Getenv("STDEADLOCKTIMEOUT"); len(t) > 0 { it, err := strconv.Atoi(t) diff --git a/gui/index.html b/gui/index.html index eb5f87a2c..af316a448 100644 --- a/gui/index.html +++ b/gui/index.html @@ -263,6 +263,7 @@  File Versioning + Trash Can File Versioning Staggered File Versioning Simple File Versioning External File Versioning @@ -681,27 +682,27 @@
- -
- -
-
- -
-
- -
-
- +  Help + +
+
+

Files are moved to .stversions folder when replaced or deleted by Syncthing.

+ +
+ +
days
+

+ The number of days to keep files in the trash can. Zero means forever. + The number of days must be a number and cannot be blank. + A negative number of days doesn't make sense. +

Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.

diff --git a/gui/scripts/syncthing/core/controllers/syncthingController.js b/gui/scripts/syncthing/core/controllers/syncthingController.js index 1256c951e..403c5a714 100644 --- a/gui/scripts/syncthing/core/controllers/syncthingController.js +++ b/gui/scripts/syncthing/core/controllers/syncthingController.js @@ -521,10 +521,10 @@ angular.module('syncthing.core') if ($scope.model[folderCfg.id].state == 'error') { return 'stopped'; // legacy, the state is called "stopped" in the GUI } - + // after restart syncthing process state may be empty if (!$scope.model[folderCfg.id].state) { - return 'unknown'; + return 'unknown'; } return '' + $scope.model[folderCfg.id].state; @@ -990,7 +990,11 @@ angular.module('syncthing.core') $scope.currentFolder.devices.forEach(function (n) { $scope.currentFolder.selectedDevices[n.deviceID] = true; }); - if ($scope.currentFolder.versioning && $scope.currentFolder.versioning.type === "simple") { + if ($scope.currentFolder.versioning && $scope.currentFolder.versioning.type === "trashcan") { + $scope.currentFolder.trashcanFileVersioning = true; + $scope.currentFolder.fileVersioningSelector = "trashcan"; + $scope.currentFolder.trashcanClean = +$scope.currentFolder.versioning.params.cleanoutDays; + } else if ($scope.currentFolder.versioning && $scope.currentFolder.versioning.type === "simple") { $scope.currentFolder.simpleFileVersioning = true; $scope.currentFolder.fileVersioningSelector = "simple"; $scope.currentFolder.simpleKeep = +$scope.currentFolder.versioning.params.keep; @@ -1007,6 +1011,7 @@ angular.module('syncthing.core') } else { $scope.currentFolder.fileVersioningSelector = "none"; } + $scope.currentFolder.trashcanClean = $scope.currentFolder.trashcanClean || 0; // weeds out nulls and undefineds $scope.currentFolder.simpleKeep = $scope.currentFolder.simpleKeep || 5; $scope.currentFolder.staggeredCleanInterval = $scope.currentFolder.staggeredCleanInterval || 3600; $scope.currentFolder.staggeredVersionsPath = $scope.currentFolder.staggeredVersionsPath || ""; @@ -1030,6 +1035,7 @@ angular.module('syncthing.core') }; $scope.currentFolder.rescanIntervalS = 60; $scope.currentFolder.fileVersioningSelector = "none"; + $scope.currentFolder.trashcanClean = 0; $scope.currentFolder.simpleKeep = 5; $scope.currentFolder.staggeredMaxAge = 365; $scope.currentFolder.staggeredCleanInterval = 3600; @@ -1051,6 +1057,7 @@ angular.module('syncthing.core') $scope.currentFolder.rescanIntervalS = 60; $scope.currentFolder.fileVersioningSelector = "none"; + $scope.currentFolder.trashcanClean = 0; $scope.currentFolder.simpleKeep = 5; $scope.currentFolder.staggeredMaxAge = 365; $scope.currentFolder.staggeredCleanInterval = 3600; @@ -1087,7 +1094,16 @@ angular.module('syncthing.core') } delete folderCfg.selectedDevices; - if (folderCfg.fileVersioningSelector === "simple") { + if (folderCfg.fileVersioningSelector === "trashcan") { + folderCfg.versioning = { + 'Type': 'trashcan', + 'Params': { + 'cleanoutDays': '' + folderCfg.trashcanClean + } + }; + delete folderCfg.trashcanFileVersioning; + delete folderCfg.trashcanClean; + } else if (folderCfg.fileVersioningSelector === "simple") { folderCfg.versioning = { 'Type': 'simple', 'Params': { diff --git a/internal/auto/gui.files.go b/internal/auto/gui.files.go index 5831c02dc..693f7b1dc 100644 --- a/internal/auto/gui.files.go +++ b/internal/auto/gui.files.go @@ -5,7 +5,7 @@ import ( ) const ( - AssetsBuildDate = "Sun, 07 Jun 2015 10:57:02 GMT" + AssetsBuildDate = "Fri, 12 Jun 2015 11:24:48 GMT" ) func Assets() map[string][]byte { @@ -85,7 +85,7 @@ func Assets() map[string][]byte { assets["assets/lang/valid-langs.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/yTMsQrCMBSF4d2nCJm9jyBIRRwUlVhwEIe0jW1oSEuSZvDpe0+6fH8ugZN1EFk7292076M4iI9sermXrS4c+c/41pYrMp1hjAO+QJcKjQU6v7g/CwIzLIxNzDjRVXEdDt8AjHiMzHjNiSq19Vlzw0TqgWIiZiZhcRmZ/0Cn+9b6Lb+7FQAA//8BAAD//9+xfOrFAAAA") - assets["index.html"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/+x9a3fbRpbg9/yKMnscS3tE0s5rdtySemXJTpz4obXs9PRms32KQJEsGwQQFCCZUTT/aD/t1/02Z//X3lsPoAAUXiSleNKTc2IRQD1vVd133Xt47+z16du/nT8ly3QVHH92eG88/mw6JadRvE74YpmSvdN98sXDR1+Rt0tGLtahly55uCAnWbqMEjGBwlj+7ZILchFlicegrs/IsyhZEXgnstl75qUkjUgKDaQsWQkSzeXDy+hXHgSUnGezgHvYzAvusVCwA3I5IV9MHk7I8zmhxIPB5HXOX5ArKkgYpcTnIk34LEuZT654uoQC0OOcB+wAG/tblBGPhiSapZTDn5ARmsI80/jxdLpSfU+iZDGFNqfQ23Ty2WfjMcAAQUECGi6ORiwckXAxpnF8NBJm8vKVF4VpEgUBS45GOVhO85cj4gVUiKMRFg0i+mGEDTPqH39GyOGKpTCtJU0ES49GWTof/9dR8QGHOGa/ZPzyaPSv43cn49NoFdOUzwIGzUIXLIRaz58eMX/BrHohXbGj0SVnV3GUpFbRK+6nyyOfXQJ4x/LhgPCQp5wGY+HRgB09mjysNeQz4SU8TnkUWm3VilG5E2olAh5+IAkLAG7wOfWylHAPW1ombA61BExdTPlqMZ3TS/wyiQGyx59h3ZSnATsuNttv5Poa1/ZMzuAVdLu3f3NzOFXl8t5Uy5cs9KNkOouiFLYHjaeeEMXTZMXDCbwZ6bGl64CJJWPpqNqOHuEcpjVNAEZXdD2oInYbXbIk4QDIppqHU7UnPjucRf5atuTzy+r+egpzSq29dXw4hVIKVnBgydsoJjOaENy9+C6kl/n2o5f4Rf0Zp1BQ//TZnGYB7BJok8lyfEHlWuMo9Dh0IzgWOELYs/wGX0UMJ6vUx3iW0NCHscGami9BtIhGRCReacHx7Rg2Bf8V2w0m4hKO1JIhujkaffnFiKj9Onr06J9HU5gr9pV3HFd6TdlHONTc91k4/ijU0VQFrh/o12L14HEWLxLqs+fhPCKff06sx0nIrlhyMzp277E47zkLrK4NGK2fEl/mEJJ7AkfDYUt09W7VgnqA0dIoJOk6hoVRDzk6maWh6Q9/wv/jOOErmqzlb7EyB0xDgnsf8u739kv9VFZxEazjJR5Ekv8ae0t2mcDfLB6Zdfg8nIn4z45m4HSFIqApK36NL2mQwb8sEbCxYEWu7ZljCZHeAOTfqbewj8n1fV36/k154WVHUwUNC8bTgA+F+Iq+j5JXW4PdBwLBkm6ov8Tu/iFAr2fjJ1HsR1cAPKShGV2wsWABMAHHjVWK81vqk2qoaprtR56Y5FQYTk465YgTp4uMT5Boj0hKkwWS1L/PoO8PQ2EOVOJDBdoVAB9/x4LYBR06BDDOSf5pVC0H6HqxQJrv05TqB7uV7j0UAWKlCafjgM6Q9jz1edoxwRMPiYDQZUpdeDRhRfXSnEvoMR//ioVZdQ0ANvmU7dPCYGgXLE1hZQWell6Ta5+Kac4acHltWgfEfUUKeg3ml8QDrrdrPMvoijw/6xpODkZ+CayDpPa9By2WWYqg7zXoaD7vHLFqbjMIJoBjaJL2GgtUhuLLjvG8US3uBoKm1CUXyFpXsc9tYCDZ5q1hIdl6+VRWsVHretFZlPVbLWBak3TMVnG67kIn2GbLeh1Os8CNOosvmtvFH0CDFYvbwJ2q8sgTn9OQBY+J3jHkFWM+iImaQy7YbOQV7kELc754HqLEkWPhJLoq2N1Sd8F45Y8ffWGzetb3GDsm8t/xFU1CLsUaa8bVsghNX5Y6XH5Z/iIFnB7rwT7Cx5Vk38eCL8ICSbsPkAZHvi7LL49zIDePE0WUKjqPrcZRQ6BAmSVyLGQJkvqMsZAIegnQBxZCCu4UaMwl1PAnlkZhlYmUaJSB6gJTSIr9wCWXm55YnHlpjzQPfw4yYIXn68H1Kf5OcXxKZCJxFgSa279TbFflwGo7M4BjOecfR47FLL8oPVoPhVxZPkXALRNFDesnKGExo4Dw9pR+4YAwlFb3CQ+JevOGoQYImYrf82yVodZw0KrIFKhHmMq1kyyY5KlRMYLTQijn3xtWsICbC1vLczdsDzuPYG3YYkWDAORZtRSTlK8Y+Q2nwB6P1vDf+OXLse+T7757vFo9RsXEzc1jGKCsVWurXcBQsED5Qq82tDWqlaK+D/tdyGJqTAjPiX6NVep0Uu+36/uq3fs3ZO/6vq5x/2afXNEwFYgoAPwhbLAJOYE5IaJQFf7imkl1ATbDIaQ4aY2H0UISNZhqnOPGMiLzPCZEiTD7PuwkBZDnZ/qg9eLwuhgJAFkreukarBKCS2zzIowSfeaZYaH7jzhhq+iyi5F+LvvYbuBG/VWM3OdixYVWAOVIa8DY8Zx1jPwF/JO0I/RbQN3PogDY4BbU/YGtbbw9l+XdeBtINL7+JNF3N9/q+6PjBsa5gugMb6hgIX6y0JZ69fPouIDtoDbbmrxYgpDd0ugfkmZIbeuchwZdWIDRp2/fSVYU1KpURb11ExWLmuT0Q0iQ61qj6/vq1/2b0aQmW+10kZW1Sr77y+72pCGCLQ3/ByJ76iCchL4E2V5twgekvldGveA0XC4fQExrG2cTEuWAiNyqCiZ/5emyflx6QOWOgSIXbpdgaabcz8pkqydcNpj0QELfa9o7p/tR6hTXcAuwJImSF1yAsDoJWLhIl+SYPPxjaz4UPHai8bA4J4AkMkwWQHHMmpTC2246apFRcn09TzgL/WCtTrbYwyZk42VbpHvD7EDjUaBv0n3sJDl4iqPrp7HvxBWvf/g9dR3PeCI1UIssoAlBVrd8eEqnw7QnKyrWIYD1J3toYg/YHBjpvLbzFH3TdojGiyTK4hHhfo6vG4rbyutD3NQVkKqxidK+XyY99r4+x/aym02vWaVcUDAbv5kpKB32sjkLwBHQWBgrVwzUAp1I/mSmbaxj6nl8ff1PwCeyj8gOSk8KaCFLRJQ8JnHEw/p2d40kTqJFYkirWEZXZk4XKU0zsace9snREXmA2n4Y9QPlB5SmyVh3K50UHsOZxRLnLPFg3HTBdOUJ9+HI3ndsTzmkfvqnHqQIJBrL+8EcL0AkZhQ3N+2NWiceXSnGpuopfjaQQGgjqK546i3dwHIM3vSU1xxfLVl4NMrCD2HdgGn5cBTb950q6rJG2jv/8z/9yz9/8dWf813uIrtt45F8ld9vQKrs7Y5IABaJ+w3oQhW95fF4NFTkvMeAdNnbHRH3a+yBe71iFPHO4OctQ0ihCecpqJw4N9RU/eZuCdlrRzX7rrE2NNfEmJZ1Cw4eQ2PTgi6VEHIJpRnETnIM342YHfyWLJhSWCVTVD3If9FLzkePUV8/o0OoPDguYKTGx871LXF/wE/LbtZGAyOKWdjB42hm4Zymy3yrQQ+Nnfv5tBE7a8k6x+8xNCM9If2GeU2bJgYzNuLAKvJZ8FO+mX6e8PCSBtwnv/1Gat8kN9qwzXsCS8sGZX7dDS3JXW4Dp+Fz2xicW8FkEUSzLpnyWyhDA4J0l+0UJgvZ8DMeMAGyCg2u6Fq8ylYzBsCoKqGOecpWhp88IP/W2NyTdSqbm/GQJuubmye/B1iXUbekHnm3AtQA290ZTGVruwJp48EPGfPVkFEfsBXkvSDK/DE6DwUR9bsEvywlr+fSGWDzNWgoTdCLx1ahRVfo/WARz9x507WMBUh2sIrYmGMRaeNMt1tf3XMCgtfrMHBR1gELCjuwS37XtO0lFbaVa4cLWenvb0y0MUxbw69OPKThEWg3zC+su4sNgidbMzwkop+xk5hO/wBgNQBVwMQbQdtBMgu9JfM+sC4sYyAJPXIhbC/X//jATBjKaM9RAQL8zQW5d0S+2RKD93ZSwktWpucd8LSVqQCiFbuBUZQgdgLIPMCbKtHqwXbwEXjJqgMhAuEg51kQkNeJvwVKrCtf1GQ692FVTFUTtwXPN/JN+xZtao0G8ZLOWMo9u8WT/O1mrUplOBOp1MeWZGT9QWlqN2s8QPdcR9sv1PttmsZ1cbT8Wr7epmG8IuRo+JV83afh3RwffTsEHZ/RdrDd4UnpQvQ5PD/mne7y8PSdSrN+ji4WDFWGJU2cfkncIx/aB1/FePnD6kC+2U3rAB7gJmhgt/9UvxvWw+8h1kkd7JgGXfhXGp99grbybQiT7E6blwuV+Jan6l6FO8draoViXZSEP4rH32kgGAA0CZa5ug7RJg9TiVRgB7xhHuOXlpv4zrkktHqg+07HvCd4pxtvGwMv8N9Id3GaGpPrA4fJ9YHTM6j4r/9wUIqjQo+sea47Pj7w3q3IhA+oBK2rdV0WqH7GYlm0hweo8olHu2fFz8RhUUPV/YNit5cOQIdGwpLjzdVqpxzfLTLEfbQSugtyusRJig6H00bDmlsb3c/Jxbql02GolGCtXEgAPrqEtSSUdsv5dwJlk6ladwLLWLfH4GMWejzo0itDy93L2WQ96eeH0HD2Bvkr9NtTgx2m1NY4CQLtHtDz0gqa//uJg9B0C3gHjzf3BOw10DjIunhL9JIsOdm67jeXV7/Xqh8uk6ptUaxG04r7ie08oq85FM4jcnnL3iMyxgN6i/qVOzgdniVDHEW0x1GHo8gQNxE12NP5Aj1FfipiK+zt/9zTLazJU0S7hOiAJthyT2eQXdz7gQlp38HnZ5U7QGwFW+362nJqzqvsVxiEfn7caGctzbLdwgqA7vTCcZpYd2FgbTavNnL7uzcknOli5E0fc04jw6+vFKGK8G2EIUp4OItLSvupQHu8o5xU78sHu/h+E5vXyOTtAGa9mJx38W3AK8rSfgCDgp8ExNJObufkJXmX8oD/Kp1NN4eVWIuUrSbwp48l73Zm61OxnEU06docp+fvdjppL860+0rFmgaPIXC0CQ0eP7q5ub8BNIzYoXuC3k/CMMpCj73+AXW+GeCxOQ8BkYGYQfWnC5agKkhtvmaTZy+YzoA3W0ZJl0eDNuKfceGhCLPeFKZN4qTR9iAsKtN8RkGQ8o3HN8gMhcs3kjnl/2duHXTI7oWvbqNc2/q19zDvVYdZDvEkx6xk0AePq+tam7Br3duUAWqYcRTjUmluBOC/wEtHS3xnvFYD6rGVdFydRcBGrvT7PCba9bV7aO+BTdl78D/DB/udSgnX2MdtE765mbprbaGraP56x+i6+wbGuxgLbY2ysti48OvIA49Hq1Gz8u+Wpku7Yt1obe3m09Uq8QvY3+Fir0W96Z5hg1LKqZLqKQEXzyj/vGGrKGVaAhK2COTici3/eV2jXeToK8ZE6ZIl5nLGrl3ezUgr8s1tubyr5rUmqRBUenq9exEaI/BA/FSXi36e/D3VDF0o6fvjh7twhr99sUx2UzaYNALKdWlGu9DrQtKF3u5rgJM8D3EN/rguzkoaGLyHhng5N03ER95LyiH9XOzPrPK3fRMhE33vIWDJ3YxmF97gDlz1H9ob3PCmlsDq2qN36CM5TLXRT1h3HrtuXUdDtYGCfE876R2swM4VJVtAv4fmpKnebuG/FVwxHHK3Ch4Zkm1gqWaPDZWo7JYbroAu0iccI4YyQ7cxjHqNnMeWjmOm2U6HxdOi/1uzwbdOGllBpaZ5UPbwCpDfoL1dT9p7CBkIH6UOXs/nt+rRVIxFhm/0M6/Fl66n/hB4FFGP1lvzQc3767miRfQPx9pK59JPF7vuTmzdAqF6AQdJQHe0vdfOrQIMfcJ73CGTLjqCsb5wq0eQKUQaN9DQ1eUCOjijqKb+jQwqf3xEvvzm65FruV7hUW9eAjXc0iHt2edhY5eGTHQ31BGnYSc4xxjcC3plR+DYavPYwa3a7mfsgOQ6ZiE1maMDMtqIAN+5T1OTV8Uh3cxNpRToTmoHbsNThTbLcHfqk2J1No+SlVa3DXbxaIikSv0hobd7enuUwnA6nVJ6+Xe0BhNRmsqpFTqk9D4PVJx/xddPpMGgX/4OAzf9CCNk/lhbHPRA2tN2NOWwKKetsE6BLiL5+c5Y2PXo191Ws+5g12eRl6FtpWyCrIaS7jVsAeOGDZutygPfYNy/ZEzUgw41eCFnMSbk2X7oCw5s5gz552k+futXwmDbClQgD54OD+dRn6koT8ggWtz6ZLgQ2UZTGXC7/EnWkhxgRxPZZAYJEIYufwQr2db2U0ivON4uLM9hg5ELFlZ5kLeq6erg2qO7I158xdKrKPmgYmuhYzANcgSpnlDvGKpSMk4AmkdQR492YhWWFgeFdx28coywwvH8wWnOzhPZxgNgAnMg5wr7UphzPYMicjlw4isZSXLGCCrzDggMGA1FDDOgURInEbAwK5WjbA3rpm7LwdBJIU1MyBuWJmto7/MlCwKuE73ooF+HUznlAjrfvX173gEaXNxPBi7sY8wwthlaACyQwF/0NsCXEjAJk4h1Qs4lKiPaE1nGgI/pgiFkTYz4oiOucsPljaKsJ1IxaYWgjq4uQ883QDDJixiQGc9oC1JFO1UY5WBH7JpDrOZ5ac1DkKLLiTGUVMtr0FzRnDGcTCZNs1T5fdommZkSLXPMW9nFFPMOdzNDk6OkcYImJ4qZH6Y9ycedB9ksJps3eKrMU6zH3i8mWKQ8gGYkOmgc+fOzxjFz/5cE8ycB/j0arZmoAJrIi+P6i5qVzkBjzUN7Fj+XhtA59+RBr8yFfL5CX7A/k5J51PbVLayWNmt5BSiK4D/I0UsJcRWFESyVx9Qj+ngh43l9vVo/P0ORsOCVMUGcuWEPH3OpXdUZzzDSAIFCSqkWUpCRpKUM08j9kkz/gh0cmYaVc3UNtjLrlkn7VQGzsVnJRGA6AVY+CFV0Ll+B6CmtWUej8SNtrJ9R7wPmNwK5OMmMBf8DW0tvOv2yDi7Z6NjnNIgWTu9sVUC7CzWE+lNl0KUAJAgaMECB8l8ThL0kzCy/Kldz2dRL6lncRaNWrXU9IZmjteJIqBXQ4K1XOJwuv+olYKrx12yB1RDW1e6lv7wkv3KZifZvMVti0mcKJzKScrn+iq5lDpMZmjJNWk5F2uMEzkyUCVNW9OpEIzsAsUDRDgmZZuSxH4bYZI5hC4Cqoayt6OfK3t6ObqqxQqvAoptJFtOULqYNqeSq3GLpUoiazyucTzVvmD3Szm3gUOj0yuBSzZHozI3Yyd52iqrl3d529aV1tEbMN6OVSEYHOdaQ2FUqhVMkJC13YFpjpxJSSUSqSQ4qxGqMqcG6hbasG+e2Y1LVwTjYDUqt4c+S1ly5TN3DwcOBePoR+EvJMrmQrK1uspFcY7O9WkVFoLPZDXAnIhKd+BV/jvKMv9j6U7l6Lb5tlsqvnG6VirEUSR48JnZTuap98k8m+trnnzeV8HmSruuOUocyg6EFPBiEGTA6fBlm5wyETCxZq8/DGLNPaftHDeI2AJAlKXxaLAZFTtxTeXgrXM9In2h8K6Eib7JKTz307lPDKxzUpKDD8W66hIdOiQCAwXtg2kMJvcPH+Dwi07qqG1CCvDMmB1op3jRLh9o4kvmdS8lAuH+g0+yoJE6m8RHRDnfX19CrTMhQH9fUDMypnDfxxxv2ewtXKS19TliWeEurvzxRMIjTsWIqGw0BNQNZw+bMQwc2fAcygzOC0WIuNN/sSZSBJW9LpFIAL0jOcAdnoY8QRpIvU3OSY6JzRALOVyguUp+l36lucEIuECLA2kB15N7xJzSrlhIQ6Z6KrOTvO/mPhlm7ERwe1L0tgQGU9a9LEIhgUynmpcjRdEA+MBYjDICv8WGmNFVpMTToZE44ABVUhaNSgoXAi9lpFA2ZY8vKSrw1yU9lB36qri+GvFU8oeR9djomCeYzgx96DUzuNZhFMUA/YipnfhBFHxTOmZDnKQipURb4EsTk6y9Qu/L1NzIxPfVwuwrpDS55U70fojkBkRi+qe2nPDPFgWKARW1fzpispHdmA1wqzKrbQtVtcpLFnGQCkXtOIlDCbScSUq+IVVx4vx+iVz0eTmWDDtRU2wJu3IbuMSUR2cZliCpCODsiBf4FFyangQapeEEm1DKi7mBC/soBv8rjBPg85dJRMirhFlg8XL8ClxQWpxWr5lwcOJd7tzKXLEabvZyITBSJYTnS4nDmUxWoJcQAFUSmLa3PZdebTtNQvHlwYn52MidAbNHc7XdvCNykRReb79S8jYs06bdjHcv3VBI3kB5XlAgWA/rAJRnx+DEavkYk7wQxzMhfwyrJmGGRkWoJzdIIVdFewW/gNsCV1JX7r1iF/blgwXy0wTKW3e/cC6cSm7uh3wRxy/2thSPTvJbyvnM736mSnU0Yr0W7kZf6HcHAK71bko56NT89d2VA9Srp+60umW3txhiQs6ianKpYWaffiTp56qDkLTQune0tWFPk1Fz76uNw76Lu83USrnME7ek0uIohoog1Tb8G6V3leN43mLHgqQDBI4vtROaNniGNaBGzoThXr3WpHImEXOVaVr5Y1irezfOl2Kn0hIwBlovPzfuhYyEu1HlHtKT7KTLISRbIgrQLwtUZpsuE4b2FIFs1xpN1bvLB+ViqYGv6OvhMqGPOdIAWO2DW6Ji0JyLR/TUvh3NLtn4Y6PFUUkTidvtddZGYJTv3fCqzAyWm36hRdqGyvIA+/zD6ymK8bk0Dik9lGtM+r0psM8eSwYFgKRvgrgaCbqe/2plsdGdaWR2Wu1Mrq8p94lrZgbrYHoGf6iraYYpZl8dmWx+709cq3Nqpr7Xz+bm+b0COG/W+9pB01sWK3rehRIPeV45B0XmLussrvk7nZqkB1kDv4vpsIKJIJUkq9SNgiR1LX+S8adAId8hbzwwhtJS/Wch/yfPYYpVYRXk/Gk3/1090/OvJ+H88HP/L+O+Tn68fHXzz1c0/TRtFNDmvfjpPWdStiWpYnFzV1/C90HuCIJ+gBkX5HMCk5soXygR7JC+1Sg/fCRTWkYkNgly+12xuowpt+OCVGk2BWqM4qSWbmw2TqxlVmZ13bWsV23Z/dVh9tYqbjktvtqHDypWyqD0sL/beN18V2kMp7AfSjOBUIB4Y7aFUGEqdDcx2b7J/ILWHZG+8L79g5J5EoHcL2fv7fql9OKktUHHy30184/Z4DlM6dWE6VaYb1zllGqw8KieQGoLiZPXeSE6V3hjNxbK6sWYlICFEuXkqPw8185FaibJpq1S3YfPXrVh5PWXC0g8vZP+FGaso5bRm6f3SYNGSX28D46pN0oZzVYkC6+Kz0YDqg6qNJTJvkPRUydDBN1eberAJUEfH54SnhXmA4U6YEDzwKYd2LFvA3r/tG8sVhh6QimKFATzYaPM8TRc5xKNaBNCR7aCRTr6u5lTfDDa98Kp11kooDLfmANx6Z1ikkveiGZXUCvbknSr16iyUO5cH2RP7fTFNtQvjRlt+2YJVFEloxiu1tvJNAILV0ejhLfNH99oXYsh6qT2pvhGuP1rENQRhMWQLmvJLpiklEk/BMMpFG3/Uf8P2uQnWQ5RAGfMFisdKjyVly0qR9vzHrmJdur9+ml9ZtFXf1Vfb9ayaS6um/3Vlv2rQaTUfpkZ1V4diUsVIRzVknESpVMiReRKtEIFj7HKyQj/YKCxb+w7IDOZeLWJri40qWWDMRk1h0EfdGGc02+7WdQ7Dkp/SMpdyU9U1/U2JpO50udF2pvsnM56q1deuHwTjCUljP/LcKIPpRZ6Qd0Iu8rOTtwTzGBBFph3mtcYBumwCGg28kVGwFB64EzRQtdnVMi41w36Q7e5Zd9alirGsOdVSk7XN0Uh3hqUBjfVOrDSgzZ75lAa02CuN0oD2emVPam7PbcdUX7bGbs7dayfead69NlGmPo+2x4qqmcatj8iiGJoyhOHdMgPmCAWRGqp8FQ3JJrQRqvzUIKETN9VhMTx/0x8DHnmyLAdINsmZ9YeASp6Aqw6UTfJwDYfJcBHW8u1qnePR0QN1Bh70lHxV6R8Yi5uFXrtMm7zbm09GY6N0jkD/MXQrW8Xojq2v7qDaiJKJSPMXWnsgGauEyYjPPmo4lQXQJ7N1cSO10fTv1O4VUxsd479myZvcxaydqKRuqwF149F63kLWtpspi9mP7tIMYa+8Wylmlyi7YBdyM5QvFhdWHR2PD5CFllzw1rp1ewgd2qnaTq4ONR+mpQxQH1EdvmurQH3ksMR9Bv23KFMjlD7cNCV4yQsEw5CZGdy+Vm0ISjKkpjdWMhVe0o8nC9aCmqoF2/GT42zUVAl3haXc968N/pEjyD0zQUZY5+2oK/drdfFAdpkuqVI5r+hHvspWRF/XZx89xpR9p9jiczXBIIiumLwDYenAJrkB141DOzC81vRCy/K+uW5UzQUV148LkyTy/mSJcQdofr+TC9jPcUqYdEH98qFRuB1Uqvl03VgLm6yWh5Z8DFTWVAc+HpAsTHlQA2JTlSvGPgykNOWdOjp+qbuBh97EptKGojjVl9uQnWpbBpPeJc2pHukGwlMtVqY+ZhFlBgFNc6zV3EPTFOyJA9hjUrn2MC9knecEF7v5Ks/GM+qiUk6kVp4Xbs4tadQd0wEV3L6gBBscHYMclTU2R5VD7LHutsoHqfxpYztsw7DbT1IrfpW2xit5kS3fpcU1IpFK9eMe8AKXTF21yBGhcRN00Ct9yUNnedyFNnkgd2DEsb7MgSl/inceQr+ZOagV3EJ4OQmJaU5dtoCjBlTXR1qK4LPSWuPlLgxFAghF+VVqUgQCpTQLSPcbYATQTKBAM4iQVGY1OtY/+p6Aan3lg1h9ufGur7X0O5CQ2sK7SUitWJmEKObBLHYA7wler1kxNMlzYVv8pV3buNIorqVeNmGBsijK0qVjtzWJqU2lQmJ6ng018Vuz0m94yWHHDpT9j5o21Zn7DNY9hlb9QP+LDOZiSX6RQdr/jCAB3d3ZRQZtc+zKs1OFWNPXwVY/c5VBd6yDBdvBnYkjjYwrh4zu/tO82aBXok98C8fNbbUx3De3zXUbeW9TKD8hNBpz+7rMgkkT9IylVxgnyzh8otORkic9jBUjWCi4xFSI0iSXCVKotwQKSL0UJFFTH51HC6fRvmFrb/MKR56quHyFo4T6/vMKx4ZXOHZ1ZWNAPukdXNkoZmUuWygfAvFET2OzydphlBtma/XVa7IYgl5Gl+tKZKB9IJQPcXNu/KGXVfRYu2+r6IKf+HUVx4WRNiBuGxPNtiLJO9nKH4RoV29xINWzqPVGVrJK2A+RqwYMTN2cN7BB8O7R17gzTMkyoVkm0/KLnKWWvgd1Red/z2CTkkWmgnkQoSIlMz8fcO6DWApZ5g4/DeQmEVM5Y3y1TFdBW1SyOXqJ+OXg0vR4/3EVKH4eM9uHZYa2f8W42lA1GIc0wWDfenIV/jE9Vp6w97TrK6xnegzv/RoUnodGJaS9qhZA90L0mkd0IDVFEzaBsWofXS/IfLafHznfb+r6v3R2fQGQApkwYJfAeV7xwPdoAuK7JLVwCpH9kzrmwlMaPcd79d3d+UtAXryx7xV+RYN50bcsKvr0Pp129o5SB6z8gVKWK59mxcSo+LKwFlQek4bu4DnYktewCuU43H2hzEqcZ/yr6w73Nze51zU+XqhIDFFyczMBciIxQQGVSsD/TdgeF5NQ4YWGkJ5/LEZnKGG8YCnuAtFAEoX+/InTw5pQWrpKaea48wuTVTRRle27hfsdOyoq2f4slyX7hCeS7RQhiqzKQzRl6Sp+Lb3dxMS3ur8D9zY1Z7yDw0IdEkcGnUGDJDlPojQCWBP1nXTFzKkAo9bqhiAJaqO7M8C8pB/fMO/yh1kMwsbz0ItkrFfMNwgwWfGU7P3An0z73MVAgNitDbPGWdBY2UO6S0BcsNBXvb7O0kW0JSDy1rYBRDGkTQDRgkUGQaxBi7alggzh9O48PH8aSl3FqEVjZgEli8PY1HB4sckvBJvtyuW3Qy3ZJwLMb4NoRoOTMBwG0YWpJnP2N8NWNU/OTKisOwTwp77XjSbFilHdlgOzWLKTLI10/OZhi0brFesrdpLHN9MDa70y8sc8FC/wLurgMxHoWh1HQjb+qZ6IjchgjkMuWIL6AcmNVE8+UR972F1tVfS9TpxTxmLWCDbkq8q92DMaZOj4nfh0zQ8C+N8935BBNU0MhB90aEI03iEH9k6g6IaTBby1xPAOKnsIXh7rsdckOyHY4M2Ck82EO2HjLc30HKpeRYnvnK352G/GeVNts47zQrWZ559uZfY7vkipl/jti4sONK7XFAvWkTbeRcRMVhfSRwiK/p5XHO4KbBeoXXyCynQZTLMPDRR2FectmiQl+vs/AgjfvRkoqSQtnFkYhesVpm15J9Ch8Q1DE4Slb0XTQ8lWbtSby+jq3ZtzTPrCrtDaq+wTfxod63fSnLDbdai/XyZk6no/FDHWI6WdPyc/sHWPaFp+r7xQGMHfELSYQ8voCjUajxri98uWjUI3h36rareaqddaKpbCdKDPPTWCfUD3LGQYptilSG5ZCaerUD177icRStJoU/9T+b618l2hhkSihgYFfOaOnFjJGobhy/EydyVv2JwG4vfU05fyiZmceMN09yd45YI0YtO/7NS4rbIceMk6RmNxZq8OFypYhU95sJZ+sLYnUgIrId0pYUfF0BQeVHm3Q7otCf6rzl9A48IJHxqZa+dJbZ2WobPRaR+aVoEVfMxfmUfLiJNoJUdmxQRWq0YXlIc1u7vtrJf/GsubouMsAVpmrN+f/5JF6Z9N1i4cRtkGrr4bo7d6UpZv9fu4uSpSK+V6SReLBAPPwPjldhWwY3VskWwG6CVYE3oJ0JX6PZqS6/swxvs3tVkNw95V3FA4pSmwa6I6qlDgN/ZHxHT6Z2n/ORFWnORurOUeAAOhQR/olXqP0dbJb+S9iEIkVuojTDZhd4Di9WF0oHgKH+L03ZvdoPe/sWYfnr7YXfleuTyuPLSj9xxqL/T+Krod3B7r3dOE4/Nd+ClZWXeBvZu54P9E2/9YaBvx2qeMATdjGjsR4OsfdoZRXjGGiRfUJdfmzOVYqC3Jr0rs6wVR5o8xkXAQUb+c+rdI9vs6kw5L0pT+HOM5NSQttj2OkmhR0iu6PgLrmhD7IccvMNg1dn7F/XT5mHzx8H7Ncyl3/luik8Ubhse5cKayQNrQ8fA+TqOYm8hnUcIXPMzDGPbqsTxVtQzbjIEBWy/vym0+iCuahNIVeOg4zvSWGQbzcufGnbq0AdKE4yV06qF7/ubjKlQs9SOlfhfupIepxFrmsol8kP/mo1FP6DLJQoGKHiOjH6YJehCOY4q7IUWPILy2oI4fHBKOp+Ucw4Uu2GP9Gn9fAFGB06ac7LA2M2f2VL3DQpjDKAXcJhsx39/iK5tsS79mREd2SLTD1C85x45ljp5uRHZ9jb1gc+Kn+YTKHP0/4wE3+ipV4ER+KBU5nKa+pbpQqApDcFeHZS53TRAvY96uB79kLJORE3KMM5c5zrBf8xtgOaNAw+Vr1Vdzo0dWoyWKYNx8bf5xlq1iDImwp+D7TN9AUd3u22jwpbzpCAxDFCM6lD24MWHeYadD/Hvmpa6U19VExmrP1+GjyE0DlMqNulYI9+H0XB/AjqVCqJqz+kBet9Orr+49A3GQb02Rn2x4/tz85Sc19J+bnVerpGQHBOX6un0wk0TSk5sbxDftUUvbaEpnN55E588Am7+WBGVoh90kZcAQnhp6st0oGmhK50DQSXk4yLclKb2GBdNpHJd9xJEGIW0Oyzha/dfZ02ydMnGGdyjgGAM5SdY3N0/ItGdFSRjsmhU1ch3DlFnqGk419BAV7YkMvWmREgcaL3ADXkM2uOFejhvg7b0G5ND8yY0dJMzzEaCERo7JQ0Ut5JMFhlY0CA+J4Q0kkTcsgUXUYRbG0IpZASS1HisJzxBlpNanSuYDMnKFj6+kx9++2jPOtnS/WX4DpCijLl1JoBcMdMDt66w6DiUwGz89engAnNEB+RL+/xr+f/Tw4c+lSAN661cZEMTbuhmbcOVU8k82mdTciZykaWBP1d5HwKufSHWoNWID2yyoiwhewGgy5x+tY3U4lSJMIeyczKKsqhMvpByKX8tCji3AlAWego7LRhtEmOWj0r73ZLZbGCFfgZweANzzAEd5i9YbkXgwKiFYKqZQYwrSfWTd6pmIywItytShHrB3NOCL8DEZP/om/jgiS4arfjSCRRwRiaOORl9+881oenw4A441l521IuJCJtHd27cl5+Wj4xqLG5fupsRrdaA/B+S//jNsnkdfm7v6OrTRKW5SDrJqlIji0lLTvfWu++rWJkcf6HEWSiDg1V77ZrdcVK/ouZ6WAQ+Bbgg948YLbWgDlvyEAt4lTzibSS8S3rdawD5STAJCvk3ofEjF0E/YFTnLwiVdDamXpMssIScfMXL+m6d/JRfecgXrPKSJzE94JsiTLP2AXvbwe0DtJ2jPP2Pkx4SzQfVYSEA6SZfRemg1mGIW/Dq0EveX0RDIPpFRkUNyvuQBjweNEUQuYB3Ii0jGxe1b7ZQGbEbg34Be0fWgiol08/oOEOmKhuGgqnBm1iF6q4csvMJIOEO2++ky4YJ8B4ecDa71fcSCIZUi4JvIDywMmT8EOGc05HA2XsI2/ff/PaQe9MQxF2cgoiEQPcO7EPwD+Y5xPxgEzKcBpwAWmsA2SPigrfN0xQPoUQDOHjLWZ0CEE5AcYdNh8CXgs/mg2gH/CDQ1YDwNB81U1XyHxDCmPBxaGw6mF3Ex/ld6iZmcvhUsGLKTvuXAggM+WGSJL4Yt7vf0QzQjT6JkyOJ8Dxyn0Benh3aXREBkL2H3BswbUpGFgpxxthoE2O8jD6+X/hiJIdju+wijKf4IEh8Nh9T7ASYXkDf//n/+3/9dex+GbDxAAg+4t+TkB7qiPh1Q8wVm5vouEukQdPUiSnzyQhGDkwVdhnwIGQHE40FtadYZWu08ex8N2dlYCZDk2a+c+oOI+EsAJwUs+T2Ll140bKC66ls8VQPqnVOBXvDfZ+FiFmRD+JVzGSTqu4gNOYSKioNsCcwDXqZOhoAHKwfkRTYbQnjOeZQm5Al7P2iHvlnDYbpAJcHlIFR+wUBqWZOXXIDsMKReyubQ41uaCm85DA+/5SvA/sNw79tohkTu1RqE8yHDfAvYRZBT9MUPhyzC2wwjwb6BXsNhqPdHxlIOSJuGNBw00h+BEgMD+KG6CoXU6rbLNQtYuUQI4rkMpyAq0pWI5umVjG6bEGkKl3GjUfUWzS1pq1Fquopq0bBQ2K6GsVhEAYjrEyB+U2XF/TYiUtlLV/L6J6DIRUYxOis9PiAusfALoquh8zqIghMbRLUu0Yg84+ks8z6wVHb7gSY+p2EkpiCWfwRZrvKirWfNB8IAohgIFuvROYYfmCyiaBGwiRetpvFUhDSO1+NFBBDIfzf3+kjO90IVHDLtBQepbiY7VVCfSp9YjwKBHh0Xv6dBkjV3/yWAGgdPnofeoD7fZ++zKe7nAO+wjo7Lz80dfgWMZBiFqIcgL1J/UJ9iHfppgtPFwBn+DABcedOyugeAMhPAnD5NMvI24fgrpEO6v+RpkoXTX0BMGB1bDw2dDt3HeDQCmrwX+vicqOfvL5on9XAsIaqW8KB7DXE+LJ1FUSoAd8RyViCLmueWXao6envFkUOt9mTwVk2ZBpjYB4QjvITHqbH2HKpHpbpSJczczV+M2T55r4JUycI9641zjLh9C2NpbN58KD5HG6xWr/Zq4f0vGUvW+s/4i8nDyZe9e8/XdPpeFA/u6rgyU9famI+LjKPrUWAuDslktY7F03WnuQcPoMOE4SbIAB22DruhqtZUBxj5CE50mJ7mL7ZuL/+0ZZsqfg+/ZGKqcgVDJ2fm3bYtBppAqoCWO2tWnsudtWYnn95ZozJ+oAoCAn931WocxXixdLv25jxAuXxKgyu6FsrO8ky+26o5YzjfRVPS9rSDhvwskWd+B00B5oPGgi1aEsDLYyDMqbw0La/ZYgDTclPVtrQxRHJEck+N8adoH4BdKU5Ymq7jhIfp0FED0mxCt4049bPDKXqZHsNfDPF2/Nn/BwAA//8BAAD//4z8ScrFEAEA") + assets["index.html"], _ = base64.StdEncoding.DecodeString("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") assets["modal.html"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/3yTUW+bMBDH3/cpbjwsrVRCW/UpSzptkSZN6qRK7csejX2AV2Mj+0jHEN99h2EsrdI9JDbmfnf3/5/ZKn0AaUQIu6R2ShgohMIESOTaKvy1S9KrBGyZCiKfKkEizYV8Ut41u6TvGXUB4ROQbxE2sAokSMsVDMMr6gm73AmvIvXFOYPCnkX6fAy+fQewfZ+mvGQZ7F3TeV1WBGf7c7i+vLqBxwrhobOSKm1L+NxS5XxYx/CJeax0gAfXeonMK4SvztfAZ6HNf6IkIAfESQh9HcAV8eG7+62NEXDf5kbLKdGdlmgDXsBhDdfryzV8K0CA5JYW6v4OnkUA6wiUDuR13hIqeNZUcQDXLLTBiyndD9eCFBZcTkLzYhEEQUXUbLKsnuqvnS8zzppxvWwUlabRkNfDSZUWxpXR2vm8X01vTLnagBG+xMnMU7R0ltDS/P5URIU8fQ/CoKfpP+37caZtGIaFY7K6eQmSJoNHARwSGlbNjepil2gunfwlStM11XgCy46rjMtYY5uN4HGmvo/Zh+Ff+ay6WURkrOJtRblTXfSLvLBBmlbh2+TcbbyWycs8hXN8c44t4JkTa6CuwV0yPSxMThb4lyosRGso7kOdQPwU+MrUesnMiqNT/zHHY+0OuFjzAevQfJyoqMoIwtv92PQcsc2mfk4oXbbzZl7+AAAA//8BAAD//53P618IBAAA") @@ -93,7 +93,7 @@ func Assets() map[string][]byte { assets["scripts/syncthing/core/controllers/eventController.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/7RUQW/bPAy951fwKwrYwee56YCdgm6HrQV62mEddhh2UGzaFiBLgSg1CIb891Gy4zqOgw7Dpkscinx8fHrSs7BQ4sbX98+oHcEdVEIRrhcLoWuvhM1bU3qFaUJ7XbhG6jovjMVkuQBe/K2dNUqhTZMI8XEIJBlUnmuk0ZBeU2G2mMF149x2CT9jdViJJwRyVhYu4a7HcJefK0EuwjIx7ZVaDwmBeNh9/MRbq1Fl2CBfFEj0oMM8A4dSODFuHdbNDXxrUMOX43RgkZywLMWukQrBNQjKcHzLQ4V9nlhjhygJpJ7Cba2pGYNi5caaHaEFTibTImyVcJWxLXEb560mEPB2tYKUpC5isylcg6JES9AIgg0y00p5arCEnXRN7NEhMa8SA9Yy67a0gTBwPgV8apj2RpAshFJ7aFHowFW4CDaabujI06DLQOiyS+G6KeiOc7VxIArnI2x/ApVXpwRkBel/cwcRFlpr7IPuDmp9tt0Neho/LE7+9ra5xla6NPn6+FnzmbFZ14szFr153sNqjkqUjk/qXhRN+mIhDF6cyz+iju7SpbSwWGYyiv1t6vQqgl5lEH9zWR6/3D7cmO77giSdBHPREyXO8GagDsvfUXZ8IQOn71Eohbpmy72B2x+nIMMNnZbzmJMzYY89yRaNdyO95zSMT0heo0u9VWxkhP8huYlj0Yd4j+4SDnWtl7Pi5L090+GhuJAXHZn2vpwKlME7vm4vwcPkFerLXn2DzkxbVbOu/TsKKclt7m6Tf6vM7eqiNH/A7jVWs2yCoX8BAAD//wEAAP//TiJq898GAAA=") - assets["scripts/syncthing/core/controllers/syncthingController.js"], _ = base64.StdEncoding.DecodeString("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") + assets["scripts/syncthing/core/controllers/syncthingController.js"], _ = base64.StdEncoding.DecodeString("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") assets["scripts/syncthing/core/directives/identiconDirective.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/5xVTVPbMBC951dsZwp2GkcOdHpJ6s4wDMxwgENz6IEyHVdWYk0VKSPLcSnkv3clJ8F2FL50wUj79r2V3m5SOS9FqslCZaVgYVDcS2pyLueEKs2Cfg9wkYxrRg1fYQDPmDScKhlEcBt8rLjMVIXfsxKBXEkIN3t9eHBgu1aphmI1v5lCAkFuzHIcx1VVkeozUXoen45GoxjPg0lvB9nlu9oShqtUlCyCgv9jzeQNAkyfKVouEEGoZqlhF4LZ/26moeOPILA8/ck+OlelyC65EN+x1DODqZ5K0qqKgCrRpbVLM1NqCR+2dZNlqgt2JU2tl9A81ecqY2fGpoGBzQOf6ioiOBn14QhOO4LWh/Rdc62Vfq9Cy2nZ4PjYqUiSBBY8ywQ7R+RLChaOGyMvlW5xP0/rSIeObwgnL9Y5e/sLWJj152te38bZ5/eopYYUDHmN5r9Lg1b/i7YO69eyp1PnuwEER13/HMDfW7x983fiK56ZHHNswW/B5ozPc+MD76Hxaki6XDKZnedcZKFFvOxHG+XZVdX+Jl6hz00b3/lTW8kdrVZnu0gq0qLAGhtDqSPcmS+p/zw+wpf26e5uEuzDEcQurh2yk4kx16nJCWVc1I0UY9vWlm4h+AzqzvdbFQ8wVT0ajJpiLXIe9olmS5FSFsa3P3/8uos5FuV9rBn2nvNUAqOJvW74WquGwUC3h+4ezLV84+JdT36D4ckEhsMDvdWsqjsin5ryOaSj92A8xfkJmzPv9ZQ+2uYEc1PL00vNtT546j/Z323vrHsd+9UDcjV/ktEI2Rw/dDAFWoaaMQQXQdT2OlVLNj5kOgQkQVtNGy64/DNuTFyXLgJWj9AI0m3fFb6r34RtBkkoWdX44XapSN0U3cnSa3+t7zDgPwAAAP//AQAA//9afsjulQgAAA==") diff --git a/internal/model/model.go b/internal/model/model.go index 2e1840632..79d08e59c 100644 --- a/internal/model/model.go +++ b/internal/model/model.go @@ -35,6 +35,7 @@ import ( "github.com/syncthing/syncthing/internal/sync" "github.com/syncthing/syncthing/internal/versioner" "github.com/syndtr/goleveldb/leveldb" + "github.com/thejerf/suture" ) // How many files to send in each Index/IndexUpdate message. @@ -61,6 +62,8 @@ type service interface { } type Model struct { + *suture.Supervisor + cfg *config.Wrapper db *leveldb.DB finder *db.BlockFinder @@ -103,6 +106,13 @@ var ( // for file data without altering the local folder in any way. func NewModel(cfg *config.Wrapper, id protocol.DeviceID, deviceName, clientName, clientVersion string, ldb *leveldb.DB) *Model { m := &Model{ + Supervisor: suture.New("model", suture.Spec{ + Log: func(line string) { + if debug { + l.Debugln(line) + } + }, + }), cfg: cfg, db: ldb, finder: db.NewBlockFinder(ldb, cfg), @@ -168,7 +178,14 @@ func (m *Model) StartFolderRW(folder string) { if !ok { l.Fatalf("Requested versioning type %q that does not exist", cfg.Versioning.Type) } - p.versioner = factory(folder, cfg.Path(), cfg.Versioning.Params) + versioner := factory(folder, cfg.Path(), cfg.Versioning.Params) + if service, ok := versioner.(suture.Service); ok { + // The versioner implements the suture.Service interface, so + // expects to be run in the background in addition to being called + // when files are going to be archived. + m.Add(service) + } + p.versioner = versioner } go p.Serve() diff --git a/internal/versioner/.gitignore b/internal/versioner/.gitignore new file mode 100644 index 000000000..d383c56ff --- /dev/null +++ b/internal/versioner/.gitignore @@ -0,0 +1 @@ +testdata diff --git a/internal/versioner/trashcan.go b/internal/versioner/trashcan.go new file mode 100644 index 000000000..f68df77f7 --- /dev/null +++ b/internal/versioner/trashcan.go @@ -0,0 +1,187 @@ +// Copyright (C) 2015 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +package versioner + +import ( + "fmt" + "os" + "path/filepath" + "strconv" + "time" + + "github.com/syncthing/syncthing/internal/osutil" +) + +func init() { + // Register the constructor for this type of versioner + Factories["trashcan"] = NewTrashcan +} + +type Trashcan struct { + folderPath string + cleanoutDays int + stop chan struct{} +} + +func NewTrashcan(folderID, folderPath string, params map[string]string) Versioner { + cleanoutDays, _ := strconv.Atoi(params["cleanoutDays"]) + // On error we default to 0, "do not clean out the trash can" + + s := &Trashcan{ + folderPath: folderPath, + cleanoutDays: cleanoutDays, + stop: make(chan struct{}), + } + + if debug { + l.Debugf("instantiated %#v", s) + } + return s +} + +// Archive moves the named file away to a version archive. If this function +// returns nil, the named file does not exist any more (has been archived). +func (t *Trashcan) Archive(filePath string) error { + _, err := osutil.Lstat(filePath) + if os.IsNotExist(err) { + if debug { + l.Debugln("not archiving nonexistent file", filePath) + } + return nil + } else if err != nil { + return err + } + + versionsDir := filepath.Join(t.folderPath, ".stversions") + if _, err := os.Stat(versionsDir); err != nil { + if !os.IsNotExist(err) { + return err + } + + if debug { + l.Debugln("creating versions dir", versionsDir) + } + if err := osutil.MkdirAll(versionsDir, 0777); err != nil { + return err + } + osutil.HideFile(versionsDir) + } + + if debug { + l.Debugln("archiving", filePath) + } + + relativePath, err := filepath.Rel(t.folderPath, filePath) + if err != nil { + return err + } + + archivedPath := filepath.Join(versionsDir, relativePath) + if err := osutil.MkdirAll(filepath.Dir(archivedPath), 0777); err != nil && !os.IsExist(err) { + return err + } + + if debug { + l.Debugln("moving to", archivedPath) + } + + if err := osutil.Rename(filePath, archivedPath); err != nil { + return err + } + + // Set the mtime to the time the file was deleted. This is used by the + // cleanout routine. If this fails things won't work optimally but there's + // not much we can do about it so we ignore the error. + os.Chtimes(archivedPath, time.Now(), time.Now()) + + return nil +} + +func (t *Trashcan) Serve() { + if debug { + l.Debugln(t, "starting") + defer l.Debugln(t, "stopping") + } + + // Do the first cleanup one minute after startup. + timer := time.NewTimer(time.Minute) + defer timer.Stop() + + for { + select { + case <-t.stop: + return + + case <-timer.C: + if t.cleanoutDays > 0 { + if err := t.cleanoutArchive(); err != nil { + l.Infoln("Cleaning trashcan:", err) + } + } + + // Cleanups once a day should be enough. + timer.Reset(24 * time.Hour) + } + } +} + +func (t *Trashcan) Stop() { + close(t.stop) +} + +func (t *Trashcan) String() string { + return fmt.Sprintf("trashcan@%p", t) +} + +func (t *Trashcan) cleanoutArchive() error { + versionsDir := filepath.Join(t.folderPath, ".stversions") + if _, err := osutil.Lstat(versionsDir); os.IsNotExist(err) { + return nil + } + + cutoff := time.Now().Add(time.Duration(-24*t.cleanoutDays) * time.Hour) + currentDir := "" + filesInDir := 0 + walkFn := func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() { + // We have entered a new directory. Lets check if the previous + // directory was empty and try to remove it. We ignore failure for + // the time being. + if currentDir != "" && filesInDir == 0 { + osutil.Remove(currentDir) + } + currentDir = path + filesInDir = 0 + return nil + } + + if info.ModTime().Before(cutoff) { + // The file is too old; remove it. + osutil.Remove(path) + } else { + // Keep this file, and remember it so we don't unnecessarily try + // to remove this directory. + filesInDir++ + } + return nil + } + + if err := filepath.Walk(versionsDir, walkFn); err != nil { + return err + } + + // The last directory seen by the walkFn may not have been removed as it + // should be. + if currentDir != "" && filesInDir == 0 { + osutil.Remove(currentDir) + } + return nil +} diff --git a/internal/versioner/trashcan_test.go b/internal/versioner/trashcan_test.go new file mode 100644 index 000000000..cb5cb16dc --- /dev/null +++ b/internal/versioner/trashcan_test.go @@ -0,0 +1,69 @@ +// Copyright (C) 2015 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +package versioner + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + "time" +) + +func TestTrashcanCleanout(t *testing.T) { + // Verify that files older than the cutoff are removed, that files newer + // than the cutoff are *not* removed, and that empty directories are + // removed (best effort). + + var testcases = []struct { + file string + shouldRemove bool + }{ + {"testdata/.stversions/file1", false}, + {"testdata/.stversions/file2", true}, + {"testdata/.stversions/keep1/file1", false}, + {"testdata/.stversions/keep1/file2", false}, + {"testdata/.stversions/keep2/file1", false}, + {"testdata/.stversions/keep2/file2", true}, + {"testdata/.stversions/remove/file1", true}, + {"testdata/.stversions/remove/file2", true}, + } + + os.RemoveAll("testdata") + defer os.RemoveAll("testdata") + + oldTime := time.Now().Add(-8 * 24 * time.Hour) + for _, tc := range testcases { + os.MkdirAll(filepath.Dir(tc.file), 0777) + if err := ioutil.WriteFile(tc.file, []byte("data"), 0644); err != nil { + t.Fatal(err) + } + if tc.shouldRemove { + if err := os.Chtimes(tc.file, oldTime, oldTime); err != nil { + t.Fatal(err) + } + } + } + + versioner := NewTrashcan("default", "testdata", map[string]string{"cleanoutDays": "7"}).(*Trashcan) + if err := versioner.cleanoutArchive(); err != nil { + t.Fatal(err) + } + + for _, tc := range testcases { + _, err := os.Lstat(tc.file) + if tc.shouldRemove && !os.IsNotExist(err) { + t.Error(tc.file, "should have been removed") + } else if !tc.shouldRemove && err != nil { + t.Error(tc.file, "should not have been removed") + } + } + + if _, err := os.Lstat("testdata/.stversions/remove"); !os.IsNotExist(err) { + t.Error("empty directory should have been removed") + } +}