8000 git: Worktree.AddWithOptions, add skipStatus option. #993 · go-git/go-git@a205f3a · GitHub
[go: up one dir, main page]

Skip to content

Commit a205f3a

Browse files
committed
git: Worktree.AddWithOptions, add skipStatus option. #993
1 parent a6e934f commit a205f3a

File tree

4 files changed

+240
-11
lines changed

4 files changed

+240
-11
lines changed

options.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,9 @@ type AddOptions struct {
474474
// Glob adds all paths, matching pattern, to the index. If pattern matches a
475475
// directory path, all directory contents are added to the index recursively.
476476
Glob string
477+
// SkipStatus adds the path with no status check. This option is relevant only
478+
// when the `Path` option is specified and does not apply when the `All` option is used.
479+
SkipStatus bool
477480
}
478481

479482
// Validate validates the fields and sets the default values.

worktree_commit_test.go

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ func (s *WorktreeSuite) TestCommitAmend(c *C) {
131131
_, err = w.Commit("foo\n", &CommitOptions{Author: defaultSignature()})
132132
c.Assert(err, IsNil)
133133

134-
135134
amendedHash, err := w.Commit("bar\n", &CommitOptions{Amend: true})
136135
c.Assert(err, IsNil)
137136

@@ -144,6 +143,118 @@ func (s *WorktreeSuite) TestCommitAmend(c *C) {
144143
assertStorageStatus(c, s.Repository, 13, 11, 11, amendedHash)
145144
}
146145

146+
func (s *WorktreeSuite) TestAddAndCommitWithSkipStatus(c *C) {
147+
expected := plumbing.NewHash("375a3808ffde7f129cdd3c8c252fd0fe37cfd13b")
148+
149+
fs := memfs.New()
150+
w := &Worktree{
151+
r: s.Repository,
152+
Filesystem: fs,
153+
}
154+
155+
err := w.Checkout(&CheckoutOptions{})
156+
c.Assert(err, IsNil)
157+
158+
util.WriteFile(fs, "LICENSE", []byte("foo"), 0644)
159+
util.WriteFile(fs, "foo", []byte("foo"), 0644)
160+
161+
err = w.AddWithOptions(&AddOptions{
162+
Path: "foo",
163+
SkipStatus: true,
164+
})
165+
c.Assert(err, IsNil)
166+
167+
hash, err := w.Commit("commit foo only\n", &CommitOptions{
168+
Author: defaultSignature(),
169+
})
170+
171+
c.Assert(hash, Equals, expected)
172+
c.Assert(err, IsNil)
173+
174+
assertStorageStatus(c, s.Repository, 13, 11, 10, expected)
175+
}
176+
177+
func (s *WorktreeSuite) TestAddAndCommitWithSkipStatusPathNotModified(c *C) {
178+
expected := plumbing.NewHash("375a3808ffde7f129cdd3c8c252fd0fe37cfd13b")
179+
expected2 := plumbing.NewHash("8691273baf8f6ee2cccfc05e910552c04d02d472")
180+
181+
fs := memfs.New()
182+
w := &Worktree{
183+
r: s.Repository,
184+
Filesystem: fs,
185+
}
186+
187+
err := w.Checkout(&CheckoutOptions{})
188+
c.Assert(err, IsNil)
189+
190+
util.WriteFile(fs, "foo", []byte("foo"), 0644)
191+
192+
status, err := w.Status()
193+
c.Assert(err, IsNil)
194+
foo := status.File("foo")
195+
c.Assert(foo.Staging, Equals, Untracked)
196+
c.Assert(foo.Worktree, Equals, Untracked)
197+
198+
err = w.AddWithOptions(&AddOptions{
199+
Path: "foo",
200+
SkipStatus: true,
201+
})
202+
c.Assert(err, IsNil)
203+
204+
status, err = w.Status()
205+
c.Assert(err, IsNil)
206+
foo = status.File("foo")
207+
c.Assert(foo.Staging, Equals, Added)
208+
c.Assert(foo.Worktree, Equals, Unmodified)
209+
210+
hash, err := w.Commit("commit foo only\n", &CommitOptions{All: true,
211+
Author: defaultSignature(),
212+
})
213+
c.Assert(hash, Equals, expected)
214+
c.Assert(err, IsNil)
215+
commit1, err := w.r.CommitObject(hash)
216+
217+
status, err = w.< 10000 span class=pl-c1>Status()
218+
c.Assert(err, IsNil)
219+
foo = status.File("foo")
220+
c.Assert(foo.Staging, Equals, Untracked)
221+
c.Assert(foo.Worktree, Equals, Untracked)
222+
223+
assertStorageStatus(c, s.Repository, 13, 11, 10, expected)
224+
225+
err = w.AddWithOptions(&AddOptions{
226+
Path: "foo",
227+
SkipStatus: true,
228+
})
229+
c.Assert(err, IsNil)
230+
231+
status, err = w.Status()
232+
c.Assert(err, IsNil)
233+
foo = status.File("foo")
234+
c.Assert(foo.Staging, Equals, Untracked)
235+
c.Assert(foo.Worktree, Equals, Untracked)
236+
237+
hash, err = w.Commit("commit with no changes\n", &CommitOptions{
238+
Author: defaultSignature(),
239+
})
240+
c.Assert(hash, Equals, expected2)
241+
c.Assert(err, IsNil)
242+
commit2, err := w.r.CommitObject(hash)
243+
244+
status, err = w.Status()
245+
c.Assert(err, IsNil)
246+
foo = status.File("foo")
247+
c.Assert(foo.Staging, Equals, Untracked)
248+
c.Assert(foo.Worktree, Equals, Untracked)
249+
250+
patch, err := commit2.Patch(commit1)
251+
c.Assert(err, IsNil)
252+
files := patch.FilePatches()
253+
c.Assert(files, IsNil)
254+
255+
assertStorageStatus(c, s.Repository, 13, 11, 11, expected2)
256+
}
257+
147258
func (s *WorktreeSuite) TestCommitAll(c *C) {
148259
expected := plumbing.NewHash("aede6f8c9c1c7ec9ca8d287c64b8ed151276fa28")
149260

worktree_status.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func diffTreeIsEquals(a, b noder.Hasher) bool {
271271
// no error is returned. When path is a file, the blob.Hash is returned.
272272
func (w *Worktree) Add(path string) (plumbing.Hash, error) {
273273
// TODO(mcuadros): deprecate in favor of AddWithOption in v6.
274-
return w.doAdd(path, make([]gitignore.Pattern, 0))
274+
return w.doAdd(path, make([]gitignore.Pattern, 0), false)
275275
}
276276

277277
func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string, ignorePattern []gitignore.Pattern) (added bool, err error) {
@@ -321,24 +321,19 @@ func (w *Worktree) AddWithOptions(opts *AddOptions) error {
321321
}
322322

323323
if opts.All {
324-
_, err := w.doAdd(".", w.Excludes)
324+
_, err := w.doAdd(".", w.Excludes, false)
325325
return err
326326
}
327327

328328
if opts.Glob != "" {
329329
return w.AddGlob(opts.Glob)
330330
}
331331

332-
_, err := w.Add(opts.Path)
332+
_, err := w.doAdd(opts.Path, make([]gitignore.Pattern, 0), opts.SkipStatus)
333333
return err
334334
}
335335

336-
func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern) (plumbing.Hash, error) {
337-
s, err := w.Status()
338-
if err != nil {
339-
return plumbing.ZeroHash, err
340-
}
341-
336+
func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern, skipStatus bool) (plumbing.Hash, error) {
342337
idx, err := w.r.Storer.Index()
343338
if err != nil {
344339
return plumbing.ZeroHash, err
@@ -348,6 +343,17 @@ func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern) (plumbi
348343
var added bool
349344

350345
fi, err := w.Filesystem.Lstat(path)
346+
347+
// status is required for doAddDirectory
348+
var s Status
349+
var err2 error
350+
if !skipStatus || fi == nil || fi.IsDir() {
351+
s, err2 = w.Status()
352+
if err2 != nil {
353+
return plumbing.ZeroHash, err2
354+
}
355+
}
356+
351357
if err != nil || !fi.IsDir() {
352358
added, h, err = w.doAddFile(idx, s, path, ignorePattern)
353359
} else {
@@ -421,8 +427,9 @@ func (w *Worktree) AddGlob(pattern string) error {
421427

422428
// doAddFile create a new blob from path and update the index, added is true if
423429
// the file added is different from the index.
430+
// if s status is nil will skip the status check and update the index anyway
424431
func (w *Worktree) doAddFile(idx *index.Index, s Status, path string, ignorePattern []gitignore.Pattern) (added bool, h plumbing.Hash, err error) {
425-
if s.File(path).Worktree == Unmodified {
432+
if s != nil && s.File(path).Worktree == Unmodified {
426433
return false, h, nil
427434
}
428435
if len(ignorePattern) > 0 {

worktree_test.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1930,6 +1930,114 @@ func (s *WorktreeSuite) TestAddGlobErrorNoMatches(c *C) {
19301930
c.Assert(err, Equals, ErrGlobNoMatches)
19311931
}
19321932

1933+
func (s *WorktreeSuite) TestAddSkipStatusAddedPath(c *C) {
1934+
fs := memfs.New()
1935+
w := &Worktree{
1936+
r: s.Repository,
1937+
Filesystem: fs,
1938+
}
1939+
1940+
err := w.Checkout(&CheckoutOptions{Force: true})
1941+
c.Assert(err, IsNil)
1942+
1943+
idx, err := w.r.Storer.Index()
1944+
c.Assert(err, IsNil)
1945+
c.Assert(idx.Entries, HasLen, 9)
1946+
1947+
err = util.WriteFile(w.Filesystem, "file1", []byte("file1"), 0644)
1948+
c.Assert(err, IsNil)
1949+
1950+
err = w.AddWithOptions(&AddOptions{Path: "file1", SkipStatus: true})
1951+
c.Assert(err, IsNil)
1952+
1953+
idx, err = w.r.Storer.Index()
1954+
c.Assert(err, IsNil)
1955+
c.Assert(idx.Entries, HasLen, 10)
1956+
1957+
e, err := idx.Entry("file1")
1958+
c.Assert(err, IsNil)
1959+
c.Assert(e.Mode, Equals, filemode.Regular)
1960+
1961+
status, err := w.Status()
1962+
c.Assert(err, IsNil)
1963+
c.Assert(status, HasLen, 1)
1964+
1965+
file := status.File("file1")
1966+
c.Assert(file.Staging, Equals, Added)
1967+
c.Assert(file.Worktree, Equals, Unmodified)
1968+
}
1969+
1970+
func (s *WorktreeSuite) TestAddSkipStatusModifiedPath(c *C) {
1971+
fs := memfs.New()
1972+
w := &Worktree{
1973+
r: s.Repository,
1974+
Filesystem: fs,
1975+
}
1976+
1977+
err := w.Checkout(&CheckoutOptions{Force: true})
1978+
c.Assert(err, IsNil)
1979+
1980+
idx, err := w.r.Storer.Index()
1981+
c.Assert(err, IsNil)
1982+
c.Assert(idx.Entries, HasLen, 9)
1983+
1984+
err = util.WriteFile(w.Filesystem, "LICENSE", []byte("file1"), 0644)
1985+
c.Assert(err, IsNil)
1986+
1987+
err = w.AddWithOptions(&AddOptions{Path: "LICENSE", SkipStatus: true})
1988+
c.Assert(err, IsNil)
1989+
1990+
idx, err = w.r.Storer.Index()
1991+
c.Assert(err, IsNil)
1992+
c.Assert(idx.Entries, HasLen, 9)
1993+
1994+
e, err := idx.Entry("LICENSE")
1995+
c.Assert(err, IsNil)
1996+
c.Assert(e.Mode, Equals, filemode.Regular)
1997+
1998+
status, err := w.Status()
1999+
c.Assert(err, IsNil)
2000+
c.Assert(status, HasLen, 1)
2001+
2002+
file := status.File("LICENSE")
2003+
c.Assert(file.Staging, Equals, Modified)
2004+
c.Assert(file.Worktree, Equals, Unmodified)
2005+
}
2006+
2007+
func (s *WorktreeSuite) TestAddSkipStatusNonModifiedPath(c *C) {
2008+
fs := memfs.New()
2009+
w := &Worktree{
2010+
r: s.Repository,
2011+
Filesystem: fs,
2012+
}
2013+
2014+
err := w.Checkout(&CheckoutOptions{Force: true})
2015+
c.Assert(err, IsNil)
2016+
2017+
idx, err := w.r.Storer.Index()
2018+
c.Assert(err, IsNil)
2019+
c.Assert(idx.Entries, HasLen, 9)
2020+
2021+
err = w.AddWithOptions(&AddOptions{Path: "LICENSE", SkipStatus: true})
2022+
c.Assert(err, IsNil)
2023+
2024+
idx, err = w.r.Storer.Index()
2025+
c.Assert(err, IsNil)
2026+
c.Assert(idx.Entries, HasLen, 9)
2027+
2028+
e, err := idx.Entry("LICENSE")
2029+
c.Assert(err, IsNil)
2030+
c.Assert(e.Mode, Equals, filemode.Regular)
2031+
2032+
status, err := w.Status()
2033+
c.Assert(err, IsNil)
2034+
c.Assert(status, HasLen, 0)
2035+
2036+
file := status.File("LICENSE")
2037+
c.Assert(file.Staging, Equals, Untracked)
2038+
c.Assert(file.Worktree, Equals, Untracked)
2039+
}
2040+
19332041
func (s *WorktreeSuite) TestRemove(c *C) {
19342042
fs := memfs.New()
19352043
w := &Worktree{

0 commit comments

Comments
 (0)
0