mirror of
https://github.com/cheat/cheat.git
synced 2026-03-07 19:23:34 +01:00
chore: modernize CI and update Go toolchain
- Bump Go from 1.19 to 1.26 and update all dependencies - Rewrite CI workflow with matrix strategy (Linux, macOS, Windows) - Update GitHub Actions to current versions (checkout@v4, setup-go@v5) - Update CodeQL actions from v1 to v3 - Fix cross-platform bug in mock/path.go (path.Join -> filepath.Join) - Clean up dependabot config (weekly schedule, remove stale ignore) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
7
vendor/github.com/go-git/go-billy/v5/Makefile
generated
vendored
7
vendor/github.com/go-git/go-billy/v5/Makefile
generated
vendored
@@ -1,6 +1,7 @@
|
||||
# Go parameters
|
||||
GOCMD = go
|
||||
GOTEST = $(GOCMD) test
|
||||
WASIRUN_WRAPPER := $(CURDIR)/scripts/wasirun-wrapper
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
@@ -9,3 +10,9 @@ test:
|
||||
test-coverage:
|
||||
echo "" > $(COVERAGE_REPORT); \
|
||||
$(GOTEST) -coverprofile=$(COVERAGE_REPORT) -coverpkg=./... -covermode=$(COVERAGE_MODE) ./...
|
||||
|
||||
.PHONY: wasitest
|
||||
wasitest: export GOARCH=wasm
|
||||
wasitest: export GOOS=wasip1
|
||||
wasitest:
|
||||
$(GOTEST) -exec $(WASIRUN_WRAPPER) ./...
|
||||
|
||||
14
vendor/github.com/go-git/go-billy/v5/fs.go
generated
vendored
14
vendor/github.com/go-git/go-billy/v5/fs.go
generated
vendored
@@ -128,12 +128,18 @@ type Symlink interface {
|
||||
Readlink(link string) (string, error)
|
||||
}
|
||||
|
||||
// Change abstract the FileInfo change related operations in a storage-agnostic
|
||||
// interface as an extension to the Basic interface
|
||||
type Change interface {
|
||||
// Chmod abstracts the logic around changing file modes.
|
||||
type Chmod interface {
|
||||
// Chmod changes the mode of the named file to mode. If the file is a
|
||||
// symbolic link, it changes the mode of the link's target.
|
||||
Chmod(name string, mode os.FileMode) error
|
||||
}
|
||||
|
||||
// Change abstract the FileInfo change related operations in a storage-agnostic
|
||||
// interface as an extension to the Basic interface
|
||||
type Change interface {
|
||||
Chmod
|
||||
|
||||
// Lchown changes the numeric uid and gid of the named file. If the file is
|
||||
// a symbolic link, it changes the uid and gid of the link itself.
|
||||
Lchown(name string, uid, gid int) error
|
||||
@@ -164,6 +170,8 @@ type File interface {
|
||||
// Name returns the name of the file as presented to Open.
|
||||
Name() string
|
||||
io.Writer
|
||||
// TODO: Add io.WriterAt for v6
|
||||
// io.WriterAt
|
||||
io.Reader
|
||||
io.ReaderAt
|
||||
io.Seeker
|
||||
|
||||
14
vendor/github.com/go-git/go-billy/v5/helper/chroot/chroot.go
generated
vendored
14
vendor/github.com/go-git/go-billy/v5/helper/chroot/chroot.go
generated
vendored
@@ -1,6 +1,7 @@
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -200,6 +201,19 @@ func (fs *ChrootHelper) Readlink(link string) (string, error) {
|
||||
return string(os.PathSeparator) + target, nil
|
||||
}
|
||||
|
||||
func (fs *ChrootHelper) Chmod(path string, mode os.FileMode) error {
|
||||
fullpath, err := fs.underlyingPath(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, ok := fs.underlying.(billy.Chmod)
|
||||
if !ok {
|
||||
return errors.New("underlying fs does not implement billy.Chmod")
|
||||
}
|
||||
return c.Chmod(fullpath, mode)
|
||||
}
|
||||
|
||||
func (fs *ChrootHelper) Chroot(path string) (billy.Filesystem, error) {
|
||||
fullpath, err := fs.underlyingPath(path)
|
||||
if err != nil {
|
||||
|
||||
40
vendor/github.com/go-git/go-billy/v5/memfs/memory.go
generated
vendored
40
vendor/github.com/go-git/go-billy/v5/memfs/memory.go
generated
vendored
@@ -9,6 +9,7 @@ import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
@@ -18,16 +19,19 @@ import (
|
||||
|
||||
const separator = filepath.Separator
|
||||
|
||||
// Memory a very convenient filesystem based on memory files
|
||||
var errNotLink = errors.New("not a link")
|
||||
|
||||
// Memory a very convenient filesystem based on memory files.
|
||||
type Memory struct {
|
||||
s *storage
|
||||
|
||||
tempCount int
|
||||
}
|
||||
|
||||
//New returns a new Memory filesystem.
|
||||
// New returns a new Memory filesystem.
|
||||
func New() billy.Filesystem {
|
||||
fs := &Memory{s: newStorage()}
|
||||
fs.s.New("/", 0755|os.ModeDir, 0)
|
||||
return chroot.New(fs, string(separator))
|
||||
}
|
||||
|
||||
@@ -57,7 +61,9 @@ func (fs *Memory) OpenFile(filename string, flag int, perm os.FileMode) (billy.F
|
||||
}
|
||||
|
||||
if target, isLink := fs.resolveLink(filename, f); isLink {
|
||||
return fs.OpenFile(target, flag, perm)
|
||||
if target != filename {
|
||||
return fs.OpenFile(target, flag, perm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,8 +74,6 @@ func (fs *Memory) OpenFile(filename string, flag int, perm os.FileMode) (billy.F
|
||||
return f.Duplicate(filename, perm, flag), nil
|
||||
}
|
||||
|
||||
var errNotLink = errors.New("not a link")
|
||||
|
||||
func (fs *Memory) resolveLink(fullpath string, f *file) (target string, isLink bool) {
|
||||
if !isSymlink(f.mode) {
|
||||
return fullpath, false
|
||||
@@ -131,8 +135,12 @@ func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (fs *Memory) ReadDir(path string) ([]os.FileInfo, error) {
|
||||
if f, has := fs.s.Get(path); has {
|
||||
if target, isLink := fs.resolveLink(path, f); isLink {
|
||||
return fs.ReadDir(target)
|
||||
if target != path {
|
||||
return fs.ReadDir(target)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil, &os.PathError{Op: "open", Path: path, Err: syscall.ENOENT}
|
||||
}
|
||||
|
||||
var entries []os.FileInfo
|
||||
@@ -169,17 +177,23 @@ func (fs *Memory) Remove(filename string) error {
|
||||
return fs.s.Remove(filename)
|
||||
}
|
||||
|
||||
func (fs *Memory) Chmod(path string, mode os.FileMode) error {
|
||||
return fs.s.Chmod(path, mode)
|
||||
}
|
||||
|
||||
// Falls back to Go's filepath.Join, which works differently depending on the
|
||||
// OS where the code is being executed.
|
||||
func (fs *Memory) Join(elem ...string) string {
|
||||
return filepath.Join(elem...)
|
||||
}
|
||||
|
||||
func (fs *Memory) Symlink(target, link string) error {
|
||||
_, err := fs.Stat(link)
|
||||
_, err := fs.Lstat(link)
|
||||
if err == nil {
|
||||
return os.ErrExist
|
||||
}
|
||||
|
||||
if !os.IsNotExist(err) {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -230,7 +244,7 @@ func (f *file) Read(b []byte) (int, error) {
|
||||
n, err := f.ReadAt(b, f.position)
|
||||
f.position += int64(n)
|
||||
|
||||
if err == io.EOF && n != 0 {
|
||||
if errors.Is(err, io.EOF) && n != 0 {
|
||||
err = nil
|
||||
}
|
||||
|
||||
@@ -269,6 +283,10 @@ func (f *file) Seek(offset int64, whence int) (int64, error) {
|
||||
}
|
||||
|
||||
func (f *file) Write(p []byte) (int, error) {
|
||||
return f.WriteAt(p, f.position)
|
||||
}
|
||||
|
||||
func (f *file) WriteAt(p []byte, off int64) (int, error) {
|
||||
if f.isClosed {
|
||||
return 0, os.ErrClosed
|
||||
}
|
||||
@@ -277,8 +295,8 @@ func (f *file) Write(p []byte) (int, error) {
|
||||
return 0, errors.New("write not supported")
|
||||
}
|
||||
|
||||
n, err := f.content.WriteAt(p, f.position)
|
||||
f.position += int64(n)
|
||||
n, err := f.content.WriteAt(p, off)
|
||||
f.position = off + int64(n)
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
15
vendor/github.com/go-git/go-billy/v5/memfs/storage.go
generated
vendored
15
vendor/github.com/go-git/go-billy/v5/memfs/storage.go
generated
vendored
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -112,7 +113,7 @@ func (s *storage) Rename(from, to string) error {
|
||||
move := [][2]string{{from, to}}
|
||||
|
||||
for pathFrom := range s.files {
|
||||
if pathFrom == from || !filepath.HasPrefix(pathFrom, from) {
|
||||
if pathFrom == from || !strings.HasPrefix(pathFrom, from) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -168,6 +169,18 @@ func (s *storage) Remove(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *storage) Chmod(path string, mode os.FileMode) error {
|
||||
path = clean(path)
|
||||
|
||||
f, has := s.Get(path)
|
||||
if !has {
|
||||
return os.ErrNotExist
|
||||
}
|
||||
|
||||
f.mode = mode
|
||||
return nil
|
||||
}
|
||||
|
||||
func clean(path string) string {
|
||||
return filepath.Clean(filepath.FromSlash(path))
|
||||
}
|
||||
|
||||
14
vendor/github.com/go-git/go-billy/v5/osfs/os_bound.go
generated
vendored
14
vendor/github.com/go-git/go-billy/v5/osfs/os_bound.go
generated
vendored
@@ -176,6 +176,14 @@ func (fs *BoundOS) Readlink(link string) (string, error) {
|
||||
return os.Readlink(link)
|
||||
}
|
||||
|
||||
func (fs *BoundOS) Chmod(path string, mode os.FileMode) error {
|
||||
abspath, err := fs.abs(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Chmod(abspath, mode)
|
||||
}
|
||||
|
||||
// Chroot returns a new OS filesystem, with the base dir set to the
|
||||
// result of joining the provided path with the underlying base dir.
|
||||
func (fs *BoundOS) Chroot(path string) (billy.Filesystem, error) {
|
||||
@@ -246,6 +254,10 @@ func (fs *BoundOS) insideBaseDir(filename string) (bool, error) {
|
||||
// a dir that is within the fs.baseDir, by first evaluating any symlinks
|
||||
// that either filename or fs.baseDir may contain.
|
||||
func (fs *BoundOS) insideBaseDirEval(filename string) (bool, error) {
|
||||
// "/" contains all others.
|
||||
if fs.baseDir == "/" {
|
||||
return true, nil
|
||||
}
|
||||
dir, err := filepath.EvalSymlinks(filepath.Dir(filename))
|
||||
if dir == "" || os.IsNotExist(err) {
|
||||
dir = filepath.Dir(filename)
|
||||
@@ -255,7 +267,7 @@ func (fs *BoundOS) insideBaseDirEval(filename string) (bool, error) {
|
||||
wd = fs.baseDir
|
||||
}
|
||||
if filename != wd && dir != wd && !strings.HasPrefix(dir, wd+string(filepath.Separator)) {
|
||||
return false, fmt.Errorf("path outside base dir")
|
||||
return false, fmt.Errorf("%q: path outside base dir %q: %w", filename, fs.baseDir, os.ErrNotExist)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
4
vendor/github.com/go-git/go-billy/v5/osfs/os_chroot.go
generated
vendored
4
vendor/github.com/go-git/go-billy/v5/osfs/os_chroot.go
generated
vendored
@@ -74,6 +74,10 @@ func (fs *ChrootOS) Remove(filename string) error {
|
||||
return os.Remove(filename)
|
||||
}
|
||||
|
||||
func (fs *ChrootOS) Chmod(path string, mode os.FileMode) error {
|
||||
return os.Chmod(path, mode)
|
||||
}
|
||||
|
||||
func (fs *ChrootOS) TempFile(dir, prefix string) (billy.File, error) {
|
||||
if err := fs.createDir(dir + string(os.PathSeparator)); err != nil {
|
||||
return nil, err
|
||||
|
||||
4
vendor/github.com/go-git/go-billy/v5/osfs/os_posix.go
generated
vendored
4
vendor/github.com/go-git/go-billy/v5/osfs/os_posix.go
generated
vendored
@@ -1,5 +1,5 @@
|
||||
//go:build !plan9 && !windows && !js
|
||||
// +build !plan9,!windows,!js
|
||||
//go:build !plan9 && !windows && !wasm
|
||||
// +build !plan9,!windows,!wasm
|
||||
|
||||
package osfs
|
||||
|
||||
|
||||
34
vendor/github.com/go-git/go-billy/v5/osfs/os_wasip1.go
generated
vendored
Normal file
34
vendor/github.com/go-git/go-billy/v5/osfs/os_wasip1.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
//go:build wasip1
|
||||
// +build wasip1
|
||||
|
||||
package osfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (f *file) Lock() error {
|
||||
f.m.Lock()
|
||||
defer f.m.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *file) Unlock() error {
|
||||
f.m.Lock()
|
||||
defer f.m.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func rename(from, to string) error {
|
||||
return os.Rename(from, to)
|
||||
}
|
||||
|
||||
// umask sets umask to a new value, and returns a func which allows the
|
||||
// caller to reset it back to what it was originally.
|
||||
func umask(new int) func() {
|
||||
old := syscall.Umask(new)
|
||||
return func() {
|
||||
syscall.Umask(old)
|
||||
}
|
||||
}
|
||||
35
vendor/github.com/go-git/go-billy/v5/util/util.go
generated
vendored
35
vendor/github.com/go-git/go-billy/v5/util/util.go
generated
vendored
@@ -1,6 +1,7 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -33,14 +34,14 @@ func removeAll(fs billy.Basic, path string) error {
|
||||
|
||||
// Simple case: if Remove works, we're done.
|
||||
err := fs.Remove(path)
|
||||
if err == nil || os.IsNotExist(err) {
|
||||
if err == nil || errors.Is(err, os.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Otherwise, is this a directory we need to recurse into?
|
||||
dir, serr := fs.Stat(path)
|
||||
if serr != nil {
|
||||
if os.IsNotExist(serr) {
|
||||
if errors.Is(serr, os.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -60,7 +61,7 @@ func removeAll(fs billy.Basic, path string) error {
|
||||
// Directory.
|
||||
fis, err := dirfs.ReadDir(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
// Race. It was deleted between the Lstat and Open.
|
||||
// Return nil per RemoveAll's docs.
|
||||
return nil
|
||||
@@ -81,7 +82,7 @@ func removeAll(fs billy.Basic, path string) error {
|
||||
|
||||
// Remove directory.
|
||||
err1 := fs.Remove(path)
|
||||
if err1 == nil || os.IsNotExist(err1) {
|
||||
if err1 == nil || errors.Is(err1, os.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -96,22 +97,26 @@ func removeAll(fs billy.Basic, path string) error {
|
||||
// WriteFile writes data to a file named by filename in the given filesystem.
|
||||
// If the file does not exist, WriteFile creates it with permissions perm;
|
||||
// otherwise WriteFile truncates it before writing.
|
||||
func WriteFile(fs billy.Basic, filename string, data []byte, perm os.FileMode) error {
|
||||
func WriteFile(fs billy.Basic, filename string, data []byte, perm os.FileMode) (err error) {
|
||||
f, err := fs.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if f != nil {
|
||||
err1 := f.Close()
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
n, err := f.Write(data)
|
||||
if err == nil && n < len(data) {
|
||||
err = io.ErrShortWrite
|
||||
}
|
||||
|
||||
if err1 := f.Close(); err == nil {
|
||||
err = err1
|
||||
}
|
||||
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// Random number state.
|
||||
@@ -154,7 +159,7 @@ func TempFile(fs billy.Basic, dir, prefix string) (f billy.File, err error) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
name := filepath.Join(dir, prefix+nextSuffix())
|
||||
f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
|
||||
if os.IsExist(err) {
|
||||
if errors.Is(err, os.ErrExist) {
|
||||
if nconflict++; nconflict > 10 {
|
||||
randmu.Lock()
|
||||
rand = reseed()
|
||||
@@ -185,7 +190,7 @@ func TempDir(fs billy.Dir, dir, prefix string) (name string, err error) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
try := filepath.Join(dir, prefix+nextSuffix())
|
||||
err = fs.MkdirAll(try, 0700)
|
||||
if os.IsExist(err) {
|
||||
if errors.Is(err, os.ErrExist) {
|
||||
if nconflict++; nconflict > 10 {
|
||||
randmu.Lock()
|
||||
rand = reseed()
|
||||
@@ -193,8 +198,8 @@ func TempDir(fs billy.Dir, dir, prefix string) (name string, err error) {
|
||||
}
|
||||
continue
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
if _, err := os.Stat(dir); errors.Is(err, os.ErrNotExist) {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
@@ -272,7 +277,7 @@ func ReadFile(fs billy.Basic, name string) ([]byte, error) {
|
||||
data = data[:len(data)+n]
|
||||
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if errors.Is(err, io.EOF) {
|
||||
err = nil
|
||||
}
|
||||
|
||||
|
||||
19
vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md
generated
vendored
19
vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md
generated
vendored
@@ -11,7 +11,7 @@ compatibility status with go-git.
|
||||
| `init` | `--bare` | ✅ | | |
|
||||
| `init` | `--template` <br/> `--separate-git-dir` <br/> `--shared` | ❌ | | |
|
||||
| `clone` | | ✅ | | - [PlainClone](_examples/clone/main.go) |
|
||||
| `clone` | Authentication: <br/> - none <br/> - access token <br/> - username + password <br/> - ssh | ✅ | | - [clone ssh](_examples/clone/auth/ssh/main.go) <br/> - [clone access token](_examples/clone/auth/basic/access_token/main.go) <br/> - [clone user + password](_examples/clone/auth/basic/username_password/main.go) |
|
||||
| `clone` | Authentication: <br/> - none <br/> - access token <br/> - username + password <br/> - ssh | ✅ | | - [clone ssh (private_key)](_examples/clone/auth/ssh/private_key/main.go) <br/> - [clone ssh (ssh_agent)](_examples/clone/auth/ssh/ssh_agent/main.go) <br/> - [clone access token](_examples/clone/auth/basic/access_token/main.go) <br/> - [clone user + password](_examples/clone/auth/basic/username_password/main.go) |
|
||||
| `clone` | `--progress` <br/> `--single-branch` <br/> `--depth` <br/> `--origin` <br/> `--recurse-submodules` <br/>`--shared` | ✅ | | - [recurse submodules](_examples/clone/main.go) <br/> - [progress](_examples/progress/main.go) |
|
||||
|
||||
## Basic snapshotting
|
||||
@@ -27,14 +27,15 @@ compatibility status with go-git.
|
||||
|
||||
## Branching and merging
|
||||
|
||||
| Feature | Sub-feature | Status | Notes | Examples |
|
||||
| ----------- | ----------- | ------ | --------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `branch` | | ✅ | | - [branch](_examples/branch/main.go) |
|
||||
| `checkout` | | ✅ | Basic usages of checkout are supported. | - [checkout](_examples/checkout/main.go) |
|
||||
| `merge` | | ❌ | | |
|
||||
| `mergetool` | | ❌ | | |
|
||||
| `stash` | | ❌ | | |
|
||||
| `tag` | | ✅ | | - [tag](_examples/tag/main.go) <br/> - [tag create and push](_examples/tag-create-push/main.go) |
|
||||
| Feature | Sub-feature | Status | Notes | Examples |
|
||||
| ----------- | ----------- | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `branch` | | ✅ | | - [branch](_examples/branch/main.go) |
|
||||
| `checkout` | | ✅ | Basic usages of checkout are supported. | - [checkout](_examples/checkout/main.go) |
|
||||
| `merge` | | ⚠️ (partial) | Fast-forward only | |
|
||||
| `mergetool` | | ❌ | | |
|
||||
| `stash` | | ❌ | | |
|
||||
| `sparse-checkout` | | ✅ | | - [sparse-checkout](_examples/sparse-checkout/main.go) |
|
||||
| `tag` | | ✅ | | - [tag](_examples/tag/main.go) <br/> - [tag create and push](_examples/tag-create-push/main.go) |
|
||||
|
||||
## Sharing and updating projects
|
||||
|
||||
|
||||
7
vendor/github.com/go-git/go-git/v5/CONTRIBUTING.md
generated
vendored
7
vendor/github.com/go-git/go-git/v5/CONTRIBUTING.md
generated
vendored
@@ -31,6 +31,13 @@ In order for a PR to be accepted it needs to pass a list of requirements:
|
||||
- If the PR is a new feature, it has to come with a suite of unit tests, that tests the new functionality.
|
||||
- In any case, all the PRs have to pass the personal evaluation of at least one of the maintainers of go-git.
|
||||
|
||||
### Branches
|
||||
|
||||
The `master` branch is currently used for maintaining the `v5` major release only. The accepted changes would
|
||||
be dependency bumps, bug fixes and small changes that aren't needed for `v6`. New development should target the
|
||||
`v6-exp` branch, and if agreed with at least one go-git maintainer, it can be back ported to `v5` by creating
|
||||
a new PR that targets `master`.
|
||||
|
||||
### Format of the commit message
|
||||
|
||||
Every commit message should describe what was changed, under which context and, if applicable, the GitHub issue it relates to:
|
||||
|
||||
1
vendor/github.com/go-git/go-git/v5/Makefile
generated
vendored
1
vendor/github.com/go-git/go-git/v5/Makefile
generated
vendored
@@ -28,6 +28,7 @@ build-git:
|
||||
test:
|
||||
@echo "running against `git version`"; \
|
||||
$(GOTEST) -race ./...
|
||||
$(GOTEST) -v _examples/common_test.go _examples/common.go --examples
|
||||
|
||||
TEMP_REPO := $(shell mktemp)
|
||||
test-sha256:
|
||||
|
||||
13
vendor/github.com/go-git/go-git/v5/blame.go
generated
vendored
13
vendor/github.com/go-git/go-git/v5/blame.go
generated
vendored
@@ -97,13 +97,10 @@ func Blame(c *object.Commit, path string) (*BlameResult, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if finished == true {
|
||||
if finished {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.lineToCommit = make([]*object.Commit, finalLength)
|
||||
for i := range needsMap {
|
||||
@@ -309,8 +306,8 @@ func (b *blame) addBlames(curItems []*queueItem) (bool, error) {
|
||||
for h := range hunks {
|
||||
hLines := countLines(hunks[h].Text)
|
||||
for hl := 0; hl < hLines; hl++ {
|
||||
switch {
|
||||
case hunks[h].Type == diffmatchpatch.DiffEqual:
|
||||
switch hunks[h].Type {
|
||||
case diffmatchpatch.DiffEqual:
|
||||
prevl++
|
||||
curl++
|
||||
if curl == curItem.NeedsMap[need].Cur {
|
||||
@@ -322,7 +319,7 @@ func (b *blame) addBlames(curItems []*queueItem) (bool, error) {
|
||||
break out
|
||||
}
|
||||
}
|
||||
case hunks[h].Type == diffmatchpatch.DiffInsert:
|
||||
case diffmatchpatch.DiffInsert:
|
||||
curl++
|
||||
if curl == curItem.NeedsMap[need].Cur {
|
||||
// the line we want is added, it may have been added here (or by another parent), skip it for now
|
||||
@@ -331,7 +328,7 @@ func (b *blame) addBlames(curItems []*queueItem) (bool, error) {
|
||||
break out
|
||||
}
|
||||
}
|
||||
case hunks[h].Type == diffmatchpatch.DiffDelete:
|
||||
case diffmatchpatch.DiffDelete:
|
||||
prevl += hLines
|
||||
continue out
|
||||
default:
|
||||
|
||||
2
vendor/github.com/go-git/go-git/v5/config/config.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/config/config.go
generated
vendored
@@ -252,6 +252,7 @@ const (
|
||||
extensionsSection = "extensions"
|
||||
fetchKey = "fetch"
|
||||
urlKey = "url"
|
||||
pushurlKey = "pushurl"
|
||||
bareKey = "bare"
|
||||
worktreeKey = "worktree"
|
||||
commentCharKey = "commentChar"
|
||||
@@ -633,6 +634,7 @@ func (c *RemoteConfig) unmarshal(s *format.Subsection) error {
|
||||
|
||||
c.Name = c.raw.Name
|
||||
c.URLs = append([]string(nil), c.raw.Options.GetAll(urlKey)...)
|
||||
c.URLs = append(c.URLs, c.raw.Options.GetAll(pushurlKey)...)
|
||||
c.Fetch = fetch
|
||||
c.Mirror = c.raw.Options.Get(mirrorKey) == "true"
|
||||
|
||||
|
||||
7
vendor/github.com/go-git/go-git/v5/internal/revision/scanner.go
generated
vendored
7
vendor/github.com/go-git/go-git/v5/internal/revision/scanner.go
generated
vendored
@@ -43,6 +43,11 @@ func tokenizeExpression(ch rune, tokenType token, check runeCategoryValidator, r
|
||||
return tokenType, string(data), nil
|
||||
}
|
||||
|
||||
// maxRevisionLength holds the maximum length that will be parsed for a
|
||||
// revision. Git itself doesn't enforce a max length, but rather leans on
|
||||
// the OS to enforce it via its ARG_MAX.
|
||||
const maxRevisionLength = 128 * 1024 // 128kb
|
||||
|
||||
var zeroRune = rune(0)
|
||||
|
||||
// scanner represents a lexical scanner.
|
||||
@@ -52,7 +57,7 @@ type scanner struct {
|
||||
|
||||
// newScanner returns a new instance of scanner.
|
||||
func newScanner(r io.Reader) *scanner {
|
||||
return &scanner{r: bufio.NewReader(r)}
|
||||
return &scanner{r: bufio.NewReader(io.LimitReader(r, maxRevisionLength))}
|
||||
}
|
||||
|
||||
// Scan extracts tokens and their strings counterpart
|
||||
|
||||
126
vendor/github.com/go-git/go-git/v5/options.go
generated
vendored
126
vendor/github.com/go-git/go-git/v5/options.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
formatcfg "github.com/go-git/go-git/v5/plumbing/format/config"
|
||||
@@ -72,9 +73,16 @@ 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 skips SSL verification if protocol is HTTPS.
|
||||
InsecureSkipTLS bool
|
||||
// CABundle specify additional ca bundle with system cert pool
|
||||
// ClientCert is the client certificate to use for mutual TLS authentication
|
||||
// over the HTTPS protocol.
|
||||
ClientCert []byte
|
||||
// ClientKey is the client key to use for mutual TLS authentication over
|
||||
// the HTTPS protocol.
|
||||
ClientKey []byte
|
||||
// CABundle specifies an additional CA bundle to use together with the
|
||||
// system cert pool.
|
||||
CABundle []byte
|
||||
// ProxyOptions provides info required for connecting to a proxy.
|
||||
ProxyOptions transport.ProxyOptions
|
||||
@@ -89,6 +97,25 @@ type CloneOptions struct {
|
||||
Shared bool
|
||||
}
|
||||
|
||||
// MergeOptions describes how a merge should be performed.
|
||||
type MergeOptions struct {
|
||||
// Strategy defines the merge strategy to be used.
|
||||
Strategy MergeStrategy
|
||||
}
|
||||
|
||||
// MergeStrategy represents the different types of merge strategies.
|
||||
type MergeStrategy int8
|
||||
|
||||
const (
|
||||
// FastForwardMerge represents a Git merge strategy where the current
|
||||
// branch can be simply updated to point to the HEAD of the branch being
|
||||
// merged. This is only possible if the history of the branch being merged
|
||||
// is a linear descendant of the current branch, with no conflicting commits.
|
||||
//
|
||||
// This is the default option.
|
||||
FastForwardMerge MergeStrategy = iota
|
||||
)
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
func (o *CloneOptions) Validate() error {
|
||||
if o.URL == "" {
|
||||
@@ -134,9 +161,16 @@ 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 skips SSL verification if protocol is HTTPS.
|
||||
InsecureSkipTLS bool
|
||||
// CABundle specify additional ca bundle with system cert pool
|
||||
// ClientCert is the client certificate to use for mutual TLS authentication
|
||||
// over the HTTPS protocol.
|
||||
ClientCert []byte
|
||||
// ClientKey is the client key to use for mutual TLS authentication over
|
||||
// the HTTPS protocol.
|
||||
ClientKey []byte
|
||||
// CABundle specifies an additional CA bundle to use together with the
|
||||
// system cert pool.
|
||||
CABundle []byte
|
||||
// ProxyOptions provides info required for connecting to a proxy.
|
||||
ProxyOptions transport.ProxyOptions
|
||||
@@ -166,7 +200,7 @@ const (
|
||||
// AllTags fetch all tags from the remote (i.e., fetch remote tags
|
||||
// refs/tags/* into local tags with the same name)
|
||||
AllTags
|
||||
//NoTags fetch no tags from the remote at all
|
||||
// NoTags fetch no tags from the remote at all
|
||||
NoTags
|
||||
)
|
||||
|
||||
@@ -192,12 +226,22 @@ 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 skips SSL verification if protocol is HTTPS.
|
||||
InsecureSkipTLS bool
|
||||
// CABundle specify additional ca bundle with system cert pool
|
||||
// ClientCert is the client certificate to use for mutual TLS authentication
|
||||
// over the HTTPS protocol.
|
||||
ClientCert []byte
|
||||
// ClientKey is the client key to use for mutual TLS authentication over
|
||||
// the HTTPS protocol.
|
||||
ClientKey []byte
|
||||
// CABundle specifies an additional CA bundle to use together with the
|
||||
// system cert pool.
|
||||
CABundle []byte
|
||||
// ProxyOptions provides info required for connecting to a proxy.
|
||||
ProxyOptions transport.ProxyOptions
|
||||
// Prune specify that local refs that match given RefSpecs and that do
|
||||
// not exist remotely will be removed.
|
||||
Prune bool
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
@@ -245,9 +289,16 @@ type PushOptions struct {
|
||||
// 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 protocol is https
|
||||
// InsecureSkipTLS skips SSL verification if protocol is HTTPS.
|
||||
InsecureSkipTLS bool
|
||||
// CABundle specify additional ca bundle with system cert pool
|
||||
// ClientCert is the client certificate to use for mutual TLS authentication
|
||||
// over the HTTPS protocol.
|
||||
ClientCert []byte
|
||||
// ClientKey is the client key to use for mutual TLS authentication over
|
||||
// the HTTPS protocol.
|
||||
ClientKey []byte
|
||||
// CABundle specifies an additional CA bundle to use together with the
|
||||
// system cert pool.
|
||||
CABundle []byte
|
||||
// RequireRemoteRefs only allows a remote ref to be updated if its current
|
||||
// value is the one specified here.
|
||||
@@ -324,9 +375,9 @@ var (
|
||||
|
||||
// CheckoutOptions describes how a checkout operation should be performed.
|
||||
type CheckoutOptions struct {
|
||||
// Hash is the hash of the commit to be checked out. If used, HEAD will be
|
||||
// in detached mode. If Create is not used, Branch and Hash are mutually
|
||||
// exclusive.
|
||||
// Hash is the hash of a commit or tag to be checked out. If used, HEAD
|
||||
// will be in detached mode. If Create is not used, Branch and Hash are
|
||||
// mutually exclusive.
|
||||
Hash plumbing.Hash
|
||||
// Branch to be checked out, if Branch and Hash are empty is set to `master`.
|
||||
Branch plumbing.ReferenceName
|
||||
@@ -394,6 +445,9 @@ type ResetOptions struct {
|
||||
// the index (resetting it to the tree of Commit) and the working tree
|
||||
// depending on Mode. If empty MixedReset is used.
|
||||
Mode ResetMode
|
||||
// Files, if not empty will constrain the reseting the index to only files
|
||||
// specified in this list.
|
||||
Files []string
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
@@ -405,6 +459,11 @@ func (o *ResetOptions) Validate(r *Repository) error {
|
||||
}
|
||||
|
||||
o.Commit = ref.Hash()
|
||||
} else {
|
||||
_, err := r.CommitObject(o.Commit)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid reset option: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -474,6 +533,11 @@ type AddOptions struct {
|
||||
// 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
|
||||
// SkipStatus adds the path with no status check. This option is relevant only
|
||||
// when the `Path` option is specified and does not apply when the `All` option is used.
|
||||
// Notice that when passing an ignored path it will be added anyway.
|
||||
// When true it can speed up adding files to the worktree in very large repositories.
|
||||
SkipStatus bool
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
@@ -507,6 +571,10 @@ type CommitOptions struct {
|
||||
// commit will not be signed. The private key must be present and already
|
||||
// decrypted.
|
||||
SignKey *openpgp.Entity
|
||||
// Signer denotes a cryptographic signer to sign the commit with.
|
||||
// A nil value here means the commit will not be signed.
|
||||
// Takes precedence over SignKey.
|
||||
Signer Signer
|
||||
// Amend will create a new commit object and replace the commit that HEAD currently
|
||||
// points to. Cannot be used with All nor Parents.
|
||||
Amend bool
|
||||
@@ -654,9 +722,16 @@ func (o *CreateTagOptions) loadConfigTagger(r *Repository) error {
|
||||
type ListOptions struct {
|
||||
// Auth credentials, if required, to use with the remote repository.
|
||||
Auth transport.AuthMethod
|
||||
// InsecureSkipTLS skips ssl verify if protocol is https
|
||||
// InsecureSkipTLS skips SSL verification if protocol is HTTPS.
|
||||
InsecureSkipTLS bool
|
||||
// CABundle specify additional ca bundle with system cert pool
|
||||
// ClientCert is the client certificate to use for mutual TLS authentication
|
||||
// over the HTTPS protocol.
|
||||
ClientCert []byte
|
||||
// ClientKey is the client key to use for mutual TLS authentication over
|
||||
// the HTTPS protocol.
|
||||
ClientKey []byte
|
||||
// CABundle specifies an additional CA bundle to use together with the
|
||||
// system cert pool.
|
||||
CABundle []byte
|
||||
// PeelingOption defines how peeled objects are handled during a
|
||||
// remote list.
|
||||
@@ -754,3 +829,26 @@ type PlainInitOptions struct {
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
func (o *PlainInitOptions) Validate() error { return nil }
|
||||
|
||||
var (
|
||||
ErrNoRestorePaths = errors.New("you must specify path(s) to restore")
|
||||
)
|
||||
|
||||
// RestoreOptions describes how a restore should be performed.
|
||||
type RestoreOptions struct {
|
||||
// Marks to restore the content in the index
|
||||
Staged bool
|
||||
// Marks to restore the content of the working tree
|
||||
Worktree bool
|
||||
// List of file paths that will be restored
|
||||
Files []string
|
||||
}
|
||||
|
||||
// Validate validates the fields and sets the default values.
|
||||
func (o *RestoreOptions) Validate() error {
|
||||
if len(o.Files) == 0 {
|
||||
return ErrNoRestorePaths
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
8
vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go
generated
vendored
8
vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go
generated
vendored
@@ -64,6 +64,10 @@ func ReadPatterns(fs billy.Filesystem, path []string) (ps []Pattern, err error)
|
||||
|
||||
for _, fi := range fis {
|
||||
if fi.IsDir() && fi.Name() != gitDir {
|
||||
if NewMatcher(ps).Match(append(path, fi.Name()), true) {
|
||||
continue
|
||||
}
|
||||
|
||||
var subps []Pattern
|
||||
subps, err = ReadPatterns(fs, append(path, fi.Name()))
|
||||
if err != nil {
|
||||
@@ -116,7 +120,7 @@ func loadPatterns(fs billy.Filesystem, path string) (ps []Pattern, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// LoadGlobalPatterns loads gitignore patterns from from the gitignore file
|
||||
// LoadGlobalPatterns loads gitignore patterns from the gitignore file
|
||||
// declared in a user's ~/.gitconfig file. If the ~/.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
|
||||
@@ -132,7 +136,7 @@ func LoadGlobalPatterns(fs billy.Filesystem) (ps []Pattern, err error) {
|
||||
return loadPatterns(fs, fs.Join(home, gitconfigFile))
|
||||
}
|
||||
|
||||
// LoadSystemPatterns loads gitignore patterns from from the gitignore file
|
||||
// LoadSystemPatterns loads gitignore patterns from the gitignore file
|
||||
// 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
|
||||
|
||||
31
vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go
generated
vendored
31
vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go
generated
vendored
@@ -1,9 +1,11 @@
|
||||
package idxfile
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/hash"
|
||||
@@ -25,12 +27,15 @@ const (
|
||||
|
||||
// Decoder reads and decodes idx files from an input stream.
|
||||
type Decoder struct {
|
||||
*bufio.Reader
|
||||
io.Reader
|
||||
h hash.Hash
|
||||
}
|
||||
|
||||
// NewDecoder builds a new idx stream decoder, that reads from r.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
return &Decoder{bufio.NewReader(r)}
|
||||
h := hash.New(crypto.SHA1)
|
||||
tr := io.TeeReader(r, h)
|
||||
return &Decoder{tr, h}
|
||||
}
|
||||
|
||||
// Decode reads from the stream and decode the content into the MemoryIndex struct.
|
||||
@@ -45,7 +50,7 @@ func (d *Decoder) Decode(idx *MemoryIndex) error {
|
||||
readObjectNames,
|
||||
readCRC32,
|
||||
readOffsets,
|
||||
readChecksums,
|
||||
readPackChecksum,
|
||||
}
|
||||
|
||||
for _, f := range flow {
|
||||
@@ -54,11 +59,21 @@ func (d *Decoder) Decode(idx *MemoryIndex) error {
|
||||
}
|
||||
}
|
||||
|
||||
actual := d.h.Sum(nil)
|
||||
if err := readIdxChecksum(idx, d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !bytes.Equal(actual, idx.IdxChecksum[:]) {
|
||||
return fmt.Errorf("%w: checksum mismatch: %q instead of %q",
|
||||
ErrMalformedIdxFile, hex.EncodeToString(idx.IdxChecksum[:]), hex.EncodeToString(actual))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateHeader(r io.Reader) error {
|
||||
var h = make([]byte, 4)
|
||||
h := make([]byte, 4)
|
||||
if _, err := io.ReadFull(r, h); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -165,11 +180,15 @@ func readOffsets(idx *MemoryIndex, r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func readChecksums(idx *MemoryIndex, r io.Reader) error {
|
||||
func readPackChecksum(idx *MemoryIndex, r io.Reader) error {
|
||||
if _, err := io.ReadFull(r, idx.PackfileChecksum[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readIdxChecksum(idx *MemoryIndex, r io.Reader) error {
|
||||
if _, err := io.ReadFull(r, idx.IdxChecksum[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
48
vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/idxfile.go
generated
vendored
48
vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/idxfile.go
generated
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"io"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
encbin "encoding/binary"
|
||||
|
||||
@@ -57,8 +58,9 @@ type MemoryIndex struct {
|
||||
PackfileChecksum [hash.Size]byte
|
||||
IdxChecksum [hash.Size]byte
|
||||
|
||||
offsetHash map[int64]plumbing.Hash
|
||||
offsetHashIsFull bool
|
||||
offsetHash map[int64]plumbing.Hash
|
||||
offsetBuildOnce sync.Once
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
var _ Index = (*MemoryIndex)(nil)
|
||||
@@ -126,13 +128,13 @@ func (idx *MemoryIndex) FindOffset(h plumbing.Hash) (int64, error) {
|
||||
|
||||
offset := idx.getOffset(k, i)
|
||||
|
||||
if !idx.offsetHashIsFull {
|
||||
// Save the offset for reverse lookup
|
||||
if idx.offsetHash == nil {
|
||||
idx.offsetHash = make(map[int64]plumbing.Hash)
|
||||
}
|
||||
idx.offsetHash[int64(offset)] = h
|
||||
// Save the offset for reverse lookup
|
||||
idx.mu.Lock()
|
||||
if idx.offsetHash == nil {
|
||||
idx.offsetHash = make(map[int64]plumbing.Hash)
|
||||
}
|
||||
idx.offsetHash[int64(offset)] = h
|
||||
idx.mu.Unlock()
|
||||
|
||||
return int64(offset), nil
|
||||
}
|
||||
@@ -173,20 +175,17 @@ func (idx *MemoryIndex) FindHash(o int64) (plumbing.Hash, error) {
|
||||
var hash plumbing.Hash
|
||||
var ok bool
|
||||
|
||||
if idx.offsetHash != nil {
|
||||
if hash, ok = idx.offsetHash[o]; ok {
|
||||
return hash, nil
|
||||
}
|
||||
var genErr error
|
||||
idx.offsetBuildOnce.Do(func() {
|
||||
genErr = idx.genOffsetHash()
|
||||
})
|
||||
if genErr != nil {
|
||||
return plumbing.ZeroHash, genErr
|
||||
}
|
||||
|
||||
// Lazily generate the reverse offset/hash map if required.
|
||||
if !idx.offsetHashIsFull || idx.offsetHash == nil {
|
||||
if err := idx.genOffsetHash(); err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
hash, ok = idx.offsetHash[o]
|
||||
}
|
||||
idx.mu.RLock()
|
||||
hash, ok = idx.offsetHash[o]
|
||||
idx.mu.RUnlock()
|
||||
|
||||
if !ok {
|
||||
return plumbing.ZeroHash, plumbing.ErrObjectNotFound
|
||||
@@ -202,8 +201,7 @@ func (idx *MemoryIndex) genOffsetHash() error {
|
||||
return err
|
||||
}
|
||||
|
||||
idx.offsetHash = make(map[int64]plumbing.Hash, count)
|
||||
idx.offsetHashIsFull = true
|
||||
offsetHash := make(map[int64]plumbing.Hash, count)
|
||||
|
||||
var hash plumbing.Hash
|
||||
i := uint32(0)
|
||||
@@ -212,11 +210,15 @@ func (idx *MemoryIndex) genOffsetHash() error {
|
||||
for secondLevel := uint32(0); i < fanoutValue; i++ {
|
||||
copy(hash[:], idx.Names[mappedFirstLevel][secondLevel*objectIDLength:])
|
||||
offset := int64(idx.getOffset(mappedFirstLevel, int(secondLevel)))
|
||||
idx.offsetHash[offset] = hash
|
||||
offsetHash[offset] = hash
|
||||
secondLevel++
|
||||
}
|
||||
}
|
||||
|
||||
idx.mu.Lock()
|
||||
idx.offsetHash = offsetHash
|
||||
idx.mu.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
115
vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go
generated
vendored
115
vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go
generated
vendored
@@ -24,8 +24,8 @@ var (
|
||||
// ErrInvalidChecksum is returned by Decode if the SHA1 hash mismatch with
|
||||
// the read content
|
||||
ErrInvalidChecksum = errors.New("invalid checksum")
|
||||
|
||||
errUnknownExtension = errors.New("unknown extension")
|
||||
// ErrUnknownExtension is returned when an index extension is encountered that is considered mandatory
|
||||
ErrUnknownExtension = errors.New("unknown extension")
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -39,6 +39,7 @@ const (
|
||||
|
||||
// A Decoder reads and decodes index files from an input stream.
|
||||
type Decoder struct {
|
||||
buf *bufio.Reader
|
||||
r io.Reader
|
||||
hash hash.Hash
|
||||
lastEntry *Entry
|
||||
@@ -49,8 +50,10 @@ type Decoder struct {
|
||||
// NewDecoder returns a new decoder that reads from r.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
h := hash.New(hash.CryptoType)
|
||||
buf := bufio.NewReader(r)
|
||||
return &Decoder{
|
||||
r: io.TeeReader(r, h),
|
||||
buf: buf,
|
||||
r: io.TeeReader(buf, h),
|
||||
hash: h,
|
||||
extReader: bufio.NewReader(nil),
|
||||
}
|
||||
@@ -210,71 +213,75 @@ func (d *Decoder) readExtensions(idx *Index) error {
|
||||
// count that they are not supported by jgit or libgit
|
||||
|
||||
var expected []byte
|
||||
var peeked []byte
|
||||
var err error
|
||||
|
||||
var header [4]byte
|
||||
// we should always be able to peek for 4 bytes (header) + 4 bytes (extlen) + final hash
|
||||
// if this fails, we know that we're at the end of the index
|
||||
peekLen := 4 + 4 + d.hash.Size()
|
||||
|
||||
for {
|
||||
expected = d.hash.Sum(nil)
|
||||
|
||||
var n int
|
||||
if n, err = io.ReadFull(d.r, header[:]); err != nil {
|
||||
if n == 0 {
|
||||
err = io.EOF
|
||||
}
|
||||
|
||||
peeked, err = d.buf.Peek(peekLen)
|
||||
if len(peeked) < peekLen {
|
||||
// there can't be an extension at this point, so let's bail out
|
||||
break
|
||||
}
|
||||
|
||||
err = d.readExtension(idx, header[:])
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err != errUnknownExtension {
|
||||
return err
|
||||
}
|
||||
|
||||
return d.readChecksum(expected, header)
|
||||
}
|
||||
|
||||
func (d *Decoder) readExtension(idx *Index, header []byte) error {
|
||||
switch {
|
||||
case bytes.Equal(header, treeExtSignature):
|
||||
r, err := d.getExtensionReader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = d.readExtension(idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return d.readChecksum(expected)
|
||||
}
|
||||
|
||||
func (d *Decoder) readExtension(idx *Index) error {
|
||||
var header [4]byte
|
||||
|
||||
if _, err := io.ReadFull(d.r, header[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := d.getExtensionReader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch {
|
||||
case bytes.Equal(header[:], treeExtSignature):
|
||||
idx.Cache = &Tree{}
|
||||
d := &treeExtensionDecoder{r}
|
||||
if err := d.Decode(idx.Cache); err != nil {
|
||||
return err
|
||||
}
|
||||
case bytes.Equal(header, resolveUndoExtSignature):
|
||||
r, err := d.getExtensionReader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case bytes.Equal(header[:], resolveUndoExtSignature):
|
||||
idx.ResolveUndo = &ResolveUndo{}
|
||||
d := &resolveUndoDecoder{r}
|
||||
if err := d.Decode(idx.ResolveUndo); err != nil {
|
||||
return err
|
||||
}
|
||||
case bytes.Equal(header, endOfIndexEntryExtSignature):
|
||||
r, err := d.getExtensionReader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case bytes.Equal(header[:], endOfIndexEntryExtSignature):
|
||||
idx.EndOfIndexEntry = &EndOfIndexEntry{}
|
||||
d := &endOfIndexEntryDecoder{r}
|
||||
if err := d.Decode(idx.EndOfIndexEntry); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errUnknownExtension
|
||||
// See https://git-scm.com/docs/index-format, which says:
|
||||
// If the first byte is 'A'..'Z' the extension is optional and can be ignored.
|
||||
if header[0] < 'A' || header[0] > 'Z' {
|
||||
return ErrUnknownExtension
|
||||
}
|
||||
|
||||
d := &unknownExtensionDecoder{r}
|
||||
if err := d.Decode(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -290,11 +297,10 @@ func (d *Decoder) getExtensionReader() (*bufio.Reader, error) {
|
||||
return d.extReader, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) readChecksum(expected []byte, alreadyRead [4]byte) error {
|
||||
func (d *Decoder) readChecksum(expected []byte) error {
|
||||
var h plumbing.Hash
|
||||
copy(h[:4], alreadyRead[:])
|
||||
|
||||
if _, err := io.ReadFull(d.r, h[4:]); err != nil {
|
||||
if _, err := io.ReadFull(d.r, h[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -476,3 +482,22 @@ func (d *endOfIndexEntryDecoder) Decode(e *EndOfIndexEntry) error {
|
||||
_, err = io.ReadFull(d.r, e.Hash[:])
|
||||
return err
|
||||
}
|
||||
|
||||
type unknownExtensionDecoder struct {
|
||||
r *bufio.Reader
|
||||
}
|
||||
|
||||
func (d *unknownExtensionDecoder) Decode() error {
|
||||
var buf [1024]byte
|
||||
|
||||
for {
|
||||
_, err := d.r.Read(buf[:])
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
94
vendor/github.com/go-git/go-git/v5/plumbing/format/index/encoder.go
generated
vendored
94
vendor/github.com/go-git/go-git/v5/plumbing/format/index/encoder.go
generated
vendored
@@ -3,8 +3,11 @@ package index
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/hash"
|
||||
@@ -13,7 +16,7 @@ import (
|
||||
|
||||
var (
|
||||
// EncodeVersionSupported is the range of supported index versions
|
||||
EncodeVersionSupported uint32 = 3
|
||||
EncodeVersionSupported uint32 = 4
|
||||
|
||||
// ErrInvalidTimestamp is returned by Encode if a Index with a Entry with
|
||||
// negative timestamp values
|
||||
@@ -22,20 +25,25 @@ var (
|
||||
|
||||
// An Encoder writes an Index to an output stream.
|
||||
type Encoder struct {
|
||||
w io.Writer
|
||||
hash hash.Hash
|
||||
w io.Writer
|
||||
hash hash.Hash
|
||||
lastEntry *Entry
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
h := hash.New(hash.CryptoType)
|
||||
mw := io.MultiWriter(w, h)
|
||||
return &Encoder{mw, h}
|
||||
return &Encoder{mw, h, nil}
|
||||
}
|
||||
|
||||
// Encode writes the Index to the stream of the encoder.
|
||||
func (e *Encoder) Encode(idx *Index) error {
|
||||
// TODO: support v4
|
||||
return e.encode(idx, true)
|
||||
}
|
||||
|
||||
func (e *Encoder) encode(idx *Index, footer bool) error {
|
||||
|
||||
// TODO: support extensions
|
||||
if idx.Version > EncodeVersionSupported {
|
||||
return ErrUnsupportedVersion
|
||||
@@ -49,7 +57,10 @@ func (e *Encoder) Encode(idx *Index) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.encodeFooter()
|
||||
if footer {
|
||||
return e.encodeFooter()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeHeader(idx *Index) error {
|
||||
@@ -64,7 +75,7 @@ func (e *Encoder) encodeEntries(idx *Index) error {
|
||||
sort.Sort(byName(idx.Entries))
|
||||
|
||||
for _, entry := range idx.Entries {
|
||||
if err := e.encodeEntry(entry); err != nil {
|
||||
if err := e.encodeEntry(idx, entry); err != nil {
|
||||
return err
|
||||
}
|
||||
entryLength := entryHeaderLength
|
||||
@@ -73,7 +84,7 @@ func (e *Encoder) encodeEntries(idx *Index) error {
|
||||
}
|
||||
|
||||
wrote := entryLength + len(entry.Name)
|
||||
if err := e.padEntry(wrote); err != nil {
|
||||
if err := e.padEntry(idx, wrote); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -81,7 +92,7 @@ func (e *Encoder) encodeEntries(idx *Index) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeEntry(entry *Entry) error {
|
||||
func (e *Encoder) encodeEntry(idx *Index, entry *Entry) error {
|
||||
sec, nsec, err := e.timeToUint32(&entry.CreatedAt)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -132,9 +143,68 @@ func (e *Encoder) encodeEntry(entry *Entry) error {
|
||||
return err
|
||||
}
|
||||
|
||||
switch idx.Version {
|
||||
case 2, 3:
|
||||
err = e.encodeEntryName(entry)
|
||||
case 4:
|
||||
err = e.encodeEntryNameV4(entry)
|
||||
default:
|
||||
err = ErrUnsupportedVersion
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeEntryName(entry *Entry) error {
|
||||
return binary.Write(e.w, []byte(entry.Name))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeEntryNameV4(entry *Entry) error {
|
||||
name := entry.Name
|
||||
l := 0
|
||||
if e.lastEntry != nil {
|
||||
dir := path.Dir(e.lastEntry.Name) + "/"
|
||||
if strings.HasPrefix(entry.Name, dir) {
|
||||
l = len(e.lastEntry.Name) - len(dir)
|
||||
name = strings.TrimPrefix(entry.Name, dir)
|
||||
} else {
|
||||
l = len(e.lastEntry.Name)
|
||||
}
|
||||
}
|
||||
|
||||
e.lastEntry = entry
|
||||
|
||||
err := binary.WriteVariableWidthInt(e.w, int64(l))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return binary.Write(e.w, []byte(name+string('\x00')))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeRawExtension(signature string, data []byte) error {
|
||||
if len(signature) != 4 {
|
||||
return fmt.Errorf("invalid signature length")
|
||||
}
|
||||
|
||||
_, err := e.w.Write([]byte(signature))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = binary.WriteUint32(e.w, uint32(len(data)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = e.w.Write(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) timeToUint32(t *time.Time) (uint32, uint32, error) {
|
||||
if t.IsZero() {
|
||||
return 0, 0, nil
|
||||
@@ -147,7 +217,11 @@ func (e *Encoder) timeToUint32(t *time.Time) (uint32, uint32, error) {
|
||||
return uint32(t.Unix()), uint32(t.Nanosecond()), nil
|
||||
}
|
||||
|
||||
func (e *Encoder) padEntry(wrote int) error {
|
||||
func (e *Encoder) padEntry(idx *Index, wrote int) error {
|
||||
if idx.Version == 4 {
|
||||
return nil
|
||||
}
|
||||
|
||||
padLen := 8 - wrote%8
|
||||
|
||||
_, err := e.w.Write(bytes.Repeat([]byte{'\x00'}, padLen))
|
||||
|
||||
2
vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go
generated
vendored
@@ -30,7 +30,7 @@ type Reader struct {
|
||||
func NewReader(r io.Reader) (*Reader, error) {
|
||||
zlib, err := sync.GetZlibReader(r)
|
||||
if err != nil {
|
||||
return nil, packfile.ErrZLib.AddDetails(err.Error())
|
||||
return nil, packfile.ErrZLib.AddDetails("%s", err.Error())
|
||||
}
|
||||
|
||||
return &Reader{
|
||||
|
||||
20
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_index.go
generated
vendored
20
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_index.go
generated
vendored
@@ -32,19 +32,17 @@ func (idx *deltaIndex) findMatch(src, tgt []byte, tgtOffset int) (srcOffset, l i
|
||||
return 0, -1
|
||||
}
|
||||
|
||||
if len(tgt) >= tgtOffset+s && len(src) >= blksz {
|
||||
h := hashBlock(tgt, tgtOffset)
|
||||
tIdx := h & idx.mask
|
||||
eIdx := idx.table[tIdx]
|
||||
if eIdx != 0 {
|
||||
srcOffset = idx.entries[eIdx]
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
l = matchLength(src, tgt, tgtOffset, srcOffset)
|
||||
h := hashBlock(tgt, tgtOffset)
|
||||
tIdx := h & idx.mask
|
||||
eIdx := idx.table[tIdx]
|
||||
if eIdx == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
srcOffset = idx.entries[eIdx]
|
||||
|
||||
l = matchLength(src, tgt, tgtOffset, srcOffset)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
36
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go
generated
vendored
36
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go
generated
vendored
@@ -47,7 +47,6 @@ type Parser struct {
|
||||
oi []*objectInfo
|
||||
oiByHash map[plumbing.Hash]*objectInfo
|
||||
oiByOffset map[int64]*objectInfo
|
||||
checksum plumbing.Hash
|
||||
|
||||
cache *cache.BufferLRU
|
||||
// delta content by offset, only used if source is not seekable
|
||||
@@ -133,28 +132,27 @@ func (p *Parser) onFooter(h plumbing.Hash) error {
|
||||
// Parse start decoding phase of the packfile.
|
||||
func (p *Parser) Parse() (plumbing.Hash, error) {
|
||||
if err := p.init(); err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
return plumbing.ZeroHash, wrapEOF(err)
|
||||
}
|
||||
|
||||
if err := p.indexObjects(); err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
return plumbing.ZeroHash, wrapEOF(err)
|
||||
}
|
||||
|
||||
var err error
|
||||
p.checksum, err = p.scanner.Checksum()
|
||||
checksum, err := p.scanner.Checksum()
|
||||
if err != nil && err != io.EOF {
|
||||
return plumbing.ZeroHash, err
|
||||
return plumbing.ZeroHash, wrapEOF(err)
|
||||
}
|
||||
|
||||
if err := p.resolveDeltas(); err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
return plumbing.ZeroHash, wrapEOF(err)
|
||||
}
|
||||
|
||||
if err := p.onFooter(p.checksum); err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
if err := p.onFooter(checksum); err != nil {
|
||||
return plumbing.ZeroHash, wrapEOF(err)
|
||||
}
|
||||
|
||||
return p.checksum, nil
|
||||
return checksum, nil
|
||||
}
|
||||
|
||||
func (p *Parser) init() error {
|
||||
@@ -218,7 +216,7 @@ func (p *Parser) indexObjects() error {
|
||||
if !ok {
|
||||
// can't find referenced object in this pack file
|
||||
// this must be a "thin" pack.
|
||||
parent = &objectInfo{ //Placeholder parent
|
||||
parent = &objectInfo{ // Placeholder parent
|
||||
SHA1: oh.Reference,
|
||||
ExternalRef: true, // mark as an external reference that must be resolved
|
||||
Type: plumbing.AnyObject,
|
||||
@@ -531,6 +529,13 @@ func (p *Parser) readData(w io.Writer, o *objectInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func wrapEOF(err error) error {
|
||||
if err == io.ErrUnexpectedEOF || err == io.EOF {
|
||||
return fmt.Errorf("%w: %w", ErrMalformedPackFile, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// applyPatchBase applies the patch to target.
|
||||
//
|
||||
// Note that ota will be updated based on the description in resolveObject.
|
||||
@@ -558,15 +563,6 @@ func applyPatchBase(ota *objectInfo, base io.ReaderAt, delta io.Reader, target i
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSHA1(t plumbing.ObjectType, data []byte) (plumbing.Hash, error) {
|
||||
hasher := plumbing.NewHasher(t, int64(len(data)))
|
||||
if _, err := hasher.Write(data); err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
return hasher.Sum(), nil
|
||||
}
|
||||
|
||||
type objectInfo struct {
|
||||
Offset int64
|
||||
Length int64
|
||||
|
||||
21
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go
generated
vendored
21
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go
generated
vendored
@@ -26,6 +26,13 @@ var (
|
||||
const (
|
||||
payload = 0x7f // 0111 1111
|
||||
continuation = 0x80 // 1000 0000
|
||||
|
||||
// maxPatchPreemptionSize defines what is the max size of bytes to be
|
||||
// premptively made available for a patch operation.
|
||||
maxPatchPreemptionSize uint = 65536
|
||||
|
||||
// minDeltaSize defines the smallest size for a delta.
|
||||
minDeltaSize = 4
|
||||
)
|
||||
|
||||
type offset struct {
|
||||
@@ -86,9 +93,13 @@ func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) (err error) {
|
||||
}
|
||||
|
||||
// PatchDelta returns the result of applying the modification deltas in delta to src.
|
||||
// An error will be returned if delta is corrupted (ErrDeltaLen) or an action command
|
||||
// An error will be returned if delta is corrupted (ErrInvalidDelta) or an action command
|
||||
// is not copy from source or copy from delta (ErrDeltaCmd).
|
||||
func PatchDelta(src, delta []byte) ([]byte, error) {
|
||||
if len(src) == 0 || len(delta) < minDeltaSize {
|
||||
return nil, ErrInvalidDelta
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
if err := patchDelta(b, src, delta); err != nil {
|
||||
return nil, err
|
||||
@@ -239,7 +250,9 @@ func patchDelta(dst *bytes.Buffer, src, delta []byte) error {
|
||||
remainingTargetSz := targetSz
|
||||
|
||||
var cmd byte
|
||||
dst.Grow(int(targetSz))
|
||||
|
||||
growSz := min(targetSz, maxPatchPreemptionSize)
|
||||
dst.Grow(int(growSz))
|
||||
for {
|
||||
if len(delta) == 0 {
|
||||
return ErrInvalidDelta
|
||||
@@ -403,6 +416,10 @@ func patchDeltaWriter(dst io.Writer, base io.ReaderAt, delta io.Reader,
|
||||
// This must be called twice on the delta data buffer, first to get the
|
||||
// expected source buffer size, and again to get the target buffer size.
|
||||
func decodeLEB128(input []byte) (uint, []byte) {
|
||||
if len(input) == 0 {
|
||||
return 0, input
|
||||
}
|
||||
|
||||
var num, sz uint
|
||||
var b byte
|
||||
for {
|
||||
|
||||
45
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go
generated
vendored
45
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go
generated
vendored
@@ -3,12 +3,15 @@ package packfile
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
gohash "hash"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/hash"
|
||||
"github.com/go-git/go-git/v5/utils/binary"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
"github.com/go-git/go-git/v5/utils/sync"
|
||||
@@ -24,6 +27,8 @@ var (
|
||||
ErrUnsupportedVersion = NewError("unsupported packfile version")
|
||||
// ErrSeekNotSupported returned if seek is not support
|
||||
ErrSeekNotSupported = NewError("not seek support")
|
||||
// ErrMalformedPackFile is returned by the parser when the pack file is corrupted.
|
||||
ErrMalformedPackFile = errors.New("malformed PACK file")
|
||||
)
|
||||
|
||||
// ObjectHeader contains the information related to the object, this information
|
||||
@@ -37,8 +42,9 @@ type ObjectHeader struct {
|
||||
}
|
||||
|
||||
type Scanner struct {
|
||||
r *scannerReader
|
||||
crc hash.Hash32
|
||||
r *scannerReader
|
||||
crc gohash.Hash32
|
||||
packHasher hash.Hash
|
||||
|
||||
// pendingObject is used to detect if an object has been read, or still
|
||||
// is waiting to be read
|
||||
@@ -56,10 +62,12 @@ func NewScanner(r io.Reader) *Scanner {
|
||||
_, ok := r.(io.ReadSeeker)
|
||||
|
||||
crc := crc32.NewIEEE()
|
||||
hasher := hash.New(crypto.SHA1)
|
||||
return &Scanner{
|
||||
r: newScannerReader(r, crc),
|
||||
r: newScannerReader(r, io.MultiWriter(crc, hasher)),
|
||||
crc: crc,
|
||||
IsSeekable: ok,
|
||||
packHasher: hasher,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +76,7 @@ func (s *Scanner) Reset(r io.Reader) {
|
||||
|
||||
s.r.Reset(r)
|
||||
s.crc.Reset()
|
||||
s.packHasher.Reset()
|
||||
s.IsSeekable = ok
|
||||
s.pendingObject = nil
|
||||
s.version = 0
|
||||
@@ -114,7 +123,7 @@ func (s *Scanner) Header() (version, objects uint32, err error) {
|
||||
|
||||
// readSignature reads a returns the signature field in the packfile.
|
||||
func (s *Scanner) readSignature() ([]byte, error) {
|
||||
var sig = make([]byte, 4)
|
||||
sig := make([]byte, 4)
|
||||
if _, err := io.ReadFull(s.r, sig); err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
@@ -322,7 +331,6 @@ func (s *Scanner) NextObject(w io.Writer) (written int64, crc32 uint32, err erro
|
||||
func (s *Scanner) ReadObject() (io.ReadCloser, error) {
|
||||
s.pendingObject = nil
|
||||
zr, err := sync.GetZlibReader(s.r)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("zlib reset error: %s", err)
|
||||
}
|
||||
@@ -374,7 +382,18 @@ func (s *Scanner) Checksum() (plumbing.Hash, error) {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
return binary.ReadHash(s.r)
|
||||
s.r.Flush()
|
||||
actual := plumbing.Hash(s.packHasher.Sum(nil))
|
||||
packChecksum, err := binary.ReadHash(s.r)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
if actual != packChecksum {
|
||||
return plumbing.ZeroHash, fmt.Errorf("%w: checksum mismatch: %q instead of %q", ErrMalformedPackFile, packChecksum, actual)
|
||||
}
|
||||
|
||||
return packChecksum, nil
|
||||
}
|
||||
|
||||
// Close reads the reader until io.EOF
|
||||
@@ -401,17 +420,17 @@ func (s *Scanner) Flush() error {
|
||||
// to the crc32 hash writer.
|
||||
type scannerReader struct {
|
||||
reader io.Reader
|
||||
crc io.Writer
|
||||
writer io.Writer
|
||||
rbuf *bufio.Reader
|
||||
wbuf *bufio.Writer
|
||||
offset int64
|
||||
}
|
||||
|
||||
func newScannerReader(r io.Reader, h io.Writer) *scannerReader {
|
||||
func newScannerReader(r io.Reader, w io.Writer) *scannerReader {
|
||||
sr := &scannerReader{
|
||||
rbuf: bufio.NewReader(nil),
|
||||
wbuf: bufio.NewWriterSize(nil, 64),
|
||||
crc: h,
|
||||
rbuf: bufio.NewReader(nil),
|
||||
wbuf: bufio.NewWriterSize(nil, 64),
|
||||
writer: w,
|
||||
}
|
||||
sr.Reset(r)
|
||||
|
||||
@@ -421,7 +440,7 @@ func newScannerReader(r io.Reader, h io.Writer) *scannerReader {
|
||||
func (r *scannerReader) Reset(reader io.Reader) {
|
||||
r.reader = reader
|
||||
r.rbuf.Reset(r.reader)
|
||||
r.wbuf.Reset(r.crc)
|
||||
r.wbuf.Reset(r.writer)
|
||||
|
||||
r.offset = 0
|
||||
if seeker, ok := r.reader.(io.ReadSeeker); ok {
|
||||
|
||||
2
vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/scanner.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/scanner.go
generated
vendored
@@ -140,6 +140,8 @@ func asciiHexToByte(b byte) (byte, error) {
|
||||
return b - '0', nil
|
||||
case b >= 'a' && b <= 'f':
|
||||
return b - 'a' + 10, nil
|
||||
case b >= 'A' && b <= 'F':
|
||||
return b - 'A' + 10, nil
|
||||
default:
|
||||
return 0, ErrInvalidPktLen
|
||||
}
|
||||
|
||||
78
vendor/github.com/go-git/go-git/v5/plumbing/object/commit.go
generated
vendored
78
vendor/github.com/go-git/go-git/v5/plumbing/object/commit.go
generated
vendored
@@ -27,7 +27,7 @@ const (
|
||||
// the commit with the "mergetag" header.
|
||||
headermergetag string = "mergetag"
|
||||
|
||||
defaultUtf8CommitMesageEncoding MessageEncoding = "UTF-8"
|
||||
defaultUtf8CommitMessageEncoding MessageEncoding = "UTF-8"
|
||||
)
|
||||
|
||||
// Hash represents the hash of an object
|
||||
@@ -62,10 +62,55 @@ type Commit struct {
|
||||
ParentHashes []plumbing.Hash
|
||||
// Encoding is the encoding of the commit.
|
||||
Encoding MessageEncoding
|
||||
// List of extra headers of the commit
|
||||
ExtraHeaders []ExtraHeader
|
||||
|
||||
s storer.EncodedObjectStorer
|
||||
}
|
||||
|
||||
// ExtraHeader holds any non-standard header
|
||||
type ExtraHeader struct {
|
||||
// Header name
|
||||
Key string
|
||||
// Value of the header
|
||||
Value string
|
||||
}
|
||||
|
||||
// Implement fmt.Formatter for ExtraHeader
|
||||
func (h ExtraHeader) Format(f fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
fmt.Fprintf(f, "ExtraHeader{Key: %v, Value: %v}", h.Key, h.Value)
|
||||
default:
|
||||
fmt.Fprintf(f, "%s", h.Key)
|
||||
if len(h.Value) > 0 {
|
||||
fmt.Fprint(f, " ")
|
||||
// Content may be spread on multiple lines, if so we need to
|
||||
// prepend each of them with a space for "continuation".
|
||||
value := strings.TrimSuffix(h.Value, "\n")
|
||||
lines := strings.Split(value, "\n")
|
||||
fmt.Fprint(f, strings.Join(lines, "\n "))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse an extra header and indicate whether it may be continue on the next line
|
||||
func parseExtraHeader(line []byte) (ExtraHeader, bool) {
|
||||
split := bytes.SplitN(line, []byte{' '}, 2)
|
||||
|
||||
out := ExtraHeader {
|
||||
Key: string(bytes.TrimRight(split[0], "\n")),
|
||||
Value: "",
|
||||
}
|
||||
|
||||
if len(split) == 2 {
|
||||
out.Value += string(split[1])
|
||||
return out, true
|
||||
} else {
|
||||
return out, false
|
||||
}
|
||||
}
|
||||
|
||||
// GetCommit gets a commit from an object storer and decodes it.
|
||||
func GetCommit(s storer.EncodedObjectStorer, h plumbing.Hash) (*Commit, error) {
|
||||
o, err := s.EncodedObject(plumbing.CommitObject, h)
|
||||
@@ -189,7 +234,7 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
|
||||
}
|
||||
|
||||
c.Hash = o.Hash()
|
||||
c.Encoding = defaultUtf8CommitMesageEncoding
|
||||
c.Encoding = defaultUtf8CommitMessageEncoding
|
||||
|
||||
reader, err := o.Reader()
|
||||
if err != nil {
|
||||
@@ -204,6 +249,7 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
|
||||
var mergetag bool
|
||||
var pgpsig bool
|
||||
var msgbuf bytes.Buffer
|
||||
var extraheader *ExtraHeader = nil
|
||||
for {
|
||||
line, err := r.ReadBytes('\n')
|
||||
if err != nil && err != io.EOF {
|
||||
@@ -230,7 +276,19 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if extraheader != nil {
|
||||
if len(line) > 0 && line[0] == ' ' {
|
||||
extraheader.Value += string(line[1:])
|
||||
continue
|
||||
} else {
|
||||
extraheader.Value = strings.TrimRight(extraheader.Value, "\n")
|
||||
c.ExtraHeaders = append(c.ExtraHeaders, *extraheader)
|
||||
extraheader = nil
|
||||
}
|
||||
}
|
||||
|
||||
if !message {
|
||||
original_line := line
|
||||
line = bytes.TrimSpace(line)
|
||||
if len(line) == 0 {
|
||||
message = true
|
||||
@@ -261,6 +319,13 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
|
||||
case headerpgp:
|
||||
c.PGPSignature += string(data) + "\n"
|
||||
pgpsig = true
|
||||
default:
|
||||
h, maybecontinued := parseExtraHeader(original_line)
|
||||
if maybecontinued {
|
||||
extraheader = &h
|
||||
} else {
|
||||
c.ExtraHeaders = append(c.ExtraHeaders, h)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
msgbuf.Write(line)
|
||||
@@ -335,12 +400,19 @@ func (c *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if string(c.Encoding) != "" && c.Encoding != defaultUtf8CommitMesageEncoding {
|
||||
if string(c.Encoding) != "" && c.Encoding != defaultUtf8CommitMessageEncoding {
|
||||
if _, err = fmt.Fprintf(w, "\n%s %s", headerencoding, c.Encoding); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, header := range c.ExtraHeaders {
|
||||
|
||||
if _, err = fmt.Fprintf(w, "\n%s", header); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if c.PGPSignature != "" && includeSig {
|
||||
if _, err = fmt.Fprint(w, "\n"+headerpgp+" "); err != nil {
|
||||
return err
|
||||
|
||||
19
vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_path.go
generated
vendored
19
vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_path.go
generated
vendored
@@ -57,6 +57,8 @@ func (c *commitPathIter) Next() (*Commit, error) {
|
||||
}
|
||||
|
||||
func (c *commitPathIter) getNextFileCommit() (*Commit, error) {
|
||||
var parentTree, currentTree *Tree
|
||||
|
||||
for {
|
||||
// Parent-commit can be nil if the current-commit is the initial commit
|
||||
parentCommit, parentCommitErr := c.sourceIter.Next()
|
||||
@@ -68,13 +70,17 @@ func (c *commitPathIter) getNextFileCommit() (*Commit, error) {
|
||||
parentCommit = nil
|
||||
}
|
||||
|
||||
// Fetch the trees of the current and parent commits
|
||||
currentTree, currTreeErr := c.currentCommit.Tree()
|
||||
if currTreeErr != nil {
|
||||
return nil, currTreeErr
|
||||
if parentTree == nil {
|
||||
var currTreeErr error
|
||||
currentTree, currTreeErr = c.currentCommit.Tree()
|
||||
if currTreeErr != nil {
|
||||
return nil, currTreeErr
|
||||
}
|
||||
} else {
|
||||
currentTree = parentTree
|
||||
parentTree = nil
|
||||
}
|
||||
|
||||
var parentTree *Tree
|
||||
if parentCommit != nil {
|
||||
var parentTreeErr error
|
||||
parentTree, parentTreeErr = parentCommit.Tree()
|
||||
@@ -115,7 +121,8 @@ func (c *commitPathIter) hasFileChange(changes Changes, parent *Commit) bool {
|
||||
|
||||
// filename matches, now check if source iterator contains all commits (from all refs)
|
||||
if c.checkParent {
|
||||
if parent != nil && isParentHash(parent.Hash, c.currentCommit) {
|
||||
// Check if parent is beyond the initial commit
|
||||
if parent == nil || isParentHash(parent.Hash, c.currentCommit) {
|
||||
return true
|
||||
}
|
||||
continue
|
||||
|
||||
97
vendor/github.com/go-git/go-git/v5/plumbing/object/patch.go
generated
vendored
97
vendor/github.com/go-git/go-git/v5/plumbing/object/patch.go
generated
vendored
@@ -6,7 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
@@ -234,69 +234,56 @@ func (fileStats FileStats) String() string {
|
||||
return printStat(fileStats)
|
||||
}
|
||||
|
||||
// printStat prints the stats of changes in content of files.
|
||||
// Original implementation: https://github.com/git/git/blob/1a87c842ece327d03d08096395969aca5e0a6996/diff.c#L2615
|
||||
// Parts of the output:
|
||||
// <pad><filename><pad>|<pad><changeNumber><pad><+++/---><newline>
|
||||
// example: " main.go | 10 +++++++--- "
|
||||
func printStat(fileStats []FileStat) string {
|
||||
padLength := float64(len(" "))
|
||||
newlineLength := float64(len("\n"))
|
||||
separatorLength := float64(len("|"))
|
||||
// Soft line length limit. The text length calculation below excludes
|
||||
// length of the change number. Adding that would take it closer to 80,
|
||||
// but probably not more than 80, until it's a huge number.
|
||||
lineLength := 72.0
|
||||
maxGraphWidth := uint(53)
|
||||
maxNameLen := 0
|
||||
maxChangeLen := 0
|
||||
|
||||
scaleLinear := func(it, width, max uint) uint {
|
||||
if it == 0 || max == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1 + (it * (width - 1) / max)
|
||||
}
|
||||
|
||||
// Get the longest filename and longest total change.
|
||||
var longestLength float64
|
||||
var longestTotalChange float64
|
||||
for _, fs := range fileStats {
|
||||
if int(longestLength) < len(fs.Name) {
|
||||
longestLength = float64(len(fs.Name))
|
||||
if len(fs.Name) > maxNameLen {
|
||||
maxNameLen = len(fs.Name)
|
||||
}
|
||||
totalChange := fs.Addition + fs.Deletion
|
||||
if int(longestTotalChange) < totalChange {
|
||||
longestTotalChange = float64(totalChange)
|
||||
|
||||
changes := strconv.Itoa(fs.Addition + fs.Deletion)
|
||||
if len(changes) > maxChangeLen {
|
||||
maxChangeLen = len(changes)
|
||||
}
|
||||
}
|
||||
|
||||
// Parts of the output:
|
||||
// <pad><filename><pad>|<pad><changeNumber><pad><+++/---><newline>
|
||||
// example: " main.go | 10 +++++++--- "
|
||||
|
||||
// <pad><filename><pad>
|
||||
leftTextLength := padLength + longestLength + padLength
|
||||
|
||||
// <pad><number><pad><+++++/-----><newline>
|
||||
// Excluding number length here.
|
||||
rightTextLength := padLength + padLength + newlineLength
|
||||
|
||||
totalTextArea := leftTextLength + separatorLength + rightTextLength
|
||||
heightOfHistogram := lineLength - totalTextArea
|
||||
|
||||
// Scale the histogram.
|
||||
var scaleFactor float64
|
||||
if longestTotalChange > heightOfHistogram {
|
||||
// Scale down to heightOfHistogram.
|
||||
scaleFactor = longestTotalChange / heightOfHistogram
|
||||
} else {
|
||||
scaleFactor = 1.0
|
||||
}
|
||||
|
||||
finalOutput := ""
|
||||
result := ""
|
||||
for _, fs := range fileStats {
|
||||
addn := float64(fs.Addition)
|
||||
deln := float64(fs.Deletion)
|
||||
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)
|
||||
}
|
||||
add := uint(fs.Addition)
|
||||
del := uint(fs.Deletion)
|
||||
np := maxNameLen - len(fs.Name)
|
||||
cp := maxChangeLen - len(strconv.Itoa(fs.Addition+fs.Deletion))
|
||||
|
||||
return finalOutput
|
||||
total := add + del
|
||||
if total > maxGraphWidth {
|
||||
add = scaleLinear(add, maxGraphWidth, total)
|
||||
del = scaleLinear(del, maxGraphWidth, total)
|
||||
}
|
||||
|
||||
adds := strings.Repeat("+", int(add))
|
||||
dels := strings.Repeat("-", int(del))
|
||||
namePad := strings.Repeat(" ", np)
|
||||
changePad := strings.Repeat(" ", cp)
|
||||
|
||||
result += fmt.Sprintf(" %s%s | %s%d %s%s\n", fs.Name, namePad, changePad, total, adds, dels)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func getFileStatsFromFilePatches(filePatches []fdiff.FilePatch) FileStats {
|
||||
|
||||
1
vendor/github.com/go-git/go-git/v5/plumbing/object/signature.go
generated
vendored
1
vendor/github.com/go-git/go-git/v5/plumbing/object/signature.go
generated
vendored
@@ -19,6 +19,7 @@ var (
|
||||
// a PKCS#7 (S/MIME) signature.
|
||||
x509SignatureFormat = signatureFormat{
|
||||
[]byte("-----BEGIN CERTIFICATE-----"),
|
||||
[]byte("-----BEGIN SIGNED MESSAGE-----"),
|
||||
}
|
||||
|
||||
// sshSignatureFormat is the format of an SSH signature.
|
||||
|
||||
33
vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go
generated
vendored
33
vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go
generated
vendored
@@ -7,6 +7,7 @@ import (
|
||||
"io"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
@@ -27,6 +28,7 @@ var (
|
||||
ErrFileNotFound = errors.New("file not found")
|
||||
ErrDirectoryNotFound = errors.New("directory not found")
|
||||
ErrEntryNotFound = errors.New("entry not found")
|
||||
ErrEntriesNotSorted = errors.New("entries in tree are not sorted")
|
||||
)
|
||||
|
||||
// Tree is basically like a directory - it references a bunch of other trees
|
||||
@@ -270,7 +272,30 @@ func (t *Tree) Decode(o plumbing.EncodedObject) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
type TreeEntrySorter []TreeEntry
|
||||
|
||||
func (s TreeEntrySorter) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s TreeEntrySorter) Less(i, j int) bool {
|
||||
name1 := s[i].Name
|
||||
name2 := s[j].Name
|
||||
if s[i].Mode == filemode.Dir {
|
||||
name1 += "/"
|
||||
}
|
||||
if s[j].Mode == filemode.Dir {
|
||||
name2 += "/"
|
||||
}
|
||||
return name1 < name2
|
||||
}
|
||||
|
||||
func (s TreeEntrySorter) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
// Encode transforms a Tree into a plumbing.EncodedObject.
|
||||
// The tree entries must be sorted by name.
|
||||
func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
|
||||
o.SetType(plumbing.TreeObject)
|
||||
w, err := o.Writer()
|
||||
@@ -279,7 +304,15 @@ func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(w, &err)
|
||||
|
||||
if !sort.IsSorted(TreeEntrySorter(t.Entries)) {
|
||||
return ErrEntriesNotSorted
|
||||
}
|
||||
|
||||
for _, entry := range t.Entries {
|
||||
if strings.IndexByte(entry.Name, 0) != -1 {
|
||||
return fmt.Errorf("malformed filename %q", entry.Name)
|
||||
}
|
||||
if _, err = fmt.Fprintf(w, "%o %s", entry.Mode, entry.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
4
vendor/github.com/go-git/go-git/v5/plumbing/object/treenoder.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/plumbing/object/treenoder.go
generated
vendored
@@ -88,7 +88,9 @@ func (t *treeNoder) Children() ([]noder.Noder, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return transformChildren(parent)
|
||||
var err error
|
||||
t.children, err = transformChildren(parent)
|
||||
return t.children, err
|
||||
}
|
||||
|
||||
// Returns the children of a tree as treenoders.
|
||||
|
||||
5
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go
generated
vendored
5
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go
generated
vendored
@@ -262,9 +262,8 @@ func decodeShallow(p *advRefsDecoder) decoderStateFn {
|
||||
p.line = bytes.TrimPrefix(p.line, shallow)
|
||||
|
||||
if len(p.line) != hashSize {
|
||||
p.error(fmt.Sprintf(
|
||||
"malformed shallow hash: wrong length, expected 40 bytes, read %d bytes",
|
||||
len(p.line)))
|
||||
p.error("malformed shallow hash: wrong length, expected 40 bytes, read %d bytes",
|
||||
len(p.line))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
76
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/filter.go
generated
vendored
Normal file
76
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/filter.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package packp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var ErrUnsupportedObjectFilterType = errors.New("unsupported object filter type")
|
||||
|
||||
// Filter values enable the partial clone capability which causes
|
||||
// the server to omit objects that match the filter.
|
||||
//
|
||||
// See [Git's documentation] for more details.
|
||||
//
|
||||
// [Git's documentation]: https://github.com/git/git/blob/e02ecfcc534e2021aae29077a958dd11c3897e4c/Documentation/rev-list-options.txt#L948
|
||||
type Filter string
|
||||
|
||||
type BlobLimitPrefix string
|
||||
|
||||
const (
|
||||
BlobLimitPrefixNone BlobLimitPrefix = ""
|
||||
BlobLimitPrefixKibi BlobLimitPrefix = "k"
|
||||
BlobLimitPrefixMebi BlobLimitPrefix = "m"
|
||||
BlobLimitPrefixGibi BlobLimitPrefix = "g"
|
||||
)
|
||||
|
||||
// FilterBlobNone omits all blobs.
|
||||
func FilterBlobNone() Filter {
|
||||
return "blob:none"
|
||||
}
|
||||
|
||||
// FilterBlobLimit omits blobs of size at least n bytes (when prefix is
|
||||
// BlobLimitPrefixNone), n kibibytes (when prefix is BlobLimitPrefixKibi),
|
||||
// n mebibytes (when prefix is BlobLimitPrefixMebi) or n gibibytes (when
|
||||
// prefix is BlobLimitPrefixGibi). n can be zero, in which case all blobs
|
||||
// will be omitted.
|
||||
func FilterBlobLimit(n uint64, prefix BlobLimitPrefix) Filter {
|
||||
return Filter(fmt.Sprintf("blob:limit=%d%s", n, prefix))
|
||||
}
|
||||
|
||||
// FilterTreeDepth omits all blobs and trees whose depth from the root tree
|
||||
// is larger or equal to depth.
|
||||
func FilterTreeDepth(depth uint64) Filter {
|
||||
return Filter(fmt.Sprintf("tree:%d", depth))
|
||||
}
|
||||
|
||||
// FilterObjectType omits all objects which are not of the requested type t.
|
||||
// Supported types are TagObject, CommitObject, TreeObject and BlobObject.
|
||||
func FilterObjectType(t plumbing.ObjectType) (Filter, error) {
|
||||
switch t {
|
||||
case plumbing.TagObject:
|
||||
fallthrough
|
||||
case plumbing.CommitObject:
|
||||
fallthrough
|
||||
case plumbing.TreeObject:
|
||||
fallthrough
|
||||
case plumbing.BlobObject:
|
||||
return Filter(fmt.Sprintf("object:type=%s", t.String())), nil
|
||||
default:
|
||||
return "", fmt.Errorf("%w: %s", ErrUnsupportedObjectFilterType, t.String())
|
||||
}
|
||||
}
|
||||
|
||||
// FilterCombine combines multiple Filter values together.
|
||||
func FilterCombine(filters ...Filter) Filter {
|
||||
var escapedFilters []string
|
||||
|
||||
for _, filter := range filters {
|
||||
escapedFilters = append(escapedFilters, url.QueryEscape(string(filter)))
|
||||
}
|
||||
|
||||
return Filter(fmt.Sprintf("combine:%s", strings.Join(escapedFilters, "+")))
|
||||
}
|
||||
2
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/demux.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/demux.go
generated
vendored
@@ -114,7 +114,7 @@ func (d *Demuxer) nextPackData() ([]byte, error) {
|
||||
|
||||
size := len(content)
|
||||
if size == 0 {
|
||||
return nil, nil
|
||||
return nil, io.EOF
|
||||
} else if size > d.max {
|
||||
return nil, ErrMaxPackedExceeded
|
||||
}
|
||||
|
||||
3
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/srvresp.go
generated
vendored
3
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/srvresp.go
generated
vendored
@@ -120,6 +120,9 @@ func (r *ServerResponse) decodeACKLine(line []byte) error {
|
||||
}
|
||||
|
||||
sp := bytes.Index(line, []byte(" "))
|
||||
if sp+41 > len(line) {
|
||||
return fmt.Errorf("malformed ACK %q", line)
|
||||
}
|
||||
h := plumbing.NewHash(string(line[sp+1 : sp+41]))
|
||||
r.ACKs = append(r.ACKs, h)
|
||||
return nil
|
||||
|
||||
1
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go
generated
vendored
1
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go
generated
vendored
@@ -17,6 +17,7 @@ type UploadRequest struct {
|
||||
Wants []plumbing.Hash
|
||||
Shallows []plumbing.Hash
|
||||
Depth Depth
|
||||
Filter Filter
|
||||
}
|
||||
|
||||
// Depth values stores the desired depth of the requested packfile: see
|
||||
|
||||
11
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go
generated
vendored
11
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go
generated
vendored
@@ -132,6 +132,17 @@ func (e *ulReqEncoder) encodeDepth() stateFn {
|
||||
return nil
|
||||
}
|
||||
|
||||
return e.encodeFilter
|
||||
}
|
||||
|
||||
func (e *ulReqEncoder) encodeFilter() stateFn {
|
||||
if filter := e.data.Filter; filter != "" {
|
||||
if err := e.pe.Encodef("filter %s\n", filter); err != nil {
|
||||
e.err = fmt.Errorf("encoding filter %s: %s", filter, err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return e.encodeFlush
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go
generated
vendored
@@ -62,7 +62,7 @@ func (req *ReferenceUpdateRequest) encodeCommands(e *pktline.Encoder,
|
||||
}
|
||||
|
||||
for _, cmd := range cmds[1:] {
|
||||
if err := e.Encodef(formatCommand(cmd)); err != nil {
|
||||
if err := e.Encodef("%s", formatCommand(cmd)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
4
vendor/github.com/go-git/go-git/v5/plumbing/reference.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/plumbing/reference.go
generated
vendored
@@ -188,7 +188,7 @@ func (r ReferenceName) Validate() error {
|
||||
|
||||
isBranch := r.IsBranch()
|
||||
isTag := r.IsTag()
|
||||
for _, part := range parts {
|
||||
for i, part := range parts {
|
||||
// rule 6
|
||||
if len(part) == 0 {
|
||||
return ErrInvalidReferenceName
|
||||
@@ -205,7 +205,7 @@ func (r ReferenceName) Validate() error {
|
||||
return ErrInvalidReferenceName
|
||||
}
|
||||
|
||||
if (isBranch || isTag) && strings.HasPrefix(part, "-") { // branches & tags can't start with -
|
||||
if (isBranch || isTag) && strings.HasPrefix(part, "-") && (i == 2) { // branches & tags can't start with -
|
||||
return ErrInvalidReferenceName
|
||||
}
|
||||
}
|
||||
|
||||
19
vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go
generated
vendored
19
vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go
generated
vendored
@@ -19,6 +19,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -112,9 +113,17 @@ type Endpoint struct {
|
||||
Port int
|
||||
// Path is the repository path.
|
||||
Path string
|
||||
// InsecureSkipTLS skips ssl verify if protocol is https
|
||||
// InsecureSkipTLS skips SSL verification if Protocol is HTTPS.
|
||||
InsecureSkipTLS bool
|
||||
// CaBundle specify additional ca bundle with system cert pool
|
||||
// ClientCert specifies an optional client certificate to use for mutual
|
||||
// TLS authentication if Protocol is HTTPS.
|
||||
ClientCert []byte
|
||||
// ClientKey specifies an optional client key to use for mutual TLS
|
||||
// authentication if Protocol is HTTPS.
|
||||
ClientKey []byte
|
||||
// CaBundle specifies an optional CA bundle to use for SSL verification
|
||||
// if Protocol is HTTPS. The bundle is added in addition to the system
|
||||
// CA bundle.
|
||||
CaBundle []byte
|
||||
// Proxy provides info required for connecting to a proxy.
|
||||
Proxy ProxyOptions
|
||||
@@ -295,7 +304,11 @@ func parseFile(endpoint string) (*Endpoint, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
path := endpoint
|
||||
path, err := filepath.Abs(endpoint)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return &Endpoint{
|
||||
Protocol: "file",
|
||||
Path: path,
|
||||
|
||||
19
vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go
generated
vendored
19
vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go
generated
vendored
@@ -7,6 +7,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
@@ -95,7 +96,23 @@ func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.Auth
|
||||
}
|
||||
}
|
||||
|
||||
return &command{cmd: execabs.Command(cmd, ep.Path)}, nil
|
||||
return &command{cmd: execabs.Command(cmd, adjustPathForWindows(ep.Path))}, nil
|
||||
}
|
||||
|
||||
func isDriveLetter(c byte) bool {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|
||||
}
|
||||
|
||||
// On Windows, the path that results from a file: URL has a leading slash. This
|
||||
// has to be removed if there's a drive letter
|
||||
func adjustPathForWindows(p string) string {
|
||||
if runtime.GOOS != "windows" {
|
||||
return p
|
||||
}
|
||||
if len(p) >= 3 && p[0] == '/' && isDriveLetter(p[1]) && p[2] == ':' {
|
||||
return p[1:]
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
type command struct {
|
||||
|
||||
61
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go
generated
vendored
61
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go
generated
vendored
@@ -15,16 +15,18 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/groupcache/lru"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
|
||||
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
"github.com/golang/groupcache/lru"
|
||||
)
|
||||
|
||||
// it requires a bytes.Buffer, because we need to know the length
|
||||
func applyHeadersToRequest(req *http.Request, content *bytes.Buffer, host string, requestType string) {
|
||||
req.Header.Add("User-Agent", "git/1.0")
|
||||
req.Header.Add("User-Agent", capability.DefaultAgent())
|
||||
req.Header.Add("Host", host) // host:port
|
||||
|
||||
if content == nil {
|
||||
@@ -91,9 +93,9 @@ func advertisedReferences(ctx context.Context, s *session, serviceName string) (
|
||||
}
|
||||
|
||||
type client struct {
|
||||
c *http.Client
|
||||
client *http.Client
|
||||
transports *lru.Cache
|
||||
m sync.RWMutex
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
// ClientOptions holds user configurable options for the client.
|
||||
@@ -147,7 +149,7 @@ func NewClientWithOptions(c *http.Client, opts *ClientOptions) transport.Transpo
|
||||
}
|
||||
}
|
||||
cl := &client{
|
||||
c: c,
|
||||
client: c,
|
||||
}
|
||||
|
||||
if opts != nil {
|
||||
@@ -184,6 +186,18 @@ func transportWithInsecureTLS(transport *http.Transport) {
|
||||
transport.TLSClientConfig.InsecureSkipVerify = true
|
||||
}
|
||||
|
||||
func transportWithClientCert(transport *http.Transport, cert, key []byte) error {
|
||||
keyPair, err := tls.X509KeyPair(cert, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if transport.TLSClientConfig == nil {
|
||||
transport.TLSClientConfig = &tls.Config{}
|
||||
}
|
||||
transport.TLSClientConfig.Certificates = []tls.Certificate{keyPair}
|
||||
return nil
|
||||
}
|
||||
|
||||
func transportWithCABundle(transport *http.Transport, caBundle []byte) error {
|
||||
rootCAs, err := x509.SystemCertPool()
|
||||
if err != nil {
|
||||
@@ -205,6 +219,11 @@ func transportWithProxy(transport *http.Transport, proxyURL *url.URL) {
|
||||
}
|
||||
|
||||
func configureTransport(transport *http.Transport, ep *transport.Endpoint) error {
|
||||
if len(ep.ClientCert) > 0 && len(ep.ClientKey) > 0 {
|
||||
if err := transportWithClientCert(transport, ep.ClientCert, ep.ClientKey); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(ep.CaBundle) > 0 {
|
||||
if err := transportWithCABundle(transport, ep.CaBundle); err != nil {
|
||||
return err
|
||||
@@ -229,21 +248,25 @@ func newSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (*
|
||||
|
||||
// We need to configure the http transport if there are transport specific
|
||||
// options present in the endpoint.
|
||||
if len(ep.CaBundle) > 0 || ep.InsecureSkipTLS || ep.Proxy.URL != "" {
|
||||
if len(ep.ClientKey) > 0 || len(ep.ClientCert) > 0 || len(ep.CaBundle) > 0 || ep.InsecureSkipTLS || ep.Proxy.URL != "" {
|
||||
var transport *http.Transport
|
||||
// if the client wasn't configured to have a cache for transports then just configure
|
||||
// the transport and use it directly, otherwise try to use the cache.
|
||||
if c.transports == nil {
|
||||
tr, ok := c.c.Transport.(*http.Transport)
|
||||
tr, ok := c.client.Transport.(*http.Transport)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected underlying client transport to be of type: %s; got: %s",
|
||||
reflect.TypeOf(transport), reflect.TypeOf(c.c.Transport))
|
||||
reflect.TypeOf(transport), reflect.TypeOf(c.client.Transport))
|
||||
}
|
||||
|
||||
transport = tr.Clone()
|
||||
configureTransport(transport, ep)
|
||||
if err := configureTransport(transport, ep); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
transportOpts := transportOptions{
|
||||
clientCert: string(ep.ClientCert),
|
||||
clientKey: string(ep.ClientKey),
|
||||
caBundle: string(ep.CaBundle),
|
||||
insecureSkipTLS: ep.InsecureSkipTLS,
|
||||
}
|
||||
@@ -258,20 +281,22 @@ func newSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (*
|
||||
transport, found = c.fetchTransport(transportOpts)
|
||||
|
||||
if !found {
|
||||
transport = c.c.Transport.(*http.Transport).Clone()
|
||||
configureTransport(transport, ep)
|
||||
transport = c.client.Transport.(*http.Transport).Clone()
|
||||
if err := configureTransport(transport, ep); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.addTransport(transportOpts, transport)
|
||||
}
|
||||
}
|
||||
|
||||
httpClient = &http.Client{
|
||||
Transport: transport,
|
||||
CheckRedirect: c.c.CheckRedirect,
|
||||
Jar: c.c.Jar,
|
||||
Timeout: c.c.Timeout,
|
||||
CheckRedirect: c.client.CheckRedirect,
|
||||
Jar: c.client.Jar,
|
||||
Timeout: c.client.Timeout,
|
||||
}
|
||||
} else {
|
||||
httpClient = c.c
|
||||
httpClient = c.client
|
||||
}
|
||||
|
||||
s := &session{
|
||||
@@ -430,11 +455,11 @@ func NewErr(r *http.Response) error {
|
||||
|
||||
switch r.StatusCode {
|
||||
case http.StatusUnauthorized:
|
||||
return transport.ErrAuthenticationRequired
|
||||
return fmt.Errorf("%w: %s", transport.ErrAuthenticationRequired, reason)
|
||||
case http.StatusForbidden:
|
||||
return transport.ErrAuthorizationFailed
|
||||
return fmt.Errorf("%w: %s", transport.ErrAuthorizationFailed, reason)
|
||||
case http.StatusNotFound:
|
||||
return transport.ErrRepositoryNotFound
|
||||
return fmt.Errorf("%w: %s", transport.ErrRepositoryNotFound, reason)
|
||||
}
|
||||
|
||||
return plumbing.NewUnexpectedError(&Err{r, reason})
|
||||
|
||||
18
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/transport.go
generated
vendored
18
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/transport.go
generated
vendored
@@ -9,26 +9,28 @@ import (
|
||||
type transportOptions struct {
|
||||
insecureSkipTLS bool
|
||||
// []byte is not comparable.
|
||||
caBundle string
|
||||
proxyURL url.URL
|
||||
clientCert string
|
||||
clientKey string
|
||||
caBundle string
|
||||
proxyURL url.URL
|
||||
}
|
||||
|
||||
func (c *client) addTransport(opts transportOptions, transport *http.Transport) {
|
||||
c.m.Lock()
|
||||
c.mutex.Lock()
|
||||
c.transports.Add(opts, transport)
|
||||
c.m.Unlock()
|
||||
c.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (c *client) removeTransport(opts transportOptions) {
|
||||
c.m.Lock()
|
||||
c.mutex.Lock()
|
||||
c.transports.Remove(opts)
|
||||
c.m.Unlock()
|
||||
c.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (c *client) fetchTransport(opts transportOptions) (*http.Transport, bool) {
|
||||
c.m.RLock()
|
||||
c.mutex.RLock()
|
||||
t, ok := c.transports.Get(opts)
|
||||
c.m.RUnlock()
|
||||
c.mutex.RUnlock()
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
12
vendor/github.com/go-git/go-git/v5/plumbing/transport/server/loader.go
generated
vendored
12
vendor/github.com/go-git/go-git/v5/plumbing/transport/server/loader.go
generated
vendored
@@ -40,8 +40,16 @@ func (l *fsLoader) Load(ep *transport.Endpoint) (storer.Storer, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := fs.Stat("config"); err != nil {
|
||||
return nil, transport.ErrRepositoryNotFound
|
||||
var bare bool
|
||||
if _, err := fs.Stat("config"); err == nil {
|
||||
bare = true
|
||||
}
|
||||
|
||||
if !bare {
|
||||
// do not use git.GitDirName due to import cycle
|
||||
if _, err := fs.Stat(".git"); err != nil {
|
||||
return nil, transport.ErrRepositoryNotFound
|
||||
}
|
||||
}
|
||||
|
||||
return filesystem.NewStorage(fs, cache.NewObjectLRUDefault()), nil
|
||||
|
||||
76
vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go
generated
vendored
76
vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go
generated
vendored
@@ -54,7 +54,7 @@ func (a *KeyboardInteractive) String() string {
|
||||
}
|
||||
|
||||
func (a *KeyboardInteractive) ClientConfig() (*ssh.ClientConfig, error) {
|
||||
return a.SetHostKeyCallback(&ssh.ClientConfig{
|
||||
return a.SetHostKeyCallbackAndAlgorithms(&ssh.ClientConfig{
|
||||
User: a.User,
|
||||
Auth: []ssh.AuthMethod{
|
||||
a.Challenge,
|
||||
@@ -78,7 +78,7 @@ func (a *Password) String() string {
|
||||
}
|
||||
|
||||
func (a *Password) ClientConfig() (*ssh.ClientConfig, error) {
|
||||
return a.SetHostKeyCallback(&ssh.ClientConfig{
|
||||
return a.SetHostKeyCallbackAndAlgorithms(&ssh.ClientConfig{
|
||||
User: a.User,
|
||||
Auth: []ssh.AuthMethod{ssh.Password(a.Password)},
|
||||
})
|
||||
@@ -101,7 +101,7 @@ func (a *PasswordCallback) String() string {
|
||||
}
|
||||
|
||||
func (a *PasswordCallback) ClientConfig() (*ssh.ClientConfig, error) {
|
||||
return a.SetHostKeyCallback(&ssh.ClientConfig{
|
||||
return a.SetHostKeyCallbackAndAlgorithms(&ssh.ClientConfig{
|
||||
User: a.User,
|
||||
Auth: []ssh.AuthMethod{ssh.PasswordCallback(a.Callback)},
|
||||
})
|
||||
@@ -150,7 +150,7 @@ func (a *PublicKeys) String() string {
|
||||
}
|
||||
|
||||
func (a *PublicKeys) ClientConfig() (*ssh.ClientConfig, error) {
|
||||
return a.SetHostKeyCallback(&ssh.ClientConfig{
|
||||
return a.SetHostKeyCallbackAndAlgorithms(&ssh.ClientConfig{
|
||||
User: a.User,
|
||||
Auth: []ssh.AuthMethod{ssh.PublicKeys(a.Signer)},
|
||||
})
|
||||
@@ -211,7 +211,7 @@ func (a *PublicKeysCallback) String() string {
|
||||
}
|
||||
|
||||
func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) {
|
||||
return a.SetHostKeyCallback(&ssh.ClientConfig{
|
||||
return a.SetHostKeyCallbackAndAlgorithms(&ssh.ClientConfig{
|
||||
User: a.User,
|
||||
Auth: []ssh.AuthMethod{ssh.PublicKeysCallback(a.Callback)},
|
||||
})
|
||||
@@ -230,11 +230,26 @@ func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) {
|
||||
// ~/.ssh/known_hosts
|
||||
// /etc/ssh/ssh_known_hosts
|
||||
func NewKnownHostsCallback(files ...string) (ssh.HostKeyCallback, error) {
|
||||
kh, err := newKnownHosts(files...)
|
||||
return ssh.HostKeyCallback(kh), err
|
||||
kh, err := NewKnownHostsDb(files...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return kh.HostKeyCallback(), nil
|
||||
}
|
||||
|
||||
func newKnownHosts(files ...string) (knownhosts.HostKeyCallback, error) {
|
||||
// NewKnownHostsDb returns knownhosts.HostKeyDB based on a file based on a
|
||||
// known_hosts file. http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT
|
||||
//
|
||||
// If list of files is empty, then it will be read from the SSH_KNOWN_HOSTS
|
||||
// environment variable, example:
|
||||
//
|
||||
// /home/foo/custom_known_hosts_file:/etc/custom_known/hosts_file
|
||||
//
|
||||
// If SSH_KNOWN_HOSTS is not set the following file locations will be used:
|
||||
//
|
||||
// ~/.ssh/known_hosts
|
||||
// /etc/ssh/ssh_known_hosts
|
||||
func NewKnownHostsDb(files ...string) (*knownhosts.HostKeyDB, error) {
|
||||
var err error
|
||||
|
||||
if len(files) == 0 {
|
||||
@@ -247,7 +262,7 @@ func newKnownHosts(files ...string) (knownhosts.HostKeyCallback, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return knownhosts.New(files...)
|
||||
return knownhosts.NewDB(files...)
|
||||
}
|
||||
|
||||
func getDefaultKnownHostsFiles() ([]string, error) {
|
||||
@@ -289,25 +304,50 @@ func filterKnownHostsFiles(files ...string) ([]string, error) {
|
||||
}
|
||||
|
||||
// HostKeyCallbackHelper is a helper that provides common functionality to
|
||||
// configure HostKeyCallback into a ssh.ClientConfig.
|
||||
// configure HostKeyCallback and HostKeyAlgorithms into a ssh.ClientConfig.
|
||||
type HostKeyCallbackHelper struct {
|
||||
// HostKeyCallback is the function type used for verifying server keys.
|
||||
// If nil default callback will be create using NewKnownHostsCallback
|
||||
// If nil, a default callback will be created using NewKnownHostsDb
|
||||
// without argument.
|
||||
HostKeyCallback ssh.HostKeyCallback
|
||||
|
||||
// HostKeyAlgorithms is a list of supported host key algorithms that will
|
||||
// be used for host key verification.
|
||||
HostKeyAlgorithms []string
|
||||
|
||||
// fallback allows for injecting the fallback call, which is called
|
||||
// when a HostKeyCallback is not set.
|
||||
fallback func(files ...string) (ssh.HostKeyCallback, error)
|
||||
}
|
||||
|
||||
// SetHostKeyCallback sets the field HostKeyCallback in the given cfg. If
|
||||
// HostKeyCallback is empty a default callback is created using
|
||||
// NewKnownHostsCallback.
|
||||
func (m *HostKeyCallbackHelper) SetHostKeyCallback(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) {
|
||||
var err error
|
||||
// SetHostKeyCallbackAndAlgorithms sets the field HostKeyCallback and HostKeyAlgorithms in the given cfg.
|
||||
// If the host key callback or algorithms is empty it is left empty. It will be handled by the dial method,
|
||||
// falling back to knownhosts.
|
||||
func (m *HostKeyCallbackHelper) SetHostKeyCallbackAndAlgorithms(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) {
|
||||
if cfg == nil {
|
||||
cfg = &ssh.ClientConfig{}
|
||||
}
|
||||
|
||||
if m.HostKeyCallback == nil {
|
||||
if m.HostKeyCallback, err = NewKnownHostsCallback(); err != nil {
|
||||
return cfg, err
|
||||
if m.fallback == nil {
|
||||
m.fallback = NewKnownHostsCallback
|
||||
}
|
||||
|
||||
hkcb, err := m.fallback()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create known hosts callback: %w", err)
|
||||
}
|
||||
|
||||
cfg.HostKeyCallback = hkcb
|
||||
cfg.HostKeyAlgorithms = m.HostKeyAlgorithms
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
cfg.HostKeyCallback = m.HostKeyCallback
|
||||
cfg.HostKeyAlgorithms = m.HostKeyAlgorithms
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (m *HostKeyCallbackHelper) SetHostKeyCallback(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) {
|
||||
return m.SetHostKeyCallbackAndAlgorithms(cfg)
|
||||
}
|
||||
|
||||
21
vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go
generated
vendored
21
vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go
generated
vendored
@@ -11,7 +11,6 @@ import (
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
|
||||
"github.com/skeema/knownhosts"
|
||||
|
||||
"github.com/kevinburke/ssh_config"
|
||||
"golang.org/x/crypto/ssh"
|
||||
@@ -49,7 +48,9 @@ type runner struct {
|
||||
func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.AuthMethod) (common.Command, error) {
|
||||
c := &command{command: cmd, endpoint: ep, config: r.config}
|
||||
if auth != nil {
|
||||
c.setAuth(auth)
|
||||
if err := c.setAuth(auth); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.connect(); err != nil {
|
||||
@@ -125,17 +126,17 @@ func (c *command) connect() error {
|
||||
}
|
||||
hostWithPort := c.getHostWithPort()
|
||||
if config.HostKeyCallback == nil {
|
||||
kh, err := newKnownHosts()
|
||||
db, err := NewKnownHostsDb()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.HostKeyCallback = kh.HostKeyCallback()
|
||||
config.HostKeyAlgorithms = kh.HostKeyAlgorithms(hostWithPort)
|
||||
} else if len(config.HostKeyAlgorithms) == 0 {
|
||||
// Set the HostKeyAlgorithms based on HostKeyCallback.
|
||||
// For background see https://github.com/go-git/go-git/issues/411 as well as
|
||||
// https://github.com/golang/go/issues/29286 for root cause.
|
||||
config.HostKeyAlgorithms = knownhosts.HostKeyAlgorithms(config.HostKeyCallback, hostWithPort)
|
||||
config.HostKeyCallback = db.HostKeyCallback()
|
||||
config.HostKeyAlgorithms = db.HostKeyAlgorithms(hostWithPort)
|
||||
} else {
|
||||
// If the user gave a custom HostKeyCallback, we do not try to detect host key algorithms
|
||||
// based on knownhosts functionality, as the user may be requesting a FixedKey or using a
|
||||
// different key approval strategy. In that case, the user is responsible for populating
|
||||
// HostKeyAlgorithms appropriately
|
||||
}
|
||||
|
||||
overrideConfig(c.config, config)
|
||||
|
||||
86
vendor/github.com/go-git/go-git/v5/remote.go
generated
vendored
86
vendor/github.com/go-git/go-git/v5/remote.go
generated
vendored
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/internal/url"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
@@ -82,7 +83,7 @@ func (r *Remote) String() string {
|
||||
var fetch, push string
|
||||
if len(r.c.URLs) > 0 {
|
||||
fetch = r.c.URLs[0]
|
||||
push = r.c.URLs[0]
|
||||
push = r.c.URLs[len(r.c.URLs)-1]
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s\t%s (fetch)\n%[1]s\t%[3]s (push)", r.c.Name, fetch, push)
|
||||
@@ -109,11 +110,11 @@ 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)
|
||||
}
|
||||
|
||||
if o.RemoteURL == "" {
|
||||
o.RemoteURL = r.c.URLs[0]
|
||||
if o.RemoteURL == "" && len(r.c.URLs) > 0 {
|
||||
o.RemoteURL = r.c.URLs[len(r.c.URLs)-1]
|
||||
}
|
||||
|
||||
s, err := newSendPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions)
|
||||
s, err := newSendPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.ClientCert, o.ClientKey, o.CABundle, o.ProxyOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -415,7 +416,7 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
|
||||
o.RemoteURL = r.c.URLs[0]
|
||||
}
|
||||
|
||||
s, err := newUploadPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions)
|
||||
s, err := newUploadPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.ClientCert, o.ClientKey, o.CABundle, o.ProxyOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -470,6 +471,14 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
|
||||
}
|
||||
}
|
||||
|
||||
var updatedPrune bool
|
||||
if o.Prune {
|
||||
updatedPrune, err = r.pruneRemotes(o.RefSpecs, localRefs, remoteRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs, specToRefs, o.Tags, o.Force)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -482,8 +491,19 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
|
||||
}
|
||||
}
|
||||
|
||||
if !updated {
|
||||
return remoteRefs, NoErrAlreadyUpToDate
|
||||
if !updated && !updatedPrune {
|
||||
// No references updated, but may have fetched new objects, check if we now have any of our wants
|
||||
for _, hash := range req.Wants {
|
||||
exists, _ := objectExists(r.s, hash)
|
||||
if exists {
|
||||
updated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !updated {
|
||||
return remoteRefs, NoErrAlreadyUpToDate
|
||||
}
|
||||
}
|
||||
|
||||
return remoteRefs, nil
|
||||
@@ -512,8 +532,8 @@ func depthChanged(before []plumbing.Hash, s storage.Storer) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func newUploadPackSession(url string, auth transport.AuthMethod, insecure bool, cabundle []byte, proxyOpts transport.ProxyOptions) (transport.UploadPackSession, error) {
|
||||
c, ep, err := newClient(url, insecure, cabundle, proxyOpts)
|
||||
func newUploadPackSession(url string, auth transport.AuthMethod, insecure bool, clientCert, clientKey, caBundle []byte, proxyOpts transport.ProxyOptions) (transport.UploadPackSession, error) {
|
||||
c, ep, err := newClient(url, insecure, clientCert, clientKey, caBundle, proxyOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -521,8 +541,8 @@ func newUploadPackSession(url string, auth transport.AuthMethod, insecure bool,
|
||||
return c.NewUploadPackSession(ep, auth)
|
||||
}
|
||||
|
||||
func newSendPackSession(url string, auth transport.AuthMethod, insecure bool, cabundle []byte, proxyOpts transport.ProxyOptions) (transport.ReceivePackSession, error) {
|
||||
c, ep, err := newClient(url, insecure, cabundle, proxyOpts)
|
||||
func newSendPackSession(url string, auth transport.AuthMethod, insecure bool, clientCert, clientKey, caBundle []byte, proxyOpts transport.ProxyOptions) (transport.ReceivePackSession, error) {
|
||||
c, ep, err := newClient(url, insecure, clientCert, clientKey, caBundle, proxyOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -530,13 +550,15 @@ func newSendPackSession(url string, auth transport.AuthMethod, insecure bool, ca
|
||||
return c.NewReceivePackSession(ep, auth)
|
||||
}
|
||||
|
||||
func newClient(url string, insecure bool, cabundle []byte, proxyOpts transport.ProxyOptions) (transport.Transport, *transport.Endpoint, error) {
|
||||
func newClient(url string, insecure bool, clientCert, clientKey, caBundle []byte, proxyOpts transport.ProxyOptions) (transport.Transport, *transport.Endpoint, error) {
|
||||
ep, err := transport.NewEndpoint(url)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ep.InsecureSkipTLS = insecure
|
||||
ep.CaBundle = cabundle
|
||||
ep.ClientCert = clientCert
|
||||
ep.ClientKey = clientKey
|
||||
ep.CaBundle = caBundle
|
||||
ep.Proxy = proxyOpts
|
||||
|
||||
c, err := client.NewClient(ep)
|
||||
@@ -574,6 +596,27 @@ func (r *Remote) fetchPack(ctx context.Context, o *FetchOptions, s transport.Upl
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Remote) pruneRemotes(specs []config.RefSpec, localRefs []*plumbing.Reference, remoteRefs memory.ReferenceStorage) (bool, error) {
|
||||
var updatedPrune bool
|
||||
for _, spec := range specs {
|
||||
rev := spec.Reverse()
|
||||
for _, ref := range localRefs {
|
||||
if !rev.Match(ref.Name()) {
|
||||
continue
|
||||
}
|
||||
_, err := remoteRefs.Reference(rev.Dst(ref.Name()))
|
||||
if errors.Is(err, plumbing.ErrReferenceNotFound) {
|
||||
updatedPrune = true
|
||||
err := r.s.RemoveReference(ref.Name())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return updatedPrune, nil
|
||||
}
|
||||
|
||||
func (r *Remote) addReferencesToUpdate(
|
||||
refspecs []config.RefSpec,
|
||||
localRefs []*plumbing.Reference,
|
||||
@@ -849,17 +892,12 @@ func getHavesFromRef(
|
||||
return nil
|
||||
}
|
||||
|
||||
// No need to load the commit if we know the remote already
|
||||
// has this hash.
|
||||
if remoteRefs[h] {
|
||||
haves[h] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
commit, err := object.GetCommit(s, h)
|
||||
if err != nil {
|
||||
// Ignore the error if this isn't a commit.
|
||||
haves[ref.Hash()] = true
|
||||
if !errors.Is(err, plumbing.ErrObjectNotFound) {
|
||||
// Ignore the error if this isn't a commit.
|
||||
haves[ref.Hash()] = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1099,7 +1137,7 @@ func isFastForward(s storer.EncodedObjectStorer, old, new plumbing.Hash, earlies
|
||||
}
|
||||
|
||||
found := false
|
||||
// stop iterating at the earlist shallow commit, ignoring its parents
|
||||
// stop iterating at the earliest shallow commit, ignoring its parents
|
||||
// note: when pull depth is smaller than the number of new changes on the remote, this fails due to missing parents.
|
||||
// as far as i can tell, without the commits in-between the shallow pull and the earliest shallow, there's no
|
||||
// real way of telling whether it will be a fast-forward merge.
|
||||
@@ -1320,7 +1358,7 @@ func (r *Remote) list(ctx context.Context, o *ListOptions) (rfs []*plumbing.Refe
|
||||
return nil, ErrEmptyUrls
|
||||
}
|
||||
|
||||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions)
|
||||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.ClientCert, o.ClientKey, o.CABundle, o.ProxyOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
72
vendor/github.com/go-git/go-git/v5/repository.go
generated
vendored
72
vendor/github.com/go-git/go-git/v5/repository.go
generated
vendored
@@ -19,6 +19,7 @@ import (
|
||||
"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/path_util"
|
||||
"github.com/go-git/go-git/v5/internal/revision"
|
||||
@@ -51,19 +52,21 @@ var (
|
||||
// ErrFetching is returned when the packfile could not be downloaded
|
||||
ErrFetching = errors.New("unable to fetch packfile")
|
||||
|
||||
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")
|
||||
ErrAnonymousRemoteName = errors.New("anonymous remote name must be 'anonymous'")
|
||||
ErrWorktreeNotProvided = errors.New("worktree should be provided")
|
||||
ErrIsBareRepository = errors.New("worktree not available in a bare repository")
|
||||
ErrUnableToResolveCommit = errors.New("unable to resolve commit")
|
||||
ErrPackedObjectsNotSupported = errors.New("packed objects not supported")
|
||||
ErrSHA256NotSupported = errors.New("go-git was not compiled with SHA256 support")
|
||||
ErrAlternatePathNotSupported = errors.New("alternate path must use the file scheme")
|
||||
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")
|
||||
ErrAnonymousRemoteName = errors.New("anonymous remote name must be 'anonymous'")
|
||||
ErrWorktreeNotProvided = errors.New("worktree should be provided")
|
||||
ErrIsBareRepository = errors.New("worktree not available in a bare repository")
|
||||
ErrUnableToResolveCommit = errors.New("unable to resolve commit")
|
||||
ErrPackedObjectsNotSupported = errors.New("packed objects not supported")
|
||||
ErrSHA256NotSupported = errors.New("go-git was not compiled with SHA256 support")
|
||||
ErrAlternatePathNotSupported = errors.New("alternate path must use the file scheme")
|
||||
ErrUnsupportedMergeStrategy = errors.New("unsupported merge strategy")
|
||||
ErrFastForwardMergeNotPossible = errors.New("not possible to fast-forward merge changes")
|
||||
)
|
||||
|
||||
// Repository represents a git repository
|
||||
@@ -928,6 +931,8 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
|
||||
Tags: o.Tags,
|
||||
RemoteName: o.RemoteName,
|
||||
InsecureSkipTLS: o.InsecureSkipTLS,
|
||||
ClientCert: o.ClientCert,
|
||||
ClientKey: o.ClientKey,
|
||||
CABundle: o.CABundle,
|
||||
ProxyOptions: o.ProxyOptions,
|
||||
}, o.ReferenceName)
|
||||
@@ -954,7 +959,7 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
|
||||
}
|
||||
|
||||
if o.RecurseSubmodules != NoRecurseSubmodules {
|
||||
if err := w.updateSubmodules(&SubmoduleUpdateOptions{
|
||||
if err := w.updateSubmodules(ctx, &SubmoduleUpdateOptions{
|
||||
RecurseSubmodules: o.RecurseSubmodules,
|
||||
Depth: func() int {
|
||||
if o.ShallowSubmodules {
|
||||
@@ -1035,7 +1040,7 @@ func (r *Repository) setIsBare(isBare bool) error {
|
||||
return r.Storer.SetConfig(cfg)
|
||||
}
|
||||
|
||||
func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.RemoteConfig, head *plumbing.Reference) error {
|
||||
func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.RemoteConfig, _ *plumbing.Reference) error {
|
||||
if !o.SingleBranch {
|
||||
return nil
|
||||
}
|
||||
@@ -1769,8 +1774,43 @@ func (r *Repository) RepackObjects(cfg *RepackConfig) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Merge merges the reference branch into the current branch.
|
||||
//
|
||||
// If the merge is not possible (or supported) returns an error without changing
|
||||
// the HEAD for the current branch. Possible errors include:
|
||||
// - The merge strategy is not supported.
|
||||
// - The specific strategy cannot be used (e.g. using FastForwardMerge when one is not possible).
|
||||
func (r *Repository) Merge(ref plumbing.Reference, opts MergeOptions) error {
|
||||
if opts.Strategy != FastForwardMerge {
|
||||
return ErrUnsupportedMergeStrategy
|
||||
}
|
||||
|
||||
// Ignore error as not having a shallow list is optional here.
|
||||
shallowList, _ := r.Storer.Shallow()
|
||||
var earliestShallow *plumbing.Hash
|
||||
if len(shallowList) > 0 {
|
||||
earliestShallow = &shallowList[0]
|
||||
}
|
||||
|
||||
head, err := r.Head()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ff, err := isFastForward(r.Storer, head.Hash(), ref.Hash(), earliestShallow)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ff {
|
||||
return ErrFastForwardMergeNotPossible
|
||||
}
|
||||
|
||||
return r.Storer.SetReference(plumbing.NewHashReference(head.Name(), ref.Hash()))
|
||||
}
|
||||
|
||||
// createNewObjectPack is a helper for RepackObjects taking care
|
||||
// of creating a new pack. It is used so the the PackfileWriter
|
||||
// of creating a new pack. It is used so the PackfileWriter
|
||||
// deferred close has the right scope.
|
||||
func (r *Repository) createNewObjectPack(cfg *RepackConfig) (h plumbing.Hash, err error) {
|
||||
ow := newObjectWalker(r.Storer)
|
||||
|
||||
33
vendor/github.com/go-git/go-git/v5/signer.go
generated
vendored
Normal file
33
vendor/github.com/go-git/go-git/v5/signer.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
)
|
||||
|
||||
// signableObject is an object which can be signed.
|
||||
type signableObject interface {
|
||||
EncodeWithoutSignature(o plumbing.EncodedObject) error
|
||||
}
|
||||
|
||||
// Signer is an interface for signing git objects.
|
||||
// message is a reader containing the encoded object to be signed.
|
||||
// Implementors should return the encoded signature and an error if any.
|
||||
// See https://git-scm.com/docs/gitformat-signature for more information.
|
||||
type Signer interface {
|
||||
Sign(message io.Reader) ([]byte, error)
|
||||
}
|
||||
|
||||
func signObject(signer Signer, obj signableObject) ([]byte, error) {
|
||||
encoded := &plumbing.MemoryObject{}
|
||||
if err := obj.EncodeWithoutSignature(encoded); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r, err := encoded.Reader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return signer.Sign(r)
|
||||
}
|
||||
69
vendor/github.com/go-git/go-git/v5/status.go
generated
vendored
69
vendor/github.com/go-git/go-git/v5/status.go
generated
vendored
@@ -4,6 +4,9 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
mindex "github.com/go-git/go-git/v5/utils/merkletrie/index"
|
||||
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
|
||||
)
|
||||
|
||||
// Status represents the current status of a Worktree.
|
||||
@@ -77,3 +80,69 @@ const (
|
||||
Copied StatusCode = 'C'
|
||||
UpdatedButUnmerged StatusCode = 'U'
|
||||
)
|
||||
|
||||
// StatusStrategy defines the different types of strategies when processing
|
||||
// the worktree status.
|
||||
type StatusStrategy int
|
||||
|
||||
const (
|
||||
// TODO: (V6) Review the default status strategy.
|
||||
// TODO: (V6) Review the type used to represent Status, to enable lazy
|
||||
// processing of statuses going direct to the backing filesystem.
|
||||
defaultStatusStrategy = Empty
|
||||
|
||||
// Empty starts its status map from empty. Missing entries for a given
|
||||
// path means that the file is untracked. This causes a known issue (#119)
|
||||
// whereby unmodified files can be incorrectly reported as untracked.
|
||||
//
|
||||
// This can be used when returning the changed state within a modified Worktree.
|
||||
// For example, to check whether the current worktree is clean.
|
||||
Empty StatusStrategy = 0
|
||||
// Preload goes through all existing nodes from the index and add them to the
|
||||
// status map as unmodified. This is currently the most reliable strategy
|
||||
// although it comes at a performance cost in large repositories.
|
||||
//
|
||||
// This method is recommended when fetching the status of unmodified files.
|
||||
// For example, to confirm the status of a specific file that is either
|
||||
// untracked or unmodified.
|
||||
Preload StatusStrategy = 1
|
||||
)
|
||||
|
||||
func (s StatusStrategy) new(w *Worktree) (Status, error) {
|
||||
switch s {
|
||||
case Preload:
|
||||
return preloadStatus(w)
|
||||
case Empty:
|
||||
return make(Status), nil
|
||||
}
|
||||
return nil, fmt.Errorf("%w: %+v", ErrUnsupportedStatusStrategy, s)
|
||||
}
|
||||
|
||||
func preloadStatus(w *Worktree) (Status, error) {
|
||||
idx, err := w.r.Storer.Index()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
idxRoot := mindex.NewRootNode(idx)
|
||||
nodes := []noder.Noder{idxRoot}
|
||||
|
||||
status := make(Status)
|
||||
for len(nodes) > 0 {
|
||||
var node noder.Noder
|
||||
node, nodes = nodes[0], nodes[1:]
|
||||
if node.IsDir() {
|
||||
children, err := node.Children()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodes = append(nodes, children...)
|
||||
continue
|
||||
}
|
||||
fs := status.File(node.Name())
|
||||
fs.Worktree = Unmodified
|
||||
fs.Staging = Unmodified
|
||||
}
|
||||
|
||||
return status, nil
|
||||
}
|
||||
|
||||
35
vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go
generated
vendored
35
vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go
generated
vendored
@@ -72,6 +72,9 @@ var (
|
||||
// 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")
|
||||
// ErrEmptyRefFile is returned when a reference file is attempted to be read,
|
||||
// but the file is empty
|
||||
ErrEmptyRefFile = errors.New("ref file is empty")
|
||||
)
|
||||
|
||||
// Options holds configuration for the storage.
|
||||
@@ -249,7 +252,7 @@ func (d *DotGit) objectPacks() ([]plumbing.Hash, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
h := plumbing.NewHash(n[5 : len(n)-5]) //pack-(hash).pack
|
||||
h := plumbing.NewHash(n[5 : len(n)-5]) // pack-(hash).pack
|
||||
if h.IsZero() {
|
||||
// Ignore files with badly-formatted names.
|
||||
continue
|
||||
@@ -661,18 +664,33 @@ func (d *DotGit) readReferenceFrom(rd io.Reader, name string) (ref *plumbing.Ref
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(b) == 0 {
|
||||
return nil, ErrEmptyRefFile
|
||||
}
|
||||
|
||||
line := strings.TrimSpace(string(b))
|
||||
return plumbing.NewReferenceFromStrings(name, line), nil
|
||||
}
|
||||
|
||||
// checkReferenceAndTruncate reads the reference from the given file, or the `pack-refs` file if
|
||||
// the file was empty. Then it checks that the old reference matches the stored reference and
|
||||
// truncates the file.
|
||||
func (d *DotGit) checkReferenceAndTruncate(f billy.File, old *plumbing.Reference) error {
|
||||
if old == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ref, err := d.readReferenceFrom(f, old.Name().String())
|
||||
if errors.Is(err, ErrEmptyRefFile) {
|
||||
// This may happen if the reference is being read from a newly created file.
|
||||
// In that case, try getting the reference from the packed refs file.
|
||||
ref, err = d.packedRef(old.Name())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ref.Hash() != old.Hash() {
|
||||
return storage.ErrReferenceHasChanged
|
||||
}
|
||||
@@ -701,7 +719,11 @@ func (d *DotGit) SetRef(r, old *plumbing.Reference) error {
|
||||
// Symbolic references are resolved and included in the output.
|
||||
func (d *DotGit) Refs() ([]*plumbing.Reference, error) {
|
||||
var refs []*plumbing.Reference
|
||||
var seen = make(map[plumbing.ReferenceName]bool)
|
||||
seen := make(map[plumbing.ReferenceName]bool)
|
||||
if err := d.addRefFromHEAD(&refs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -710,10 +732,6 @@ func (d *DotGit) Refs() ([]*plumbing.Reference, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := d.addRefFromHEAD(&refs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
@@ -815,7 +833,8 @@ func (d *DotGit) addRefsFromPackedRefsFile(refs *[]*plumbing.Reference, f billy.
|
||||
}
|
||||
|
||||
func (d *DotGit) openAndLockPackedRefs(doCreate bool) (
|
||||
pr billy.File, err error) {
|
||||
pr billy.File, err error,
|
||||
) {
|
||||
var f billy.File
|
||||
defer func() {
|
||||
if err != nil && f != nil {
|
||||
@@ -1020,7 +1039,7 @@ func (d *DotGit) readReferenceFile(path, name string) (ref *plumbing.Reference,
|
||||
|
||||
func (d *DotGit) CountLooseRefs() (int, error) {
|
||||
var refs []*plumbing.Reference
|
||||
var seen = make(map[plumbing.ReferenceName]bool)
|
||||
seen := make(map[plumbing.ReferenceName]bool)
|
||||
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
2
vendor/github.com/go-git/go-git/v5/storage/filesystem/index.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/storage/filesystem/index.go
generated
vendored
@@ -48,7 +48,7 @@ func (s *IndexStorage) Index() (i *index.Index, err error) {
|
||||
|
||||
defer ioutil.CheckClose(f, &err)
|
||||
|
||||
d := index.NewDecoder(bufio.NewReader(f))
|
||||
d := index.NewDecoder(f)
|
||||
err = d.Decode(idx)
|
||||
return idx, err
|
||||
}
|
||||
|
||||
31
vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go
generated
vendored
31
vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go
generated
vendored
@@ -2,6 +2,8 @@ package filesystem
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
@@ -87,6 +89,11 @@ func (s *ObjectStorage) loadIdxFile(h plumbing.Hash) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if !bytes.Equal(idxf.PackfileChecksum[:], h[:]) {
|
||||
return fmt.Errorf("%w: packfile mismatch: target is %q not %q",
|
||||
idxfile.ErrMalformedIdxFile, hex.EncodeToString(idxf.PackfileChecksum[:]), h.String())
|
||||
}
|
||||
|
||||
s.index[h] = idxf
|
||||
return err
|
||||
}
|
||||
@@ -186,7 +193,8 @@ func (s *ObjectStorage) HasEncodedObject(h plumbing.Hash) (err error) {
|
||||
}
|
||||
|
||||
func (s *ObjectStorage) encodedObjectSizeFromUnpacked(h plumbing.Hash) (
|
||||
size int64, err error) {
|
||||
size int64, err error,
|
||||
) {
|
||||
f, err := s.dir.Object(h)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
@@ -274,7 +282,8 @@ func (s *ObjectStorage) storePackfileInCache(hash plumbing.Hash, p *packfile.Pac
|
||||
}
|
||||
|
||||
func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) (
|
||||
size int64, err error) {
|
||||
size int64, err error,
|
||||
) {
|
||||
if err := s.requireIndex(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -310,7 +319,8 @@ func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) (
|
||||
// EncodedObjectSize returns the plaintext size of the given object,
|
||||
// without actually reading the full object data from storage.
|
||||
func (s *ObjectStorage) EncodedObjectSize(h plumbing.Hash) (
|
||||
size int64, err error) {
|
||||
size int64, err error,
|
||||
) {
|
||||
size, err = s.encodedObjectSizeFromUnpacked(h)
|
||||
if err != nil && err != plumbing.ErrObjectNotFound {
|
||||
return 0, err
|
||||
@@ -371,7 +381,8 @@ func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (p
|
||||
// DeltaObject returns the object with the given hash, by searching for
|
||||
// it in the packfile and the git object directories.
|
||||
func (s *ObjectStorage) DeltaObject(t plumbing.ObjectType,
|
||||
h plumbing.Hash) (plumbing.EncodedObject, error) {
|
||||
h plumbing.Hash,
|
||||
) (plumbing.EncodedObject, error) {
|
||||
obj, err := s.getFromUnpacked(h)
|
||||
if err == plumbing.ErrObjectNotFound {
|
||||
obj, err = s.getFromPackfile(h, true)
|
||||
@@ -431,13 +442,13 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb
|
||||
|
||||
defer ioutil.CheckClose(w, &err)
|
||||
|
||||
s.objectCache.Put(obj)
|
||||
|
||||
bufp := copyBufferPool.Get().(*[]byte)
|
||||
buf := *bufp
|
||||
_, err = io.CopyBuffer(w, r, buf)
|
||||
copyBufferPool.Put(bufp)
|
||||
|
||||
s.objectCache.Put(obj)
|
||||
|
||||
return obj, err
|
||||
}
|
||||
|
||||
@@ -451,8 +462,8 @@ var copyBufferPool = sync.Pool{
|
||||
// Get returns the object with the given hash, by searching for it in
|
||||
// the packfile.
|
||||
func (s *ObjectStorage) getFromPackfile(h plumbing.Hash, canBeDelta bool) (
|
||||
plumbing.EncodedObject, error) {
|
||||
|
||||
plumbing.EncodedObject, error,
|
||||
) {
|
||||
if err := s.requireIndex(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -509,9 +520,7 @@ func (s *ObjectStorage) decodeDeltaObjectAt(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
base plumbing.Hash
|
||||
)
|
||||
var base plumbing.Hash
|
||||
|
||||
switch header.Type {
|
||||
case plumbing.REFDeltaObject:
|
||||
|
||||
6
vendor/github.com/go-git/go-git/v5/submodule.go
generated
vendored
6
vendor/github.com/go-git/go-git/v5/submodule.go
generated
vendored
@@ -214,10 +214,10 @@ func (s *Submodule) update(ctx context.Context, o *SubmoduleUpdateOptions, force
|
||||
return err
|
||||
}
|
||||
|
||||
return s.doRecursiveUpdate(r, o)
|
||||
return s.doRecursiveUpdate(ctx, r, o)
|
||||
}
|
||||
|
||||
func (s *Submodule) doRecursiveUpdate(r *Repository, o *SubmoduleUpdateOptions) error {
|
||||
func (s *Submodule) doRecursiveUpdate(ctx context.Context, r *Repository, o *SubmoduleUpdateOptions) error {
|
||||
if o.RecurseSubmodules == NoRecurseSubmodules {
|
||||
return nil
|
||||
}
|
||||
@@ -236,7 +236,7 @@ func (s *Submodule) doRecursiveUpdate(r *Repository, o *SubmoduleUpdateOptions)
|
||||
*new = *o
|
||||
|
||||
new.RecurseSubmodules--
|
||||
return l.Update(new)
|
||||
return l.UpdateContext(ctx, new)
|
||||
}
|
||||
|
||||
func (s *Submodule) fetchAndCheckout(
|
||||
|
||||
15
vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go
generated
vendored
15
vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go
generated
vendored
@@ -1,12 +1,17 @@
|
||||
package merkletrie
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrEmptyFileName = errors.New("empty filename in tree entry")
|
||||
)
|
||||
|
||||
// Action values represent the kind of things a Change can represent:
|
||||
// insertion, deletions or modifications of files.
|
||||
type Action int
|
||||
@@ -121,8 +126,14 @@ func (l *Changes) AddRecursiveDelete(root noder.Path) error {
|
||||
type noderToChangeFn func(noder.Path) Change // NewInsert or NewDelete
|
||||
|
||||
func (l *Changes) addRecursive(root noder.Path, ctor noderToChangeFn) error {
|
||||
if root.String() == "" {
|
||||
return ErrEmptyFileName
|
||||
}
|
||||
|
||||
if !root.IsDir() {
|
||||
l.Add(ctor(root))
|
||||
if !root.Skip() {
|
||||
l.Add(ctor(root))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -139,7 +150,7 @@ func (l *Changes) addRecursive(root noder.Path, ctor noderToChangeFn) error {
|
||||
}
|
||||
return err
|
||||
}
|
||||
if current.IsDir() {
|
||||
if current.IsDir() || current.Skip() {
|
||||
continue
|
||||
}
|
||||
l.Add(ctor(current))
|
||||
|
||||
45
vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go
generated
vendored
45
vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go
generated
vendored
@@ -11,7 +11,7 @@ package merkletrie
|
||||
// corresponding changes and move the iterators further over both
|
||||
// trees.
|
||||
//
|
||||
// The table bellow show all the possible comparison results, along
|
||||
// The table below shows all the possible comparison results, along
|
||||
// with what changes should we produce and how to advance the
|
||||
// iterators.
|
||||
//
|
||||
@@ -297,18 +297,16 @@ func DiffTreeContext(ctx context.Context, fromTree, toTree noder.Noder,
|
||||
case noMoreNoders:
|
||||
return ret, nil
|
||||
case onlyFromRemains:
|
||||
if err = ret.AddRecursiveDelete(from); err != nil {
|
||||
return nil, err
|
||||
if !from.Skip() {
|
||||
if err = ret.AddRecursiveDelete(from); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err = ii.nextFrom(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case onlyToRemains:
|
||||
if to.Skip() {
|
||||
if err = ret.AddRecursiveDelete(to); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if !to.Skip() {
|
||||
if err = ret.AddRecursiveInsert(to); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -317,26 +315,25 @@ func DiffTreeContext(ctx context.Context, fromTree, toTree noder.Noder,
|
||||
return nil, err
|
||||
}
|
||||
case bothHaveNodes:
|
||||
if from.Skip() {
|
||||
if err = ret.AddRecursiveDelete(from); err != nil {
|
||||
return nil, err
|
||||
var err error
|
||||
switch {
|
||||
case from.Skip():
|
||||
if from.Name() == to.Name() {
|
||||
err = ii.nextBoth()
|
||||
} else {
|
||||
err = ii.nextFrom()
|
||||
}
|
||||
if err := ii.nextBoth(); err != nil {
|
||||
return nil, err
|
||||
case to.Skip():
|
||||
if from.Name() == to.Name() {
|
||||
err = ii.nextBoth()
|
||||
} else {
|
||||
err = ii.nextTo()
|
||||
}
|
||||
break
|
||||
}
|
||||
if to.Skip() {
|
||||
if err = ret.AddRecursiveDelete(to); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ii.nextBoth(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
break
|
||||
default:
|
||||
err = diffNodes(&ret, ii)
|
||||
}
|
||||
|
||||
if err = diffNodes(&ret, ii); err != nil {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
|
||||
80
vendor/github.com/go-git/go-git/v5/utils/merkletrie/filesystem/node.go
generated
vendored
80
vendor/github.com/go-git/go-git/v5/utils/merkletrie/filesystem/node.go
generated
vendored
@@ -29,6 +29,8 @@ type node struct {
|
||||
hash []byte
|
||||
children []noder.Noder
|
||||
isDir bool
|
||||
mode os.FileMode
|
||||
size int64
|
||||
}
|
||||
|
||||
// NewRootNode returns the root node based on a given billy.Filesystem.
|
||||
@@ -48,8 +50,15 @@ func NewRootNode(
|
||||
// difftree algorithm will detect changes in the contents of files and also in
|
||||
// their mode.
|
||||
//
|
||||
// Please note that the hash is calculated on first invocation of Hash(),
|
||||
// meaning that it will not update when the underlying file changes
|
||||
// between invocations.
|
||||
//
|
||||
// The hash of a directory is always a 24-bytes slice of zero values
|
||||
func (n *node) Hash() []byte {
|
||||
if n.hash == nil {
|
||||
n.calculateHash()
|
||||
}
|
||||
return n.hash
|
||||
}
|
||||
|
||||
@@ -121,81 +130,74 @@ func (n *node) calculateChildren() error {
|
||||
func (n *node) newChildNode(file os.FileInfo) (*node, error) {
|
||||
path := path.Join(n.path, file.Name())
|
||||
|
||||
hash, err := n.calculateHash(path, file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node := &node{
|
||||
fs: n.fs,
|
||||
submodules: n.submodules,
|
||||
|
||||
path: path,
|
||||
hash: hash,
|
||||
isDir: file.IsDir(),
|
||||
size: file.Size(),
|
||||
mode: file.Mode(),
|
||||
}
|
||||
|
||||
if hash, isSubmodule := n.submodules[path]; isSubmodule {
|
||||
node.hash = append(hash[:], filemode.Submodule.Bytes()...)
|
||||
if _, isSubmodule := n.submodules[path]; isSubmodule {
|
||||
node.isDir = false
|
||||
}
|
||||
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (n *node) calculateHash(path string, file os.FileInfo) ([]byte, error) {
|
||||
if file.IsDir() {
|
||||
return make([]byte, 24), nil
|
||||
func (n *node) calculateHash() {
|
||||
if n.isDir {
|
||||
n.hash = make([]byte, 24)
|
||||
return
|
||||
}
|
||||
mode, err := filemode.NewFromOSFileMode(n.mode)
|
||||
if err != nil {
|
||||
n.hash = plumbing.ZeroHash[:]
|
||||
return
|
||||
}
|
||||
if submoduleHash, isSubmodule := n.submodules[n.path]; isSubmodule {
|
||||
n.hash = append(submoduleHash[:], filemode.Submodule.Bytes()...)
|
||||
return
|
||||
}
|
||||
|
||||
var hash plumbing.Hash
|
||||
var err error
|
||||
if file.Mode()&os.ModeSymlink != 0 {
|
||||
hash, err = n.doCalculateHashForSymlink(path, file)
|
||||
if n.mode&os.ModeSymlink != 0 {
|
||||
hash = n.doCalculateHashForSymlink()
|
||||
} else {
|
||||
hash, err = n.doCalculateHashForRegular(path, file)
|
||||
hash = n.doCalculateHashForRegular()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mode, err := filemode.NewFromOSFileMode(file.Mode())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append(hash[:], mode.Bytes()...), nil
|
||||
n.hash = append(hash[:], mode.Bytes()...)
|
||||
}
|
||||
|
||||
func (n *node) doCalculateHashForRegular(path string, file os.FileInfo) (plumbing.Hash, error) {
|
||||
f, err := n.fs.Open(path)
|
||||
func (n *node) doCalculateHashForRegular() plumbing.Hash {
|
||||
f, err := n.fs.Open(n.path)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
return plumbing.ZeroHash
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
h := plumbing.NewHasher(plumbing.BlobObject, file.Size())
|
||||
h := plumbing.NewHasher(plumbing.BlobObject, n.size)
|
||||
if _, err := io.Copy(h, f); err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
return plumbing.ZeroHash
|
||||
}
|
||||
|
||||
return h.Sum(), nil
|
||||
return h.Sum()
|
||||
}
|
||||
|
||||
func (n *node) doCalculateHashForSymlink(path string, file os.FileInfo) (plumbing.Hash, error) {
|
||||
target, err := n.fs.Readlink(path)
|
||||
func (n *node) doCalculateHashForSymlink() plumbing.Hash {
|
||||
target, err := n.fs.Readlink(n.path)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
return plumbing.ZeroHash
|
||||
}
|
||||
|
||||
h := plumbing.NewHasher(plumbing.BlobObject, file.Size())
|
||||
h := plumbing.NewHasher(plumbing.BlobObject, n.size)
|
||||
if _, err := h.Write([]byte(target)); err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
return plumbing.ZeroHash
|
||||
}
|
||||
|
||||
return h.Sum(), nil
|
||||
return h.Sum()
|
||||
}
|
||||
|
||||
func (n *node) String() string {
|
||||
|
||||
10
vendor/github.com/go-git/go-git/v5/utils/merkletrie/index/node.go
generated
vendored
10
vendor/github.com/go-git/go-git/v5/utils/merkletrie/index/node.go
generated
vendored
@@ -36,7 +36,15 @@ func NewRootNode(idx *index.Index) noder.Noder {
|
||||
parent := fullpath
|
||||
fullpath = path.Join(fullpath, part)
|
||||
|
||||
if _, ok := m[fullpath]; ok {
|
||||
// It's possible that the first occurrence of subdirectory is skipped.
|
||||
// The parent node can be created with SkipWorktree set to true, but
|
||||
// if any future children do not skip their subtree, the entire lineage
|
||||
// of the tree needs to have this value set to false so that subdirectories
|
||||
// are not ignored.
|
||||
if parentNode, ok := m[fullpath]; ok {
|
||||
if e.SkipWorktree == false {
|
||||
parentNode.skip = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/go-git/go-git/v5/utils/sync/bufio.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/utils/sync/bufio.go
generated
vendored
@@ -13,7 +13,7 @@ var bufioReader = sync.Pool{
|
||||
}
|
||||
|
||||
// GetBufioReader returns a *bufio.Reader that is managed by a sync.Pool.
|
||||
// Returns a bufio.Reader that is resetted with reader and ready for use.
|
||||
// Returns a bufio.Reader that is reset with reader and ready for use.
|
||||
//
|
||||
// After use, the *bufio.Reader should be put back into the sync.Pool
|
||||
// by calling PutBufioReader.
|
||||
|
||||
2
vendor/github.com/go-git/go-git/v5/utils/sync/bytes.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/utils/sync/bytes.go
generated
vendored
@@ -35,7 +35,7 @@ func PutByteSlice(buf *[]byte) {
|
||||
}
|
||||
|
||||
// GetBytesBuffer returns a *bytes.Buffer that is managed by a sync.Pool.
|
||||
// Returns a buffer that is resetted and ready for use.
|
||||
// Returns a buffer that is reset and ready for use.
|
||||
//
|
||||
// After use, the *bytes.Buffer should be put back into the sync.Pool
|
||||
// by calling PutBytesBuffer.
|
||||
|
||||
4
vendor/github.com/go-git/go-git/v5/utils/sync/zlib.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/utils/sync/zlib.go
generated
vendored
@@ -35,7 +35,7 @@ type ZLibReader struct {
|
||||
}
|
||||
|
||||
// GetZlibReader returns a ZLibReader that is managed by a sync.Pool.
|
||||
// Returns a ZLibReader that is resetted using a dictionary that is
|
||||
// Returns a ZLibReader that is reset using a dictionary that is
|
||||
// also managed by a sync.Pool.
|
||||
//
|
||||
// After use, the ZLibReader should be put back into the sync.Pool
|
||||
@@ -58,7 +58,7 @@ func PutZlibReader(z ZLibReader) {
|
||||
}
|
||||
|
||||
// GetZlibWriter returns a *zlib.Writer that is managed by a sync.Pool.
|
||||
// Returns a writer that is resetted with w and ready for use.
|
||||
// Returns a writer that is reset with w and ready for use.
|
||||
//
|
||||
// After use, the *zlib.Writer should be put back into the sync.Pool
|
||||
// by calling PutZlibWriter.
|
||||
|
||||
171
vendor/github.com/go-git/go-git/v5/worktree.go
generated
vendored
171
vendor/github.com/go-git/go-git/v5/worktree.go
generated
vendored
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/go-git/go-billy/v5/util"
|
||||
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/filemode"
|
||||
@@ -25,11 +26,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrWorktreeNotClean = errors.New("worktree is not clean")
|
||||
ErrSubmoduleNotFound = errors.New("submodule not found")
|
||||
ErrUnstagedChanges = errors.New("worktree contains unstaged changes")
|
||||
ErrGitModulesSymlink = errors.New(gitmodulesFile + " is a symlink")
|
||||
ErrNonFastForwardUpdate = errors.New("non-fast-forward update")
|
||||
ErrWorktreeNotClean = errors.New("worktree is not clean")
|
||||
ErrSubmoduleNotFound = errors.New("submodule not found")
|
||||
ErrUnstagedChanges = errors.New("worktree contains unstaged changes")
|
||||
ErrGitModulesSymlink = errors.New(gitmodulesFile + " is a symlink")
|
||||
ErrNonFastForwardUpdate = errors.New("non-fast-forward update")
|
||||
ErrRestoreWorktreeOnlyNotSupported = errors.New("worktree only is not supported")
|
||||
)
|
||||
|
||||
// Worktree represents a git worktree.
|
||||
@@ -78,6 +80,8 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
|
||||
Progress: o.Progress,
|
||||
Force: o.Force,
|
||||
InsecureSkipTLS: o.InsecureSkipTLS,
|
||||
ClientCert: o.ClientCert,
|
||||
ClientKey: o.ClientKey,
|
||||
CABundle: o.CABundle,
|
||||
ProxyOptions: o.ProxyOptions,
|
||||
})
|
||||
@@ -139,7 +143,7 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
|
||||
}
|
||||
|
||||
if o.RecurseSubmodules != NoRecurseSubmodules {
|
||||
return w.updateSubmodules(&SubmoduleUpdateOptions{
|
||||
return w.updateSubmodules(ctx, &SubmoduleUpdateOptions{
|
||||
RecurseSubmodules: o.RecurseSubmodules,
|
||||
Auth: o.Auth,
|
||||
})
|
||||
@@ -148,13 +152,13 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *Worktree) updateSubmodules(o *SubmoduleUpdateOptions) error {
|
||||
func (w *Worktree) updateSubmodules(ctx context.Context, o *SubmoduleUpdateOptions) error {
|
||||
s, err := w.Submodules()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.Init = true
|
||||
return s.Update(o)
|
||||
return s.UpdateContext(ctx, o)
|
||||
}
|
||||
|
||||
// Checkout switch branches or restore working tree files.
|
||||
@@ -227,20 +231,17 @@ func (w *Worktree) createBranch(opts *CheckoutOptions) error {
|
||||
}
|
||||
|
||||
func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing.Hash, error) {
|
||||
if !opts.Hash.IsZero() {
|
||||
return opts.Hash, nil
|
||||
hash := opts.Hash
|
||||
if hash.IsZero() {
|
||||
b, err := w.r.Reference(opts.Branch, true)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
hash = b.Hash()
|
||||
}
|
||||
|
||||
b, err := w.r.Reference(opts.Branch, true)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
if !b.Name().IsTag() {
|
||||
return b.Hash(), nil
|
||||
}
|
||||
|
||||
o, err := w.r.Object(plumbing.AnyObject, b.Hash())
|
||||
o, err := w.r.Object(plumbing.AnyObject, hash)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
@@ -248,7 +249,7 @@ func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing
|
||||
switch o := o.(type) {
|
||||
case *object.Tag:
|
||||
if o.TargetType != plumbing.CommitObject {
|
||||
return plumbing.ZeroHash, fmt.Errorf("unsupported tag object target %q", o.TargetType)
|
||||
return plumbing.ZeroHash, fmt.Errorf("%w: tag target %q", object.ErrUnsupportedObject, o.TargetType)
|
||||
}
|
||||
|
||||
return o.Target, nil
|
||||
@@ -256,7 +257,7 @@ func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing
|
||||
return o.Hash, nil
|
||||
}
|
||||
|
||||
return plumbing.ZeroHash, fmt.Errorf("unsupported tag target %q", o.Type())
|
||||
return plumbing.ZeroHash, fmt.Errorf("%w: %q", object.ErrUnsupportedObject, o.Type())
|
||||
}
|
||||
|
||||
func (w *Worktree) setHEADToCommit(commit plumbing.Hash) error {
|
||||
@@ -309,14 +310,21 @@ func (w *Worktree) ResetSparsely(opts *ResetOptions, dirs []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var removedFiles []string
|
||||
if opts.Mode == MixedReset || opts.Mode == MergeReset || opts.Mode == HardReset {
|
||||
if err := w.resetIndex(t, dirs); err != nil {
|
||||
if removedFiles, err = w.resetIndex(t, dirs, opts.Files); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if opts.Mode == MergeReset || opts.Mode == HardReset {
|
||||
if err := w.resetWorktree(t); err != nil {
|
||||
if opts.Mode == MergeReset && len(removedFiles) > 0 {
|
||||
if err := w.resetWorktree(t, removedFiles); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if opts.Mode == HardReset {
|
||||
if err := w.resetWorktree(t, opts.Files); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -324,31 +332,64 @@ func (w *Worktree) ResetSparsely(opts *ResetOptions, dirs []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Restore restores specified files in the working tree or stage with contents from
|
||||
// a restore source. If a path is tracked but does not exist in the restore,
|
||||
// source, it will be removed to match the source.
|
||||
//
|
||||
// If Staged and Worktree are true, then the restore source will be the index.
|
||||
// If only Staged is true, then the restore source will be HEAD.
|
||||
// If only Worktree is true or neither Staged nor Worktree are true, will
|
||||
// result in ErrRestoreWorktreeOnlyNotSupported because restoring the working
|
||||
// tree while leaving the stage untouched is not currently supported.
|
||||
//
|
||||
// Restore with no files specified will return ErrNoRestorePaths.
|
||||
func (w *Worktree) Restore(o *RestoreOptions) error {
|
||||
if err := o.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if o.Staged {
|
||||
opts := &ResetOptions{
|
||||
Files: o.Files,
|
||||
}
|
||||
|
||||
if o.Worktree {
|
||||
// If we are doing both Worktree and Staging then it is a hard reset
|
||||
opts.Mode = HardReset
|
||||
} else {
|
||||
// If we are doing just staging then it is a mixed reset
|
||||
opts.Mode = MixedReset
|
||||
}
|
||||
|
||||
return w.Reset(opts)
|
||||
}
|
||||
|
||||
return ErrRestoreWorktreeOnlyNotSupported
|
||||
}
|
||||
|
||||
// Reset the worktree to a specified state.
|
||||
func (w *Worktree) Reset(opts *ResetOptions) error {
|
||||
return w.ResetSparsely(opts, nil)
|
||||
}
|
||||
|
||||
func (w *Worktree) resetIndex(t *object.Tree, dirs []string) error {
|
||||
func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) ([]string, error) {
|
||||
idx, err := w.r.Storer.Index()
|
||||
if len(dirs) > 0 {
|
||||
idx.SkipUnless(dirs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b := newIndexBuilder(idx)
|
||||
|
||||
changes, err := w.diffTreeWithStaging(t, true)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var removedFiles []string
|
||||
for _, ch := range changes {
|
||||
a, err := ch.Action()
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var name string
|
||||
@@ -359,13 +400,21 @@ func (w *Worktree) resetIndex(t *object.Tree, dirs []string) error {
|
||||
name = ch.To.String()
|
||||
e, err = t.FindEntry(name)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
case merkletrie.Delete:
|
||||
name = ch.From.String()
|
||||
}
|
||||
|
||||
if len(files) > 0 {
|
||||
contains := inFiles(files, name)
|
||||
if !contains {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
b.Remove(name)
|
||||
removedFiles = append(removedFiles, name)
|
||||
if e == nil {
|
||||
continue
|
||||
}
|
||||
@@ -379,10 +428,26 @@ func (w *Worktree) resetIndex(t *object.Tree, dirs []string) error {
|
||||
}
|
||||
|
||||
b.Write(idx)
|
||||
return w.r.Storer.SetIndex(idx)
|
||||
|
||||
if len(dirs) > 0 {
|
||||
idx.SkipUnless(dirs)
|
||||
}
|
||||
|
||||
return removedFiles, w.r.Storer.SetIndex(idx)
|
||||
}
|
||||
|
||||
func (w *Worktree) resetWorktree(t *object.Tree) error {
|
||||
func inFiles(files []string, v string) bool {
|
||||
v = filepath.Clean(v)
|
||||
for _, s := range files {
|
||||
if filepath.Clean(s) == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *Worktree) resetWorktree(t *object.Tree, files []string) error {
|
||||
changes, err := w.diffStagingWithWorktree(true, false)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -398,6 +463,25 @@ func (w *Worktree) resetWorktree(t *object.Tree) error {
|
||||
if err := w.validChange(ch); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(files) > 0 {
|
||||
file := ""
|
||||
if ch.From != nil {
|
||||
file = ch.From.String()
|
||||
} else if ch.To != nil {
|
||||
file = ch.To.String()
|
||||
}
|
||||
|
||||
if file == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
contains := inFiles(files, file)
|
||||
if !contains {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err := w.checkoutChange(ch, t, b); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -431,6 +515,10 @@ var worktreeDeny = map[string]struct{}{
|
||||
func validPath(paths ...string) error {
|
||||
for _, p := range paths {
|
||||
parts := strings.FieldsFunc(p, func(r rune) bool { return (r == '\\' || r == '/') })
|
||||
if len(parts) == 0 {
|
||||
return fmt.Errorf("invalid path: %q", p)
|
||||
}
|
||||
|
||||
if _, denied := worktreeDeny[strings.ToLower(parts[0])]; denied {
|
||||
return fmt.Errorf("invalid path prefix: %q", p)
|
||||
}
|
||||
@@ -641,7 +729,7 @@ func (w *Worktree) checkoutChangeRegularFile(name string,
|
||||
return err
|
||||
}
|
||||
|
||||
return w.addIndexFromFile(name, e.Hash, idx)
|
||||
return w.addIndexFromFile(name, e.Hash, f.Mode, idx)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -724,18 +812,13 @@ func (w *Worktree) addIndexFromTreeEntry(name string, f *object.TreeEntry, idx *
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, idx *indexBuilder) error {
|
||||
func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, mode filemode.FileMode, idx *indexBuilder) error {
|
||||
idx.Remove(name)
|
||||
fi, err := w.Filesystem.Lstat(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mode, err := filemode.NewFromOSFileMode(fi.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e := &index.Entry{
|
||||
Hash: h,
|
||||
Name: name,
|
||||
@@ -1057,7 +1140,7 @@ func rmFileAndDirsIfEmpty(fs billy.Filesystem, name string) error {
|
||||
dir := filepath.Dir(name)
|
||||
for {
|
||||
removed, err := removeDirIfEmpty(fs, dir)
|
||||
if err != nil {
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
106
vendor/github.com/go-git/go-git/v5/worktree_commit.go
generated
vendored
106
vendor/github.com/go-git/go-git/v5/worktree_commit.go
generated
vendored
@@ -3,7 +3,9 @@ package git
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"path"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -14,6 +16,7 @@ import (
|
||||
"github.com/go-git/go-git/v5/storage"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
"github.com/go-git/go-billy/v5"
|
||||
)
|
||||
|
||||
@@ -21,6 +24,10 @@ var (
|
||||
// ErrEmptyCommit occurs when a commit is attempted using a clean
|
||||
// working tree, with no changes to be committed.
|
||||
ErrEmptyCommit = errors.New("cannot create empty commit: clean working tree")
|
||||
|
||||
// characters to be removed from user name and/or email before using them to build a commit object
|
||||
// See https://git-scm.com/docs/git-commit#_commit_information
|
||||
invalidCharactersRe = regexp.MustCompile(`[<>\n]`)
|
||||
)
|
||||
|
||||
// Commit stores the current contents of the index in a new commit along with
|
||||
@@ -36,36 +43,53 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error
|
||||
}
|
||||
}
|
||||
|
||||
var treeHash plumbing.Hash
|
||||
|
||||
if opts.Amend {
|
||||
head, err := w.r.Head()
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
t, err := w.r.getTreeFromCommitHash(head.Hash())
|
||||
headCommit, err := w.r.CommitObject(head.Hash())
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
treeHash = t.Hash
|
||||
opts.Parents = []plumbing.Hash{head.Hash()}
|
||||
} else {
|
||||
idx, err := w.r.Storer.Index()
|
||||
opts.Parents = nil
|
||||
if len(headCommit.ParentHashes) != 0 {
|
||||
opts.Parents = []plumbing.Hash{headCommit.ParentHashes[0]}
|
||||
}
|
||||
}
|
||||
|
||||
idx, err := w.r.Storer.Index()
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
// First handle the case of the first commit in the repository being empty.
|
||||
if len(opts.Parents) == 0 && len(idx.Entries) == 0 && !opts.AllowEmptyCommits {
|
||||
return plumbing.ZeroHash, ErrEmptyCommit
|
||||
}
|
||||
|
||||
h := &buildTreeHelper{
|
||||
fs: w.Filesystem,
|
||||
s: w.r.Storer,
|
||||
}
|
||||
|
||||
treeHash, err := h.BuildTree(idx, opts)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
previousTree := plumbing.ZeroHash
|
||||
if len(opts.Parents) > 0 {
|
||||
parentCommit, err := w.r.CommitObject(opts.Parents[0])
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
previousTree = parentCommit.TreeHash
|
||||
}
|
||||
|
||||
h := &buildTreeHelper{
|
||||
fs: w.Filesystem,
|
||||
s: w.r.Storer,
|
||||
}
|
||||
|
||||
treeHash, err = h.BuildTree(idx, opts)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
if treeHash == previousTree && !opts.AllowEmptyCommits {
|
||||
return plumbing.ZeroHash, ErrEmptyCommit
|
||||
}
|
||||
|
||||
commit, err := w.buildCommitObject(msg, opts, treeHash)
|
||||
@@ -118,19 +142,24 @@ func (w *Worktree) updateHEAD(commit plumbing.Hash) error {
|
||||
|
||||
func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumbing.Hash) (plumbing.Hash, error) {
|
||||
commit := &object.Commit{
|
||||
Author: *opts.Author,
|
||||
Committer: *opts.Committer,
|
||||
Author: w.sanitize(*opts.Author),
|
||||
Committer: w.sanitize(*opts.Committer),
|
||||
Message: msg,
|
||||
TreeHash: tree,
|
||||
ParentHashes: opts.Parents,
|
||||
}
|
||||
|
||||
if opts.SignKey != nil {
|
||||
sig, err := w.buildCommitSignature(commit, opts.SignKey)
|
||||
// Convert SignKey into a Signer if set. Existing Signer should take priority.
|
||||
signer := opts.Signer
|
||||
if signer == nil && opts.SignKey != nil {
|
||||
signer = &gpgSigner{key: opts.SignKey}
|
||||
}
|
||||
if signer != nil {
|
||||
sig, err := signObject(signer, commit)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
commit.PGPSignature = sig
|
||||
commit.PGPSignature = string(sig)
|
||||
}
|
||||
|
||||
obj := w.r.Storer.NewEncodedObject()
|
||||
@@ -140,20 +169,25 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb
|
||||
return w.r.Storer.SetEncodedObject(obj)
|
||||
}
|
||||
|
||||
func (w *Worktree) buildCommitSignature(commit *object.Commit, signKey *openpgp.Entity) (string, error) {
|
||||
encoded := &plumbing.MemoryObject{}
|
||||
if err := commit.Encode(encoded); err != nil {
|
||||
return "", err
|
||||
}
|
||||
r, err := encoded.Reader()
|
||||
if err != nil {
|
||||
return "", err
|
||||
func (w *Worktree) sanitize(signature object.Signature) object.Signature {
|
||||
return object.Signature{
|
||||
Name: invalidCharactersRe.ReplaceAllString(signature.Name, ""),
|
||||
Email: invalidCharactersRe.ReplaceAllString(signature.Email, ""),
|
||||
When: signature.When,
|
||||
}
|
||||
}
|
||||
|
||||
type gpgSigner struct {
|
||||
key *openpgp.Entity
|
||||
cfg *packet.Config
|
||||
}
|
||||
|
||||
func (s *gpgSigner) Sign(message io.Reader) ([]byte, error) {
|
||||
var b bytes.Buffer
|
||||
if err := openpgp.ArmoredDetachSign(&b, signKey, r, nil); err != nil {
|
||||
return "", err
|
||||
if err := openpgp.ArmoredDetachSign(&b, s.key, message, s.cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b.String(), nil
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// buildTreeHelper converts a given index.Index file into multiple git objects
|
||||
@@ -170,10 +204,6 @@ type buildTreeHelper struct {
|
||||
// BuildTree builds the tree objects and push its to the storer, the hash
|
||||
// of the root tree is returned.
|
||||
func (h *buildTreeHelper) BuildTree(idx *index.Index, opts *CommitOptions) (plumbing.Hash, error) {
|
||||
if len(idx.Entries) == 0 && (opts == nil || !opts.AllowEmptyCommits) {
|
||||
return plumbing.ZeroHash, ErrEmptyCommit
|
||||
}
|
||||
|
||||
const rootNode = ""
|
||||
h.trees = map[string]*object.Tree{rootNode: {}}
|
||||
h.entries = map[string]*object.TreeEntry{}
|
||||
@@ -263,4 +293,4 @@ func (h *buildTreeHelper) copyTreeToStorageRecursive(parent string, t *object.Tr
|
||||
return hash, nil
|
||||
}
|
||||
return h.s.SetEncodedObject(o)
|
||||
}
|
||||
}
|
||||
|
||||
3
vendor/github.com/go-git/go-git/v5/worktree_linux.go
generated
vendored
3
vendor/github.com/go-git/go-git/v5/worktree_linux.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package git
|
||||
@@ -21,6 +22,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func isSymlinkWindowsNonAdmin(err error) bool {
|
||||
func isSymlinkWindowsNonAdmin(_ error) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
63
vendor/github.com/go-git/go-git/v5/worktree_status.go
generated
vendored
63
vendor/github.com/go-git/go-git/v5/worktree_status.go
generated
vendored
@@ -29,10 +29,23 @@ var (
|
||||
// ErrGlobNoMatches in an AddGlob if the glob pattern does not match any
|
||||
// files in the worktree.
|
||||
ErrGlobNoMatches = errors.New("glob pattern did not match any files")
|
||||
// ErrUnsupportedStatusStrategy occurs when an invalid StatusStrategy is used
|
||||
// when processing the Worktree status.
|
||||
ErrUnsupportedStatusStrategy = errors.New("unsupported status strategy")
|
||||
)
|
||||
|
||||
// Status returns the working tree status.
|
||||
func (w *Worktree) Status() (Status, error) {
|
||||
return w.StatusWithOptions(StatusOptions{Strategy: defaultStatusStrategy})
|
||||
}
|
||||
|
||||
// StatusOptions defines the options for Worktree.StatusWithOptions().
|
||||
type StatusOptions struct {
|
||||
Strategy StatusStrategy
|
||||
}
|
||||
|
||||
// StatusWithOptions returns the working tree status.
|
||||
func (w *Worktree) StatusWithOptions(o StatusOptions) (Status, error) {
|
||||
var hash plumbing.Hash
|
||||
|
||||
ref, err := w.r.Head()
|
||||
@@ -44,11 +57,14 @@ func (w *Worktree) Status() (Status, error) {
|
||||
hash = ref.Hash()
|
||||
}
|
||||
|
||||
return w.status(hash)
|
||||
return w.status(o.Strategy, hash)
|
||||
}
|
||||
|
||||
func (w *Worktree) status(commit plumbing.Hash) (Status, error) {
|
||||
s := make(Status)
|
||||
func (w *Worktree) status(ss StatusStrategy, commit plumbing.Hash) (Status, error) {
|
||||
s, err := ss.new(w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
left, err := w.diffCommitWithStaging(commit, false)
|
||||
if err != nil {
|
||||
@@ -271,7 +287,7 @@ func diffTreeIsEquals(a, b noder.Hasher) bool {
|
||||
// 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): deprecate in favor of AddWithOption in v6.
|
||||
return w.doAdd(path, make([]gitignore.Pattern, 0))
|
||||
return w.doAdd(path, make([]gitignore.Pattern, 0), false)
|
||||
}
|
||||
|
||||
func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string, ignorePattern []gitignore.Pattern) (added bool, err error) {
|
||||
@@ -321,7 +337,7 @@ func (w *Worktree) AddWithOptions(opts *AddOptions) error {
|
||||
}
|
||||
|
||||
if opts.All {
|
||||
_, err := w.doAdd(".", w.Excludes)
|
||||
_, err := w.doAdd(".", w.Excludes, false)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -329,16 +345,11 @@ func (w *Worktree) AddWithOptions(opts *AddOptions) error {
|
||||
return w.AddGlob(opts.Glob)
|
||||
}
|
||||
|
||||
_, err := w.Add(opts.Path)
|
||||
_, err := w.doAdd(opts.Path, make([]gitignore.Pattern, 0), opts.SkipStatus)
|
||||
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
|
||||
}
|
||||
|
||||
func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern, skipStatus bool) (plumbing.Hash, error) {
|
||||
idx, err := w.r.Storer.Index()
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
@@ -348,6 +359,19 @@ func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern) (plumbi
|
||||
var added bool
|
||||
|
||||
fi, err := w.Filesystem.Lstat(path)
|
||||
|
||||
// status is required for doAddDirectory
|
||||
var s Status
|
||||
var err2 error
|
||||
if !skipStatus || fi == nil || fi.IsDir() {
|
||||
s, err2 = w.Status()
|
||||
if err2 != nil {
|
||||
return plumbing.ZeroHash, err2
|
||||
}
|
||||
}
|
||||
|
||||
path = filepath.Clean(path)
|
||||
|
||||
if err != nil || !fi.IsDir() {
|
||||
added, h, err = w.doAddFile(idx, s, path, ignorePattern)
|
||||
} else {
|
||||
@@ -421,8 +445,9 @@ 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.
|
||||
// if s status is nil will skip the status check and update the index anyway
|
||||
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 {
|
||||
if s != nil && s.File(path).Worktree == Unmodified {
|
||||
return false, h, nil
|
||||
}
|
||||
if len(ignorePattern) > 0 {
|
||||
@@ -481,7 +506,7 @@ func (w *Worktree) copyFileToStorage(path string) (hash plumbing.Hash, err error
|
||||
return w.r.Storer.SetEncodedObject(obj)
|
||||
}
|
||||
|
||||
func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, fi os.FileInfo) (err error) {
|
||||
func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, _ os.FileInfo) (err error) {
|
||||
src, err := w.Filesystem.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -496,7 +521,7 @@ func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, fi os.F
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, fi os.FileInfo) error {
|
||||
func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, _ os.FileInfo) error {
|
||||
target, err := w.Filesystem.Readlink(path)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -536,9 +561,11 @@ func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbi
|
||||
return err
|
||||
}
|
||||
|
||||
if e.Mode.IsRegular() {
|
||||
e.Size = uint32(info.Size())
|
||||
}
|
||||
// The entry size must always reflect the current state, otherwise
|
||||
// it will cause go-git's Worktree.Status() to divert from "git status".
|
||||
// The size of a symlink is the length of the path to the target.
|
||||
// The size of Regular and Executable files is the size of the files.
|
||||
e.Size = uint32(info.Size())
|
||||
|
||||
fillSystemInfo(e, info.Sys())
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user