Skip to content

Commit d138255

Browse files
committed
Merge branch 'master' of github.com:go-git/go-git into scope-config
2 parents a107e18 + 6d8103d commit d138255

File tree

10 files changed

+187
-41
lines changed

10 files changed

+187
-41
lines changed

_examples/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Here you can find a list of annotated _go-git_ examples:
2020
- [remotes](remotes/main.go) - Working with remotes: adding, removing, etc
2121
- [progress](progress/main.go) - Printing the progress information from the sideband
2222
- [revision](revision/main.go) - Solve a revision into a commit
23+
- [submodule](submodule/main.go) - Submodule update remote
2324

2425
### Advanced
2526
- [custom_http](custom_http/main.go) - Replacing the HTTP client using a custom one

_examples/submodule/main.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package main
2+
3+
import (
4+
"os"
5+
6+
"github.com/go-git/go-git/v5"
7+
. "github.com/go-git/go-git/v5/_examples"
8+
)
9+
10+
// Basic example of how to clone a repository including a submodule and
11+
// updating submodule ref
12+
func main() {
13+
CheckArgs("<url>", "<directory>", "<submodule>")
14+
url := os.Args[1]
15+
directory := os.Args[2]
16+
submodule := os.Args[3]
17+
18+
// Clone the given repository to the given directory
19+
Info("git clone %s %s --recursive", url, directory)
20+
21+
r, err := git.PlainClone(directory, false, &git.CloneOptions{
22+
URL: url,
23+
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
24+
})
25+
26+
CheckIfError(err)
27+
28+
w, err := r.Worktree()
29+
if err != nil {
30+
CheckIfError(err)
31+
}
32+
33+
sub, err := w.Submodule(submodule)
34+
if err != nil {
35+
CheckIfError(err)
36+
}
37+
38+
sr, err := sub.Repository()
39+
if err != nil {
40+
CheckIfError(err)
41+
}
42+
43+
sw, err := sr.Worktree()
44+
if err != nil {
45+
CheckIfError(err)
46+
}
47+
48+
Info("git submodule update --remote")
49+
err = sw.Pull(&git.PullOptions{
50+
RemoteName: "origin",
51+
})
52+
if err != nil {
53+
CheckIfError(err)
54+
}
55+
}

options.go

+3
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ type PushOptions struct {
190190
// Prune specify that remote refs that match given RefSpecs and that do
191191
// not exist locally will be removed.
192192
Prune bool
193+
// Force allows the push to update a remote branch even when the local
194+
// branch does not descend from it.
195+
Force bool
193196
}
194197

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

plumbing/format/diff/unified_encoder.go

+53-26
Original file line numberDiff line numberDiff line change
@@ -86,48 +86,73 @@ func (e *UnifiedEncoder) writeFilePatchHeader(sb *strings.Builder, filePatch Fil
8686
}
8787
isBinary := filePatch.IsBinary()
8888

89-
sb.WriteString(e.color[Meta])
89+
var lines []string
9090
switch {
9191
case from != nil && to != nil:
9292
hashEquals := from.Hash() == to.Hash()
93-
fmt.Fprintf(sb, "diff --git a/%s b/%s\n", from.Path(), to.Path())
93+
lines = append(lines,
94+
fmt.Sprintf("diff --git a/%s b/%s", from.Path(), to.Path()),
95+
)
9496
if from.Mode() != to.Mode() {
95-
fmt.Fprintf(sb, "old mode %o\n", from.Mode())
96-
fmt.Fprintf(sb, "new mode %o\n", to.Mode())
97+
lines = append(lines,
98+
fmt.Sprintf("old mode %o", from.Mode()),
99+
fmt.Sprintf("new mode %o", to.Mode()),
100+
)
97101
}
98102
if from.Path() != to.Path() {
99-
fmt.Fprintf(sb, "rename from %s\n", from.Path())
100-
fmt.Fprintf(sb, "rename to %s\n", to.Path())
103+
lines = append(lines,
104+
fmt.Sprintf("rename from %s", from.Path()),
105+
fmt.Sprintf("rename to %s", to.Path()),
106+
)
101107
}
102108
if from.Mode() != to.Mode() && !hashEquals {
103-
fmt.Fprintf(sb, "index %s..%s\n", from.Hash(), to.Hash())
109+
lines = append(lines,
110+
fmt.Sprintf("index %s..%s", from.Hash(), to.Hash()),
111+
)
104112
} else if !hashEquals {
105-
fmt.Fprintf(sb, "index %s..%s %o\n", from.Hash(), to.Hash(), from.Mode())
113+
lines = append(lines,
114+
fmt.Sprintf("index %s..%s %o", from.Hash(), to.Hash(), from.Mode()),
115+
)
106116
}
107117
if !hashEquals {
108-
e.writePathLines(sb, "a/"+from.Path(), "b/"+to.Path(), isBinary)
118+
lines = e.appendPathLines(lines, "a/"+from.Path(), "b/"+to.Path(), isBinary)
109119
}
110120
case from == nil:
111-
fmt.Fprintf(sb, "diff --git a/%s b/%s\n", to.Path(), to.Path())
112-
fmt.Fprintf(sb, "new file mode %o\n", to.Mode())
113-
fmt.Fprintf(sb, "index %s..%s\n", plumbing.ZeroHash, to.Hash())
114-
e.writePathLines(sb, "/dev/null", "b/"+to.Path(), isBinary)
121+
lines = append(lines,
122+
fmt.Sprintf("diff --git a/%s b/%s", to.Path(), to.Path()),
123+
fmt.Sprintf("new file mode %o", to.Mode()),
124+
fmt.Sprintf("index %s..%s", plumbing.ZeroHash, to.Hash()),
125+
)
126+
lines = e.appendPathLines(lines, "/dev/null", "b/"+to.Path(), isBinary)
115127
case to == nil:
116-
fmt.Fprintf(sb, "diff --git a/%s b/%s\n", from.Path(), from.Path())
117-
fmt.Fprintf(sb, "deleted file mode %o\n", from.Mode())
118-
fmt.Fprintf(sb, "index %s..%s\n", from.Hash(), plumbing.ZeroHash)
119-
e.writePathLines(sb, "a/"+from.Path(), "/dev/null", isBinary)
128+
lines = append(lines,
129+
fmt.Sprintf("diff --git a/%s b/%s", from.Path(), from.Path()),
130+
fmt.Sprintf("deleted file mode %o", from.Mode()),
131+
fmt.Sprintf("index %s..%s", from.Hash(), plumbing.ZeroHash),
132+
)
133+
lines = e.appendPathLines(lines, "a/"+from.Path(), "/dev/null", isBinary)
134+
}
135+
136+
sb.WriteString(e.color[Meta])
137+
sb.WriteString(lines[0])
138+
for _, line := range lines[1:] {
139+
sb.WriteByte('\n')
140+
sb.WriteString(line)
120141
}
121142
sb.WriteString(e.color.Reset(Meta))
143+
sb.WriteByte('\n')
122144
}
123145

124-
func (e *UnifiedEncoder) writePathLines(sb *strings.Builder, fromPath, toPath string, isBinary bool) {
146+
func (e *UnifiedEncoder) appendPathLines(lines []string, fromPath, toPath string, isBinary bool) []string {
125147
if isBinary {
126-
fmt.Fprintf(sb, "Binary files %s and %s differ\n", fromPath, toPath)
127-
} else {
128-
fmt.Fprintf(sb, "--- %s\n", fromPath)
129-
fmt.Fprintf(sb, "+++ %s\n", toPath)
148+
return append(lines,
149+
fmt.Sprintf("Binary files %s and %s differ", fromPath, toPath),
150+
)
130151
}
152+
return append(lines,
153+
fmt.Sprintf("--- %s", fromPath),
154+
fmt.Sprintf("+++ %s", toPath),
155+
)
131156
}
132157

133158
type hunksGenerator struct {
@@ -341,9 +366,11 @@ func (o *op) writeTo(sb *strings.Builder, color ColorConfig) {
341366
colorKey := operationColorKey[o.t]
342367
sb.WriteString(color[colorKey])
343368
sb.WriteByte(operationChar[o.t])
344-
sb.WriteString(o.text)
345-
sb.WriteString(color.Reset(colorKey))
346-
if !strings.HasSuffix(o.text, "\n") {
347-
sb.WriteString("\n\\ No newline at end of file\n")
369+
if strings.HasSuffix(o.text, "\n") {
370+
sb.WriteString(strings.TrimSuffix(o.text, "\n"))
371+
} else {
372+
sb.WriteString(o.text + "\n\\ No newline at end of file")
348373
}
374+
sb.WriteString(color.Reset(colorKey))
375+
sb.WriteByte('\n')
349376
}

plumbing/format/diff/unified_encoder_test.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -894,11 +894,11 @@ index 0adddcde4fd38042c354518351820eb06c417c82..d39ae38aad7ba9447b5e7998b2e4714f
894894
color.Bold + "diff --git a/README.md b/README.md\n" +
895895
"index 94954abda49de8615a048f8d2e64b5de848e27a1..f3dad9514629b9ff9136283ae331ad1fc95748a8 100644\n" +
896896
"--- a/README.md\n" +
897-
"+++ b/README.md\n" + color.Reset +
897+
"+++ b/README.md" + color.Reset + "\n" +
898898
color.Cyan + "@@ -1,2 +1,2 @@" + color.Reset + "\n" +
899899
" hello\n" +
900-
color.Red + "-world\n" + color.Reset +
901-
color.Green + "+bug\n" + color.Reset,
900+
color.Red + "-world" + color.Reset + "\n" +
901+
color.Green + "+bug" + color.Reset + "\n",
902902
}, {
903903
patch: testPatch{
904904
message: "",
@@ -933,10 +933,10 @@ index 0adddcde4fd38042c354518351820eb06c417c82..d39ae38aad7ba9447b5e7998b2e4714f
933933
color.Bold + "diff --git a/test.txt b/test.txt\n" +
934934
"index 9daeafb9864cf43055ae93beb0afd6c7d144bfa4..180cf8328022becee9aaa2577a8f84ea2b9f3827 100644\n" +
935935
"--- a/test.txt\n" +
936-
"+++ b/test.txt\n" + color.Reset +
936+
"+++ b/test.txt" + color.Reset + "\n" +
937937
color.Cyan + "@@ -1 +1 @@" + color.Reset + "\n" +
938-
color.Red + "-test\n" + color.Reset +
939-
color.Green + "+test2\n" + color.Reset,
938+
color.Red + "-test" + color.Reset + "\n" +
939+
color.Green + "+test2" + color.Reset + "\n",
940940
}, {
941941
patch: oneChunkPatch,
942942
desc: "modified deleting lines file with context to 1 with color",
@@ -948,21 +948,21 @@ index 0adddcde4fd38042c354518351820eb06c417c82..d39ae38aad7ba9447b5e7998b2e4714f
948948
color.Bold + "diff --git a/onechunk.txt b/onechunk.txt\n" +
949949
"index ab5eed5d4a2c33aeef67e0188ee79bed666bde6f..0adddcde4fd38042c354518351820eb06c417c82 100644\n" +
950950
"--- a/onechunk.txt\n" +
951-
"+++ b/onechunk.txt\n" + color.Reset +
951+
"+++ b/onechunk.txt" + color.Reset + "\n" +
952952
color.Cyan + "@@ -1,2 +1 @@" + color.Reset + "\n" +
953-
color.Red + "-A\n" + color.Reset +
953+
color.Red + "-A" + color.Reset + "\n" +
954954
" B\n" +
955955
color.Cyan + "@@ -7,3 +6,2 @@" + color.Reset + " " + color.Reverse + "F" + color.Reset + "\n" +
956956
" G\n" +
957-
color.Red + "-H\n" + color.Reset +
957+
color.Red + "-H" + color.Reset + "\n" +
958958
" I\n" +
959959
color.Cyan + "@@ -14,3 +12,2 @@" + color.Reset + " " + color.Reverse + "M" + color.Reset + "\n" +
960960
" N\n" +
961-
color.Red + "-Ñ\n" + color.Reset +
961+
color.Red + "-Ñ" + color.Reset + "\n" +
962962
" O\n" +
963963
color.Cyan + "@@ -21,3 +18,2 @@" + color.Reset + " " + color.Reverse + "S" + color.Reset + "\n" +
964964
" T\n" +
965-
color.Red + "-U\n" + color.Reset +
965+
color.Red + "-U" + color.Reset + "\n" +
966966
" V\n",
967967
}}
968968

plumbing/object/commit.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,12 @@ func (c *Commit) PatchContext(ctx context.Context, to *Commit) (*Patch, error) {
8787
return nil, err
8888
}
8989

90-
toTree, err := to.Tree()
91-
if err != nil {
92-
return nil, err
90+
var toTree *Tree
91+
if to != nil {
92+
toTree, err = to.Tree()
93+
if err != nil {
94+
return nil, err
95+
}
9396
}
9497

9598
return fromTree.PatchContext(ctx, toTree)

plumbing/object/commit_test.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import (
1212
"github.com/go-git/go-git/v5/plumbing"
1313
"github.com/go-git/go-git/v5/plumbing/cache"
1414

15-
. "gopkg.in/check.v1"
1615
"github.com/go-git/go-git/v5/storage/filesystem"
16+
. "gopkg.in/check.v1"
1717
)
1818

1919
type SuiteCommit struct {
@@ -188,6 +188,15 @@ Binary files /dev/null and b/binary.jpg differ
188188
c.Assert(buf.String(), Equals, patch.String())
189189
}
190190

191+
func (s *SuiteCommit) TestPatchContext_ToNil(c *C) {
192+
from := s.commit(c, plumbing.NewHash("918c48b83bd081e863dbe1b80f8998f058cd8294"))
193+
194+
patch, err := from.PatchContext(context.Background(), nil)
195+
c.Assert(err, IsNil)
196+
197+
c.Assert(len(patch.String()), Equals, 242679)
198+
}
199+
191200
func (s *SuiteCommit) TestCommitEncodeDecodeIdempotent(c *C) {
192201
ts, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05-07:00")
193202
c.Assert(err, IsNil)

plumbing/object/tree_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,17 @@ func (s *TreeSuite) TestTreeWalkerNextNonRecursive(c *C) {
377377
c.Assert(count, Equals, 8)
378378
}
379379

380+
func (s *TreeSuite) TestPatchContext_ToNil(c *C) {
381+
commit := s.commit(c, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
382+
tree, err := commit.Tree()
383+
c.Assert(err, IsNil)
384+
385+
patch, err := tree.PatchContext(context.Background(), nil)
386+
c.Assert(err, IsNil)
387+
388+
c.Assert(len(patch.String()), Equals, 242971)
389+
}
390+
380391
func (s *TreeSuite) TestTreeWalkerNextSubmodule(c *C) {
381392
dotgit := fixtures.ByURL("https://github.com/git-fixtures/submodule.git").One().DotGit()
382393
st := filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault())

remote.go

+9
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
123123
return ErrDeleteRefNotSupported
124124
}
125125

126+
if o.Force {
127+
for i := 0; i < len(o.RefSpecs); i++ {
128+
rs := &o.RefSpecs[i]
129+
if !rs.IsForceUpdate() {
130+
o.RefSpecs[i] = config.RefSpec("+" + rs.String())
131+
}
132+
}
133+
}
134+
126135
localRefs, err := r.references()
127136
if err != nil {
128137
return err

remote_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,34 @@ func (s *RemoteSuite) TestPushForce(c *C) {
612612
c.Assert(newRef, Not(DeepEquals), oldRef)
613613
}
614614

615+
func (s *RemoteSuite) TestPushForceWithOption(c *C) {
616+
f := fixtures.Basic().One()
617+
sto := filesystem.NewStorage(f.DotGit(), cache.NewObjectLRUDefault())
618+
619+
dstFs := f.DotGit()
620+
dstSto := filesystem.NewStorage(dstFs, cache.NewObjectLRUDefault())
621+
622+
url := dstFs.Root()
623+
r := NewRemote(sto, &config.RemoteConfig{
624+
Name: DefaultRemoteName,
625+
URLs: []string{url},
626+
})
627+
628+
oldRef, err := dstSto.Reference(plumbing.ReferenceName("refs/heads/branch"))
629+
c.Assert(err, IsNil)
630+
c.Assert(oldRef, NotNil)
631+
632+
err = r.Push(&PushOptions{
633+
RefSpecs: []config.RefSpec{"refs/heads/master:refs/heads/branch"},
634+
Force: true,
635+
})
636+
c.Assert(err, IsNil)
637+
638+
newRef, err := dstSto.Reference(plumbing.ReferenceName("refs/heads/branch"))
639+
c.Assert(err, IsNil)
640+
c.Assert(newRef, Not(DeepEquals), oldRef)
641+
}
642+
615643
func (s *RemoteSuite) TestPushPrune(c *C) {
616644
fs := fixtures.Basic().One().DotGit()
617645
url := c.MkDir()

0 commit comments

Comments
 (0)