Skip to content

Commit 408a484

Browse files
authored
Adjust object format interface (#28469)
- Remove `ObjectFormatID` - Remove function `ObjectFormatFromID`. - Use `Sha1ObjectFormat` directly but not a pointer because it's an empty struct. - Store `ObjectFormatName` in `repository` struct
1 parent 7fb6b51 commit 408a484

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+190
-202
lines changed

models/git/branch_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
func TestAddDeletedBranch(t *testing.T) {
2121
assert.NoError(t, unittest.PrepareTestDatabase())
2222
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
23+
assert.EqualValues(t, git.Sha1ObjectFormat.Name(), repo.ObjectFormatName)
2324
firstBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{ID: 1})
2425

2526
assert.True(t, firstBranch.IsDeleted)
@@ -29,8 +30,9 @@ func TestAddDeletedBranch(t *testing.T) {
2930
secondBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo.ID, Name: "branch2"})
3031
assert.True(t, secondBranch.IsDeleted)
3132

33+
objectFormat := git.ObjectFormatFromName(repo.ObjectFormatName)
3234
commit := &git.Commit{
33-
ID: repo.ObjectFormat.MustIDFromString(secondBranch.CommitID),
35+
ID: objectFormat.MustIDFromString(secondBranch.CommitID),
3436
CommitMessage: secondBranch.CommitMessage,
3537
Committer: &git.Signature{
3638
When: secondBranch.CommitTime.AsLocalTime(),

models/repo/repo.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ type Repository struct {
180180
IsFsckEnabled bool `xorm:"NOT NULL DEFAULT true"`
181181
CloseIssuesViaCommitInAnyBranch bool `xorm:"NOT NULL DEFAULT false"`
182182
Topics []string `xorm:"TEXT JSON"`
183-
ObjectFormat git.ObjectFormat `xorm:"-"`
183+
ObjectFormatName string `xorm:"-"`
184184

185185
TrustModel TrustModelType
186186

@@ -277,7 +277,9 @@ func (repo *Repository) AfterLoad() {
277277
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
278278
repo.NumOpenActionRuns = repo.NumActionRuns - repo.NumClosedActionRuns
279279

280-
repo.ObjectFormat = git.ObjectFormatFromID(git.Sha1)
280+
// this is a temporary behaviour to support old repos, next step is to store the object format in the database
281+
// and read from database so this line could be removed. To not depend on git module, we use a constant variable here
282+
repo.ObjectFormatName = "sha1"
281283
}
282284

283285
// LoadAttributes loads attributes of the repository.

modules/git/blame_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func TestReadingBlameOutput(t *testing.T) {
3939
}
4040

4141
for _, bypass := range []bool{false, true} {
42-
blameReader, err := CreateBlameReader(ctx, &Sha1ObjectFormat{}, "./tests/repos/repo5_pulls", commit, "README.md", bypass)
42+
blameReader, err := CreateBlameReader(ctx, Sha1ObjectFormat, "./tests/repos/repo5_pulls", commit, "README.md", bypass)
4343
assert.NoError(t, err)
4444
assert.NotNil(t, blameReader)
4545
defer blameReader.Close()

modules/git/commit.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ func (c *Commit) IsForcePush(oldCommitID string) (bool, error) {
236236
if err != nil {
237237
return false, err
238238
}
239-
if oldCommitID == objectFormat.Empty().String() {
239+
if oldCommitID == objectFormat.EmptyObjectID().String() {
240240
return false, nil
241241
}
242242

modules/git/object_format.go

+37-42
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,17 @@ package git
55

66
import (
77
"crypto/sha1"
8-
"fmt"
98
"regexp"
10-
"strings"
11-
)
12-
13-
type ObjectFormatID int
14-
15-
const (
16-
Sha1 ObjectFormatID = iota
179
)
1810

1911
// sha1Pattern can be used to determine if a string is an valid sha
2012
var sha1Pattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
2113

2214
type ObjectFormat interface {
23-
ID() ObjectFormatID
24-
String() string
25-
26-
// Empty is the hash of empty git
27-
Empty() ObjectID
15+
// Name returns the name of the object format
16+
Name() string
17+
// EmptyObjectID creates a new empty ObjectID from an object format hash name
18+
EmptyObjectID() ObjectID
2819
// EmptyTree is the hash of an empty tree
2920
EmptyTree() ObjectID
3021
// FullLength is the length of the hash's hex string
@@ -35,67 +26,71 @@ type ObjectFormat interface {
3526
MustIDFromString(s string) ObjectID
3627
NewID(b []byte) (ObjectID, error)
3728
NewIDFromString(s string) (ObjectID, error)
38-
NewEmptyID() ObjectID
3929

4030
NewHasher() HasherInterface
4131
}
4232

43-
type Sha1ObjectFormat struct{}
33+
type Sha1ObjectFormatImpl struct{}
4434

45-
func (*Sha1ObjectFormat) ID() ObjectFormatID { return Sha1 }
46-
func (*Sha1ObjectFormat) String() string { return "sha1" }
47-
func (*Sha1ObjectFormat) Empty() ObjectID { return &Sha1Hash{} }
48-
func (*Sha1ObjectFormat) EmptyTree() ObjectID {
49-
return &Sha1Hash{
35+
var (
36+
emptyObjectID = &Sha1Hash{}
37+
emptyTree = &Sha1Hash{
5038
0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
5139
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,
5240
}
41+
)
42+
43+
func (Sha1ObjectFormatImpl) Name() string { return "sha1" }
44+
func (Sha1ObjectFormatImpl) EmptyObjectID() ObjectID {
45+
return emptyObjectID
46+
}
47+
48+
func (Sha1ObjectFormatImpl) EmptyTree() ObjectID {
49+
return emptyTree
5350
}
54-
func (*Sha1ObjectFormat) FullLength() int { return 40 }
55-
func (*Sha1ObjectFormat) IsValid(input string) bool {
51+
func (Sha1ObjectFormatImpl) FullLength() int { return 40 }
52+
func (Sha1ObjectFormatImpl) IsValid(input string) bool {
5653
return sha1Pattern.MatchString(input)
5754
}
5855

59-
func (*Sha1ObjectFormat) MustID(b []byte) ObjectID {
56+
func (Sha1ObjectFormatImpl) MustID(b []byte) ObjectID {
6057
var id Sha1Hash
6158
copy(id[0:20], b)
6259
return &id
6360
}
6461

65-
func (h *Sha1ObjectFormat) MustIDFromString(s string) ObjectID {
62+
func (h Sha1ObjectFormatImpl) MustIDFromString(s string) ObjectID {
6663
return MustIDFromString(h, s)
6764
}
6865

69-
func (h *Sha1ObjectFormat) NewID(b []byte) (ObjectID, error) {
66+
func (h Sha1ObjectFormatImpl) NewID(b []byte) (ObjectID, error) {
7067
return IDFromRaw(h, b)
7168
}
7269

73-
func (h *Sha1ObjectFormat) NewIDFromString(s string) (ObjectID, error) {
70+
func (h Sha1ObjectFormatImpl) NewIDFromString(s string) (ObjectID, error) {
7471
return genericIDFromString(h, s)
7572
}
7673

77-
func (*Sha1ObjectFormat) NewEmptyID() ObjectID {
78-
return NewSha1()
79-
}
80-
81-
func (h *Sha1ObjectFormat) NewHasher() HasherInterface {
74+
func (h Sha1ObjectFormatImpl) NewHasher() HasherInterface {
8275
return &Sha1Hasher{sha1.New()}
8376
}
8477

85-
func ObjectFormatFromID(id ObjectFormatID) ObjectFormat {
86-
switch id {
87-
case Sha1:
88-
return &Sha1ObjectFormat{}
89-
}
78+
var Sha1ObjectFormat ObjectFormat = Sha1ObjectFormatImpl{}
9079

91-
return nil
80+
var SupportedObjectFormats = []ObjectFormat{
81+
Sha1ObjectFormat,
82+
// TODO: add sha256
9283
}
9384

94-
func ObjectFormatFromString(hash string) (ObjectFormat, error) {
95-
switch strings.ToLower(hash) {
96-
case "sha1":
97-
return &Sha1ObjectFormat{}, nil
85+
func ObjectFormatFromName(name string) ObjectFormat {
86+
for _, objectFormat := range SupportedObjectFormats {
87+
if name == objectFormat.Name() {
88+
return objectFormat
89+
}
9890
}
91+
return nil
92+
}
9993

100-
return nil, fmt.Errorf("unknown hash type: %s", hash)
94+
func IsValidObjectFormat(name string) bool {
95+
return ObjectFormatFromName(name) != nil
10196
}

modules/git/object_id.go

+13-20
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,23 @@ func (h *Sha1Hash) IsZero() bool {
3131
return bytes.Equal(empty[:], h[:])
3232
}
3333
func (h *Sha1Hash) RawValue() []byte { return h[:] }
34-
func (*Sha1Hash) Type() ObjectFormat { return &Sha1ObjectFormat{} }
34+
func (*Sha1Hash) Type() ObjectFormat { return Sha1ObjectFormat }
3535

36-
func NewSha1() *Sha1Hash {
37-
return &Sha1Hash{}
38-
}
36+
var _ ObjectID = &Sha1Hash{}
3937

40-
// NewHash is for generic implementations
41-
func NewHash(hash string) (ObjectID, error) {
42-
hash = strings.ToLower(hash)
43-
switch hash {
44-
case "sha1":
45-
return &Sha1Hash{}, nil
38+
// EmptyObjectID creates a new ObjectID from an object format hash name
39+
func EmptyObjectID(objectFormatName string) (ObjectID, error) {
40+
objectFormat := ObjectFormatFromName(objectFormatName)
41+
if objectFormat != nil {
42+
return objectFormat.EmptyObjectID(), nil
4643
}
4744

4845
return nil, errors.New("unsupported hash type")
4946
}
5047

5148
func IDFromRaw(h ObjectFormat, b []byte) (ObjectID, error) {
5249
if len(b) != h.FullLength()/2 {
53-
return h.Empty(), fmt.Errorf("length must be %d: %v", h.FullLength(), b)
50+
return h.EmptyObjectID(), fmt.Errorf("length must be %d: %v", h.FullLength(), b)
5451
}
5552
return h.MustID(b), nil
5653
}
@@ -63,24 +60,20 @@ func MustIDFromString(h ObjectFormat, s string) ObjectID {
6360
func genericIDFromString(h ObjectFormat, s string) (ObjectID, error) {
6461
s = strings.TrimSpace(s)
6562
if len(s) != h.FullLength() {
66-
return h.Empty(), fmt.Errorf("length must be %d: %s", h.FullLength(), s)
63+
return h.EmptyObjectID(), fmt.Errorf("length must be %d: %s", h.FullLength(), s)
6764
}
6865
b, err := hex.DecodeString(s)
6966
if err != nil {
70-
return h.Empty(), err
67+
return h.EmptyObjectID(), err
7168
}
7269
return h.NewID(b)
7370
}
7471

7572
func IDFromString(hexHash string) (ObjectID, error) {
76-
switch len(hexHash) {
77-
case 40:
78-
hashType := Sha1ObjectFormat{}
79-
h, err := hashType.NewIDFromString(hexHash)
80-
if err != nil {
81-
return nil, err
73+
for _, objectFormat := range SupportedObjectFormats {
74+
if len(hexHash) == objectFormat.FullLength() {
75+
return objectFormat.NewIDFromString(hexHash)
8276
}
83-
return h, nil
8477
}
8578

8679
return nil, fmt.Errorf("invalid hash hex string: '%s' len: %d", hexHash, len(hexHash))

modules/git/object_id_gogit.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
func ParseGogitHash(h plumbing.Hash) ObjectID {
1313
switch hash.Size {
1414
case 20:
15-
return ObjectFormatFromID(Sha1).MustID(h[:])
15+
return Sha1ObjectFormat.MustID(h[:])
1616
}
1717

1818
return nil

modules/git/object_id_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
)
1111

1212
func TestIsValidSHAPattern(t *testing.T) {
13-
h := NewSha1().Type()
13+
h := Sha1ObjectFormat
1414
assert.True(t, h.IsValid("fee1"))
1515
assert.True(t, h.IsValid("abc000"))
1616
assert.True(t, h.IsValid("9023902390239023902390239023902390239023"))

modules/git/parse_gogit_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ func TestParseTreeEntries(t *testing.T) {
2828
Input: "100644 blob 61ab7345a1a3bbc590068ccae37b8515cfc5843c 1022\texample/file2.txt\n",
2929
Expected: []*TreeEntry{
3030
{
31-
ID: ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
31+
ID: Sha1ObjectFormat.MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
3232
gogitTreeEntry: &object.TreeEntry{
33-
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
33+
Hash: plumbing.Hash(Sha1ObjectFormat.MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
3434
Name: "example/file2.txt",
3535
Mode: filemode.Regular,
3636
},
@@ -44,20 +44,20 @@ func TestParseTreeEntries(t *testing.T) {
4444
"040000 tree 1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8 -\texample\n",
4545
Expected: []*TreeEntry{
4646
{
47-
ID: ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
47+
ID: Sha1ObjectFormat.MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
4848
gogitTreeEntry: &object.TreeEntry{
49-
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
49+
Hash: plumbing.Hash(Sha1ObjectFormat.MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
5050
Name: "example/\n.txt",
5151
Mode: filemode.Symlink,
5252
},
5353
size: 234131,
5454
sized: true,
5555
},
5656
{
57-
ID: ObjectFormatFromID(Sha1).MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8"),
57+
ID: Sha1ObjectFormat.MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8"),
5858
sized: true,
5959
gogitTreeEntry: &object.TreeEntry{
60-
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8").RawValue()),
60+
Hash: plumbing.Hash(Sha1ObjectFormat.MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8").RawValue()),
6161
Name: "example",
6262
Mode: filemode.Dir,
6363
},
@@ -67,7 +67,7 @@ func TestParseTreeEntries(t *testing.T) {
6767
}
6868

6969
for _, testCase := range testCases {
70-
entries, err := ParseTreeEntries(ObjectFormatFromID(Sha1), []byte(testCase.Input))
70+
entries, err := ParseTreeEntries(Sha1ObjectFormat, []byte(testCase.Input))
7171
assert.NoError(t, err)
7272
if len(entries) > 1 {
7373
fmt.Println(testCase.Expected[0].ID)

modules/git/parse_nogogit_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
)
1313

1414
func TestParseTreeEntriesLong(t *testing.T) {
15-
objectFormat := ObjectFormatFromID(Sha1)
15+
objectFormat := Sha1ObjectFormat
1616

1717
testCases := []struct {
1818
Input string
@@ -66,7 +66,7 @@ func TestParseTreeEntriesLong(t *testing.T) {
6666
}
6767

6868
func TestParseTreeEntriesShort(t *testing.T) {
69-
objectFormat := ObjectFormatFromID(Sha1)
69+
objectFormat := Sha1ObjectFormat
7070

7171
testCases := []struct {
7272
Input string
@@ -102,7 +102,7 @@ func TestParseTreeEntriesShort(t *testing.T) {
102102

103103
func TestParseTreeEntriesInvalid(t *testing.T) {
104104
// there was a panic: "runtime error: slice bounds out of range" when the input was invalid: #20315
105-
entries, err := ParseTreeEntries(ObjectFormatFromID(Sha1), []byte("100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af"))
105+
entries, err := ParseTreeEntries(Sha1ObjectFormat, []byte("100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af"))
106106
assert.Error(t, err)
107107
assert.Len(t, entries, 0)
108108
}

modules/git/ref.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ func RefURL(repoURL, ref string) string {
205205
return repoURL + "/src/branch/" + refName
206206
case refFullName.IsTag():
207207
return repoURL + "/src/tag/" + refName
208-
case !ObjectFormatFromID(Sha1).IsValid(ref):
208+
case !Sha1ObjectFormat.IsValid(ref):
209209
// assume they mean a branch
210210
return repoURL + "/src/branch/" + refName
211211
default:

modules/git/repo.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,21 @@ func GetObjectFormatOfRepo(ctx context.Context, repoPath string) (ObjectFormat,
9090
}
9191

9292
// InitRepository initializes a new Git repository.
93-
func InitRepository(ctx context.Context, repoPath string, bare bool, objectFormat ObjectFormat) error {
93+
func InitRepository(ctx context.Context, repoPath string, bare bool, objectFormatName string) error {
9494
err := os.MkdirAll(repoPath, os.ModePerm)
9595
if err != nil {
9696
return err
9797
}
9898

9999
cmd := NewCommand(ctx, "init")
100100
if SupportHashSha256 {
101-
cmd.AddOptionValues("--object-format", objectFormat.String())
101+
if objectFormatName == "" {
102+
objectFormatName = Sha1ObjectFormat.Name()
103+
}
104+
if !IsValidObjectFormat(objectFormatName) {
105+
return fmt.Errorf("invalid object format: %s", objectFormatName)
106+
}
107+
cmd.AddOptionValues("--object-format", objectFormatName)
102108
}
103109
if bare {
104110
cmd.AddArguments("--bare")

modules/git/repo_commit_gogit.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
5454
if err != nil {
5555
if strings.Contains(err.Error(), "unknown revision or path") ||
5656
strings.Contains(err.Error(), "fatal: Needed a single revision") {
57-
return objectFormat.Empty(), ErrNotExist{commitID, ""}
57+
return objectFormat.EmptyObjectID(), ErrNotExist{commitID, ""}
5858
}
59-
return objectFormat.Empty(), err
59+
return objectFormat.EmptyObjectID(), err
6060
}
6161

6262
return objectFormat.NewIDFromString(actualCommitID)

modules/git/repo_compare.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ func (repo *Repository) GetPatch(base, head string, w io.Writer) error {
284284
// If base is the SHA of an empty tree (EmptyTreeSHA), it returns the files changes from the initial commit to the head commit
285285
func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, error) {
286286
cmd := NewCommand(repo.Ctx, "diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z")
287-
if base == repo.objectFormat.Empty().String() {
287+
if base == repo.objectFormat.EmptyObjectID().String() {
288288
cmd.AddDynamicArguments(head)
289289
} else {
290290
cmd.AddDynamicArguments(base, head)

0 commit comments

Comments
 (0)