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  }