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  }