2
vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md
generated
vendored
2
vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md
generated
vendored
@@ -101,7 +101,7 @@ is supported by go-git.
|
||||
| http(s):// (smart) | ✔ |
|
||||
| git:// | ✔ |
|
||||
| ssh:// | ✔ |
|
||||
| file:// | ✔ |
|
||||
| file:// | partial | Warning: this is not pure Golang. This shells out to the `git` binary. |
|
||||
| custom | ✔ |
|
||||
| **other features** |
|
||||
| gitignore | ✔ |
|
||||
|
||||
8
vendor/github.com/go-git/go-git/v5/README.md
generated
vendored
8
vendor/github.com/go-git/go-git/v5/README.md
generated
vendored
@@ -1,9 +1,9 @@
|
||||

|
||||
[](https://godoc.org/github.com/src-d/go-git) [](https://github.com/go-git/go-git/actions) [](https://goreportcard.com/report/github.com/src-d/go-git)
|
||||
[](https://pkg.go.dev/github.com/go-git/go-git/v5) [](https://github.com/go-git/go-git/actions) [](https://goreportcard.com/report/github.com/go-git/go-git)
|
||||
|
||||
*go-git* is a highly extensible git implementation library written in **pure Go**.
|
||||
|
||||
It can be used to manipulate git repositories at low level *(plumbing)* or high level *(porcelain)*, through an idiomatic Go API. It also supports several types of storage, such as in-memory filesystems, or custom implementations, thanks to the [`Storer`](https://godoc.org/github.com/go-git/go-git/v5/plumbing/storer) interface.
|
||||
It can be used to manipulate git repositories at low level *(plumbing)* or high level *(porcelain)*, through an idiomatic Go API. It also supports several types of storage, such as in-memory filesystems, or custom implementations, thanks to the [`Storer`](https://pkg.go.dev/github.com/go-git/go-git/v5/plumbing/storer) interface.
|
||||
|
||||
It's being actively developed since 2015 and is being used extensively by [Keybase](https://keybase.io/blog/encrypted-git-for-everyone), [Gitea](https://gitea.io/en-us/) or [Pulumi](https://github.com/search?q=org%3Apulumi+go-git&type=Code), and by many other libraries and tools.
|
||||
|
||||
@@ -12,7 +12,7 @@ Project Status
|
||||
|
||||
After the legal issues with the [`src-d`](https://github.com/src-d) organization, the lack of update for four months and the requirement to make a hard fork, the project is **now back to normality**.
|
||||
|
||||
The project is currently actively maintained by individual contributors, including several of the original authors, but also backed by a new company `gitsigth` where `go-git` is a critical component used at scale.
|
||||
The project is currently actively maintained by individual contributors, including several of the original authors, but also backed by a new company, [gitsight](https://github.com/gitsight), where `go-git` is a critical component used at scale.
|
||||
|
||||
|
||||
Comparison with git
|
||||
@@ -37,7 +37,7 @@ import "github.com/go-git/go-git" // with go modules disabled
|
||||
Examples
|
||||
--------
|
||||
|
||||
> Please note that the `CheckIfError` and `Info` functions used in the examples are from the [examples package](https://github.com/src-d/go-git/blob/master/_examples/common.go#L17) just to be used in the examples.
|
||||
> Please note that the `CheckIfError` and `Info` functions used in the examples are from the [examples package](https://github.com/go-git/go-git/blob/master/_examples/common.go#L19) just to be used in the examples.
|
||||
|
||||
|
||||
### Basic example
|
||||
|
||||
2
vendor/github.com/go-git/go-git/v5/common.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/common.go
generated
vendored
@@ -2,8 +2,6 @@ package git
|
||||
|
||||
import "strings"
|
||||
|
||||
const defaultDotGitPath = ".git"
|
||||
|
||||
// countLines returns the number of lines in a string à la git, this is
|
||||
// The newline character is assumed to be '\n'. The empty string
|
||||
// contains 0 lines. If the last line of the string doesn't end with a
|
||||
|
||||
254
vendor/github.com/go-git/go-git/v5/config/config.go
generated
vendored
254
vendor/github.com/go-git/go-git/v5/config/config.go
generated
vendored
@@ -5,11 +5,17 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
"github.com/go-git/go-git/v5/internal/url"
|
||||
format "github.com/go-git/go-git/v5/plumbing/format/config"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -32,6 +38,16 @@ var (
|
||||
ErrRemoteConfigEmptyName = errors.New("remote config: empty name")
|
||||
)
|
||||
|
||||
// Scope defines the scope of a config file, such as local, global or system.
|
||||
type Scope int
|
||||
|
||||
// Available ConfigScope's
|
||||
const (
|
||||
LocalScope Scope = iota
|
||||
GlobalScope
|
||||
SystemScope
|
||||
)
|
||||
|
||||
// Config contains the repository configuration
|
||||
// https://www.kernel.org/pub/software/scm/git/docs/git-config.html#FILES
|
||||
type Config struct {
|
||||
@@ -46,6 +62,27 @@ type Config struct {
|
||||
CommentChar string
|
||||
}
|
||||
|
||||
User struct {
|
||||
// Name is the personal name of the author and the commiter of a commit.
|
||||
Name string
|
||||
// Email is the email of the author and the commiter of a commit.
|
||||
Email string
|
||||
}
|
||||
|
||||
Author struct {
|
||||
// Name is the personal name of the author of a commit.
|
||||
Name string
|
||||
// Email is the email of the author of a commit.
|
||||
Email string
|
||||
}
|
||||
|
||||
Committer struct {
|
||||
// Name is the personal name of the commiter of a commit.
|
||||
Name string
|
||||
// Email is the email of the the commiter of a commit.
|
||||
Email string
|
||||
}
|
||||
|
||||
Pack struct {
|
||||
// Window controls the size of the sliding window for delta
|
||||
// compression. The default is 10. A value of 0 turns off
|
||||
@@ -53,6 +90,13 @@ type Config struct {
|
||||
Window uint
|
||||
}
|
||||
|
||||
Init struct {
|
||||
// DefaultBranch Allows overriding the default branch name
|
||||
// e.g. when initializing a new repository or when cloning
|
||||
// an empty repository.
|
||||
DefaultBranch string
|
||||
}
|
||||
|
||||
// Remotes list of repository remotes, the key of the map is the name
|
||||
// of the remote, should equal to RemoteConfig.Name.
|
||||
Remotes map[string]*RemoteConfig
|
||||
@@ -62,6 +106,9 @@ type Config struct {
|
||||
// Branches list of branches, the key is the branch name and should
|
||||
// equal Branch.Name
|
||||
Branches map[string]*Branch
|
||||
// URLs list of url rewrite rules, if repo url starts with URL.InsteadOf value, it will be replaced with the
|
||||
// key instead.
|
||||
URLs map[string]*URL
|
||||
// Raw contains the raw information of a config file. The main goal is
|
||||
// preserve the parsed information from the original format, to avoid
|
||||
// dropping unsupported fields.
|
||||
@@ -74,6 +121,7 @@ func NewConfig() *Config {
|
||||
Remotes: make(map[string]*RemoteConfig),
|
||||
Submodules: make(map[string]*Submodule),
|
||||
Branches: make(map[string]*Branch),
|
||||
URLs: make(map[string]*URL),
|
||||
Raw: format.New(),
|
||||
}
|
||||
|
||||
@@ -82,6 +130,77 @@ func NewConfig() *Config {
|
||||
return config
|
||||
}
|
||||
|
||||
// ReadConfig reads a config file from a io.Reader.
|
||||
func ReadConfig(r io.Reader) (*Config, error) {
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg := NewConfig()
|
||||
if err = cfg.Unmarshal(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// LoadConfig loads a config file from a given scope. The returned Config,
|
||||
// contains exclusively information fom the given scope. If couldn't find a
|
||||
// config file to the given scope, a empty one is returned.
|
||||
func LoadConfig(scope Scope) (*Config, error) {
|
||||
if scope == LocalScope {
|
||||
return nil, fmt.Errorf("LocalScope should be read from the a ConfigStorer.")
|
||||
}
|
||||
|
||||
files, err := Paths(scope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
f, err := osfs.Default.Open(file)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
return ReadConfig(f)
|
||||
}
|
||||
|
||||
return NewConfig(), nil
|
||||
}
|
||||
|
||||
// Paths returns the config file location for a given scope.
|
||||
func Paths(scope Scope) ([]string, error) {
|
||||
var files []string
|
||||
switch scope {
|
||||
case GlobalScope:
|
||||
xdg := os.Getenv("XDG_CONFIG_HOME")
|
||||
if xdg != "" {
|
||||
files = append(files, filepath.Join(xdg, "git/config"))
|
||||
}
|
||||
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
files = append(files,
|
||||
filepath.Join(home, ".gitconfig"),
|
||||
filepath.Join(home, ".config/git/config"),
|
||||
)
|
||||
case SystemScope:
|
||||
files = append(files, "/etc/gitconfig")
|
||||
}
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
func (c *Config) Validate() error {
|
||||
for name, r := range c.Remotes {
|
||||
@@ -113,6 +232,11 @@ const (
|
||||
branchSection = "branch"
|
||||
coreSection = "core"
|
||||
packSection = "pack"
|
||||
userSection = "user"
|
||||
authorSection = "author"
|
||||
committerSection = "committer"
|
||||
initSection = "init"
|
||||
urlSection = "url"
|
||||
fetchKey = "fetch"
|
||||
urlKey = "url"
|
||||
bareKey = "bare"
|
||||
@@ -121,6 +245,9 @@ const (
|
||||
windowKey = "window"
|
||||
mergeKey = "merge"
|
||||
rebaseKey = "rebase"
|
||||
nameKey = "name"
|
||||
emailKey = "email"
|
||||
defaultBranchKey = "defaultBranch"
|
||||
|
||||
// DefaultPackWindow holds the number of previous objects used to
|
||||
// generate deltas. The value 10 is the same used by git command.
|
||||
@@ -138,6 +265,8 @@ func (c *Config) Unmarshal(b []byte) error {
|
||||
}
|
||||
|
||||
c.unmarshalCore()
|
||||
c.unmarshalUser()
|
||||
c.unmarshalInit()
|
||||
if err := c.unmarshalPack(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -147,6 +276,10 @@ func (c *Config) Unmarshal(b []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.unmarshalURLs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.unmarshalRemotes()
|
||||
}
|
||||
|
||||
@@ -160,6 +293,20 @@ func (c *Config) unmarshalCore() {
|
||||
c.Core.CommentChar = s.Options.Get(commentCharKey)
|
||||
}
|
||||
|
||||
func (c *Config) unmarshalUser() {
|
||||
s := c.Raw.Section(userSection)
|
||||
c.User.Name = s.Options.Get(nameKey)
|
||||
c.User.Email = s.Options.Get(emailKey)
|
||||
|
||||
s = c.Raw.Section(authorSection)
|
||||
c.Author.Name = s.Options.Get(nameKey)
|
||||
c.Author.Email = s.Options.Get(emailKey)
|
||||
|
||||
s = c.Raw.Section(committerSection)
|
||||
c.Committer.Name = s.Options.Get(nameKey)
|
||||
c.Committer.Email = s.Options.Get(emailKey)
|
||||
}
|
||||
|
||||
func (c *Config) unmarshalPack() error {
|
||||
s := c.Raw.Section(packSection)
|
||||
window := s.Options.Get(windowKey)
|
||||
@@ -186,6 +333,25 @@ func (c *Config) unmarshalRemotes() error {
|
||||
c.Remotes[r.Name] = r
|
||||
}
|
||||
|
||||
// Apply insteadOf url rules
|
||||
for _, r := range c.Remotes {
|
||||
r.applyURLRules(c.URLs)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) unmarshalURLs() error {
|
||||
s := c.Raw.Section(urlSection)
|
||||
for _, sub := range s.Subsections {
|
||||
r := &URL{}
|
||||
if err := r.unmarshal(sub); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.URLs[r.Name] = r
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -217,13 +383,21 @@ func (c *Config) unmarshalBranches() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) unmarshalInit() {
|
||||
s := c.Raw.Section(initSection)
|
||||
c.Init.DefaultBranch = s.Options.Get(defaultBranchKey)
|
||||
}
|
||||
|
||||
// Marshal returns Config encoded as a git-config file.
|
||||
func (c *Config) Marshal() ([]byte, error) {
|
||||
c.marshalCore()
|
||||
c.marshalUser()
|
||||
c.marshalPack()
|
||||
c.marshalRemotes()
|
||||
c.marshalSubmodules()
|
||||
c.marshalBranches()
|
||||
c.marshalURLs()
|
||||
c.marshalInit()
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := format.NewEncoder(buf).Encode(c.Raw); err != nil {
|
||||
@@ -242,6 +416,35 @@ func (c *Config) marshalCore() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) marshalUser() {
|
||||
s := c.Raw.Section(userSection)
|
||||
if c.User.Name != "" {
|
||||
s.SetOption(nameKey, c.User.Name)
|
||||
}
|
||||
|
||||
if c.User.Email != "" {
|
||||
s.SetOption(emailKey, c.User.Email)
|
||||
}
|
||||
|
||||
s = c.Raw.Section(authorSection)
|
||||
if c.Author.Name != "" {
|
||||
s.SetOption(nameKey, c.Author.Name)
|
||||
}
|
||||
|
||||
if c.Author.Email != "" {
|
||||
s.SetOption(emailKey, c.Author.Email)
|
||||
}
|
||||
|
||||
s = c.Raw.Section(committerSection)
|
||||
if c.Committer.Name != "" {
|
||||
s.SetOption(nameKey, c.Committer.Name)
|
||||
}
|
||||
|
||||
if c.Committer.Email != "" {
|
||||
s.SetOption(emailKey, c.Committer.Email)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) marshalPack() {
|
||||
s := c.Raw.Section(packSection)
|
||||
if c.Pack.Window != DefaultPackWindow {
|
||||
@@ -318,6 +521,27 @@ func (c *Config) marshalBranches() {
|
||||
s.Subsections = newSubsections
|
||||
}
|
||||
|
||||
func (c *Config) marshalURLs() {
|
||||
s := c.Raw.Section(urlSection)
|
||||
s.Subsections = make(format.Subsections, len(c.URLs))
|
||||
|
||||
var i int
|
||||
for _, r := range c.URLs {
|
||||
section := r.marshal()
|
||||
// the submodule section at config is a subset of the .gitmodule file
|
||||
// we should remove the non-valid options for the config file.
|
||||
s.Subsections[i] = section
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) marshalInit() {
|
||||
s := c.Raw.Section(initSection)
|
||||
if c.Init.DefaultBranch != "" {
|
||||
s.SetOption(defaultBranchKey, c.Init.DefaultBranch)
|
||||
}
|
||||
}
|
||||
|
||||
// RemoteConfig contains the configuration for a given remote repository.
|
||||
type RemoteConfig struct {
|
||||
// Name of the remote
|
||||
@@ -325,6 +549,12 @@ type RemoteConfig struct {
|
||||
// URLs the URLs of a remote repository. It must be non-empty. Fetch will
|
||||
// always use the first URL, while push will use all of them.
|
||||
URLs []string
|
||||
|
||||
// insteadOfRulesApplied have urls been modified
|
||||
insteadOfRulesApplied bool
|
||||
// originalURLs are the urls before applying insteadOf rules
|
||||
originalURLs []string
|
||||
|
||||
// Fetch the default set of "refspec" for fetch operation
|
||||
Fetch []RefSpec
|
||||
|
||||
@@ -385,7 +615,12 @@ func (c *RemoteConfig) marshal() *format.Subsection {
|
||||
if len(c.URLs) == 0 {
|
||||
c.raw.RemoveOption(urlKey)
|
||||
} else {
|
||||
c.raw.SetOption(urlKey, c.URLs...)
|
||||
urls := c.URLs
|
||||
if c.insteadOfRulesApplied {
|
||||
urls = c.originalURLs
|
||||
}
|
||||
|
||||
c.raw.SetOption(urlKey, urls...)
|
||||
}
|
||||
|
||||
if len(c.Fetch) == 0 {
|
||||
@@ -405,3 +640,20 @@ func (c *RemoteConfig) marshal() *format.Subsection {
|
||||
func (c *RemoteConfig) IsFirstURLLocal() bool {
|
||||
return url.IsLocalEndpoint(c.URLs[0])
|
||||
}
|
||||
|
||||
func (c *RemoteConfig) applyURLRules(urlRules map[string]*URL) {
|
||||
// save original urls
|
||||
originalURLs := make([]string, len(c.URLs))
|
||||
copy(originalURLs, c.URLs)
|
||||
|
||||
for i, url := range c.URLs {
|
||||
if matchingURLRule := findLongestInsteadOfMatch(url, urlRules); matchingURLRule != nil {
|
||||
c.URLs[i] = matchingURLRule.ApplyInsteadOf(c.URLs[i])
|
||||
c.insteadOfRulesApplied = true
|
||||
}
|
||||
}
|
||||
|
||||
if c.insteadOfRulesApplied {
|
||||
c.originalURLs = originalURLs
|
||||
}
|
||||
}
|
||||
|
||||
9
vendor/github.com/go-git/go-git/v5/config/refspec.go
generated
vendored
9
vendor/github.com/go-git/go-git/v5/config/refspec.go
generated
vendored
@@ -25,7 +25,7 @@ var (
|
||||
// reference even if it isn’t a fast-forward.
|
||||
// eg.: "+refs/heads/*:refs/remotes/origin/*"
|
||||
//
|
||||
// https://git-scm.com/book/es/v2/Git-Internals-The-Refspec
|
||||
// https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
|
||||
type RefSpec string
|
||||
|
||||
// Validate validates the RefSpec
|
||||
@@ -59,6 +59,11 @@ func (s RefSpec) IsDelete() bool {
|
||||
return s[0] == refSpecSeparator[0]
|
||||
}
|
||||
|
||||
// IsExactSHA1 returns true if the source is a SHA1 hash.
|
||||
func (s RefSpec) IsExactSHA1() bool {
|
||||
return plumbing.IsHash(s.Src())
|
||||
}
|
||||
|
||||
// Src return the src side.
|
||||
func (s RefSpec) Src() string {
|
||||
spec := string(s)
|
||||
@@ -69,8 +74,8 @@ func (s RefSpec) Src() string {
|
||||
} else {
|
||||
start = 0
|
||||
}
|
||||
end := strings.Index(spec, refSpecSeparator)
|
||||
|
||||
end := strings.Index(spec, refSpecSeparator)
|
||||
return spec[start:end]
|
||||
}
|
||||
|
||||
|
||||
81
vendor/github.com/go-git/go-git/v5/config/url.go
generated
vendored
Normal file
81
vendor/github.com/go-git/go-git/v5/config/url.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
format "github.com/go-git/go-git/v5/plumbing/format/config"
|
||||
)
|
||||
|
||||
var (
|
||||
errURLEmptyInsteadOf = errors.New("url config: empty insteadOf")
|
||||
)
|
||||
|
||||
// Url defines Url rewrite rules
|
||||
type URL struct {
|
||||
// Name new base url
|
||||
Name string
|
||||
// Any URL that starts with this value will be rewritten to start, instead, with <base>.
|
||||
// When more than one insteadOf strings match a given URL, the longest match is used.
|
||||
InsteadOf string
|
||||
|
||||
// raw representation of the subsection, filled by marshal or unmarshal are
|
||||
// called.
|
||||
raw *format.Subsection
|
||||
}
|
||||
|
||||
// Validate validates fields of branch
|
||||
func (b *URL) Validate() error {
|
||||
if b.InsteadOf == "" {
|
||||
return errURLEmptyInsteadOf
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
insteadOfKey = "insteadOf"
|
||||
)
|
||||
|
||||
func (u *URL) unmarshal(s *format.Subsection) error {
|
||||
u.raw = s
|
||||
|
||||
u.Name = s.Name
|
||||
u.InsteadOf = u.raw.Option(insteadOfKey)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *URL) marshal() *format.Subsection {
|
||||
if u.raw == nil {
|
||||
u.raw = &format.Subsection{}
|
||||
}
|
||||
|
||||
u.raw.Name = u.Name
|
||||
u.raw.SetOption(insteadOfKey, u.InsteadOf)
|
||||
|
||||
return u.raw
|
||||
}
|
||||
|
||||
func findLongestInsteadOfMatch(remoteURL string, urls map[string]*URL) *URL {
|
||||
var longestMatch *URL
|
||||
for _, u := range urls {
|
||||
if !strings.HasPrefix(remoteURL, u.InsteadOf) {
|
||||
continue
|
||||
}
|
||||
|
||||
// according to spec if there is more than one match, take the logest
|
||||
if longestMatch == nil || len(longestMatch.InsteadOf) < len(u.InsteadOf) {
|
||||
longestMatch = u
|
||||
}
|
||||
}
|
||||
|
||||
return longestMatch
|
||||
}
|
||||
|
||||
func (u *URL) ApplyInsteadOf(url string) string {
|
||||
if !strings.HasPrefix(url, u.InsteadOf) {
|
||||
return url
|
||||
}
|
||||
|
||||
return u.Name + url[len(u.InsteadOf):]
|
||||
}
|
||||
24
vendor/github.com/go-git/go-git/v5/go.mod
generated
vendored
24
vendor/github.com/go-git/go-git/v5/go.mod
generated
vendored
@@ -1,26 +1,30 @@
|
||||
module github.com/go-git/go-git/v5
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.4.16 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7
|
||||
github.com/acomagu/bufpipe v1.0.3
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 // indirect
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||
github.com/emirpasic/gods v1.12.0
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
|
||||
github.com/gliderlabs/ssh v0.2.2
|
||||
github.com/go-git/gcfg v1.5.0
|
||||
github.com/go-git/go-billy/v5 v5.0.0
|
||||
github.com/go-git/go-git-fixtures/v4 v4.0.1
|
||||
github.com/go-git/go-billy/v5 v5.3.1
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1
|
||||
github.com/google/go-cmp v0.3.0
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
|
||||
github.com/jessevdk/go-flags v1.4.0
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd
|
||||
github.com/jessevdk/go-flags v1.5.0
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
github.com/sergi/go-diff v1.1.0
|
||||
github.com/xanzy/ssh-agent v0.2.1
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a
|
||||
golang.org/x/text v0.3.2
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f
|
||||
github.com/xanzy/ssh-agent v0.3.0
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897
|
||||
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79
|
||||
golang.org/x/text v0.3.3
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
||||
|
||||
|
||||
91
vendor/github.com/go-git/go-git/v5/go.sum
generated
vendored
91
vendor/github.com/go-git/go-git/v5/go.sum
generated
vendored
@@ -1,5 +1,10 @@
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
|
||||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
@@ -16,63 +21,83 @@ github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
|
||||
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
|
||||
github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-billy/v5 v5.3.0 h1:KZL1OFdS+afiIjN4hr/zpj5cEtC0OJhbmTA18PsBb8c=
|
||||
github.com/go-git/go-billy/v5 v5.3.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
|
||||
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
|
||||
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79 h1:RX8C8PRZc2hTIod4ds8ij+/4RQX3AqhYj3uOHmyaz4E=
|
||||
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
8
vendor/github.com/go-git/go-git/v5/internal/revision/parser.go
generated
vendored
8
vendor/github.com/go-git/go-git/v5/internal/revision/parser.go
generated
vendored
@@ -28,7 +28,7 @@ func (e *ErrInvalidRevision) Error() string {
|
||||
type Revisioner interface {
|
||||
}
|
||||
|
||||
// Ref represents a reference name : HEAD, master
|
||||
// Ref represents a reference name : HEAD, master, <hash>
|
||||
type Ref string
|
||||
|
||||
// TildePath represents ~, ~{n}
|
||||
@@ -297,7 +297,7 @@ func (p *Parser) parseAt() (Revisioner, error) {
|
||||
}
|
||||
|
||||
if t != cbrace {
|
||||
return nil, &ErrInvalidRevision{fmt.Sprintf(`missing "}" in @{-n} structure`)}
|
||||
return nil, &ErrInvalidRevision{s: `missing "}" in @{-n} structure`}
|
||||
}
|
||||
|
||||
return AtCheckout{n}, nil
|
||||
@@ -419,7 +419,7 @@ func (p *Parser) parseCaretBraces() (Revisioner, error) {
|
||||
case re == "" && tok == emark && nextTok == minus:
|
||||
negate = true
|
||||
case re == "" && tok == emark:
|
||||
return nil, &ErrInvalidRevision{fmt.Sprintf(`revision suffix brace component sequences starting with "/!" others than those defined are reserved`)}
|
||||
return nil, &ErrInvalidRevision{s: `revision suffix brace component sequences starting with "/!" others than those defined are reserved`}
|
||||
case re == "" && tok == slash:
|
||||
p.unscan()
|
||||
case tok != slash && start:
|
||||
@@ -490,7 +490,7 @@ func (p *Parser) parseColonSlash() (Revisioner, error) {
|
||||
case re == "" && tok == emark && nextTok == minus:
|
||||
negate = true
|
||||
case re == "" && tok == emark:
|
||||
return nil, &ErrInvalidRevision{fmt.Sprintf(`revision suffix brace component sequences starting with "/!" others than those defined are reserved`)}
|
||||
return nil, &ErrInvalidRevision{s: `revision suffix brace component sequences starting with "/!" others than those defined are reserved`}
|
||||
case tok == eof:
|
||||
p.unscan()
|
||||
reg, err := regexp.Compile(re)
|
||||
|
||||
136
vendor/github.com/go-git/go-git/v5/options.go
generated
vendored
136
vendor/github.com/go-git/go-git/v5/options.go
generated
vendored
@@ -2,11 +2,12 @@ package git
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
@@ -59,6 +60,10 @@ type CloneOptions struct {
|
||||
// Tags describe how the tags will be fetched from the remote repository,
|
||||
// by default is AllTags.
|
||||
Tags TagMode
|
||||
// InsecureSkipTLS skips ssl verify if protocol is https
|
||||
InsecureSkipTLS bool
|
||||
// CABundle specify additional ca bundle with system cert pool
|
||||
CABundle []byte
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
@@ -104,6 +109,10 @@ type PullOptions struct {
|
||||
// Force allows the pull to update a local branch even when the remote
|
||||
// branch does not descend from it.
|
||||
Force bool
|
||||
// InsecureSkipTLS skips ssl verify if protocol is https
|
||||
InsecureSkipTLS bool
|
||||
// CABundle specify additional ca bundle with system cert pool
|
||||
CABundle []byte
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
@@ -154,6 +163,10 @@ type FetchOptions struct {
|
||||
// Force allows the fetch to update a local branch even when the remote
|
||||
// branch does not descend from it.
|
||||
Force bool
|
||||
// InsecureSkipTLS skips ssl verify if protocol is https
|
||||
InsecureSkipTLS bool
|
||||
// CABundle specify additional ca bundle with system cert pool
|
||||
CABundle []byte
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
@@ -190,6 +203,16 @@ type PushOptions struct {
|
||||
// Prune specify that remote refs that match given RefSpecs and that do
|
||||
// not exist locally will be removed.
|
||||
Prune bool
|
||||
// Force allows the push to update a remote branch even when the local
|
||||
// branch does not descend from it.
|
||||
Force bool
|
||||
// InsecureSkipTLS skips ssl verify if protocal is https
|
||||
InsecureSkipTLS bool
|
||||
// CABundle specify additional ca bundle with system cert pool
|
||||
CABundle []byte
|
||||
// RequireRemoteRefs only allows a remote ref to be updated if its current
|
||||
// value is the one specified here.
|
||||
RequireRemoteRefs []config.RefSpec
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
@@ -370,12 +393,37 @@ var (
|
||||
ErrMissingAuthor = errors.New("author field is required")
|
||||
)
|
||||
|
||||
// AddOptions describes how an `add` operation should be performed
|
||||
type AddOptions struct {
|
||||
// All equivalent to `git add -A`, update the index not only where the
|
||||
// working tree has a file matching `Path` but also where the index already
|
||||
// has an entry. This adds, modifies, and removes index entries to match the
|
||||
// working tree. If no `Path` nor `Glob` is given when `All` option is
|
||||
// used, all files in the entire working tree are updated.
|
||||
All bool
|
||||
// Path is the exact filepath to the file or directory to be added.
|
||||
Path string
|
||||
// Glob adds all paths, matching pattern, to the index. If pattern matches a
|
||||
// directory path, all directory contents are added to the index recursively.
|
||||
Glob string
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
func (o *AddOptions) Validate(r *Repository) error {
|
||||
if o.Path != "" && o.Glob != "" {
|
||||
return fmt.Errorf("fields Path and Glob are mutual exclusive")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommitOptions describes how a commit operation should be performed.
|
||||
type CommitOptions struct {
|
||||
// All automatically stage files that have been modified and deleted, but
|
||||
// new files you have not told Git about are not affected.
|
||||
All bool
|
||||
// Author is the author's signature of the commit.
|
||||
// Author is the author's signature of the commit. If Author is empty the
|
||||
// Name and Email is read from the config, and time.Now it's used as When.
|
||||
Author *object.Signature
|
||||
// Committer is the committer's signature of the commit. If Committer is
|
||||
// nil the Author signature is used.
|
||||
@@ -392,7 +440,9 @@ type CommitOptions struct {
|
||||
// Validate validates the fields and sets the default values.
|
||||
func (o *CommitOptions) Validate(r *Repository) error {
|
||||
if o.Author == nil {
|
||||
return ErrMissingAuthor
|
||||
if err := o.loadConfigAuthorAndCommitter(r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if o.Committer == nil {
|
||||
@@ -413,6 +463,43 @@ func (o *CommitOptions) Validate(r *Repository) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *CommitOptions) loadConfigAuthorAndCommitter(r *Repository) error {
|
||||
cfg, err := r.ConfigScoped(config.SystemScope)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if o.Author == nil && cfg.Author.Email != "" && cfg.Author.Name != "" {
|
||||
o.Author = &object.Signature{
|
||||
Name: cfg.Author.Name,
|
||||
Email: cfg.Author.Email,
|
||||
When: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
if o.Committer == nil && cfg.Committer.Email != "" && cfg.Committer.Name != "" {
|
||||
o.Committer = &object.Signature{
|
||||
Name: cfg.Committer.Name,
|
||||
Email: cfg.Committer.Email,
|
||||
When: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
if o.Author == nil && cfg.User.Email != "" && cfg.User.Name != "" {
|
||||
o.Author = &object.Signature{
|
||||
Name: cfg.User.Name,
|
||||
Email: cfg.User.Email,
|
||||
When: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
if o.Author == nil {
|
||||
return ErrMissingAuthor
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
ErrMissingName = errors.New("name field is required")
|
||||
ErrMissingTagger = errors.New("tagger field is required")
|
||||
@@ -421,7 +508,8 @@ var (
|
||||
|
||||
// CreateTagOptions describes how a tag object should be created.
|
||||
type CreateTagOptions struct {
|
||||
// Tagger defines the signature of the tag creator.
|
||||
// Tagger defines the signature of the tag creator. If Tagger is empty the
|
||||
// Name and Email is read from the config, and time.Now it's used as When.
|
||||
Tagger *object.Signature
|
||||
// Message defines the annotation of the tag. It is canonicalized during
|
||||
// validation into the format expected by git - no leading whitespace and
|
||||
@@ -435,7 +523,9 @@ type CreateTagOptions struct {
|
||||
// Validate validates the fields and sets the default values.
|
||||
func (o *CreateTagOptions) Validate(r *Repository, hash plumbing.Hash) error {
|
||||
if o.Tagger == nil {
|
||||
return ErrMissingTagger
|
||||
if err := o.loadConfigTagger(r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if o.Message == "" {
|
||||
@@ -448,10 +538,43 @@ func (o *CreateTagOptions) Validate(r *Repository, hash plumbing.Hash) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *CreateTagOptions) loadConfigTagger(r *Repository) error {
|
||||
cfg, err := r.ConfigScoped(config.SystemScope)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if o.Tagger == nil && cfg.Author.Email != "" && cfg.Author.Name != "" {
|
||||
o.Tagger = &object.Signature{
|
||||
Name: cfg.Author.Name,
|
||||
Email: cfg.Author.Email,
|
||||
When: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
if o.Tagger == nil && cfg.User.Email != "" && cfg.User.Name != "" {
|
||||
o.Tagger = &object.Signature{
|
||||
Name: cfg.User.Name,
|
||||
Email: cfg.User.Email,
|
||||
When: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
if o.Tagger == nil {
|
||||
return ErrMissingTagger
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListOptions describes how a remote list should be performed.
|
||||
type ListOptions struct {
|
||||
// Auth credentials, if required, to use with the remote repository.
|
||||
Auth transport.AuthMethod
|
||||
// InsecureSkipTLS skips ssl verify if protocal is https
|
||||
InsecureSkipTLS bool
|
||||
// CABundle specify additional ca bundle with system cert pool
|
||||
CABundle []byte
|
||||
}
|
||||
|
||||
// CleanOptions describes how a clean should be performed.
|
||||
@@ -502,6 +625,9 @@ type PlainOpenOptions struct {
|
||||
// DetectDotGit defines whether parent directories should be
|
||||
// walked until a .git directory or file is found.
|
||||
DetectDotGit bool
|
||||
// Enable .git/commondir support (see https://git-scm.com/docs/gitrepository-layout#Documentation/gitrepository-layout.txt).
|
||||
// NOTE: This option will only work with the filesystem storage.
|
||||
EnableDotGitCommonDir bool
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
|
||||
38
vendor/github.com/go-git/go-git/v5/plumbing/color/color.go
generated
vendored
Normal file
38
vendor/github.com/go-git/go-git/v5/plumbing/color/color.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
package color
|
||||
|
||||
// TODO read colors from a github.com/go-git/go-git/plumbing/format/config.Config struct
|
||||
// TODO implement color parsing, see https://github.com/git/git/blob/v2.26.2/color.c
|
||||
|
||||
// Colors. See https://github.com/git/git/blob/v2.26.2/color.h#L24-L53.
|
||||
const (
|
||||
Normal = ""
|
||||
Reset = "\033[m"
|
||||
Bold = "\033[1m"
|
||||
Red = "\033[31m"
|
||||
Green = "\033[32m"
|
||||
Yellow = "\033[33m"
|
||||
Blue = "\033[34m"
|
||||
Magenta = "\033[35m"
|
||||
Cyan = "\033[36m"
|
||||
BoldRed = "\033[1;31m"
|
||||
BoldGreen = "\033[1;32m"
|
||||
BoldYellow = "\033[1;33m"
|
||||
BoldBlue = "\033[1;34m"
|
||||
BoldMagenta = "\033[1;35m"
|
||||
BoldCyan = "\033[1;36m"
|
||||
FaintRed = "\033[2;31m"
|
||||
FaintGreen = "\033[2;32m"
|
||||
FaintYellow = "\033[2;33m"
|
||||
FaintBlue = "\033[2;34m"
|
||||
FaintMagenta = "\033[2;35m"
|
||||
FaintCyan = "\033[2;36m"
|
||||
BgRed = "\033[41m"
|
||||
BgGreen = "\033[42m"
|
||||
BgYellow = "\033[43m"
|
||||
BgBlue = "\033[44m"
|
||||
BgMagenta = "\033[45m"
|
||||
BgCyan = "\033[46m"
|
||||
Faint = "\033[2m"
|
||||
FaintItalic = "\033[2;3m"
|
||||
Reverse = "\033[7m"
|
||||
)
|
||||
2
vendor/github.com/go-git/go-git/v5/plumbing/filemode/filemode.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/plumbing/filemode/filemode.go
generated
vendored
@@ -118,7 +118,7 @@ func isSetSymLink(m os.FileMode) bool {
|
||||
func (m FileMode) Bytes() []byte {
|
||||
ret := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(ret, uint32(m))
|
||||
return ret[:]
|
||||
return ret
|
||||
}
|
||||
|
||||
// IsMalformed returns if the FileMode should not appear in a git packfile,
|
||||
|
||||
70
vendor/github.com/go-git/go-git/v5/plumbing/format/config/common.go
generated
vendored
70
vendor/github.com/go-git/go-git/v5/plumbing/format/config/common.go
generated
vendored
@@ -44,6 +44,46 @@ func (c *Config) Section(name string) *Section {
|
||||
return s
|
||||
}
|
||||
|
||||
// HasSection checks if the Config has a section with the specified name.
|
||||
func (c *Config) HasSection(name string) bool {
|
||||
for _, s := range c.Sections {
|
||||
if s.IsName(name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RemoveSection removes a section from a config file.
|
||||
func (c *Config) RemoveSection(name string) *Config {
|
||||
result := Sections{}
|
||||
for _, s := range c.Sections {
|
||||
if !s.IsName(name) {
|
||||
result = append(result, s)
|
||||
}
|
||||
}
|
||||
|
||||
c.Sections = result
|
||||
return c
|
||||
}
|
||||
|
||||
// RemoveSubsection remove a subsection from a config file.
|
||||
func (c *Config) RemoveSubsection(section string, subsection string) *Config {
|
||||
for _, s := range c.Sections {
|
||||
if s.IsName(section) {
|
||||
result := Subsections{}
|
||||
for _, ss := range s.Subsections {
|
||||
if !ss.IsName(subsection) {
|
||||
result = append(result, ss)
|
||||
}
|
||||
}
|
||||
s.Subsections = result
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// AddOption adds an option to a given section and subsection. Use the
|
||||
// NoSubsection constant for the subsection argument if no subsection is wanted.
|
||||
func (c *Config) AddOption(section string, subsection string, key string, value string) *Config {
|
||||
@@ -67,33 +107,3 @@ func (c *Config) SetOption(section string, subsection string, key string, value
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// RemoveSection removes a section from a config file.
|
||||
func (c *Config) RemoveSection(name string) *Config {
|
||||
result := Sections{}
|
||||
for _, s := range c.Sections {
|
||||
if !s.IsName(name) {
|
||||
result = append(result, s)
|
||||
}
|
||||
}
|
||||
|
||||
c.Sections = result
|
||||
return c
|
||||
}
|
||||
|
||||
// RemoveSubsection remove s a subsection from a config file.
|
||||
func (c *Config) RemoveSubsection(section string, subsection string) *Config {
|
||||
for _, s := range c.Sections {
|
||||
if s.IsName(section) {
|
||||
result := Subsections{}
|
||||
for _, ss := range s.Subsections {
|
||||
if !ss.IsName(subsection) {
|
||||
result = append(result, ss)
|
||||
}
|
||||
}
|
||||
s.Subsections = result
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
12
vendor/github.com/go-git/go-git/v5/plumbing/format/config/option.go
generated
vendored
12
vendor/github.com/go-git/go-git/v5/plumbing/format/config/option.go
generated
vendored
@@ -19,7 +19,7 @@ type Options []*Option
|
||||
// IsKey returns true if the given key matches
|
||||
// this option's key in a case-insensitive comparison.
|
||||
func (o *Option) IsKey(key string) bool {
|
||||
return strings.ToLower(o.Key) == strings.ToLower(key)
|
||||
return strings.EqualFold(o.Key, key)
|
||||
}
|
||||
|
||||
func (opts Options) GoString() string {
|
||||
@@ -54,6 +54,16 @@ func (opts Options) Get(key string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Has checks if an Option exist with the given key.
|
||||
func (opts Options) Has(key string) bool {
|
||||
for _, o := range opts {
|
||||
if o.IsKey(key) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetAll returns all possible values for the same key.
|
||||
func (opts Options) GetAll(key string) []string {
|
||||
result := []string{}
|
||||
|
||||
87
vendor/github.com/go-git/go-git/v5/plumbing/format/config/section.go
generated
vendored
87
vendor/github.com/go-git/go-git/v5/plumbing/format/config/section.go
generated
vendored
@@ -61,32 +61,7 @@ func (s Subsections) GoString() string {
|
||||
|
||||
// IsName checks if the name provided is equals to the Section name, case insensitive.
|
||||
func (s *Section) IsName(name string) bool {
|
||||
return strings.ToLower(s.Name) == strings.ToLower(name)
|
||||
}
|
||||
|
||||
// Option return the value for the specified key. Empty string is returned if
|
||||
// key does not exists.
|
||||
func (s *Section) Option(key string) string {
|
||||
return s.Options.Get(key)
|
||||
}
|
||||
|
||||
// AddOption adds a new Option to the Section. The updated Section is returned.
|
||||
func (s *Section) AddOption(key string, value string) *Section {
|
||||
s.Options = s.Options.withAddedOption(key, value)
|
||||
return s
|
||||
}
|
||||
|
||||
// SetOption adds a new Option to the Section. If the option already exists, is replaced.
|
||||
// The updated Section is returned.
|
||||
func (s *Section) SetOption(key string, value string) *Section {
|
||||
s.Options = s.Options.withSettedOption(key, value)
|
||||
return s
|
||||
}
|
||||
|
||||
// Remove an option with the specified key. The updated Section is returned.
|
||||
func (s *Section) RemoveOption(key string) *Section {
|
||||
s.Options = s.Options.withoutOption(key)
|
||||
return s
|
||||
return strings.EqualFold(s.Name, name)
|
||||
}
|
||||
|
||||
// Subsection returns a Subsection from the specified Section. If the
|
||||
@@ -115,6 +90,55 @@ func (s *Section) HasSubsection(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// RemoveSubsection removes a subsection from a Section.
|
||||
func (s *Section) RemoveSubsection(name string) *Section {
|
||||
result := Subsections{}
|
||||
for _, s := range s.Subsections {
|
||||
if !s.IsName(name) {
|
||||
result = append(result, s)
|
||||
}
|
||||
}
|
||||
|
||||
s.Subsections = result
|
||||
return s
|
||||
}
|
||||
|
||||
// Option return the value for the specified key. Empty string is returned if
|
||||
// key does not exists.
|
||||
func (s *Section) Option(key string) string {
|
||||
return s.Options.Get(key)
|
||||
}
|
||||
|
||||
// OptionAll returns all possible values for an option with the specified key.
|
||||
// If the option does not exists, an empty slice will be returned.
|
||||
func (s *Section) OptionAll(key string) []string {
|
||||
return s.Options.GetAll(key)
|
||||
}
|
||||
|
||||
// HasOption checks if the Section has an Option with the given key.
|
||||
func (s *Section) HasOption(key string) bool {
|
||||
return s.Options.Has(key)
|
||||
}
|
||||
|
||||
// AddOption adds a new Option to the Section. The updated Section is returned.
|
||||
func (s *Section) AddOption(key string, value string) *Section {
|
||||
s.Options = s.Options.withAddedOption(key, value)
|
||||
return s
|
||||
}
|
||||
|
||||
// SetOption adds a new Option to the Section. If the option already exists, is replaced.
|
||||
// The updated Section is returned.
|
||||
func (s *Section) SetOption(key string, value string) *Section {
|
||||
s.Options = s.Options.withSettedOption(key, value)
|
||||
return s
|
||||
}
|
||||
|
||||
// Remove an option with the specified key. The updated Section is returned.
|
||||
func (s *Section) RemoveOption(key string) *Section {
|
||||
s.Options = s.Options.withoutOption(key)
|
||||
return s
|
||||
}
|
||||
|
||||
// IsName checks if the name of the subsection is exactly the specified name.
|
||||
func (s *Subsection) IsName(name string) bool {
|
||||
return s.Name == name
|
||||
@@ -126,6 +150,17 @@ func (s *Subsection) Option(key string) string {
|
||||
return s.Options.Get(key)
|
||||
}
|
||||
|
||||
// OptionAll returns all possible values for an option with the specified key.
|
||||
// If the option does not exists, an empty slice will be returned.
|
||||
func (s *Subsection) OptionAll(key string) []string {
|
||||
return s.Options.GetAll(key)
|
||||
}
|
||||
|
||||
// HasOption checks if the Subsection has an Option with the given key.
|
||||
func (s *Subsection) HasOption(key string) bool {
|
||||
return s.Options.Has(key)
|
||||
}
|
||||
|
||||
// AddOption adds a new Option to the Subsection. The updated Subsection is returned.
|
||||
func (s *Subsection) AddOption(key string, value string) *Subsection {
|
||||
s.Options = s.Options.withAddedOption(key, value)
|
||||
|
||||
97
vendor/github.com/go-git/go-git/v5/plumbing/format/diff/colorconfig.go
generated
vendored
Normal file
97
vendor/github.com/go-git/go-git/v5/plumbing/format/diff/colorconfig.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
package diff
|
||||
|
||||
import "github.com/go-git/go-git/v5/plumbing/color"
|
||||
|
||||
// A ColorKey is a key into a ColorConfig map and also equal to the key in the
|
||||
// diff.color subsection of the config. See
|
||||
// https://github.com/git/git/blob/v2.26.2/diff.c#L83-L106.
|
||||
type ColorKey string
|
||||
|
||||
// ColorKeys.
|
||||
const (
|
||||
Context ColorKey = "context"
|
||||
Meta ColorKey = "meta"
|
||||
Frag ColorKey = "frag"
|
||||
Old ColorKey = "old"
|
||||
New ColorKey = "new"
|
||||
Commit ColorKey = "commit"
|
||||
Whitespace ColorKey = "whitespace"
|
||||
Func ColorKey = "func"
|
||||
OldMoved ColorKey = "oldMoved"
|
||||
OldMovedAlternative ColorKey = "oldMovedAlternative"
|
||||
OldMovedDimmed ColorKey = "oldMovedDimmed"
|
||||
OldMovedAlternativeDimmed ColorKey = "oldMovedAlternativeDimmed"
|
||||
NewMoved ColorKey = "newMoved"
|
||||
NewMovedAlternative ColorKey = "newMovedAlternative"
|
||||
NewMovedDimmed ColorKey = "newMovedDimmed"
|
||||
NewMovedAlternativeDimmed ColorKey = "newMovedAlternativeDimmed"
|
||||
ContextDimmed ColorKey = "contextDimmed"
|
||||
OldDimmed ColorKey = "oldDimmed"
|
||||
NewDimmed ColorKey = "newDimmed"
|
||||
ContextBold ColorKey = "contextBold"
|
||||
OldBold ColorKey = "oldBold"
|
||||
NewBold ColorKey = "newBold"
|
||||
)
|
||||
|
||||
// A ColorConfig is a color configuration. A nil or empty ColorConfig
|
||||
// corresponds to no color.
|
||||
type ColorConfig map[ColorKey]string
|
||||
|
||||
// A ColorConfigOption sets an option on a ColorConfig.
|
||||
type ColorConfigOption func(ColorConfig)
|
||||
|
||||
// WithColor sets the color for key.
|
||||
func WithColor(key ColorKey, color string) ColorConfigOption {
|
||||
return func(cc ColorConfig) {
|
||||
cc[key] = color
|
||||
}
|
||||
}
|
||||
|
||||
// defaultColorConfig is the default color configuration. See
|
||||
// https://github.com/git/git/blob/v2.26.2/diff.c#L57-L81.
|
||||
var defaultColorConfig = ColorConfig{
|
||||
Context: color.Normal,
|
||||
Meta: color.Bold,
|
||||
Frag: color.Cyan,
|
||||
Old: color.Red,
|
||||
New: color.Green,
|
||||
Commit: color.Yellow,
|
||||
Whitespace: color.BgRed,
|
||||
Func: color.Normal,
|
||||
OldMoved: color.BoldMagenta,
|
||||
OldMovedAlternative: color.BoldBlue,
|
||||
OldMovedDimmed: color.Faint,
|
||||
OldMovedAlternativeDimmed: color.FaintItalic,
|
||||
NewMoved: color.BoldCyan,
|
||||
NewMovedAlternative: color.BoldYellow,
|
||||
NewMovedDimmed: color.Faint,
|
||||
NewMovedAlternativeDimmed: color.FaintItalic,
|
||||
ContextDimmed: color.Faint,
|
||||
OldDimmed: color.FaintRed,
|
||||
NewDimmed: color.FaintGreen,
|
||||
ContextBold: color.Bold,
|
||||
OldBold: color.BoldRed,
|
||||
NewBold: color.BoldGreen,
|
||||
}
|
||||
|
||||
// NewColorConfig returns a new ColorConfig.
|
||||
func NewColorConfig(options ...ColorConfigOption) ColorConfig {
|
||||
cc := make(ColorConfig)
|
||||
for key, value := range defaultColorConfig {
|
||||
cc[key] = value
|
||||
}
|
||||
for _, option := range options {
|
||||
option(cc)
|
||||
}
|
||||
return cc
|
||||
}
|
||||
|
||||
// Reset returns the ANSI escape sequence to reset the color with key set from
|
||||
// cc. If no color was set then no reset is needed so it returns the empty
|
||||
// string.
|
||||
func (cc ColorConfig) Reset(key ColorKey) string {
|
||||
if cc[key] == "" {
|
||||
return ""
|
||||
}
|
||||
return color.Reset
|
||||
}
|
||||
418
vendor/github.com/go-git/go-git/v5/plumbing/format/diff/unified_encoder.go
generated
vendored
418
vendor/github.com/go-git/go-git/v5/plumbing/format/diff/unified_encoder.go
generated
vendored
@@ -1,157 +1,177 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
)
|
||||
|
||||
const (
|
||||
diffInit = "diff --git a/%s b/%s\n"
|
||||
// DefaultContextLines is the default number of context lines.
|
||||
const DefaultContextLines = 3
|
||||
|
||||
chunkStart = "@@ -"
|
||||
chunkMiddle = " +"
|
||||
chunkEnd = " @@%s\n"
|
||||
chunkCount = "%d,%d"
|
||||
var (
|
||||
splitLinesRegexp = regexp.MustCompile(`[^\n]*(\n|$)`)
|
||||
|
||||
noFilePath = "/dev/null"
|
||||
aDir = "a/"
|
||||
bDir = "b/"
|
||||
operationChar = map[Operation]byte{
|
||||
Add: '+',
|
||||
Delete: '-',
|
||||
Equal: ' ',
|
||||
}
|
||||
|
||||
fPath = "--- %s\n"
|
||||
tPath = "+++ %s\n"
|
||||
binary = "Binary files %s and %s differ\n"
|
||||
|
||||
addLine = "+%s%s"
|
||||
deleteLine = "-%s%s"
|
||||
equalLine = " %s%s"
|
||||
noNewLine = "\n\\ No newline at end of file\n"
|
||||
|
||||
oldMode = "old mode %o\n"
|
||||
newMode = "new mode %o\n"
|
||||
deletedFileMode = "deleted file mode %o\n"
|
||||
newFileMode = "new file mode %o\n"
|
||||
|
||||
renameFrom = "from"
|
||||
renameTo = "to"
|
||||
renameFileMode = "rename %s %s\n"
|
||||
|
||||
indexAndMode = "index %s..%s %o\n"
|
||||
indexNoMode = "index %s..%s\n"
|
||||
|
||||
DefaultContextLines = 3
|
||||
operationColorKey = map[Operation]ColorKey{
|
||||
Add: New,
|
||||
Delete: Old,
|
||||
Equal: Context,
|
||||
}
|
||||
)
|
||||
|
||||
// UnifiedEncoder encodes an unified diff into the provided Writer.
|
||||
// There are some unsupported features:
|
||||
// - Similarity index for renames
|
||||
// - Sort hash representation
|
||||
// UnifiedEncoder encodes an unified diff into the provided Writer. It does not
|
||||
// support similarity index for renames or sorting hash representations.
|
||||
type UnifiedEncoder struct {
|
||||
io.Writer
|
||||
|
||||
// ctxLines is the count of unchanged lines that will appear
|
||||
// surrounding a change.
|
||||
ctxLines int
|
||||
// contextLines is the count of unchanged lines that will appear surrounding
|
||||
// a change.
|
||||
contextLines int
|
||||
|
||||
buf bytes.Buffer
|
||||
// srcPrefix and dstPrefix are prepended to file paths when encoding a diff.
|
||||
srcPrefix string
|
||||
dstPrefix string
|
||||
|
||||
// colorConfig is the color configuration. The default is no color.
|
||||
color ColorConfig
|
||||
}
|
||||
|
||||
func NewUnifiedEncoder(w io.Writer, ctxLines int) *UnifiedEncoder {
|
||||
return &UnifiedEncoder{ctxLines: ctxLines, Writer: w}
|
||||
// NewUnifiedEncoder returns a new UnifiedEncoder that writes to w.
|
||||
func NewUnifiedEncoder(w io.Writer, contextLines int) *UnifiedEncoder {
|
||||
return &UnifiedEncoder{
|
||||
Writer: w,
|
||||
srcPrefix: "a/",
|
||||
dstPrefix: "b/",
|
||||
contextLines: contextLines,
|
||||
}
|
||||
}
|
||||
|
||||
// SetColor sets e's color configuration and returns e.
|
||||
func (e *UnifiedEncoder) SetColor(colorConfig ColorConfig) *UnifiedEncoder {
|
||||
e.color = colorConfig
|
||||
return e
|
||||
}
|
||||
|
||||
// SetSrcPrefix sets e's srcPrefix and returns e.
|
||||
func (e *UnifiedEncoder) SetSrcPrefix(prefix string) *UnifiedEncoder {
|
||||
e.srcPrefix = prefix
|
||||
return e
|
||||
}
|
||||
|
||||
// SetDstPrefix sets e's dstPrefix and returns e.
|
||||
func (e *UnifiedEncoder) SetDstPrefix(prefix string) *UnifiedEncoder {
|
||||
e.dstPrefix = prefix
|
||||
return e
|
||||
}
|
||||
|
||||
// Encode encodes patch.
|
||||
func (e *UnifiedEncoder) Encode(patch Patch) error {
|
||||
e.printMessage(patch.Message())
|
||||
sb := &strings.Builder{}
|
||||
|
||||
if err := e.encodeFilePatch(patch.FilePatches()); err != nil {
|
||||
return err
|
||||
if message := patch.Message(); message != "" {
|
||||
sb.WriteString(message)
|
||||
if !strings.HasSuffix(message, "\n") {
|
||||
sb.WriteByte('\n')
|
||||
}
|
||||
}
|
||||
|
||||
_, err := e.buf.WriteTo(e)
|
||||
for _, filePatch := range patch.FilePatches() {
|
||||
e.writeFilePatchHeader(sb, filePatch)
|
||||
g := newHunksGenerator(filePatch.Chunks(), e.contextLines)
|
||||
for _, hunk := range g.Generate() {
|
||||
hunk.writeTo(sb, e.color)
|
||||
}
|
||||
}
|
||||
|
||||
_, err := e.Write([]byte(sb.String()))
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *UnifiedEncoder) encodeFilePatch(filePatches []FilePatch) error {
|
||||
for _, p := range filePatches {
|
||||
f, t := p.Files()
|
||||
if err := e.header(f, t, p.IsBinary()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g := newHunksGenerator(p.Chunks(), e.ctxLines)
|
||||
for _, c := range g.Generate() {
|
||||
c.WriteTo(&e.buf)
|
||||
}
|
||||
func (e *UnifiedEncoder) writeFilePatchHeader(sb *strings.Builder, filePatch FilePatch) {
|
||||
from, to := filePatch.Files()
|
||||
if from == nil && to == nil {
|
||||
return
|
||||
}
|
||||
isBinary := filePatch.IsBinary()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *UnifiedEncoder) printMessage(message string) {
|
||||
isEmpty := message == ""
|
||||
hasSuffix := strings.HasSuffix(message, "\n")
|
||||
if !isEmpty && !hasSuffix {
|
||||
message += "\n"
|
||||
}
|
||||
|
||||
e.buf.WriteString(message)
|
||||
}
|
||||
|
||||
func (e *UnifiedEncoder) header(from, to File, isBinary bool) error {
|
||||
var lines []string
|
||||
switch {
|
||||
case from == nil && to == nil:
|
||||
return nil
|
||||
case from != nil && to != nil:
|
||||
hashEquals := from.Hash() == to.Hash()
|
||||
|
||||
fmt.Fprintf(&e.buf, diffInit, from.Path(), to.Path())
|
||||
|
||||
lines = append(lines,
|
||||
fmt.Sprintf("diff --git %s%s %s%s",
|
||||
e.srcPrefix, from.Path(), e.dstPrefix, to.Path()),
|
||||
)
|
||||
if from.Mode() != to.Mode() {
|
||||
fmt.Fprintf(&e.buf, oldMode+newMode, from.Mode(), to.Mode())
|
||||
lines = append(lines,
|
||||
fmt.Sprintf("old mode %o", from.Mode()),
|
||||
fmt.Sprintf("new mode %o", to.Mode()),
|
||||
)
|
||||
}
|
||||
|
||||
if from.Path() != to.Path() {
|
||||
fmt.Fprintf(&e.buf,
|
||||
renameFileMode+renameFileMode,
|
||||
renameFrom, from.Path(), renameTo, to.Path())
|
||||
lines = append(lines,
|
||||
fmt.Sprintf("rename from %s", from.Path()),
|
||||
fmt.Sprintf("rename to %s", to.Path()),
|
||||
)
|
||||
}
|
||||
|
||||
if from.Mode() != to.Mode() && !hashEquals {
|
||||
fmt.Fprintf(&e.buf, indexNoMode, from.Hash(), to.Hash())
|
||||
lines = append(lines,
|
||||
fmt.Sprintf("index %s..%s", from.Hash(), to.Hash()),
|
||||
)
|
||||
} else if !hashEquals {
|
||||
fmt.Fprintf(&e.buf, indexAndMode, from.Hash(), to.Hash(), from.Mode())
|
||||
lines = append(lines,
|
||||
fmt.Sprintf("index %s..%s %o", from.Hash(), to.Hash(), from.Mode()),
|
||||
)
|
||||
}
|
||||
|
||||
if !hashEquals {
|
||||
e.pathLines(isBinary, aDir+from.Path(), bDir+to.Path())
|
||||
lines = e.appendPathLines(lines, e.srcPrefix+from.Path(), e.dstPrefix+to.Path(), isBinary)
|
||||
}
|
||||
case from == nil:
|
||||
fmt.Fprintf(&e.buf, diffInit, to.Path(), to.Path())
|
||||
fmt.Fprintf(&e.buf, newFileMode, to.Mode())
|
||||
fmt.Fprintf(&e.buf, indexNoMode, plumbing.ZeroHash, to.Hash())
|
||||
e.pathLines(isBinary, noFilePath, bDir+to.Path())
|
||||
lines = append(lines,
|
||||
fmt.Sprintf("diff --git %s %s", e.srcPrefix+to.Path(), e.dstPrefix+to.Path()),
|
||||
fmt.Sprintf("new file mode %o", to.Mode()),
|
||||
fmt.Sprintf("index %s..%s", plumbing.ZeroHash, to.Hash()),
|
||||
)
|
||||
lines = e.appendPathLines(lines, "/dev/null", e.dstPrefix+to.Path(), isBinary)
|
||||
case to == nil:
|
||||
fmt.Fprintf(&e.buf, diffInit, from.Path(), from.Path())
|
||||
fmt.Fprintf(&e.buf, deletedFileMode, from.Mode())
|
||||
fmt.Fprintf(&e.buf, indexNoMode, from.Hash(), plumbing.ZeroHash)
|
||||
e.pathLines(isBinary, aDir+from.Path(), noFilePath)
|
||||
lines = append(lines,
|
||||
fmt.Sprintf("diff --git %s %s", e.srcPrefix+from.Path(), e.dstPrefix+from.Path()),
|
||||
fmt.Sprintf("deleted file mode %o", from.Mode()),
|
||||
fmt.Sprintf("index %s..%s", from.Hash(), plumbing.ZeroHash),
|
||||
)
|
||||
lines = e.appendPathLines(lines, e.srcPrefix+from.Path(), "/dev/null", isBinary)
|
||||
}
|
||||
|
||||
return nil
|
||||
sb.WriteString(e.color[Meta])
|
||||
sb.WriteString(lines[0])
|
||||
for _, line := range lines[1:] {
|
||||
sb.WriteByte('\n')
|
||||
sb.WriteString(line)
|
||||
}
|
||||
sb.WriteString(e.color.Reset(Meta))
|
||||
sb.WriteByte('\n')
|
||||
}
|
||||
|
||||
func (e *UnifiedEncoder) pathLines(isBinary bool, fromPath, toPath string) {
|
||||
format := fPath + tPath
|
||||
func (e *UnifiedEncoder) appendPathLines(lines []string, fromPath, toPath string, isBinary bool) []string {
|
||||
if isBinary {
|
||||
format = binary
|
||||
return append(lines,
|
||||
fmt.Sprintf("Binary files %s and %s differ", fromPath, toPath),
|
||||
)
|
||||
}
|
||||
|
||||
fmt.Fprintf(&e.buf, format, fromPath, toPath)
|
||||
return append(lines,
|
||||
fmt.Sprintf("--- %s", fromPath),
|
||||
fmt.Sprintf("+++ %s", toPath),
|
||||
)
|
||||
}
|
||||
|
||||
type hunksGenerator struct {
|
||||
@@ -170,84 +190,84 @@ func newHunksGenerator(chunks []Chunk, ctxLines int) *hunksGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *hunksGenerator) Generate() []*hunk {
|
||||
for i, chunk := range c.chunks {
|
||||
ls := splitLines(chunk.Content())
|
||||
lsLen := len(ls)
|
||||
func (g *hunksGenerator) Generate() []*hunk {
|
||||
for i, chunk := range g.chunks {
|
||||
lines := splitLines(chunk.Content())
|
||||
nLines := len(lines)
|
||||
|
||||
switch chunk.Type() {
|
||||
case Equal:
|
||||
c.fromLine += lsLen
|
||||
c.toLine += lsLen
|
||||
c.processEqualsLines(ls, i)
|
||||
g.fromLine += nLines
|
||||
g.toLine += nLines
|
||||
g.processEqualsLines(lines, i)
|
||||
case Delete:
|
||||
if lsLen != 0 {
|
||||
c.fromLine++
|
||||
if nLines != 0 {
|
||||
g.fromLine++
|
||||
}
|
||||
|
||||
c.processHunk(i, chunk.Type())
|
||||
c.fromLine += lsLen - 1
|
||||
c.current.AddOp(chunk.Type(), ls...)
|
||||
g.processHunk(i, chunk.Type())
|
||||
g.fromLine += nLines - 1
|
||||
g.current.AddOp(chunk.Type(), lines...)
|
||||
case Add:
|
||||
if lsLen != 0 {
|
||||
c.toLine++
|
||||
if nLines != 0 {
|
||||
g.toLine++
|
||||
}
|
||||
c.processHunk(i, chunk.Type())
|
||||
c.toLine += lsLen - 1
|
||||
c.current.AddOp(chunk.Type(), ls...)
|
||||
g.processHunk(i, chunk.Type())
|
||||
g.toLine += nLines - 1
|
||||
g.current.AddOp(chunk.Type(), lines...)
|
||||
}
|
||||
|
||||
if i == len(c.chunks)-1 && c.current != nil {
|
||||
c.hunks = append(c.hunks, c.current)
|
||||
if i == len(g.chunks)-1 && g.current != nil {
|
||||
g.hunks = append(g.hunks, g.current)
|
||||
}
|
||||
}
|
||||
|
||||
return c.hunks
|
||||
return g.hunks
|
||||
}
|
||||
|
||||
func (c *hunksGenerator) processHunk(i int, op Operation) {
|
||||
if c.current != nil {
|
||||
func (g *hunksGenerator) processHunk(i int, op Operation) {
|
||||
if g.current != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var ctxPrefix string
|
||||
linesBefore := len(c.beforeContext)
|
||||
if linesBefore > c.ctxLines {
|
||||
ctxPrefix = " " + c.beforeContext[linesBefore-c.ctxLines-1]
|
||||
c.beforeContext = c.beforeContext[linesBefore-c.ctxLines:]
|
||||
linesBefore = c.ctxLines
|
||||
linesBefore := len(g.beforeContext)
|
||||
if linesBefore > g.ctxLines {
|
||||
ctxPrefix = g.beforeContext[linesBefore-g.ctxLines-1]
|
||||
g.beforeContext = g.beforeContext[linesBefore-g.ctxLines:]
|
||||
linesBefore = g.ctxLines
|
||||
}
|
||||
|
||||
c.current = &hunk{ctxPrefix: strings.TrimSuffix(ctxPrefix, "\n")}
|
||||
c.current.AddOp(Equal, c.beforeContext...)
|
||||
g.current = &hunk{ctxPrefix: strings.TrimSuffix(ctxPrefix, "\n")}
|
||||
g.current.AddOp(Equal, g.beforeContext...)
|
||||
|
||||
switch op {
|
||||
case Delete:
|
||||
c.current.fromLine, c.current.toLine =
|
||||
c.addLineNumbers(c.fromLine, c.toLine, linesBefore, i, Add)
|
||||
g.current.fromLine, g.current.toLine =
|
||||
g.addLineNumbers(g.fromLine, g.toLine, linesBefore, i, Add)
|
||||
case Add:
|
||||
c.current.toLine, c.current.fromLine =
|
||||
c.addLineNumbers(c.toLine, c.fromLine, linesBefore, i, Delete)
|
||||
g.current.toLine, g.current.fromLine =
|
||||
g.addLineNumbers(g.toLine, g.fromLine, linesBefore, i, Delete)
|
||||
}
|
||||
|
||||
c.beforeContext = nil
|
||||
g.beforeContext = nil
|
||||
}
|
||||
|
||||
// addLineNumbers obtains the line numbers in a new chunk
|
||||
func (c *hunksGenerator) addLineNumbers(la, lb int, linesBefore int, i int, op Operation) (cla, clb int) {
|
||||
// addLineNumbers obtains the line numbers in a new chunk.
|
||||
func (g *hunksGenerator) addLineNumbers(la, lb int, linesBefore int, i int, op Operation) (cla, clb int) {
|
||||
cla = la - linesBefore
|
||||
// we need to search for a reference for the next diff
|
||||
switch {
|
||||
case linesBefore != 0 && c.ctxLines != 0:
|
||||
if lb > c.ctxLines {
|
||||
clb = lb - c.ctxLines + 1
|
||||
case linesBefore != 0 && g.ctxLines != 0:
|
||||
if lb > g.ctxLines {
|
||||
clb = lb - g.ctxLines + 1
|
||||
} else {
|
||||
clb = 1
|
||||
}
|
||||
case c.ctxLines == 0:
|
||||
case g.ctxLines == 0:
|
||||
clb = lb
|
||||
case i != len(c.chunks)-1:
|
||||
next := c.chunks[i+1]
|
||||
case i != len(g.chunks)-1:
|
||||
next := g.chunks[i+1]
|
||||
if next.Type() == op || next.Type() == Equal {
|
||||
// this diff will be into this chunk
|
||||
clb = lb + 1
|
||||
@@ -257,34 +277,32 @@ func (c *hunksGenerator) addLineNumbers(la, lb int, linesBefore int, i int, op O
|
||||
return
|
||||
}
|
||||
|
||||
func (c *hunksGenerator) processEqualsLines(ls []string, i int) {
|
||||
if c.current == nil {
|
||||
c.beforeContext = append(c.beforeContext, ls...)
|
||||
func (g *hunksGenerator) processEqualsLines(ls []string, i int) {
|
||||
if g.current == nil {
|
||||
g.beforeContext = append(g.beforeContext, ls...)
|
||||
return
|
||||
}
|
||||
|
||||
c.afterContext = append(c.afterContext, ls...)
|
||||
if len(c.afterContext) <= c.ctxLines*2 && i != len(c.chunks)-1 {
|
||||
c.current.AddOp(Equal, c.afterContext...)
|
||||
c.afterContext = nil
|
||||
g.afterContext = append(g.afterContext, ls...)
|
||||
if len(g.afterContext) <= g.ctxLines*2 && i != len(g.chunks)-1 {
|
||||
g.current.AddOp(Equal, g.afterContext...)
|
||||
g.afterContext = nil
|
||||
} else {
|
||||
ctxLines := c.ctxLines
|
||||
if ctxLines > len(c.afterContext) {
|
||||
ctxLines = len(c.afterContext)
|
||||
ctxLines := g.ctxLines
|
||||
if ctxLines > len(g.afterContext) {
|
||||
ctxLines = len(g.afterContext)
|
||||
}
|
||||
c.current.AddOp(Equal, c.afterContext[:ctxLines]...)
|
||||
c.hunks = append(c.hunks, c.current)
|
||||
g.current.AddOp(Equal, g.afterContext[:ctxLines]...)
|
||||
g.hunks = append(g.hunks, g.current)
|
||||
|
||||
c.current = nil
|
||||
c.beforeContext = c.afterContext[ctxLines:]
|
||||
c.afterContext = nil
|
||||
g.current = nil
|
||||
g.beforeContext = g.afterContext[ctxLines:]
|
||||
g.afterContext = nil
|
||||
}
|
||||
}
|
||||
|
||||
var splitLinesRE = regexp.MustCompile(`[^\n]*(\n|$)`)
|
||||
|
||||
func splitLines(s string) []string {
|
||||
out := splitLinesRE.FindAllString(s, -1)
|
||||
out := splitLinesRegexp.FindAllString(s, -1)
|
||||
if out[len(out)-1] == "" {
|
||||
out = out[:len(out)-1]
|
||||
}
|
||||
@@ -302,44 +320,59 @@ type hunk struct {
|
||||
ops []*op
|
||||
}
|
||||
|
||||
func (c *hunk) WriteTo(buf *bytes.Buffer) {
|
||||
buf.WriteString(chunkStart)
|
||||
func (h *hunk) writeTo(sb *strings.Builder, color ColorConfig) {
|
||||
sb.WriteString(color[Frag])
|
||||
sb.WriteString("@@ -")
|
||||
|
||||
if c.fromCount == 1 {
|
||||
fmt.Fprintf(buf, "%d", c.fromLine)
|
||||
if h.fromCount == 1 {
|
||||
sb.WriteString(strconv.Itoa(h.fromLine))
|
||||
} else {
|
||||
fmt.Fprintf(buf, chunkCount, c.fromLine, c.fromCount)
|
||||
sb.WriteString(strconv.Itoa(h.fromLine))
|
||||
sb.WriteByte(',')
|
||||
sb.WriteString(strconv.Itoa(h.fromCount))
|
||||
}
|
||||
|
||||
buf.WriteString(chunkMiddle)
|
||||
sb.WriteString(" +")
|
||||
|
||||
if c.toCount == 1 {
|
||||
fmt.Fprintf(buf, "%d", c.toLine)
|
||||
if h.toCount == 1 {
|
||||
sb.WriteString(strconv.Itoa(h.toLine))
|
||||
} else {
|
||||
fmt.Fprintf(buf, chunkCount, c.toLine, c.toCount)
|
||||
sb.WriteString(strconv.Itoa(h.toLine))
|
||||
sb.WriteByte(',')
|
||||
sb.WriteString(strconv.Itoa(h.toCount))
|
||||
}
|
||||
|
||||
fmt.Fprintf(buf, chunkEnd, c.ctxPrefix)
|
||||
sb.WriteString(" @@")
|
||||
sb.WriteString(color.Reset(Frag))
|
||||
|
||||
for _, d := range c.ops {
|
||||
buf.WriteString(d.String())
|
||||
if h.ctxPrefix != "" {
|
||||
sb.WriteByte(' ')
|
||||
sb.WriteString(color[Func])
|
||||
sb.WriteString(h.ctxPrefix)
|
||||
sb.WriteString(color.Reset(Func))
|
||||
}
|
||||
|
||||
sb.WriteByte('\n')
|
||||
|
||||
for _, op := range h.ops {
|
||||
op.writeTo(sb, color)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *hunk) AddOp(t Operation, s ...string) {
|
||||
ls := len(s)
|
||||
func (h *hunk) AddOp(t Operation, ss ...string) {
|
||||
n := len(ss)
|
||||
switch t {
|
||||
case Add:
|
||||
c.toCount += ls
|
||||
h.toCount += n
|
||||
case Delete:
|
||||
c.fromCount += ls
|
||||
h.fromCount += n
|
||||
case Equal:
|
||||
c.toCount += ls
|
||||
c.fromCount += ls
|
||||
h.toCount += n
|
||||
h.fromCount += n
|
||||
}
|
||||
|
||||
for _, l := range s {
|
||||
c.ops = append(c.ops, &op{l, t})
|
||||
for _, s := range ss {
|
||||
h.ops = append(h.ops, &op{s, t})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,20 +381,15 @@ type op struct {
|
||||
t Operation
|
||||
}
|
||||
|
||||
func (o *op) String() string {
|
||||
var prefix, suffix string
|
||||
switch o.t {
|
||||
case Add:
|
||||
prefix = addLine
|
||||
case Delete:
|
||||
prefix = deleteLine
|
||||
case Equal:
|
||||
prefix = equalLine
|
||||
func (o *op) writeTo(sb *strings.Builder, color ColorConfig) {
|
||||
colorKey := operationColorKey[o.t]
|
||||
sb.WriteString(color[colorKey])
|
||||
sb.WriteByte(operationChar[o.t])
|
||||
if strings.HasSuffix(o.text, "\n") {
|
||||
sb.WriteString(strings.TrimSuffix(o.text, "\n"))
|
||||
} else {
|
||||
sb.WriteString(o.text + "\n\\ No newline at end of file")
|
||||
}
|
||||
n := len(o.text)
|
||||
if n > 0 && o.text[n-1] != '\n' {
|
||||
suffix = noNewLine
|
||||
}
|
||||
|
||||
return fmt.Sprintf(prefix, o.text, suffix)
|
||||
sb.WriteString(color.Reset(colorKey))
|
||||
sb.WriteByte('\n')
|
||||
}
|
||||
|
||||
19
vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go
generated
vendored
19
vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go
generated
vendored
@@ -1,10 +1,10 @@
|
||||
package gitignore
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/user"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
const (
|
||||
commentPrefix = "#"
|
||||
coreSection = "core"
|
||||
eol = "\n"
|
||||
excludesfile = "excludesfile"
|
||||
gitDir = ".git"
|
||||
gitignoreFile = ".gitignore"
|
||||
@@ -29,11 +28,11 @@ func readIgnoreFile(fs billy.Filesystem, path []string, ignoreFile string) (ps [
|
||||
if err == nil {
|
||||
defer f.Close()
|
||||
|
||||
if data, err := ioutil.ReadAll(f); err == nil {
|
||||
for _, s := range strings.Split(string(data), eol) {
|
||||
if !strings.HasPrefix(s, commentPrefix) && len(strings.TrimSpace(s)) > 0 {
|
||||
ps = append(ps, ParsePattern(s, path))
|
||||
}
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
s := scanner.Text()
|
||||
if !strings.HasPrefix(s, commentPrefix) && len(strings.TrimSpace(s)) > 0 {
|
||||
ps = append(ps, ParsePattern(s, path))
|
||||
}
|
||||
}
|
||||
} else if !os.IsNotExist(err) {
|
||||
@@ -116,16 +115,16 @@ func loadPatterns(fs billy.Filesystem, path string) (ps []Pattern, err error) {
|
||||
//
|
||||
// The function assumes fs is rooted at the root filesystem.
|
||||
func LoadGlobalPatterns(fs billy.Filesystem) (ps []Pattern, err error) {
|
||||
usr, err := user.Current()
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return loadPatterns(fs, fs.Join(usr.HomeDir, gitconfigFile))
|
||||
return loadPatterns(fs, fs.Join(home, gitconfigFile))
|
||||
}
|
||||
|
||||
// LoadSystemPatterns loads gitignore patterns from from the gitignore file
|
||||
// declared in a system's /etc/gitconfig file. If the ~/.gitconfig file does
|
||||
// declared in a system's /etc/gitconfig file. If the /etc/gitconfig file does
|
||||
// not exist the function will return nil. If the core.excludesfile property
|
||||
// is not declared, the function will return nil. If the file pointed to by
|
||||
// the core.excludesfile property does not exist, the function will return nil.
|
||||
|
||||
6
vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go
generated
vendored
6
vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go
generated
vendored
@@ -188,7 +188,7 @@ func (d *Decoder) doReadEntryNameV4() (string, error) {
|
||||
|
||||
func (d *Decoder) doReadEntryName(len uint16) (string, error) {
|
||||
name := make([]byte, len)
|
||||
_, err := io.ReadFull(d.r, name[:])
|
||||
_, err := io.ReadFull(d.r, name)
|
||||
|
||||
return string(name), err
|
||||
}
|
||||
@@ -390,7 +390,9 @@ func (d *treeExtensionDecoder) readEntry() (*TreeEntry, error) {
|
||||
|
||||
e.Trees = i
|
||||
_, err = io.ReadFull(d.r, e.Hash[:])
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
|
||||
10
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/diff_delta.go
generated
vendored
10
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/diff_delta.go
generated
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
)
|
||||
|
||||
// See https://github.com/jelmer/dulwich/blob/master/dulwich/pack.py and
|
||||
@@ -27,17 +28,20 @@ func GetDelta(base, target plumbing.EncodedObject) (plumbing.EncodedObject, erro
|
||||
return getDelta(new(deltaIndex), base, target)
|
||||
}
|
||||
|
||||
func getDelta(index *deltaIndex, base, target plumbing.EncodedObject) (plumbing.EncodedObject, error) {
|
||||
func getDelta(index *deltaIndex, base, target plumbing.EncodedObject) (o plumbing.EncodedObject, err error) {
|
||||
br, err := base.Reader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer br.Close()
|
||||
|
||||
defer ioutil.CheckClose(br, &err)
|
||||
|
||||
tr, err := target.Reader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tr.Close()
|
||||
|
||||
defer ioutil.CheckClose(tr, &err)
|
||||
|
||||
bb := bufPool.Get().(*bytes.Buffer)
|
||||
defer bufPool.Put(bb)
|
||||
|
||||
10
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/encoder.go
generated
vendored
10
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/encoder.go
generated
vendored
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/storer"
|
||||
"github.com/go-git/go-git/v5/utils/binary"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
)
|
||||
|
||||
// Encoder gets the data from the storage and write it into the writer in PACK
|
||||
@@ -80,7 +81,7 @@ func (e *Encoder) head(numEntries int) error {
|
||||
)
|
||||
}
|
||||
|
||||
func (e *Encoder) entry(o *ObjectToPack) error {
|
||||
func (e *Encoder) entry(o *ObjectToPack) (err error) {
|
||||
if o.WantWrite() {
|
||||
// A cycle exists in this delta chain. This should only occur if a
|
||||
// selected object representation disappeared during writing
|
||||
@@ -119,17 +120,22 @@ func (e *Encoder) entry(o *ObjectToPack) error {
|
||||
}
|
||||
|
||||
e.zw.Reset(e.w)
|
||||
|
||||
defer ioutil.CheckClose(e.zw, &err)
|
||||
|
||||
or, err := o.Object.Reader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(or, &err)
|
||||
|
||||
_, err = io.Copy(e.zw, or)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.zw.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) writeBaseIfDelta(o *ObjectToPack) error {
|
||||
|
||||
5
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/packfile.go
generated
vendored
5
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/packfile.go
generated
vendored
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/go-git/go-git/v5/plumbing/cache"
|
||||
"github.com/go-git/go-git/v5/plumbing/format/idxfile"
|
||||
"github.com/go-git/go-git/v5/plumbing/storer"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -307,12 +308,14 @@ func (p *Packfile) getNextMemoryObject(h *ObjectHeader) (plumbing.EncodedObject,
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (p *Packfile) fillRegularObjectContent(obj plumbing.EncodedObject) error {
|
||||
func (p *Packfile) fillRegularObjectContent(obj plumbing.EncodedObject) (err error) {
|
||||
w, err := obj.Writer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(w, &err)
|
||||
|
||||
_, _, err = p.s.NextObject(w)
|
||||
p.cachePut(obj)
|
||||
|
||||
|
||||
15
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go
generated
vendored
15
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go
generated
vendored
@@ -4,11 +4,12 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
stdioutil "io/ioutil"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/cache"
|
||||
"github.com/go-git/go-git/v5/plumbing/storer"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -283,7 +284,7 @@ func (p *Parser) resolveDeltas() error {
|
||||
|
||||
if !obj.IsDelta() && len(obj.Children) > 0 {
|
||||
for _, child := range obj.Children {
|
||||
if err := p.resolveObject(ioutil.Discard, child, content); err != nil {
|
||||
if err := p.resolveObject(stdioutil.Discard, child, content); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -298,7 +299,7 @@ func (p *Parser) resolveDeltas() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) get(o *objectInfo, buf *bytes.Buffer) error {
|
||||
func (p *Parser) get(o *objectInfo, buf *bytes.Buffer) (err error) {
|
||||
if !o.ExternalRef { // skip cache check for placeholder parents
|
||||
b, ok := p.cache.Get(o.Offset)
|
||||
if ok {
|
||||
@@ -310,17 +311,21 @@ func (p *Parser) get(o *objectInfo, buf *bytes.Buffer) error {
|
||||
// If it's not on the cache and is not a delta we can try to find it in the
|
||||
// storage, if there's one. External refs must enter here.
|
||||
if p.storage != nil && !o.Type.IsDelta() {
|
||||
e, err := p.storage.EncodedObject(plumbing.AnyObject, o.SHA1)
|
||||
var e plumbing.EncodedObject
|
||||
e, err = p.storage.EncodedObject(plumbing.AnyObject, o.SHA1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.Type = e.Type()
|
||||
|
||||
r, err := e.Reader()
|
||||
var r io.ReadCloser
|
||||
r, err = e.Reader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(r, &err)
|
||||
|
||||
_, err = buf.ReadFrom(io.LimitReader(r, e.Size()))
|
||||
return err
|
||||
}
|
||||
|
||||
10
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go
generated
vendored
10
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go
generated
vendored
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
)
|
||||
|
||||
// See https://github.com/git/git/blob/49fa3dc76179e04b0833542fa52d0f287a4955ac/delta.h
|
||||
@@ -16,17 +17,21 @@ import (
|
||||
const deltaSizeMin = 4
|
||||
|
||||
// ApplyDelta writes to target the result of applying the modification deltas in delta to base.
|
||||
func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) error {
|
||||
func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) (err error) {
|
||||
r, err := base.Reader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(r, &err)
|
||||
|
||||
w, err := target.Writer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(w, &err)
|
||||
|
||||
buf := bufPool.Get().(*bytes.Buffer)
|
||||
defer bufPool.Put(buf)
|
||||
buf.Reset()
|
||||
@@ -44,7 +49,6 @@ func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
target.SetSize(int64(dst.Len()))
|
||||
|
||||
b := byteSlicePool.Get().([]byte)
|
||||
@@ -108,7 +112,7 @@ func patchDelta(dst *bytes.Buffer, src, delta []byte) error {
|
||||
invalidOffsetSize(offset, sz, srcSz) {
|
||||
break
|
||||
}
|
||||
dst.Write(src[offset:offset+sz])
|
||||
dst.Write(src[offset : offset+sz])
|
||||
remainingTargetSz -= sz
|
||||
} else if isCopyFromDelta(cmd) {
|
||||
sz := uint(cmd) // cmd is the size itself
|
||||
|
||||
10
vendor/github.com/go-git/go-git/v5/plumbing/hash.go
generated
vendored
10
vendor/github.com/go-git/go-git/v5/plumbing/hash.go
generated
vendored
@@ -71,3 +71,13 @@ type HashSlice []Hash
|
||||
func (p HashSlice) Len() int { return len(p) }
|
||||
func (p HashSlice) Less(i, j int) bool { return bytes.Compare(p[i][:], p[j][:]) < 0 }
|
||||
func (p HashSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
||||
// IsHash returns true if the given string is a valid hash.
|
||||
func IsHash(s string) bool {
|
||||
if len(s) != 40 {
|
||||
return false
|
||||
}
|
||||
|
||||
_, err := hex.DecodeString(s)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
17
vendor/github.com/go-git/go-git/v5/plumbing/memory.go
generated
vendored
17
vendor/github.com/go-git/go-git/v5/plumbing/memory.go
generated
vendored
@@ -3,7 +3,6 @@ package plumbing
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// MemoryObject on memory Object implementation
|
||||
@@ -39,9 +38,11 @@ func (o *MemoryObject) Size() int64 { return o.sz }
|
||||
// afterwards
|
||||
func (o *MemoryObject) SetSize(s int64) { o.sz = s }
|
||||
|
||||
// Reader returns a ObjectReader used to read the object's content.
|
||||
// Reader returns an io.ReadCloser used to read the object's content.
|
||||
//
|
||||
// For a MemoryObject, this reader is seekable.
|
||||
func (o *MemoryObject) Reader() (io.ReadCloser, error) {
|
||||
return ioutil.NopCloser(bytes.NewBuffer(o.cont)), nil
|
||||
return nopCloser{bytes.NewReader(o.cont)}, nil
|
||||
}
|
||||
|
||||
// Writer returns a ObjectWriter used to write the object's content.
|
||||
@@ -59,3 +60,13 @@ func (o *MemoryObject) Write(p []byte) (n int, err error) {
|
||||
// Close releases any resources consumed by the object when it is acting as a
|
||||
// ObjectWriter.
|
||||
func (o *MemoryObject) Close() error { return nil }
|
||||
|
||||
// nopCloser exposes the extra methods of bytes.Reader while nopping Close().
|
||||
//
|
||||
// This allows clients to attempt seeking in a cached Blob's Reader.
|
||||
type nopCloser struct {
|
||||
*bytes.Reader
|
||||
}
|
||||
|
||||
// Close does nothing.
|
||||
func (nc nopCloser) Close() error { return nil }
|
||||
|
||||
6
vendor/github.com/go-git/go-git/v5/plumbing/object/change.go
generated
vendored
6
vendor/github.com/go-git/go-git/v5/plumbing/object/change.go
generated
vendored
@@ -18,7 +18,7 @@ type Change struct {
|
||||
To ChangeEntry
|
||||
}
|
||||
|
||||
var empty = ChangeEntry{}
|
||||
var empty ChangeEntry
|
||||
|
||||
// Action returns the kind of action represented by the change, an
|
||||
// insertion, a deletion or a modification.
|
||||
@@ -27,9 +27,11 @@ func (c *Change) Action() (merkletrie.Action, error) {
|
||||
return merkletrie.Action(0),
|
||||
fmt.Errorf("malformed change: empty from and to")
|
||||
}
|
||||
|
||||
if c.From == empty {
|
||||
return merkletrie.Insert, nil
|
||||
}
|
||||
|
||||
if c.To == empty {
|
||||
return merkletrie.Delete, nil
|
||||
}
|
||||
@@ -73,7 +75,7 @@ func (c *Change) Files() (from, to *File, err error) {
|
||||
func (c *Change) String() string {
|
||||
action, err := c.Action()
|
||||
if err != nil {
|
||||
return fmt.Sprintf("malformed change")
|
||||
return "malformed change"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("<Action: %s, Path: %s>", action, c.name())
|
||||
|
||||
43
vendor/github.com/go-git/go-git/v5/plumbing/object/commit.go
generated
vendored
43
vendor/github.com/go-git/go-git/v5/plumbing/object/commit.go
generated
vendored
@@ -9,7 +9,7 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/storer"
|
||||
@@ -78,21 +78,30 @@ func (c *Commit) Tree() (*Tree, error) {
|
||||
|
||||
// PatchContext returns the Patch between the actual commit and the provided one.
|
||||
// Error will be return if context expires. Provided context must be non-nil.
|
||||
//
|
||||
// NOTE: Since version 5.1.0 the renames are correctly handled, the settings
|
||||
// used are the recommended options DefaultDiffTreeOptions.
|
||||
func (c *Commit) PatchContext(ctx context.Context, to *Commit) (*Patch, error) {
|
||||
fromTree, err := c.Tree()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
toTree, err := to.Tree()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var toTree *Tree
|
||||
if to != nil {
|
||||
toTree, err = to.Tree()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return fromTree.PatchContext(ctx, toTree)
|
||||
}
|
||||
|
||||
// Patch returns the Patch between the actual commit and the provided one.
|
||||
//
|
||||
// NOTE: Since version 5.1.0 the renames are correctly handled, the settings
|
||||
// used are the recommended options DefaultDiffTreeOptions.
|
||||
func (c *Commit) Patch(to *Commit) (*Patch, error) {
|
||||
return c.PatchContext(context.Background(), to)
|
||||
}
|
||||
@@ -234,16 +243,16 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
|
||||
}
|
||||
|
||||
// Encode transforms a Commit into a plumbing.EncodedObject.
|
||||
func (b *Commit) Encode(o plumbing.EncodedObject) error {
|
||||
return b.encode(o, true)
|
||||
func (c *Commit) Encode(o plumbing.EncodedObject) error {
|
||||
return c.encode(o, true)
|
||||
}
|
||||
|
||||
// EncodeWithoutSignature export a Commit into a plumbing.EncodedObject without the signature (correspond to the payload of the PGP signature).
|
||||
func (b *Commit) EncodeWithoutSignature(o plumbing.EncodedObject) error {
|
||||
return b.encode(o, false)
|
||||
func (c *Commit) EncodeWithoutSignature(o plumbing.EncodedObject) error {
|
||||
return c.encode(o, false)
|
||||
}
|
||||
|
||||
func (b *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
|
||||
func (c *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
|
||||
o.SetType(plumbing.CommitObject)
|
||||
w, err := o.Writer()
|
||||
if err != nil {
|
||||
@@ -252,11 +261,11 @@ func (b *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
|
||||
|
||||
defer ioutil.CheckClose(w, &err)
|
||||
|
||||
if _, err = fmt.Fprintf(w, "tree %s\n", b.TreeHash.String()); err != nil {
|
||||
if _, err = fmt.Fprintf(w, "tree %s\n", c.TreeHash.String()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, parent := range b.ParentHashes {
|
||||
for _, parent := range c.ParentHashes {
|
||||
if _, err = fmt.Fprintf(w, "parent %s\n", parent.String()); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -266,7 +275,7 @@ func (b *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = b.Author.Encode(w); err != nil {
|
||||
if err = c.Author.Encode(w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -274,11 +283,11 @@ func (b *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = b.Committer.Encode(w); err != nil {
|
||||
if err = c.Committer.Encode(w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.PGPSignature != "" && includeSig {
|
||||
if c.PGPSignature != "" && includeSig {
|
||||
if _, err = fmt.Fprint(w, "\n"+headerpgp+" "); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -287,14 +296,14 @@ func (b *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
|
||||
// newline. Use join for this so it's clear that a newline should not be
|
||||
// added after this section, as it will be added when the message is
|
||||
// printed.
|
||||
signature := strings.TrimSuffix(b.PGPSignature, "\n")
|
||||
signature := strings.TrimSuffix(c.PGPSignature, "\n")
|
||||
lines := strings.Split(signature, "\n")
|
||||
if _, err = fmt.Fprint(w, strings.Join(lines, "\n ")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = fmt.Fprintf(w, "\n\n%s", b.Message); err != nil {
|
||||
if _, err = fmt.Fprintf(w, "\n\n%s", c.Message); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -365,7 +374,7 @@ func (c *Commit) Verify(armoredKeyRing string) (*openpgp.Entity, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return openpgp.CheckArmoredDetachedSignature(keyring, er, signature)
|
||||
return openpgp.CheckArmoredDetachedSignature(keyring, er, signature, nil)
|
||||
}
|
||||
|
||||
func indent(t string) string {
|
||||
|
||||
1
vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_bfs_filtered.go
generated
vendored
1
vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_bfs_filtered.go
generated
vendored
@@ -173,4 +173,3 @@ func (w *filterCommitIter) addToQueue(
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
3
vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_path.go
generated
vendored
3
vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_path.go
generated
vendored
@@ -4,7 +4,6 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/storer"
|
||||
)
|
||||
|
||||
@@ -29,7 +28,7 @@ func NewCommitPathIterFromIter(pathFilter func(string) bool, commitIter CommitIt
|
||||
return iterator
|
||||
}
|
||||
|
||||
// this function is kept for compatibilty, can be replaced with NewCommitPathIterFromIter
|
||||
// NewCommitFileIterFromIter is kept for compatibility, can be replaced with NewCommitPathIterFromIter
|
||||
func NewCommitFileIterFromIter(fileName string, commitIter CommitIter, checkParent bool) CommitIter {
|
||||
return NewCommitPathIterFromIter(
|
||||
func(path string) bool {
|
||||
|
||||
67
vendor/github.com/go-git/go-git/v5/plumbing/object/difftree.go
generated
vendored
67
vendor/github.com/go-git/go-git/v5/plumbing/object/difftree.go
generated
vendored
@@ -10,14 +10,62 @@ import (
|
||||
|
||||
// DiffTree compares the content and mode of the blobs found via two
|
||||
// tree objects.
|
||||
// DiffTree does not perform rename detection, use DiffTreeWithOptions
|
||||
// instead to detect renames.
|
||||
func DiffTree(a, b *Tree) (Changes, error) {
|
||||
return DiffTreeContext(context.Background(), a, b)
|
||||
}
|
||||
|
||||
// DiffTree compares the content and mode of the blobs found via two
|
||||
// DiffTreeContext compares the content and mode of the blobs found via two
|
||||
// tree objects. Provided context must be non-nil.
|
||||
// An error will be return if context expires
|
||||
// An error will be returned if context expires.
|
||||
func DiffTreeContext(ctx context.Context, a, b *Tree) (Changes, error) {
|
||||
return DiffTreeWithOptions(ctx, a, b, nil)
|
||||
}
|
||||
|
||||
// DiffTreeOptions are the configurable options when performing a diff tree.
|
||||
type DiffTreeOptions struct {
|
||||
// DetectRenames is whether the diff tree will use rename detection.
|
||||
DetectRenames bool
|
||||
// RenameScore is the threshold to of similarity between files to consider
|
||||
// that a pair of delete and insert are a rename. The number must be
|
||||
// exactly between 0 and 100.
|
||||
RenameScore uint
|
||||
// RenameLimit is the maximum amount of files that can be compared when
|
||||
// detecting renames. The number of comparisons that have to be performed
|
||||
// is equal to the number of deleted files * the number of added files.
|
||||
// That means, that if 100 files were deleted and 50 files were added, 5000
|
||||
// file comparisons may be needed. So, if the rename limit is 50, the number
|
||||
// of both deleted and added needs to be equal or less than 50.
|
||||
// A value of 0 means no limit.
|
||||
RenameLimit uint
|
||||
// OnlyExactRenames performs only detection of exact renames and will not perform
|
||||
// any detection of renames based on file similarity.
|
||||
OnlyExactRenames bool
|
||||
}
|
||||
|
||||
// DefaultDiffTreeOptions are the default and recommended options for the
|
||||
// diff tree.
|
||||
var DefaultDiffTreeOptions = &DiffTreeOptions{
|
||||
DetectRenames: true,
|
||||
RenameScore: 60,
|
||||
RenameLimit: 0,
|
||||
OnlyExactRenames: false,
|
||||
}
|
||||
|
||||
// DiffTreeWithOptions compares the content and mode of the blobs found
|
||||
// via two tree objects with the given options. The provided context
|
||||
// must be non-nil.
|
||||
// If no options are passed, no rename detection will be performed. The
|
||||
// recommended options are DefaultDiffTreeOptions.
|
||||
// An error will be returned if the context expires.
|
||||
// This function will be deprecated and removed in v6 so the default
|
||||
// behaviour of DiffTree is to detect renames.
|
||||
func DiffTreeWithOptions(
|
||||
ctx context.Context,
|
||||
a, b *Tree,
|
||||
opts *DiffTreeOptions,
|
||||
) (Changes, error) {
|
||||
from := NewTreeRootNode(a)
|
||||
to := NewTreeRootNode(b)
|
||||
|
||||
@@ -33,5 +81,18 @@ func DiffTreeContext(ctx context.Context, a, b *Tree) (Changes, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newChanges(merkletrieChanges)
|
||||
changes, err := newChanges(merkletrieChanges)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts == nil {
|
||||
opts = new(DiffTreeOptions)
|
||||
}
|
||||
|
||||
if opts.DetectRenames {
|
||||
return DetectRenames(changes, opts)
|
||||
}
|
||||
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
30
vendor/github.com/go-git/go-git/v5/plumbing/object/patch.go
generated
vendored
30
vendor/github.com/go-git/go-git/v5/plumbing/object/patch.go
generated
vendored
@@ -115,18 +115,18 @@ func fileContent(f *File) (content string, isBinary bool, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// textPatch is an implementation of fdiff.Patch interface
|
||||
// Patch is an implementation of fdiff.Patch interface
|
||||
type Patch struct {
|
||||
message string
|
||||
filePatches []fdiff.FilePatch
|
||||
}
|
||||
|
||||
func (t *Patch) FilePatches() []fdiff.FilePatch {
|
||||
return t.filePatches
|
||||
func (p *Patch) FilePatches() []fdiff.FilePatch {
|
||||
return p.filePatches
|
||||
}
|
||||
|
||||
func (t *Patch) Message() string {
|
||||
return t.message
|
||||
func (p *Patch) Message() string {
|
||||
return p.message
|
||||
}
|
||||
|
||||
func (p *Patch) Encode(w io.Writer) error {
|
||||
@@ -198,12 +198,12 @@ func (tf *textFilePatch) Files() (from fdiff.File, to fdiff.File) {
|
||||
return
|
||||
}
|
||||
|
||||
func (t *textFilePatch) IsBinary() bool {
|
||||
return len(t.chunks) == 0
|
||||
func (tf *textFilePatch) IsBinary() bool {
|
||||
return len(tf.chunks) == 0
|
||||
}
|
||||
|
||||
func (t *textFilePatch) Chunks() []fdiff.Chunk {
|
||||
return t.chunks
|
||||
func (tf *textFilePatch) Chunks() []fdiff.Chunk {
|
||||
return tf.chunks
|
||||
}
|
||||
|
||||
// textChunk is an implementation of fdiff.Chunk interface
|
||||
@@ -287,8 +287,16 @@ func printStat(fileStats []FileStat) string {
|
||||
for _, fs := range fileStats {
|
||||
addn := float64(fs.Addition)
|
||||
deln := float64(fs.Deletion)
|
||||
adds := strings.Repeat("+", int(math.Floor(addn/scaleFactor)))
|
||||
dels := strings.Repeat("-", int(math.Floor(deln/scaleFactor)))
|
||||
addc := int(math.Floor(addn/scaleFactor))
|
||||
delc := int(math.Floor(deln/scaleFactor))
|
||||
if addc < 0 {
|
||||
addc = 0
|
||||
}
|
||||
if delc < 0 {
|
||||
delc = 0
|
||||
}
|
||||
adds := strings.Repeat("+", addc)
|
||||
dels := strings.Repeat("-", delc)
|
||||
finalOutput += fmt.Sprintf(" %s | %d %s%s\n", fs.Name, (fs.Addition + fs.Deletion), adds, dels)
|
||||
}
|
||||
|
||||
|
||||
813
vendor/github.com/go-git/go-git/v5/plumbing/object/rename.go
generated
vendored
Normal file
813
vendor/github.com/go-git/go-git/v5/plumbing/object/rename.go
generated
vendored
Normal file
@@ -0,0 +1,813 @@
|
||||
package object
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/filemode"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
"github.com/go-git/go-git/v5/utils/merkletrie"
|
||||
)
|
||||
|
||||
// DetectRenames detects the renames in the given changes on two trees with
|
||||
// the given options. It will return the given changes grouping additions and
|
||||
// deletions into modifications when possible.
|
||||
// If options is nil, the default diff tree options will be used.
|
||||
func DetectRenames(
|
||||
changes Changes,
|
||||
opts *DiffTreeOptions,
|
||||
) (Changes, error) {
|
||||
if opts == nil {
|
||||
opts = DefaultDiffTreeOptions
|
||||
}
|
||||
|
||||
detector := &renameDetector{
|
||||
renameScore: int(opts.RenameScore),
|
||||
renameLimit: int(opts.RenameLimit),
|
||||
onlyExact: opts.OnlyExactRenames,
|
||||
}
|
||||
|
||||
for _, c := range changes {
|
||||
action, err := c.Action()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch action {
|
||||
case merkletrie.Insert:
|
||||
detector.added = append(detector.added, c)
|
||||
case merkletrie.Delete:
|
||||
detector.deleted = append(detector.deleted, c)
|
||||
default:
|
||||
detector.modified = append(detector.modified, c)
|
||||
}
|
||||
}
|
||||
|
||||
return detector.detect()
|
||||
}
|
||||
|
||||
// renameDetector will detect and resolve renames in a set of changes.
|
||||
// see: https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
|
||||
type renameDetector struct {
|
||||
added []*Change
|
||||
deleted []*Change
|
||||
modified []*Change
|
||||
|
||||
renameScore int
|
||||
renameLimit int
|
||||
onlyExact bool
|
||||
}
|
||||
|
||||
// detectExactRenames detects matches files that were deleted with files that
|
||||
// were added where the hash is the same on both. If there are multiple targets
|
||||
// the one with the most similar path will be chosen as the rename and the
|
||||
// rest as either deletions or additions.
|
||||
func (d *renameDetector) detectExactRenames() {
|
||||
added := groupChangesByHash(d.added)
|
||||
deletes := groupChangesByHash(d.deleted)
|
||||
var uniqueAdds []*Change
|
||||
var nonUniqueAdds [][]*Change
|
||||
var addedLeft []*Change
|
||||
|
||||
for _, cs := range added {
|
||||
if len(cs) == 1 {
|
||||
uniqueAdds = append(uniqueAdds, cs[0])
|
||||
} else {
|
||||
nonUniqueAdds = append(nonUniqueAdds, cs)
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range uniqueAdds {
|
||||
hash := changeHash(c)
|
||||
deleted := deletes[hash]
|
||||
|
||||
if len(deleted) == 1 {
|
||||
if sameMode(c, deleted[0]) {
|
||||
d.modified = append(d.modified, &Change{From: deleted[0].From, To: c.To})
|
||||
delete(deletes, hash)
|
||||
} else {
|
||||
addedLeft = append(addedLeft, c)
|
||||
}
|
||||
} else if len(deleted) > 1 {
|
||||
bestMatch := bestNameMatch(c, deleted)
|
||||
if bestMatch != nil && sameMode(c, bestMatch) {
|
||||
d.modified = append(d.modified, &Change{From: bestMatch.From, To: c.To})
|
||||
delete(deletes, hash)
|
||||
|
||||
var newDeletes = make([]*Change, 0, len(deleted)-1)
|
||||
for _, d := range deleted {
|
||||
if d != bestMatch {
|
||||
newDeletes = append(newDeletes, d)
|
||||
}
|
||||
}
|
||||
deletes[hash] = newDeletes
|
||||
}
|
||||
} else {
|
||||
addedLeft = append(addedLeft, c)
|
||||
}
|
||||
}
|
||||
|
||||
for _, added := range nonUniqueAdds {
|
||||
hash := changeHash(added[0])
|
||||
deleted := deletes[hash]
|
||||
|
||||
if len(deleted) == 1 {
|
||||
deleted := deleted[0]
|
||||
bestMatch := bestNameMatch(deleted, added)
|
||||
if bestMatch != nil && sameMode(deleted, bestMatch) {
|
||||
d.modified = append(d.modified, &Change{From: deleted.From, To: bestMatch.To})
|
||||
delete(deletes, hash)
|
||||
|
||||
for _, c := range added {
|
||||
if c != bestMatch {
|
||||
addedLeft = append(addedLeft, c)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addedLeft = append(addedLeft, added...)
|
||||
}
|
||||
} else if len(deleted) > 1 {
|
||||
maxSize := len(deleted) * len(added)
|
||||
if d.renameLimit > 0 && d.renameLimit < maxSize {
|
||||
maxSize = d.renameLimit
|
||||
}
|
||||
|
||||
matrix := make(similarityMatrix, 0, maxSize)
|
||||
|
||||
for delIdx, del := range deleted {
|
||||
deletedName := changeName(del)
|
||||
|
||||
for addIdx, add := range added {
|
||||
addedName := changeName(add)
|
||||
|
||||
score := nameSimilarityScore(addedName, deletedName)
|
||||
matrix = append(matrix, similarityPair{added: addIdx, deleted: delIdx, score: score})
|
||||
|
||||
if len(matrix) >= maxSize {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(matrix) >= maxSize {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
sort.Stable(matrix)
|
||||
|
||||
usedAdds := make(map[*Change]struct{})
|
||||
usedDeletes := make(map[*Change]struct{})
|
||||
for i := len(matrix) - 1; i >= 0; i-- {
|
||||
del := deleted[matrix[i].deleted]
|
||||
add := added[matrix[i].added]
|
||||
|
||||
if add == nil || del == nil {
|
||||
// it was already matched
|
||||
continue
|
||||
}
|
||||
|
||||
usedAdds[add] = struct{}{}
|
||||
usedDeletes[del] = struct{}{}
|
||||
d.modified = append(d.modified, &Change{From: del.From, To: add.To})
|
||||
added[matrix[i].added] = nil
|
||||
deleted[matrix[i].deleted] = nil
|
||||
}
|
||||
|
||||
for _, c := range added {
|
||||
if _, ok := usedAdds[c]; !ok && c != nil {
|
||||
addedLeft = append(addedLeft, c)
|
||||
}
|
||||
}
|
||||
|
||||
var newDeletes = make([]*Change, 0, len(deleted)-len(usedDeletes))
|
||||
for _, c := range deleted {
|
||||
if _, ok := usedDeletes[c]; !ok && c != nil {
|
||||
newDeletes = append(newDeletes, c)
|
||||
}
|
||||
}
|
||||
deletes[hash] = newDeletes
|
||||
} else {
|
||||
addedLeft = append(addedLeft, added...)
|
||||
}
|
||||
}
|
||||
|
||||
d.added = addedLeft
|
||||
d.deleted = nil
|
||||
for _, dels := range deletes {
|
||||
d.deleted = append(d.deleted, dels...)
|
||||
}
|
||||
}
|
||||
|
||||
// detectContentRenames detects renames based on the similarity of the content
|
||||
// in the files by building a matrix of pairs between sources and destinations
|
||||
// and matching by the highest score.
|
||||
// see: https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
|
||||
func (d *renameDetector) detectContentRenames() error {
|
||||
cnt := max(len(d.added), len(d.deleted))
|
||||
if d.renameLimit > 0 && cnt > d.renameLimit {
|
||||
return nil
|
||||
}
|
||||
|
||||
srcs, dsts := d.deleted, d.added
|
||||
matrix, err := buildSimilarityMatrix(srcs, dsts, d.renameScore)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
renames := make([]*Change, 0, min(len(matrix), len(dsts)))
|
||||
|
||||
// Match rename pairs on a first come, first serve basis until
|
||||
// we have looked at everything that is above the minimum score.
|
||||
for i := len(matrix) - 1; i >= 0; i-- {
|
||||
pair := matrix[i]
|
||||
src := srcs[pair.deleted]
|
||||
dst := dsts[pair.added]
|
||||
|
||||
if dst == nil || src == nil {
|
||||
// It was already matched before
|
||||
continue
|
||||
}
|
||||
|
||||
renames = append(renames, &Change{From: src.From, To: dst.To})
|
||||
|
||||
// Claim destination and source as matched
|
||||
dsts[pair.added] = nil
|
||||
srcs[pair.deleted] = nil
|
||||
}
|
||||
|
||||
d.modified = append(d.modified, renames...)
|
||||
d.added = compactChanges(dsts)
|
||||
d.deleted = compactChanges(srcs)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *renameDetector) detect() (Changes, error) {
|
||||
if len(d.added) > 0 && len(d.deleted) > 0 {
|
||||
d.detectExactRenames()
|
||||
|
||||
if !d.onlyExact {
|
||||
if err := d.detectContentRenames(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result := make(Changes, 0, len(d.added)+len(d.deleted)+len(d.modified))
|
||||
result = append(result, d.added...)
|
||||
result = append(result, d.deleted...)
|
||||
result = append(result, d.modified...)
|
||||
|
||||
sort.Stable(result)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func bestNameMatch(change *Change, changes []*Change) *Change {
|
||||
var best *Change
|
||||
var bestScore int
|
||||
|
||||
cname := changeName(change)
|
||||
|
||||
for _, c := range changes {
|
||||
score := nameSimilarityScore(cname, changeName(c))
|
||||
if score > bestScore {
|
||||
bestScore = score
|
||||
best = c
|
||||
}
|
||||
}
|
||||
|
||||
return best
|
||||
}
|
||||
|
||||
func nameSimilarityScore(a, b string) int {
|
||||
aDirLen := strings.LastIndexByte(a, '/') + 1
|
||||
bDirLen := strings.LastIndexByte(b, '/') + 1
|
||||
|
||||
dirMin := min(aDirLen, bDirLen)
|
||||
dirMax := max(aDirLen, bDirLen)
|
||||
|
||||
var dirScoreLtr, dirScoreRtl int
|
||||
if dirMax == 0 {
|
||||
dirScoreLtr = 100
|
||||
dirScoreRtl = 100
|
||||
} else {
|
||||
var dirSim int
|
||||
|
||||
for ; dirSim < dirMin; dirSim++ {
|
||||
if a[dirSim] != b[dirSim] {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
dirScoreLtr = dirSim * 100 / dirMax
|
||||
|
||||
if dirScoreLtr == 100 {
|
||||
dirScoreRtl = 100
|
||||
} else {
|
||||
for dirSim = 0; dirSim < dirMin; dirSim++ {
|
||||
if a[aDirLen-1-dirSim] != b[bDirLen-1-dirSim] {
|
||||
break
|
||||
}
|
||||
}
|
||||
dirScoreRtl = dirSim * 100 / dirMax
|
||||
}
|
||||
}
|
||||
|
||||
fileMin := min(len(a)-aDirLen, len(b)-bDirLen)
|
||||
fileMax := max(len(a)-aDirLen, len(b)-bDirLen)
|
||||
|
||||
fileSim := 0
|
||||
for ; fileSim < fileMin; fileSim++ {
|
||||
if a[len(a)-1-fileSim] != b[len(b)-1-fileSim] {
|
||||
break
|
||||
}
|
||||
}
|
||||
fileScore := fileSim * 100 / fileMax
|
||||
|
||||
return (((dirScoreLtr + dirScoreRtl) * 25) + (fileScore * 50)) / 100
|
||||
}
|
||||
|
||||
func changeName(c *Change) string {
|
||||
if c.To != empty {
|
||||
return c.To.Name
|
||||
}
|
||||
return c.From.Name
|
||||
}
|
||||
|
||||
func changeHash(c *Change) plumbing.Hash {
|
||||
if c.To != empty {
|
||||
return c.To.TreeEntry.Hash
|
||||
}
|
||||
|
||||
return c.From.TreeEntry.Hash
|
||||
}
|
||||
|
||||
func changeMode(c *Change) filemode.FileMode {
|
||||
if c.To != empty {
|
||||
return c.To.TreeEntry.Mode
|
||||
}
|
||||
|
||||
return c.From.TreeEntry.Mode
|
||||
}
|
||||
|
||||
func sameMode(a, b *Change) bool {
|
||||
return changeMode(a) == changeMode(b)
|
||||
}
|
||||
|
||||
func groupChangesByHash(changes []*Change) map[plumbing.Hash][]*Change {
|
||||
var result = make(map[plumbing.Hash][]*Change)
|
||||
for _, c := range changes {
|
||||
hash := changeHash(c)
|
||||
result[hash] = append(result[hash], c)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type similarityMatrix []similarityPair
|
||||
|
||||
func (m similarityMatrix) Len() int { return len(m) }
|
||||
func (m similarityMatrix) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
|
||||
func (m similarityMatrix) Less(i, j int) bool {
|
||||
if m[i].score == m[j].score {
|
||||
if m[i].added == m[j].added {
|
||||
return m[i].deleted < m[j].deleted
|
||||
}
|
||||
return m[i].added < m[j].added
|
||||
}
|
||||
return m[i].score < m[j].score
|
||||
}
|
||||
|
||||
type similarityPair struct {
|
||||
// index of the added file
|
||||
added int
|
||||
// index of the deleted file
|
||||
deleted int
|
||||
// similarity score
|
||||
score int
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func buildSimilarityMatrix(srcs, dsts []*Change, renameScore int) (similarityMatrix, error) {
|
||||
// Allocate for the worst-case scenario where every pair has a score
|
||||
// that we need to consider. We might not need that many.
|
||||
matrix := make(similarityMatrix, 0, len(srcs)*len(dsts))
|
||||
srcSizes := make([]int64, len(srcs))
|
||||
dstSizes := make([]int64, len(dsts))
|
||||
dstTooLarge := make(map[int]bool)
|
||||
|
||||
// Consider each pair of files, if the score is above the minimum
|
||||
// threshold we need to record that scoring in the matrix so we can
|
||||
// later find the best matches.
|
||||
outerLoop:
|
||||
for srcIdx, src := range srcs {
|
||||
if changeMode(src) != filemode.Regular {
|
||||
continue
|
||||
}
|
||||
|
||||
// Declare the from file and the similarity index here to be able to
|
||||
// reuse it inside the inner loop. The reason to not initialize them
|
||||
// here is so we can skip the initialization in case they happen to
|
||||
// not be needed later. They will be initialized inside the inner
|
||||
// loop if and only if they're needed and reused in subsequent passes.
|
||||
var from *File
|
||||
var s *similarityIndex
|
||||
var err error
|
||||
for dstIdx, dst := range dsts {
|
||||
if changeMode(dst) != filemode.Regular {
|
||||
continue
|
||||
}
|
||||
|
||||
if dstTooLarge[dstIdx] {
|
||||
continue
|
||||
}
|
||||
|
||||
var to *File
|
||||
srcSize := srcSizes[srcIdx]
|
||||
if srcSize == 0 {
|
||||
from, _, err = src.Files()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
srcSize = from.Size + 1
|
||||
srcSizes[srcIdx] = srcSize
|
||||
}
|
||||
|
||||
dstSize := dstSizes[dstIdx]
|
||||
if dstSize == 0 {
|
||||
_, to, err = dst.Files()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dstSize = to.Size + 1
|
||||
dstSizes[dstIdx] = dstSize
|
||||
}
|
||||
|
||||
min, max := srcSize, dstSize
|
||||
if dstSize < srcSize {
|
||||
min = dstSize
|
||||
max = srcSize
|
||||
}
|
||||
|
||||
if int(min*100/max) < renameScore {
|
||||
// File sizes are too different to be a match
|
||||
continue
|
||||
}
|
||||
|
||||
if s == nil {
|
||||
s, err = fileSimilarityIndex(from)
|
||||
if err != nil {
|
||||
if err == errIndexFull {
|
||||
continue outerLoop
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if to == nil {
|
||||
_, to, err = dst.Files()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
di, err := fileSimilarityIndex(to)
|
||||
if err != nil {
|
||||
if err == errIndexFull {
|
||||
dstTooLarge[dstIdx] = true
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
contentScore := s.score(di, 10000)
|
||||
// The name score returns a value between 0 and 100, so we need to
|
||||
// convert it to the same range as the content score.
|
||||
nameScore := nameSimilarityScore(src.From.Name, dst.To.Name) * 100
|
||||
score := (contentScore*99 + nameScore*1) / 10000
|
||||
|
||||
if score < renameScore {
|
||||
continue
|
||||
}
|
||||
|
||||
matrix = append(matrix, similarityPair{added: dstIdx, deleted: srcIdx, score: score})
|
||||
}
|
||||
}
|
||||
|
||||
sort.Stable(matrix)
|
||||
|
||||
return matrix, nil
|
||||
}
|
||||
|
||||
func compactChanges(changes []*Change) []*Change {
|
||||
var result []*Change
|
||||
for _, c := range changes {
|
||||
if c != nil {
|
||||
result = append(result, c)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const (
|
||||
keyShift = 32
|
||||
maxCountValue = (1 << keyShift) - 1
|
||||
)
|
||||
|
||||
var errIndexFull = errors.New("index is full")
|
||||
|
||||
// similarityIndex is an index structure of lines/blocks in one file.
|
||||
// This structure can be used to compute an approximation of the similarity
|
||||
// between two files.
|
||||
// To save space in memory, this index uses a space efficient encoding which
|
||||
// will not exceed 1MiB per instance. The index starts out at a smaller size
|
||||
// (closer to 2KiB), but may grow as more distinct blocks within the scanned
|
||||
// file are discovered.
|
||||
// see: https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java
|
||||
type similarityIndex struct {
|
||||
hashed uint64
|
||||
// number of non-zero entries in hashes
|
||||
numHashes int
|
||||
growAt int
|
||||
hashes []keyCountPair
|
||||
hashBits int
|
||||
}
|
||||
|
||||
func fileSimilarityIndex(f *File) (*similarityIndex, error) {
|
||||
idx := newSimilarityIndex()
|
||||
if err := idx.hash(f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sort.Stable(keyCountPairs(idx.hashes))
|
||||
|
||||
return idx, nil
|
||||
}
|
||||
|
||||
func newSimilarityIndex() *similarityIndex {
|
||||
return &similarityIndex{
|
||||
hashBits: 8,
|
||||
hashes: make([]keyCountPair, 1<<8),
|
||||
growAt: shouldGrowAt(8),
|
||||
}
|
||||
}
|
||||
|
||||
func (i *similarityIndex) hash(f *File) error {
|
||||
isBin, err := f.IsBinary()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := f.Reader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(r, &err)
|
||||
|
||||
return i.hashContent(r, f.Size, isBin)
|
||||
}
|
||||
|
||||
func (i *similarityIndex) hashContent(r io.Reader, size int64, isBin bool) error {
|
||||
var buf = make([]byte, 4096)
|
||||
var ptr, cnt int
|
||||
remaining := size
|
||||
|
||||
for 0 < remaining {
|
||||
hash := 5381
|
||||
var blockHashedCnt uint64
|
||||
|
||||
// Hash one line or block, whatever happens first
|
||||
n := int64(0)
|
||||
for {
|
||||
if ptr == cnt {
|
||||
ptr = 0
|
||||
var err error
|
||||
cnt, err = io.ReadFull(r, buf)
|
||||
if err != nil && err != io.ErrUnexpectedEOF {
|
||||
return err
|
||||
}
|
||||
|
||||
if cnt == 0 {
|
||||
return io.EOF
|
||||
}
|
||||
}
|
||||
n++
|
||||
c := buf[ptr] & 0xff
|
||||
ptr++
|
||||
|
||||
// Ignore CR in CRLF sequence if it's text
|
||||
if !isBin && c == '\r' && ptr < cnt && buf[ptr] == '\n' {
|
||||
continue
|
||||
}
|
||||
blockHashedCnt++
|
||||
|
||||
if c == '\n' {
|
||||
break
|
||||
}
|
||||
|
||||
hash = (hash << 5) + hash + int(c)
|
||||
|
||||
if n >= 64 || n >= remaining {
|
||||
break
|
||||
}
|
||||
}
|
||||
i.hashed += blockHashedCnt
|
||||
if err := i.add(hash, blockHashedCnt); err != nil {
|
||||
return err
|
||||
}
|
||||
remaining -= n
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// score computes the similarity score between this index and another one.
|
||||
// A region of a file is defined as a line in a text file or a fixed-size
|
||||
// block in a binary file. To prepare an index, each region in the file is
|
||||
// hashed; the values and counts of hashes are retained in a sorted table.
|
||||
// Define the similarity fraction F as the count of matching regions between
|
||||
// the two files divided between the maximum count of regions in either file.
|
||||
// The similarity score is F multiplied by the maxScore constant, yielding a
|
||||
// range [0, maxScore]. It is defined as maxScore for the degenerate case of
|
||||
// two empty files.
|
||||
// The similarity score is symmetrical; i.e. a.score(b) == b.score(a).
|
||||
func (i *similarityIndex) score(other *similarityIndex, maxScore int) int {
|
||||
var maxHashed = i.hashed
|
||||
if maxHashed < other.hashed {
|
||||
maxHashed = other.hashed
|
||||
}
|
||||
if maxHashed == 0 {
|
||||
return maxScore
|
||||
}
|
||||
|
||||
return int(i.common(other) * uint64(maxScore) / maxHashed)
|
||||
}
|
||||
|
||||
func (i *similarityIndex) common(dst *similarityIndex) uint64 {
|
||||
srcIdx, dstIdx := 0, 0
|
||||
if i.numHashes == 0 || dst.numHashes == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
var common uint64
|
||||
srcKey, dstKey := i.hashes[srcIdx].key(), dst.hashes[dstIdx].key()
|
||||
|
||||
for {
|
||||
if srcKey == dstKey {
|
||||
srcCnt, dstCnt := i.hashes[srcIdx].count(), dst.hashes[dstIdx].count()
|
||||
if srcCnt < dstCnt {
|
||||
common += srcCnt
|
||||
} else {
|
||||
common += dstCnt
|
||||
}
|
||||
|
||||
srcIdx++
|
||||
if srcIdx == len(i.hashes) {
|
||||
break
|
||||
}
|
||||
srcKey = i.hashes[srcIdx].key()
|
||||
|
||||
dstIdx++
|
||||
if dstIdx == len(dst.hashes) {
|
||||
break
|
||||
}
|
||||
dstKey = dst.hashes[dstIdx].key()
|
||||
} else if srcKey < dstKey {
|
||||
// Region of src that is not in dst
|
||||
srcIdx++
|
||||
if srcIdx == len(i.hashes) {
|
||||
break
|
||||
}
|
||||
srcKey = i.hashes[srcIdx].key()
|
||||
} else {
|
||||
// Region of dst that is not in src
|
||||
dstIdx++
|
||||
if dstIdx == len(dst.hashes) {
|
||||
break
|
||||
}
|
||||
dstKey = dst.hashes[dstIdx].key()
|
||||
}
|
||||
}
|
||||
|
||||
return common
|
||||
}
|
||||
|
||||
func (i *similarityIndex) add(key int, cnt uint64) error {
|
||||
key = int(uint32(key) * 0x9e370001 >> 1)
|
||||
|
||||
j := i.slot(key)
|
||||
for {
|
||||
v := i.hashes[j]
|
||||
if v == 0 {
|
||||
// It's an empty slot, so we can store it here.
|
||||
if i.growAt <= i.numHashes {
|
||||
if err := i.grow(); err != nil {
|
||||
return err
|
||||
}
|
||||
j = i.slot(key)
|
||||
continue
|
||||
}
|
||||
|
||||
var err error
|
||||
i.hashes[j], err = newKeyCountPair(key, cnt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.numHashes++
|
||||
return nil
|
||||
} else if v.key() == key {
|
||||
// It's the same key, so increment the counter.
|
||||
var err error
|
||||
i.hashes[j], err = newKeyCountPair(key, v.count()+cnt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
} else if j+1 >= len(i.hashes) {
|
||||
j = 0
|
||||
} else {
|
||||
j++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type keyCountPair uint64
|
||||
|
||||
func newKeyCountPair(key int, cnt uint64) (keyCountPair, error) {
|
||||
if cnt > maxCountValue {
|
||||
return 0, errIndexFull
|
||||
}
|
||||
|
||||
return keyCountPair((uint64(key) << keyShift) | cnt), nil
|
||||
}
|
||||
|
||||
func (p keyCountPair) key() int {
|
||||
return int(p >> keyShift)
|
||||
}
|
||||
|
||||
func (p keyCountPair) count() uint64 {
|
||||
return uint64(p) & maxCountValue
|
||||
}
|
||||
|
||||
func (i *similarityIndex) slot(key int) int {
|
||||
// We use 31 - hashBits because the upper bit was already forced
|
||||
// to be 0 and we want the remaining high bits to be used as the
|
||||
// table slot.
|
||||
return int(uint32(key) >> uint(31-i.hashBits))
|
||||
}
|
||||
|
||||
func shouldGrowAt(hashBits int) int {
|
||||
return (1 << uint(hashBits)) * (hashBits - 3) / hashBits
|
||||
}
|
||||
|
||||
func (i *similarityIndex) grow() error {
|
||||
if i.hashBits == 30 {
|
||||
return errIndexFull
|
||||
}
|
||||
|
||||
old := i.hashes
|
||||
|
||||
i.hashBits++
|
||||
i.growAt = shouldGrowAt(i.hashBits)
|
||||
|
||||
// TODO(erizocosmico): find a way to check if it will OOM and return
|
||||
// errIndexFull instead.
|
||||
i.hashes = make([]keyCountPair, 1<<uint(i.hashBits))
|
||||
|
||||
for _, v := range old {
|
||||
if v != 0 {
|
||||
j := i.slot(v.key())
|
||||
for i.hashes[j] != 0 {
|
||||
j++
|
||||
if j >= len(i.hashes) {
|
||||
j = 0
|
||||
}
|
||||
}
|
||||
i.hashes[j] = v
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type keyCountPairs []keyCountPair
|
||||
|
||||
func (p keyCountPairs) Len() int { return len(p) }
|
||||
func (p keyCountPairs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
func (p keyCountPairs) Less(i, j int) bool { return p[i] < p[j] }
|
||||
4
vendor/github.com/go-git/go-git/v5/plumbing/object/tag.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/plumbing/object/tag.go
generated
vendored
@@ -8,7 +8,7 @@ import (
|
||||
stdioutil "io/ioutil"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/storer"
|
||||
@@ -304,7 +304,7 @@ func (t *Tag) Verify(armoredKeyRing string) (*openpgp.Entity, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return openpgp.CheckArmoredDetachedSignature(keyring, er, signature)
|
||||
return openpgp.CheckArmoredDetachedSignature(keyring, er, signature, nil)
|
||||
}
|
||||
|
||||
// TagIter provides an iterator for a set of tags.
|
||||
|
||||
35
vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go
generated
vendored
35
vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go
generated
vendored
@@ -304,29 +304,34 @@ func (t *Tree) buildMap() {
|
||||
}
|
||||
|
||||
// Diff returns a list of changes between this tree and the provided one
|
||||
func (from *Tree) Diff(to *Tree) (Changes, error) {
|
||||
return DiffTree(from, to)
|
||||
func (t *Tree) Diff(to *Tree) (Changes, error) {
|
||||
return t.DiffContext(context.Background(), to)
|
||||
}
|
||||
|
||||
// Diff returns a list of changes between this tree and the provided one
|
||||
// Error will be returned if context expires
|
||||
// Provided context must be non nil
|
||||
func (from *Tree) DiffContext(ctx context.Context, to *Tree) (Changes, error) {
|
||||
return DiffTreeContext(ctx, from, to)
|
||||
// DiffContext returns a list of changes between this tree and the provided one
|
||||
// Error will be returned if context expires. Provided context must be non nil.
|
||||
//
|
||||
// NOTE: Since version 5.1.0 the renames are correctly handled, the settings
|
||||
// used are the recommended options DefaultDiffTreeOptions.
|
||||
func (t *Tree) DiffContext(ctx context.Context, to *Tree) (Changes, error) {
|
||||
return DiffTreeWithOptions(ctx, t, to, DefaultDiffTreeOptions)
|
||||
}
|
||||
|
||||
// Patch returns a slice of Patch objects with all the changes between trees
|
||||
// in chunks. This representation can be used to create several diff outputs.
|
||||
func (from *Tree) Patch(to *Tree) (*Patch, error) {
|
||||
return from.PatchContext(context.Background(), to)
|
||||
func (t *Tree) Patch(to *Tree) (*Patch, error) {
|
||||
return t.PatchContext(context.Background(), to)
|
||||
}
|
||||
|
||||
// Patch returns a slice of Patch objects with all the changes between trees
|
||||
// in chunks. This representation can be used to create several diff outputs.
|
||||
// If context expires, an error will be returned
|
||||
// Provided context must be non-nil
|
||||
func (from *Tree) PatchContext(ctx context.Context, to *Tree) (*Patch, error) {
|
||||
changes, err := DiffTreeContext(ctx, from, to)
|
||||
// PatchContext returns a slice of Patch objects with all the changes between
|
||||
// trees in chunks. This representation can be used to create several diff
|
||||
// outputs. If context expires, an error will be returned. Provided context must
|
||||
// be non-nil.
|
||||
//
|
||||
// NOTE: Since version 5.1.0 the renames are correctly handled, the settings
|
||||
// used are the recommended options DefaultDiffTreeOptions.
|
||||
func (t *Tree) PatchContext(ctx context.Context, to *Tree) (*Patch, error) {
|
||||
changes, err := t.DiffContext(ctx, to)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
8
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs.go
generated
vendored
8
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs.go
generated
vendored
@@ -201,3 +201,11 @@ func (a *AdvRefs) addSymbolicRefs(s storer.ReferenceStorer) error {
|
||||
func (a *AdvRefs) supportSymrefs() bool {
|
||||
return a.Capabilities.Supports(capability.SymRef)
|
||||
}
|
||||
|
||||
// IsEmpty returns true if doesn't contain any reference.
|
||||
func (a *AdvRefs) IsEmpty() bool {
|
||||
return a.Head == nil &&
|
||||
len(a.References) == 0 &&
|
||||
len(a.Peeled) == 0 &&
|
||||
len(a.Shallows) == 0
|
||||
}
|
||||
|
||||
9
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/capability/capability.go
generated
vendored
9
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/capability/capability.go
generated
vendored
@@ -230,6 +230,12 @@ const (
|
||||
PushCert Capability = "push-cert"
|
||||
// SymRef symbolic reference support for better negotiation.
|
||||
SymRef Capability = "symref"
|
||||
// ObjectFormat takes a hash algorithm as an argument, indicates that the
|
||||
// server supports the given hash algorithms.
|
||||
ObjectFormat Capability = "object-format"
|
||||
// Filter if present, fetch-pack may send "filter" commands to request a
|
||||
// partial clone or partial fetch and request that the server omit various objects from the packfile
|
||||
Filter Capability = "filter"
|
||||
)
|
||||
|
||||
const DefaultAgent = "go-git/4.x"
|
||||
@@ -241,10 +247,11 @@ var known = map[Capability]bool{
|
||||
NoProgress: true, IncludeTag: true, ReportStatus: true, DeleteRefs: true,
|
||||
Quiet: true, Atomic: true, PushOptions: true, AllowTipSHA1InWant: true,
|
||||
AllowReachableSHA1InWant: true, PushCert: true, SymRef: true,
|
||||
ObjectFormat: true, Filter: true,
|
||||
}
|
||||
|
||||
var requiresArgument = map[Capability]bool{
|
||||
Agent: true, PushCert: true, SymRef: true,
|
||||
Agent: true, PushCert: true, SymRef: true, ObjectFormat: true,
|
||||
}
|
||||
|
||||
var multipleArgument = map[Capability]bool{
|
||||
|
||||
5
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/capability/list.go
generated
vendored
5
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/capability/list.go
generated
vendored
@@ -86,10 +86,7 @@ func (l *List) Get(capability Capability) []string {
|
||||
|
||||
// Set sets a capability removing the previous values
|
||||
func (l *List) Set(capability Capability, values ...string) error {
|
||||
if _, ok := l.m[capability]; ok {
|
||||
delete(l.m, capability)
|
||||
}
|
||||
|
||||
delete(l.m, capability)
|
||||
return l.Add(capability, values...)
|
||||
}
|
||||
|
||||
|
||||
32
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go
generated
vendored
32
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go
generated
vendored
@@ -109,42 +109,42 @@ func NewUploadRequestFromCapabilities(adv *capability.List) *UploadRequest {
|
||||
// - is a DepthReference is given capability.DeepenNot MUST be present
|
||||
// - MUST contain only maximum of one of capability.Sideband and capability.Sideband64k
|
||||
// - MUST contain only maximum of one of capability.MultiACK and capability.MultiACKDetailed
|
||||
func (r *UploadRequest) Validate() error {
|
||||
if len(r.Wants) == 0 {
|
||||
func (req *UploadRequest) Validate() error {
|
||||
if len(req.Wants) == 0 {
|
||||
return fmt.Errorf("want can't be empty")
|
||||
}
|
||||
|
||||
if err := r.validateRequiredCapabilities(); err != nil {
|
||||
if err := req.validateRequiredCapabilities(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.validateConflictCapabilities(); err != nil {
|
||||
if err := req.validateConflictCapabilities(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *UploadRequest) validateRequiredCapabilities() error {
|
||||
func (req *UploadRequest) validateRequiredCapabilities() error {
|
||||
msg := "missing capability %s"
|
||||
|
||||
if len(r.Shallows) != 0 && !r.Capabilities.Supports(capability.Shallow) {
|
||||
if len(req.Shallows) != 0 && !req.Capabilities.Supports(capability.Shallow) {
|
||||
return fmt.Errorf(msg, capability.Shallow)
|
||||
}
|
||||
|
||||
switch r.Depth.(type) {
|
||||
switch req.Depth.(type) {
|
||||
case DepthCommits:
|
||||
if r.Depth != DepthCommits(0) {
|
||||
if !r.Capabilities.Supports(capability.Shallow) {
|
||||
if req.Depth != DepthCommits(0) {
|
||||
if !req.Capabilities.Supports(capability.Shallow) {
|
||||
return fmt.Errorf(msg, capability.Shallow)
|
||||
}
|
||||
}
|
||||
case DepthSince:
|
||||
if !r.Capabilities.Supports(capability.DeepenSince) {
|
||||
if !req.Capabilities.Supports(capability.DeepenSince) {
|
||||
return fmt.Errorf(msg, capability.DeepenSince)
|
||||
}
|
||||
case DepthReference:
|
||||
if !r.Capabilities.Supports(capability.DeepenNot) {
|
||||
if !req.Capabilities.Supports(capability.DeepenNot) {
|
||||
return fmt.Errorf(msg, capability.DeepenNot)
|
||||
}
|
||||
}
|
||||
@@ -152,15 +152,15 @@ func (r *UploadRequest) validateRequiredCapabilities() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *UploadRequest) validateConflictCapabilities() error {
|
||||
func (req *UploadRequest) validateConflictCapabilities() error {
|
||||
msg := "capabilities %s and %s are mutually exclusive"
|
||||
if r.Capabilities.Supports(capability.Sideband) &&
|
||||
r.Capabilities.Supports(capability.Sideband64k) {
|
||||
if req.Capabilities.Supports(capability.Sideband) &&
|
||||
req.Capabilities.Supports(capability.Sideband64k) {
|
||||
return fmt.Errorf(msg, capability.Sideband, capability.Sideband64k)
|
||||
}
|
||||
|
||||
if r.Capabilities.Supports(capability.MultiACK) &&
|
||||
r.Capabilities.Supports(capability.MultiACKDetailed) {
|
||||
if req.Capabilities.Supports(capability.MultiACK) &&
|
||||
req.Capabilities.Supports(capability.MultiACKDetailed) {
|
||||
return fmt.Errorf(msg, capability.MultiACK, capability.MultiACKDetailed)
|
||||
}
|
||||
|
||||
|
||||
4
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_decode.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_decode.go
generated
vendored
@@ -14,9 +14,9 @@ import (
|
||||
|
||||
// Decode reads the next upload-request form its input and
|
||||
// stores it in the UploadRequest.
|
||||
func (u *UploadRequest) Decode(r io.Reader) error {
|
||||
func (req *UploadRequest) Decode(r io.Reader) error {
|
||||
d := newUlReqDecoder(r)
|
||||
return d.Decode(u)
|
||||
return d.Decode(req)
|
||||
}
|
||||
|
||||
type ulReqDecoder struct {
|
||||
|
||||
4
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go
generated
vendored
@@ -15,9 +15,9 @@ import (
|
||||
// All the payloads will end with a newline character. Wants and
|
||||
// shallows are sorted alphabetically. A depth of 0 means no depth
|
||||
// request is sent.
|
||||
func (u *UploadRequest) Encode(w io.Writer) error {
|
||||
func (req *UploadRequest) Encode(w io.Writer) error {
|
||||
e := newUlReqEncoder(w)
|
||||
return e.Encode(u)
|
||||
return e.Encode(req)
|
||||
}
|
||||
|
||||
type ulReqEncoder struct {
|
||||
|
||||
6
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq.go
generated
vendored
6
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq.go
generated
vendored
@@ -68,12 +68,12 @@ func NewReferenceUpdateRequestFromCapabilities(adv *capability.List) *ReferenceU
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *ReferenceUpdateRequest) validate() error {
|
||||
if len(r.Commands) == 0 {
|
||||
func (req *ReferenceUpdateRequest) validate() error {
|
||||
if len(req.Commands) == 0 {
|
||||
return ErrEmptyCommands
|
||||
}
|
||||
|
||||
for _, c := range r.Commands {
|
||||
for _, c := range req.Commands {
|
||||
if err := c.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
18
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go
generated
vendored
18
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go
generated
vendored
@@ -14,33 +14,33 @@ var (
|
||||
)
|
||||
|
||||
// Encode writes the ReferenceUpdateRequest encoding to the stream.
|
||||
func (r *ReferenceUpdateRequest) Encode(w io.Writer) error {
|
||||
if err := r.validate(); err != nil {
|
||||
func (req *ReferenceUpdateRequest) Encode(w io.Writer) error {
|
||||
if err := req.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e := pktline.NewEncoder(w)
|
||||
|
||||
if err := r.encodeShallow(e, r.Shallow); err != nil {
|
||||
if err := req.encodeShallow(e, req.Shallow); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.encodeCommands(e, r.Commands, r.Capabilities); err != nil {
|
||||
if err := req.encodeCommands(e, req.Commands, req.Capabilities); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.Packfile != nil {
|
||||
if _, err := io.Copy(w, r.Packfile); err != nil {
|
||||
if req.Packfile != nil {
|
||||
if _, err := io.Copy(w, req.Packfile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return r.Packfile.Close()
|
||||
return req.Packfile.Close()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReferenceUpdateRequest) encodeShallow(e *pktline.Encoder,
|
||||
func (req *ReferenceUpdateRequest) encodeShallow(e *pktline.Encoder,
|
||||
h *plumbing.Hash) error {
|
||||
|
||||
if h == nil {
|
||||
@@ -51,7 +51,7 @@ func (r *ReferenceUpdateRequest) encodeShallow(e *pktline.Encoder,
|
||||
return e.Encodef("%s%s", shallow, objId)
|
||||
}
|
||||
|
||||
func (r *ReferenceUpdateRequest) encodeCommands(e *pktline.Encoder,
|
||||
func (req *ReferenceUpdateRequest) encodeCommands(e *pktline.Encoder,
|
||||
cmds []*Command, cap *capability.List) error {
|
||||
|
||||
if err := e.Encodef("%s\x00%s",
|
||||
|
||||
37
vendor/github.com/go-git/go-git/v5/plumbing/transport/client/client.go
generated
vendored
37
vendor/github.com/go-git/go-git/v5/plumbing/transport/client/client.go
generated
vendored
@@ -3,7 +3,10 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
gohttp "net/http"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/file"
|
||||
@@ -21,6 +24,14 @@ var Protocols = map[string]transport.Transport{
|
||||
"file": file.DefaultClient,
|
||||
}
|
||||
|
||||
var insecureClient = http.NewClient(&gohttp.Client{
|
||||
Transport: &gohttp.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// InstallProtocol adds or modifies an existing protocol.
|
||||
func InstallProtocol(scheme string, c transport.Transport) {
|
||||
if c == nil {
|
||||
@@ -35,6 +46,31 @@ func InstallProtocol(scheme string, c transport.Transport) {
|
||||
// http://, https://, ssh:// and file://.
|
||||
// See `InstallProtocol` to add or modify protocols.
|
||||
func NewClient(endpoint *transport.Endpoint) (transport.Transport, error) {
|
||||
return getTransport(endpoint)
|
||||
}
|
||||
|
||||
func getTransport(endpoint *transport.Endpoint) (transport.Transport, error) {
|
||||
if endpoint.Protocol == "https" {
|
||||
if endpoint.InsecureSkipTLS {
|
||||
return insecureClient, nil
|
||||
}
|
||||
|
||||
if len(endpoint.CaBundle) != 0 {
|
||||
rootCAs, _ := x509.SystemCertPool()
|
||||
if rootCAs == nil {
|
||||
rootCAs = x509.NewCertPool()
|
||||
}
|
||||
rootCAs.AppendCertsFromPEM(endpoint.CaBundle)
|
||||
return http.NewClient(&gohttp.Client{
|
||||
Transport: &gohttp.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: rootCAs,
|
||||
},
|
||||
},
|
||||
}), nil
|
||||
}
|
||||
}
|
||||
|
||||
f, ok := Protocols[endpoint.Protocol]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unsupported scheme %q", endpoint.Protocol)
|
||||
@@ -43,6 +79,5 @@ func NewClient(endpoint *transport.Endpoint) (transport.Transport, error) {
|
||||
if f == nil {
|
||||
return nil, fmt.Errorf("malformed client for scheme %q, client is defined as nil", endpoint.Protocol)
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
9
vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go
generated
vendored
9
vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go
generated
vendored
@@ -58,6 +58,11 @@ type Session interface {
|
||||
// If the repository does not exist, returns ErrRepositoryNotFound.
|
||||
// If the repository exists, but is empty, returns ErrEmptyRemoteRepository.
|
||||
AdvertisedReferences() (*packp.AdvRefs, error)
|
||||
// AdvertisedReferencesContext retrieves the advertised references for a
|
||||
// repository.
|
||||
// If the repository does not exist, returns ErrRepositoryNotFound.
|
||||
// If the repository exists, but is empty, returns ErrEmptyRemoteRepository.
|
||||
AdvertisedReferencesContext(context.Context) (*packp.AdvRefs, error)
|
||||
io.Closer
|
||||
}
|
||||
|
||||
@@ -107,6 +112,10 @@ type Endpoint struct {
|
||||
Port int
|
||||
// Path is the repository path.
|
||||
Path string
|
||||
// InsecureSkipTLS skips ssl verify if protocal is https
|
||||
InsecureSkipTLS bool
|
||||
// CaBundle specify additional ca bundle with system cert pool
|
||||
CaBundle []byte
|
||||
}
|
||||
|
||||
var defaultPorts = map[string]int{
|
||||
|
||||
21
vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go
generated
vendored
21
vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go
generated
vendored
@@ -6,12 +6,13 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
"golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
// DefaultClient is the default local client.
|
||||
@@ -36,7 +37,7 @@ func NewClient(uploadPackBin, receivePackBin string) transport.Transport {
|
||||
|
||||
func prefixExecPath(cmd string) (string, error) {
|
||||
// Use `git --exec-path` to find the exec path.
|
||||
execCmd := exec.Command("git", "--exec-path")
|
||||
execCmd := execabs.Command("git", "--exec-path")
|
||||
|
||||
stdout, err := execCmd.StdoutPipe()
|
||||
if err != nil {
|
||||
@@ -54,7 +55,7 @@ func prefixExecPath(cmd string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
if isPrefix {
|
||||
return "", errors.New("Couldn't read exec-path line all at once")
|
||||
return "", errors.New("couldn't read exec-path line all at once")
|
||||
}
|
||||
|
||||
err = execCmd.Wait()
|
||||
@@ -66,7 +67,7 @@ func prefixExecPath(cmd string) (string, error) {
|
||||
cmd = filepath.Join(execPath, cmd)
|
||||
|
||||
// Make sure it actually exists.
|
||||
_, err = exec.LookPath(cmd)
|
||||
_, err = execabs.LookPath(cmd)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -83,9 +84,9 @@ func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.Auth
|
||||
cmd = r.ReceivePackBin
|
||||
}
|
||||
|
||||
_, err := exec.LookPath(cmd)
|
||||
_, err := execabs.LookPath(cmd)
|
||||
if err != nil {
|
||||
if e, ok := err.(*exec.Error); ok && e.Err == exec.ErrNotFound {
|
||||
if e, ok := err.(*execabs.Error); ok && e.Err == execabs.ErrNotFound {
|
||||
cmd, err = prefixExecPath(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -95,11 +96,11 @@ func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.Auth
|
||||
}
|
||||
}
|
||||
|
||||
return &command{cmd: exec.Command(cmd, ep.Path)}, nil
|
||||
return &command{cmd: execabs.Command(cmd, ep.Path)}, nil
|
||||
}
|
||||
|
||||
type command struct {
|
||||
cmd *exec.Cmd
|
||||
cmd *execabs.Cmd
|
||||
stderrCloser io.Closer
|
||||
closed bool
|
||||
}
|
||||
@@ -111,7 +112,7 @@ func (c *command) Start() error {
|
||||
func (c *command) StderrPipe() (io.Reader, error) {
|
||||
// Pipe returned by Command.StderrPipe has a race with Read + Command.Wait.
|
||||
// We use an io.Pipe and close it after the command finishes.
|
||||
r, w := io.Pipe()
|
||||
r, w := ioutil.Pipe()
|
||||
c.cmd.Stderr = w
|
||||
c.stderrCloser = r
|
||||
return r, nil
|
||||
@@ -148,7 +149,7 @@ func (c *command) Close() error {
|
||||
}
|
||||
|
||||
// When a repository does not exist, the command exits with code 128.
|
||||
if _, ok := err.(*exec.ExitError); ok {
|
||||
if _, ok := err.(*execabs.ExitError); ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
5
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go
generated
vendored
5
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go
generated
vendored
@@ -3,6 +3,7 @@ package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -32,7 +33,7 @@ func applyHeadersToRequest(req *http.Request, content *bytes.Buffer, host string
|
||||
|
||||
const infoRefsPath = "/info/refs"
|
||||
|
||||
func advertisedReferences(s *session, serviceName string) (ref *packp.AdvRefs, err error) {
|
||||
func advertisedReferences(ctx context.Context, s *session, serviceName string) (ref *packp.AdvRefs, err error) {
|
||||
url := fmt.Sprintf(
|
||||
"%s%s?service=%s",
|
||||
s.endpoint.String(), infoRefsPath, serviceName,
|
||||
@@ -45,7 +46,7 @@ func advertisedReferences(s *session, serviceName string) (ref *packp.AdvRefs, e
|
||||
|
||||
s.ApplyAuthToRequest(req)
|
||||
applyHeadersToRequest(req, nil, s.endpoint.Host, serviceName)
|
||||
res, err := s.client.Do(req)
|
||||
res, err := s.client.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
6
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/receive_pack.go
generated
vendored
6
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/receive_pack.go
generated
vendored
@@ -25,7 +25,11 @@ func newReceivePackSession(c *http.Client, ep *transport.Endpoint, auth transpor
|
||||
}
|
||||
|
||||
func (s *rpSession) AdvertisedReferences() (*packp.AdvRefs, error) {
|
||||
return advertisedReferences(s.session, transport.ReceivePackServiceName)
|
||||
return advertisedReferences(context.TODO(), s.session, transport.ReceivePackServiceName)
|
||||
}
|
||||
|
||||
func (s *rpSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) {
|
||||
return advertisedReferences(ctx, s.session, transport.ReceivePackServiceName)
|
||||
}
|
||||
|
||||
func (s *rpSession) ReceivePack(ctx context.Context, req *packp.ReferenceUpdateRequest) (
|
||||
|
||||
6
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/upload_pack.go
generated
vendored
6
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/upload_pack.go
generated
vendored
@@ -25,7 +25,11 @@ func newUploadPackSession(c *http.Client, ep *transport.Endpoint, auth transport
|
||||
}
|
||||
|
||||
func (s *upSession) AdvertisedReferences() (*packp.AdvRefs, error) {
|
||||
return advertisedReferences(s.session, transport.UploadPackServiceName)
|
||||
return advertisedReferences(context.TODO(), s.session, transport.UploadPackServiceName)
|
||||
}
|
||||
|
||||
func (s *upSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) {
|
||||
return advertisedReferences(ctx, s.session, transport.UploadPackServiceName)
|
||||
}
|
||||
|
||||
func (s *upSession) UploadPack(
|
||||
|
||||
19
vendor/github.com/go-git/go-git/v5/plumbing/transport/internal/common/common.go
generated
vendored
19
vendor/github.com/go-git/go-git/v5/plumbing/transport/internal/common/common.go
generated
vendored
@@ -162,19 +162,30 @@ func (c *client) listenFirstError(r io.Reader) chan string {
|
||||
return errLine
|
||||
}
|
||||
|
||||
// AdvertisedReferences retrieves the advertised references from the server.
|
||||
func (s *session) AdvertisedReferences() (*packp.AdvRefs, error) {
|
||||
return s.AdvertisedReferencesContext(context.TODO())
|
||||
}
|
||||
|
||||
// AdvertisedReferences retrieves the advertised references from the server.
|
||||
func (s *session) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) {
|
||||
if s.advRefs != nil {
|
||||
return s.advRefs, nil
|
||||
}
|
||||
|
||||
ar := packp.NewAdvRefs()
|
||||
if err := ar.Decode(s.Stdout); err != nil {
|
||||
if err := ar.Decode(s.StdoutContext(ctx)); err != nil {
|
||||
if err := s.handleAdvRefDecodeError(err); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Some servers like jGit, announce capabilities instead of returning an
|
||||
// packp message with a flush. This verifies that we received a empty
|
||||
// adv-refs, even it contains capabilities.
|
||||
if !s.isReceivePack && ar.IsEmpty() {
|
||||
return nil, transport.ErrEmptyRemoteRepository
|
||||
}
|
||||
|
||||
transport.FilterUnsupportedCapabilities(ar.Capabilities)
|
||||
s.advRefs = ar
|
||||
return ar, nil
|
||||
@@ -222,7 +233,7 @@ func (s *session) handleAdvRefDecodeError(err error) error {
|
||||
// UploadPack performs a request to the server to fetch a packfile. A reader is
|
||||
// returned with the packfile content. The reader must be closed after reading.
|
||||
func (s *session) UploadPack(ctx context.Context, req *packp.UploadPackRequest) (*packp.UploadPackResponse, error) {
|
||||
if req.IsEmpty() {
|
||||
if req.IsEmpty() && len(req.Shallows) == 0 {
|
||||
return nil, transport.ErrEmptyUploadPackRequest
|
||||
}
|
||||
|
||||
@@ -230,7 +241,7 @@ func (s *session) UploadPack(ctx context.Context, req *packp.UploadPackRequest)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := s.AdvertisedReferences(); err != nil {
|
||||
if _, err := s.AdvertisedReferencesContext(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
22
vendor/github.com/go-git/go-git/v5/plumbing/transport/server/server.go
generated
vendored
22
vendor/github.com/go-git/go-git/v5/plumbing/transport/server/server.go
generated
vendored
@@ -108,6 +108,10 @@ type upSession struct {
|
||||
}
|
||||
|
||||
func (s *upSession) AdvertisedReferences() (*packp.AdvRefs, error) {
|
||||
return s.AdvertisedReferencesContext(context.TODO())
|
||||
}
|
||||
|
||||
func (s *upSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) {
|
||||
ar := packp.NewAdvRefs()
|
||||
|
||||
if err := s.setSupportedCapabilities(ar.Capabilities); err != nil {
|
||||
@@ -162,7 +166,7 @@ func (s *upSession) UploadPack(ctx context.Context, req *packp.UploadPackRequest
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pr, pw := io.Pipe()
|
||||
pr, pw := ioutil.Pipe()
|
||||
e := packfile.NewEncoder(pw, s.storer, false)
|
||||
go func() {
|
||||
// TODO: plumb through a pack window.
|
||||
@@ -204,6 +208,10 @@ type rpSession struct {
|
||||
}
|
||||
|
||||
func (s *rpSession) AdvertisedReferences() (*packp.AdvRefs, error) {
|
||||
return s.AdvertisedReferencesContext(context.TODO())
|
||||
}
|
||||
|
||||
func (s *rpSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) {
|
||||
ar := packp.NewAdvRefs()
|
||||
|
||||
if err := s.setSupportedCapabilities(ar.Capabilities); err != nil {
|
||||
@@ -243,11 +251,13 @@ func (s *rpSession) ReceivePack(ctx context.Context, req *packp.ReferenceUpdateR
|
||||
|
||||
//TODO: Implement 'atomic' update of references.
|
||||
|
||||
r := ioutil.NewContextReadCloser(ctx, req.Packfile)
|
||||
if err := s.writePackfile(r); err != nil {
|
||||
s.unpackErr = err
|
||||
s.firstErr = err
|
||||
return s.reportStatus(), err
|
||||
if req.Packfile != nil {
|
||||
r := ioutil.NewContextReadCloser(ctx, req.Packfile)
|
||||
if err := s.writePackfile(r); err != nil {
|
||||
s.unpackErr = err
|
||||
s.firstErr = err
|
||||
return s.reportStatus(), err
|
||||
}
|
||||
}
|
||||
|
||||
s.updateReferences(req)
|
||||
|
||||
24
vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go
generated
vendored
24
vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go
generated
vendored
@@ -1,8 +1,6 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@@ -13,7 +11,7 @@ import (
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/xanzy/ssh-agent"
|
||||
sshagent "github.com/xanzy/ssh-agent"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/knownhosts"
|
||||
)
|
||||
@@ -121,27 +119,15 @@ type PublicKeys struct {
|
||||
// NewPublicKeys returns a PublicKeys from a PEM encoded private key. An
|
||||
// encryption password should be given if the pemBytes contains a password
|
||||
// encrypted PEM block otherwise password should be empty. It supports RSA
|
||||
// (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
|
||||
// (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys.
|
||||
func NewPublicKeys(user string, pemBytes []byte, password string) (*PublicKeys, error) {
|
||||
block, _ := pem.Decode(pemBytes)
|
||||
if block == nil {
|
||||
return nil, errors.New("invalid PEM data")
|
||||
}
|
||||
if x509.IsEncryptedPEMBlock(block) {
|
||||
key, err := x509.DecryptPEMBlock(block, []byte(password))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block = &pem.Block{Type: block.Type, Bytes: key}
|
||||
pemBytes = pem.EncodeToMemory(block)
|
||||
}
|
||||
|
||||
signer, err := ssh.ParsePrivateKey(pemBytes)
|
||||
if _, ok := err.(*ssh.PassphraseMissingError); ok {
|
||||
signer, err = ssh.ParsePrivateKeyWithPassphrase(pemBytes, []byte(password))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &PublicKeys{User: user, Signer: signer}, nil
|
||||
}
|
||||
|
||||
|
||||
9
vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go
generated
vendored
9
vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go
generated
vendored
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
|
||||
@@ -90,8 +91,14 @@ func (c *command) Close() error {
|
||||
//XXX: If did read the full packfile, then the session might be already
|
||||
// closed.
|
||||
_ = c.Session.Close()
|
||||
err := c.client.Close()
|
||||
|
||||
return c.client.Close()
|
||||
//XXX: in go1.16+ we can use errors.Is(err, net.ErrClosed)
|
||||
if err != nil && strings.HasSuffix(err.Error(), "use of closed network connection") {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// connect connects to the SSH server, unless a AuthMethod was set with
|
||||
|
||||
202
vendor/github.com/go-git/go-git/v5/remote.go
generated
vendored
202
vendor/github.com/go-git/go-git/v5/remote.go
generated
vendored
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
@@ -29,8 +30,22 @@ var (
|
||||
NoErrAlreadyUpToDate = errors.New("already up-to-date")
|
||||
ErrDeleteRefNotSupported = errors.New("server does not support delete-refs")
|
||||
ErrForceNeeded = errors.New("some refs were not updated")
|
||||
ErrExactSHA1NotSupported = errors.New("server does not support exact SHA1 refspec")
|
||||
)
|
||||
|
||||
type NoMatchingRefSpecError struct {
|
||||
refSpec config.RefSpec
|
||||
}
|
||||
|
||||
func (e NoMatchingRefSpecError) Error() string {
|
||||
return fmt.Sprintf("couldn't find remote ref %q", e.refSpec.Src())
|
||||
}
|
||||
|
||||
func (e NoMatchingRefSpecError) Is(target error) bool {
|
||||
_, ok := target.(NoMatchingRefSpecError)
|
||||
return ok
|
||||
}
|
||||
|
||||
const (
|
||||
// This describes the maximum number of commits to walk when
|
||||
// computing the haves to send to a server, for each ref in the
|
||||
@@ -77,7 +92,7 @@ func (r *Remote) Push(o *PushOptions) error {
|
||||
// the remote was already up-to-date.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// operation is complete, an error is returned. The context only affects the
|
||||
// transport operations.
|
||||
func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
|
||||
if err := o.Validate(); err != nil {
|
||||
@@ -88,14 +103,14 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
|
||||
return fmt.Errorf("remote names don't match: %s != %s", o.RemoteName, r.c.Name)
|
||||
}
|
||||
|
||||
s, err := newSendPackSession(r.c.URLs[0], o.Auth)
|
||||
s, err := newSendPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(s, &err)
|
||||
|
||||
ar, err := s.AdvertisedReferences()
|
||||
ar, err := s.AdvertisedReferencesContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -105,6 +120,10 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.checkRequireRemoteRefs(o.RequireRemoteRefs, remoteRefs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isDelete := false
|
||||
allDelete := true
|
||||
for _, rs := range o.RefSpecs {
|
||||
@@ -122,6 +141,15 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
|
||||
return ErrDeleteRefNotSupported
|
||||
}
|
||||
|
||||
if o.Force {
|
||||
for i := 0; i < len(o.RefSpecs); i++ {
|
||||
rs := &o.RefSpecs[i]
|
||||
if !rs.IsForceUpdate() && !rs.IsDelete() {
|
||||
o.RefSpecs[i] = config.RefSpec("+" + rs.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
localRefs, err := r.references()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -208,9 +236,9 @@ func (r *Remote) newReferenceUpdateRequest(
|
||||
if o.Progress != nil {
|
||||
req.Progress = o.Progress
|
||||
if ar.Capabilities.Supports(capability.Sideband64k) {
|
||||
req.Capabilities.Set(capability.Sideband64k)
|
||||
_ = req.Capabilities.Set(capability.Sideband64k)
|
||||
} else if ar.Capabilities.Supports(capability.Sideband) {
|
||||
req.Capabilities.Set(capability.Sideband)
|
||||
_ = req.Capabilities.Set(capability.Sideband)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +285,7 @@ func (r *Remote) updateRemoteReferenceStorage(
|
||||
// no changes to be fetched, or an error.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// operation is complete, an error is returned. The context only affects the
|
||||
// transport operations.
|
||||
func (r *Remote) FetchContext(ctx context.Context, o *FetchOptions) error {
|
||||
_, err := r.fetch(ctx, o)
|
||||
@@ -286,14 +314,14 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
|
||||
o.RefSpecs = r.c.Fetch
|
||||
}
|
||||
|
||||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth)
|
||||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(s, &err)
|
||||
|
||||
ar, err := s.AdvertisedReferences()
|
||||
ar, err := s.AdvertisedReferencesContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -303,6 +331,10 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := r.isSupportedRefSpec(o.RefSpecs, ar); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
remoteRefs, err := ar.AllReferences()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -318,6 +350,13 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !req.Depth.IsZero() {
|
||||
req.Shallows, err = r.s.Shallow()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("existing checkout is not shallow")
|
||||
}
|
||||
}
|
||||
|
||||
req.Wants, err = getWants(r.s, refs)
|
||||
if len(req.Wants) > 0 {
|
||||
req.Haves, err = getHaves(localRefs, remoteRefs, r.s)
|
||||
@@ -335,6 +374,13 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !updated {
|
||||
updated, err = depthChanged(req.Shallows, r.s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error checking depth change: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if !updated {
|
||||
return remoteRefs, NoErrAlreadyUpToDate
|
||||
}
|
||||
@@ -342,8 +388,31 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
|
||||
return remoteRefs, nil
|
||||
}
|
||||
|
||||
func newUploadPackSession(url string, auth transport.AuthMethod) (transport.UploadPackSession, error) {
|
||||
c, ep, err := newClient(url)
|
||||
func depthChanged(before []plumbing.Hash, s storage.Storer) (bool, error) {
|
||||
after, err := s.Shallow()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if len(before) != len(after) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
bm := make(map[plumbing.Hash]bool, len(before))
|
||||
for _, b := range before {
|
||||
bm[b] = true
|
||||
}
|
||||
for _, a := range after {
|
||||
if _, ok := bm[a]; !ok {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func newUploadPackSession(url string, auth transport.AuthMethod, insecure bool, cabundle []byte) (transport.UploadPackSession, error) {
|
||||
c, ep, err := newClient(url, auth, insecure, cabundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -351,8 +420,8 @@ func newUploadPackSession(url string, auth transport.AuthMethod) (transport.Uplo
|
||||
return c.NewUploadPackSession(ep, auth)
|
||||
}
|
||||
|
||||
func newSendPackSession(url string, auth transport.AuthMethod) (transport.ReceivePackSession, error) {
|
||||
c, ep, err := newClient(url)
|
||||
func newSendPackSession(url string, auth transport.AuthMethod, insecure bool, cabundle []byte) (transport.ReceivePackSession, error) {
|
||||
c, ep, err := newClient(url, auth, insecure, cabundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -360,11 +429,13 @@ func newSendPackSession(url string, auth transport.AuthMethod) (transport.Receiv
|
||||
return c.NewReceivePackSession(ep, auth)
|
||||
}
|
||||
|
||||
func newClient(url string) (transport.Transport, *transport.Endpoint, error) {
|
||||
func newClient(url string, auth transport.AuthMethod, insecure bool, cabundle []byte) (transport.Transport, *transport.Endpoint, error) {
|
||||
ep, err := transport.NewEndpoint(url)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ep.InsecureSkipTLS = insecure
|
||||
ep.CaBundle = cabundle
|
||||
|
||||
c, err := client.NewClient(ep)
|
||||
if err != nil {
|
||||
@@ -484,10 +555,8 @@ func (r *Remote) deleteReferences(rs config.RefSpec,
|
||||
if _, ok := refsDict[rs.Dst(ref.Name()).String()]; ok {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if rs.Dst("") != ref.Name() {
|
||||
return nil
|
||||
}
|
||||
} else if rs.Dst("") != ref.Name() {
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := &packp.Command{
|
||||
@@ -546,6 +615,7 @@ func (r *Remote) addReferenceIfRefSpecMatches(rs config.RefSpec,
|
||||
|
||||
func (r *Remote) references() ([]*plumbing.Reference, error) {
|
||||
var localRefs []*plumbing.Reference
|
||||
|
||||
iter, err := r.s.IterReferences()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -701,6 +771,11 @@ func doCalculateRefs(
|
||||
return err
|
||||
}
|
||||
|
||||
if s.IsExactSHA1() {
|
||||
ref := plumbing.NewHashReference(s.Dst(""), plumbing.NewHash(s.Src()))
|
||||
return refs.SetReference(ref)
|
||||
}
|
||||
|
||||
var matched bool
|
||||
err = iter.ForEach(func(ref *plumbing.Reference) error {
|
||||
if !s.Match(ref.Name()) {
|
||||
@@ -733,13 +808,18 @@ func doCalculateRefs(
|
||||
})
|
||||
|
||||
if !matched && !s.IsWildcard() {
|
||||
return fmt.Errorf("couldn't find remote ref %q", s.Src())
|
||||
return NoMatchingRefSpecError{refSpec: s}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func getWants(localStorer storage.Storer, refs memory.ReferenceStorage) ([]plumbing.Hash, error) {
|
||||
shallow := false
|
||||
if s, _ := localStorer.Shallow(); len(s) > 0 {
|
||||
shallow = true
|
||||
}
|
||||
|
||||
wants := map[plumbing.Hash]bool{}
|
||||
for _, ref := range refs {
|
||||
hash := ref.Hash()
|
||||
@@ -748,7 +828,7 @@ func getWants(localStorer storage.Storer, refs memory.ReferenceStorage) ([]plumb
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
if !exists || shallow {
|
||||
wants[hash] = true
|
||||
}
|
||||
}
|
||||
@@ -850,6 +930,26 @@ func (r *Remote) newUploadPackRequest(o *FetchOptions,
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (r *Remote) isSupportedRefSpec(refs []config.RefSpec, ar *packp.AdvRefs) error {
|
||||
var containsIsExact bool
|
||||
for _, ref := range refs {
|
||||
if ref.IsExactSHA1() {
|
||||
containsIsExact = true
|
||||
}
|
||||
}
|
||||
|
||||
if !containsIsExact {
|
||||
return nil
|
||||
}
|
||||
|
||||
if ar.Capabilities.Supports(capability.AllowReachableSHA1InWant) ||
|
||||
ar.Capabilities.Supports(capability.AllowTipSHA1InWant) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ErrExactSHA1NotSupported
|
||||
}
|
||||
|
||||
func buildSidebandIfSupported(l *capability.List, reader io.Reader, p sideband.Progress) io.Reader {
|
||||
var t sideband.Type
|
||||
|
||||
@@ -883,7 +983,7 @@ func (r *Remote) updateLocalReferenceStorage(
|
||||
}
|
||||
|
||||
for _, ref := range fetchedRefs {
|
||||
if !spec.Match(ref.Name()) {
|
||||
if !spec.Match(ref.Name()) && !spec.IsExactSHA1() {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -973,15 +1073,32 @@ func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) (updated bool, e
|
||||
}
|
||||
|
||||
// List the references on the remote repository.
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// transport operations.
|
||||
func (r *Remote) ListContext(ctx context.Context, o *ListOptions) (rfs []*plumbing.Reference, err error) {
|
||||
refs, err := r.list(ctx, o)
|
||||
if err != nil {
|
||||
return refs, err
|
||||
}
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
func (r *Remote) List(o *ListOptions) (rfs []*plumbing.Reference, err error) {
|
||||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
return r.ListContext(ctx, o)
|
||||
}
|
||||
|
||||
func (r *Remote) list(ctx context.Context, o *ListOptions) (rfs []*plumbing.Reference, err error) {
|
||||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(s, &err)
|
||||
|
||||
ar, err := s.AdvertisedReferences()
|
||||
ar, err := s.AdvertisedReferencesContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -997,21 +1114,22 @@ func (r *Remote) List(o *ListOptions) (rfs []*plumbing.Reference, err error) {
|
||||
}
|
||||
|
||||
var resultRefs []*plumbing.Reference
|
||||
refs.ForEach(func(ref *plumbing.Reference) error {
|
||||
err = refs.ForEach(func(ref *plumbing.Reference) error {
|
||||
resultRefs = append(resultRefs, ref)
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resultRefs, nil
|
||||
}
|
||||
|
||||
func objectsToPush(commands []*packp.Command) []plumbing.Hash {
|
||||
var objects []plumbing.Hash
|
||||
objects := make([]plumbing.Hash, 0, len(commands))
|
||||
for _, cmd := range commands {
|
||||
if cmd.New == plumbing.ZeroHash {
|
||||
continue
|
||||
}
|
||||
|
||||
objects = append(objects, cmd.New)
|
||||
}
|
||||
return objects
|
||||
@@ -1049,7 +1167,7 @@ func pushHashes(
|
||||
allDelete bool,
|
||||
) (*packp.ReportStatus, error) {
|
||||
|
||||
rd, wr := io.Pipe()
|
||||
rd, wr := ioutil.Pipe()
|
||||
|
||||
config, err := s.Config()
|
||||
if err != nil {
|
||||
@@ -1112,3 +1230,33 @@ outer:
|
||||
|
||||
return r.s.SetShallow(shallows)
|
||||
}
|
||||
|
||||
func (r *Remote) checkRequireRemoteRefs(requires []config.RefSpec, remoteRefs storer.ReferenceStorer) error {
|
||||
for _, require := range requires {
|
||||
if require.IsWildcard() {
|
||||
return fmt.Errorf("wildcards not supported in RequireRemoteRefs, got %s", require.String())
|
||||
}
|
||||
|
||||
name := require.Dst("")
|
||||
remote, err := remoteRefs.Reference(name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("remote ref %s required to be %s but is absent", name.String(), require.Src())
|
||||
}
|
||||
|
||||
var requireHash string
|
||||
if require.IsExactSHA1() {
|
||||
requireHash = require.Src()
|
||||
} else {
|
||||
target, err := storer.ResolveReference(remoteRefs, plumbing.ReferenceName(require.Src()))
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not resolve ref %s in RequireRemoteRefs", require.Src())
|
||||
}
|
||||
requireHash = target.Hash().String()
|
||||
}
|
||||
|
||||
if remote.Hash().String() != requireHash {
|
||||
return fmt.Errorf("remote ref %s required to be %s but is %s", name.String(), requireHash, remote.Hash().String())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
285
vendor/github.com/go-git/go-git/v5/repository.go
generated
vendored
285
vendor/github.com/go-git/go-git/v5/repository.go
generated
vendored
@@ -3,9 +3,9 @@ package git
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
stdioutil "io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
@@ -13,7 +13,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
"github.com/go-git/go-billy/v5/util"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/internal/revision"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
@@ -23,10 +26,9 @@ import (
|
||||
"github.com/go-git/go-git/v5/plumbing/storer"
|
||||
"github.com/go-git/go-git/v5/storage"
|
||||
"github.com/go-git/go-git/v5/storage/filesystem"
|
||||
"github.com/go-git/go-git/v5/storage/filesystem/dotgit"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
"github.com/imdario/mergo"
|
||||
)
|
||||
|
||||
// GitDirName this is a special folder where all the git stuff is.
|
||||
@@ -46,6 +48,7 @@ var (
|
||||
|
||||
ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch")
|
||||
ErrRepositoryNotExists = errors.New("repository does not exist")
|
||||
ErrRepositoryIncomplete = errors.New("repository's commondir path does not exist")
|
||||
ErrRepositoryAlreadyExists = errors.New("repository already exists")
|
||||
ErrRemoteNotFound = errors.New("remote not found")
|
||||
ErrRemoteExists = errors.New("remote already exists")
|
||||
@@ -88,7 +91,7 @@ func Init(s storage.Storer, worktree billy.Filesystem) (*Repository, error) {
|
||||
}
|
||||
|
||||
if worktree == nil {
|
||||
r.setIsBare(true)
|
||||
_ = r.setIsBare(true)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
@@ -155,7 +158,7 @@ func setConfigWorktree(r *Repository, worktree, storage billy.Filesystem) error
|
||||
return nil
|
||||
}
|
||||
|
||||
cfg, err := r.Storer.Config()
|
||||
cfg, err := r.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -185,10 +188,6 @@ func Open(s storage.Storer, worktree billy.Filesystem) (*Repository, error) {
|
||||
// Clone a repository into the given Storer and worktree Filesystem with the
|
||||
// given options, if worktree is nil a bare repository is created. If the given
|
||||
// storer is not empty ErrRepositoryAlreadyExists is returned.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// transport operations.
|
||||
func Clone(s storage.Storer, worktree billy.Filesystem, o *CloneOptions) (*Repository, error) {
|
||||
return CloneContext(context.Background(), s, worktree, o)
|
||||
}
|
||||
@@ -198,7 +197,7 @@ func Clone(s storage.Storer, worktree billy.Filesystem, o *CloneOptions) (*Repos
|
||||
// given storer is not empty ErrRepositoryAlreadyExists is returned.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// operation is complete, an error is returned. The context only affects the
|
||||
// transport operations.
|
||||
func CloneContext(
|
||||
ctx context.Context, s storage.Storer, worktree billy.Filesystem, o *CloneOptions,
|
||||
@@ -252,7 +251,19 @@ func PlainOpenWithOptions(path string, o *PlainOpenOptions) (*Repository, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := filesystem.NewStorage(dot, cache.NewObjectLRUDefault())
|
||||
var repositoryFs billy.Filesystem
|
||||
|
||||
if o.EnableDotGitCommonDir {
|
||||
dotGitCommon, err := dotGitCommonDirectory(dot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repositoryFs = dotgit.NewRepositoryFilesystem(dot, dotGitCommon)
|
||||
} else {
|
||||
repositoryFs = dot
|
||||
}
|
||||
|
||||
s := filesystem.NewStorage(repositoryFs, cache.NewObjectLRUDefault())
|
||||
|
||||
return Open(s, wt)
|
||||
}
|
||||
@@ -261,10 +272,19 @@ func dotGitToOSFilesystems(path string, detect bool) (dot, wt billy.Filesystem,
|
||||
if path, err = filepath.Abs(path); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var fs billy.Filesystem
|
||||
var fi os.FileInfo
|
||||
for {
|
||||
fs = osfs.New(path)
|
||||
|
||||
pathinfo, err := fs.Stat("/")
|
||||
if !os.IsNotExist(err) {
|
||||
if !pathinfo.IsDir() && detect {
|
||||
fs = osfs.New(filepath.Dir(path))
|
||||
}
|
||||
}
|
||||
|
||||
fi, err = fs.Stat(GitDirName)
|
||||
if err == nil {
|
||||
// no error; stop
|
||||
@@ -327,6 +347,38 @@ func dotGitFileToOSFilesystem(path string, fs billy.Filesystem) (bfs billy.Files
|
||||
return osfs.New(fs.Join(path, gitdir)), nil
|
||||
}
|
||||
|
||||
func dotGitCommonDirectory(fs billy.Filesystem) (commonDir billy.Filesystem, err error) {
|
||||
f, err := fs.Open("commondir")
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := stdioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(b) > 0 {
|
||||
path := strings.TrimSpace(string(b))
|
||||
if filepath.IsAbs(path) {
|
||||
commonDir = osfs.New(path)
|
||||
} else {
|
||||
commonDir = osfs.New(filepath.Join(fs.Root(), path))
|
||||
}
|
||||
if _, err := commonDir.Stat(""); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, ErrRepositoryIncomplete
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return commonDir, nil
|
||||
}
|
||||
|
||||
// PlainClone a repository into the path with the given options, isBare defines
|
||||
// if the new repository will be bare or normal. If the path is not empty
|
||||
// ErrRepositoryAlreadyExists is returned.
|
||||
@@ -341,7 +393,7 @@ func PlainClone(path string, isBare bool, o *CloneOptions) (*Repository, error)
|
||||
// ErrRepositoryAlreadyExists is returned.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// operation is complete, an error is returned. The context only affects the
|
||||
// transport operations.
|
||||
//
|
||||
// TODO(mcuadros): move isBare to CloneOptions in v5
|
||||
@@ -360,7 +412,7 @@ func PlainCloneContext(ctx context.Context, path string, isBare bool, o *CloneOp
|
||||
err = r.clone(ctx, o)
|
||||
if err != nil && err != ErrRepositoryAlreadyExists {
|
||||
if cleanup {
|
||||
cleanUpDir(path, cleanupParent)
|
||||
_ = cleanUpDir(path, cleanupParent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,7 +428,7 @@ func newRepository(s storage.Storer, worktree billy.Filesystem) *Repository {
|
||||
}
|
||||
|
||||
func checkIfCleanupIsNeeded(path string) (cleanup bool, cleanParent bool, err error) {
|
||||
fi, err := os.Stat(path)
|
||||
fi, err := osfs.Default.Stat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return true, true, nil
|
||||
@@ -389,44 +441,30 @@ func checkIfCleanupIsNeeded(path string) (cleanup bool, cleanParent bool, err er
|
||||
return false, false, fmt.Errorf("path is not a directory: %s", path)
|
||||
}
|
||||
|
||||
f, err := os.Open(path)
|
||||
files, err := osfs.Default.ReadDir(path)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(f, &err)
|
||||
|
||||
_, err = f.Readdirnames(1)
|
||||
if err == io.EOF {
|
||||
if len(files) == 0 {
|
||||
return true, false, nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
return false, false, nil
|
||||
}
|
||||
|
||||
func cleanUpDir(path string, all bool) error {
|
||||
if all {
|
||||
return os.RemoveAll(path)
|
||||
return util.RemoveAll(osfs.Default, path)
|
||||
}
|
||||
|
||||
f, err := os.Open(path)
|
||||
files, err := osfs.Default.ReadDir(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(f, &err)
|
||||
|
||||
names, err := f.Readdirnames(-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
if err := os.RemoveAll(filepath.Join(path, name)); err != nil {
|
||||
for _, fi := range files {
|
||||
if err := util.RemoveAll(osfs.Default, osfs.Default.Join(path, fi.Name())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -434,14 +472,56 @@ func cleanUpDir(path string, all bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Config return the repository config
|
||||
// Config return the repository config. In a filesystem backed repository this
|
||||
// means read the `.git/config`.
|
||||
func (r *Repository) Config() (*config.Config, error) {
|
||||
return r.Storer.Config()
|
||||
}
|
||||
|
||||
// SetConfig marshall and writes the repository config. In a filesystem backed
|
||||
// repository this means write the `.git/config`. This function should be called
|
||||
// with the result of `Repository.Config` and never with the output of
|
||||
// `Repository.ConfigScoped`.
|
||||
func (r *Repository) SetConfig(cfg *config.Config) error {
|
||||
return r.Storer.SetConfig(cfg)
|
||||
}
|
||||
|
||||
// ConfigScoped returns the repository config, merged with requested scope and
|
||||
// lower. For example if, config.GlobalScope is given the local and global config
|
||||
// are returned merged in one config value.
|
||||
func (r *Repository) ConfigScoped(scope config.Scope) (*config.Config, error) {
|
||||
// TODO(mcuadros): v6, add this as ConfigOptions.Scoped
|
||||
|
||||
var err error
|
||||
system := config.NewConfig()
|
||||
if scope >= config.SystemScope {
|
||||
system, err = config.LoadConfig(config.SystemScope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
global := config.NewConfig()
|
||||
if scope >= config.GlobalScope {
|
||||
global, err = config.LoadConfig(config.GlobalScope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
local, err := r.Storer.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_ = mergo.Merge(global, system)
|
||||
_ = mergo.Merge(local, global)
|
||||
return local, nil
|
||||
}
|
||||
|
||||
// Remote return a remote if exists
|
||||
func (r *Repository) Remote(name string) (*Remote, error) {
|
||||
cfg, err := r.Storer.Config()
|
||||
cfg, err := r.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -456,7 +536,7 @@ func (r *Repository) Remote(name string) (*Remote, error) {
|
||||
|
||||
// Remotes returns a list with all the remotes
|
||||
func (r *Repository) Remotes() ([]*Remote, error) {
|
||||
cfg, err := r.Storer.Config()
|
||||
cfg, err := r.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -480,7 +560,7 @@ func (r *Repository) CreateRemote(c *config.RemoteConfig) (*Remote, error) {
|
||||
|
||||
remote := NewRemote(r.Storer, c)
|
||||
|
||||
cfg, err := r.Storer.Config()
|
||||
cfg, err := r.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -511,7 +591,7 @@ func (r *Repository) CreateRemoteAnonymous(c *config.RemoteConfig) (*Remote, err
|
||||
|
||||
// DeleteRemote delete a remote from the repository and delete the config
|
||||
func (r *Repository) DeleteRemote(name string) error {
|
||||
cfg, err := r.Storer.Config()
|
||||
cfg, err := r.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -526,7 +606,7 @@ func (r *Repository) DeleteRemote(name string) error {
|
||||
|
||||
// Branch return a Branch if exists
|
||||
func (r *Repository) Branch(name string) (*config.Branch, error) {
|
||||
cfg, err := r.Storer.Config()
|
||||
cfg, err := r.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -545,7 +625,7 @@ func (r *Repository) CreateBranch(c *config.Branch) error {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg, err := r.Storer.Config()
|
||||
cfg, err := r.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -560,7 +640,7 @@ func (r *Repository) CreateBranch(c *config.Branch) error {
|
||||
|
||||
// DeleteBranch delete a Branch from the repository and delete the config
|
||||
func (r *Repository) DeleteBranch(name string) error {
|
||||
cfg, err := r.Storer.Config()
|
||||
cfg, err := r.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -742,12 +822,14 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
|
||||
}
|
||||
|
||||
ref, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{
|
||||
RefSpecs: c.Fetch,
|
||||
Depth: o.Depth,
|
||||
Auth: o.Auth,
|
||||
Progress: o.Progress,
|
||||
Tags: o.Tags,
|
||||
RemoteName: o.RemoteName,
|
||||
RefSpecs: c.Fetch,
|
||||
Depth: o.Depth,
|
||||
Auth: o.Auth,
|
||||
Progress: o.Progress,
|
||||
Tags: o.Tags,
|
||||
RemoteName: o.RemoteName,
|
||||
InsecureSkipTLS: o.InsecureSkipTLS,
|
||||
CABundle: o.CABundle,
|
||||
}, o.ReferenceName)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -793,11 +875,13 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
|
||||
Name: branchName,
|
||||
Merge: branchRef,
|
||||
}
|
||||
|
||||
if o.RemoteName == "" {
|
||||
b.Remote = "origin"
|
||||
} else {
|
||||
b.Remote = o.RemoteName
|
||||
}
|
||||
|
||||
if err := r.CreateBranch(b); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -835,7 +919,7 @@ func (r *Repository) cloneRefSpec(o *CloneOptions) []config.RefSpec {
|
||||
}
|
||||
|
||||
func (r *Repository) setIsBare(isBare bool) error {
|
||||
cfg, err := r.Storer.Config()
|
||||
cfg, err := r.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -851,7 +935,7 @@ func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.Remot
|
||||
|
||||
c.Fetch = r.cloneRefSpec(o)
|
||||
|
||||
cfg, err := r.Storer.Config()
|
||||
cfg, err := r.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1000,7 +1084,7 @@ func (r *Repository) Fetch(o *FetchOptions) error {
|
||||
// no changes to be fetched, or an error.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// operation is complete, an error is returned. The context only affects the
|
||||
// transport operations.
|
||||
func (r *Repository) FetchContext(ctx context.Context, o *FetchOptions) error {
|
||||
if err := o.Validate(); err != nil {
|
||||
@@ -1027,7 +1111,7 @@ func (r *Repository) Push(o *PushOptions) error {
|
||||
// FetchOptions.RemoteName.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// operation is complete, an error is returned. The context only affects the
|
||||
// transport operations.
|
||||
func (r *Repository) PushContext(ctx context.Context, o *PushOptions) error {
|
||||
if err := o.Validate(); err != nil {
|
||||
@@ -1336,7 +1420,7 @@ func (r *Repository) Worktree() (*Worktree, error) {
|
||||
// resolve to a commit hash, not a tree or annotated tag.
|
||||
//
|
||||
// Implemented resolvers : HEAD, branch, tag, heads/branch, refs/heads/branch,
|
||||
// refs/tags/tag, refs/remotes/origin/branch, refs/remotes/origin/HEAD, tilde and caret (HEAD~1, master~^, tag~2, ref/heads/master~1, ...), selection by text (HEAD^{/fix nasty bug})
|
||||
// refs/tags/tag, refs/remotes/origin/branch, refs/remotes/origin/HEAD, tilde and caret (HEAD~1, master~^, tag~2, ref/heads/master~1, ...), selection by text (HEAD^{/fix nasty bug}), hash (prefix and full)
|
||||
func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, error) {
|
||||
p := revision.NewParserFromString(string(rev))
|
||||
|
||||
@@ -1349,17 +1433,13 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
|
||||
var commit *object.Commit
|
||||
|
||||
for _, item := range items {
|
||||
switch item.(type) {
|
||||
switch item := item.(type) {
|
||||
case revision.Ref:
|
||||
revisionRef := item.(revision.Ref)
|
||||
revisionRef := item
|
||||
|
||||
var tryHashes []plumbing.Hash
|
||||
|
||||
maybeHash := plumbing.NewHash(string(revisionRef))
|
||||
|
||||
if !maybeHash.IsZero() {
|
||||
tryHashes = append(tryHashes, maybeHash)
|
||||
}
|
||||
tryHashes = append(tryHashes, r.resolveHashPrefix(string(revisionRef))...)
|
||||
|
||||
for _, rule := range append([]string{"%s"}, plumbing.RefRevParseRules...) {
|
||||
ref, err := storer.ResolveReference(r.Storer, plumbing.ReferenceName(fmt.Sprintf(rule, revisionRef)))
|
||||
@@ -1404,7 +1484,7 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
|
||||
}
|
||||
|
||||
case revision.CaretPath:
|
||||
depth := item.(revision.CaretPath).Depth
|
||||
depth := item.Depth
|
||||
|
||||
if depth == 0 {
|
||||
break
|
||||
@@ -1432,7 +1512,7 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
|
||||
|
||||
commit = c
|
||||
case revision.TildePath:
|
||||
for i := 0; i < item.(revision.TildePath).Depth; i++ {
|
||||
for i := 0; i < item.Depth; i++ {
|
||||
c, err := commit.Parents().Next()
|
||||
|
||||
if err != nil {
|
||||
@@ -1444,8 +1524,8 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
|
||||
case revision.CaretReg:
|
||||
history := object.NewCommitPreorderIter(commit, nil, nil)
|
||||
|
||||
re := item.(revision.CaretReg).Regexp
|
||||
negate := item.(revision.CaretReg).Negate
|
||||
re := item.Regexp
|
||||
negate := item.Negate
|
||||
|
||||
var c *object.Commit
|
||||
|
||||
@@ -1477,6 +1557,49 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
|
||||
return &commit.Hash, nil
|
||||
}
|
||||
|
||||
// resolveHashPrefix returns a list of potential hashes that the given string
|
||||
// is a prefix of. It quietly swallows errors, returning nil.
|
||||
func (r *Repository) resolveHashPrefix(hashStr string) []plumbing.Hash {
|
||||
// Handle complete and partial hashes.
|
||||
// plumbing.NewHash forces args into a full 20 byte hash, which isn't suitable
|
||||
// for partial hashes since they will become zero-filled.
|
||||
|
||||
if hashStr == "" {
|
||||
return nil
|
||||
}
|
||||
if len(hashStr) == len(plumbing.ZeroHash)*2 {
|
||||
// Only a full hash is possible.
|
||||
hexb, err := hex.DecodeString(hashStr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var h plumbing.Hash
|
||||
copy(h[:], hexb)
|
||||
return []plumbing.Hash{h}
|
||||
}
|
||||
|
||||
// Partial hash.
|
||||
// hex.DecodeString only decodes to complete bytes, so only works with pairs of hex digits.
|
||||
evenHex := hashStr[:len(hashStr)&^1]
|
||||
hexb, err := hex.DecodeString(evenHex)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
candidates := expandPartialHash(r.Storer, hexb)
|
||||
if len(evenHex) == len(hashStr) {
|
||||
// The prefix was an exact number of bytes.
|
||||
return candidates
|
||||
}
|
||||
// Do another prefix check to ensure the dangling nybble is correct.
|
||||
var hashes []plumbing.Hash
|
||||
for _, h := range candidates {
|
||||
if strings.HasPrefix(h.String(), hashStr) {
|
||||
hashes = append(hashes, h)
|
||||
}
|
||||
}
|
||||
return hashes
|
||||
}
|
||||
|
||||
type RepackConfig struct {
|
||||
// UseRefDeltas configures whether packfile encoder will use reference deltas.
|
||||
// By default OFSDeltaObject is used.
|
||||
@@ -1541,7 +1664,7 @@ func (r *Repository) createNewObjectPack(cfg *RepackConfig) (h plumbing.Hash, er
|
||||
return h, err
|
||||
}
|
||||
defer ioutil.CheckClose(wc, &err)
|
||||
scfg, err := r.Storer.Config()
|
||||
scfg, err := r.Config()
|
||||
if err != nil {
|
||||
return h, err
|
||||
}
|
||||
@@ -1569,3 +1692,31 @@ func (r *Repository) createNewObjectPack(cfg *RepackConfig) (h plumbing.Hash, er
|
||||
|
||||
return h, err
|
||||
}
|
||||
|
||||
func expandPartialHash(st storer.EncodedObjectStorer, prefix []byte) (hashes []plumbing.Hash) {
|
||||
// The fast version is implemented by storage/filesystem.ObjectStorage.
|
||||
type fastIter interface {
|
||||
HashesWithPrefix(prefix []byte) ([]plumbing.Hash, error)
|
||||
}
|
||||
if fi, ok := st.(fastIter); ok {
|
||||
h, err := fi.HashesWithPrefix(prefix)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
// Slow path.
|
||||
iter, err := st.IterEncodedObjects(plumbing.AnyObject)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
iter.ForEach(func(obj plumbing.EncodedObject) error {
|
||||
h := obj.Hash()
|
||||
if bytes.HasPrefix(h[:], prefix) {
|
||||
hashes = append(hashes, h)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
17
vendor/github.com/go-git/go-git/v5/storage/filesystem/config.go
generated
vendored
17
vendor/github.com/go-git/go-git/v5/storage/filesystem/config.go
generated
vendored
@@ -1,7 +1,6 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
stdioutil "io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
@@ -14,29 +13,17 @@ type ConfigStorage struct {
|
||||
}
|
||||
|
||||
func (c *ConfigStorage) Config() (conf *config.Config, err error) {
|
||||
cfg := config.NewConfig()
|
||||
|
||||
f, err := c.dir.Config()
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return cfg, nil
|
||||
return config.NewConfig(), nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(f, &err)
|
||||
|
||||
b, err := stdioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = cfg.Unmarshal(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cfg, err
|
||||
return config.ReadConfig(f)
|
||||
}
|
||||
|
||||
func (c *ConfigStorage) SetConfig(cfg *config.Config) (err error) {
|
||||
|
||||
94
vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go
generated
vendored
94
vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go
generated
vendored
@@ -3,12 +3,14 @@ package dotgit
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
stdioutil "io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -30,6 +32,12 @@ const (
|
||||
objectsPath = "objects"
|
||||
packPath = "pack"
|
||||
refsPath = "refs"
|
||||
branchesPath = "branches"
|
||||
hooksPath = "hooks"
|
||||
infoPath = "info"
|
||||
remotesPath = "remotes"
|
||||
logsPath = "logs"
|
||||
worktreesPath = "worktrees"
|
||||
|
||||
tmpPackedRefsPrefix = "._packed-refs"
|
||||
|
||||
@@ -57,6 +65,9 @@ var (
|
||||
// targeting a non-existing object. This usually means the repository
|
||||
// is corrupt.
|
||||
ErrSymRefTargetNotFound = errors.New("symbolic reference target not found")
|
||||
// ErrIsDir is returned when a reference file is attempting to be read,
|
||||
// but the path specified is a directory.
|
||||
ErrIsDir = errors.New("reference path is a directory")
|
||||
)
|
||||
|
||||
// Options holds configuration for the storage.
|
||||
@@ -79,7 +90,7 @@ type DotGit struct {
|
||||
incomingChecked bool
|
||||
incomingDirName string
|
||||
|
||||
objectList []plumbing.Hash
|
||||
objectList []plumbing.Hash // sorted
|
||||
objectMap map[plumbing.Hash]struct{}
|
||||
packList []plumbing.Hash
|
||||
packMap map[plumbing.Hash]struct{}
|
||||
@@ -327,6 +338,53 @@ func (d *DotGit) NewObject() (*ObjectWriter, error) {
|
||||
return newObjectWriter(d.fs)
|
||||
}
|
||||
|
||||
// ObjectsWithPrefix returns the hashes of objects that have the given prefix.
|
||||
func (d *DotGit) ObjectsWithPrefix(prefix []byte) ([]plumbing.Hash, error) {
|
||||
// Handle edge cases.
|
||||
if len(prefix) < 1 {
|
||||
return d.Objects()
|
||||
} else if len(prefix) > len(plumbing.ZeroHash) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if d.options.ExclusiveAccess {
|
||||
err := d.genObjectList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Rely on d.objectList being sorted.
|
||||
// Figure out the half-open interval defined by the prefix.
|
||||
first := sort.Search(len(d.objectList), func(i int) bool {
|
||||
// Same as plumbing.HashSlice.Less.
|
||||
return bytes.Compare(d.objectList[i][:], prefix) >= 0
|
||||
})
|
||||
lim := len(d.objectList)
|
||||
if limPrefix, overflow := incBytes(prefix); !overflow {
|
||||
lim = sort.Search(len(d.objectList), func(i int) bool {
|
||||
// Same as plumbing.HashSlice.Less.
|
||||
return bytes.Compare(d.objectList[i][:], limPrefix) >= 0
|
||||
})
|
||||
}
|
||||
return d.objectList[first:lim], nil
|
||||
}
|
||||
|
||||
// This is the slow path.
|
||||
var objects []plumbing.Hash
|
||||
var n int
|
||||
err := d.ForEachObjectHash(func(hash plumbing.Hash) error {
|
||||
n++
|
||||
if bytes.HasPrefix(hash[:], prefix) {
|
||||
objects = append(objects, hash)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return objects, nil
|
||||
}
|
||||
|
||||
// Objects returns a slice with the hashes of objects found under the
|
||||
// .git/objects/ directory.
|
||||
func (d *DotGit) Objects() ([]plumbing.Hash, error) {
|
||||
@@ -418,12 +476,17 @@ func (d *DotGit) genObjectList() error {
|
||||
}
|
||||
|
||||
d.objectMap = make(map[plumbing.Hash]struct{})
|
||||
return d.forEachObjectHash(func(h plumbing.Hash) error {
|
||||
populate := func(h plumbing.Hash) error {
|
||||
d.objectList = append(d.objectList, h)
|
||||
d.objectMap[h] = struct{}{}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := d.forEachObjectHash(populate); err != nil {
|
||||
return err
|
||||
}
|
||||
plumbing.HashesSort(d.objectList)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DotGit) hasObject(h plumbing.Hash) error {
|
||||
@@ -926,6 +989,14 @@ func (d *DotGit) addRefFromHEAD(refs *[]*plumbing.Reference) error {
|
||||
|
||||
func (d *DotGit) readReferenceFile(path, name string) (ref *plumbing.Reference, err error) {
|
||||
path = d.fs.Join(path, d.fs.Join(strings.Split(name, "/")...))
|
||||
st, err := d.fs.Stat(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if st.IsDir() {
|
||||
return nil, ErrIsDir
|
||||
}
|
||||
|
||||
f, err := d.fs.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1098,3 +1169,20 @@ func isNum(b byte) bool {
|
||||
func isHexAlpha(b byte) bool {
|
||||
return b >= 'a' && b <= 'f' || b >= 'A' && b <= 'F'
|
||||
}
|
||||
|
||||
// incBytes increments a byte slice, which involves incrementing the
|
||||
// right-most byte, and following carry leftward.
|
||||
// It makes a copy so that the provided slice's underlying array is not modified.
|
||||
// If the overall operation overflows (e.g. incBytes(0xff, 0xff)), the second return parameter indicates that.
|
||||
func incBytes(in []byte) (out []byte, overflow bool) {
|
||||
out = make([]byte, len(in))
|
||||
copy(out, in)
|
||||
for i := len(out) - 1; i >= 0; i-- {
|
||||
out[i]++
|
||||
if out[i] != 0 {
|
||||
return // Didn't overflow.
|
||||
}
|
||||
}
|
||||
overflow = true
|
||||
return
|
||||
}
|
||||
|
||||
111
vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/repository_filesystem.go
generated
vendored
Normal file
111
vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/repository_filesystem.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
package dotgit
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
)
|
||||
|
||||
// RepositoryFilesystem is a billy.Filesystem compatible object wrapper
|
||||
// which handles dot-git filesystem operations and supports commondir according to git scm layout:
|
||||
// https://github.com/git/git/blob/master/Documentation/gitrepository-layout.txt
|
||||
type RepositoryFilesystem struct {
|
||||
dotGitFs billy.Filesystem
|
||||
commonDotGitFs billy.Filesystem
|
||||
}
|
||||
|
||||
func NewRepositoryFilesystem(dotGitFs, commonDotGitFs billy.Filesystem) *RepositoryFilesystem {
|
||||
return &RepositoryFilesystem{
|
||||
dotGitFs: dotGitFs,
|
||||
commonDotGitFs: commonDotGitFs,
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) mapToRepositoryFsByPath(path string) billy.Filesystem {
|
||||
// Nothing to decide if commondir not defined
|
||||
if fs.commonDotGitFs == nil {
|
||||
return fs.dotGitFs
|
||||
}
|
||||
|
||||
cleanPath := filepath.Clean(path)
|
||||
|
||||
// Check exceptions for commondir (https://git-scm.com/docs/gitrepository-layout#Documentation/gitrepository-layout.txt)
|
||||
switch cleanPath {
|
||||
case fs.dotGitFs.Join(logsPath, "HEAD"):
|
||||
return fs.dotGitFs
|
||||
case fs.dotGitFs.Join(refsPath, "bisect"), fs.dotGitFs.Join(refsPath, "rewritten"), fs.dotGitFs.Join(refsPath, "worktree"):
|
||||
return fs.dotGitFs
|
||||
}
|
||||
|
||||
// Determine dot-git root by first path element.
|
||||
// There are some elements which should always use commondir when commondir defined.
|
||||
// Usual dot-git root will be used for the rest of files.
|
||||
switch strings.Split(cleanPath, string(filepath.Separator))[0] {
|
||||
case objectsPath, refsPath, packedRefsPath, configPath, branchesPath, hooksPath, infoPath, remotesPath, logsPath, shallowPath, worktreesPath:
|
||||
return fs.commonDotGitFs
|
||||
default:
|
||||
return fs.dotGitFs
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Create(filename string) (billy.File, error) {
|
||||
return fs.mapToRepositoryFsByPath(filename).Create(filename)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Open(filename string) (billy.File, error) {
|
||||
return fs.mapToRepositoryFsByPath(filename).Open(filename)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) {
|
||||
return fs.mapToRepositoryFsByPath(filename).OpenFile(filename, flag, perm)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Stat(filename string) (os.FileInfo, error) {
|
||||
return fs.mapToRepositoryFsByPath(filename).Stat(filename)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Rename(oldpath, newpath string) error {
|
||||
return fs.mapToRepositoryFsByPath(oldpath).Rename(oldpath, newpath)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Remove(filename string) error {
|
||||
return fs.mapToRepositoryFsByPath(filename).Remove(filename)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Join(elem ...string) string {
|
||||
return fs.dotGitFs.Join(elem...)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) TempFile(dir, prefix string) (billy.File, error) {
|
||||
return fs.mapToRepositoryFsByPath(dir).TempFile(dir, prefix)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) ReadDir(path string) ([]os.FileInfo, error) {
|
||||
return fs.mapToRepositoryFsByPath(path).ReadDir(path)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) MkdirAll(filename string, perm os.FileMode) error {
|
||||
return fs.mapToRepositoryFsByPath(filename).MkdirAll(filename, perm)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Lstat(filename string) (os.FileInfo, error) {
|
||||
return fs.mapToRepositoryFsByPath(filename).Lstat(filename)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Symlink(target, link string) error {
|
||||
return fs.mapToRepositoryFsByPath(target).Symlink(target, link)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Readlink(link string) (string, error) {
|
||||
return fs.mapToRepositoryFsByPath(link).Readlink(link)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Chroot(path string) (billy.Filesystem, error) {
|
||||
return fs.mapToRepositoryFsByPath(path).Chroot(path)
|
||||
}
|
||||
|
||||
func (fs *RepositoryFilesystem) Root() string {
|
||||
return fs.dotGitFs.Root()
|
||||
}
|
||||
33
vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go
generated
vendored
33
vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go
generated
vendored
@@ -1,6 +1,7 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
@@ -408,6 +409,8 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(w, &err)
|
||||
|
||||
s.objectCache.Put(obj)
|
||||
|
||||
_, err = io.Copy(w, r)
|
||||
@@ -516,6 +519,36 @@ func (s *ObjectStorage) findObjectInPackfile(h plumbing.Hash) (plumbing.Hash, pl
|
||||
return plumbing.ZeroHash, plumbing.ZeroHash, -1
|
||||
}
|
||||
|
||||
func (s *ObjectStorage) HashesWithPrefix(prefix []byte) ([]plumbing.Hash, error) {
|
||||
hashes, err := s.dir.ObjectsWithPrefix(prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: This could be faster with some idxfile changes,
|
||||
// or diving into the packfile.
|
||||
for _, index := range s.index {
|
||||
ei, err := index.Entries()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for {
|
||||
e, err := ei.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if bytes.HasPrefix(e.Hash[:], prefix) {
|
||||
hashes = append(hashes, e.Hash)
|
||||
}
|
||||
}
|
||||
ei.Close()
|
||||
}
|
||||
|
||||
return hashes, nil
|
||||
}
|
||||
|
||||
// IterEncodedObjects returns an iterator for all the objects in the packfile
|
||||
// with the given type.
|
||||
func (s *ObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (storer.EncodedObjectIter, error) {
|
||||
|
||||
4
vendor/github.com/go-git/go-git/v5/storage/memory/storage.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/storage/memory/storage.go
generated
vendored
@@ -195,10 +195,10 @@ func (o *ObjectStorage) DeleteOldObjectPackAndIndex(plumbing.Hash, time.Time) er
|
||||
|
||||
var errNotSupported = fmt.Errorf("Not supported")
|
||||
|
||||
func (s *ObjectStorage) LooseObjectTime(hash plumbing.Hash) (time.Time, error) {
|
||||
func (o *ObjectStorage) LooseObjectTime(hash plumbing.Hash) (time.Time, error) {
|
||||
return time.Time{}, errNotSupported
|
||||
}
|
||||
func (s *ObjectStorage) DeleteLooseObject(plumbing.Hash) error {
|
||||
func (o *ObjectStorage) DeleteLooseObject(plumbing.Hash) error {
|
||||
return errNotSupported
|
||||
}
|
||||
|
||||
|
||||
48
vendor/github.com/go-git/go-git/v5/submodule.go
generated
vendored
48
vendor/github.com/go-git/go-git/v5/submodule.go
generated
vendored
@@ -5,6 +5,8 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
@@ -35,7 +37,7 @@ func (s *Submodule) Config() *config.Submodule {
|
||||
// Init initialize the submodule reading the recorded Entry in the index for
|
||||
// the given submodule
|
||||
func (s *Submodule) Init() error {
|
||||
cfg, err := s.w.r.Storer.Config()
|
||||
cfg, err := s.w.r.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -131,9 +133,29 @@ func (s *Submodule) Repository() (*Repository, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
moduleURL, err := url.Parse(s.c.URL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !path.IsAbs(moduleURL.Path) {
|
||||
remotes, err := s.w.r.Remotes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rootURL, err := url.Parse(remotes[0].c.URLs[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rootURL.Path = path.Join(rootURL.Path, moduleURL.Path)
|
||||
*moduleURL = *rootURL
|
||||
}
|
||||
|
||||
_, err = r.CreateRemote(&config.RemoteConfig{
|
||||
Name: DefaultRemoteName,
|
||||
URLs: []string{s.c.URL},
|
||||
URLs: []string{moduleURL.String()},
|
||||
})
|
||||
|
||||
return r, err
|
||||
@@ -151,7 +173,7 @@ func (s *Submodule) Update(o *SubmoduleUpdateOptions) error {
|
||||
// setting in the options SubmoduleUpdateOptions.Init equals true.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// operation is complete, an error is returned. The context only affects the
|
||||
// transport operations.
|
||||
func (s *Submodule) UpdateContext(ctx context.Context, o *SubmoduleUpdateOptions) error {
|
||||
return s.update(ctx, o, plumbing.ZeroHash)
|
||||
@@ -232,6 +254,24 @@ func (s *Submodule) fetchAndCheckout(
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle a case when submodule refers to an orphaned commit that's still reachable
|
||||
// through Git server using a special protocol capability[1].
|
||||
//
|
||||
// [1]: https://git-scm.com/docs/protocol-capabilities#_allow_reachable_sha1_in_want
|
||||
if !o.NoFetch {
|
||||
if _, err := w.r.Object(plumbing.AnyObject, hash); err != nil {
|
||||
refSpec := config.RefSpec("+" + hash.String() + ":" + hash.String())
|
||||
|
||||
err := r.FetchContext(ctx, &FetchOptions{
|
||||
Auth: o.Auth,
|
||||
RefSpecs: []config.RefSpec{refSpec},
|
||||
})
|
||||
if err != nil && err != NoErrAlreadyUpToDate && err != ErrExactSHA1NotSupported {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := w.Checkout(&CheckoutOptions{Hash: hash}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -262,7 +302,7 @@ func (s Submodules) Update(o *SubmoduleUpdateOptions) error {
|
||||
// UpdateContext updates all the submodules in this list.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// operation is complete, an error is returned. The context only affects the
|
||||
// transport operations.
|
||||
func (s Submodules) UpdateContext(ctx context.Context, o *SubmoduleUpdateOptions) error {
|
||||
for _, sub := range s {
|
||||
|
||||
2
vendor/github.com/go-git/go-git/v5/utils/diff/diff.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/utils/diff/diff.go
generated
vendored
@@ -29,7 +29,7 @@ func Do(src, dst string) (diffs []diffmatchpatch.Diff) {
|
||||
// a bulk delete+insert and the half-baked suboptimal result is returned at once.
|
||||
// The underlying algorithm is Meyers, its complexity is O(N*d) where N is
|
||||
// min(lines(src), lines(dst)) and d is the size of the diff.
|
||||
func DoWithTimeout (src, dst string, timeout time.Duration) (diffs []diffmatchpatch.Diff) {
|
||||
func DoWithTimeout(src, dst string, timeout time.Duration) (diffs []diffmatchpatch.Diff) {
|
||||
dmp := diffmatchpatch.New()
|
||||
dmp.DiffTimeout = timeout
|
||||
wSrc, wDst, warray := dmp.DiffLinesToRunes(src, dst)
|
||||
|
||||
12
vendor/github.com/go-git/go-git/v5/utils/ioutil/common.go
generated
vendored
12
vendor/github.com/go-git/go-git/v5/utils/ioutil/common.go
generated
vendored
@@ -7,7 +7,7 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/jbenet/go-context/io"
|
||||
ctxio "github.com/jbenet/go-context/io"
|
||||
)
|
||||
|
||||
type readPeeker interface {
|
||||
@@ -168,3 +168,13 @@ func (r *writerOnError) Write(p []byte) (n int, err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type PipeReader interface {
|
||||
io.ReadCloser
|
||||
CloseWithError(err error) error
|
||||
}
|
||||
|
||||
type PipeWriter interface {
|
||||
io.WriteCloser
|
||||
CloseWithError(err error) error
|
||||
}
|
||||
|
||||
9
vendor/github.com/go-git/go-git/v5/utils/ioutil/pipe.go
generated
vendored
Normal file
9
vendor/github.com/go-git/go-git/v5/utils/ioutil/pipe.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build !js
|
||||
|
||||
package ioutil
|
||||
|
||||
import "io"
|
||||
|
||||
func Pipe() (PipeReader, PipeWriter) {
|
||||
return io.Pipe()
|
||||
}
|
||||
9
vendor/github.com/go-git/go-git/v5/utils/ioutil/pipe_js.go
generated
vendored
Normal file
9
vendor/github.com/go-git/go-git/v5/utils/ioutil/pipe_js.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build js
|
||||
|
||||
package ioutil
|
||||
|
||||
import "github.com/acomagu/bufpipe"
|
||||
|
||||
func Pipe() (PipeReader, PipeWriter) {
|
||||
return bufpipe.New(nil)
|
||||
}
|
||||
12
vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go
generated
vendored
12
vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go
generated
vendored
@@ -23,7 +23,7 @@ package merkletrie
|
||||
|
||||
// # Cases
|
||||
//
|
||||
// When comparing noders in both trees you will found yourself in
|
||||
// When comparing noders in both trees you will find yourself in
|
||||
// one of 169 possible cases, but if we ignore moves, we can
|
||||
// simplify a lot the search space into the following table:
|
||||
//
|
||||
@@ -256,17 +256,21 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrCanceled is returned whenever the operation is canceled.
|
||||
ErrCanceled = errors.New("operation canceled")
|
||||
)
|
||||
|
||||
// DiffTree calculates the list of changes between two merkletries. It
|
||||
// uses the provided hashEqual callback to compare noders.
|
||||
func DiffTree(fromTree, toTree noder.Noder,
|
||||
hashEqual noder.Equal) (Changes, error) {
|
||||
func DiffTree(
|
||||
fromTree,
|
||||
toTree noder.Noder,
|
||||
hashEqual noder.Equal,
|
||||
) (Changes, error) {
|
||||
return DiffTreeContext(context.Background(), fromTree, toTree, hashEqual)
|
||||
}
|
||||
|
||||
// DiffTree calculates the list of changes between two merkletries. It
|
||||
// DiffTreeContext calculates the list of changes between two merkletries. It
|
||||
// uses the provided hashEqual callback to compare noders.
|
||||
// Error will be returned if context expires
|
||||
// Provided context must be non nil
|
||||
|
||||
3
vendor/github.com/go-git/go-git/v5/utils/merkletrie/filesystem/node.go
generated
vendored
3
vendor/github.com/go-git/go-git/v5/utils/merkletrie/filesystem/node.go
generated
vendored
@@ -91,8 +91,7 @@ func (n *node) calculateChildren() error {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
|
||||
29
vendor/github.com/go-git/go-git/v5/worktree.go
generated
vendored
29
vendor/github.com/go-git/go-git/v5/worktree.go
generated
vendored
@@ -59,7 +59,7 @@ func (w *Worktree) Pull(o *PullOptions) error {
|
||||
// Pull only supports merges where the can be resolved as a fast-forward.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before the
|
||||
// operation is complete, an error is returned. The context only affects to the
|
||||
// operation is complete, an error is returned. The context only affects the
|
||||
// transport operations.
|
||||
func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
|
||||
if err := o.Validate(); err != nil {
|
||||
@@ -72,11 +72,13 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
|
||||
}
|
||||
|
||||
fetchHead, err := remote.fetch(ctx, &FetchOptions{
|
||||
RemoteName: o.RemoteName,
|
||||
Depth: o.Depth,
|
||||
Auth: o.Auth,
|
||||
Progress: o.Progress,
|
||||
Force: o.Force,
|
||||
RemoteName: o.RemoteName,
|
||||
Depth: o.Depth,
|
||||
Auth: o.Auth,
|
||||
Progress: o.Progress,
|
||||
Force: o.Force,
|
||||
InsecureSkipTLS: o.InsecureSkipTLS,
|
||||
CABundle: o.CABundle,
|
||||
})
|
||||
|
||||
updated := true
|
||||
@@ -93,7 +95,12 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
|
||||
|
||||
head, err := w.r.Head()
|
||||
if err == nil {
|
||||
if !updated && head.Hash() == ref.Hash() {
|
||||
headAheadOfRef, err := isFastForward(w.r.Storer, ref.Hash(), head.Hash())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !updated && headAheadOfRef {
|
||||
return NoErrAlreadyUpToDate
|
||||
}
|
||||
|
||||
@@ -711,7 +718,11 @@ func (w *Worktree) readGitmodulesFile() (*config.Modules, error) {
|
||||
}
|
||||
|
||||
m := config.NewModules()
|
||||
return m, m.Unmarshal(input)
|
||||
if err := m.Unmarshal(input); err != nil {
|
||||
return m, err
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Clean the worktree by removing untracked files.
|
||||
@@ -760,7 +771,7 @@ func (w *Worktree) doClean(status Status, opts *CleanOptions, dir string, files
|
||||
}
|
||||
}
|
||||
|
||||
if opts.Dir {
|
||||
if opts.Dir && dir != "" {
|
||||
return doCleanDirectories(w.Filesystem, dir)
|
||||
}
|
||||
return nil
|
||||
|
||||
16
vendor/github.com/go-git/go-git/v5/worktree_commit.go
generated
vendored
16
vendor/github.com/go-git/go-git/v5/worktree_commit.go
generated
vendored
@@ -6,13 +6,13 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/filemode"
|
||||
"github.com/go-git/go-git/v5/plumbing/format/index"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/go-git/go-git/v5/storage"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/go-git/go-billy/v5"
|
||||
)
|
||||
|
||||
@@ -58,17 +58,23 @@ func (w *Worktree) autoAddModifiedAndDeleted() error {
|
||||
return err
|
||||
}
|
||||
|
||||
idx, err := w.r.Storer.Index()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for path, fs := range s {
|
||||
if fs.Worktree != Modified && fs.Worktree != Deleted {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, err := w.Add(path); err != nil {
|
||||
if _, _, err := w.doAddFile(idx, s, path, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
return w.r.Storer.SetIndex(idx)
|
||||
}
|
||||
|
||||
func (w *Worktree) updateHEAD(commit plumbing.Hash) error {
|
||||
@@ -224,5 +230,9 @@ func (h *buildTreeHelper) copyTreeToStorageRecursive(parent string, t *object.Tr
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
hash := o.Hash()
|
||||
if h.s.HasEncodedObject(hash) == nil {
|
||||
return hash, nil
|
||||
}
|
||||
return h.s.SetEncodedObject(o)
|
||||
}
|
||||
|
||||
26
vendor/github.com/go-git/go-git/v5/worktree_js.go
generated
vendored
Normal file
26
vendor/github.com/go-git/go-git/v5/worktree_js.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// +build js
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/format/index"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fillSystemInfo = func(e *index.Entry, sys interface{}) {
|
||||
if os, ok := sys.(*syscall.Stat_t); ok {
|
||||
e.CreatedAt = time.Unix(int64(os.Ctime), int64(os.CtimeNsec))
|
||||
e.Dev = uint32(os.Dev)
|
||||
e.Inode = uint32(os.Ino)
|
||||
e.GID = os.Gid
|
||||
e.UID = os.Uid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isSymlinkWindowsNonAdmin(err error) bool {
|
||||
return false
|
||||
}
|
||||
124
vendor/github.com/go-git/go-git/v5/worktree_status.go
generated
vendored
124
vendor/github.com/go-git/go-git/v5/worktree_status.go
generated
vendored
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-billy/v5/util"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
@@ -264,7 +265,77 @@ func diffTreeIsEquals(a, b noder.Hasher) bool {
|
||||
// the worktree to the index. If any of the files is already staged in the index
|
||||
// no error is returned. When path is a file, the blob.Hash is returned.
|
||||
func (w *Worktree) Add(path string) (plumbing.Hash, error) {
|
||||
// TODO(mcuadros): remove plumbing.Hash from signature at v5.
|
||||
// TODO(mcuadros): deprecate in favor of AddWithOption in v6.
|
||||
return w.doAdd(path, make([]gitignore.Pattern, 0))
|
||||
}
|
||||
|
||||
func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string, ignorePattern []gitignore.Pattern) (added bool, err error) {
|
||||
files, err := w.Filesystem.ReadDir(directory)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(ignorePattern) > 0 {
|
||||
m := gitignore.NewMatcher(ignorePattern)
|
||||
matchPath := strings.Split(directory, string(os.PathSeparator))
|
||||
if m.Match(matchPath, true) {
|
||||
// ignore
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
name := path.Join(directory, file.Name())
|
||||
|
||||
var a bool
|
||||
if file.IsDir() {
|
||||
if file.Name() == GitDirName {
|
||||
// ignore special git directory
|
||||
continue
|
||||
}
|
||||
a, err = w.doAddDirectory(idx, s, name, ignorePattern)
|
||||
} else {
|
||||
a, _, err = w.doAddFile(idx, s, name, ignorePattern)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !added && a {
|
||||
added = true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// AddWithOptions file contents to the index, updates the index using the
|
||||
// current content found in the working tree, to prepare the content staged for
|
||||
// the next commit.
|
||||
//
|
||||
// It typically adds the current content of existing paths as a whole, but with
|
||||
// some options it can also be used to add content with only part of the changes
|
||||
// made to the working tree files applied, or remove paths that do not exist in
|
||||
// the working tree anymore.
|
||||
func (w *Worktree) AddWithOptions(opts *AddOptions) error {
|
||||
if err := opts.Validate(w.r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if opts.All {
|
||||
_, err := w.doAdd(".", w.Excludes)
|
||||
return err
|
||||
}
|
||||
|
||||
if opts.Glob != "" {
|
||||
return w.AddGlob(opts.Glob)
|
||||
}
|
||||
|
||||
_, err := w.Add(opts.Path)
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern) (plumbing.Hash, error) {
|
||||
s, err := w.Status()
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
@@ -280,9 +351,9 @@ func (w *Worktree) Add(path string) (plumbing.Hash, error) {
|
||||
|
||||
fi, err := w.Filesystem.Lstat(path)
|
||||
if err != nil || !fi.IsDir() {
|
||||
added, h, err = w.doAddFile(idx, s, path)
|
||||
added, h, err = w.doAddFile(idx, s, path, ignorePattern)
|
||||
} else {
|
||||
added, err = w.doAddDirectory(idx, s, path)
|
||||
added, err = w.doAddDirectory(idx, s, path, ignorePattern)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -296,42 +367,11 @@ func (w *Worktree) Add(path string) (plumbing.Hash, error) {
|
||||
return h, w.r.Storer.SetIndex(idx)
|
||||
}
|
||||
|
||||
func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string) (added bool, err error) {
|
||||
files, err := w.Filesystem.ReadDir(directory)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
name := path.Join(directory, file.Name())
|
||||
|
||||
var a bool
|
||||
if file.IsDir() {
|
||||
if file.Name() == GitDirName {
|
||||
// ignore special git directory
|
||||
continue
|
||||
}
|
||||
a, err = w.doAddDirectory(idx, s, name)
|
||||
} else {
|
||||
a, _, err = w.doAddFile(idx, s, name)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !added && a {
|
||||
added = true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// AddGlob adds all paths, matching pattern, to the index. If pattern matches a
|
||||
// directory path, all directory contents are added to the index recursively. No
|
||||
// error is returned if all matching paths are already staged in index.
|
||||
func (w *Worktree) AddGlob(pattern string) error {
|
||||
// TODO(mcuadros): deprecate in favor of AddWithOption in v6.
|
||||
files, err := util.Glob(w.Filesystem, pattern)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -360,9 +400,9 @@ func (w *Worktree) AddGlob(pattern string) error {
|
||||
|
||||
var added bool
|
||||
if fi.IsDir() {
|
||||
added, err = w.doAddDirectory(idx, s, file)
|
||||
added, err = w.doAddDirectory(idx, s, file, make([]gitignore.Pattern, 0))
|
||||
} else {
|
||||
added, _, err = w.doAddFile(idx, s, file)
|
||||
added, _, err = w.doAddFile(idx, s, file, make([]gitignore.Pattern, 0))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -383,10 +423,18 @@ func (w *Worktree) AddGlob(pattern string) error {
|
||||
|
||||
// doAddFile create a new blob from path and update the index, added is true if
|
||||
// the file added is different from the index.
|
||||
func (w *Worktree) doAddFile(idx *index.Index, s Status, path string) (added bool, h plumbing.Hash, err error) {
|
||||
func (w *Worktree) doAddFile(idx *index.Index, s Status, path string, ignorePattern []gitignore.Pattern) (added bool, h plumbing.Hash, err error) {
|
||||
if s.File(path).Worktree == Unmodified {
|
||||
return false, h, nil
|
||||
}
|
||||
if len(ignorePattern) > 0 {
|
||||
m := gitignore.NewMatcher(ignorePattern)
|
||||
matchPath := strings.Split(path, string(os.PathSeparator))
|
||||
if m.Match(matchPath, true) {
|
||||
// ignore
|
||||
return false, h, nil
|
||||
}
|
||||
}
|
||||
|
||||
h, err = w.copyFileToStorage(path)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user