github.com/psexton/git-lfs@v2.1.1-0.20170517224304-289a18b2bc53+incompatible/config/filesystem.go (about) 1 package config 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "strings" 9 10 "github.com/git-lfs/git-lfs/git" 11 "github.com/git-lfs/git-lfs/tools" 12 "github.com/rubyist/tracerx" 13 ) 14 15 var ( 16 LocalWorkingDir string 17 LocalGitDir string // parent of index / config / hooks etc 18 LocalGitStorageDir string // parent of objects/lfs (may be same as LocalGitDir but may not) 19 LocalReferenceDir string // alternative local media dir (relative to clone reference repo) 20 LocalLogDir string 21 ) 22 23 // Determins the LocalWorkingDir, LocalGitDir etc 24 func ResolveGitBasicDirs() { 25 var err error 26 LocalGitDir, LocalWorkingDir, err = git.GitAndRootDirs() 27 if err == nil { 28 // Make sure we've fully evaluated symlinks, failure to do consistently 29 // can cause discrepancies 30 LocalGitDir = tools.ResolveSymlinks(LocalGitDir) 31 LocalWorkingDir = tools.ResolveSymlinks(LocalWorkingDir) 32 33 LocalGitStorageDir = resolveGitStorageDir(LocalGitDir) 34 LocalReferenceDir = resolveReferenceDir(LocalGitStorageDir) 35 36 } else { 37 errMsg := err.Error() 38 tracerx.Printf("Error running 'git rev-parse': %s", errMsg) 39 if !strings.Contains(errMsg, "Not a git repository") { 40 fmt.Fprintf(os.Stderr, "Error: %s\n", errMsg) 41 } 42 } 43 } 44 45 func resolveReferenceDir(gitStorageDir string) string { 46 cloneReferencePath := filepath.Join(gitStorageDir, "objects", "info", "alternates") 47 if tools.FileExists(cloneReferencePath) { 48 buffer, err := ioutil.ReadFile(cloneReferencePath) 49 if err == nil { 50 path := strings.TrimSpace(string(buffer[:])) 51 referenceLfsStoragePath := filepath.Join(filepath.Dir(path), "lfs", "objects") 52 if tools.DirExists(referenceLfsStoragePath) { 53 return referenceLfsStoragePath 54 } 55 } 56 } 57 return "" 58 } 59 60 // From a git dir, get the location that objects are to be stored (we will store lfs alongside) 61 // Sometimes there is an additional level of redirect on the .git folder by way of a commondir file 62 // before you find object storage, e.g. 'git worktree' uses this. It redirects to gitdir either by GIT_DIR 63 // (during setup) or .git/git-dir: (during use), but this only contains the index etc, the objects 64 // are found in another git dir via 'commondir'. 65 func resolveGitStorageDir(gitDir string) string { 66 commondirpath := filepath.Join(gitDir, "commondir") 67 if tools.FileExists(commondirpath) && !tools.DirExists(filepath.Join(gitDir, "objects")) { 68 // no git-dir: prefix in commondir 69 storage, err := processGitRedirectFile(commondirpath, "") 70 if err == nil { 71 return storage 72 } 73 } 74 return gitDir 75 } 76 77 func processGitRedirectFile(file, prefix string) (string, error) { 78 data, err := ioutil.ReadFile(file) 79 if err != nil { 80 return "", err 81 } 82 83 contents := string(data) 84 var dir string 85 if len(prefix) > 0 { 86 if !strings.HasPrefix(contents, prefix) { 87 // Prefix required & not found 88 return "", nil 89 } 90 dir = strings.TrimSpace(contents[len(prefix):]) 91 } else { 92 dir = strings.TrimSpace(contents) 93 } 94 95 if !filepath.IsAbs(dir) { 96 // The .git file contains a relative path. 97 // Create an absolute path based on the directory the .git file is located in. 98 dir = filepath.Join(filepath.Dir(file), dir) 99 } 100 101 return dir, nil 102 }