Skip to content

Commit

Permalink
Merge pull request #837 from github/use-lfsconfig
Browse files Browse the repository at this point in the history
use .lfsconfig (with fallback to .gitconfig)
  • Loading branch information
technoweenie committed Nov 18, 2015
2 parents 16103be + 826f8e3 commit 14aeecc
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 25 deletions.
1 change: 1 addition & 0 deletions commands/command_env.go
Expand Up @@ -14,6 +14,7 @@ var (
)

func envCommand(cmd *cobra.Command, args []string) {
lfs.ShowConfigWarnings = true
config := lfs.Config
endpoint := config.Endpoint()

Expand Down
8 changes: 4 additions & 4 deletions docs/spec.md
Expand Up @@ -128,8 +128,10 @@ of rules that Git LFS uses to determine a repository's Git LFS server:
Git LFS runs two `git config` commands to build up the list of values that it
uses:

1. `git config -l -f .gitconfig` - This file is checked into the repository and
can set defaults for every user that clones the repository.
1. `git config -l -f .lfsconfig` - This file is checked into the repository and
can set defaults for every user that clones the repository. Note: Git LFS used
".gitconfig" instead of ".lfsconfig" until Git LFS v1.1. Git LFS will continue
to read ".gitconfig" if ".lfsconfig" does not exist until Git LFS v2.0.
2. `git config -l` - A user's local git configuration can override any settings
from `.gitconfig`.

Expand Down Expand Up @@ -201,5 +203,3 @@ $ cat .gitattributes
```

Use the `git lfs track` command to view and add to `.gitattributes`.


3 changes: 0 additions & 3 deletions git/git.go
Expand Up @@ -280,9 +280,6 @@ func (c *gitConfig) List() (string, error) {

// ListFromFile lists all of the git config values in the given config file
func (c *gitConfig) ListFromFile(f string) (string, error) {
if _, err := os.Stat(f); os.IsNotExist(err) {
return "", nil
}
return simpleExec("git", "config", "-l", "-f", f)
}

Expand Down
66 changes: 50 additions & 16 deletions lfs/config.go
Expand Up @@ -16,8 +16,9 @@ import (
)

var (
Config = NewConfig()
defaultRemote = "origin"
Config = NewConfig()
defaultRemote = "origin"
ShowConfigWarnings = false
)

// FetchPruneConfig collects together the config options that control fetching and pruning
Expand Down Expand Up @@ -327,28 +328,22 @@ func (c *Configuration) loadGitConfig() bool {

c.gitConfig = make(map[string]string)
c.extensions = make(map[string]Extension)
uniqRemotes := make(map[string]bool)

listOutput, err := git.Config.List()
if err != nil {
panic(fmt.Errorf("Error listing git config: %s", err))
}
configFiles := []string{
filepath.Join(LocalWorkingDir, ".lfsconfig"),

configFile := filepath.Join(LocalWorkingDir, ".gitconfig")
fileOutput, err := git.Config.ListFromFile(configFile)
if err != nil {
panic(fmt.Errorf("Error listing git config from %s: %s", configFile, err))
// TODO: remove .gitconfig support for Git LFS v2.0 https://github.com/github/git-lfs/issues/839
filepath.Join(LocalWorkingDir, ".gitconfig"),
}
c.readGitConfigFromFiles(configFiles, 0, uniqRemotes)

localConfig := filepath.Join(LocalGitDir, "config")
localOutput, err := git.Config.ListFromFile(localConfig)
listOutput, err := git.Config.List()
if err != nil {
panic(fmt.Errorf("Error listing git config from %s: %s", localConfig, err))
panic(fmt.Errorf("Error listing git config: %s", err))
}

uniqRemotes := make(map[string]bool)
c.readGitConfig(fileOutput, uniqRemotes, true)
c.readGitConfig(listOutput, uniqRemotes, false)
c.readGitConfig(localOutput, uniqRemotes, false)

c.remotes = make([]string, 0, len(uniqRemotes))
for remote, isOrigin := range uniqRemotes {
Expand All @@ -361,8 +356,39 @@ func (c *Configuration) loadGitConfig() bool {
return true
}

func (c *Configuration) readGitConfigFromFiles(filenames []string, filenameIndex int, uniqRemotes map[string]bool) {
filename := filenames[filenameIndex]
_, err := os.Stat(filename)
if err == nil {
if filenameIndex > 0 && ShowConfigWarnings {
expected := ".lfsconfig"
fmt.Fprintf(os.Stderr, "WARNING: Reading LFS config from %q, not %q. Rename to %q before Git LFS v2.0 to remove this warning.\n",
filepath.Base(filename), expected, expected)
}

fileOutput, err := git.Config.ListFromFile(filename)
if err != nil {
panic(fmt.Errorf("Error listing git config from %s: %s", filename, err))
}
c.readGitConfig(fileOutput, uniqRemotes, true)
return
}

if os.IsNotExist(err) {
newIndex := filenameIndex + 1
if len(filenames) > newIndex {
c.readGitConfigFromFiles(filenames, newIndex, uniqRemotes)
}
return
}

panic(fmt.Errorf("Error listing git config from %s: %s", filename, err))
}

func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool, onlySafe bool) {
lines := strings.Split(output, "\n")
uniqKeys := make(map[string]string)

for _, line := range lines {
pieces := strings.SplitN(line, "=", 2)
if len(pieces) < 2 {
Expand All @@ -373,6 +399,14 @@ func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool
key := strings.ToLower(pieces[0])
value := pieces[1]

if origKey, ok := uniqKeys[key]; ok && c.gitConfig[key] != value {
fmt.Fprintf(os.Stderr, "WARNING: These git config values clash:\n")
fmt.Fprintf(os.Stderr, " git config %q = %q\n", origKey, c.gitConfig[key])
fmt.Fprintf(os.Stderr, " git config %q = %q\n", pieces[0], value)
} else {
uniqKeys[key] = pieces[0]
}

keyParts := strings.Split(key, ".")
if len(keyParts) == 4 && keyParts[0] == "lfs" && keyParts[1] == "extension" {
name := keyParts[2]
Expand Down
72 changes: 70 additions & 2 deletions test/test-config.sh
Expand Up @@ -13,6 +13,74 @@ begin_test "default config"
git lfs env | tee env.log
grep "Endpoint=$GITSERVER/$reponame.git/info/lfs (auth=none)" env.log

git config --file=.gitconfig lfs.url http://gitconfig-file-ignored
git config --file=.lfsconfig lfs.url http://lfsconfig-file
git lfs env | tee env.log
grep "Endpoint=http://lfsconfig-file (auth=none)" env.log

git config lfs.url http://local-lfsconfig
git lfs env | tee env.log
grep "Endpoint=http://local-lfsconfig (auth=none)" env.log
)
end_test

begin_test "extension config"
(
set -e

git config --global lfs.extension.env-test.clean "env-test-clean"
git config --global lfs.extension.env-test.smudge "env-test-smudge"
git config --global lfs.extension.env-test.priority 0

reponame="extension-config"
mkdir $reponame
cd $reponame
git init

expected0="Extension: env-test
clean = env-test-clean
smudge = env-test-smudge
priority = 0"

[ "$expected0" = "$(git lfs ext)" ]

# any git config takes precedence over .lfsconfig
git config --global --unset lfs.extension.env-test.priority

git config --file=.lfsconfig lfs.extension.env-test.clean "file-env-test-clean"
git config --file=.lfsconfig lfs.extension.env-test.smudge "file-env-test-smudge"
git config --file=.lfsconfig lfs.extension.env-test.priority 1
cat .lfsconfig
expected1="Extension: env-test
clean = env-test-clean
smudge = env-test-smudge
priority = 1"

[ "$expected1" = "$(GIT_TRACE=5 git lfs ext)" ]

git config lfs.extension.env-test.clean "local-env-test-clean"
git config lfs.extension.env-test.smudge "local-env-test-smudge"
git config lfs.extension.env-test.priority 2
expected2="Extension: env-test
clean = local-env-test-clean
smudge = local-env-test-smudge
priority = 2"

[ "$expected2" = "$(git lfs ext)" ]
)
end_test

begin_test "default config (with gitconfig)"
(
set -e
reponame="default-config-with-gitconfig"
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=.gitconfig lfs.url http://gitconfig-file
git lfs env | tee env.log
grep "Endpoint=http://gitconfig-file (auth=none)" env.log
Expand All @@ -23,15 +91,15 @@ begin_test "default config"
)
end_test

begin_test "extension config"
begin_test "extension config (with gitconfig)"
(
set -e

git config --global lfs.extension.env-test.clean "env-test-clean"
git config --global lfs.extension.env-test.smudge "env-test-smudge"
git config --global lfs.extension.env-test.priority 0

reponame="extension-config"
reponame="extension-config-with-gitconfig"
mkdir $reponame
cd $reponame
git init
Expand Down
52 changes: 52 additions & 0 deletions test/test-env.sh
Expand Up @@ -296,6 +296,58 @@ BatchTransfer=false
)
end_test

begin_test "env with .lfsconfig"
(
set -e
reponame="env-with-lfsconfig"

git init $reponame
cd $reponame

git remote add origin "$GITSERVER/env-origin-remote"
echo '[remote "origin"]
lfsurl = http://foobar:8080/
[lfs]
batch = false
concurrenttransfers = 5
' > .lfsconfig
echo '[remote "origin"]
lfsurl = http://foobar:5050/
[lfs]
batch = true
concurrenttransfers = 50
' > .gitconfig

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=%s
LocalGitDir=%s
LocalGitStorageDir=%s
LocalMediaDir=%s
TempDir=%s
ConcurrentTransfers=3
BatchTransfer=true
%s
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$envVars" "$envInitConfig")
actual=$(git lfs env)
contains_same_elements "$expected" "$actual"

mkdir a
cd a
actual2=$(git lfs env)
contains_same_elements "$expected" "$actual2"
)
end_test

begin_test "env with .gitconfig"
(
set -e
Expand Down

0 comments on commit 14aeecc

Please sign in to comment.