diff --git a/duplicacy/duplicacy_main.go b/duplicacy/duplicacy_main.go index 5e29d0e..daa5be8 100644 --- a/duplicacy/duplicacy_main.go +++ b/duplicacy/duplicacy_main.go @@ -1255,7 +1255,7 @@ func copySnapshots(context *cli.Context) { destinationStorage.SetRateLimits(0, context.Int("upload-limit-rate")) destinationManager := duplicacy.CreateBackupManager(destination.SnapshotID, destinationStorage, repository, - destinationPassword, "", "", fasle) + destinationPassword, "", "", false) duplicacy.SavePassword(*destination, "password", destinationPassword) destinationManager.SetupSnapshotCache(destination.Name) diff --git a/src/duplicacy_backupmanager.go b/src/duplicacy_backupmanager.go index 40e685c..df1a321 100644 --- a/src/duplicacy_backupmanager.go +++ b/src/duplicacy_backupmanager.go @@ -73,9 +73,9 @@ func CreateBackupManager(snapshotID string, storage Storage, top string, passwor nobackupFile: nobackupFile, - filtersFile: filtersFile, + filtersFile: filtersFile, - excludeByAttribute: excludeByAttribute, + excludeByAttribute: excludeByAttribute, } if IsDebugging() { @@ -200,6 +200,10 @@ func (manager *BackupManager) Backup(top string, quickMode bool, threads int, ta LOG_INFO("BACKUP_KEY", "RSA encryption is enabled") } + if manager.excludeByAttribute { + LOG_INFO("BACKUP_EXCLUDE", "Exclude files with no-backup attributes") + } + remoteSnapshot := manager.SnapshotManager.downloadLatestSnapshot(manager.snapshotID) if remoteSnapshot == nil { remoteSnapshot = CreateEmptySnapshot(manager.snapshotID) diff --git a/src/duplicacy_entry.go b/src/duplicacy_entry.go index 0069904..7d2849f 100644 --- a/src/duplicacy_entry.go +++ b/src/duplicacy_entry.go @@ -28,29 +28,6 @@ var fileModeMask = os.ModePerm | os.ModeSetuid | os.ModeSetgid | os.ModeSticky // Regex for matching 'StartChunk:StartOffset:EndChunk:EndOffset' var contentRegex = regexp.MustCompile(`^([0-9]+):([0-9]+):([0-9]+):([0-9]+)`) -// AttributeExcludeName attribute name to determine file exclusion -var AttributeExcludeName = getDefaultAttributeExcludeName() - -// AttributeExcludeValue attribute value to determine file exclusion -var AttributeExcludeValue = getDefaultAttributeExcludeValue() - -func getDefaultAttributeExcludeName() string { - if runtime.GOOS == "darwin" { - return "com.apple.metadata:com_apple_backup_excludeItem" - } - if runtime.GOOS == "linux" { - return "duplicacy_exclude" - } - return "" -} - -func getDefaultAttributeExcludeValue() string { - if runtime.GOOS == "darwin" { - return "com.apple.backupd" - } - return "" -} - // Entry encapsulates information about a file or directory. type Entry struct { Path string @@ -547,15 +524,9 @@ func ListEntries(top string, path string, fileList *[]*Entry, patterns []string, entry.ReadAttributes(top) } - if excludeByAttribute && (runtime.GOOS == "darwin" || runtime.GOOS == "linux") { - attrValue, ok := entry.Attributes[AttributeExcludeName] - if ok { - attrValueString := string(attrValue) - if strings.Contains(attrValueString, AttributeExcludeValue) { - LOG_WARN("LIST_NOBACKUPXATTR", "%s is excluded due to extended attribute: %s", entry.Path, AttributeExcludeName) - continue - } - } + if excludeByAttribute && excludedByAttribute(entry.Attributes) { + LOG_DEBUG("LIST_EXCLUDE", "%s is excluded by attribute", entry.Path) + continue } if f.Mode()&(os.ModeNamedPipe|os.ModeSocket|os.ModeDevice) != 0 { diff --git a/src/duplicacy_preference.go b/src/duplicacy_preference.go index 6a77a44..fe24b22 100644 --- a/src/duplicacy_preference.go +++ b/src/duplicacy_preference.go @@ -25,8 +25,8 @@ type Preference struct { DoNotSavePassword bool `json:"no_save_password"` NobackupFile string `json:"nobackup_file"` Keys map[string]string `json:"keys"` - FiltersFile string `json:"filters"` - ExcludeByAttribute bool `json:"exclude_by_attribute"` + FiltersFile string `json:"filters"` + ExcludeByAttribute bool `json:"exclude_by_attribute"` } var preferencePath string diff --git a/src/duplicacy_snapshot.go b/src/duplicacy_snapshot.go index 61be0cd..9b4fef2 100644 --- a/src/duplicacy_snapshot.go +++ b/src/duplicacy_snapshot.go @@ -58,7 +58,7 @@ func CreateEmptySnapshot(id string) (snapshto *Snapshot) { // CreateSnapshotFromDirectory creates a snapshot from the local directory 'top'. Only 'Files' // will be constructed, while 'ChunkHashes' and 'ChunkLengths' can only be populated after uploading. -func CreateSnapshotFromDirectory(id string, top string, nobackupFile string, filtersFile string, , excludeByAttribute bool) (snapshot *Snapshot, skippedDirectories []string, +func CreateSnapshotFromDirectory(id string, top string, nobackupFile string, filtersFile string, excludeByAttribute bool) (snapshot *Snapshot, skippedDirectories []string, skippedFiles []string, err error) { snapshot = &Snapshot{ diff --git a/src/duplicacy_utils_darwin.go b/src/duplicacy_utils_darwin.go new file mode 100644 index 0000000..38e2a51 --- /dev/null +++ b/src/duplicacy_utils_darwin.go @@ -0,0 +1,14 @@ +// Copyright (c) Acrosync LLC. All rights reserved. +// Free for personal use and commercial trial +// Commercial use requires per-user licenses available from https://duplicacy.com + +package duplicacy + +import ( + "strings" +) + +func excludedByAttribute(attirbutes map[string][]byte) bool { + value, ok := attirbutes["com.apple.metadata:com_apple_backup_excludeItem"] + return ok && strings.Contains(string(value), "com.apple.backupd") +} diff --git a/src/duplicacy_utils_linux.go b/src/duplicacy_utils_linux.go new file mode 100644 index 0000000..223f32c --- /dev/null +++ b/src/duplicacy_utils_linux.go @@ -0,0 +1,13 @@ +// Copyright (c) Acrosync LLC. All rights reserved. +// Free for personal use and commercial trial +// Commercial use requires per-user licenses available from https://duplicacy.com + +package duplicacy + +import ( +) + +func excludedByAttribute(attirbutes map[string][]byte) bool { + _, ok := attirbutes["duplicacy_exclude"] + return ok +} diff --git a/src/duplicacy_utils_windows.go b/src/duplicacy_utils_windows.go index ec5c171..3a01682 100644 --- a/src/duplicacy_utils_windows.go +++ b/src/duplicacy_utils_windows.go @@ -131,3 +131,7 @@ func SplitDir(fullPath string) (dir string, file string) { i := strings.LastIndex(fullPath, "\\") return fullPath[:i+1], fullPath[i+1:] } + +func excludedByAttribute(attirbutes map[string][]byte) bool { + return false +}