Merge branch 'master' into git-odb-no-extraline
This commit is contained in:
commit
aa4f5fe021
@ -121,6 +121,12 @@ func includeExcludeRefs(l *tasklog.Logger, args []string) (include, exclude []st
|
||||
}
|
||||
|
||||
for _, name := range args {
|
||||
var excluded bool
|
||||
if strings.HasPrefix("^", name) {
|
||||
name = name[1:]
|
||||
excluded = true
|
||||
}
|
||||
|
||||
// Then, loop through each branch given, resolve that reference,
|
||||
// and include it.
|
||||
ref, err := git.ResolveRef(name)
|
||||
@ -128,7 +134,11 @@ func includeExcludeRefs(l *tasklog.Logger, args []string) (include, exclude []st
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
include = append(include, ref.Refspec())
|
||||
if excluded {
|
||||
exclude = append(exclude, ref.Refspec())
|
||||
} else {
|
||||
include = append(include, ref.Refspec())
|
||||
}
|
||||
}
|
||||
|
||||
if hardcore {
|
||||
|
@ -39,6 +39,9 @@ git-lfs-migrate(1) - Migrate history to or from git-lfs
|
||||
Migrate only the set of branches listed. If not given, `git-lfs-migrate(1)`
|
||||
will migrate the currently checked out branch.
|
||||
|
||||
References beginning with '^' will be excluded, whereas branches that do not
|
||||
begin with '^' will be included.
|
||||
|
||||
If any of `--include-ref` or `--exclude-ref` are given, the checked out
|
||||
branch will not be appended, but branches given explicitly will be appended.
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
ref: refs/heads/master
|
@ -0,0 +1,7 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
0000000000000000000000000000000000000000 91b85be6928569390e937479509b80a1d0dccb0c Taylor Blau <me@ttaylorr.com> 1496954196 -0600 commit (initial): some.txt: a
|
||||
91b85be6928569390e937479509b80a1d0dccb0c 228afe30855933151f7a88e70d9d88314fd2f191 Taylor Blau <me@ttaylorr.com> 1496954207 -0600 commit: some.txt: b
|
||||
228afe30855933151f7a88e70d9d88314fd2f191 d941e4756add6b06f5bee766fcf669f55419f13f Taylor Blau <me@ttaylorr.com> 1496954214 -0600 commit: some.txt: c
|
@ -0,0 +1,3 @@
|
||||
0000000000000000000000000000000000000000 91b85be6928569390e937479509b80a1d0dccb0c Taylor Blau <me@ttaylorr.com> 1496954196 -0600 commit (initial): some.txt: a
|
||||
91b85be6928569390e937479509b80a1d0dccb0c 228afe30855933151f7a88e70d9d88314fd2f191 Taylor Blau <me@ttaylorr.com> 1496954207 -0600 commit: some.txt: b
|
||||
228afe30855933151f7a88e70d9d88314fd2f191 d941e4756add6b06f5bee766fcf669f55419f13f Taylor Blau <me@ttaylorr.com> 1496954214 -0600 commit: some.txt: c
|
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/05/797a38b05f910e6efe40dc1a5c0a046a9403e8
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/05/797a38b05f910e6efe40dc1a5c0a046a9403e8
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/20/ecedad3e74a113695fe5f00ab003694e2e1e9c
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/20/ecedad3e74a113695fe5f00ab003694e2e1e9c
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/22/8afe30855933151f7a88e70d9d88314fd2f191
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/22/8afe30855933151f7a88e70d9d88314fd2f191
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/2e/65efe2a145dda7ee51d1741299f848e5bf752e
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/2e/65efe2a145dda7ee51d1741299f848e5bf752e
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/34/10062ba67c5ed59b854387a8bc0ec012479368
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/34/10062ba67c5ed59b854387a8bc0ec012479368
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/3c/b3201d7942353fff5f45e03d114e8e7a061f87
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/3c/b3201d7942353fff5f45e03d114e8e7a061f87
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/4a/78e180c45f18489941174df19d538c26d5318b
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/4a/78e180c45f18489941174df19d538c26d5318b
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/52/a8963f48d54c7d352695a278ca4b025e130cb4
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/52/a8963f48d54c7d352695a278ca4b025e130cb4
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/63/d8dbd40c23542e740659a7168a0ce3138ea748
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/63/d8dbd40c23542e740659a7168a0ce3138ea748
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/6b/de0b381fa1a039396445e2ce5a28c0451fde15
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/6b/de0b381fa1a039396445e2ce5a28c0451fde15
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/91/b85be6928569390e937479509b80a1d0dccb0c
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/91/b85be6928569390e937479509b80a1d0dccb0c
Normal file
Binary file not shown.
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/d9/41e4756add6b06f5bee766fcf669f55419f13f
Normal file
BIN
git/githistory/fixtures/linear-history-with-annotated-tags.git/objects/d9/41e4756add6b06f5bee766fcf669f55419f13f
Normal file
Binary file not shown.
@ -0,0 +1 @@
|
||||
d941e4756add6b06f5bee766fcf669f55419f13f
|
@ -0,0 +1 @@
|
||||
05797a38b05f910e6efe40dc1a5c0a046a9403e8
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/git-lfs/git-lfs/errors"
|
||||
"github.com/git-lfs/git-lfs/git"
|
||||
"github.com/git-lfs/git-lfs/git/odb"
|
||||
"github.com/git-lfs/git-lfs/tasklog"
|
||||
"github.com/git-lfs/git-lfs/tools"
|
||||
)
|
||||
@ -25,6 +26,8 @@ type refUpdater struct {
|
||||
// Root is the given directory on disk in which the repository is
|
||||
// located.
|
||||
Root string
|
||||
|
||||
db *odb.ObjectDatabase
|
||||
}
|
||||
|
||||
// UpdateRefs performs the reference update(s) from existing locations (see:
|
||||
@ -51,6 +54,36 @@ func (r *refUpdater) UpdateRefs() error {
|
||||
}
|
||||
|
||||
to, ok := r.CacheFn(sha1)
|
||||
|
||||
if ref.Type == git.RefTypeLocalTag {
|
||||
tag, _ := r.db.Tag(sha1)
|
||||
if tag != nil && tag.ObjectType == odb.CommitObjectType {
|
||||
// Assume that a non-nil error is an indication
|
||||
// that the tag is bare (without annotation).
|
||||
|
||||
toObj, okObj := r.CacheFn(tag.Object)
|
||||
if !okObj {
|
||||
continue
|
||||
}
|
||||
|
||||
newTag, err := r.db.WriteTag(&odb.Tag{
|
||||
Object: toObj,
|
||||
ObjectType: tag.ObjectType,
|
||||
Name: tag.Name,
|
||||
Tagger: tag.Tagger,
|
||||
|
||||
Message: tag.Message,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not rewrite tag: %s", tag.Name)
|
||||
}
|
||||
|
||||
to = newTag
|
||||
ok = true
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ func TestRefUpdaterMovesRefs(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Root: root,
|
||||
db: db,
|
||||
}
|
||||
|
||||
err := updater.UpdateRefs()
|
||||
@ -36,6 +37,36 @@ func TestRefUpdaterMovesRefs(t *testing.T) {
|
||||
"refs/tags/middle", HexDecode(t, "d941e4756add6b06f5bee766fcf669f55419f13f"))
|
||||
}
|
||||
|
||||
func TestRefUpdaterMovesRefsWithAnnotatedTags(t *testing.T) {
|
||||
db := DatabaseFromFixture(t, "linear-history-with-annotated-tags.git")
|
||||
root, _ := db.Root()
|
||||
|
||||
AssertRef(t, db,
|
||||
"refs/tags/middle", HexDecode(t, "05797a38b05f910e6efe40dc1a5c0a046a9403e8"))
|
||||
|
||||
updater := &refUpdater{
|
||||
CacheFn: func(old []byte) ([]byte, bool) {
|
||||
return HexDecode(t, "d941e4756add6b06f5bee766fcf669f55419f13f"), true
|
||||
},
|
||||
Refs: []*git.Ref{
|
||||
{
|
||||
Name: "middle",
|
||||
Sha: "05797a38b05f910e6efe40dc1a5c0a046a9403e8",
|
||||
Type: git.RefTypeLocalTag,
|
||||
},
|
||||
},
|
||||
Root: root,
|
||||
db: db,
|
||||
}
|
||||
|
||||
err := updater.UpdateRefs()
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
AssertRef(t, db,
|
||||
"refs/tags/middle", HexDecode(t, "6873f9b24037dade0bd1d8a17b0913bf9a6a4f12"))
|
||||
}
|
||||
|
||||
func TestRefUpdaterIgnoresUnovedRefs(t *testing.T) {
|
||||
db := DatabaseFromFixture(t, "linear-history-with-tags.git")
|
||||
root, _ := db.Root()
|
||||
@ -55,6 +86,7 @@ func TestRefUpdaterIgnoresUnovedRefs(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Root: root,
|
||||
db: db,
|
||||
}
|
||||
|
||||
err := updater.UpdateRefs()
|
||||
|
@ -280,6 +280,8 @@ func (r *Rewriter) Rewrite(opt *RewriteOptions) ([]byte, error) {
|
||||
Logger: r.l,
|
||||
Refs: refs,
|
||||
Root: root,
|
||||
|
||||
db: r.db,
|
||||
}
|
||||
|
||||
if err := updater.UpdateRefs(); err != nil {
|
||||
|
@ -100,7 +100,7 @@ func (c *Commit) Decode(from io.Reader, size int64) (n int, err error) {
|
||||
text := s.Text()
|
||||
n = n + len(text+"\n")
|
||||
|
||||
if len(s.Text()) == 0 {
|
||||
if len(s.Text()) == 0 && !finishedHeaders {
|
||||
finishedHeaders = true
|
||||
continue
|
||||
}
|
||||
|
@ -117,6 +117,33 @@ func TestCommitDecodingWithMessageKeywordPrefix(t *testing.T) {
|
||||
treeId := []byte("aaaaaaaaaaaaaaaaaaaa")
|
||||
treeIdAscii := hex.EncodeToString(treeId)
|
||||
|
||||
from := new(bytes.Buffer)
|
||||
fmt.Fprintf(from, "author %s\n", author)
|
||||
fmt.Fprintf(from, "committer %s\n", committer)
|
||||
fmt.Fprintf(from, "tree %s\n", hex.EncodeToString(treeId))
|
||||
fmt.Fprintf(from, "\nfirst line\n\nsecond line\n")
|
||||
|
||||
flen := from.Len()
|
||||
|
||||
commit := new(Commit)
|
||||
n, err := commit.Decode(from, int64(flen))
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, flen, n)
|
||||
|
||||
assert.Equal(t, author.String(), commit.Author)
|
||||
assert.Equal(t, committer.String(), commit.Committer)
|
||||
assert.Equal(t, treeIdAscii, hex.EncodeToString(commit.TreeID))
|
||||
assert.Equal(t, "first line\n\nsecond line", commit.Message)
|
||||
}
|
||||
|
||||
func TestCommitDecodingWithWhitespace(t *testing.T) {
|
||||
author := &Signature{Name: "John Doe", Email: "john@example.com", When: time.Now()}
|
||||
committer := &Signature{Name: "Jane Doe", Email: "jane@example.com", When: time.Now()}
|
||||
|
||||
treeId := []byte("aaaaaaaaaaaaaaaaaaaa")
|
||||
treeIdAscii := hex.EncodeToString(treeId)
|
||||
|
||||
from := new(bytes.Buffer)
|
||||
fmt.Fprintf(from, "author %s\n", author)
|
||||
fmt.Fprintf(from, "committer %s\n", committer)
|
||||
|
@ -96,6 +96,17 @@ func (o *ObjectDatabase) Commit(sha []byte) (*Commit, error) {
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// Tag returns a *Tag as identified by the SHA given, or an error if one was
|
||||
// encountered.
|
||||
func (o *ObjectDatabase) Tag(sha []byte) (*Tag, error) {
|
||||
var t Tag
|
||||
|
||||
if err := o.decode(sha, &t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &t, nil
|
||||
}
|
||||
|
||||
// WriteBlob stores a *Blob on disk and returns the SHA it is uniquely
|
||||
// identified by, or an error if one was encountered.
|
||||
func (o *ObjectDatabase) WriteBlob(b *Blob) ([]byte, error) {
|
||||
@ -137,6 +148,16 @@ func (o *ObjectDatabase) WriteCommit(c *Commit) ([]byte, error) {
|
||||
return sha, nil
|
||||
}
|
||||
|
||||
// WriteTag stores a *Tag on disk and returns the SHA it is uniquely identified
|
||||
// by, or an error if one was encountered.
|
||||
func (o *ObjectDatabase) WriteTag(t *Tag) ([]byte, error) {
|
||||
sha, _, err := o.encode(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sha, nil
|
||||
}
|
||||
|
||||
// Root returns the filesystem root that this *ObjectDatabase works within, if
|
||||
// backed by a fileStorer (constructed by FromFilesystem). If so, it returns
|
||||
// the fully-qualified path on a disk and a value of true.
|
||||
|
@ -166,6 +166,57 @@ func TestWriteCommit(t *testing.T) {
|
||||
assert.NotNil(t, fs.fs[hex.EncodeToString(sha)])
|
||||
}
|
||||
|
||||
func TestDecodeTag(t *testing.T) {
|
||||
const sha = "7639ba293cd2c457070e8446ecdea56682af0f48"
|
||||
tagShaHex, err := hex.DecodeString(sha)
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
zw := zlib.NewWriter(&buf)
|
||||
fmt.Fprintf(zw, "tag 165\x00")
|
||||
fmt.Fprintf(zw, "object 6161616161616161616161616161616161616161\n")
|
||||
fmt.Fprintf(zw, "type commit\n")
|
||||
fmt.Fprintf(zw, "tag v2.4.0\n")
|
||||
fmt.Fprintf(zw, "tagger A U Thor <author@example.com>\n")
|
||||
fmt.Fprintf(zw, "\n")
|
||||
fmt.Fprintf(zw, "The quick brown fox jumps over the lazy dog.\n")
|
||||
zw.Close()
|
||||
|
||||
odb := &ObjectDatabase{s: newMemoryStorer(map[string]io.ReadWriter{
|
||||
sha: &buf,
|
||||
})}
|
||||
|
||||
tag, err := odb.Tag(tagShaHex)
|
||||
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, []byte("aaaaaaaaaaaaaaaaaaaa"), tag.Object)
|
||||
assert.Equal(t, CommitObjectType, tag.ObjectType)
|
||||
assert.Equal(t, "v2.4.0", tag.Name)
|
||||
assert.Equal(t, "A U Thor <author@example.com>", tag.Tagger)
|
||||
assert.Equal(t, "The quick brown fox jumps over the lazy dog.", tag.Message)
|
||||
}
|
||||
|
||||
func TestWriteTag(t *testing.T) {
|
||||
fs := newMemoryStorer(make(map[string]io.ReadWriter))
|
||||
odb := &ObjectDatabase{s: fs}
|
||||
|
||||
sha, err := odb.WriteTag(&Tag{
|
||||
Object: []byte("aaaaaaaaaaaaaaaaaaaa"),
|
||||
ObjectType: CommitObjectType,
|
||||
Name: "v2.4.0",
|
||||
Tagger: "A U Thor <author@example.com>",
|
||||
|
||||
Message: "The quick brown fox jumps over the lazy dog.",
|
||||
})
|
||||
|
||||
expected := "b0ea0039d536fb739dfa44e74e488b635bbb3a86"
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, expected, hex.EncodeToString(sha))
|
||||
assert.NotNil(t, fs.fs[hex.EncodeToString(sha)])
|
||||
}
|
||||
|
||||
func TestReadingAMissingObjectAfterClose(t *testing.T) {
|
||||
sha, _ := hex.DecodeString("af5626b4a114abcb82d63db7c8082c3c4756e51b")
|
||||
|
||||
|
@ -11,6 +11,7 @@ const (
|
||||
BlobObjectType
|
||||
TreeObjectType
|
||||
CommitObjectType
|
||||
TagObjectType
|
||||
)
|
||||
|
||||
// ObjectTypeFromString converts from a given string to an ObjectType
|
||||
@ -23,6 +24,8 @@ func ObjectTypeFromString(s string) ObjectType {
|
||||
return TreeObjectType
|
||||
case "commit":
|
||||
return CommitObjectType
|
||||
case "tag":
|
||||
return TagObjectType
|
||||
default:
|
||||
return UnknownObjectType
|
||||
}
|
||||
@ -40,6 +43,8 @@ func (t ObjectType) String() string {
|
||||
return "tree"
|
||||
case CommitObjectType:
|
||||
return "commit"
|
||||
case TagObjectType:
|
||||
return "tag"
|
||||
}
|
||||
return "<unknown>"
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ func TestObjectTypeFromString(t *testing.T) {
|
||||
"blob": BlobObjectType,
|
||||
"tree": TreeObjectType,
|
||||
"commit": CommitObjectType,
|
||||
"tag": TagObjectType,
|
||||
"something else": UnknownObjectType,
|
||||
} {
|
||||
t.Run(str, func(t *testing.T) {
|
||||
@ -25,6 +26,7 @@ func TestObjectTypeToString(t *testing.T) {
|
||||
BlobObjectType: "blob",
|
||||
TreeObjectType: "tree",
|
||||
CommitObjectType: "commit",
|
||||
TagObjectType: "tag",
|
||||
UnknownObjectType: "unknown",
|
||||
ObjectType(math.MaxUint8): "<unknown>",
|
||||
} {
|
||||
|
118
git/odb/tag.go
Normal file
118
git/odb/tag.go
Normal file
@ -0,0 +1,118 @@
|
||||
package odb
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/git-lfs/git-lfs/errors"
|
||||
)
|
||||
|
||||
type Tag struct {
|
||||
Object []byte
|
||||
ObjectType ObjectType
|
||||
Name string
|
||||
Tagger string
|
||||
|
||||
Message string
|
||||
}
|
||||
|
||||
// Decode implements Object.Decode and decodes the uncompressed tag being
|
||||
// read. It returns the number of uncompressed bytes being consumed off of the
|
||||
// stream, which should be strictly equal to the size given.
|
||||
//
|
||||
// If any error was encountered along the way it will be returned, and the
|
||||
// receiving *Tag is considered invalid.
|
||||
func (t *Tag) Decode(r io.Reader, size int64) (int, error) {
|
||||
scanner := bufio.NewScanner(io.LimitReader(r, size))
|
||||
|
||||
var (
|
||||
finishedHeaders bool
|
||||
message []string
|
||||
)
|
||||
|
||||
for scanner.Scan() {
|
||||
if finishedHeaders {
|
||||
message = append(message, scanner.Text())
|
||||
} else {
|
||||
if len(scanner.Bytes()) == 0 {
|
||||
finishedHeaders = true
|
||||
continue
|
||||
}
|
||||
|
||||
parts := strings.SplitN(scanner.Text(), " ", 2)
|
||||
if len(parts) < 2 {
|
||||
return 0, errors.Errorf("git/odb: invalid tag header: %s", scanner.Text())
|
||||
}
|
||||
|
||||
switch parts[0] {
|
||||
case "object":
|
||||
sha, err := hex.DecodeString(parts[1])
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "git/odb: unable to decode SHA-1")
|
||||
}
|
||||
|
||||
t.Object = sha
|
||||
case "type":
|
||||
t.ObjectType = ObjectTypeFromString(parts[1])
|
||||
case "tag":
|
||||
t.Name = parts[1]
|
||||
case "tagger":
|
||||
t.Tagger = parts[1]
|
||||
default:
|
||||
return 0, errors.Errorf("git/odb: unknown tag header: %s", parts[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
t.Message = strings.Join(message, "\n")
|
||||
|
||||
return int(size), nil
|
||||
}
|
||||
|
||||
// Encode encodes the Tag's contents to the given io.Writer, "w". If there was
|
||||
// any error copying the Tag's contents, that error will be returned.
|
||||
//
|
||||
// Otherwise, the number of bytes written will be returned.
|
||||
func (t *Tag) Encode(w io.Writer) (int, error) {
|
||||
headers := []string{
|
||||
fmt.Sprintf("object %s", hex.EncodeToString(t.Object)),
|
||||
fmt.Sprintf("type %s", t.ObjectType),
|
||||
fmt.Sprintf("tag %s", t.Name),
|
||||
fmt.Sprintf("tagger %s", t.Tagger),
|
||||
}
|
||||
|
||||
return fmt.Fprintf(w, "%s\n\n%s\n", strings.Join(headers, "\n"), t.Message)
|
||||
}
|
||||
|
||||
// Equal returns whether the receiving and given Tags are equal, or in other
|
||||
// words, whether they are represented by the same SHA-1 when saved to the
|
||||
// object database.
|
||||
func (t *Tag) Equal(other *Tag) bool {
|
||||
if (t == nil) != (other == nil) {
|
||||
return false
|
||||
}
|
||||
|
||||
if t != nil {
|
||||
return bytes.Equal(t.Object, other.Object) &&
|
||||
t.ObjectType == other.ObjectType &&
|
||||
t.Name == other.Name &&
|
||||
t.Tagger == other.Tagger &&
|
||||
t.Message == other.Message
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Type implements Object.ObjectType by returning the correct object type for
|
||||
// Tags, TagObjectType.
|
||||
func (t *Tag) Type() ObjectType {
|
||||
return TagObjectType
|
||||
}
|
65
git/odb/tag_test.go
Normal file
65
git/odb/tag_test.go
Normal file
@ -0,0 +1,65 @@
|
||||
package odb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTagTypeReturnsCorrectObjectType(t *testing.T) {
|
||||
assert.Equal(t, TagObjectType, new(Tag).Type())
|
||||
}
|
||||
|
||||
func TestTagEncode(t *testing.T) {
|
||||
tag := &Tag{
|
||||
Object: []byte("aaaaaaaaaaaaaaaaaaaa"),
|
||||
ObjectType: CommitObjectType,
|
||||
Name: "v2.4.0",
|
||||
Tagger: "A U Thor <author@example.com>",
|
||||
|
||||
Message: "The quick brown fox jumps over the lazy dog.",
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
n, err := tag.Encode(buf)
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.EqualValues(t, buf.Len(), n)
|
||||
|
||||
assertLine(t, buf, "object 6161616161616161616161616161616161616161")
|
||||
assertLine(t, buf, "type commit")
|
||||
assertLine(t, buf, "tag v2.4.0")
|
||||
assertLine(t, buf, "tagger A U Thor <author@example.com>")
|
||||
assertLine(t, buf, "")
|
||||
assertLine(t, buf, "The quick brown fox jumps over the lazy dog.")
|
||||
|
||||
assert.Equal(t, 0, buf.Len())
|
||||
}
|
||||
|
||||
func TestTagDecode(t *testing.T) {
|
||||
from := new(bytes.Buffer)
|
||||
|
||||
fmt.Fprintf(from, "object 6161616161616161616161616161616161616161\n")
|
||||
fmt.Fprintf(from, "type commit\n")
|
||||
fmt.Fprintf(from, "tag v2.4.0\n")
|
||||
fmt.Fprintf(from, "tagger A U Thor <author@example.com>\n")
|
||||
fmt.Fprintf(from, "\n")
|
||||
fmt.Fprintf(from, "The quick brown fox jumps over the lazy dog.\n")
|
||||
|
||||
flen := from.Len()
|
||||
|
||||
tag := new(Tag)
|
||||
n, err := tag.Decode(from, int64(flen))
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, n, flen)
|
||||
|
||||
assert.Equal(t, []byte("aaaaaaaaaaaaaaaaaaaa"), tag.Object)
|
||||
assert.Equal(t, CommitObjectType, tag.ObjectType)
|
||||
assert.Equal(t, "v2.4.0", tag.Name)
|
||||
assert.Equal(t, "A U Thor <author@example.com>", tag.Tagger)
|
||||
assert.Equal(t, "The quick brown fox jumps over the lazy dog.", tag.Message)
|
||||
}
|
@ -159,6 +159,67 @@ setup_multiple_remote_branches() {
|
||||
git checkout master
|
||||
}
|
||||
|
||||
# setup_single_local_branch_with_tags creates a repository as follows:
|
||||
#
|
||||
# A---B
|
||||
# |\
|
||||
# | refs/heads/master
|
||||
# |
|
||||
# \
|
||||
# refs/tags/v1.0.0
|
||||
#
|
||||
# - Commit 'A' has 1 byte of data in 'a.txt'
|
||||
# - Commit 'B' has 2 bytes of data in 'a.txt', and is tagged at 'v1.0.0'.
|
||||
setup_single_local_branch_with_tags() {
|
||||
set -e
|
||||
|
||||
reponame="migrate-single-local-branch-tags"
|
||||
|
||||
remove_and_create_local_repo "$reponame"
|
||||
|
||||
base64 < /dev/urandom | head -c 1 > a.txt
|
||||
|
||||
git add a.txt
|
||||
git commit -m "initial commit"
|
||||
|
||||
base64 < /dev/urandom | head -c 2 > a.txt
|
||||
|
||||
git add a.txt
|
||||
git commit -m "secondary commit"
|
||||
git tag "v1.0.0"
|
||||
}
|
||||
|
||||
# setup_single_local_branch_with_annotated_tags creates a repository as follows:
|
||||
#
|
||||
# A---B
|
||||
# |\
|
||||
# | refs/heads/master
|
||||
# |
|
||||
# \
|
||||
# refs/tags/v1.0.0 (annotated)
|
||||
#
|
||||
# - Commit 'A' has 1 byte of data in 'a.txt'
|
||||
# - Commit 'B' has 2 bytes of data in 'a.txt', and is tagged (with annotation)
|
||||
# at 'v1.0.0'.
|
||||
setup_single_local_branch_with_annotated_tags() {
|
||||
set -e
|
||||
|
||||
reponame="migrate-single-local-branch-annotated-tags"
|
||||
|
||||
remove_and_create_local_repo "$reponame"
|
||||
|
||||
base64 < /dev/urandom | head -c 1 > a.txt
|
||||
|
||||
git add a.txt
|
||||
git commit -m "initial commit"
|
||||
|
||||
base64 < /dev/urandom | head -c 2 > a.txt
|
||||
|
||||
git add a.txt
|
||||
git commit -m "secondary commit"
|
||||
git tag "v1.0.0" -m "v1.0.0"
|
||||
}
|
||||
|
||||
# setup_single_local_branch_deep_trees creates a repository as follows:
|
||||
#
|
||||
# A
|
||||
|
@ -253,6 +253,40 @@ begin_test "migrate import (given ref, --skip-fetch)"
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "migrate import (un-annotated tags)"
|
||||
(
|
||||
set -e
|
||||
|
||||
setup_single_local_branch_with_tags
|
||||
|
||||
txt_master_oid="$(calc_oid "$(git cat-file -p "refs/heads/master:a.txt")")"
|
||||
|
||||
git lfs migrate import --everything
|
||||
|
||||
assert_pointer "refs/heads/master" "a.txt" "$txt_master_oid" "2"
|
||||
assert_local_object "$txt_master_oid" "2"
|
||||
|
||||
git tag --points-at "$(git rev-parse HEAD)" | grep -q "v1.0.0"
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "migrate import (annotated tags)"
|
||||
(
|
||||
set -e
|
||||
|
||||
setup_single_local_branch_with_annotated_tags
|
||||
|
||||
txt_master_oid="$(calc_oid "$(git cat-file -p "refs/heads/master:a.txt")")"
|
||||
|
||||
git lfs migrate import --everything
|
||||
|
||||
assert_pointer "refs/heads/master" "a.txt" "$txt_master_oid" "2"
|
||||
assert_local_object "$txt_master_oid" "2"
|
||||
|
||||
git tag --points-at "$(git rev-parse HEAD)" | grep -q "v1.0.0"
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "migrate import (include/exclude ref)"
|
||||
(
|
||||
set -e
|
||||
@ -293,6 +327,44 @@ begin_test "migrate import (include/exclude ref)"
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "migrate import (include/exclude ref args)"
|
||||
(
|
||||
set -e
|
||||
|
||||
setup_multiple_remote_branches
|
||||
|
||||
md_master_oid="$(calc_oid "$(git cat-file -p "refs/heads/master:a.md")")"
|
||||
md_remote_oid="$(calc_oid "$(git cat-file -p "refs/remotes/origin/master:a.md")")"
|
||||
md_feature_oid="$(calc_oid "$(git cat-file -p "refs/heads/my-feature:a.md")")"
|
||||
txt_master_oid="$(calc_oid "$(git cat-file -p "refs/heads/master:a.txt")")"
|
||||
txt_remote_oid="$(calc_oid "$(git cat-file -p "refs/remotes/origin/master:a.txt")")"
|
||||
txt_feature_oid="$(calc_oid "$(git cat-file -p "refs/heads/my-feature:a.txt")")"
|
||||
|
||||
git lfs migrate import my-feature ^master
|
||||
|
||||
assert_pointer "refs/heads/my-feature" "a.md" "$md_feature_oid" "31"
|
||||
assert_pointer "refs/heads/my-feature" "a.txt" "$txt_feature_oid" "30"
|
||||
|
||||
assert_local_object "$md_feature_oid" "31"
|
||||
refute_local_object "$md_master_oid" "21"
|
||||
assert_local_object "$txt_feature_oid" "30"
|
||||
refute_local_object "$txt_master_oid" "20"
|
||||
refute_local_object "$md_remote_oid" "11"
|
||||
refute_local_object "$txt_remote_oid" "10"
|
||||
|
||||
master="$(git rev-parse refs/heads/master)"
|
||||
feature="$(git rev-parse refs/heads/my-feature)"
|
||||
remote="$(git rev-parse refs/remotes/origin/master)"
|
||||
|
||||
[ ! $(git cat-file -p "$master:.gitattributes") ]
|
||||
[ ! $(git cat-file -p "$remote:.gitattributes") ]
|
||||
feature_attrs="$(git cat-file -p "$feature:.gitattributes")"
|
||||
|
||||
echo "$feature_attrs" | grep -q "*.md filter=lfs diff=lfs merge=lfs"
|
||||
echo "$feature_attrs" | grep -q "*.txt filter=lfs diff=lfs merge=lfs"
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "migrate import (include/exclude ref with filter)"
|
||||
(
|
||||
set -e
|
||||
|
@ -193,6 +193,29 @@ begin_test "migrate info (include/exclude ref)"
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "migrate info (include/exclude ref args)"
|
||||
(
|
||||
set -e
|
||||
|
||||
setup_multiple_remote_branches
|
||||
|
||||
original_master="$(git rev-parse refs/heads/master)"
|
||||
original_feature="$(git rev-parse refs/heads/my-feature)"
|
||||
|
||||
diff -u <(git lfs migrate info \
|
||||
my-feature ^master 2>&1 | tail -n 2) <(cat <<-EOF
|
||||
*.md 31 B 1/1 files(s) 100%
|
||||
*.txt 30 B 1/1 files(s) 100%
|
||||
EOF)
|
||||
|
||||
migrated_master="$(git rev-parse refs/heads/master)"
|
||||
migrated_feature="$(git rev-parse refs/heads/my-feature)"
|
||||
|
||||
assert_ref_unmoved "refs/heads/master" "$original_master" "$migrated_master"
|
||||
assert_ref_unmoved "refs/heads/my-feature" "$original_feature" "$migrated_feature"
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "migrate info (include/exclude ref with filter)"
|
||||
(
|
||||
set -e
|
||||
|
Loading…
Reference in New Issue
Block a user