diff --git a/config/config.go b/config/config.go index 52a8052c..fa064003 100644 --- a/config/config.go +++ b/config/config.go @@ -76,7 +76,7 @@ func NewIn(workdir, gitdir string) *Configuration { c.Git = &delayedEnvironment{ callback: func() Environment { - sources, err := gitConf.Sources(filepath.Join(c.LocalWorkingDir(), ".lfsconfig")) + sources, err := gitConf.Sources(c.LocalWorkingDir(), ".lfsconfig") if err != nil { fmt.Fprintf(os.Stderr, "Error reading git config: %s\n", err) } diff --git a/docs/man/git-lfs-config.5.ronn b/docs/man/git-lfs-config.5.ronn index 889382e6..742df999 100644 --- a/docs/man/git-lfs-config.5.ronn +++ b/docs/man/git-lfs-config.5.ronn @@ -12,6 +12,11 @@ details. This configuration file is useful for setting options such as the LFS URL or access type for all users of a repository, especially when these differ from the default. The `.lfsconfig` file uses the same format as `.gitconfig`. +If the `.lfsconfig` file is missing, the index is checked for a version of the +file, and that is used instead. If both are missing, `HEAD` is checked for the +file. If the repository is bare, only `HEAD` is checked. This order may change +for checkouts in the future to better match Git's behavior. + Settings from Git configuration files override the `.lfsconfig` file. This allows you to override settings like `lfs.url` in your local environment without having to modify the `.lfsconfig` file. diff --git a/git/config.go b/git/config.go index 262e11ad..43d33a5f 100644 --- a/git/config.go +++ b/git/config.go @@ -2,6 +2,7 @@ package git import ( "errors" + "fmt" "os" "path/filepath" "strings" @@ -134,17 +135,33 @@ func (c *Configuration) UnsetLocalKey(key string) (string, error) { return c.gitConfigWrite("--unset", key) } -func (c *Configuration) Sources(optionalFilename string) ([]*ConfigurationSource, error) { +func (c *Configuration) Sources(dir string, optionalFilename string) ([]*ConfigurationSource, error) { gitconfig, err := c.Source() if err != nil { return nil, err } - fileconfig, err := c.FileSource(optionalFilename) - if err != nil && !os.IsNotExist(err) { + bare, err := IsBare() + if err != nil { return nil, err } + // First try to read from the working directory and then the index if + // the file is missing from the working directory. + var fileconfig *ConfigurationSource + if !bare { + fileconfig, err = c.FileSource(filepath.Join(dir, optionalFilename)) + if err != nil { + if !os.IsNotExist(err) { + return nil, err + } + fileconfig, _ = c.RevisionSource(fmt.Sprintf(":%s", optionalFilename)) + } + } + if fileconfig == nil { + fileconfig, _ = c.RevisionSource(fmt.Sprintf("HEAD:%s", optionalFilename)) + } + configs := make([]*ConfigurationSource, 0, 2) if fileconfig != nil { configs = append(configs, fileconfig) @@ -165,6 +182,14 @@ func (c *Configuration) FileSource(filename string) (*ConfigurationSource, error return ParseConfigLines(out, true), nil } +func (c *Configuration) RevisionSource(revision string) (*ConfigurationSource, error) { + out, err := c.gitConfig("-l", "--blob", revision) + if err != nil { + return nil, err + } + return ParseConfigLines(out, true), nil +} + func (c *Configuration) Source() (*ConfigurationSource, error) { out, err := c.gitConfig("-l") if err != nil { diff --git a/t/t-config.sh b/t/t-config.sh index e78b02f0..ec92fa7a 100755 --- a/t/t-config.sh +++ b/t/t-config.sh @@ -42,6 +42,80 @@ begin_test "default config" ) end_test +begin_test "config reads from repository" +( + set -e + reponame="repository-config" + setup_remote_repo "$reponame" + mkdir $reponame + cd $reponame + git init + git remote add origin "$GITSERVER/$reponame" + git lfs env | tee env.log + grep "Endpoint=$GITSERVER/$reponame.git/info/lfs (auth=none)" env.log + + git config --file=.lfsconfig lfs.url http://lfsconfig-file + git config --file=.lfsconfig lfs.http://lfsconfig-file.access lfsconfig + git add .lfsconfig + git commit -m 'Add file' + git push origin HEAD + + git checkout -b side + git config --file=.lfsconfig lfs.url http://lfsconfig-file-side + git config --file=.lfsconfig lfs.http://lfsconfig-file-side.access lfsconfig + git add .lfsconfig + git commit -m 'Add file for side' + git push origin HEAD + + mkdir "../$reponame-2" + cd "../$reponame-2" + git init + git remote add origin "$GITSERVER/$reponame" + + git lfs env | tee env.log + grep "Endpoint=$GITSERVER/$reponame.git/info/lfs (auth=none)" env.log + + git fetch origin + git symbolic-ref HEAD refs/remotes/origin/side + git show "HEAD:.lfsconfig" + git lfs env | tee env.log + grep "Endpoint=http://lfsconfig-file-side (auth=lfsconfig)" env.log + + git read-tree refs/remotes/origin/main + git lfs env | tee env.log + grep "Endpoint=http://lfsconfig-file (auth=lfsconfig)" env.log +) +end_test + +begin_test "can read LFS file with name before .lfsconfig" +( + set -e + reponame="early-file-config" + setup_remote_repo "$reponame" + mkdir $reponame + cd $reponame + git init + git remote add origin "$GITSERVER/$reponame" + + git lfs track "*.bin" + git config --file=.lfsconfig lfs.url "$GITSERVER/$reponame.git/info/lfs" + + echo "abc" > .bin + echo "def" > a.bin + + git add . + git commit -m "Add files" + git push origin HEAD + rm -fr .git/lfs/objects + + cd .. + git clone "$reponame" "$reponame-2" + cd "$reponame-2" + grep abc .bin + grep def a.bin +) +end_test + begin_test "extension config" ( set -e