diff options
Diffstat (limited to 'drive/upload_sync.go')
| -rw-r--r-- | drive/upload_sync.go | 370 | 
1 files changed, 0 insertions, 370 deletions
| diff --git a/drive/upload_sync.go b/drive/upload_sync.go index 0af83f0..a2a0640 100644 --- a/drive/upload_sync.go +++ b/drive/upload_sync.go @@ -7,7 +7,6 @@ import (      "time"      "sort"      "path/filepath" -    "github.com/gyuho/goraph/graph"      "google.golang.org/api/googleapi"      "google.golang.org/api/drive/v3"  ) @@ -73,37 +72,6 @@ func (self *Drive) UploadSync(args UploadSyncArgs) error {      return nil  } -func (self *Drive) prepareSyncFiles(localPath string, root *drive.File) (*syncFiles, error) { -    localCh := make(chan struct{files []*localFile; err error}) -    remoteCh := make(chan struct{files []*remoteFile; err error}) - -    go func() { -        files, err := prepareLocalFiles(localPath) -        localCh <- struct{files []*localFile; err error}{files, err} -    }() - -    go func() { -        files, err := self.prepareRemoteFiles(root) -        remoteCh <- struct{files []*remoteFile; err error}{files, err} -    }() - -    local := <-localCh -    if local.err != nil { -        return nil, local.err -    } - -    remote := <-remoteCh -    if remote.err != nil { -        return nil, remote.err -    } - -    return &syncFiles{ -        root: &remoteFile{file: root}, -        local: local.files, -        remote: remote.files, -    }, nil -} -  func (self *Drive) prepareSyncRoot(args UploadSyncArgs) (*drive.File, error) {      fields := []googleapi.Field{"id", "name", "mimeType", "appProperties"}      f, err := self.service.Files.Get(args.RootId).Fields(fields...).Do() @@ -312,38 +280,6 @@ func (self *Drive) deleteRemoteFile(rf *remoteFile, args UploadSyncArgs) error {      return nil  } -func (self *Drive) prepareRemoteFiles(rootDir *drive.File) ([]*remoteFile, error) { -    // Find all files which has rootDir as root -    query := fmt.Sprintf("appProperties has {key='syncRootId' and value='%s'}", rootDir.Id) -    fileList, err := self.service.Files.List().Q(query).Fields("files(id,name,parents,md5Checksum,mimeType)").Do() -    if err != nil { -        return nil, fmt.Errorf("Failed listing files: %s", err) -    } - -    if err := checkFiles(fileList.Files); err != nil { -        return nil, err -    } - -    relPaths, err := prepareRemoteRelPaths(rootDir.Id, fileList.Files) -    if err != nil { -        return nil, err -    } - -    var remoteFiles []*remoteFile -    for _, f := range fileList.Files { -        relPath, ok := relPaths[f.Id] -        if !ok { -            return nil, fmt.Errorf("File %s does not have a valid parent, aborting...", f.Id) -        } -        remoteFiles = append(remoteFiles, &remoteFile{ -            relPath: relPath, -            file: f, -        }) -    } - -    return remoteFiles, nil -} -  func (self *Drive) dirIsEmpty(id string) (bool, error) {      query := fmt.Sprintf("'%s' in parents", id)      fileList, err := self.service.Files.List().Q(query).Do() @@ -353,309 +289,3 @@ func (self *Drive) dirIsEmpty(id string) (bool, error) {      return len(fileList.Files) == 0, nil  } - -func checkFiles(files []*drive.File) error { -    uniq := map[string]string{} - -    for _, f := range files { -        // Ensure all files have exactly one parent -        if len(f.Parents) != 1 { -            return fmt.Errorf("File %s does not have exacly one parent, aborting...", f.Id) -        } - -        // Ensure that there are no duplicate files -        uniqKey := f.Name + f.Parents[0] -        if dupeId, isDupe := uniq[uniqKey]; isDupe { -            return fmt.Errorf("Found name collision between %s and %s, aborting", f.Id, dupeId) -        } -        uniq[uniqKey] = f.Id -    } - -    return nil -} - -func prepareRemoteRelPaths(rootId string, files []*drive.File) (map[string]string, error) { -    names := map[string]string{} -    idGraph := graph.NewDefaultGraph() - -    for _, f := range files { -        // Store directory name for quick lookup -        names[f.Id] = f.Name - -        // Store path between parent and child folder -        idGraph.AddVertex(f.Id) -        idGraph.AddVertex(f.Parents[0]) -        idGraph.AddEdge(f.Parents[0], f.Id, 0) -    } - -    paths := map[string]string{} - -    for _, f := range files { -        // Find path from root to directory -        pathIds, _, err := graph.Dijkstra(idGraph, rootId, f.Id) -        if err != nil { -            return nil, err -        } - -        // Convert path ids to path names -        var pathNames []string -        for _, id := range pathIds { -            pathNames = append(pathNames, names[id]) -        } - -        // Store relative file path from root to directory -        paths[f.Id] = filepath.Join(pathNames...) -    } - -    return paths, nil -} - -type localFile struct { -    absPath string -    relPath string -    info os.FileInfo -} - -type remoteFile struct { -    relPath string -    file *drive.File -} - -type changedFile struct { -    local *localFile -    remote *remoteFile -} - -func prepareLocalFiles(root string) ([]*localFile, error) { -    var files []*localFile - -    // Get absolute root path -    absRootPath, err := filepath.Abs(root) -    if err != nil { -        return nil, err -    } - -    err = filepath.Walk(absRootPath, func(absPath string, info os.FileInfo, err error) error { -        if err != nil { -            return err -        } - -        // Skip root directory -        if absPath == absRootPath { -            return nil -        } - -        relPath, err := filepath.Rel(absRootPath, absPath) -        if err != nil { -            return err -        } - -        files = append(files, &localFile{ -            absPath: absPath, -            relPath: relPath, -            info: info, -        }) - -        return nil -    }) - -    if err != nil { -        return nil, fmt.Errorf("Failed to prepare local files: %s", err) -    } - -    return files, err -} - -type syncFiles struct { -    root *remoteFile -    local []*localFile -    remote []*remoteFile -} - -func (self *syncFiles) filterMissingRemoteDirs() []*localFile { -    var files []*localFile - -    for _, f := range self.local { -        if f.info.IsDir() && !self.existsRemote(f) { -            files = append(files, f) -        } -    } - -    return files -} - -func (self *syncFiles) filterMissingLocalDirs() []*remoteFile { -    var files []*remoteFile - -    for _, rf := range self.remote { -        if isDir(rf.file) && !self.existsLocal(rf) { -            files = append(files, rf) -        } -    } - -    return files -} - -func (self *syncFiles) filterMissingRemoteFiles() []*localFile { -    var files []*localFile - -    for _, f := range self.local { -        if !f.info.IsDir() && !self.existsRemote(f) { -            files = append(files, f) -        } -    } - -    return files -} - -func (self *syncFiles) filterMissingLocalFiles() []*remoteFile { -    var files []*remoteFile - -    for _, rf := range self.remote { -        if !isDir(rf.file) && !self.existsLocal(rf) { -            files = append(files, rf) -        } -    } - -    return files -} - -func (self *syncFiles) filterChangedLocalFiles() []*changedFile { -    var files []*changedFile - -    for _, lf := range self.local { -        // Skip directories -        if lf.info.IsDir() { -            continue -        } - -        // Skip files that don't exist on drive -        rf, found := self.findRemoteByPath(lf.relPath) -        if !found { -            continue -        } - -        // Add files where remote md5 sum does not match local -        if rf.file.Md5Checksum != md5sum(lf.absPath) { -            files = append(files, &changedFile{ -                local: lf, -                remote: rf, -            }) -        } -    } - -    return files -} - -func (self *syncFiles) filterChangedRemoteFiles() []*changedFile { -    var files []*changedFile - -    for _, rf := range self.remote { -        // Skip directories -        if isDir(rf.file) { -            continue -        } - -        // Skip local files that don't exist -        lf, found := self.findLocalByPath(rf.relPath) -        if !found { -            continue -        } - -        // Add files where remote md5 sum does not match local -        if rf.file.Md5Checksum != md5sum(lf.absPath) { -            files = append(files, &changedFile{ -                local: lf, -                remote: rf, -            }) -        } -    } - -    return files -} - -func (self *syncFiles) filterExtraneousRemoteFiles() []*remoteFile { -    var files []*remoteFile - -    for _, rf := range self.remote { -        if !self.existsLocal(rf) { -            files = append(files, rf) -        } -    } - -    return files -} - -func (self *syncFiles) filterExtraneousLocalFiles() []*localFile { -    var files []*localFile - -    for _, lf := range self.local { -        if !self.existsRemote(lf) { -            files = append(files, lf) -        } -    } - -    return files -} - -func (self *syncFiles) existsRemote(lf *localFile) bool { -    _, found := self.findRemoteByPath(lf.relPath) -    return found -} - -func (self *syncFiles) existsLocal(rf *remoteFile) bool { -    _, found := self.findLocalByPath(rf.relPath) -    return found -} - -func (self *syncFiles) findRemoteByPath(relPath string) (*remoteFile, bool) { -    if relPath == "." { -        return self.root, true -    } - -    for _, rf := range self.remote { -        if relPath == rf.relPath { -            return rf, true -        } -    } - -    return nil, false -} - -func (self *syncFiles) findLocalByPath(relPath string) (*localFile, bool) { -    for _, lf := range self.local { -        if relPath == lf.relPath { -            return lf, true -        } -    } - -    return nil, false -} - -type byLocalPathLength []*localFile - -func (self byLocalPathLength) Len() int { -    return len(self) -} - -func (self byLocalPathLength) Swap(i, j int) { -    self[i], self[j] = self[j], self[i] -} - -func (self byLocalPathLength) Less(i, j int) bool { -    return pathLength(self[i].relPath) < pathLength(self[j].relPath) -} - -type byRemotePathLength []*remoteFile - -func (self byRemotePathLength) Len() int { -    return len(self) -} - -func (self byRemotePathLength) Swap(i, j int) { -    self[i], self[j] = self[j], self[i] -} - -func (self byRemotePathLength) Less(i, j int) bool { -    return pathLength(self[i].relPath) < pathLength(self[j].relPath) -} | 
