%PDF- %PDF-
Direktori : /home/waritko/go/src/github.com/odeke-em/drive/src/ |
Current File : //home/waritko/go/src/github.com/odeke-em/drive/src/copy.go |
// Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package drive import ( "errors" "fmt" ) var ErrPathNotDir = errors.New("not a directory") type copyArgs struct { destPath string src *File dest *File } func (g *Commands) Copy(byId bool) error { argc := len(g.opts.Sources) if argc < 2 { return invalidArgumentsErr(fmt.Errorf("expecting src [src1....] dest got: %v", g.opts.Sources)) } g.log.Logln("Processing...") spin := g.playabler() spin.play() defer spin.stop() end := argc - 1 sources, dest := g.opts.Sources[:end], g.opts.Sources[end] destFile, err := g.rem.FindByPath(dest) if err != nil && err != ErrPathNotExists { return remoteLookupErr(fmt.Errorf("destination: %s err: %v", dest, err)) } multiPaths := len(sources) > 1 if multiPaths { if destFile != nil && !destFile.IsDir { return illogicalStateErr(fmt.Errorf("%s: %v", dest, ErrPathNotDir)) } _, err := g.remoteMkdirAll(dest) if err != nil { return err } } srcResolver := g.rem.FindByPath if byId { srcResolver = g.rem.FindById } done := make(chan bool) waitCount := uint64(0) for _, srcPath := range sources { srcFile, srcErr := srcResolver(srcPath) if srcErr != nil { g.log.LogErrf("%s: %v\n", srcPath, srcErr) continue } waitCount += 1 go func(fromPath, toPath string, fromFile *File) { _, copyErr := g.copy(fromFile, toPath) if copyErr != nil { g.log.LogErrf("%s: %v\n", fromPath, copyErr) } done <- true }(srcPath, dest, srcFile) } for i := uint64(0); i < waitCount; i += 1 { <-done } return nil } func (g *Commands) copy(src *File, destPath string) (*File, error) { if src == nil { return nil, illogicalStateErr(fmt.Errorf("non existent src")) } if !src.IsDir { if !src.Copyable { return nil, illogicalStateErr(fmt.Errorf("%s is non-copyable", src.Name)) } destDir, destBase := g.pathSplitter(destPath) destParent, destParErr := g.remoteMkdirAll(destDir) if destParErr != nil { return nil, destParErr } parentId := destParent.Id destFile, destErr := g.rem.FindByPath(destPath) if destErr != nil && destErr != ErrPathNotExists { return nil, destErr } if destFile != nil && destFile.IsDir { parentId = destFile.Id destBase = src.Name } return g.rem.copy(destBase, parentId, src) } destFile, destErr := g.remoteMkdirAll(destPath) if destErr != nil { return nil, destErr } pagePair := g.rem.findChildren(src.Id, false) children := pagePair.filesChan errsChan := pagePair.errsChan working := true for working { select { case err := <-errsChan: if err != nil { // TODO: What should we do here? Should we continue? return nil, err } case child, stillHasContent := <-children: if !stillHasContent { working = false break } // TODO: add concurrency after retry scheme is added // because could suffer from rate limit restrictions chName := sepJoin("/", destPath, child.Name) _, chErr := g.copy(child, chName) if chErr != nil { g.log.LogErrf("copy: %s: %v\n", chName, chErr) } } } return destFile, nil }