Skip to content

Commit

Permalink
Add a --file option to install and uninstall
Browse files Browse the repository at this point in the history
There are actually two possible global configuration files,
`$HOME/.gitconfig` and `$XDG_CONFIG_HOME/git/config`.  However, the
`--global` file by default modifies only the former if it's present.
Add a `--file` option to `git lfs install` and `git lfs uninstall` so
that users can choose which of those files they'd like to use.

Update several tests to deal with our new, simpler error message so we
can avoid having to produce a huge number of different error messages.
  • Loading branch information
bk2204 committed May 2, 2023
1 parent 698e6a8 commit 84ca7e7
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 13 deletions.
26 changes: 19 additions & 7 deletions commands/command_install.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
)

var (
fileInstall = ""
forceInstall = false
localInstall = false
worktreeInstall = false
Expand Down Expand Up @@ -40,13 +41,22 @@ func cmdInstallOptions() *lfs.FilterOptions {
setupRepository()
}

switch {
case localInstall && worktreeInstall:
Exit(tr.Tr.Get("Only one of --local and --worktree options can be specified."))
case localInstall && systemInstall:
Exit(tr.Tr.Get("Only one of --local and --system options can be specified."))
case worktreeInstall && systemInstall:
Exit(tr.Tr.Get("Only one of --worktree and --system options can be specified."))
destArgs := 0
if localInstall {
destArgs++
}
if worktreeInstall {
destArgs++
}
if systemInstall {
destArgs++
}
if fileInstall != "" {
destArgs++
}

if destArgs > 1 {
Exit(tr.Tr.Get("Only one of the --local, --system, --worktree, and --file options can be specified."))
}

// This call will return -1 on Windows; don't warn about this there,
Expand All @@ -59,6 +69,7 @@ func cmdInstallOptions() *lfs.FilterOptions {
return &lfs.FilterOptions{
GitConfig: cfg.GitConfig(),
Force: forceInstall,
File: fileInstall,
Local: localInstall,
Worktree: worktreeInstall,
System: systemInstall,
Expand All @@ -85,6 +96,7 @@ func init() {
RegisterCommand("install", installCommand, func(cmd *cobra.Command) {
cmd.Flags().BoolVarP(&forceInstall, "force", "f", false, "Set the Git LFS global config, overwriting previous values.")
cmd.Flags().BoolVarP(&localInstall, "local", "l", false, "Set the Git LFS config for the local Git repository only.")
cmd.Flags().StringVarP(&fileInstall, "file", "", "", "Set the Git LFS config for the given configuration file only.")
if git.IsGitVersionAtLeast("2.20.0") {
cmd.Flags().BoolVarP(&worktreeInstall, "worktree", "w", false, "Set the Git LFS config for the current Git working tree, if multiple working trees are configured; otherwise, the same as --local.")
}
Expand Down
1 change: 1 addition & 0 deletions commands/command_uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func uninstallHooksCommand(cmd *cobra.Command, args []string) {
func init() {
RegisterCommand("uninstall", uninstallCommand, func(cmd *cobra.Command) {
cmd.Flags().BoolVarP(&localInstall, "local", "l", false, "Remove the Git LFS config for the local Git repository only.")
cmd.Flags().StringVarP(&fileInstall, "file", "", "", "Remove the Git LFS config for the given configuration file only.")
if git.IsGitVersionAtLeast("2.20.0") {
cmd.Flags().BoolVarP(&worktreeInstall, "worktree", "w", false, "Remove the Git LFS config for the current Git working tree, if multiple working trees are configured; otherwise, the same as --local.")
}
Expand Down
16 changes: 16 additions & 0 deletions git/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ func (c *Configuration) FindWorktree(key string) string {
return output
}

// FindWorktree returns the git config value for the key in the given configuration file
func (c *Configuration) FindFile(file, key string) string {
output, _ := c.gitConfig("--file", file, key)
return output
}

// SetGlobal sets the git config value for the key in the global config
func (c *Configuration) SetGlobal(key, val string) (string, error) {
return c.gitConfigWrite("--global", "--replace-all", key, val)
Expand All @@ -111,6 +117,11 @@ func (c *Configuration) SetWorktree(key, val string) (string, error) {
return c.gitConfigWrite("--worktree", "--replace-all", key, val)
}

// SetFile sets the git config value for the key in the given configuration file
func (c *Configuration) SetFile(file, key, val string) (string, error) {
return c.gitConfigWrite("--file", file, "--replace-all", key, val)
}

// UnsetGlobalSection removes the entire named section from the global config
func (c *Configuration) UnsetGlobalSection(key string) (string, error) {
return c.gitConfigWrite("--global", "--remove-section", key)
Expand All @@ -131,6 +142,11 @@ func (c *Configuration) UnsetWorktreeSection(key string) (string, error) {
return c.gitConfigWrite("--worktree", "--remove-section", key)
}

// UnsetFileSection removes the entire named section from the given configuration file
func (c *Configuration) UnsetFileSection(file, key string) (string, error) {
return c.gitConfigWrite("--file", file, "--remove-section", key)
}

// UnsetLocalKey removes the git config value for the key from the specified config file
func (c *Configuration) UnsetLocalKey(key string) (string, error) {
return c.gitConfigWrite("--unset", key)
Expand Down
7 changes: 7 additions & 0 deletions lfs/attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Attribute struct {
type FilterOptions struct {
GitConfig *git.Configuration
Force bool
File string
Local bool
Worktree bool
System bool
Expand Down Expand Up @@ -142,6 +143,8 @@ func (a *Attribute) set(gitConfig *git.Configuration, key, value string, upgrade
currentValue = gitConfig.FindWorktree(key)
} else if opt.System {
currentValue = gitConfig.FindSystem(key)
} else if opt.File != "" {
currentValue = gitConfig.FindFile(opt.File, key)
} else {
currentValue = gitConfig.FindGlobal(key)
}
Expand All @@ -154,6 +157,8 @@ func (a *Attribute) set(gitConfig *git.Configuration, key, value string, upgrade
_, err = gitConfig.SetWorktree(key, value)
} else if opt.System {
_, err = gitConfig.SetSystem(key, value)
} else if opt.File != "" {
_, err = gitConfig.SetFile(opt.File, key, value)
} else {
_, err = gitConfig.SetGlobal(key, value)
}
Expand All @@ -175,6 +180,8 @@ func (a *Attribute) Uninstall(opt *FilterOptions) error {
_, err = opt.GitConfig.UnsetWorktreeSection(a.Section)
} else if opt.System {
_, err = opt.GitConfig.UnsetSystemSection(a.Section)
} else if opt.File != "" {
_, err = opt.GitConfig.UnsetFileSection(opt.File, a.Section)
} else {
_, err = opt.GitConfig.UnsetGlobalSection(a.Section)
}
Expand Down
12 changes: 10 additions & 2 deletions t/t-install-worktree.sh
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,23 @@ begin_test "install --worktree with conflicting scope"
res=$?
set -e

[ "Only one of --local and --worktree options can be specified." = "$(cat err.log)" ]
[ "Only one of the --local, --system, --worktree, and --file options can be specified." = "$(cat err.log)" ]
[ "0" != "$res" ]

set +e
git lfs install --worktree --system 2>err.log
res=$?
set -e

[ "Only one of --worktree and --system options can be specified." = "$(cat err.log)" ]
[ "Only one of the --local, --system, --worktree, and --file options can be specified." = "$(cat err.log)" ]
[ "0" != "$res" ]

set +e
git lfs install --worktree --file test-file 2>err.log
res=$?
set -e

[ "Only one of the --local, --system, --worktree, and --file options can be specified." = "$(cat err.log)" ]
[ "0" != "$res" ]
)
end_test
28 changes: 27 additions & 1 deletion t/t-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,32 @@ begin_test "install --local"
)
end_test

begin_test "install --file"
(
set -e

# old values that should be ignored by `install --local`
git config --global filter.lfs.smudge "global smudge"
git config --global filter.lfs.clean "global clean"
git config --global filter.lfs.process "global filter"

mkdir install-file-repo
cd install-file-repo
git init
git lfs install --file=test-file

# local configs are correct
[ "git-lfs smudge -- %f" = "$(git config --file test-file filter.lfs.smudge)" ]
[ "git-lfs clean -- %f" = "$(git config --file test-file filter.lfs.clean)" ]
[ "git-lfs filter-process" = "$(git config --file test-file filter.lfs.process)" ]

# global configs
[ "global smudge" = "$(git config --global filter.lfs.smudge)" ]
[ "global clean" = "$(git config --global filter.lfs.clean)" ]
[ "global filter" = "$(git config --global filter.lfs.process)" ]
)
end_test

begin_test "install --local with failed permissions"
(
set -e
Expand Down Expand Up @@ -300,7 +326,7 @@ begin_test "install --local with conflicting scope"
res=$?
set -e

[ "Only one of --local and --system options can be specified." = "$(cat err.log)" ]
[ "Only one of the --local, --system, --worktree, and --file options can be specified." = "$(cat err.log)" ]
[ "0" != "$res" ]
)
end_test
Expand Down
12 changes: 10 additions & 2 deletions t/t-uninstall-worktree.sh
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,23 @@ begin_test "uninstall --worktree with conflicting scope"
res=$?
set -e

[ "Only one of --local and --worktree options can be specified." = "$(cat err.log)" ]
[ "Only one of the --local, --system, --worktree, and --file options can be specified." = "$(cat err.log)" ]
[ "0" != "$res" ]

set +e
git lfs uninstall --worktree --system 2>err.log
res=$?
set -e

[ "Only one of --worktree and --system options can be specified." = "$(cat err.log)" ]
[ "Only one of the --local, --system, --worktree, and --file options can be specified." = "$(cat err.log)" ]
[ "0" != "$res" ]

set +e
git lfs uninstall --worktree --file test-file 2>err.log
res=$?
set -e

[ "Only one of the --local, --system, --worktree, and --file options can be specified." = "$(cat err.log)" ]
[ "0" != "$res" ]
)
end_test
49 changes: 48 additions & 1 deletion t/t-uninstall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ begin_test "uninstall --local with conflicting scope"
res=$?
set -e

[ "Only one of --local and --system options can be specified." = "$(cat err.log)" ]
[ "Only one of the --local, --system, --worktree, and --file options can be specified." = "$(cat err.log)" ]
[ "0" != "$res" ]
)
end_test
Expand Down Expand Up @@ -263,3 +263,50 @@ begin_test "uninstall --local"
[ "" = "$(git config --local filter.lfs.process)" ]
)
end_test

begin_test "uninstall --file"
(
set -e

# old values that should be ignored by `uninstall --local`
git config --global filter.lfs.smudge "global smudge"
git config --global filter.lfs.clean "global clean"
git config --global filter.lfs.process "global filter"

reponame="$(basename "$0" ".sh")-file"
mkdir "$reponame"
cd "$reponame"
git init
git lfs install --file=test-file

# local configs are correct
[ "git-lfs smudge -- %f" = "$(git config --file test-file filter.lfs.smudge)" ]
[ "git-lfs clean -- %f" = "$(git config --file test-file filter.lfs.clean)" ]
[ "git-lfs filter-process" = "$(git config --file test-file filter.lfs.process)" ]

# global configs
[ "global smudge" = "$(git config --global filter.lfs.smudge)" ]
[ "global clean" = "$(git config --global filter.lfs.clean)" ]
[ "global filter" = "$(git config --global filter.lfs.process)" ]

git lfs uninstall --file=test-file 2>&1 | tee uninstall.log
if [ ${PIPESTATUS[0]} -ne 0 ]; then
echo >&2 "fatal: expected 'git lfs uninstall --file=test-file' to succeed"
exit 1
fi
grep -v "Global Git LFS configuration has been removed." uninstall.log

# global configs
[ "global smudge" = "$(git config filter.lfs.smudge)" ]
[ "global smudge" = "$(git config --global filter.lfs.smudge)" ]
[ "global clean" = "$(git config filter.lfs.clean)" ]
[ "global clean" = "$(git config --global filter.lfs.clean)" ]
[ "global filter" = "$(git config filter.lfs.process)" ]
[ "global filter" = "$(git config --global filter.lfs.process)" ]

# local configs are empty
[ "" = "$(git config --file test-file filter.lfs.smudge)" ]
[ "" = "$(git config --file test-file filter.lfs.clean)" ]
[ "" = "$(git config --file test-file filter.lfs.process)" ]
)
end_test

0 comments on commit 84ca7e7

Please sign in to comment.