From 66ebac22a7c37007cd453c729f2c580787c2fd27 Mon Sep 17 00:00:00 2001 From: Steve Streeting Date: Fri, 31 Jul 2015 12:17:50 +0100 Subject: [PATCH] Fixed support for worktree Issue is that during 'git worktree add', git uses GIT_DIR to locate the worktree girder, which then resolves via commondir. When actually running in the worktree, it follows .git/git-dir THEN commondir. Generalised so this now works, and introduced LocalGitStorageDir. --- commands/command_fsck.go | 2 +- lfs/lfs.go | 49 +++++++++++++++++++++++++--------------- test/test-env.sh | 13 +++++++++++ test/test-submodule.sh | 4 ++++ 4 files changed, 49 insertions(+), 19 deletions(-) diff --git a/commands/command_fsck.go b/commands/command_fsck.go index 6a689ebd..7b800e5c 100644 --- a/commands/command_fsck.go +++ b/commands/command_fsck.go @@ -83,7 +83,7 @@ func doFsck() (bool, error) { continue } - badDir := filepath.Join(lfs.LocalGitDir, "lfs", "bad") + badDir := filepath.Join(lfs.LocalGitStorageDir, "lfs", "bad") if err := os.MkdirAll(badDir, 0755); err != nil { return false, err } diff --git a/lfs/lfs.go b/lfs/lfs.go index b3c3d1c1..3d754752 100644 --- a/lfs/lfs.go +++ b/lfs/lfs.go @@ -25,6 +25,7 @@ var ( UserAgent string LocalWorkingDir string LocalGitDir string + LocalGitStorageDir string // parent of objects/lfs (may be same as LocalGitDir but may not) LocalMediaDir string LocalLogDir string checkedTempDir string @@ -69,13 +70,16 @@ func ObjectExistsOfSize(sha string, size int64) bool { func Environ() []string { osEnviron := os.Environ() - env := make([]string, 6, len(osEnviron)+6) - env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir) - env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir) - env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir) - env[3] = fmt.Sprintf("TempDir=%s", TempDir) - env[4] = fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers()) - env[5] = fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer()) + env := make([]string, 7, len(osEnviron)+7) + env = append(env, + fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir), + fmt.Sprintf("LocalGitDir=%s", LocalGitDir), + fmt.Sprintf("LocalGitStorageDir=%s", LocalGitStorageDir), + fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir), + fmt.Sprintf("TempDir=%s", TempDir), + fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers()), + fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer()), + ) for _, e := range osEnviron { if !strings.Contains(e, "GIT_") { @@ -99,9 +103,10 @@ func init() { LocalWorkingDir, LocalGitDir, err = resolveGitDir() if err == nil { - LocalMediaDir = filepath.Join(LocalGitDir, "lfs", "objects") + LocalGitStorageDir = resolveGitStorageDir(LocalGitDir) + LocalMediaDir = filepath.Join(LocalGitStorageDir, "lfs", "objects") // objects across all worktrees LocalLogDir = filepath.Join(LocalMediaDir, "logs") - TempDir = filepath.Join(LocalGitDir, "lfs", "tmp") + TempDir = filepath.Join(LocalGitDir, "lfs", "tmp") // temp files per worktree if err := os.MkdirAll(LocalMediaDir, localMediaDirPerms); err != nil { panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err)) @@ -257,18 +262,26 @@ func processGitRedirectFile(file, prefix string) (string, error) { dir = filepath.Join(filepath.Dir(file), dir) } - // Finally, check the contents of dir; if it contains a "commondir" file and - // not an "objects" dir, then this is probably a worktree link (see man git-worktree) - // The commondir file points to the actual location - commondirpath := filepath.Join(dir, "commondir") - if FileExists(commondirpath) && !DirExists(filepath.Join(dir, "objects")) { - // no git-dir: prefix in commondir - return processGitRedirectFile(commondirpath, "") - } - return dir, nil } +// From a git dir, get the location that objects are to be stored (we will store lfs alongside) +// Sometimes there is an additional level of redirect on the .git folder by way of a commondir file +// before you find object storage, e.g. 'git worktree' uses this. It redirects to gitdir either by GIT_DIR +// (during setup) or .git/git-dir: (during use), but this only contains the index etc, the objects +// are found in another git dir via 'commondir'. +func resolveGitStorageDir(gitDir string) string { + commondirpath := filepath.Join(gitDir, "commondir") + if FileExists(commondirpath) && !DirExists(filepath.Join(gitDir, "objects")) { + // no git-dir: prefix in commondir + storage, err := processGitRedirectFile(commondirpath, "") + if err == nil { + return storage + } + } + return gitDir +} + const ( gitExt = ".git" gitPtrPrefix = "gitdir: " diff --git a/test/test-env.sh b/test/test-env.sh index 98815f0a..d6508a33 100755 --- a/test/test-env.sh +++ b/test/test-env.sh @@ -13,6 +13,7 @@ begin_test "env with no remote" expected=$(printf "%s\n%s\n LocalWorkingDir=$TRASHDIR/$reponame LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 @@ -37,6 +38,7 @@ begin_test "env with origin remote" Endpoint=$GITSERVER/$reponame.git/info/lfs LocalWorkingDir=$TRASHDIR/$reponame LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 @@ -68,6 +70,7 @@ Endpoint=$GITSERVER/env-origin-remote.git/info/lfs Endpoint (other)=$GITSERVER/env-other-remote.git/info/lfs LocalWorkingDir=$TRASHDIR/$reponame LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 @@ -97,6 +100,7 @@ begin_test "env with other remote" Endpoint (other)=$GITSERVER/env-other-remote.git/info/lfs LocalWorkingDir=$TRASHDIR/$reponame LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 @@ -129,6 +133,7 @@ Endpoint=http://foo/bar Endpoint (other)=$GITSERVER/env-other-remote.git/info/lfs LocalWorkingDir=$TRASHDIR/$reponame LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 @@ -163,6 +168,7 @@ Endpoint=http://foo/bar Endpoint (other)=http://custom/other LocalWorkingDir=$TRASHDIR/$reponame LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 @@ -199,6 +205,7 @@ Endpoint=http://foo/bar Endpoint (other)=http://custom/other LocalWorkingDir=$TRASHDIR/$reponame LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=5 @@ -235,6 +242,7 @@ begin_test "env with .gitconfig" Endpoint=http://foobar:8080/ LocalWorkingDir=$TRASHDIR/$reponame LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=5 @@ -265,6 +273,7 @@ begin_test "env with environment variables" expected=$(printf "%s\n%s\n LocalWorkingDir=$TRASHDIR/$reponame/a/b LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 @@ -290,6 +299,7 @@ $(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree env | grep "^GIT") expected5=$(printf "%s\n%s\n LocalWorkingDir=$TRASHDIR/$reponame/a/b LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 @@ -302,6 +312,7 @@ $(GIT_DIR=$gitDir GIT_WORK_TREE=a/b env | grep "^GIT") expected6=$(printf "%s\n%s\n LocalWorkingDir=$TRASHDIR/$reponame/a/b LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 @@ -315,6 +326,7 @@ $(GIT_WORK_TREE=a/b env | grep "^GIT") expected7=$(printf "%s\n%s\n LocalWorkingDir=$TRASHDIR/$reponame/a/b LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 @@ -328,6 +340,7 @@ $(GIT_DIR=$gitDir env | grep "^GIT") expected8=$(printf "%s\n%s\n LocalWorkingDir=$TRASHDIR/$reponame/a/b LocalGitDir=$TRASHDIR/$reponame/.git +LocalGitStorageDir=$LocalGitDir LocalMediaDir=$TRASHDIR/$reponame/.git/lfs/objects TempDir=$TRASHDIR/$reponame/.git/lfs/tmp ConcurrentTransfers=3 diff --git a/test/test-submodule.sh b/test/test-submodule.sh index 5c439890..4b01a55a 100755 --- a/test/test-submodule.sh +++ b/test/test-submodule.sh @@ -43,6 +43,7 @@ begin_test "submodule env" grep "Endpoint=$GITSERVER/$reponame.git/info/lfs$" 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 @@ -53,6 +54,7 @@ begin_test "submodule env" grep "Endpoint=$GITSERVER/$reponame.git/info/lfs$" 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 @@ -63,6 +65,7 @@ begin_test "submodule env" grep "Endpoint=$GITSERVER/$submodname.git/info/lfs$" env.log grep "LocalWorkingDir=$TRASHDIR/repo/sub$" env.log grep "LocalGitDir=$TRASHDIR/repo/.git/modules/sub$" env.log + grep "LocalGitStorageDir=$TRASHDIR/repo/.git$" env.log grep "LocalMediaDir=$TRASHDIR/repo/.git/modules/sub/lfs/objects$" env.log grep "TempDir=$TRASHDIR/repo/.git/modules/sub/lfs/tmp$" env.log @@ -73,6 +76,7 @@ begin_test "submodule env" grep "Endpoint=$GITSERVER/$submodname.git/info/lfs$" env.log grep "LocalWorkingDir=$TRASHDIR/repo/sub$" env.log grep "LocalGitDir=$TRASHDIR/repo/.git/modules/sub$" env.log + grep "LocalGitStorageDir=$TRASHDIR/repo/.git$" env.log grep "LocalMediaDir=$TRASHDIR/repo/.git/modules/sub/lfs/objects$" env.log grep "TempDir=$TRASHDIR/repo/.git/modules/sub/lfs/tmp$" env.log )