merge latest master
This commit is contained in:
commit
4e4dac25c5
1
Nut.toml
1
Nut.toml
@ -19,4 +19,3 @@ authors = [
|
||||
"github.com/spf13/cobra" = "c55cdf33856a08e4822738728b41783292812889"
|
||||
"github.com/spf13/pflag" = "580b9be06c33d8ba9dcc8757ea56b7642472c2f5"
|
||||
"github.com/technoweenie/assert" = "b25ea301d127043ffacf3b2545726e79b6632139"
|
||||
"github.com/technoweenie/go-contentaddressable" = "38171def3cd15e3b76eb156219b3d48704643899"
|
||||
|
26
git-lfs.go
26
git-lfs.go
@ -1,11 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/github/git-lfs/commands"
|
||||
"github.com/github/git-lfs/lfs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, os.Kill)
|
||||
|
||||
var once sync.Once
|
||||
|
||||
go func() {
|
||||
for {
|
||||
sig := <-c
|
||||
once.Do(lfs.ClearTempObjects)
|
||||
fmt.Fprintf(os.Stderr, "\nExiting because of %q signal.\n", sig)
|
||||
|
||||
exitCode := 1
|
||||
if sysSig, ok := sig.(syscall.Signal); ok {
|
||||
exitCode = int(sysSig)
|
||||
}
|
||||
os.Exit(exitCode + 128)
|
||||
}
|
||||
}()
|
||||
|
||||
commands.Run()
|
||||
lfs.LogHttpStats()
|
||||
once.Do(lfs.ClearTempObjects)
|
||||
}
|
||||
|
@ -425,7 +425,7 @@ func doApiBatchRequest(req *http.Request) (*http.Response, []*objectResource, er
|
||||
res, err := doAPIRequest(req, Config.PrivateAccess())
|
||||
|
||||
if err != nil {
|
||||
if res.StatusCode == 401 {
|
||||
if res != nil && res.StatusCode == 401 {
|
||||
return res, nil, newAuthError(err)
|
||||
}
|
||||
return res, nil, err
|
||||
|
@ -337,7 +337,7 @@ func (c *Configuration) loadGitConfig() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool, whitelisted bool) {
|
||||
func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool, onlySafe bool) {
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
pieces := strings.SplitN(line, "=", 2)
|
||||
@ -345,7 +345,7 @@ func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool
|
||||
continue
|
||||
}
|
||||
|
||||
allowed := !whitelisted
|
||||
allowed := !onlySafe
|
||||
key := strings.ToLower(pieces[0])
|
||||
value := pieces[1]
|
||||
|
||||
@ -355,12 +355,12 @@ func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool
|
||||
ext := c.extensions[name]
|
||||
switch keyParts[3] {
|
||||
case "clean":
|
||||
if whitelisted {
|
||||
if onlySafe {
|
||||
continue
|
||||
}
|
||||
ext.Clean = value
|
||||
case "smudge":
|
||||
if whitelisted {
|
||||
if onlySafe {
|
||||
continue
|
||||
}
|
||||
ext.Smudge = value
|
||||
@ -375,7 +375,7 @@ func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool
|
||||
ext.Name = name
|
||||
c.extensions[name] = ext
|
||||
} else if len(keyParts) > 1 && keyParts[0] == "remote" {
|
||||
if whitelisted && (len(keyParts) < 3 || keyParts[2] != "lfsurl") {
|
||||
if onlySafe && (len(keyParts) == 3 && keyParts[2] != "lfsurl") {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -384,7 +384,7 @@ func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool
|
||||
uniqRemotes[remote] = remote == "origin"
|
||||
}
|
||||
|
||||
if !allowed && key != "lfs.url" {
|
||||
if !allowed && keyIsUnsafe(key) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -403,3 +403,18 @@ func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func keyIsUnsafe(key string) bool {
|
||||
for _, safe := range safeKeys {
|
||||
if safe == key {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
var safeKeys = []string{
|
||||
"lfs.url",
|
||||
"lfs.fetchinclude",
|
||||
"lfs.fetchexclude",
|
||||
}
|
||||
|
@ -84,7 +84,9 @@ func TestSuccessfulDownload(t *testing.T) {
|
||||
})
|
||||
|
||||
defer Config.ResetConfig()
|
||||
Config.SetConfig("lfs.batch", "false")
|
||||
Config.SetConfig("lfs.url", server.URL+"/media")
|
||||
|
||||
reader, size, err := Download("oid")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
@ -213,6 +215,7 @@ func TestSuccessfulDownloadWithRedirects(t *testing.T) {
|
||||
})
|
||||
|
||||
defer Config.ResetConfig()
|
||||
Config.SetConfig("lfs.batch", "false")
|
||||
Config.SetConfig("lfs.url", server.URL+"/redirect")
|
||||
|
||||
for _, redirect := range redirectCodes {
|
||||
@ -319,6 +322,7 @@ func TestSuccessfulDownloadWithAuthorization(t *testing.T) {
|
||||
})
|
||||
|
||||
defer Config.ResetConfig()
|
||||
Config.SetConfig("lfs.batch", "false")
|
||||
Config.SetConfig("lfs.url", server.URL+"/media")
|
||||
reader, size, err := Download("oid")
|
||||
if err != nil {
|
||||
@ -419,6 +423,7 @@ func TestSuccessfulDownloadFromSeparateHost(t *testing.T) {
|
||||
})
|
||||
|
||||
defer Config.ResetConfig()
|
||||
Config.SetConfig("lfs.batch", "false")
|
||||
Config.SetConfig("lfs.url", server.URL+"/media")
|
||||
reader, size, err := Download("oid")
|
||||
if err != nil {
|
||||
@ -550,6 +555,7 @@ func TestSuccessfulDownloadFromSeparateRedirectedHost(t *testing.T) {
|
||||
})
|
||||
|
||||
defer Config.ResetConfig()
|
||||
Config.SetConfig("lfs.batch", "false")
|
||||
Config.SetConfig("lfs.url", server.URL+"/media")
|
||||
|
||||
for _, redirect := range redirectCodes {
|
||||
@ -587,6 +593,7 @@ func TestDownloadAPIError(t *testing.T) {
|
||||
})
|
||||
|
||||
defer Config.ResetConfig()
|
||||
Config.SetConfig("lfs.batch", "false")
|
||||
Config.SetConfig("lfs.url", server.URL+"/media")
|
||||
_, _, err := Download("oid")
|
||||
if err == nil {
|
||||
@ -655,6 +662,7 @@ func TestDownloadStorageError(t *testing.T) {
|
||||
})
|
||||
|
||||
defer Config.ResetConfig()
|
||||
Config.SetConfig("lfs.batch", "false")
|
||||
Config.SetConfig("lfs.url", server.URL+"/media")
|
||||
_, _, err := Download("oid")
|
||||
if err == nil {
|
||||
|
@ -28,6 +28,7 @@ var (
|
||||
LocalGitDir string // parent of index / config / hooks etc
|
||||
LocalGitStorageDir string // parent of objects/lfs (may be same as LocalGitDir but may not)
|
||||
LocalMediaDir string // root of lfs objects
|
||||
LocalObjectTempDir string // where temporarily downloading objects are stored
|
||||
LocalLogDir string
|
||||
checkedTempDir string
|
||||
)
|
||||
@ -112,7 +113,8 @@ func ResolveDirs() {
|
||||
panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(TempDir, tempDirPerms); err != nil {
|
||||
LocalObjectTempDir = filepath.Join(TempDir, "objects")
|
||||
if err := os.MkdirAll(LocalObjectTempDir, tempDirPerms); err != nil {
|
||||
panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
|
||||
}
|
||||
}
|
||||
|
62
lfs/localstorage.go
Normal file
62
lfs/localstorage.go
Normal file
@ -0,0 +1,62 @@
|
||||
package lfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
|
||||
)
|
||||
|
||||
func ClearTempObjects() {
|
||||
if len(LocalObjectTempDir) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
d, err := os.Open(LocalObjectTempDir)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error opening %q to clear old temp files: %s\n", LocalObjectTempDir, err)
|
||||
return
|
||||
}
|
||||
|
||||
filenames, _ := d.Readdirnames(-1)
|
||||
for _, filename := range filenames {
|
||||
path := filepath.Join(LocalObjectTempDir, filename)
|
||||
if shouldDeleteTempObject(path) {
|
||||
os.RemoveAll(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func shouldDeleteTempObject(path string) bool {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return false
|
||||
}
|
||||
|
||||
base := filepath.Base(path)
|
||||
parts := strings.SplitN(base, "-", 2)
|
||||
oid := parts[0]
|
||||
if len(parts) < 2 || len(oid) != 64 {
|
||||
tracerx.Printf("Removing invalid tmp object file: %s", path)
|
||||
return true
|
||||
}
|
||||
|
||||
if FileExists(localMediaPathNoCreate(oid)) {
|
||||
tracerx.Printf("Removing existing tmp object file: %s", path)
|
||||
return true
|
||||
}
|
||||
|
||||
if time.Since(info.ModTime()) > time.Hour {
|
||||
tracerx.Printf("Removing old tmp object file: %s", path)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
@ -1,14 +1,17 @@
|
||||
package lfs
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/github/git-lfs/vendor/_nuts/github.com/cheggaaa/pb"
|
||||
"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
|
||||
contentaddressable "github.com/github/git-lfs/vendor/_nuts/github.com/technoweenie/go-contentaddressable"
|
||||
)
|
||||
|
||||
func PointerSmudgeToFile(filename string, ptr *Pointer, download bool, cb CopyCallback) error {
|
||||
@ -99,7 +102,6 @@ func downloadObject(ptr *Pointer, obj *objectResource, mediafile string, cb Copy
|
||||
defer reader.Close()
|
||||
}
|
||||
|
||||
// TODO this can be unified with the same code in downloadFile
|
||||
if err != nil {
|
||||
return Errorf(err, "Error downloading %s", mediafile)
|
||||
}
|
||||
@ -108,18 +110,7 @@ func downloadObject(ptr *Pointer, obj *objectResource, mediafile string, cb Copy
|
||||
ptr.Size = size
|
||||
}
|
||||
|
||||
mediaFile, err := contentaddressable.NewFile(mediafile)
|
||||
if err != nil {
|
||||
return Errorf(err, "Error opening media file buffer.")
|
||||
}
|
||||
|
||||
_, err = CopyWithCallback(mediaFile, reader, ptr.Size, cb)
|
||||
if err == nil {
|
||||
err = mediaFile.Accept()
|
||||
}
|
||||
mediaFile.Close()
|
||||
|
||||
if err != nil {
|
||||
if err := bufferDownloadedFile(mediafile, reader, ptr.Size, cb); err != nil {
|
||||
return Errorf(err, "Error buffering media file.")
|
||||
}
|
||||
|
||||
@ -134,31 +125,84 @@ func downloadFile(writer io.Writer, ptr *Pointer, workingfile, mediafile string,
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return Errorf(err, "Error downloading %s.", mediafile)
|
||||
return Errorf(err, "Error downloading %s: %s", filepath.Base(mediafile), err)
|
||||
}
|
||||
|
||||
if ptr.Size == 0 {
|
||||
ptr.Size = size
|
||||
}
|
||||
|
||||
mediaFile, err := contentaddressable.NewFile(mediafile)
|
||||
if err != nil {
|
||||
return Errorf(err, "Error opening media file buffer.")
|
||||
}
|
||||
|
||||
_, err = CopyWithCallback(mediaFile, reader, ptr.Size, cb)
|
||||
if err == nil {
|
||||
err = mediaFile.Accept()
|
||||
}
|
||||
mediaFile.Close()
|
||||
|
||||
if err != nil {
|
||||
return Errorf(err, "Error buffering media file.")
|
||||
if err := bufferDownloadedFile(mediafile, reader, ptr.Size, cb); err != nil {
|
||||
return Errorf(err, "Error buffering media file: %s", err)
|
||||
}
|
||||
|
||||
return readLocalFile(writer, ptr, mediafile, workingfile, nil)
|
||||
}
|
||||
|
||||
// Writes the content of reader to filename atomically by writing to a temp file
|
||||
// first, and confirming the content SHA-256 is valid. This is basically a copy
|
||||
// of atomic.WriteFile() at:
|
||||
//
|
||||
// https://github.com/natefinch/atomic/blob/a62ce929ffcc871a51e98c6eba7b20321e3ed62d/atomic.go#L12-L17
|
||||
//
|
||||
// filename - Absolute path to a file to write, with the filename a 64 character
|
||||
// SHA-256 hex signature.
|
||||
// reader - Any io.Reader
|
||||
// size - Expected byte size of the content. Used for the progress bar in
|
||||
// the optional CopyCallback.
|
||||
// cb - Optional CopyCallback object for providing download progress to
|
||||
// external Git LFS tools.
|
||||
func bufferDownloadedFile(filename string, reader io.Reader, size int64, cb CopyCallback) error {
|
||||
oid := filepath.Base(filename)
|
||||
f, err := ioutil.TempFile(LocalObjectTempDir, oid+"-")
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create temp file: %v", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
// Don't leave the temp file lying around on error.
|
||||
_ = os.Remove(f.Name()) // yes, ignore the error, not much we can do about it.
|
||||
}
|
||||
}()
|
||||
|
||||
hasher := newHashingReader(reader)
|
||||
|
||||
// ensure we always close f. Note that this does not conflict with the
|
||||
// close below, as close is idempotent.
|
||||
defer f.Close()
|
||||
name := f.Name()
|
||||
written, err := CopyWithCallback(f, hasher, size, cb)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot write data to tempfile %q: %v", name, err)
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return fmt.Errorf("can't close tempfile %q: %v", name, err)
|
||||
}
|
||||
|
||||
if actual := hasher.Hash(); actual != oid {
|
||||
return fmt.Errorf("Expected OID %s, got %s after %d bytes written", oid, actual, written)
|
||||
}
|
||||
|
||||
// get the file mode from the original file and use that for the replacement
|
||||
// file, too.
|
||||
info, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
// no original file
|
||||
} else if err != nil {
|
||||
return err
|
||||
} else {
|
||||
if err := os.Chmod(name, info.Mode()); err != nil {
|
||||
return fmt.Errorf("can't set filemode on tempfile %q: %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Rename(name, filename); err != nil {
|
||||
return fmt.Errorf("cannot replace %q with tempfile %q: %v", filename, name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readLocalFile(writer io.Writer, ptr *Pointer, mediafile string, workingfile string, cb CopyCallback) error {
|
||||
reader, err := os.Open(mediafile)
|
||||
if err != nil {
|
||||
@ -191,7 +235,7 @@ func readLocalFile(writer io.Writer, ptr *Pointer, mediafile string, workingfile
|
||||
|
||||
// pipe extensions in reverse order
|
||||
var extsR []Extension
|
||||
for i, _ := range exts {
|
||||
for i := range exts {
|
||||
ext := exts[len(exts)-1-i]
|
||||
extsR = append(extsR, ext)
|
||||
}
|
||||
@ -230,15 +274,41 @@ func readLocalFile(writer io.Writer, ptr *Pointer, mediafile string, workingfile
|
||||
// setup reader
|
||||
reader, err = os.Open(response.file.Name())
|
||||
if err != nil {
|
||||
return Errorf(err, "Error opening smudged file.")
|
||||
return Errorf(err, "Error opening smudged file: %s", err)
|
||||
}
|
||||
defer reader.Close()
|
||||
}
|
||||
|
||||
_, err = CopyWithCallback(writer, reader, ptr.Size, cb)
|
||||
if err != nil {
|
||||
return Errorf(err, "Error reading from media file.")
|
||||
return Errorf(err, "Error reading from media file: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type hashingReader struct {
|
||||
reader io.Reader
|
||||
hasher hash.Hash
|
||||
}
|
||||
|
||||
func newHashingReader(r io.Reader) *hashingReader {
|
||||
tracerx.Printf("NEW HASHING READER")
|
||||
return &hashingReader{r, sha256.New()}
|
||||
}
|
||||
|
||||
func (r *hashingReader) Hash() string {
|
||||
return hex.EncodeToString(r.hasher.Sum(nil))
|
||||
}
|
||||
|
||||
func (r *hashingReader) Read(b []byte) (int, error) {
|
||||
w, err := r.reader.Read(b)
|
||||
if err == nil || err == io.EOF {
|
||||
_, e := r.hasher.Write(b[0:w])
|
||||
if e != nil && err == nil {
|
||||
return w, e
|
||||
}
|
||||
}
|
||||
|
||||
return w, err
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ $ script/test lfs -run TestSuccessStatus -v
|
||||
github.com/kr/text
|
||||
github.com/cheggaaa/pb
|
||||
github.com/rubyist/tracerx
|
||||
github.com/technoweenie/go-contentaddressable
|
||||
github.com/kr/pretty
|
||||
github.com/github/git-lfs/git
|
||||
github.com/technoweenie/assert
|
||||
|
@ -18,7 +18,7 @@ begin_test "checkout"
|
||||
contentsize=19
|
||||
contents_oid=$(calc_oid "$contents")
|
||||
|
||||
# Same content everywhere is ok, just one object in lfs db
|
||||
echo "Same content everywhere is ok, just one object in lfs db"
|
||||
printf "$contents" > file1.dat
|
||||
printf "$contents" > file2.dat
|
||||
printf "$contents" > file3.dat
|
||||
@ -40,7 +40,7 @@ begin_test "checkout"
|
||||
# Remove the working directory
|
||||
rm -rf file1.dat file2.dat file3.dat folder1/nested.dat folder2/nested.dat
|
||||
|
||||
# checkout should replace all
|
||||
echo "checkout should replace all"
|
||||
git lfs checkout
|
||||
[ "$contents" = "$(cat file1.dat)" ]
|
||||
[ "$contents" = "$(cat file2.dat)" ]
|
||||
@ -51,7 +51,7 @@ begin_test "checkout"
|
||||
# Remove again
|
||||
rm -rf file1.dat file2.dat file3.dat folder1/nested.dat folder2/nested.dat
|
||||
|
||||
# checkout with filters
|
||||
echo "checkout with filters"
|
||||
git lfs checkout file2.dat
|
||||
[ "$contents" = "$(cat file2.dat)" ]
|
||||
[ ! -f file1.dat ]
|
||||
@ -59,14 +59,14 @@ begin_test "checkout"
|
||||
[ ! -f folder1/nested.dat ]
|
||||
[ ! -f folder2/nested.dat ]
|
||||
|
||||
# quotes to avoid shell globbing
|
||||
echo "quotes to avoid shell globbing"
|
||||
git lfs checkout "file*.dat"
|
||||
[ "$contents" = "$(cat file1.dat)" ]
|
||||
[ "$contents" = "$(cat file3.dat)" ]
|
||||
[ ! -f folder1/nested.dat ]
|
||||
[ ! -f folder2/nested.dat ]
|
||||
|
||||
# test subdir context
|
||||
echo "test subdir context"
|
||||
pushd folder1
|
||||
git lfs checkout nested.dat
|
||||
[ "$contents" = "$(cat nested.dat)" ]
|
||||
@ -77,11 +77,11 @@ begin_test "checkout"
|
||||
[ "$contents" = "$(cat nested.dat)" ]
|
||||
popd
|
||||
|
||||
# test folder param
|
||||
echo "test folder param"
|
||||
git lfs checkout folder2
|
||||
[ "$contents" = "$(cat folder2/nested.dat)" ]
|
||||
|
||||
# test '.' in current dir
|
||||
echo "test '.' in current dir"
|
||||
rm -rf file1.dat file2.dat file3.dat folder1/nested.dat folder2/nested.dat
|
||||
git lfs checkout .
|
||||
[ "$contents" = "$(cat file1.dat)" ]
|
||||
@ -90,7 +90,7 @@ begin_test "checkout"
|
||||
[ "$contents" = "$(cat folder1/nested.dat)" ]
|
||||
[ "$contents" = "$(cat folder2/nested.dat)" ]
|
||||
|
||||
# test checkout with missing data doesn't fail
|
||||
echo "test checkout with missing data doesn't fail"
|
||||
git push origin master
|
||||
rm -rf .git/lfs/objects
|
||||
rm file*.dat
|
||||
|
360
test/test-env.sh
360
test/test-env.sh
@ -13,19 +13,29 @@ begin_test "env with no remote"
|
||||
cd $reponame
|
||||
git init
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
LocalWorkingDir=$TRASHDIR/$reponame
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
localwd=$(native_path "$TRASHDIR/$reponame")
|
||||
localgit=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localgitstore=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localmedia=$(native_path "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
tempdir=$(native_path "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||
envVars=$(printf "%s" "$(env | grep "^GIT")")
|
||||
|
||||
expected=$(printf '%s
|
||||
%s
|
||||
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
|
||||
contains_same_elements "$expected" "$actual"
|
||||
)
|
||||
end_test
|
||||
|
||||
@ -38,25 +48,34 @@ begin_test "env with origin remote"
|
||||
git init
|
||||
git remote add origin "$GITSERVER/env-origin-remote"
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
Endpoint=$GITSERVER/$reponame.git/info/lfs (auth=none)
|
||||
LocalWorkingDir=$TRASHDIR/$reponame
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
endpoint="$GITSERVER/$reponame.git/info/lfs (auth=none)"
|
||||
localwd=$(native_path "$TRASHDIR/$reponame")
|
||||
localgit=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localgitstore=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localmedia=$(native_path "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
tempdir=$(native_path "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||
envVars=$(printf "%s" "$(env | grep "^GIT")")
|
||||
expected=$(printf '%s
|
||||
%s
|
||||
|
||||
Endpoint=%s
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$endpoint" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
|
||||
cd .git
|
||||
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
|
||||
actual2=$(git lfs env)
|
||||
[ "$expected2" = "$actual2" ]
|
||||
contains_same_elements "$expected2" "$actual2"
|
||||
)
|
||||
end_test
|
||||
|
||||
@ -70,26 +89,36 @@ begin_test "env with multiple remotes"
|
||||
git remote add origin "$GITSERVER/env-origin-remote"
|
||||
git remote add other "$GITSERVER/env-other-remote"
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
Endpoint=$GITSERVER/env-origin-remote.git/info/lfs (auth=none)
|
||||
Endpoint (other)=$GITSERVER/env-other-remote.git/info/lfs (auth=none)
|
||||
LocalWorkingDir=$TRASHDIR/$reponame
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
endpoint="$GITSERVER/env-origin-remote.git/info/lfs (auth=none)"
|
||||
endpoint2="$GITSERVER/env-other-remote.git/info/lfs (auth=none)"
|
||||
localwd=$(native_path "$TRASHDIR/$reponame")
|
||||
localgit=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localgitstore=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localmedia=$(native_path "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
tempdir=$(native_path "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||
envVars=$(printf "%s" "$(env | grep "^GIT")")
|
||||
expected=$(printf '%s
|
||||
%s
|
||||
|
||||
Endpoint=%s
|
||||
Endpoint (other)=%s
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$endpoint" "$endpoint2" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
|
||||
cd .git
|
||||
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
|
||||
actual2=$(git lfs env)
|
||||
[ "$expected2" = "$actual2" ]
|
||||
contains_same_elements "$expected2" "$actual2"
|
||||
)
|
||||
end_test
|
||||
|
||||
@ -102,25 +131,35 @@ begin_test "env with other remote"
|
||||
git init
|
||||
git remote add other "$GITSERVER/env-other-remote"
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
Endpoint (other)=$GITSERVER/env-other-remote.git/info/lfs (auth=none)
|
||||
LocalWorkingDir=$TRASHDIR/$reponame
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
endpoint="$GITSERVER/env-other-remote.git/info/lfs (auth=none)"
|
||||
localwd=$(native_path "$TRASHDIR/$reponame")
|
||||
localgit=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localgitstore=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localmedia=$(native_path "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
tempdir=$(native_path "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||
envVars=$(printf "%s" "$(env | grep "^GIT")")
|
||||
|
||||
expected=$(printf '%s
|
||||
%s
|
||||
|
||||
Endpoint (other)=%s
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$endpoint" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
|
||||
cd .git
|
||||
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
|
||||
actual2=$(git lfs env)
|
||||
[ "$expected2" = "$actual2" ]
|
||||
contains_same_elements "$expected2" "$actual2"
|
||||
)
|
||||
end_test
|
||||
|
||||
@ -135,26 +174,35 @@ begin_test "env with multiple remotes and lfs.url config"
|
||||
git remote add other "$GITSERVER/env-other-remote"
|
||||
git config lfs.url "http://foo/bar"
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
endpoint="$GITSERVER/env-other-remote.git/info/lfs (auth=none)"
|
||||
localwd=$(native_path "$TRASHDIR/$reponame")
|
||||
localgit=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localgitstore=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localmedia=$(native_path "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
tempdir=$(native_path "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||
envVars=$(printf "%s" "$(env | grep "^GIT")")
|
||||
expected=$(printf '%s
|
||||
%s
|
||||
|
||||
Endpoint=http://foo/bar (auth=none)
|
||||
Endpoint (other)=$GITSERVER/env-other-remote.git/info/lfs (auth=none)
|
||||
LocalWorkingDir=$TRASHDIR/$reponame
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
Endpoint (other)=%s
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$endpoint" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
|
||||
cd .git
|
||||
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
|
||||
actual2=$(git lfs env)
|
||||
[ "$expected2" = "$actual2" ]
|
||||
contains_same_elements "$expected2" "$actual2"
|
||||
)
|
||||
end_test
|
||||
|
||||
@ -171,26 +219,34 @@ begin_test "env with multiple remotes and lfs configs"
|
||||
git config remote.origin.lfsurl "http://custom/origin"
|
||||
git config remote.other.lfsurl "http://custom/other"
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
localwd=$(native_path "$TRASHDIR/$reponame")
|
||||
localgit=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localgitstore=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localmedia=$(native_path "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
tempdir=$(native_path "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||
envVars=$(printf "%s" "$(env | grep "^GIT")")
|
||||
expected=$(printf '%s
|
||||
%s
|
||||
|
||||
Endpoint=http://foo/bar (auth=none)
|
||||
Endpoint (other)=http://custom/other (auth=none)
|
||||
LocalWorkingDir=$TRASHDIR/$reponame
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
|
||||
cd .git
|
||||
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
|
||||
actual2=$(git lfs env)
|
||||
[ "$expected2" = "$actual2" ]
|
||||
contains_same_elements "$expected2" "$actual2"
|
||||
)
|
||||
end_test
|
||||
|
||||
@ -209,26 +265,34 @@ begin_test "env with multiple remotes and lfs url and batch configs"
|
||||
git config remote.origin.lfsurl "http://custom/origin"
|
||||
git config remote.other.lfsurl "http://custom/other"
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
localwd=$(native_path "$TRASHDIR/$reponame")
|
||||
localgit=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localgitstore=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localmedia=$(native_path "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
tempdir=$(native_path "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||
envVars=$(printf "%s" "$(env | grep "^GIT")")
|
||||
expected=$(printf '%s
|
||||
%s
|
||||
|
||||
Endpoint=http://foo/bar (auth=none)
|
||||
Endpoint (other)=http://custom/other (auth=none)
|
||||
LocalWorkingDir=$TRASHDIR/$reponame
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=5
|
||||
BatchTransfer=false
|
||||
$(env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
|
||||
cd .git
|
||||
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
|
||||
actual2=$(git lfs env)
|
||||
[ "$expected2" = "$actual2" ]
|
||||
contains_same_elements "$expected2" "$actual2"
|
||||
)
|
||||
end_test
|
||||
|
||||
@ -248,26 +312,33 @@ begin_test "env with .gitconfig"
|
||||
concurrenttransfers = 5
|
||||
' > .gitconfig
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
localwd=$(native_path "$TRASHDIR/$reponame")
|
||||
localgit=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localgitstore=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localmedia=$(native_path "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
tempdir=$(native_path "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||
envVars=$(printf "%s" "$(env | grep "^GIT")")
|
||||
expected=$(printf '%s
|
||||
%s
|
||||
|
||||
Endpoint=http://foobar:8080/ (auth=none)
|
||||
LocalWorkingDir=$TRASHDIR/$reponame
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
|
||||
mkdir a
|
||||
cd a
|
||||
actual2=$(git lfs env)
|
||||
[ "$expected" = "$actual2" ]
|
||||
contains_same_elements "$expected" "$actual2"
|
||||
)
|
||||
end_test
|
||||
|
||||
@ -278,80 +349,97 @@ begin_test "env with environment variables"
|
||||
git init $reponame
|
||||
mkdir -p $reponame/a/b/c
|
||||
|
||||
gitDir=$TRASHDIR/$reponame/.git
|
||||
workTree=$TRASHDIR/$reponame/a/b
|
||||
gitDir=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
workTree=$(native_path "$TRASHDIR/$reponame/a/b")
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
LocalWorkingDir=$TRASHDIR/$reponame/a/b
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
localwd=$(native_path "$TRASHDIR/$reponame/a/b")
|
||||
localgit=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localgitstore=$(native_path "$TRASHDIR/$reponame/.git")
|
||||
localmedia=$(native_path "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
tempdir=$(native_path "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||
envVars="$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree env | grep "^GIT" | sort)"
|
||||
expected=$(printf '%s
|
||||
%s
|
||||
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
|
||||
actual=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
|
||||
cd $TRASHDIR/$reponame
|
||||
actual2=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env)
|
||||
[ "$expected" = "$actual2" ]
|
||||
contains_same_elements "$expected" "$actual2"
|
||||
|
||||
cd $TRASHDIR/$reponame/.git
|
||||
actual3=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env)
|
||||
[ "$expected" = "$actual3" ]
|
||||
contains_same_elements "$expected" "$actual3"
|
||||
|
||||
cd $TRASHDIR/$reponame/a/b/c
|
||||
actual4=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env)
|
||||
[ "$expected" = "$actual4" ]
|
||||
contains_same_elements "$expected" "$actual4"
|
||||
|
||||
expected5=$(printf "%s\n%s\n
|
||||
LocalWorkingDir=$TRASHDIR/$reponame/a/b
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
envVars="$(GIT_DIR=$gitDir GIT_WORK_TREE=a/b env | grep "^GIT" | sort)"
|
||||
expected5=$(printf '%s
|
||||
%s
|
||||
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(GIT_DIR=$gitDir GIT_WORK_TREE=a/b env | grep "^GIT")
|
||||
%s
|
||||
git config filter.lfs.smudge = \"\"
|
||||
git config filter.lfs.clean = \"\"
|
||||
" "$(git lfs version)" "$(git version)")
|
||||
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars")
|
||||
actual5=$(GIT_DIR=$gitDir GIT_WORK_TREE=a/b git lfs env)
|
||||
[ "$expected5" = "$actual5" ]
|
||||
contains_same_elements "$expected5" "$actual5"
|
||||
|
||||
cd $TRASHDIR/$reponame/a/b
|
||||
expected7=$(printf "%s\n%s\n
|
||||
LocalWorkingDir=$TRASHDIR/$reponame/a/b
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
envVars="$(GIT_DIR=$gitDir env | grep "^GIT" | sort)"
|
||||
expected7=$(printf '%s
|
||||
%s
|
||||
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(GIT_DIR=$gitDir env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual7=$(GIT_DIR=$gitDir git lfs env)
|
||||
[ "$expected7" = "$actual7" ]
|
||||
contains_same_elements "$expected7" "$actual7"
|
||||
|
||||
cd $TRASHDIR/$reponame/a
|
||||
expected8=$(printf "%s\n%s\n
|
||||
LocalWorkingDir=$TRASHDIR/$reponame/a/b
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
envVars="$(GIT_WORK_TREE=$workTree env | grep "^GIT" | sort)"
|
||||
expected8=$(printf '%s
|
||||
%s
|
||||
|
||||
LocalWorkingDir=%s
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(GIT_WORK_TREE=$workTree env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual8=$(GIT_WORK_TREE=$workTree git lfs env)
|
||||
[ "$expected8" = "$actual8" ]
|
||||
contains_same_elements "$expected8" "$actual8"
|
||||
)
|
||||
end_test
|
||||
|
||||
@ -363,19 +451,25 @@ begin_test "env with bare repo"
|
||||
git init --bare $reponame
|
||||
cd $reponame
|
||||
|
||||
localgit=$(native_path "$TRASHDIR/$reponame")
|
||||
localgitstore=$(native_path "$TRASHDIR/$reponame")
|
||||
localmedia=$(native_path "$TRASHDIR/$reponame/lfs/objects")
|
||||
tempdir=$(native_path "$TRASHDIR/$reponame/lfs/tmp")
|
||||
envVars=$(printf "%s" "$(env | grep "^GIT")")
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
LocalWorkingDir=
|
||||
LocalGitDir=$TRASHDIR/$reponame
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame
|
||||
LocalMediaDir=$TRASHDIR/$reponame/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/lfs/tmp
|
||||
LocalGitDir=%s
|
||||
LocalGitStorageDir=%s
|
||||
LocalMediaDir=%s
|
||||
TempDir=%s
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(env | grep "^GIT")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
|
||||
)
|
||||
end_test
|
||||
|
@ -22,7 +22,7 @@ begin_test "fsck default"
|
||||
aOid=$(git log --patch a.dat | grep "^+oid" | cut -d ":" -f 2)
|
||||
aOid12=$(echo $aOid | cut -b 1-2)
|
||||
aOid34=$(echo $aOid | cut -b 3-4)
|
||||
if [ "$aOid .git/lfs/objects/$aOid12/$aOid34/$aOid" != "$(shasum -a 256 .git/lfs/objects/$aOid12/$aOid34/$aOid)" ]; then
|
||||
if [ "$aOid" != "$(shasum -a 256 .git/lfs/objects/$aOid12/$aOid34/$aOid | cut -d " " -f 1)" ]; then
|
||||
echo "oid for a.dat does not match"
|
||||
exit 1
|
||||
fi
|
||||
@ -30,7 +30,7 @@ begin_test "fsck default"
|
||||
bOid=$(git log --patch b.dat | grep "^+oid" | cut -d ":" -f 2)
|
||||
bOid12=$(echo $bOid | cut -b 1-2)
|
||||
bOid34=$(echo $bOid | cut -b 3-4)
|
||||
if [ "$bOid ".git/lfs/objects/$bOid12/$bOid34/$bOid != "$(shasum -a 256 .git/lfs/objects/$bOid12/$bOid34/$bOid)" ]; then
|
||||
if [ "$bOid" != "$(shasum -a 256 .git/lfs/objects/$bOid12/$bOid34/$bOid | cut -d " " -f 1)" ]; then
|
||||
echo "oid for b.dat does not match"
|
||||
exit 1
|
||||
fi
|
||||
@ -38,8 +38,9 @@ begin_test "fsck default"
|
||||
|
||||
echo "CORRUPTION" >> .git/lfs/objects/$aOid12/$aOid34/$aOid
|
||||
|
||||
expected="Object a.dat ($aOid) is corrupt
|
||||
moved to $TRASHDIR/$reponame/.git/lfs/bad/$aOid"
|
||||
moved=$(native_path "$TRASHDIR/$reponame/.git/lfs/bad/$aOid")
|
||||
expected="$(printf 'Object a.dat (%s) is corrupt
|
||||
moved to %s' "$aOid" "$moved")"
|
||||
[ "$expected" = "$(git lfs fsck)" ]
|
||||
|
||||
if [ -e .git/lfs/objects/$aOid12/$aOid34/$aOid ]; then
|
||||
@ -47,7 +48,7 @@ begin_test "fsck default"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$bOid ".git/lfs/objects/$bOid12/$bOid34/$bOid != "$(shasum -a 256 .git/lfs/objects/$bOid12/$bOid34/$bOid)" ]; then
|
||||
if [ "$bOid" != "$(shasum -a 256 .git/lfs/objects/$bOid12/$bOid34/$bOid | cut -d " " -f 1)" ]; then
|
||||
echo "oid for b.dat does not match"
|
||||
exit 1
|
||||
fi
|
||||
@ -74,7 +75,7 @@ begin_test "fsck dry run"
|
||||
aOid=$(git log --patch a.dat | grep "^+oid" | cut -d ":" -f 2)
|
||||
aOid12=$(echo $aOid | cut -b 1-2)
|
||||
aOid34=$(echo $aOid | cut -b 3-4)
|
||||
if [ "$aOid .git/lfs/objects/$aOid12/$aOid34/$aOid" != "$(shasum -a 256 .git/lfs/objects/$aOid12/$aOid34/$aOid)" ]; then
|
||||
if [ "$aOid" != "$(shasum -a 256 .git/lfs/objects/$aOid12/$aOid34/$aOid | cut -d " " -f 1)" ]; then
|
||||
echo "oid for a.dat does not match"
|
||||
exit 1
|
||||
fi
|
||||
@ -82,7 +83,7 @@ begin_test "fsck dry run"
|
||||
bOid=$(git log --patch b.dat | grep "^+oid" | cut -d ":" -f 2)
|
||||
bOid12=$(echo $bOid | cut -b 1-2)
|
||||
bOid34=$(echo $bOid | cut -b 3-4)
|
||||
if [ "$bOid ".git/lfs/objects/$bOid12/$bOid34/$bOid != "$(shasum -a 256 .git/lfs/objects/$bOid12/$bOid34/$bOid)" ]; then
|
||||
if [ "$bOid" != "$(shasum -a 256 .git/lfs/objects/$bOid12/$bOid34/$bOid | cut -d " " -f 1)" ]; then
|
||||
echo "oid for b.dat does not match"
|
||||
exit 1
|
||||
fi
|
||||
@ -91,12 +92,12 @@ begin_test "fsck dry run"
|
||||
|
||||
[ "Object a.dat ($aOid) is corrupt" = "$(git lfs fsck --dry-run)" ]
|
||||
|
||||
if [ "$aOid .git/lfs/objects/$aOid12/$aOid34/$aOid" = "$(shasum -a 256 .git/lfs/objects/$aOid12/$aOid34/$aOid)" ]; then
|
||||
if [ "$aOid" = "$(shasum -a 256 .git/lfs/objects/$aOid12/$aOid34/$aOid | cut -d " " -f 1)" ]; then
|
||||
echo "oid for a.dat still matches match"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$bOid ".git/lfs/objects/$bOid12/$bOid34/$bOid != "$(shasum -a 256 .git/lfs/objects/$bOid12/$bOid34/$bOid)" ]; then
|
||||
if [ "$bOid" != "$(shasum -a 256 .git/lfs/objects/$bOid12/$bOid34/$bOid | cut -d " " -f 1)" ]; then
|
||||
echo "oid for b.dat does not match"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -4,6 +4,41 @@
|
||||
|
||||
. "test/testlib.sh"
|
||||
|
||||
begin_test "clears local temp objects"
|
||||
(
|
||||
set -e
|
||||
|
||||
mkdir repo-temp-objects
|
||||
cd repo-temp-objects
|
||||
git init
|
||||
|
||||
# abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01
|
||||
mkdir -p .git/lfs/objects/go/od
|
||||
mkdir -p .git/lfs/tmp/objects
|
||||
|
||||
touch .git/lfs/objects/go/od/goodabcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwx
|
||||
touch .git/lfs/tmp/objects/goodabcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwx-rand123
|
||||
touch .git/lfs/tmp/objects/goodabcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwx-rand456
|
||||
touch .git/lfs/tmp/objects/badabcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxy-rand123
|
||||
touch .git/lfs/tmp/objects/badabcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxy-rand456
|
||||
|
||||
GIT_TRACE=5 git lfs env
|
||||
|
||||
# object file exists
|
||||
[ -e ".git/lfs/objects/go/od/goodabcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwx" ]
|
||||
|
||||
# newer tmp files exist
|
||||
[ -e ".git/lfs/tmp/objects/badabcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxy-rand123" ]
|
||||
[ -e ".git/lfs/tmp/objects/badabcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxy-rand456" ]
|
||||
|
||||
# existing tmp files were cleaned up
|
||||
[ ! -e ".git/lfs/tmp/objects/goodabcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwx-rand123" ]
|
||||
[ ! -e ".git/lfs/tmp/objects/goodabcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwx-rand456" ]
|
||||
)
|
||||
end_test
|
||||
|
||||
exit 0
|
||||
|
||||
begin_test "happy path"
|
||||
(
|
||||
set -e
|
||||
|
@ -161,6 +161,12 @@ end_test
|
||||
|
||||
begin_test "init --local outside repository"
|
||||
(
|
||||
# If run inside the git-lfs source dir this will update its .git/config & cause issues
|
||||
if [ "$GIT_LFS_TEST_DIR" == "" ]; then
|
||||
echo "Skipping init --local because GIT_LFS_TEST_DIR is not set"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
set +e
|
||||
|
||||
[ -n "$LFS_DOCKER" ] && exit 0
|
||||
|
@ -93,7 +93,13 @@ end_test
|
||||
|
||||
begin_test "pointer --stdin without stdin"
|
||||
(
|
||||
output=$(git lfs pointer --stdin 2>&1)
|
||||
# this test doesn't work on Windows, it just operates like 'bad pointer' case
|
||||
# stdin isn't detectable as detached, it just times out with no content
|
||||
if [[ "$(is_stdin_attached)" == "0" ]]; then
|
||||
echo "Skipping pointer without stdin because STDIN attached"
|
||||
exit 0
|
||||
fi
|
||||
output=$(echo "" | git lfs pointer --stdin 2>&1)
|
||||
status=$?
|
||||
|
||||
set -e
|
||||
@ -212,7 +218,7 @@ begin_test "pointer missing --pointer"
|
||||
set -e
|
||||
|
||||
[ "1" = "$status" ]
|
||||
[ "open missing-pointer: no such file or directory" = "$output" ]
|
||||
[[ "$output" == open missing-pointer:* ]]
|
||||
)
|
||||
end_test
|
||||
|
||||
|
@ -38,6 +38,24 @@ begin_test "smudge --info"
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "smudge with temp file"
|
||||
(
|
||||
set -e
|
||||
|
||||
cd repo
|
||||
|
||||
rm -rf .git/lfs/objects
|
||||
mkdir -p .git/lfs/tmp/objects
|
||||
touch .git/lfs/tmp/objects/fcf5015df7a9089a7aa7fe74139d4b8f7d62e52d5a34f9a87aeffc8e8c668254-1
|
||||
pointer fcf5015df7a9089a7aa7fe74139d4b8f7d62e52d5a34f9a87aeffc8e8c668254 9 | GIT_TRACE=5 git lfs smudge | tee smudge.log
|
||||
[ "smudge a" = "$(cat smudge.log)" ] || {
|
||||
rm -rf .git/lfs/tmp
|
||||
git lfs logs last
|
||||
exit 1
|
||||
}
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "smudge with invalid pointer"
|
||||
(
|
||||
set -e
|
||||
|
@ -41,43 +41,44 @@ begin_test "submodule env"
|
||||
|
||||
git lfs env | tee env.log
|
||||
grep "Endpoint=$GITSERVER/$reponame.git/info/lfs (auth=none)$" env.log
|
||||
grep "LocalWorkingDir=$TRASHDIR/repo$" env.log
|
||||
grep "LocalGitDir=$TRASHDIR/repo/.git$" env.log
|
||||
grep "LocalGitStorageDir=$TRASHDIR/repo/.git$" env.log
|
||||
grep "LocalMediaDir=$TRASHDIR/repo/.git/lfs/objects$" env.log
|
||||
grep "TempDir=$TRASHDIR/repo/.git/lfs/tmp$" env.log
|
||||
grep "LocalWorkingDir=$(native_path_escaped "$TRASHDIR/repo$")" env.log
|
||||
grep "LocalGitDir=$(native_path_escaped "$TRASHDIR/repo/.git$")" env.log
|
||||
grep "LocalGitStorageDir=$(native_path_escaped "$TRASHDIR/repo/.git$")" env.log
|
||||
grep "LocalMediaDir=$(native_path_escaped "$TRASHDIR/repo/.git/lfs/objects$")" env.log
|
||||
grep "TempDir=$(native_path_escaped "$TRASHDIR/repo/.git/lfs/tmp$")" env.log
|
||||
|
||||
cd .git
|
||||
|
||||
echo "./.git"
|
||||
git lfs env | tee env.log
|
||||
cat env.log
|
||||
grep "Endpoint=$GITSERVER/$reponame.git/info/lfs (auth=none)$" env.log
|
||||
grep "LocalWorkingDir=$" env.log
|
||||
grep "LocalGitDir=$TRASHDIR/repo/.git$" env.log
|
||||
grep "LocalGitStorageDir=$TRASHDIR/repo/.git$" env.log
|
||||
grep "LocalMediaDir=$TRASHDIR/repo/.git/lfs/objects$" env.log
|
||||
grep "TempDir=$TRASHDIR/repo/.git/lfs/tmp$" env.log
|
||||
grep "LocalGitDir=$(native_path_escaped "$TRASHDIR/repo/.git$")" env.log
|
||||
grep "LocalGitStorageDir=$(native_path_escaped "$TRASHDIR/repo/.git$")" env.log
|
||||
grep "LocalMediaDir=$(native_path_escaped "$TRASHDIR/repo/.git/lfs/objects$")" env.log
|
||||
grep "TempDir=$(native_path_escaped "$TRASHDIR/repo/.git/lfs/tmp$")" env.log
|
||||
|
||||
cd ../sub
|
||||
|
||||
echo "./sub"
|
||||
git lfs env | tee env.log
|
||||
grep "Endpoint=$GITSERVER/$submodname.git/info/lfs (auth=none)$" env.log
|
||||
grep "LocalWorkingDir=$TRASHDIR/repo/sub$" env.log
|
||||
grep "LocalGitDir=$TRASHDIR/repo/.git/modules/sub$" env.log
|
||||
grep "LocalGitStorageDir=$TRASHDIR/repo/.git/modules/sub$" env.log
|
||||
grep "LocalMediaDir=$TRASHDIR/repo/.git/modules/sub/lfs/objects$" env.log
|
||||
grep "TempDir=$TRASHDIR/repo/.git/modules/sub/lfs/tmp$" env.log
|
||||
grep "LocalWorkingDir=$(native_path_escaped "$TRASHDIR/repo/sub$")" env.log
|
||||
grep "LocalGitDir=$(native_path_escaped "$TRASHDIR/repo/.git/modules/sub$")" env.log
|
||||
grep "LocalGitStorageDir=$(native_path_escaped "$TRASHDIR/repo/.git/modules/sub$")" env.log
|
||||
grep "LocalMediaDir=$(native_path_escaped "$TRASHDIR/repo/.git/modules/sub/lfs/objects$")" env.log
|
||||
grep "TempDir=$(native_path_escaped "$TRASHDIR/repo/.git/modules/sub/lfs/tmp$")" env.log
|
||||
|
||||
cd dir
|
||||
|
||||
echo "./sub/dir"
|
||||
git lfs env | tee env.log
|
||||
grep "Endpoint=$GITSERVER/$submodname.git/info/lfs (auth=none)$" env.log
|
||||
grep "LocalWorkingDir=$TRASHDIR/repo/sub$" env.log
|
||||
grep "LocalGitDir=$TRASHDIR/repo/.git/modules/sub$" env.log
|
||||
grep "LocalGitStorageDir=$TRASHDIR/repo/.git/modules/sub$" env.log
|
||||
grep "LocalMediaDir=$TRASHDIR/repo/.git/modules/sub/lfs/objects$" env.log
|
||||
grep "TempDir=$TRASHDIR/repo/.git/modules/sub/lfs/tmp$" env.log
|
||||
grep "LocalWorkingDir=$(native_path_escaped "$TRASHDIR/repo/sub$")" env.log
|
||||
grep "LocalGitDir=$(native_path_escaped "$TRASHDIR/repo/.git/modules/sub$")" env.log
|
||||
grep "LocalGitStorageDir=$(native_path_escaped "$TRASHDIR/repo/.git/modules/sub$")" env.log
|
||||
grep "LocalMediaDir=$(native_path_escaped "$TRASHDIR/repo/.git/modules/sub/lfs/objects$")" env.log
|
||||
grep "TempDir=$(native_path_escaped "$TRASHDIR/repo/.git/modules/sub/lfs/tmp$")" env.log
|
||||
)
|
||||
end_test
|
||||
|
@ -38,10 +38,10 @@ begin_test "track"
|
||||
|
||||
out=$(git lfs track)
|
||||
echo "$out" | grep "Listing tracked paths"
|
||||
echo "$out" | grep "*.mov (.git/info/attributes)"
|
||||
echo "$out" | grep "*.mov ($(native_path_escaped ".git/info/attributes"))"
|
||||
echo "$out" | grep "*.jpg (.gitattributes)"
|
||||
echo "$out" | grep "*.gif (a/.gitattributes)"
|
||||
echo "$out" | grep "*.png (a/b/.gitattributes)"
|
||||
echo "$out" | grep "*.gif ($(native_path_escaped "a/.gitattributes"))"
|
||||
echo "$out" | grep "*.png ($(native_path_escaped "a/b/.gitattributes"))"
|
||||
)
|
||||
end_test
|
||||
|
||||
@ -134,9 +134,9 @@ begin_test "track representation"
|
||||
cd track-representation
|
||||
|
||||
git lfs track "*.jpg"
|
||||
out=$(git lfs track "$PWD/*.jpg")
|
||||
out=$(git lfs track "$(native_path "$PWD/")*.jpg")
|
||||
|
||||
if [ "$out" != "$PWD/*.jpg already supported" ]; then
|
||||
if [ "$out" != "$(native_path "$PWD/")*.jpg already supported" ]; then
|
||||
echo "Track didn't recognize duplicate path"
|
||||
cat .gitattributes
|
||||
exit 1
|
||||
@ -179,7 +179,7 @@ begin_test "track absolute"
|
||||
git init track-absolute
|
||||
cd track-absolute
|
||||
|
||||
git lfs track "$PWD/*.jpg"
|
||||
git lfs track "$(native_path "$PWD/")*.jpg"
|
||||
grep "^*.jpg" .gitattributes || {
|
||||
echo ".gitattributes doesn't contain the expected relative path *.jpg:"
|
||||
cat .gitattributes
|
||||
|
@ -20,18 +20,18 @@ begin_test "git worktree"
|
||||
git commit -m "Initial commit"
|
||||
|
||||
expected=$(printf "%s\n%s\n
|
||||
LocalWorkingDir=$TRASHDIR/$reponame
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/lfs/tmp
|
||||
LocalWorkingDir=$(native_path_escaped "$TRASHDIR/$reponame")
|
||||
LocalGitDir=$(native_path_escaped "$TRASHDIR/$reponame/.git")
|
||||
LocalGitStorageDir=$(native_path_escaped "$TRASHDIR/$reponame/.git")
|
||||
LocalMediaDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
TempDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(env | grep "^GIT")
|
||||
$(escape_path "$(env | grep "^GIT")")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
|
||||
worktreename="worktree-2"
|
||||
git worktree add "$TRASHDIR/$worktreename"
|
||||
@ -41,17 +41,17 @@ $(env | grep "^GIT")
|
||||
# is only for index, temp etc
|
||||
# storage of git objects and lfs objects is in the original .git
|
||||
expected=$(printf "%s\n%s\n
|
||||
LocalWorkingDir=$TRASHDIR/$worktreename
|
||||
LocalGitDir=$TRASHDIR/$reponame/.git/worktrees/$worktreename
|
||||
LocalGitStorageDir=$TRASHDIR/$reponame/.git
|
||||
LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects
|
||||
TempDir=$TRASHDIR/$reponame/.git/worktrees/$worktreename/lfs/tmp
|
||||
LocalWorkingDir=$(native_path_escaped "$TRASHDIR/$worktreename")
|
||||
LocalGitDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/worktrees/$worktreename")
|
||||
LocalGitStorageDir=$(native_path_escaped "$TRASHDIR/$reponame/.git")
|
||||
LocalMediaDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||
TempDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/worktrees/$worktreename/lfs/tmp")
|
||||
ConcurrentTransfers=3
|
||||
BatchTransfer=true
|
||||
$(env | grep "^GIT")
|
||||
$(escape_path "$(env | grep "^GIT")")
|
||||
%s
|
||||
" "$(git lfs version)" "$(git version)" "$envInitConfig")
|
||||
actual=$(git lfs env)
|
||||
[ "$expected" = "$actual" ]
|
||||
contains_same_elements "$expected" "$actual"
|
||||
)
|
||||
end_test
|
||||
|
@ -49,6 +49,13 @@ TESTHOME="$REMOTEDIR/home"
|
||||
|
||||
GIT_CONFIG_NOSYSTEM=1
|
||||
|
||||
UNAME=$(uname -s)
|
||||
IS_WINDOWS=0
|
||||
if [[ $UNAME == MINGW* || $UNAME == CYGWIN* ]]
|
||||
then
|
||||
IS_WINDOWS=1
|
||||
fi
|
||||
|
||||
export CREDSDIR
|
||||
|
||||
if [[ `git config --system credential.helper | grep osxkeychain` == "osxkeychain" ]]
|
||||
|
@ -382,3 +382,51 @@ get_date() {
|
||||
date $ARGS -u +%Y-%m-%dT%TZ
|
||||
fi
|
||||
}
|
||||
|
||||
# Convert potentially MinGW bash paths to native Windows paths
|
||||
# Needed to match generic built paths in test scripts to native paths generated from Go
|
||||
native_path() {
|
||||
local arg=$1
|
||||
if [ $IS_WINDOWS == "1" ]; then
|
||||
# Use params form to avoid interpreting any '\' characters
|
||||
printf '%s' "$(cygpath -w $arg)"
|
||||
else
|
||||
printf '%s' "$arg"
|
||||
fi
|
||||
}
|
||||
|
||||
# escape any instance of '\' with '\\' on Windows
|
||||
escape_path() {
|
||||
local unescaped="$1"
|
||||
if [ $IS_WINDOWS == "1" ]; then
|
||||
printf '%s' "${unescaped//\\/\\\\}"
|
||||
else
|
||||
printf '%s' "$unescaped"
|
||||
fi
|
||||
}
|
||||
|
||||
# As native_path but escape all backslash characters to "\\"
|
||||
native_path_escaped() {
|
||||
local unescaped=$(native_path "$1")
|
||||
escape_path "$unescaped"
|
||||
}
|
||||
|
||||
# Compare 2 lists which are newline-delimited in a string, ignoring ordering and blank lines
|
||||
contains_same_elements() {
|
||||
# Remove blank lines then sort
|
||||
printf '%s' "$1" | grep -v '^$' | sort > a.txt
|
||||
printf '%s' "$2" | grep -v '^$' | sort > b.txt
|
||||
|
||||
set +e
|
||||
diff -u a.txt b.txt 1>&2
|
||||
res=$?
|
||||
set -e
|
||||
rm a.txt b.txt
|
||||
exit $res
|
||||
}
|
||||
|
||||
|
||||
is_stdin_attached() {
|
||||
test -t0
|
||||
echo $?
|
||||
}
|
@ -75,11 +75,17 @@ begin_test () {
|
||||
err="$TRASHDIR/err"
|
||||
trace="$TRASHDIR/trace"
|
||||
|
||||
exec 1>"$out" 2>"$err" 5>"$trace"
|
||||
exec 1>"$out" 2>"$err"
|
||||
|
||||
# enabling GIT_TRACE can cause Windows git to stall, esp with fd 5
|
||||
# other fd numbers like 8/9 don't stall but still don't work, so disable
|
||||
if [ $IS_WINDOWS == "0" ]; then
|
||||
exec 5>"$trace"
|
||||
export GIT_TRACE=5
|
||||
fi
|
||||
|
||||
# reset global git config
|
||||
HOME="$TRASHDIR/home"
|
||||
export GIT_TRACE=5
|
||||
rm -rf "$TRASHDIR/home"
|
||||
mkdir "$HOME"
|
||||
cp "$TESTHOME/.gitconfig" "$HOME/.gitconfig"
|
||||
@ -97,6 +103,8 @@ end_test () {
|
||||
test_status="${1:-$?}"
|
||||
set +x -e
|
||||
exec 1>&3 2>&4
|
||||
# close fd 5 (GIT_TRACE)
|
||||
exec 5>&-
|
||||
|
||||
if [ "$test_status" -eq 0 ]; then
|
||||
printf "test: %-60s OK\n" "$test_description ..."
|
||||
@ -109,8 +117,10 @@ end_test () {
|
||||
echo "-- stderr --"
|
||||
grep -v -e '^\+ end_test' -e '^+ set +x' <"$TRASHDIR/err" |
|
||||
sed 's/^/ /'
|
||||
if [ "$IS_WINDOWS" == "0" ]; then
|
||||
echo "-- git trace --"
|
||||
sed 's/^/ /' <"$TRASHDIR/trace"
|
||||
fi
|
||||
) 1>&2
|
||||
echo
|
||||
fi
|
||||
|
@ -1,20 +0,0 @@
|
||||
Copyright (c) 2014 rick olson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,49 +0,0 @@
|
||||
# Content Addressable
|
||||
|
||||
Package contentaddressable contains tools for writing content addressable files.
|
||||
Files are written to a temporary location, and only renamed to the final
|
||||
location after the file's OID (Object ID) has been verified.
|
||||
|
||||
```go
|
||||
filename := "path/to/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b"
|
||||
file, err := contentaddressable.NewFile(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
file.Oid // 01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b
|
||||
|
||||
written, err := io.Copy(file, someReader)
|
||||
|
||||
if err == nil {
|
||||
// Move file to final location if OID is verified.
|
||||
err = file.Accept()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
```
|
||||
|
||||
See the [godocs](http://godoc.org/github.com/technoweenie/go-contentaddressable)
|
||||
for details.
|
||||
|
||||
## Installation
|
||||
|
||||
$ go get github.com/technoweenie/go-contentaddressable
|
||||
|
||||
Then import it:
|
||||
|
||||
import "github.com/technoweenie/go-contentaddressable"
|
||||
|
||||
## Note on Patches/Pull Requests
|
||||
|
||||
1. Fork the project on GitHub.
|
||||
2. Make your feature addition or bug fix.
|
||||
3. Add tests for it. This is important so I don't break it in a future version
|
||||
unintentionally.
|
||||
4. Commit, do not mess with version or history. (if you want to have
|
||||
your own version, that is fine but bump version in a commit by itself I can
|
||||
ignore when I pull)
|
||||
5. Send me a pull request. Bonus points for topic branches.
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
Package contentaddressable contains tools for writing content addressable files.
|
||||
Files are written to a temporary location, and only renamed to the final
|
||||
location after the file's OID (Object ID) has been verified.
|
||||
|
||||
filename := "path/to/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b"
|
||||
file, err := contentaddressable.NewFile(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
file.Oid // 01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b
|
||||
|
||||
written, err := io.Copy(file, someReader)
|
||||
|
||||
if err == nil {
|
||||
// Move file to final location if OID is verified.
|
||||
err = file.Accept()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Currently SHA-256 is used for a file's OID.
|
||||
*/
|
||||
package contentaddressable
|
@ -1,131 +0,0 @@
|
||||
package contentaddressable
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var (
|
||||
AlreadyClosed = errors.New("Already closed.")
|
||||
HasData = errors.New("Destination file already has data.")
|
||||
)
|
||||
|
||||
// File handles the atomic writing of a content addressable file. It writes to
|
||||
// a temp file, and then renames to the final location after Accept().
|
||||
type File struct {
|
||||
Oid string
|
||||
filename string
|
||||
tempFilename string
|
||||
file *os.File
|
||||
tempFile *os.File
|
||||
hasher hash.Hash
|
||||
}
|
||||
|
||||
// NewFile initializes a content addressable file for writing. It opens both
|
||||
// the given filename, and a temp filename in exclusive mode. The *File OID
|
||||
// is taken from the base name of the given filename.
|
||||
func NewFile(filename string) (*File, error) {
|
||||
oid := filepath.Base(filename)
|
||||
dir := filepath.Dir(filename)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tempFilename := filename + "-temp"
|
||||
tempFile, err := os.OpenFile(tempFilename, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
|
||||
if err != nil {
|
||||
cleanupFile(tempFile)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caw := &File{
|
||||
Oid: oid,
|
||||
filename: filename,
|
||||
tempFilename: tempFilename,
|
||||
file: file,
|
||||
tempFile: tempFile,
|
||||
hasher: sha256.New(),
|
||||
}
|
||||
|
||||
return caw, nil
|
||||
}
|
||||
|
||||
// Write sends data to the temporary file.
|
||||
func (w *File) Write(p []byte) (int, error) {
|
||||
if w.Closed() {
|
||||
return 0, AlreadyClosed
|
||||
}
|
||||
|
||||
w.hasher.Write(p)
|
||||
return w.tempFile.Write(p)
|
||||
}
|
||||
|
||||
// Accept verifies the written content SHA-256 signature matches the given OID.
|
||||
// If it matches, the temp file is renamed to the original filename. If not,
|
||||
// an error is returned.
|
||||
func (w *File) Accept() error {
|
||||
if w.Closed() {
|
||||
return AlreadyClosed
|
||||
}
|
||||
|
||||
sig := hex.EncodeToString(w.hasher.Sum(nil))
|
||||
if sig != w.Oid {
|
||||
return fmt.Errorf("Content mismatch. Expected OID %s, got %s", w.Oid, sig)
|
||||
}
|
||||
|
||||
if err := cleanupFile(w.file); err != nil {
|
||||
return err
|
||||
}
|
||||
w.file = nil
|
||||
|
||||
w.tempFile.Close()
|
||||
err := os.Rename(w.tempFilename, w.filename)
|
||||
w.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
// Close cleans up the internal file objects.
|
||||
func (w *File) Close() error {
|
||||
if w.tempFile != nil {
|
||||
if err := cleanupFile(w.tempFile); err != nil {
|
||||
return err
|
||||
}
|
||||
w.tempFile = nil
|
||||
}
|
||||
|
||||
if w.file != nil {
|
||||
if err := cleanupFile(w.file); err != nil {
|
||||
return err
|
||||
}
|
||||
w.file = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Closed reports whether this file object has been closed.
|
||||
func (w *File) Closed() bool {
|
||||
if w.tempFile == nil || w.file == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func cleanupFile(f *os.File) error {
|
||||
err := f.Close()
|
||||
if err := os.RemoveAll(f.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
@ -1,176 +0,0 @@
|
||||
package contentaddressable
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"reflect"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var supOid = "a2b71d6ee8997eb87b25ab42d566c44f6a32871752c7c73eb5578cb1182f7be0"
|
||||
|
||||
func TestFile(t *testing.T) {
|
||||
test := SetupFile(t)
|
||||
defer test.Teardown()
|
||||
|
||||
filename := filepath.Join(test.Path, supOid)
|
||||
aw, err := NewFile(filename)
|
||||
assertEqual(t, nil, err)
|
||||
|
||||
n, err := aw.Write([]byte("SUP"))
|
||||
assertEqual(t, nil, err)
|
||||
assertEqual(t, 3, n)
|
||||
|
||||
by, err := ioutil.ReadFile(filename)
|
||||
assertEqual(t, nil, err)
|
||||
assertEqual(t, 0, len(by))
|
||||
|
||||
assertEqual(t, nil, aw.Accept())
|
||||
|
||||
by, err = ioutil.ReadFile(filename)
|
||||
assertEqual(t, nil, err)
|
||||
assertEqual(t, "SUP", string(by))
|
||||
|
||||
assertEqual(t, nil, aw.Close())
|
||||
}
|
||||
|
||||
func TestFileMismatch(t *testing.T) {
|
||||
test := SetupFile(t)
|
||||
defer test.Teardown()
|
||||
|
||||
filename := filepath.Join(test.Path, "b2b71d6ee8997eb87b25ab42d566c44f6a32871752c7c73eb5578cb1182f7be0")
|
||||
aw, err := NewFile(filename)
|
||||
assertEqual(t, nil, err)
|
||||
|
||||
n, err := aw.Write([]byte("SUP"))
|
||||
assertEqual(t, nil, err)
|
||||
assertEqual(t, 3, n)
|
||||
|
||||
by, err := ioutil.ReadFile(filename)
|
||||
assertEqual(t, nil, err)
|
||||
assertEqual(t, 0, len(by))
|
||||
|
||||
err = aw.Accept()
|
||||
if err == nil || !strings.Contains(err.Error(), "Content mismatch") {
|
||||
t.Errorf("Expected mismatch error: %s", err)
|
||||
}
|
||||
|
||||
by, err = ioutil.ReadFile(filename)
|
||||
assertEqual(t, nil, err)
|
||||
assertEqual(t, "", string(by))
|
||||
|
||||
assertEqual(t, nil, aw.Close())
|
||||
|
||||
_, err = ioutil.ReadFile(filename)
|
||||
assertEqual(t, true, os.IsNotExist(err))
|
||||
}
|
||||
|
||||
func TestFileCancel(t *testing.T) {
|
||||
test := SetupFile(t)
|
||||
defer test.Teardown()
|
||||
|
||||
filename := filepath.Join(test.Path, supOid)
|
||||
aw, err := NewFile(filename)
|
||||
assertEqual(t, nil, err)
|
||||
|
||||
n, err := aw.Write([]byte("SUP"))
|
||||
assertEqual(t, nil, err)
|
||||
assertEqual(t, 3, n)
|
||||
|
||||
assertEqual(t, nil, aw.Close())
|
||||
|
||||
for _, name := range []string{aw.filename, aw.tempFilename} {
|
||||
if _, err := os.Stat(name); err == nil {
|
||||
t.Errorf("%s exists?", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileLocks(t *testing.T) {
|
||||
test := SetupFile(t)
|
||||
defer test.Teardown()
|
||||
|
||||
filename := filepath.Join(test.Path, supOid)
|
||||
aw, err := NewFile(filename)
|
||||
assertEqual(t, nil, err)
|
||||
assertEqual(t, filename, aw.filename)
|
||||
assertEqual(t, filename+"-temp", aw.tempFilename)
|
||||
|
||||
files := []string{aw.filename, aw.tempFilename}
|
||||
|
||||
for _, name := range files {
|
||||
if _, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0665); err == nil {
|
||||
t.Errorf("Able to open %s!", name)
|
||||
}
|
||||
}
|
||||
|
||||
assertEqual(t, nil, aw.Close())
|
||||
|
||||
for _, name := range files {
|
||||
f, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0665)
|
||||
assertEqualf(t, nil, err, "unable to open %s: %s", name, err)
|
||||
cleanupFile(f)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileDuel(t *testing.T) {
|
||||
test := SetupFile(t)
|
||||
defer test.Teardown()
|
||||
|
||||
filename := filepath.Join(test.Path, supOid)
|
||||
aw, err := NewFile(filename)
|
||||
assertEqual(t, nil, err)
|
||||
defer aw.Close()
|
||||
|
||||
if _, err := NewFile(filename); err == nil {
|
||||
t.Errorf("Expected a file open conflict!")
|
||||
}
|
||||
}
|
||||
|
||||
func SetupFile(t *testing.T) *FileTest {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting wd: %s", err)
|
||||
}
|
||||
|
||||
return &FileTest{filepath.Join(wd, "File"), t}
|
||||
}
|
||||
|
||||
type FileTest struct {
|
||||
Path string
|
||||
*testing.T
|
||||
}
|
||||
|
||||
func (t *FileTest) Teardown() {
|
||||
if err := os.RemoveAll(t.Path); err != nil {
|
||||
t.Fatalf("Error removing %s: %s", t.Path, err)
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqual(t *testing.T, expected, actual interface{}) {
|
||||
checkAssertion(t, expected, actual, "")
|
||||
}
|
||||
|
||||
func assertEqualf(t *testing.T, expected, actual interface{}, format string, args ...interface{}) {
|
||||
checkAssertion(t, expected, actual, format, args...)
|
||||
}
|
||||
|
||||
func checkAssertion(t *testing.T, expected, actual interface{}, format string, args ...interface{}) {
|
||||
if expected == nil {
|
||||
if actual == nil {
|
||||
return
|
||||
}
|
||||
} else if reflect.DeepEqual(expected, actual) {
|
||||
return
|
||||
}
|
||||
|
||||
_, file, line, _ := runtime.Caller(2) // assertEqual + checkAssertion
|
||||
t.Logf("%s:%d\nExpected: %v\nActual: %v", file, line, expected, actual)
|
||||
if len(args) > 0 {
|
||||
t.Logf("! - "+format, args...)
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
Loading…
Reference in New Issue
Block a user