diff --git a/go.mod b/go.mod index 463189fc..f14df64e 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/git-lfs/git-lfs require ( github.com/alexbrainman/sspi v0.0.0-20180125232955-4729b3d4d858 - github.com/git-lfs/gitobj v1.3.1 + github.com/git-lfs/gitobj v1.4.0 github.com/git-lfs/go-netrc v0.0.0-20180525200031-e0e9ca483a18 github.com/git-lfs/go-ntlm v0.0.0-20190307203151-c5056e7fa066 github.com/git-lfs/wildmatch v1.0.2 diff --git a/go.sum b/go.sum index aa6a89bb..6b1ad5a9 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/alexbrainman/sspi v0.0.0-20180125232955-4729b3d4d858 h1:OZQyEhf4Bviyd github.com/alexbrainman/sspi v0.0.0-20180125232955-4729b3d4d858/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/git-lfs/gitobj v1.3.1 h1:Nni8wnRfvT3x91rDl3V397LjKOUoiaEK6vyIcA92aM8= -github.com/git-lfs/gitobj v1.3.1/go.mod h1:EdPNGHVxXe1jTuNXzZT1+CdJCuASoDSLPQuvNOo9nGM= +github.com/git-lfs/gitobj v1.4.0 h1:F7fKUUM/OTVu0ejnBA6x0trSYM8A9Zv7VGoBTsMmhHk= +github.com/git-lfs/gitobj v1.4.0/go.mod h1:EdPNGHVxXe1jTuNXzZT1+CdJCuASoDSLPQuvNOo9nGM= github.com/git-lfs/go-netrc v0.0.0-20180525200031-e0e9ca483a18 h1:7Th0eBA4rT8WJNiM1vppjaIv9W5WJinhpbCJvRJxloI= github.com/git-lfs/go-netrc v0.0.0-20180525200031-e0e9ca483a18/go.mod h1:70O4NAtvWn1jW8V8V+OKrJJYcxDLTmIozfi2fmSz5SI= github.com/git-lfs/go-ntlm v0.0.0-20190307203151-c5056e7fa066 h1:j7JwIEwLNQ/kBdKpHO3U1jjMXIPjSq7eCFvQIF3e8Fs= diff --git a/vendor/github.com/git-lfs/gitobj/backend.go b/vendor/github.com/git-lfs/gitobj/backend.go index fea385c3..9e64285d 100644 --- a/vendor/github.com/git-lfs/gitobj/backend.go +++ b/vendor/github.com/git-lfs/gitobj/backend.go @@ -5,6 +5,9 @@ import ( "io" "os" "path" + "regexp" + "strconv" + "strings" "github.com/git-lfs/gitobj/pack" "github.com/git-lfs/gitobj/storage" @@ -12,6 +15,14 @@ import ( // NewFilesystemBackend initializes a new filesystem-based backend. func NewFilesystemBackend(root, tmp string) (storage.Backend, error) { + return NewFilesystemBackendWithAlternates(root, tmp, "") +} + +// NewFilesystemBackendWithAlternates initializes a new filesystem-based +// backend, optionally with additional alternates as specified in the +// `alternates` variable. The syntax is that of the Git environment variable +// GIT_ALTERNATE_OBJECT_DIRECTORIES. +func NewFilesystemBackendWithAlternates(root, tmp, alternates string) (storage.Backend, error) { fsobj := newFileStorer(root, tmp) packs, err := pack.NewStorage(root) if err != nil { @@ -23,6 +34,11 @@ func NewFilesystemBackend(root, tmp string) (storage.Backend, error) { return nil, err } + storage, err = addAlternatesFromEnvironment(storage, alternates) + if err != nil { + return nil, err + } + return &filesystemBackend{ fs: fsobj, backends: storage, @@ -45,12 +61,10 @@ func findAllBackends(mainLoose *fileStorer, mainPacked *pack.Storage, root strin scanner := bufio.NewScanner(f) for scanner.Scan() { - storage = append(storage, newFileStorer(scanner.Text(), "")) - pack, err := pack.NewStorage(scanner.Text()) + storage, err = addAlternateDirectory(storage, scanner.Text()) if err != nil { return nil, err } - storage = append(storage, pack) } if err := scanner.Err(); err != nil { @@ -60,6 +74,76 @@ func findAllBackends(mainLoose *fileStorer, mainPacked *pack.Storage, root strin return storage, nil } +func addAlternateDirectory(s []storage.Storage, dir string) ([]storage.Storage, error) { + s = append(s, newFileStorer(dir, "")) + pack, err := pack.NewStorage(dir) + if err != nil { + return s, err + } + s = append(s, pack) + return s, nil +} + +func addAlternatesFromEnvironment(s []storage.Storage, env string) ([]storage.Storage, error) { + if len(env) == 0 { + return s, nil + } + + for _, dir := range splitAlternateString(env, alternatesSeparator) { + var err error + s, err = addAlternateDirectory(s, dir) + if err != nil { + return nil, err + } + } + return s, nil +} + +var ( + octalEscape = regexp.MustCompile("\\\\[0-7]{1,3}") + hexEscape = regexp.MustCompile("\\\\x[0-9a-fA-F]{2}") + replacements = []struct { + olds string + news string + }{ + {`\a`, "\a"}, + {`\b`, "\b"}, + {`\t`, "\t"}, + {`\n`, "\n"}, + {`\v`, "\v"}, + {`\f`, "\f"}, + {`\r`, "\r"}, + {`\\`, "\\"}, + {`\"`, "\""}, + {`\'`, "'"}, + } +) + +func splitAlternateString(env string, separator string) []string { + dirs := strings.Split(env, separator) + for i, s := range dirs { + if !strings.HasPrefix(s, `"`) || !strings.HasSuffix(s, `"`) { + continue + } + + // Strip leading and trailing quotation marks + s = s[1 : len(s)-1] + for _, repl := range replacements { + s = strings.Replace(s, repl.olds, repl.news, -1) + } + s = octalEscape.ReplaceAllStringFunc(s, func(inp string) string { + val, _ := strconv.ParseUint(inp[1:], 8, 64) + return string([]byte{byte(val)}) + }) + s = hexEscape.ReplaceAllStringFunc(s, func(inp string) string { + val, _ := strconv.ParseUint(inp[2:], 16, 64) + return string([]byte{byte(val)}) + }) + dirs[i] = s + } + return dirs +} + // NewMemoryBackend initializes a new memory-based backend. // // A value of "nil" is acceptable and indicates that no entries should be added diff --git a/vendor/github.com/git-lfs/gitobj/backend_nix.go b/vendor/github.com/git-lfs/gitobj/backend_nix.go new file mode 100644 index 00000000..58ed2d88 --- /dev/null +++ b/vendor/github.com/git-lfs/gitobj/backend_nix.go @@ -0,0 +1,5 @@ +// +build !windows + +package gitobj + +const alternatesSeparator = ":" diff --git a/vendor/github.com/git-lfs/gitobj/backend_windows.go b/vendor/github.com/git-lfs/gitobj/backend_windows.go new file mode 100644 index 00000000..49239c3a --- /dev/null +++ b/vendor/github.com/git-lfs/gitobj/backend_windows.go @@ -0,0 +1,5 @@ +// +build windows + +package gitobj + +const alternatesSeparator = ";" diff --git a/vendor/github.com/git-lfs/gitobj/object_db.go b/vendor/github.com/git-lfs/gitobj/object_db.go index 659b45b1..89ce7e02 100644 --- a/vendor/github.com/git-lfs/gitobj/object_db.go +++ b/vendor/github.com/git-lfs/gitobj/object_db.go @@ -36,7 +36,16 @@ type ObjectDatabase struct { // // /absolute/repo/path/.git/objects func FromFilesystem(root, tmp string) (*ObjectDatabase, error) { - b, err := NewFilesystemBackend(root, tmp) + return FromFilesystemWithAlternates(root, tmp, "") +} + +// FromFilesystemWithAlternates constructs an *ObjectDatabase instance that is +// backed by a directory on the filesystem, optionally with one or more +// alternates. Specifically, this should point to: +// +// /absolute/repo/path/.git/objects +func FromFilesystemWithAlternates(root, tmp, alternates string) (*ObjectDatabase, error) { + b, err := NewFilesystemBackendWithAlternates(root, tmp, alternates) if err != nil { return nil, err } diff --git a/vendor/modules.txt b/vendor/modules.txt index 20b4c8ce..f352b101 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -3,7 +3,7 @@ github.com/alexbrainman/sspi github.com/alexbrainman/sspi/ntlm # github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew/spew -# github.com/git-lfs/gitobj v1.3.1 +# github.com/git-lfs/gitobj v1.4.0 github.com/git-lfs/gitobj github.com/git-lfs/gitobj/errors github.com/git-lfs/gitobj/pack