Skip to content

Commit

Permalink
git: worktree_commit, Modify checking empty commit. Fixes #723
Browse files Browse the repository at this point in the history
  • Loading branch information
onee-only committed Mar 13, 2024
1 parent ca05e2c commit 1906753
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 8 deletions.
32 changes: 25 additions & 7 deletions worktree_commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error
}
}

var treeHash plumbing.Hash

if opts.Amend {
head, err := w.r.Head()
if err != nil {
Expand All @@ -61,16 +59,40 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error
return plumbing.ZeroHash, err
}

allowEmpty := opts != nil && opts.AllowEmptyCommits

// First handle the case of the first commit in the repository being empty.
if len(opts.Parents) == 0 && len(idx.Entries) == 0 && !allowEmpty {
return plumbing.ZeroHash, ErrEmptyCommit
}

h := &buildTreeHelper{
fs: w.Filesystem,
s: w.r.Storer,
}

treeHash, err = h.BuildTree(idx, opts)
treeHash, err := h.BuildTree(idx, opts)
if err != nil {
return plumbing.ZeroHash, err
}

previousTree := plumbing.ZeroHash
if len(opts.Parents) > 0 {
parentCommit, err := w.r.CommitObject(opts.Parents[0])
if err != nil {
// Parent might not be a commit.
if err != plumbing.ErrObjectNotFound {
return plumbing.ZeroHash, err
}
} else {
previousTree = parentCommit.TreeHash
}
}

if treeHash == previousTree && !allowEmpty {
return plumbing.ZeroHash, ErrEmptyCommit
}

commit, err := w.buildCommitObject(msg, opts, treeHash)
if err != nil {
return plumbing.ZeroHash, err
Expand Down Expand Up @@ -175,10 +197,6 @@ type buildTreeHelper struct {
// BuildTree builds the tree objects and push its to the storer, the hash
// of the root tree is returned.
func (h *buildTreeHelper) BuildTree(idx *index.Index, opts *CommitOptions) (plumbing.Hash, error) {
if len(idx.Entries) == 0 && (opts == nil || !opts.AllowEmptyCommits) {
return plumbing.ZeroHash, ErrEmptyCommit
}

const rootNode = ""
h.trees = map[string]*object.Tree{rootNode: {}}
h.entries = map[string]*object.TreeEntry{}
Expand Down
111 changes: 110 additions & 1 deletion worktree_commit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,54 @@ func (s *WorktreeSuite) TestNothingToCommit(c *C) {
c.Assert(err, IsNil)
}

func (s *WorktreeSuite) TestNothingToCommitNonEmptyRepo(c *C) {
fs := memfs.New()
r, err := Init(memory.NewStorage(), fs)
c.Assert(err, IsNil)

w, err := r.Worktree()
c.Assert(err, IsNil)

util.WriteFile(fs, "foo", []byte("foo"), 0644)
w.Add("foo")
_, err = w.Commit("previous commit\n", &CommitOptions{Author: defaultSignature()})
c.Assert(err, IsNil)

hash, err := w.Commit("failed empty commit\n", &CommitOptions{Author: defaultSignature()})
c.Assert(hash, Equals, plumbing.ZeroHash)
c.Assert(err, Equals, ErrEmptyCommit)

_, err = w.Commit("enable empty commits\n", &CommitOptions{Author: defaultSignature(), AllowEmptyCommits: true})
c.Assert(err, IsNil)
}

func (s *WorktreeSuite) TestRemoveAndCommitToMakeEmptyRepo(c *C) {
fs := memfs.New()
r, err := Init(memory.NewStorage(), fs)
c.Assert(err, IsNil)

w, err := r.Worktree()
c.Assert(err, IsNil)

err = util.WriteFile(fs, "foo", []byte("foo"), 0644)
c.Assert(err, IsNil)

_, err = w.Add("foo")
c.Assert(err, IsNil)

_, err = w.Commit("Add in Repo\n", &CommitOptions{Author: defaultSignature()})
c.Assert(err, IsNil)

err = fs.Remove("foo")
c.Assert(err, IsNil)

_, err = w.Add("foo")
c.Assert(err, IsNil)

_, err = w.Commit("Remove foo\n", &CommitOptions{Author: defaultSignature()})
c.Assert(err, IsNil)
}

func (s *WorktreeSuite) TestCommitParent(c *C) {
expected := plumbing.NewHash("ef3ca05477530b37f48564be33ddd48063fc7a22")

Expand All @@ -113,7 +161,41 @@ func (s *WorktreeSuite) TestCommitParent(c *C) {
assertStorageStatus(c, s.Repository, 13, 11, 10, expected)
}

func (s *WorktreeSuite) TestCommitAmend(c *C) {
func (s *WorktreeSuite) TestCommitAmendWithoutChanges(c *C) {
fs := memfs.New()
w := &Worktree{
r: s.Repository,
Filesystem: fs,
}

err := w.Checkout(&CheckoutOptions{})
c.Assert(err, IsNil)

util.WriteFile(fs, "foo", []byte("foo"), 0644)

_, err = w.Add("foo")
c.Assert(err, IsNil)

prevHash, err := w.Commit("foo\n", &CommitOptions{Author: defaultSignature()})
c.Assert(err, IsNil)

amendedHash, err := w.Commit("foo\n", &CommitOptions{Author: defaultSignature(), Amend: true})
c.Assert(err, IsNil)

headRef, err := w.r.Head()
c.Assert(err, IsNil)

c.Assert(amendedHash, Equals, headRef.Hash())
c.Assert(amendedHash, Equals, prevHash)

commit, err := w.r.CommitObject(headRef.Hash())
c.Assert(err, IsNil)
c.Assert(commit.Message, Equals, "foo\n")

assertStorageStatus(c, s.Repository, 13, 11, 10, amendedHash)
}

func (s *WorktreeSuite) TestCommitAmendWithChanges(c *C) {
fs := memfs.New()
w := &Worktree{
r: s.Repository,
Expand Down Expand Up @@ -164,6 +246,33 @@ func (s *WorktreeSuite) TestCommitAmend(c *C) {
assertStorageStatus(c, s.Repository, 14, 12, 11, amendedHash)
}

func (s *WorktreeSuite) TestCommitAmendNothingToCommit(c *C) {
fs := memfs.New()
w := &Worktree{
r: s.Repository,
Filesystem: fs,
}

err := w.Checkout(&CheckoutOptions{})
c.Assert(err, IsNil)

util.WriteFile(fs, "foo", []byte("foo"), 0644)

_, err = w.Add("foo")
c.Assert(err, IsNil)

prevHash, err := w.Commit("foo\n", &CommitOptions{Author: defaultSignature()})
c.Assert(err, IsNil)

_, err = w.Commit("bar\n", &CommitOptions{Author: defaultSignature(), AllowEmptyCommits: true})
c.Assert(err, IsNil)

amendedHash, err := w.Commit("foo\n", &CommitOptions{Author: defaultSignature(), Amend: true})
c.Log(prevHash, amendedHash)
c.Assert(err, Equals, ErrEmptyCommit)
c.Assert(amendedHash, Equals, plumbing.ZeroHash)
}

func (s *WorktreeSuite) TestAddAndCommitWithSkipStatus(c *C) {
expected := plumbing.NewHash("375a3808ffde7f129cdd3c8c252fd0fe37cfd13b")

Expand Down

0 comments on commit 1906753

Please sign in to comment.