mirror of
https://github.com/jkl1337/duplicacy.git
synced 2026-01-02 11:44:45 -06:00
Merge pull request #254 from lowne/restore-ignore-uid
allow skip setting uid/gid on restored files
This commit is contained in:
5
GUIDE.md
5
GUIDE.md
@@ -87,18 +87,21 @@ OPTIONS:
|
|||||||
-hash detect file differences by hash (rather than size and timestamp)
|
-hash detect file differences by hash (rather than size and timestamp)
|
||||||
-overwrite overwrite existing files in the repository
|
-overwrite overwrite existing files in the repository
|
||||||
-delete delete files not in the snapshot
|
-delete delete files not in the snapshot
|
||||||
|
-ignore-owner do not set the original uid/gid on restored files
|
||||||
-stats show statistics during and after restore
|
-stats show statistics during and after restore
|
||||||
-threads <n> number of downloading threads
|
-threads <n> number of downloading threads
|
||||||
-limit-rate <kB/s> the maximum download rate (in kilobytes/sec)
|
-limit-rate <kB/s> the maximum download rate (in kilobytes/sec)
|
||||||
-storage <storage name> restore from the specified storage instead of the default one
|
-storage <storage name> restore from the specified storage instead of the default one
|
||||||
```
|
```
|
||||||
|
|
||||||
The *restore* command restores the repository to a previous revision. By default the restore procedure will treat files that have the same sizes and timestamps as those in the snapshot as unchanged files, but with the -hash option, every file will be fully scanned to make sure they are in fact unchanged.
|
The *restore* command restores the repository to a previous revision. By default the restore procedure will treat files that have the same sizes and timestamps as those in the snapshot as unchanged files, but with the `-hash` option, every file will be fully scanned to make sure they are in fact unchanged.
|
||||||
|
|
||||||
By default the restore procedure will not overwriting existing files, unless the `-overwrite` option is specified.
|
By default the restore procedure will not overwriting existing files, unless the `-overwrite` option is specified.
|
||||||
|
|
||||||
The `-delete` option indicates that files not in the snapshot will be removed.
|
The `-delete` option indicates that files not in the snapshot will be removed.
|
||||||
|
|
||||||
|
If the `-ignore-owner` option is specified, the restore procedure will not attempt to restore the original user/group id ownership on restored files (all restored files will be owned by the current user); this can be useful when restoring to a new or different machine.
|
||||||
|
|
||||||
If the `-stats` option is specified, statistical information such as transfer speed, and number of chunks will be displayed throughout the restore procedure.
|
If the `-stats` option is specified, statistical information such as transfer speed, and number of chunks will be displayed throughout the restore procedure.
|
||||||
|
|
||||||
The `-threads` option can be used to specify more than one thread to download chunks.
|
The `-threads` option can be used to specify more than one thread to download chunks.
|
||||||
|
|||||||
@@ -691,6 +691,8 @@ func restoreRepository(context *cli.Context) {
|
|||||||
quickMode := !context.Bool("hash")
|
quickMode := !context.Bool("hash")
|
||||||
overwrite := context.Bool("overwrite")
|
overwrite := context.Bool("overwrite")
|
||||||
deleteMode := context.Bool("delete")
|
deleteMode := context.Bool("delete")
|
||||||
|
setOwner := !context.Bool("ignore-owner")
|
||||||
|
|
||||||
showStatistics := context.Bool("stats")
|
showStatistics := context.Bool("stats")
|
||||||
|
|
||||||
var patterns []string
|
var patterns []string
|
||||||
@@ -732,7 +734,7 @@ func restoreRepository(context *cli.Context) {
|
|||||||
duplicacy.SavePassword(*preference, "password", password)
|
duplicacy.SavePassword(*preference, "password", password)
|
||||||
|
|
||||||
backupManager.SetupSnapshotCache(preference.Name)
|
backupManager.SetupSnapshotCache(preference.Name)
|
||||||
backupManager.Restore(repository, revision, true, quickMode, threads, overwrite, deleteMode, showStatistics, patterns)
|
backupManager.Restore(repository, revision, true, quickMode, threads, overwrite, deleteMode, setOwner, showStatistics, patterns)
|
||||||
|
|
||||||
runScript(context, preference.Name, "post")
|
runScript(context, preference.Name, "post")
|
||||||
}
|
}
|
||||||
@@ -1279,6 +1281,10 @@ func main() {
|
|||||||
Name: "delete",
|
Name: "delete",
|
||||||
Usage: "delete files not in the snapshot",
|
Usage: "delete files not in the snapshot",
|
||||||
},
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "ignore-owner",
|
||||||
|
Usage: "do not set the original uid/gid on restored files",
|
||||||
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "stats",
|
Name: "stats",
|
||||||
Usage: "show statistics during and after restore",
|
Usage: "show statistics during and after restore",
|
||||||
|
|||||||
@@ -711,7 +711,7 @@ func (manager *BackupManager) Backup(top string, quickMode bool, threads int, ta
|
|||||||
// the same as 'top'. 'quickMode' will bypass files with unchanged sizes and timestamps. 'deleteMode' will
|
// the same as 'top'. 'quickMode' will bypass files with unchanged sizes and timestamps. 'deleteMode' will
|
||||||
// remove local files that don't exist in the snapshot. 'patterns' is used to include/exclude certain files.
|
// remove local files that don't exist in the snapshot. 'patterns' is used to include/exclude certain files.
|
||||||
func (manager *BackupManager) Restore(top string, revision int, inPlace bool, quickMode bool, threads int, overwrite bool,
|
func (manager *BackupManager) Restore(top string, revision int, inPlace bool, quickMode bool, threads int, overwrite bool,
|
||||||
deleteMode bool, showStatistics bool, patterns []string) bool {
|
deleteMode bool, setOwner bool, showStatistics bool, patterns []string) bool {
|
||||||
|
|
||||||
startTime := time.Now().Unix()
|
startTime := time.Now().Unix()
|
||||||
|
|
||||||
@@ -878,7 +878,8 @@ func (manager *BackupManager) Restore(top string, revision int, inPlace bool, qu
|
|||||||
if quickMode {
|
if quickMode {
|
||||||
if file.IsSameAsFileInfo(stat) {
|
if file.IsSameAsFileInfo(stat) {
|
||||||
LOG_TRACE("RESTORE_SKIP", "File %s unchanged (by size and timestamp)", file.Path)
|
LOG_TRACE("RESTORE_SKIP", "File %s unchanged (by size and timestamp)", file.Path)
|
||||||
file.RestoreMetadata(fullPath, &stat)
|
// shouldn't this be skipped?
|
||||||
|
// file.RestoreMetadata(fullPath, &stat)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -903,7 +904,7 @@ func (manager *BackupManager) Restore(top string, revision int, inPlace bool, qu
|
|||||||
}
|
}
|
||||||
newFile.Close()
|
newFile.Close()
|
||||||
|
|
||||||
file.RestoreMetadata(fullPath, nil)
|
file.RestoreMetadata(fullPath, nil, setOwner)
|
||||||
if !showStatistics {
|
if !showStatistics {
|
||||||
LOG_INFO("DOWNLOAD_DONE", "Downloaded %s (0)", file.Path)
|
LOG_INFO("DOWNLOAD_DONE", "Downloaded %s (0)", file.Path)
|
||||||
}
|
}
|
||||||
@@ -915,9 +916,9 @@ func (manager *BackupManager) Restore(top string, revision int, inPlace bool, qu
|
|||||||
totalFileSize, downloadedFileSize, startDownloadingTime) {
|
totalFileSize, downloadedFileSize, startDownloadingTime) {
|
||||||
downloadedFileSize += file.Size
|
downloadedFileSize += file.Size
|
||||||
downloadedFiles = append(downloadedFiles, file)
|
downloadedFiles = append(downloadedFiles, file)
|
||||||
|
file.RestoreMetadata(fullPath, nil, setOwner)
|
||||||
}
|
}
|
||||||
|
|
||||||
file.RestoreMetadata(fullPath, nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if deleteMode && len(patterns) == 0 {
|
if deleteMode && len(patterns) == 0 {
|
||||||
@@ -933,7 +934,7 @@ func (manager *BackupManager) Restore(top string, revision int, inPlace bool, qu
|
|||||||
for _, entry := range remoteSnapshot.Files {
|
for _, entry := range remoteSnapshot.Files {
|
||||||
if entry.IsDir() && !entry.IsLink() {
|
if entry.IsDir() && !entry.IsLink() {
|
||||||
dir := joinPath(top, entry.Path)
|
dir := joinPath(top, entry.Path)
|
||||||
entry.RestoreMetadata(dir, nil)
|
entry.RestoreMetadata(dir, nil, setOwner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ func (entry *Entry) String(maxSizeDigits int) string {
|
|||||||
return fmt.Sprintf("%*d %s %64s %s", maxSizeDigits, entry.Size, modifiedTime, entry.Hash, entry.Path)
|
return fmt.Sprintf("%*d %s %64s %s", maxSizeDigits, entry.Size, modifiedTime, entry.Hash, entry.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) RestoreMetadata(fullPath string, fileInfo *os.FileInfo) bool {
|
func (entry *Entry) RestoreMetadata(fullPath string, fileInfo *os.FileInfo, setOwner bool) bool {
|
||||||
|
|
||||||
if fileInfo == nil {
|
if fileInfo == nil {
|
||||||
stat, err := os.Stat(fullPath)
|
stat, err := os.Stat(fullPath)
|
||||||
@@ -318,7 +318,11 @@ func (entry *Entry) RestoreMetadata(fullPath string, fileInfo *os.FileInfo) bool
|
|||||||
entry.SetAttributesToFile(fullPath)
|
entry.SetAttributesToFile(fullPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
return SetOwner(fullPath, entry, fileInfo)
|
if setOwner {
|
||||||
|
return SetOwner(fullPath, entry, fileInfo)
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return -1 if 'left' should appear before 'right', 1 if opposite, and 0 if they are the same.
|
// Return -1 if 'left' should appear before 'right', 1 if opposite, and 0 if they are the same.
|
||||||
|
|||||||
Reference in New Issue
Block a user