githistory: rewrite tags pointing to tags

When rewriting history, we've ignored tags pointing to other tags. This
leads to problems for folks that are trying to shrink the size of their
repository, since they may still have tags that point to the old
history. Add additional handling for tags pointing to tags, recursively
rewriting the inner tags until we reach a commit.
This commit is contained in:
brian m. carlson 2019-06-24 15:55:17 +00:00
parent 5346eb49fb
commit ff410fa761
No known key found for this signature in database
GPG Key ID: 2D0C9BC12F82B3A1
2 changed files with 68 additions and 10 deletions

@ -57,12 +57,7 @@ func (r *refUpdater) UpdateRefs() error {
return nil
}
func (r *refUpdater) updateOneTag(tag *gitobj.Tag) ([]byte, error) {
toObj, okObj := r.CacheFn(tag.Object)
if !okObj {
return nil, nil
}
func (r *refUpdater) updateOneTag(tag *gitobj.Tag, toObj []byte) ([]byte, error) {
newTag, err := r.db.WriteTag(&gitobj.Tag{
Object: toObj,
ObjectType: tag.ObjectType,
@ -93,11 +88,43 @@ func (r *refUpdater) updateOneRef(list *tasklog.ListTask, maxNameLen int, seen m
if ref.Type == git.RefTypeLocalTag {
tag, _ := r.db.Tag(sha1)
if tag != nil && tag.ObjectType == gitobj.CommitObjectType {
// Assume that a non-nil error is an indication
// that the tag is bare (without annotation).
if tag != nil && tag.ObjectType == gitobj.TagObjectType {
innerTag, _ := r.db.Tag(tag.Object)
name := fmt.Sprintf("refs/tags/%s", innerTag.Name)
if _, ok := seen[name]; !ok {
old, err := git.ResolveRef(name)
if err != nil {
return err
}
newTag, err := r.updateOneTag(tag)
err = r.updateOneRef(list, maxNameLen, seen, old)
if err != nil {
return err
}
}
updated, err := git.ResolveRef(name)
if err != nil {
return err
}
updatedSha, err := hex.DecodeString(updated.Sha)
if err != nil {
return errors.Wrapf(err, "could not decode: %q", ref.Sha)
}
newTag, err := r.updateOneTag(tag, updatedSha)
if newTag == nil {
return err
}
to = newTag
ok = true
} else if tag != nil && tag.ObjectType == gitobj.CommitObjectType {
toObj, okObj := r.CacheFn(tag.Object)
if !okObj {
return nil
}
newTag, err := r.updateOneTag(tag, toObj)
if newTag == nil {
return err
}

@ -578,6 +578,37 @@ begin_test "migrate import (--everything and --include with glob pattern)"
)
end_test
begin_test "migrate import (--everything with tag pointing to tag)"
(
set -e
setup_multiple_local_branches
md_master_oid="$(calc_oid "$(git cat-file -p "refs/heads/master:a.md")")"
txt_master_oid="$(calc_oid "$(git cat-file -p "refs/heads/master:a.txt")")"
md_feature_oid="$(calc_oid "$(git cat-file -p "refs/heads/my-feature:a.md")")"
txt_feature_oid="$(calc_oid "$(git cat-file -p "refs/heads/my-feature:a.txt")")"
git tag -a -m abc abc refs/heads/master
git tag -a -m def def refs/tags/abc
git lfs migrate import --verbose --everything --include='*.[mM][dD]'
assert_pointer "refs/heads/master" "a.md" "$md_master_oid" "140"
assert_pointer "refs/tags/abc" "a.md" "$md_master_oid" "140"
assert_pointer "refs/tags/def" "a.md" "$md_master_oid" "140"
assert_pointer "refs/heads/my-feature" "a.md" "$md_feature_oid" "30"
git tag --points-at refs/tags/abc | grep -q def
! git tag --points-at refs/tags/def | grep -q abc
assert_local_object "$md_master_oid" "140"
assert_local_object "$md_feature_oid" "30"
refute_local_object "$txt_master_oid"
refute_local_object "$txt_feature_oid"
)
end_test
begin_test "migrate import (nested sub-trees and --include with wildcard)"
(
set -e