aboutsummaryrefslogtreecommitdiffstats
path: root/drive/sync_download.go
diff options
context:
space:
mode:
Diffstat (limited to 'drive/sync_download.go')
-rw-r--r--drive/sync_download.go75
1 files changed, 72 insertions, 3 deletions
diff --git a/drive/sync_download.go b/drive/sync_download.go
index f947142..9dcd719 100644
--- a/drive/sync_download.go
+++ b/drive/sync_download.go
@@ -6,6 +6,7 @@ import (
"os"
"sort"
"time"
+ "bytes"
"path/filepath"
"google.golang.org/api/googleapi"
"google.golang.org/api/drive/v3"
@@ -18,6 +19,7 @@ type DownloadSyncArgs struct {
Path string
DryRun bool
DeleteExtraneous bool
+ Resolution ConflictResolution
Comparer FileComparer
}
@@ -37,8 +39,19 @@ func (self *Drive) DownloadSync(args DownloadSyncArgs) error {
return err
}
+ // Find changed files
+ changedFiles := files.filterChangedRemoteFiles()
+
fmt.Fprintf(args.Out, "Found %d local files and %d remote files\n", len(files.local), len(files.remote))
+ // Ensure that that we don't overwrite any local changes
+ if args.Resolution == NoResolution {
+ err = ensureNoLocalModifications(changedFiles)
+ if err != nil {
+ return fmt.Errorf("Conflict detected!\nThe following files have changed and the local file are newer than it's remote counterpart:\n\n%s\nNo conflict resolution was given, aborting...", err)
+ }
+ }
+
// Create missing directories
err = self.createMissingLocalDirs(files, args)
if err != nil {
@@ -52,7 +65,7 @@ func (self *Drive) DownloadSync(args DownloadSyncArgs) error {
}
// Download files that has changed
- err = self.downloadChangedFiles(files, args)
+ err = self.downloadChangedFiles(changedFiles, args)
if err != nil {
return err
}
@@ -145,8 +158,7 @@ func (self *Drive) downloadMissingFiles(files *syncFiles, args DownloadSyncArgs)
return nil
}
-func (self *Drive) downloadChangedFiles(files *syncFiles, args DownloadSyncArgs) error {
- changedFiles := files.filterChangedRemoteFiles()
+func (self *Drive) downloadChangedFiles(changedFiles []*changedFile, args DownloadSyncArgs) error {
changedCount := len(changedFiles)
if changedCount > 0 {
@@ -154,6 +166,11 @@ func (self *Drive) downloadChangedFiles(files *syncFiles, args DownloadSyncArgs)
}
for i, cf := range changedFiles {
+ if skip, reason := checkLocalConflict(cf, args.Resolution); skip {
+ fmt.Fprintf(args.Out, "[%04d/%04d] Skipping %s (%s)\n", i + 1, changedCount, cf.remote.relPath, reason)
+ continue
+ }
+
absPath, err := filepath.Abs(filepath.Join(args.Path, cf.remote.relPath))
if err != nil {
return fmt.Errorf("Failed to determine local absolute path: %s", err)
@@ -246,3 +263,55 @@ func (self *Drive) deleteExtraneousLocalFiles(files *syncFiles, args DownloadSyn
return nil
}
+
+func checkLocalConflict(cf *changedFile, resolution ConflictResolution) (bool, string) {
+ // No conflict unless local file was last modified
+ if cf.compareModTime() != LocalLastModified {
+ return false, ""
+ }
+
+ // Don't skip if want to keep the remote file
+ if resolution == KeepRemote {
+ return false, ""
+ }
+
+ // Skip if we want to keep the local file
+ if resolution == KeepLocal {
+ return true, "conflicting file, keeping local file"
+ }
+
+ if resolution == KeepLargest {
+ largest := cf.compareSize()
+
+ // Skip if the local file is largest
+ if largest == LocalLargestSize {
+ return true, "conflicting file, local file is largest, keeping local"
+ }
+
+ // Don't skip if the remote file is largest
+ if largest == RemoteLargestSize {
+ return false, ""
+ }
+
+ // Keep local if both files have the same size
+ if largest == EqualSize {
+ return true, "conflicting file, file sizes are equal, keeping local"
+ }
+ }
+
+ // The conditionals above should cover all cases,
+ // unless the programmer did something wrong,
+ // in which case we default to being non-destructive and skip the file
+ return true, "conflicting file, unhandled case"
+}
+
+func ensureNoLocalModifications(files []*changedFile) error {
+ conflicts := findLocalConflicts(files)
+ if len(conflicts) == 0 {
+ return nil
+ }
+
+ buffer := bytes.NewBufferString("")
+ formatConflicts(conflicts, buffer)
+ return fmt.Errorf(buffer.String())
+}