github.com/stffabi/git-lfs@v2.3.5-0.20180214015214-8eeaa8d88902+incompatible/git/githistory/ref_updater.go (about) 1 package githistory 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "strings" 7 8 "github.com/git-lfs/git-lfs/errors" 9 "github.com/git-lfs/git-lfs/git" 10 "github.com/git-lfs/git-lfs/git/odb" 11 "github.com/git-lfs/git-lfs/tasklog" 12 "github.com/git-lfs/git-lfs/tools" 13 ) 14 15 // refUpdater is a type responsible for moving references from one point in the 16 // Git object graph to another. 17 type refUpdater struct { 18 // CacheFn is a function that returns the SHA1 transformation from an 19 // original hash to a new one. It specifies a "bool" return value 20 // signaling whether or not that given "old" SHA1 was migrated. 21 CacheFn func(old []byte) ([]byte, bool) 22 // Logger logs the progress of reference updating. 23 Logger *tasklog.Logger 24 // Refs is a set of *git.Ref's to migrate. 25 Refs []*git.Ref 26 // Root is the given directory on disk in which the repository is 27 // located. 28 Root string 29 30 db *odb.ObjectDatabase 31 } 32 33 // UpdateRefs performs the reference update(s) from existing locations (see: 34 // Refs) to their respective new locations in the graph (see CacheFn). 35 // 36 // It creates reflog entries as well as stderr log entries as it progresses 37 // through the reference updates. 38 // 39 // It returns any error encountered, or nil if the reference update(s) was/were 40 // successful. 41 func (r *refUpdater) UpdateRefs() error { 42 list := r.Logger.List("migrate: Updating refs") 43 defer list.Complete() 44 45 var maxNameLen int 46 for _, ref := range r.Refs { 47 maxNameLen = tools.MaxInt(maxNameLen, len(ref.Name)) 48 } 49 50 for _, ref := range r.Refs { 51 sha1, err := hex.DecodeString(ref.Sha) 52 if err != nil { 53 return errors.Wrapf(err, "could not decode: %q", ref.Sha) 54 } 55 56 to, ok := r.CacheFn(sha1) 57 58 if ref.Type == git.RefTypeLocalTag { 59 tag, _ := r.db.Tag(sha1) 60 if tag != nil && tag.ObjectType == odb.CommitObjectType { 61 // Assume that a non-nil error is an indication 62 // that the tag is bare (without annotation). 63 64 toObj, okObj := r.CacheFn(tag.Object) 65 if !okObj { 66 continue 67 } 68 69 newTag, err := r.db.WriteTag(&odb.Tag{ 70 Object: toObj, 71 ObjectType: tag.ObjectType, 72 Name: tag.Name, 73 Tagger: tag.Tagger, 74 75 Message: tag.Message, 76 }) 77 78 if err != nil { 79 return errors.Wrapf(err, "could not rewrite tag: %s", tag.Name) 80 } 81 82 to = newTag 83 ok = true 84 } 85 } 86 87 if !ok { 88 continue 89 } 90 91 if err := git.UpdateRefIn(r.Root, ref, to, ""); err != nil { 92 return err 93 } 94 95 namePadding := tools.MaxInt(maxNameLen-len(ref.Name), 0) 96 list.Entry(fmt.Sprintf(" %s%s\t%s -> %x", ref.Name, strings.Repeat(" ", namePadding), ref.Sha, to)) 97 } 98 99 return nil 100 }