Skip to content

Commit 275ffa3

Browse files
committed
Merge branch 'master' into yoel/allow-missing-blobs
2 parents ae6a062 + c798d4a commit 275ffa3

File tree

117 files changed

+2400
-468
lines changed

Some content is hidden

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

117 files changed

+2400
-468
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ coverage.out
22
*~
33
coverage.txt
44
profile.out
5+
.tmp/

_examples/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Here you can find a list of annotated _go-git_ examples:
1919
- [branch](branch/main.go) - How to create and remove branches or any other kind of reference.
2020
- [tag](tag/main.go) - List/print repository tags.
2121
- [tag create and push](tag-create-push/main.go) - Create and push a new tag.
22+
- [tag find if head is tagged](find-if-any-tag-point-head/main.go) - Find if `HEAD` is tagged.
2223
- [remotes](remotes/main.go) - Working with remotes: adding, removing, etc.
2324
- [progress](progress/main.go) - Printing the progress information from the sideband.
2425
- [revision](revision/main.go) - Solve a revision into a commit.

_examples/azure_devops/main.go

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
git "github.com/go-git/go-git/v5"
8+
. "github.com/go-git/go-git/v5/_examples"
9+
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
10+
"github.com/go-git/go-git/v5/plumbing/transport"
11+
"github.com/go-git/go-git/v5/plumbing/transport/http"
12+
)
13+
14+
func main() {
15+
CheckArgs("<url>", "<directory>", "<azuredevops_username>", "<azuredevops_password>")
16+
url, directory, username, password := os.Args[1], os.Args[2], os.Args[3], os.Args[4]
17+
18+
// Clone the given repository to the given directory
19+
Info("git clone %s %s", url, directory)
20+
21+
// Azure DevOps requires capabilities multi_ack / multi_ack_detailed,
22+
// which are not fully implemented and by default are included in
23+
// transport.UnsupportedCapabilities.
24+
//
25+
// The initial clone operations require a full download of the repository,
26+
// and therefore those unsupported capabilities are not as crucial, so
27+
// by removing them from that list allows for the first clone to work
28+
// successfully.
29+
//
30+
// Additional fetches will yield issues, therefore work always from a clean
31+
// clone until those capabilities are fully supported.
32+
//
33+
// New commits and pushes against a remote worked without any issues.
34+
transport.UnsupportedCapabilities = []capability.Capability{
35+
capability.ThinPack,
36+
}
37+
38+
r, err := git.PlainClone(directory, false, &git.CloneOptions{
39+
Auth: &http.BasicAuth{
40+
Username: username,
41+
Password: password,
42+
},
43+
URL: url,
44+
Progress: os.Stdout,
45+
})
46+
CheckIfError(err)
47+
48+
// ... retrieving the branch being pointed by HEAD
49+
ref, err := r.Head()
50+
CheckIfError(err)
51+
// ... retrieving the commit object
52+
commit, err := r.CommitObject(ref.Hash())
53+
CheckIfError(err)
54+
55+
fmt.Println(commit)
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/go-git/go-git/v5"
8+
. "github.com/go-git/go-git/v5/_examples"
9+
"github.com/go-git/go-git/v5/plumbing"
10+
)
11+
12+
// Basic example of how to find if HEAD is tagged.
13+
func main() {
14+
CheckArgs("<path>")
15+
path := os.Args[1]
16+
17+
// We instantiate a new repository targeting the given path (the .git folder)
18+
r, err := git.PlainOpen(path)
19+
CheckIfError(err)
20+
21+
// Get HEAD reference to use for comparison later on.
22+
ref, err := r.Head()
23+
CheckIfError(err)
24+
25+
tags, err := r.Tags()
26+
CheckIfError(err)
27+
28+
// List all tags, both lightweight tags and annotated tags and see if some tag points to HEAD reference.
29+
err = tags.ForEach(func(t *plumbing.Reference) error {
30+
// This technique should work for both lightweight and annotated tags.
31+
revHash, err := r.ResolveRevision(plumbing.Revision(t.Name()))
32+
CheckIfError(err)
33+
if *revHash == ref.Hash() {
34+
fmt.Printf("Found tag %s with hash %s pointing to HEAD %s\n", t.Name().Short(), revHash, ref.Hash())
35+
}
36+
return nil
37+
})
38+
}

_examples/remotes/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func main() {
3333
CheckIfError(err)
3434

3535
// List remotes from a repository
36-
Info("git remotes -v")
36+
Info("git remote -v")
3737

3838
list, err := r.Remotes()
3939
CheckIfError(err)

common_test.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"github.com/go-git/go-git/v5/plumbing"
88
"github.com/go-git/go-git/v5/plumbing/cache"
99
"github.com/go-git/go-git/v5/plumbing/format/packfile"
10-
"github.com/go-git/go-git/v5/plumbing/transport"
1110
"github.com/go-git/go-git/v5/storage/filesystem"
1211
"github.com/go-git/go-git/v5/storage/memory"
1312

@@ -25,8 +24,7 @@ type BaseSuite struct {
2524
fixtures.Suite
2625
Repository *Repository
2726

28-
backupProtocol transport.Transport
29-
cache map[string]*Repository
27+
cache map[string]*Repository
3028
}
3129

3230
func (s *BaseSuite) SetUpSuite(c *C) {
@@ -198,3 +196,11 @@ func AssertReferences(c *C, r *Repository, expected map[string]string) {
198196
c.Assert(obtained, DeepEquals, expected)
199197
}
200198
}
199+
200+
func AssertReferencesMissing(c *C, r *Repository, expected []string) {
201+
for _, name := range expected {
202+
_, err := r.Reference(plumbing.ReferenceName(name), false)
203+
c.Assert(err, NotNil)
204+
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
205+
}
206+
}

config/branch.go

+33
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package config
22

33
import (
44
"errors"
5+
"strings"
56

67
"github.com/go-git/go-git/v5/plumbing"
78
format "github.com/go-git/go-git/v5/plumbing/format/config"
@@ -26,6 +27,12 @@ type Branch struct {
2627
// "true" and "interactive". "false" is undocumented and
2728
// typically represented by the non-existence of this field
2829
Rebase string
30+
// Description explains what the branch is for.
31+
// Multi-line explanations may be used.
32+
//
33+
// Original git command to edit:
34+
// git branch --edit-description
35+
Description string
2936

3037
raw *format.Subsection
3138
}
@@ -75,16 +82,42 @@ func (b *Branch) marshal() *format.Subsection {
7582
b.raw.SetOption(rebaseKey, b.Rebase)
7683
}
7784

85+
if b.Description == "" {
86+
b.raw.RemoveOption(descriptionKey)
87+
} else {
88+
desc := quoteDescription(b.Description)
89+
b.raw.SetOption(descriptionKey, desc)
90+
}
91+
7892
return b.raw
7993
}
8094

95+
// hack to trigger conditional quoting in the
96+
// plumbing/format/config/Encoder.encodeOptions
97+
//
98+
// Current Encoder implementation uses Go %q format if value contains a backslash character,
99+
// which is not consistent with reference git implementation.
100+
// git just replaces newline characters with \n, while Encoder prints them directly.
101+
// Until value quoting fix, we should escape description value by replacing newline characters with \n.
102+
func quoteDescription(desc string) string {
103+
return strings.ReplaceAll(desc, "\n", `\n`)
104+
}
105+
81106
func (b *Branch) unmarshal(s *format.Subsection) error {
82107
b.raw = s
83108

84109
b.Name = b.raw.Name
85110
b.Remote = b.raw.Options.Get(remoteSection)
86111
b.Merge = plumbing.ReferenceName(b.raw.Options.Get(mergeKey))
87112
b.Rebase = b.raw.Options.Get(rebaseKey)
113+
b.Description = unquoteDescription(b.raw.Options.Get(descriptionKey))
88114

89115
return b.Validate()
90116
}
117+
118+
// hack to enable conditional quoting in the
119+
// plumbing/format/config/Encoder.encodeOptions
120+
// goto quoteDescription for details.
121+
func unquoteDescription(desc string) string {
122+
return strings.ReplaceAll(desc, `\n`, "\n")
123+
}

config/config.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"github.com/go-git/go-billy/v5/osfs"
1616
"github.com/go-git/go-git/v5/internal/url"
1717
format "github.com/go-git/go-git/v5/plumbing/format/config"
18-
"github.com/mitchellh/go-homedir"
1918
)
2019

2120
const (
@@ -150,7 +149,7 @@ func ReadConfig(r io.Reader) (*Config, error) {
150149
// config file to the given scope, a empty one is returned.
151150
func LoadConfig(scope Scope) (*Config, error) {
152151
if scope == LocalScope {
153-
return nil, fmt.Errorf("LocalScope should be read from the a ConfigStorer.")
152+
return nil, fmt.Errorf("LocalScope should be read from the a ConfigStorer")
154153
}
155154

156155
files, err := Paths(scope)
@@ -185,7 +184,7 @@ func Paths(scope Scope) ([]string, error) {
185184
files = append(files, filepath.Join(xdg, "git/config"))
186185
}
187186

188-
home, err := homedir.Dir()
187+
home, err := os.UserHomeDir()
189188
if err != nil {
190189
return nil, err
191190
}
@@ -247,6 +246,7 @@ const (
247246
rebaseKey = "rebase"
248247
nameKey = "name"
249248
emailKey = "email"
249+
descriptionKey = "description"
250250
defaultBranchKey = "defaultBranch"
251251

252252
// DefaultPackWindow holds the number of previous objects used to

config/config_test.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ func (s *ConfigSuite) TestUnmarshal(c *C) {
5050
[branch "master"]
5151
remote = origin
5252
merge = refs/heads/master
53+
description = "Add support for branch description.\\n\\nEdit branch description: git branch --edit-description\\n"
5354
[init]
5455
defaultBranch = main
5556
[url "ssh://[email protected]/"]
@@ -86,6 +87,7 @@ func (s *ConfigSuite) TestUnmarshal(c *C) {
8687
c.Assert(cfg.Submodules["qux"].Branch, Equals, "bar")
8788
c.Assert(cfg.Branches["master"].Remote, Equals, "origin")
8889
c.Assert(cfg.Branches["master"].Merge, Equals, plumbing.ReferenceName("refs/heads/master"))
90+
c.Assert(cfg.Branches["master"].Description, Equals, "Add support for branch description.\n\nEdit branch description: git branch --edit-description\n")
8991
c.Assert(cfg.Init.DefaultBranch, Equals, "main")
9092
}
9193

@@ -111,6 +113,7 @@ func (s *ConfigSuite) TestMarshal(c *C) {
111113
[branch "master"]
112114
remote = origin
113115
merge = refs/heads/master
116+
description = "Add support for branch description.\\n\\nEdit branch description: git branch --edit-description\\n"
114117
[url "ssh://[email protected]/"]
115118
insteadOf = https://github.com/
116119
[init]
@@ -149,9 +152,10 @@ func (s *ConfigSuite) TestMarshal(c *C) {
149152
}
150153

151154
cfg.Branches["master"] = &Branch{
152-
Name: "master",
153-
Remote: "origin",
154-
Merge: "refs/heads/master",
155+
Name: "master",
156+
Remote: "origin",
157+
Merge: "refs/heads/master",
158+
Description: "Add support for branch description.\n\nEdit branch description: git branch --edit-description\n",
155159
}
156160

157161
cfg.URLs["ssh://[email protected]/"] = &URL{
@@ -361,7 +365,9 @@ func (s *ConfigSuite) TestRemoveUrlOptions(c *C) {
361365
cfg.Remotes["alt"].URLs = []string{}
362366

363367
buf, err = cfg.Marshal()
368+
c.Assert(err, IsNil)
364369
if strings.Contains(string(buf), "url") {
365370
c.Fatal("conifg should not contain any url sections")
366371
}
372+
c.Assert(err, IsNil)
367373
}

config/refspec.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func (s RefSpec) IsExactSHA1() bool {
6464
return plumbing.IsHash(s.Src())
6565
}
6666

67-
// Src return the src side.
67+
// Src returns the src side.
6868
func (s RefSpec) Src() string {
6969
spec := string(s)
7070

go.mod

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
module github.com/go-git/go-git/v5
22

33
require (
4-
github.com/Microsoft/go-winio v0.4.16 // indirect
54
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7
65
github.com/acomagu/bufpipe v1.0.3
76
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 // indirect
@@ -11,19 +10,19 @@ require (
1110
github.com/gliderlabs/ssh v0.2.2
1211
github.com/go-git/gcfg v1.5.0
1312
github.com/go-git/go-billy/v5 v5.3.1
14-
github.com/go-git/go-git-fixtures/v4 v4.2.1
13+
github.com/go-git/go-git-fixtures/v4 v4.3.1
1514
github.com/google/go-cmp v0.3.0
1615
github.com/imdario/mergo v0.3.12
1716
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
1817
github.com/jessevdk/go-flags v1.5.0
1918
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351
20-
github.com/mitchellh/go-homedir v1.1.0
2119
github.com/sergi/go-diff v1.1.0
22-
github.com/xanzy/ssh-agent v0.3.0
23-
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
24-
golang.org/x/net v0.0.0-20210326060303-6b1517762897
25-
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79
26-
golang.org/x/text v0.3.3
20+
github.com/skeema/knownhosts v1.1.0
21+
github.com/xanzy/ssh-agent v0.3.1
22+
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
23+
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
24+
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
25+
golang.org/x/text v0.3.6
2726
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
2827
gopkg.in/warnings.v0 v0.1.2 // indirect
2928
)

0 commit comments

Comments
 (0)