+4
options.go
+4
options.go
···
458
458
// All automatically stage files that have been modified and deleted, but
459
459
// new files you have not told Git about are not affected.
460
460
All bool
461
+
// AllowEmptyCommits enable empty commits to be created. An empty commit
462
+
// is when no changes to the tree were made, but a new commit message is
463
+
// provided. The default behavior is false, which results in ErrEmptyCommit.
464
+
AllowEmptyCommits bool
461
465
// Author is the author's signature of the commit. If Author is empty the
462
466
// Name and Email is read from the config, and time.Now it's used as When.
463
467
Author *object.Signature
+13
-2
worktree_commit.go
+13
-2
worktree_commit.go
···
2
2
3
3
import (
4
4
"bytes"
5
+
"errors"
5
6
"path"
6
7
"sort"
7
8
"strings"
···
14
15
15
16
"github.com/ProtonMail/go-crypto/openpgp"
16
17
"github.com/go-git/go-billy/v5"
18
+
)
19
+
20
+
var (
21
+
// ErrEmptyCommit occurs when a commit is attempted using a clean
22
+
// working tree, with no changes to be committed.
23
+
ErrEmptyCommit = errors.New("cannot create empty commit: clean working tree")
17
24
)
18
25
19
26
// Commit stores the current contents of the index in a new commit along with
···
39
46
s: w.r.Storer,
40
47
}
41
48
42
-
tree, err := h.BuildTree(idx)
49
+
tree, err := h.BuildTree(idx, opts)
43
50
if err != nil {
44
51
return plumbing.ZeroHash, err
45
52
}
···
145
152
146
153
// BuildTree builds the tree objects and push its to the storer, the hash
147
154
// of the root tree is returned.
148
-
func (h *buildTreeHelper) BuildTree(idx *index.Index) (plumbing.Hash, error) {
155
+
func (h *buildTreeHelper) BuildTree(idx *index.Index, opts *CommitOptions) (plumbing.Hash, error) {
156
+
if len(idx.Entries) == 0 && (opts == nil || !opts.AllowEmptyCommits) {
157
+
return plumbing.ZeroHash, ErrEmptyCommit
158
+
}
159
+
149
160
const rootNode = ""
150
161
h.trees = map[string]*object.Tree{rootNode: {}}
151
162
h.entries = map[string]*object.TreeEntry{}
+25
-1
worktree_commit_test.go
+25
-1
worktree_commit_test.go
···
26
26
)
27
27
28
28
func (s *WorktreeSuite) TestCommitEmptyOptions(c *C) {
29
-
r, err := Init(memory.NewStorage(), memfs.New())
29
+
fs := memfs.New()
30
+
r, err := Init(memory.NewStorage(), fs)
30
31
c.Assert(err, IsNil)
31
32
32
33
w, err := r.Worktree()
34
+
c.Assert(err, IsNil)
35
+
36
+
util.WriteFile(fs, "foo", []byte("foo"), 0644)
37
+
38
+
_, err = w.Add("foo")
33
39
c.Assert(err, IsNil)
34
40
35
41
hash, err := w.Commit("foo", &CommitOptions{})
···
63
69
c.Assert(err, IsNil)
64
70
65
71
assertStorageStatus(c, r, 1, 1, 1, expected)
72
+
}
73
+
74
+
func (s *WorktreeSuite) TestNothingToCommit(c *C) {
75
+
expected := plumbing.NewHash("838ea833ce893e8555907e5ef224aa076f5e274a")
76
+
77
+
r, err := Init(memory.NewStorage(), memfs.New())
78
+
c.Assert(err, IsNil)
79
+
80
+
w, err := r.Worktree()
81
+
c.Assert(err, IsNil)
82
+
83
+
hash, err := w.Commit("failed empty commit\n", &CommitOptions{Author: defaultSignature()})
84
+
c.Assert(hash, Equals, plumbing.ZeroHash)
85
+
c.Assert(err, Equals, ErrEmptyCommit)
86
+
87
+
hash, err = w.Commit("enable empty commits\n", &CommitOptions{Author: defaultSignature(), AllowEmptyCommits: true})
88
+
c.Assert(hash, Equals, expected)
89
+
c.Assert(err, IsNil)
66
90
}
67
91
68
92
func (s *WorktreeSuite) TestCommitParent(c *C) {
+33
-3
worktree_test.go
+33
-3
worktree_test.go
···
3
3
import (
4
4
"bytes"
5
5
"context"
6
-
"errors"
7
6
"io"
8
7
"io/ioutil"
9
8
"os"
···
2167
2166
}
2168
2167
2169
2168
func (s *WorktreeSuite) TestAddAndCommit(c *C) {
2169
+
expectedFiles := 2
2170
+
2170
2171
dir, clean := s.TemporalDir()
2171
2172
defer clean()
2172
2173
···
2175
2176
2176
2177
w, err := repo.Worktree()
2177
2178
c.Assert(err, IsNil)
2179
+
2180
+
os.WriteFile(filepath.Join(dir, "foo"), []byte("bar"), 0o644)
2181
+
os.WriteFile(filepath.Join(dir, "bar"), []byte("foo"), 0o644)
2178
2182
2179
2183
_, err = w.Add(".")
2180
2184
c.Assert(err, IsNil)
2181
2185
2182
-
w.Commit("Test Add And Commit", &CommitOptions{Author: &object.Signature{
2186
+
_, err = w.Commit("Test Add And Commit", &CommitOptions{Author: &object.Signature{
2183
2187
Name: "foo",
2184
2188
Email: "foo@foo.foo",
2185
2189
When: time.Now(),
2186
2190
}})
2191
+
c.Assert(err, IsNil)
2187
2192
2188
2193
iter, err := w.r.Log(&LogOptions{})
2189
2194
c.Assert(err, IsNil)
2195
+
2196
+
filesFound := 0
2190
2197
err = iter.ForEach(func(c *object.Commit) error {
2191
2198
files, err := c.Files()
2192
2199
if err != nil {
···
2194
2201
}
2195
2202
2196
2203
err = files.ForEach(func(f *object.File) error {
2197
-
return errors.New("Expected no files, got at least 1")
2204
+
filesFound++
2205
+
return nil
2198
2206
})
2199
2207
return err
2200
2208
})
2201
2209
c.Assert(err, IsNil)
2210
+
c.Assert(filesFound, Equals, expectedFiles)
2211
+
}
2212
+
2213
+
func (s *WorktreeSuite) TestAddAndCommitEmpty(c *C) {
2214
+
dir, clean := s.TemporalDir()
2215
+
defer clean()
2216
+
2217
+
repo, err := PlainInit(dir, false)
2218
+
c.Assert(err, IsNil)
2219
+
2220
+
w, err := repo.Worktree()
2221
+
c.Assert(err, IsNil)
2222
+
2223
+
_, err = w.Add(".")
2224
+
c.Assert(err, IsNil)
2225
+
2226
+
_, err = w.Commit("Test Add And Commit", &CommitOptions{Author: &object.Signature{
2227
+
Name: "foo",
2228
+
Email: "foo@foo.foo",
2229
+
When: time.Now(),
2230
+
}})
2231
+
c.Assert(err, Equals, ErrEmptyCommit)
2202
2232
}
2203
2233
2204
2234
func (s *WorktreeSuite) TestLinkedWorktree(c *C) {