// fileMapFromDuplicate queries the server's search interface for an // existing file blob for the file contents of wholeRef. // If the server has it, it's validated, and then fileMap (which must // already be partially populated) has its "parts" field populated, // and then fileMap is uploaded (if necessary). // If no file blob is found, a zero blob.Ref (and no error) is returned. func (cl *Client) fileMapFromDuplicate(fileMap *schema.Builder, wholeRef blob.Ref) (blob.Ref, error) { dupFileRef, err := cl.SearchExistingFileSchema(wholeRef) if err != nil { return blob.Ref{}, err } if !dupFileRef.Valid() { // because SearchExistingFileSchema returns blob.Ref{}, nil when file is not found. return blob.Ref{}, nil } dupMap, err := cl.FetchSchemaBlob(dupFileRef) if err != nil { return blob.Ref{}, fmt.Errorf("could not find existing file blob for wholeRef %q: %v", wholeRef, err) } fileMap.PopulateParts(dupMap.PartsSize(), dupMap.ByteParts()) json, err := fileMap.JSON() if err != nil { return blob.Ref{}, fmt.Errorf("could not write file map for wholeRef %q: %v", wholeRef, err) } bref := blob.SHA1FromString(json) if bref == dupFileRef { // Unchanged (same filename, modtime, JSON serialization, etc) return dupFileRef, nil } sbr, err := cl.ReceiveBlob(bref, strings.NewReader(json)) if err != nil { return blob.Ref{}, err } return sbr.Ref, nil }
// fileMapFromDuplicate queries the server's search interface for an // existing file with an entire contents of sum (a blobref string). // If the server has it, it's validated, and then fileMap (which must // already be partially populated) has its "parts" field populated, // and then fileMap is uploaded (if necessary) and a PutResult with // its blobref is returned. If there's any problem, or a dup doesn't // exist, ok is false. // If required, Vivify is also done here. func (up *Uploader) fileMapFromDuplicate(bs blobserver.StatReceiver, fileMap *schema.Builder, sum string) (pr *client.PutResult, ok bool) { if noDupSearch { return } _, err := up.Client.SearchRoot() if err != nil { return } dupFileRef, err := up.Client.SearchExistingFileSchema(blob.MustParse(sum)) if err != nil { log.Printf("Warning: error searching for already-uploaded copy of %s: %v", sum, err) return nil, false } if !dupFileRef.Valid() { return nil, false } if *cmdmain.FlagVerbose { log.Printf("Found dup of contents %s in file schema %s", sum, dupFileRef) } dupMap, err := up.Client.FetchSchemaBlob(dupFileRef) if err != nil { log.Printf("Warning: error fetching %v: %v", dupFileRef, err) return nil, false } fileMap.PopulateParts(dupMap.PartsSize(), dupMap.ByteParts()) json, err := fileMap.JSON() if err != nil { return nil, false } uh := client.NewUploadHandleFromString(json) if up.fileOpts.wantVivify() { uh.Vivify = true } if !uh.Vivify && uh.BlobRef == dupFileRef { // Unchanged (same filename, modtime, JSON serialization, etc) return &client.PutResult{BlobRef: dupFileRef, Size: uint32(len(json)), Skipped: true}, true } pr, err = up.Upload(uh) if err != nil { log.Printf("Warning: error uploading file map after finding server dup of %v: %v", sum, err) return nil, false } return pr, true }