mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-04-25 12:24:47 +02:00
Per-repo config files (and reloading of edited config files) (#3787)
- **PR Description** Support per-repo user config files. For now we only support `.git/lazygit.yml`; in the future we would also like to support `./.lazygit.yml`, but that one will need a trust prompt as it could be versioned, which adds quite a bit of complexity, so we leave that for later. We do, however, support config files in parent directories (all the way up to the root directory). This makes it possible to add a config file that applies to multiple repos at once. Useful if you want to set different options for all your work repos vs. all your open-source repos, for instance. In addition, we support re-loading edited config files. This makes it much easier to experiment with config settings, especially the ones that affect the layout or color scheme, because you see the effect immediately without having to restart lazygit.
This commit is contained in:
commit
aa55995924
1
.github/pull_request_template.md
vendored
1
.github/pull_request_template.md
vendored
@ -6,6 +6,7 @@
|
||||
* [ ] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting))
|
||||
* [ ] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide)
|
||||
* [ ] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation))
|
||||
* [ ] If a new UserConfig entry was added, make sure it can be hot-reloaded (see [here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig))
|
||||
* [ ] Docs have been updated if necessary
|
||||
* [ ] You've read through your own file changes for silly mistakes etc
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# User Config
|
||||
|
||||
Default path for the config file:
|
||||
Default path for the global config file:
|
||||
|
||||
- Linux: `~/.config/lazygit/config.yml`
|
||||
- MacOS: `~/Library/Application\ Support/lazygit/config.yml`
|
||||
@ -16,6 +16,8 @@ If you want to change the config directory:
|
||||
|
||||
- MacOS: `export XDG_CONFIG_HOME="$HOME/.config"`
|
||||
|
||||
In addition to the global config file you can create repo-specific config files in `<repo>/.git/lazygit.yml`. Settings in these files override settings in the global config file. In addition, files called `.lazygit.yml` in any of the parent directories of a repo will also be loaded; this can be useful if you have settings that you want to apply to a group of repositories.
|
||||
|
||||
JSON schema is available for `config.yml` so that IntelliSense in Visual Studio Code (completion and error checking) is automatically enabled when the [YAML Red Hat][yaml] extension is installed. However, note that automatic schema detection only works if your config file is in one of the standard paths mentioned above. If you override the path to the file, you can still make IntelliSense work by adding
|
||||
|
||||
```yaml
|
||||
|
@ -12,7 +12,7 @@
|
||||
* `pkg/commands/models`: Contains model structs that represent commits, branches, files, etc.
|
||||
* `pkg/commands/patch`: Contains code for parsing and working with git patches
|
||||
* `pkg/common`: Contains the `Common` struct which holds common dependencies like the logger, i18n, and the user config. Most structs in the code will have a field named `c` which holds a common struct (or a derivative of the common struct).
|
||||
* `pkg/config`: Contains code relating to the Lazygit user config. Specifically `pkg/config/user_config/go` defines the user config struct and its default values.
|
||||
* `pkg/config`: Contains code relating to the Lazygit user config. Specifically `pkg/config/user_config/go` defines the user config struct and its default values. See [below](#using-userconfig) for some important information about using it.
|
||||
* `pkg/constants`: Contains some constant strings (e.g. links to docs)
|
||||
* `pkg/env`: Contains code relating to setting/getting environment variables
|
||||
* `pkg/i18n`: Contains internationalised strings
|
||||
@ -86,6 +86,12 @@ The event loop is managed in the `MainLoop` function of `vendor/github.com/jesse
|
||||
|
||||
Often, as part of handling a keypress, we'll want to run some code asynchronously so that it doesn't block the UI thread. For this we'll typically run `self.c.OnWorker(myFunc)`. If the worker wants to then do something on the UI thread again it can call `self.c.OnUIThread(myOtherFunc)`.
|
||||
|
||||
## Using UserConfig
|
||||
|
||||
The UserConfig struct is loaded from lazygit's global config file (and possibly repo-specific config files). It can be re-loaded while lazygit is running, e.g. when the user edits one of the config files. In this case we should make sure that any new or changed config values take effect immediately. The easiest way to achieve this is what we do in most controllers or helpers: these have a pointer to the `common.Common` struct, which contains the UserConfig, and access it from there. Since the UserConfig instance in `common.Common` is updated whenever we reload the config, the code can be sure that it always uses an up-to-date value, and there's nothing else to do.
|
||||
|
||||
If that's not possible for some reason, see if you can add code to `Gui.onUserConfigLoaded` to update things from the new config; there are some examples in that function to use as a guide. If that's too hard to do too, add the config to the list in `Gui.checkForChangedConfigsThatDontAutoReload` so that the user is asked to quit and restart lazygit.
|
||||
|
||||
## Legacy code structure
|
||||
|
||||
Before we had controllers and contexts, all the code lived directly in the gui package under a gui God Struct. This was fairly bloated and so we split things out to have a better separation of concerns. Nonetheless, it's a big effort to migrate all the code so we still have some logic in the gui struct that ought to live somewhere else. Likewise, we have some keybindings defined in `pkg/gui/keybindings.go` that ought to live on a controller (all keybindings used to be defined in that one file).
|
||||
|
2
go.mod
2
go.mod
@ -16,7 +16,7 @@ require (
|
||||
github.com/integrii/flaggy v1.4.0
|
||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240817084901-ea75eca94702
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240818082312-49cc572a9ffa
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
|
||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
|
||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
|
||||
|
4
go.sum
4
go.sum
@ -188,8 +188,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
|
||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240817084901-ea75eca94702 h1:9fkowh/FchykVmSXXcNS3XsJ2HWW3MeTlPwQmG1liJM=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240817084901-ea75eca94702/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240818082312-49cc572a9ffa h1:XZX6Rf60E3IuF1K+fvxjIr29f4p9kNY83mveGoJ5Uuo=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240818082312-49cc572a9ffa/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
|
||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
|
||||
|
@ -63,22 +63,20 @@ func Run(
|
||||
func NewCommon(config config.AppConfigurer) (*common.Common, error) {
|
||||
userConfig := config.GetUserConfig()
|
||||
appState := config.GetAppState()
|
||||
|
||||
var err error
|
||||
log := newLogger(config)
|
||||
tr, err := i18n.NewTranslationSetFromConfig(log, userConfig.Gui.Language)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Initialize with English for the time being; the real translation set for
|
||||
// the configured language will be read after reading the user config
|
||||
tr := i18n.EnglishTranslationSet()
|
||||
|
||||
return &common.Common{
|
||||
Log: log,
|
||||
Tr: tr,
|
||||
UserConfig: userConfig,
|
||||
AppState: appState,
|
||||
Debug: config.GetDebug(),
|
||||
Fs: afero.NewOsFs(),
|
||||
}, nil
|
||||
cmn := &common.Common{
|
||||
Log: log,
|
||||
Tr: tr,
|
||||
AppState: appState,
|
||||
Debug: config.GetDebug(),
|
||||
Fs: afero.NewOsFs(),
|
||||
}
|
||||
cmn.SetUserConfig(userConfig)
|
||||
return cmn, nil
|
||||
}
|
||||
|
||||
func newLogger(cfg config.AppConfigurer) *logrus.Entry {
|
||||
@ -195,7 +193,7 @@ func (app *App) setupRepo(
|
||||
|
||||
var shouldInitRepo bool
|
||||
initialBranchArg := ""
|
||||
switch app.UserConfig.NotARepository {
|
||||
switch app.UserConfig().NotARepository {
|
||||
case "prompt":
|
||||
// Offer to initialize a new repository in current directory.
|
||||
fmt.Print(app.Tr.CreateRepo)
|
||||
|
@ -136,6 +136,12 @@ func Start(buildInfo *BuildInfo, integrationTest integrationTypes.IntegrationTes
|
||||
|
||||
if integrationTest != nil {
|
||||
integrationTest.SetupConfig(appConfig)
|
||||
|
||||
// Preserve the changes that the test setup just made to the config, so
|
||||
// they don't get lost when we reload the config while running the test
|
||||
// (which happens when switching between repos, going in and out of
|
||||
// submodules, etc).
|
||||
appConfig.SaveGlobalUserConfig()
|
||||
}
|
||||
|
||||
common, err := NewCommon(appConfig)
|
||||
|
@ -63,6 +63,11 @@ func generateAtDir(cheatsheetDir string) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
tr, err := i18n.NewTranslationSetFromConfig(common.Log, lang)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
common.Tr = tr
|
||||
mApp, _ := app.NewApp(mConfig, nil, common)
|
||||
path := cheatsheetDir + "/Keybindings_" + lang + ".md"
|
||||
file, err := os.Create(path)
|
||||
|
@ -145,7 +145,7 @@ func (self *BranchCommands) GetGraph(branchName string) (string, error) {
|
||||
}
|
||||
|
||||
func (self *BranchCommands) GetGraphCmdObj(branchName string) oscommands.ICmdObj {
|
||||
branchLogCmdTemplate := self.UserConfig.Git.BranchLogCmd
|
||||
branchLogCmdTemplate := self.UserConfig().Git.BranchLogCmd
|
||||
templateValues := map[string]string{
|
||||
"branchName": self.cmd.Quote(branchName),
|
||||
}
|
||||
@ -236,7 +236,7 @@ func (self *BranchCommands) Merge(branchName string, opts MergeOpts) error {
|
||||
}
|
||||
cmdArgs := NewGitCmd("merge").
|
||||
Arg("--no-edit").
|
||||
Arg(strings.Fields(self.UserConfig.Git.Merging.Args)...).
|
||||
Arg(strings.Fields(self.UserConfig().Git.Merging.Args)...).
|
||||
ArgIf(opts.FastForwardOnly, "--ff-only").
|
||||
ArgIf(opts.Squash, "--squash", "--ff").
|
||||
Arg(branchName).
|
||||
@ -248,9 +248,9 @@ func (self *BranchCommands) Merge(branchName string, opts MergeOpts) error {
|
||||
func (self *BranchCommands) AllBranchesLogCmdObj() oscommands.ICmdObj {
|
||||
// Only choose between non-empty, non-identical commands
|
||||
candidates := lo.Uniq(lo.WithoutEmpty(append([]string{
|
||||
self.UserConfig.Git.AllBranchesLogCmd,
|
||||
self.UserConfig().Git.AllBranchesLogCmd,
|
||||
},
|
||||
self.UserConfig.Git.AllBranchesLogCmds...,
|
||||
self.UserConfig().Git.AllBranchesLogCmds...,
|
||||
)))
|
||||
|
||||
n := len(candidates)
|
||||
|
@ -140,7 +140,7 @@ func (self *BranchLoader) Load(reflogCommits []*models.Commit,
|
||||
}
|
||||
}
|
||||
|
||||
if loadBehindCounts && self.UserConfig.Gui.ShowDivergenceFromBaseBranch != "none" {
|
||||
if loadBehindCounts && self.UserConfig().Gui.ShowDivergenceFromBaseBranch != "none" {
|
||||
onWorker(func() error {
|
||||
return self.GetBehindBaseBranchValuesForAllBranches(branches, mainBranches, renderFunc)
|
||||
})
|
||||
|
@ -88,7 +88,7 @@ func (self *CommitCommands) ResetToCommit(hash string, strength string, envVars
|
||||
func (self *CommitCommands) CommitCmdObj(summary string, description string) oscommands.ICmdObj {
|
||||
messageArgs := self.commitMessageArgs(summary, description)
|
||||
|
||||
skipHookPrefix := self.UserConfig.Git.SkipHookPrefix
|
||||
skipHookPrefix := self.UserConfig().Git.SkipHookPrefix
|
||||
|
||||
cmdArgs := NewGitCmd("commit").
|
||||
ArgIf(skipHookPrefix != "" && strings.HasPrefix(summary, skipHookPrefix), "--no-verify").
|
||||
@ -148,7 +148,7 @@ func (self *CommitCommands) CommitEditorCmdObj() oscommands.ICmdObj {
|
||||
}
|
||||
|
||||
func (self *CommitCommands) signoffFlag() string {
|
||||
if self.UserConfig.Git.Commit.SignOff {
|
||||
if self.UserConfig().Git.Commit.SignOff {
|
||||
return "--signoff"
|
||||
} else {
|
||||
return ""
|
||||
@ -258,13 +258,13 @@ func (self *CommitCommands) AmendHeadCmdObj() oscommands.ICmdObj {
|
||||
func (self *CommitCommands) ShowCmdObj(hash string, filterPath string) oscommands.ICmdObj {
|
||||
contextSize := self.AppState.DiffContextSize
|
||||
|
||||
extDiffCmd := self.UserConfig.Git.Paging.ExternalDiffCommand
|
||||
extDiffCmd := self.UserConfig().Git.Paging.ExternalDiffCommand
|
||||
cmdArgs := NewGitCmd("show").
|
||||
Config("diff.noprefix=false").
|
||||
ConfigIf(extDiffCmd != "", "diff.external="+extDiffCmd).
|
||||
ArgIfElse(extDiffCmd != "", "--ext-diff", "--no-ext-diff").
|
||||
Arg("--submodule").
|
||||
Arg("--color="+self.UserConfig.Git.Paging.ColorArg).
|
||||
Arg("--color="+self.UserConfig().Git.Paging.ColorArg).
|
||||
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
||||
Arg("--stat").
|
||||
Arg("--decorate").
|
||||
|
@ -322,9 +322,9 @@ func TestGetCommits(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
common.UserConfig.Git.MainBranches = scenario.mainBranches
|
||||
common.UserConfig().Git.MainBranches = scenario.mainBranches
|
||||
opts := scenario.opts
|
||||
opts.MainBranches = NewMainBranches(scenario.mainBranches, cmd)
|
||||
opts.MainBranches = NewMainBranches(common, cmd)
|
||||
commits, err := builder.GetCommits(opts)
|
||||
|
||||
assert.Equal(t, scenario.expectedCommits, commits)
|
||||
|
@ -43,7 +43,7 @@ func (self *ConfigCommands) ConfiguredPager() string {
|
||||
}
|
||||
|
||||
func (self *ConfigCommands) GetPager(width int) string {
|
||||
useConfig := self.UserConfig.Git.Paging.UseConfig
|
||||
useConfig := self.UserConfig().Git.Paging.UseConfig
|
||||
if useConfig {
|
||||
pager := self.ConfiguredPager()
|
||||
return strings.Split(pager, "| less")[0]
|
||||
@ -53,14 +53,14 @@ func (self *ConfigCommands) GetPager(width int) string {
|
||||
"columnWidth": strconv.Itoa(width/2 - 6),
|
||||
}
|
||||
|
||||
pagerTemplate := string(self.UserConfig.Git.Paging.Pager)
|
||||
pagerTemplate := string(self.UserConfig().Git.Paging.Pager)
|
||||
return utils.ResolvePlaceholderString(pagerTemplate, templateValues)
|
||||
}
|
||||
|
||||
// UsingGpg tells us whether the user has gpg enabled so that we can know
|
||||
// whether we need to run a subprocess to allow them to enter their password
|
||||
func (self *ConfigCommands) UsingGpg() bool {
|
||||
overrideGpg := self.UserConfig.Git.OverrideGpg
|
||||
overrideGpg := self.UserConfig().Git.OverrideGpg
|
||||
if overrideGpg {
|
||||
return false
|
||||
}
|
||||
|
@ -58,9 +58,9 @@ func buildGitCommon(deps commonDeps) *GitCommon {
|
||||
}
|
||||
gitCommon.cmd = cmd
|
||||
|
||||
gitCommon.Common.UserConfig = deps.userConfig
|
||||
if gitCommon.Common.UserConfig == nil {
|
||||
gitCommon.Common.UserConfig = config.GetDefaultConfig()
|
||||
gitCommon.Common.SetUserConfig(deps.userConfig)
|
||||
if gitCommon.Common.UserConfig() == nil {
|
||||
gitCommon.Common.SetUserConfig(config.GetDefaultConfig())
|
||||
}
|
||||
|
||||
gitCommon.version = deps.gitVersion
|
||||
|
@ -17,7 +17,7 @@ func NewDiffCommands(gitCommon *GitCommon) *DiffCommands {
|
||||
}
|
||||
|
||||
func (self *DiffCommands) DiffCmdObj(diffArgs []string) oscommands.ICmdObj {
|
||||
extDiffCmd := self.UserConfig.Git.Paging.ExternalDiffCommand
|
||||
extDiffCmd := self.UserConfig().Git.Paging.ExternalDiffCommand
|
||||
useExtDiff := extDiffCmd != ""
|
||||
|
||||
return self.cmd.New(
|
||||
@ -26,7 +26,7 @@ func (self *DiffCommands) DiffCmdObj(diffArgs []string) oscommands.ICmdObj {
|
||||
ConfigIf(useExtDiff, "diff.external="+extDiffCmd).
|
||||
ArgIfElse(useExtDiff, "--ext-diff", "--no-ext-diff").
|
||||
Arg("--submodule").
|
||||
Arg(fmt.Sprintf("--color=%s", self.UserConfig.Git.Paging.ColorArg)).
|
||||
Arg(fmt.Sprintf("--color=%s", self.UserConfig().Git.Paging.ColorArg)).
|
||||
Arg(diffArgs...).
|
||||
Dir(self.repoPaths.worktreePath).
|
||||
ToArgv(),
|
||||
|
@ -31,7 +31,7 @@ func (self *FileCommands) Cat(fileName string) (string, error) {
|
||||
}
|
||||
|
||||
func (self *FileCommands) GetEditCmdStrLegacy(filename string, lineNumber int) (string, error) {
|
||||
editor := self.UserConfig.OS.EditCommand
|
||||
editor := self.UserConfig().OS.EditCommand
|
||||
|
||||
if editor == "" {
|
||||
editor = self.config.GetCoreEditor()
|
||||
@ -60,7 +60,7 @@ func (self *FileCommands) GetEditCmdStrLegacy(filename string, lineNumber int) (
|
||||
"line": strconv.Itoa(lineNumber),
|
||||
}
|
||||
|
||||
editCmdTemplate := self.UserConfig.OS.EditCommandTemplate
|
||||
editCmdTemplate := self.UserConfig().OS.EditCommandTemplate
|
||||
if len(editCmdTemplate) == 0 {
|
||||
switch editor {
|
||||
case "emacs", "nano", "vi", "vim", "nvim":
|
||||
@ -78,7 +78,7 @@ func (self *FileCommands) GetEditCmdStrLegacy(filename string, lineNumber int) (
|
||||
|
||||
func (self *FileCommands) GetEditCmdStr(filenames []string) (string, bool) {
|
||||
// Legacy support for old config; to be removed at some point
|
||||
if self.UserConfig.OS.Edit == "" && self.UserConfig.OS.EditCommandTemplate != "" {
|
||||
if self.UserConfig().OS.Edit == "" && self.UserConfig().OS.EditCommandTemplate != "" {
|
||||
// If multiple files are selected, we'll simply edit just the first one.
|
||||
// It's not worth fixing this for the legacy support.
|
||||
if cmdStr, err := self.GetEditCmdStrLegacy(filenames[0], 1); err == nil {
|
||||
@ -86,7 +86,7 @@ func (self *FileCommands) GetEditCmdStr(filenames []string) (string, bool) {
|
||||
}
|
||||
}
|
||||
|
||||
template, suspend := config.GetEditTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
|
||||
template, suspend := config.GetEditTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
|
||||
quotedFilenames := lo.Map(filenames, func(filename string, _ int) string { return self.cmd.Quote(filename) })
|
||||
|
||||
templateValues := map[string]string{
|
||||
@ -99,13 +99,13 @@ func (self *FileCommands) GetEditCmdStr(filenames []string) (string, bool) {
|
||||
|
||||
func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (string, bool) {
|
||||
// Legacy support for old config; to be removed at some point
|
||||
if self.UserConfig.OS.EditAtLine == "" && self.UserConfig.OS.EditCommandTemplate != "" {
|
||||
if self.UserConfig().OS.EditAtLine == "" && self.UserConfig().OS.EditCommandTemplate != "" {
|
||||
if cmdStr, err := self.GetEditCmdStrLegacy(filename, lineNumber); err == nil {
|
||||
return cmdStr, true
|
||||
}
|
||||
}
|
||||
|
||||
template, suspend := config.GetEditAtLineTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
|
||||
template, suspend := config.GetEditAtLineTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
|
||||
|
||||
templateValues := map[string]string{
|
||||
"filename": self.cmd.Quote(filename),
|
||||
@ -118,13 +118,13 @@ func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (
|
||||
|
||||
func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber int) string {
|
||||
// Legacy support for old config; to be removed at some point
|
||||
if self.UserConfig.OS.EditAtLineAndWait == "" && self.UserConfig.OS.EditCommandTemplate != "" {
|
||||
if self.UserConfig().OS.EditAtLineAndWait == "" && self.UserConfig().OS.EditCommandTemplate != "" {
|
||||
if cmdStr, err := self.GetEditCmdStrLegacy(filename, lineNumber); err == nil {
|
||||
return cmdStr
|
||||
}
|
||||
}
|
||||
|
||||
template := config.GetEditAtLineAndWaitTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
|
||||
template := config.GetEditAtLineAndWaitTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
|
||||
|
||||
templateValues := map[string]string{
|
||||
"filename": self.cmd.Quote(filename),
|
||||
@ -136,7 +136,7 @@ func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber
|
||||
}
|
||||
|
||||
func (self *FileCommands) GetOpenDirInEditorCmdStr(path string) (string, bool) {
|
||||
template, suspend := config.GetOpenDirInEditorTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
|
||||
template, suspend := config.GetOpenDirInEditorTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
|
||||
|
||||
templateValues := map[string]string{
|
||||
"dir": self.cmd.Quote(path),
|
||||
|
@ -5,32 +5,34 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/sasha-s/go-deadlock"
|
||||
)
|
||||
|
||||
type MainBranches struct {
|
||||
// List of main branches configured by the user. Just the bare names.
|
||||
configuredMainBranches []string
|
||||
// Which of these actually exist in the repository. Full ref names, and it
|
||||
// could be either "refs/heads/..." or "refs/remotes/origin/..." depending
|
||||
// on which one exists for a given bare name.
|
||||
c *common.Common
|
||||
// Which of the configured main branches actually exist in the repository. Full
|
||||
// ref names, and it could be either "refs/heads/..." or "refs/remotes/origin/..."
|
||||
// depending on which one exists for a given bare name.
|
||||
existingMainBranches []string
|
||||
|
||||
previousMainBranches []string
|
||||
|
||||
cmd oscommands.ICmdObjBuilder
|
||||
mutex *deadlock.Mutex
|
||||
}
|
||||
|
||||
func NewMainBranches(
|
||||
configuredMainBranches []string,
|
||||
cmn *common.Common,
|
||||
cmd oscommands.ICmdObjBuilder,
|
||||
) *MainBranches {
|
||||
return &MainBranches{
|
||||
configuredMainBranches: configuredMainBranches,
|
||||
existingMainBranches: nil,
|
||||
cmd: cmd,
|
||||
mutex: &deadlock.Mutex{},
|
||||
c: cmn,
|
||||
existingMainBranches: nil,
|
||||
cmd: cmd,
|
||||
mutex: &deadlock.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,8 +42,11 @@ func (self *MainBranches) Get() []string {
|
||||
self.mutex.Lock()
|
||||
defer self.mutex.Unlock()
|
||||
|
||||
if self.existingMainBranches == nil {
|
||||
self.existingMainBranches = self.determineMainBranches()
|
||||
configuredMainBranches := self.c.UserConfig().Git.MainBranches
|
||||
|
||||
if self.existingMainBranches == nil || !utils.EqualSlices(self.previousMainBranches, configuredMainBranches) {
|
||||
self.existingMainBranches = self.determineMainBranches(configuredMainBranches)
|
||||
self.previousMainBranches = configuredMainBranches
|
||||
}
|
||||
|
||||
return self.existingMainBranches
|
||||
@ -71,13 +76,13 @@ func (self *MainBranches) GetMergeBase(refName string) string {
|
||||
return ignoringWarnings(output)
|
||||
}
|
||||
|
||||
func (self *MainBranches) determineMainBranches() []string {
|
||||
func (self *MainBranches) determineMainBranches(configuredMainBranches []string) []string {
|
||||
var existingBranches []string
|
||||
var wg sync.WaitGroup
|
||||
|
||||
existingBranches = make([]string, len(self.configuredMainBranches))
|
||||
existingBranches = make([]string, len(configuredMainBranches))
|
||||
|
||||
for i, branchName := range self.configuredMainBranches {
|
||||
for i, branchName := range configuredMainBranches {
|
||||
wg.Add(1)
|
||||
go utils.Safe(func() {
|
||||
defer wg.Done()
|
||||
|
@ -3,7 +3,6 @@ package git_commands
|
||||
import (
|
||||
ioFs "io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@ -64,9 +63,9 @@ func (self *RepoPaths) IsBareRepo() bool {
|
||||
func MockRepoPaths(currentPath string) *RepoPaths {
|
||||
return &RepoPaths{
|
||||
worktreePath: currentPath,
|
||||
worktreeGitDirPath: path.Join(currentPath, ".git"),
|
||||
worktreeGitDirPath: filepath.Join(currentPath, ".git"),
|
||||
repoPath: currentPath,
|
||||
repoGitDirPath: path.Join(currentPath, ".git"),
|
||||
repoGitDirPath: filepath.Join(currentPath, ".git"),
|
||||
repoName: "lazygit",
|
||||
isBareRepo: false,
|
||||
}
|
||||
@ -116,9 +115,9 @@ func GetRepoPathsForDir(
|
||||
if isSubmodule {
|
||||
repoPath = worktreePath
|
||||
} else {
|
||||
repoPath = path.Dir(repoGitDirPath)
|
||||
repoPath = filepath.Dir(repoGitDirPath)
|
||||
}
|
||||
repoName := path.Base(repoPath)
|
||||
repoName := filepath.Base(repoPath)
|
||||
|
||||
return &RepoPaths{
|
||||
worktreePath: worktreePath,
|
||||
@ -154,7 +153,7 @@ func linkedWortkreePaths(fs afero.Fs, repoGitDirPath string) []string {
|
||||
result := []string{}
|
||||
// For each directory in this path we're going to cat the `gitdir` file and append its contents to our result
|
||||
// That file points us to the `.git` file in the worktree.
|
||||
worktreeGitDirsPath := path.Join(repoGitDirPath, "worktrees")
|
||||
worktreeGitDirsPath := filepath.Join(repoGitDirPath, "worktrees")
|
||||
|
||||
// ensure the directory exists
|
||||
_, err := fs.Stat(worktreeGitDirsPath)
|
||||
@ -171,7 +170,7 @@ func linkedWortkreePaths(fs afero.Fs, repoGitDirPath string) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
gitDirPath := path.Join(currPath, "gitdir")
|
||||
gitDirPath := filepath.Join(currPath, "gitdir")
|
||||
gitDirBytes, err := afero.ReadFile(fs, gitDirPath)
|
||||
if err != nil {
|
||||
// ignoring error
|
||||
@ -179,7 +178,7 @@ func linkedWortkreePaths(fs afero.Fs, repoGitDirPath string) []string {
|
||||
}
|
||||
trimmedGitDir := strings.TrimSpace(string(gitDirBytes))
|
||||
// removing the .git part
|
||||
worktreeDir := path.Dir(trimmedGitDir)
|
||||
worktreeDir := filepath.Dir(trimmedGitDir)
|
||||
result = append(result, worktreeDir)
|
||||
return nil
|
||||
})
|
||||
|
@ -2,11 +2,13 @@ package git_commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -29,7 +31,17 @@ func TestGetRepoPaths(t *testing.T) {
|
||||
Name: "typical case",
|
||||
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
|
||||
// setup for main worktree
|
||||
expectedOutput := []string{
|
||||
mockOutput := lo.Ternary(runtime.GOOS == "windows", []string{
|
||||
// --show-toplevel
|
||||
`C:\path\to\repo`,
|
||||
// --git-dir
|
||||
`C:\path\to\repo\.git`,
|
||||
// --git-common-dir
|
||||
`C:\path\to\repo\.git`,
|
||||
// --is-bare-repository
|
||||
"false",
|
||||
// --show-superproject-working-tree
|
||||
}, []string{
|
||||
// --show-toplevel
|
||||
"/path/to/repo",
|
||||
// --git-dir
|
||||
@ -39,28 +51,45 @@ func TestGetRepoPaths(t *testing.T) {
|
||||
// --is-bare-repository
|
||||
"false",
|
||||
// --show-superproject-working-tree
|
||||
}
|
||||
})
|
||||
runner.ExpectGitArgs(
|
||||
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--is-bare-repository", "--show-superproject-working-tree"),
|
||||
strings.Join(expectedOutput, "\n"),
|
||||
strings.Join(mockOutput, "\n"),
|
||||
nil)
|
||||
},
|
||||
Path: "/path/to/repo",
|
||||
Expected: &RepoPaths{
|
||||
Expected: lo.Ternary(runtime.GOOS == "windows", &RepoPaths{
|
||||
worktreePath: `C:\path\to\repo`,
|
||||
worktreeGitDirPath: `C:\path\to\repo\.git`,
|
||||
repoPath: `C:\path\to\repo`,
|
||||
repoGitDirPath: `C:\path\to\repo\.git`,
|
||||
repoName: `repo`,
|
||||
isBareRepo: false,
|
||||
}, &RepoPaths{
|
||||
worktreePath: "/path/to/repo",
|
||||
worktreeGitDirPath: "/path/to/repo/.git",
|
||||
repoPath: "/path/to/repo",
|
||||
repoGitDirPath: "/path/to/repo/.git",
|
||||
repoName: "repo",
|
||||
isBareRepo: false,
|
||||
},
|
||||
}),
|
||||
Err: nil,
|
||||
},
|
||||
{
|
||||
Name: "bare repo",
|
||||
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
|
||||
// setup for main worktree
|
||||
expectedOutput := []string{
|
||||
mockOutput := lo.Ternary(runtime.GOOS == "windows", []string{
|
||||
// --show-toplevel
|
||||
`C:\path\to\repo`,
|
||||
// --git-dir
|
||||
`C:\path\to\bare_repo\bare.git`,
|
||||
// --git-common-dir
|
||||
`C:\path\to\bare_repo\bare.git`,
|
||||
// --is-bare-repository
|
||||
`true`,
|
||||
// --show-superproject-working-tree
|
||||
}, []string{
|
||||
// --show-toplevel
|
||||
"/path/to/repo",
|
||||
// --git-dir
|
||||
@ -70,27 +99,45 @@ func TestGetRepoPaths(t *testing.T) {
|
||||
// --is-bare-repository
|
||||
"true",
|
||||
// --show-superproject-working-tree
|
||||
}
|
||||
})
|
||||
runner.ExpectGitArgs(
|
||||
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--is-bare-repository", "--show-superproject-working-tree"),
|
||||
strings.Join(expectedOutput, "\n"),
|
||||
strings.Join(mockOutput, "\n"),
|
||||
nil)
|
||||
},
|
||||
Path: "/path/to/repo",
|
||||
Expected: &RepoPaths{
|
||||
Expected: lo.Ternary(runtime.GOOS == "windows", &RepoPaths{
|
||||
worktreePath: `C:\path\to\repo`,
|
||||
worktreeGitDirPath: `C:\path\to\bare_repo\bare.git`,
|
||||
repoPath: `C:\path\to\bare_repo`,
|
||||
repoGitDirPath: `C:\path\to\bare_repo\bare.git`,
|
||||
repoName: `bare_repo`,
|
||||
isBareRepo: true,
|
||||
}, &RepoPaths{
|
||||
worktreePath: "/path/to/repo",
|
||||
worktreeGitDirPath: "/path/to/bare_repo/bare.git",
|
||||
repoPath: "/path/to/bare_repo",
|
||||
repoGitDirPath: "/path/to/bare_repo/bare.git",
|
||||
repoName: "bare_repo",
|
||||
isBareRepo: true,
|
||||
},
|
||||
}),
|
||||
Err: nil,
|
||||
},
|
||||
{
|
||||
Name: "submodule",
|
||||
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
|
||||
expectedOutput := []string{
|
||||
mockOutput := lo.Ternary(runtime.GOOS == "windows", []string{
|
||||
// --show-toplevel
|
||||
`C:\path\to\repo\submodule1`,
|
||||
// --git-dir
|
||||
`C:\path\to\repo\.git\modules\submodule1`,
|
||||
// --git-common-dir
|
||||
`C:\path\to\repo\.git\modules\submodule1`,
|
||||
// --is-bare-repository
|
||||
`false`,
|
||||
// --show-superproject-working-tree
|
||||
`C:\path\to\repo`,
|
||||
}, []string{
|
||||
// --show-toplevel
|
||||
"/path/to/repo/submodule1",
|
||||
// --git-dir
|
||||
@ -101,21 +148,28 @@ func TestGetRepoPaths(t *testing.T) {
|
||||
"false",
|
||||
// --show-superproject-working-tree
|
||||
"/path/to/repo",
|
||||
}
|
||||
})
|
||||
runner.ExpectGitArgs(
|
||||
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--is-bare-repository", "--show-superproject-working-tree"),
|
||||
strings.Join(expectedOutput, "\n"),
|
||||
strings.Join(mockOutput, "\n"),
|
||||
nil)
|
||||
},
|
||||
Path: "/path/to/repo/submodule1",
|
||||
Expected: &RepoPaths{
|
||||
Expected: lo.Ternary(runtime.GOOS == "windows", &RepoPaths{
|
||||
worktreePath: `C:\path\to\repo\submodule1`,
|
||||
worktreeGitDirPath: `C:\path\to\repo\.git\modules\submodule1`,
|
||||
repoPath: `C:\path\to\repo\submodule1`,
|
||||
repoGitDirPath: `C:\path\to\repo\.git\modules\submodule1`,
|
||||
repoName: `submodule1`,
|
||||
isBareRepo: false,
|
||||
}, &RepoPaths{
|
||||
worktreePath: "/path/to/repo/submodule1",
|
||||
worktreeGitDirPath: "/path/to/repo/.git/modules/submodule1",
|
||||
repoPath: "/path/to/repo/submodule1",
|
||||
repoGitDirPath: "/path/to/repo/.git/modules/submodule1",
|
||||
repoName: "submodule1",
|
||||
isBareRepo: false,
|
||||
},
|
||||
}),
|
||||
Err: nil,
|
||||
},
|
||||
{
|
||||
|
@ -84,7 +84,7 @@ func (self *StashCommands) ShowStashEntryCmdObj(index int) oscommands.ICmdObj {
|
||||
cmdArgs := NewGitCmd("stash").Arg("show").
|
||||
Arg("-p").
|
||||
Arg("--stat").
|
||||
Arg(fmt.Sprintf("--color=%s", self.UserConfig.Git.Paging.ColorArg)).
|
||||
Arg(fmt.Sprintf("--color=%s", self.UserConfig().Git.Paging.ColorArg)).
|
||||
Arg(fmt.Sprintf("--unified=%d", self.AppState.DiffContextSize)).
|
||||
ArgIf(self.AppState.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||
Arg(fmt.Sprintf("--find-renames=%d%%", self.AppState.RenameSimilarityThreshold)).
|
||||
|
@ -60,7 +60,7 @@ func (self *SyncCommands) fetchCommandBuilder(fetchAll bool) *GitCommandBuilder
|
||||
}
|
||||
|
||||
func (self *SyncCommands) FetchCmdObj(task gocui.Task) oscommands.ICmdObj {
|
||||
cmdArgs := self.fetchCommandBuilder(self.UserConfig.Git.FetchAll).ToArgv()
|
||||
cmdArgs := self.fetchCommandBuilder(self.UserConfig().Git.FetchAll).ToArgv()
|
||||
|
||||
cmdObj := self.cmd.New(cmdArgs)
|
||||
cmdObj.PromptOnCredentialRequest(task)
|
||||
@ -72,7 +72,7 @@ func (self *SyncCommands) Fetch(task gocui.Task) error {
|
||||
}
|
||||
|
||||
func (self *SyncCommands) FetchBackgroundCmdObj() oscommands.ICmdObj {
|
||||
cmdArgs := self.fetchCommandBuilder(self.UserConfig.Git.FetchAll).ToArgv()
|
||||
cmdArgs := self.fetchCommandBuilder(self.UserConfig().Git.FetchAll).ToArgv()
|
||||
|
||||
cmdObj := self.cmd.New(cmdArgs)
|
||||
cmdObj.DontLog().FailOnCredentialRequest()
|
||||
|
@ -133,7 +133,7 @@ func TestSyncFetch(t *testing.T) {
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
instance := buildSyncCommands(commonDeps{})
|
||||
instance.UserConfig.Git.FetchAll = s.fetchAllConfig
|
||||
instance.UserConfig().Git.FetchAll = s.fetchAllConfig
|
||||
task := gocui.NewFakeTask()
|
||||
s.test(instance.FetchCmdObj(task))
|
||||
})
|
||||
@ -171,7 +171,7 @@ func TestSyncFetchBackground(t *testing.T) {
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
instance := buildSyncCommands(commonDeps{})
|
||||
instance.UserConfig.Git.FetchAll = s.fetchAllConfig
|
||||
instance.UserConfig().Git.FetchAll = s.fetchAllConfig
|
||||
s.test(instance.FetchBackgroundCmdObj())
|
||||
})
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package git_commands
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
@ -233,7 +233,7 @@ func (self *WorkingTreeCommands) Ignore(filename string) error {
|
||||
|
||||
// Exclude adds a file to the .git/info/exclude for the repo
|
||||
func (self *WorkingTreeCommands) Exclude(filename string) error {
|
||||
excludeFile := path.Join(self.repoPaths.repoGitDirPath, "info", "exclude")
|
||||
excludeFile := filepath.Join(self.repoPaths.repoGitDirPath, "info", "exclude")
|
||||
return self.os.AppendLineToFile(excludeFile, filename)
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ func (self *WorkingTreeCommands) WorktreeFileDiff(file *models.File, plain bool,
|
||||
}
|
||||
|
||||
func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cached bool) oscommands.ICmdObj {
|
||||
colorArg := self.UserConfig.Git.Paging.ColorArg
|
||||
colorArg := self.UserConfig().Git.Paging.ColorArg
|
||||
if plain {
|
||||
colorArg = "never"
|
||||
}
|
||||
@ -253,7 +253,7 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain
|
||||
contextSize := self.AppState.DiffContextSize
|
||||
prevPath := node.GetPreviousPath()
|
||||
noIndex := !node.GetIsTracked() && !node.GetHasStagedChanges() && !cached && node.GetIsFile()
|
||||
extDiffCmd := self.UserConfig.Git.Paging.ExternalDiffCommand
|
||||
extDiffCmd := self.UserConfig().Git.Paging.ExternalDiffCommand
|
||||
useExtDiff := extDiffCmd != "" && !plain
|
||||
|
||||
cmdArgs := NewGitCmd("diff").
|
||||
@ -285,12 +285,12 @@ func (self *WorkingTreeCommands) ShowFileDiff(from string, to string, reverse bo
|
||||
func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileName string, plain bool) oscommands.ICmdObj {
|
||||
contextSize := self.AppState.DiffContextSize
|
||||
|
||||
colorArg := self.UserConfig.Git.Paging.ColorArg
|
||||
colorArg := self.UserConfig().Git.Paging.ColorArg
|
||||
if plain {
|
||||
colorArg = "never"
|
||||
}
|
||||
|
||||
extDiffCmd := self.UserConfig.Git.Paging.ExternalDiffCommand
|
||||
extDiffCmd := self.UserConfig().Git.Paging.ExternalDiffCommand
|
||||
useExtDiff := extDiffCmd != "" && !plain
|
||||
|
||||
cmdArgs := NewGitCmd("diff").
|
||||
|
@ -80,10 +80,10 @@ func FileType(path string) string {
|
||||
}
|
||||
|
||||
func (c *OSCommand) OpenFile(filename string) error {
|
||||
commandTemplate := c.UserConfig.OS.Open
|
||||
commandTemplate := c.UserConfig().OS.Open
|
||||
if commandTemplate == "" {
|
||||
// Legacy support
|
||||
commandTemplate = c.UserConfig.OS.OpenCommand
|
||||
commandTemplate = c.UserConfig().OS.OpenCommand
|
||||
}
|
||||
if commandTemplate == "" {
|
||||
commandTemplate = config.GetPlatformDefaultConfig().Open
|
||||
@ -96,10 +96,10 @@ func (c *OSCommand) OpenFile(filename string) error {
|
||||
}
|
||||
|
||||
func (c *OSCommand) OpenLink(link string) error {
|
||||
commandTemplate := c.UserConfig.OS.OpenLink
|
||||
commandTemplate := c.UserConfig().OS.OpenLink
|
||||
if commandTemplate == "" {
|
||||
// Legacy support
|
||||
commandTemplate = c.UserConfig.OS.OpenLinkCommand
|
||||
commandTemplate = c.UserConfig().OS.OpenLinkCommand
|
||||
}
|
||||
if commandTemplate == "" {
|
||||
commandTemplate = config.GetPlatformDefaultConfig().OpenLink
|
||||
@ -294,8 +294,8 @@ func (c *OSCommand) CopyToClipboard(str string) error {
|
||||
},
|
||||
)
|
||||
c.LogCommand(msg, false)
|
||||
if c.UserConfig.OS.CopyToClipboardCmd != "" {
|
||||
cmdStr := utils.ResolvePlaceholderString(c.UserConfig.OS.CopyToClipboardCmd, map[string]string{
|
||||
if c.UserConfig().OS.CopyToClipboardCmd != "" {
|
||||
cmdStr := utils.ResolvePlaceholderString(c.UserConfig().OS.CopyToClipboardCmd, map[string]string{
|
||||
"text": c.Cmd.Quote(str),
|
||||
})
|
||||
return c.Cmd.NewShell(cmdStr).Run()
|
||||
@ -307,8 +307,8 @@ func (c *OSCommand) CopyToClipboard(str string) error {
|
||||
func (c *OSCommand) PasteFromClipboard() (string, error) {
|
||||
var s string
|
||||
var err error
|
||||
if c.UserConfig.OS.CopyToClipboardCmd != "" {
|
||||
cmdStr := c.UserConfig.OS.ReadFromClipboardCmd
|
||||
if c.UserConfig().OS.CopyToClipboardCmd != "" {
|
||||
cmdStr := c.UserConfig().OS.ReadFromClipboardCmd
|
||||
s, err = c.Cmd.NewShell(cmdStr).RunWithOutput()
|
||||
} else {
|
||||
s, err = clipboard.ReadAll()
|
||||
|
@ -75,7 +75,7 @@ func TestOSCommandOpenFileDarwin(t *testing.T) {
|
||||
for _, s := range scenarios {
|
||||
oSCmd := NewDummyOSCommandWithRunner(s.runner)
|
||||
oSCmd.Platform.OS = "darwin"
|
||||
oSCmd.UserConfig.OS.Open = "open {{filename}}"
|
||||
oSCmd.UserConfig().OS.Open = "open {{filename}}"
|
||||
|
||||
s.test(oSCmd.OpenFile(s.filename))
|
||||
}
|
||||
@ -135,7 +135,7 @@ func TestOSCommandOpenFileLinux(t *testing.T) {
|
||||
for _, s := range scenarios {
|
||||
oSCmd := NewDummyOSCommandWithRunner(s.runner)
|
||||
oSCmd.Platform.OS = "linux"
|
||||
oSCmd.UserConfig.OS.Open = `xdg-open {{filename}} > /dev/null`
|
||||
oSCmd.UserConfig().OS.Open = `xdg-open {{filename}} > /dev/null`
|
||||
|
||||
s.test(oSCmd.OpenFile(s.filename))
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ func TestOSCommandOpenFileWindows(t *testing.T) {
|
||||
}
|
||||
oSCmd.Platform = platform
|
||||
oSCmd.Cmd.platform = platform
|
||||
oSCmd.UserConfig.OS.OpenCommand = `start "" {{filename}}`
|
||||
oSCmd.UserConfig().OS.OpenCommand = `start "" {{filename}}`
|
||||
|
||||
s.test(oSCmd.OpenFile(s.filename))
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -11,10 +13,18 @@ import (
|
||||
type Common struct {
|
||||
Log *logrus.Entry
|
||||
Tr *i18n.TranslationSet
|
||||
UserConfig *config.UserConfig
|
||||
userConfig atomic.Pointer[config.UserConfig]
|
||||
AppState *config.AppState
|
||||
Debug bool
|
||||
// for interacting with the filesystem. We use afero rather than the default
|
||||
// `os` package for the sake of mocking the filesystem in tests
|
||||
Fs afero.Fs
|
||||
}
|
||||
|
||||
func (c *Common) UserConfig() *config.UserConfig {
|
||||
return c.userConfig.Load()
|
||||
}
|
||||
|
||||
func (c *Common) SetUserConfig(userConfig *config.UserConfig) {
|
||||
c.userConfig.Store(userConfig)
|
||||
}
|
||||
|
@ -2,29 +2,31 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils/yaml_utils"
|
||||
"github.com/samber/lo"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// AppConfig contains the base configuration fields required for lazygit.
|
||||
type AppConfig struct {
|
||||
Debug bool `long:"debug" env:"DEBUG" default:"false"`
|
||||
Version string `long:"version" env:"VERSION" default:"unversioned"`
|
||||
BuildDate string `long:"build-date" env:"BUILD_DATE"`
|
||||
Name string `long:"name" env:"NAME" default:"lazygit"`
|
||||
BuildSource string `long:"build-source" env:"BUILD_SOURCE" default:""`
|
||||
UserConfig *UserConfig
|
||||
UserConfigPaths []string
|
||||
DeafultConfFiles bool
|
||||
UserConfigDir string
|
||||
TempDir string
|
||||
AppState *AppState
|
||||
IsNewRepo bool
|
||||
debug bool `long:"debug" env:"DEBUG" default:"false"`
|
||||
version string `long:"version" env:"VERSION" default:"unversioned"`
|
||||
buildDate string `long:"build-date" env:"BUILD_DATE"`
|
||||
name string `long:"name" env:"NAME" default:"lazygit"`
|
||||
buildSource string `long:"build-source" env:"BUILD_SOURCE" default:""`
|
||||
userConfig *UserConfig
|
||||
globalUserConfigFiles []*ConfigFile
|
||||
userConfigFiles []*ConfigFile
|
||||
userConfigDir string
|
||||
tempDir string
|
||||
appState *AppState
|
||||
}
|
||||
|
||||
type AppConfigurer interface {
|
||||
@ -38,13 +40,29 @@ type AppConfigurer interface {
|
||||
GetUserConfig() *UserConfig
|
||||
GetUserConfigPaths() []string
|
||||
GetUserConfigDir() string
|
||||
ReloadUserConfig() error
|
||||
ReloadUserConfigForRepo(repoConfigFiles []*ConfigFile) error
|
||||
ReloadChangedUserConfigFiles() (error, bool)
|
||||
GetTempDir() string
|
||||
|
||||
GetAppState() *AppState
|
||||
SaveAppState() error
|
||||
}
|
||||
|
||||
type ConfigFilePolicy int
|
||||
|
||||
const (
|
||||
ConfigFilePolicyCreateIfMissing ConfigFilePolicy = iota
|
||||
ConfigFilePolicyErrorIfMissing
|
||||
ConfigFilePolicySkipIfMissing
|
||||
)
|
||||
|
||||
type ConfigFile struct {
|
||||
Path string
|
||||
Policy ConfigFilePolicy
|
||||
modDate time.Time
|
||||
exists bool
|
||||
}
|
||||
|
||||
// NewAppConfig makes a new app config
|
||||
func NewAppConfig(
|
||||
name string,
|
||||
@ -60,17 +78,22 @@ func NewAppConfig(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var userConfigPaths []string
|
||||
var configFiles []*ConfigFile
|
||||
customConfigFiles := os.Getenv("LG_CONFIG_FILE")
|
||||
if customConfigFiles != "" {
|
||||
// Load user defined config files
|
||||
userConfigPaths = strings.Split(customConfigFiles, ",")
|
||||
userConfigPaths := strings.Split(customConfigFiles, ",")
|
||||
configFiles = lo.Map(userConfigPaths, func(path string, _ int) *ConfigFile {
|
||||
return &ConfigFile{Path: path, Policy: ConfigFilePolicyErrorIfMissing}
|
||||
})
|
||||
} else {
|
||||
// Load default config files
|
||||
userConfigPaths = []string{filepath.Join(configDir, ConfigFilename)}
|
||||
path := filepath.Join(configDir, ConfigFilename)
|
||||
configFile := &ConfigFile{Path: path, Policy: ConfigFilePolicyCreateIfMissing}
|
||||
configFiles = []*ConfigFile{configFile}
|
||||
}
|
||||
|
||||
userConfig, err := loadUserConfigWithDefaults(userConfigPaths)
|
||||
userConfig, err := loadUserConfigWithDefaults(configFiles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -92,26 +115,22 @@ func NewAppConfig(
|
||||
}
|
||||
|
||||
appConfig := &AppConfig{
|
||||
Name: name,
|
||||
Version: version,
|
||||
BuildDate: date,
|
||||
Debug: debuggingFlag,
|
||||
BuildSource: buildSource,
|
||||
UserConfig: userConfig,
|
||||
UserConfigPaths: userConfigPaths,
|
||||
UserConfigDir: configDir,
|
||||
TempDir: tempDir,
|
||||
AppState: appState,
|
||||
IsNewRepo: false,
|
||||
name: name,
|
||||
version: version,
|
||||
buildDate: date,
|
||||
debug: debuggingFlag,
|
||||
buildSource: buildSource,
|
||||
userConfig: userConfig,
|
||||
globalUserConfigFiles: configFiles,
|
||||
userConfigFiles: configFiles,
|
||||
userConfigDir: configDir,
|
||||
tempDir: tempDir,
|
||||
appState: appState,
|
||||
}
|
||||
|
||||
return appConfig, nil
|
||||
}
|
||||
|
||||
func isCustomConfigFile(path string) bool {
|
||||
return path != filepath.Join(ConfigDir(), ConfigFilename)
|
||||
}
|
||||
|
||||
func ConfigDir() string {
|
||||
_, filePath := findConfigFile("config.yml")
|
||||
|
||||
@ -123,32 +142,48 @@ func findOrCreateConfigDir() (string, error) {
|
||||
return folder, os.MkdirAll(folder, 0o755)
|
||||
}
|
||||
|
||||
func loadUserConfigWithDefaults(configFiles []string) (*UserConfig, error) {
|
||||
func loadUserConfigWithDefaults(configFiles []*ConfigFile) (*UserConfig, error) {
|
||||
return loadUserConfig(configFiles, GetDefaultConfig())
|
||||
}
|
||||
|
||||
func loadUserConfig(configFiles []string, base *UserConfig) (*UserConfig, error) {
|
||||
for _, path := range configFiles {
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
func loadUserConfig(configFiles []*ConfigFile, base *UserConfig) (*UserConfig, error) {
|
||||
for _, configFile := range configFiles {
|
||||
path := configFile.Path
|
||||
statInfo, err := os.Stat(path)
|
||||
if err == nil {
|
||||
configFile.exists = true
|
||||
configFile.modDate = statInfo.ModTime()
|
||||
} else {
|
||||
if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if use has supplied their own custom config file path(s), we assume
|
||||
// the files have already been created, so we won't go and create them here.
|
||||
if isCustomConfigFile(path) {
|
||||
switch configFile.Policy {
|
||||
case ConfigFilePolicyErrorIfMissing:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
// apparently when people have read-only permissions they prefer us to fail silently
|
||||
continue
|
||||
case ConfigFilePolicySkipIfMissing:
|
||||
configFile.exists = false
|
||||
continue
|
||||
|
||||
case ConfigFilePolicyCreateIfMissing:
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
// apparently when people have read-only permissions they prefer us to fail silently
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
file.Close()
|
||||
|
||||
configFile.exists = true
|
||||
statInfo, err := os.Stat(configFile.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
configFile.modDate = statInfo.ModTime()
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(path)
|
||||
@ -220,53 +255,81 @@ func changeNullKeybindingsToDisabled(changedContent []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
func (c *AppConfig) GetDebug() bool {
|
||||
return c.Debug
|
||||
return c.debug
|
||||
}
|
||||
|
||||
func (c *AppConfig) GetVersion() string {
|
||||
return c.Version
|
||||
return c.version
|
||||
}
|
||||
|
||||
func (c *AppConfig) GetName() string {
|
||||
return c.Name
|
||||
return c.name
|
||||
}
|
||||
|
||||
// GetBuildSource returns the source of the build. For builds from goreleaser
|
||||
// this will be binaryBuild
|
||||
func (c *AppConfig) GetBuildSource() string {
|
||||
return c.BuildSource
|
||||
return c.buildSource
|
||||
}
|
||||
|
||||
// GetUserConfig returns the user config
|
||||
func (c *AppConfig) GetUserConfig() *UserConfig {
|
||||
return c.UserConfig
|
||||
return c.userConfig
|
||||
}
|
||||
|
||||
// GetAppState returns the app state
|
||||
func (c *AppConfig) GetAppState() *AppState {
|
||||
return c.AppState
|
||||
return c.appState
|
||||
}
|
||||
|
||||
func (c *AppConfig) GetUserConfigPaths() []string {
|
||||
return c.UserConfigPaths
|
||||
return lo.FilterMap(c.userConfigFiles, func(f *ConfigFile, _ int) (string, bool) {
|
||||
return f.Path, f.exists
|
||||
})
|
||||
}
|
||||
|
||||
func (c *AppConfig) GetUserConfigDir() string {
|
||||
return c.UserConfigDir
|
||||
return c.userConfigDir
|
||||
}
|
||||
|
||||
func (c *AppConfig) ReloadUserConfig() error {
|
||||
userConfig, err := loadUserConfigWithDefaults(c.UserConfigPaths)
|
||||
func (c *AppConfig) ReloadUserConfigForRepo(repoConfigFiles []*ConfigFile) error {
|
||||
configFiles := append(c.globalUserConfigFiles, repoConfigFiles...)
|
||||
userConfig, err := loadUserConfigWithDefaults(configFiles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.UserConfig = userConfig
|
||||
c.userConfig = userConfig
|
||||
c.userConfigFiles = configFiles
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *AppConfig) ReloadChangedUserConfigFiles() (error, bool) {
|
||||
fileHasChanged := func(f *ConfigFile) bool {
|
||||
info, err := os.Stat(f.Path)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
// If we can't stat the file, assume it hasn't changed
|
||||
return false
|
||||
}
|
||||
exists := err == nil
|
||||
return exists != f.exists || (exists && info.ModTime() != f.modDate)
|
||||
}
|
||||
|
||||
if lo.NoneBy(c.userConfigFiles, fileHasChanged) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
userConfig, err := loadUserConfigWithDefaults(c.userConfigFiles)
|
||||
if err != nil {
|
||||
return err, false
|
||||
}
|
||||
|
||||
c.userConfig = userConfig
|
||||
return nil, true
|
||||
}
|
||||
|
||||
func (c *AppConfig) GetTempDir() string {
|
||||
return c.TempDir
|
||||
return c.tempDir
|
||||
}
|
||||
|
||||
// findConfigFile looks for a possibly existing config file.
|
||||
@ -305,14 +368,9 @@ func stateFilePath(filename string) (string, error) {
|
||||
return xdg.StateFile(filepath.Join("lazygit", filename))
|
||||
}
|
||||
|
||||
// ConfigFilename returns the filename of the default config file
|
||||
func (c *AppConfig) ConfigFilename() string {
|
||||
return filepath.Join(c.UserConfigDir, ConfigFilename)
|
||||
}
|
||||
|
||||
// SaveAppState marshalls the AppState struct and writes it to the disk
|
||||
func (c *AppConfig) SaveAppState() error {
|
||||
marshalledAppState, err := yaml.Marshal(c.AppState)
|
||||
marshalledAppState, err := yaml.Marshal(c.appState)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -363,6 +421,24 @@ func loadAppState() (*AppState, error) {
|
||||
return appState, nil
|
||||
}
|
||||
|
||||
// SaveGlobalUserConfig saves the UserConfig back to disk. This is only used in
|
||||
// integration tests, so we are a bit sloppy with error handling.
|
||||
func (c *AppConfig) SaveGlobalUserConfig() {
|
||||
if len(c.globalUserConfigFiles) != 1 {
|
||||
panic("expected exactly one global user config file")
|
||||
}
|
||||
|
||||
yamlContent, err := yaml.Marshal(c.userConfig)
|
||||
if err != nil {
|
||||
log.Fatalf("error marshalling user config: %v", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(c.globalUserConfigFiles[0].Path, yamlContent, 0o644)
|
||||
if err != nil {
|
||||
log.Fatalf("error saving user config: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// AppState stores data between runs of the app like when the last update check
|
||||
// was performed and which other repos have been checked out
|
||||
type AppState struct {
|
||||
|
@ -7,12 +7,12 @@ import (
|
||||
// NewDummyAppConfig creates a new dummy AppConfig for testing
|
||||
func NewDummyAppConfig() *AppConfig {
|
||||
appConfig := &AppConfig{
|
||||
Name: "lazygit",
|
||||
Version: "unversioned",
|
||||
Debug: false,
|
||||
UserConfig: GetDefaultConfig(),
|
||||
AppState: &AppState{},
|
||||
name: "lazygit",
|
||||
version: "unversioned",
|
||||
debug: false,
|
||||
userConfig: GetDefaultConfig(),
|
||||
appState: &AppState{},
|
||||
}
|
||||
_ = yaml.Unmarshal([]byte{}, appConfig.AppState)
|
||||
_ = yaml.Unmarshal([]byte{}, appConfig.appState)
|
||||
return appConfig
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ func (self *BackgroundRoutineMgr) PauseBackgroundRefreshes(pause bool) {
|
||||
}
|
||||
|
||||
func (self *BackgroundRoutineMgr) startBackgroundRoutines() {
|
||||
userConfig := self.gui.UserConfig
|
||||
userConfig := self.gui.UserConfig()
|
||||
|
||||
if userConfig.Git.AutoFetch {
|
||||
fetchInterval := userConfig.Refresher.FetchInterval
|
||||
@ -77,7 +77,7 @@ func (self *BackgroundRoutineMgr) startBackgroundFetch() {
|
||||
self.gui.waitForIntro.Wait()
|
||||
|
||||
isNew := self.gui.IsNewRepo
|
||||
userConfig := self.gui.UserConfig
|
||||
userConfig := self.gui.UserConfig()
|
||||
if !isNew {
|
||||
time.After(time.Duration(userConfig.Refresher.FetchInterval) * time.Second)
|
||||
}
|
||||
|
@ -55,11 +55,11 @@ func (gui *Gui) LogCommand(cmdStr string, commandLine bool) {
|
||||
func (gui *Gui) printCommandLogHeader() {
|
||||
introStr := fmt.Sprintf(
|
||||
gui.c.Tr.CommandLogHeader,
|
||||
keybindings.Label(gui.c.UserConfig.Keybinding.Universal.ExtrasMenu),
|
||||
keybindings.Label(gui.c.UserConfig().Keybinding.Universal.ExtrasMenu),
|
||||
)
|
||||
fmt.Fprintln(gui.Views.Extras, style.FgCyan.Sprint(introStr))
|
||||
|
||||
if gui.c.UserConfig.Gui.ShowRandomTip {
|
||||
if gui.c.UserConfig().Gui.ShowRandomTip {
|
||||
fmt.Fprintf(
|
||||
gui.Views.Extras,
|
||||
"%s: %s",
|
||||
@ -70,7 +70,7 @@ func (gui *Gui) printCommandLogHeader() {
|
||||
}
|
||||
|
||||
func (gui *Gui) getRandomTip() string {
|
||||
config := gui.c.UserConfig.Keybinding
|
||||
config := gui.c.UserConfig().Keybinding
|
||||
|
||||
formattedKey := func(key string) string {
|
||||
return keybindings.Label(key)
|
||||
|
@ -32,7 +32,7 @@ func NewBranchesContext(c *ContextCommon) *BranchesContext {
|
||||
c.Modes().Diffing.Ref,
|
||||
c.Views().Branches.Width(),
|
||||
c.Tr,
|
||||
c.UserConfig,
|
||||
c.UserConfig(),
|
||||
c.Model().Worktrees,
|
||||
)
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
|
||||
viewModel := filetree.NewCommitFileTreeViewModel(
|
||||
func() []*models.CommitFile { return c.Model().CommitFiles },
|
||||
c.Log,
|
||||
c.UserConfig.Gui.ShowFileTree,
|
||||
c.UserConfig().Gui.ShowFileTree,
|
||||
)
|
||||
|
||||
getDisplayStrings := func(_ int, _ int) [][]string {
|
||||
@ -36,7 +36,7 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
|
||||
return [][]string{{style.FgRed.Sprint("(none)")}}
|
||||
}
|
||||
|
||||
showFileIcons := icons.IsIconEnabled() && c.UserConfig.Gui.ShowFileIcons
|
||||
showFileIcons := icons.IsIconEnabled() && c.UserConfig().Gui.ShowFileIcons
|
||||
lines := presentation.RenderCommitFileTree(viewModel, c.Git().Patch.PatchBuilder, showFileIcons)
|
||||
return lo.Map(lines, func(line string, _ int) []string {
|
||||
return []string{line}
|
||||
|
@ -113,19 +113,19 @@ func (self *CommitMessageContext) SetPanelState(
|
||||
|
||||
self.c.Views().CommitDescription.Subtitle = utils.ResolvePlaceholderString(self.c.Tr.CommitDescriptionSubTitle,
|
||||
map[string]string{
|
||||
"togglePanelKeyBinding": keybindings.Label(self.c.UserConfig.Keybinding.Universal.TogglePanel),
|
||||
"commitMenuKeybinding": keybindings.Label(self.c.UserConfig.Keybinding.CommitMessage.CommitMenu),
|
||||
"togglePanelKeyBinding": keybindings.Label(self.c.UserConfig().Keybinding.Universal.TogglePanel),
|
||||
"commitMenuKeybinding": keybindings.Label(self.c.UserConfig().Keybinding.CommitMessage.CommitMenu),
|
||||
})
|
||||
|
||||
self.c.Views().CommitDescription.Visible = true
|
||||
}
|
||||
|
||||
func (self *CommitMessageContext) RenderCommitLength() {
|
||||
if !self.c.UserConfig.Gui.CommitLength.Show {
|
||||
return
|
||||
if self.c.UserConfig().Gui.CommitLength.Show {
|
||||
self.c.Views().CommitMessage.Subtitle = getBufferLength(self.c.Views().CommitMessage)
|
||||
} else {
|
||||
self.c.Views().CommitMessage.Subtitle = ""
|
||||
}
|
||||
|
||||
self.c.Views().CommitMessage.Subtitle = getBufferLength(self.c.Views().CommitMessage)
|
||||
}
|
||||
|
||||
func getBufferLength(view *gocui.View) string {
|
||||
|
@ -54,10 +54,10 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
|
||||
c.Modes().CherryPicking.SelectedHashSet(),
|
||||
c.Modes().Diffing.Ref,
|
||||
c.Modes().MarkedBaseCommit.GetHash(),
|
||||
c.UserConfig.Gui.TimeFormat,
|
||||
c.UserConfig.Gui.ShortTimeFormat,
|
||||
c.UserConfig().Gui.TimeFormat,
|
||||
c.UserConfig().Gui.ShortTimeFormat,
|
||||
time.Now(),
|
||||
c.UserConfig.Git.ParseEmoji,
|
||||
c.UserConfig().Git.ParseEmoji,
|
||||
selectedCommitHash,
|
||||
startIdx,
|
||||
endIdx,
|
||||
@ -110,7 +110,7 @@ func NewLocalCommitsViewModel(getModel func() []*models.Commit, c *ContextCommon
|
||||
self := &LocalCommitsViewModel{
|
||||
ListViewModel: NewListViewModel(getModel),
|
||||
limitCommits: true,
|
||||
showWholeGitGraph: c.UserConfig.Git.Log.ShowWholeGraph,
|
||||
showWholeGitGraph: c.UserConfig().Git.Log.ShowWholeGraph,
|
||||
}
|
||||
|
||||
return self
|
||||
|
@ -139,7 +139,7 @@ func (self *MenuViewModel) GetNonModelItems() []*NonModelItem {
|
||||
// Don't display section headers when we are filtering, and the filter mode
|
||||
// is fuzzy. The reason is that filtering changes the order of the items
|
||||
// (they are sorted by best match), so all the sections would be messed up.
|
||||
if self.FilteredListViewModel.IsFiltering() && self.c.UserConfig.Gui.UseFuzzySearch() {
|
||||
if self.FilteredListViewModel.IsFiltering() && self.c.UserConfig().Gui.UseFuzzySearch() {
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -33,9 +33,9 @@ func NewReflogCommitsContext(c *ContextCommon) *ReflogCommitsContext {
|
||||
c.Modes().CherryPicking.SelectedHashSet(),
|
||||
c.Modes().Diffing.Ref,
|
||||
time.Now(),
|
||||
c.UserConfig.Gui.TimeFormat,
|
||||
c.UserConfig.Gui.ShortTimeFormat,
|
||||
c.UserConfig.Git.ParseEmoji,
|
||||
c.UserConfig().Gui.TimeFormat,
|
||||
c.UserConfig().Gui.ShortTimeFormat,
|
||||
c.UserConfig().Git.ParseEmoji,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ func NewRemotesContext(c *ContextCommon) *RemotesContext {
|
||||
|
||||
getDisplayStrings := func(_ int, _ int) [][]string {
|
||||
return presentation.GetRemoteListDisplayStrings(
|
||||
viewModel.GetItems(), c.Modes().Diffing.Ref, c.State().GetItemOperation, c.Tr, c.UserConfig)
|
||||
viewModel.GetItems(), c.Modes().Diffing.Ref, c.State().GetItemOperation, c.Tr, c.UserConfig())
|
||||
}
|
||||
|
||||
return &RemotesContext{
|
||||
|
@ -51,7 +51,7 @@ func (self *SearchTrait) onSelectItemWrapper(innerFunc func(int) error) func(int
|
||||
}
|
||||
|
||||
func (self *SearchTrait) RenderSearchStatus(index int, total int) {
|
||||
keybindingConfig := self.c.UserConfig.Keybinding
|
||||
keybindingConfig := self.c.UserConfig().Keybinding
|
||||
|
||||
if total == 0 {
|
||||
self.c.SetViewContent(
|
||||
|
@ -68,10 +68,10 @@ func NewSubCommitsContext(
|
||||
c.Modes().CherryPicking.SelectedHashSet(),
|
||||
c.Modes().Diffing.Ref,
|
||||
"",
|
||||
c.UserConfig.Gui.TimeFormat,
|
||||
c.UserConfig.Gui.ShortTimeFormat,
|
||||
c.UserConfig().Gui.TimeFormat,
|
||||
c.UserConfig().Gui.ShortTimeFormat,
|
||||
time.Now(),
|
||||
c.UserConfig.Git.ParseEmoji,
|
||||
c.UserConfig().Git.ParseEmoji,
|
||||
selectedCommitHash,
|
||||
startIdx,
|
||||
endIdx,
|
||||
|
@ -30,7 +30,7 @@ func NewTagsContext(
|
||||
return presentation.GetTagListDisplayStrings(
|
||||
viewModel.GetItems(),
|
||||
c.State().GetItemOperation,
|
||||
c.Modes().Diffing.Ref, c.Tr, c.UserConfig)
|
||||
c.Modes().Diffing.Ref, c.Tr, c.UserConfig())
|
||||
}
|
||||
|
||||
return &TagsContext{
|
||||
|
@ -25,11 +25,11 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
|
||||
viewModel := filetree.NewFileTreeViewModel(
|
||||
func() []*models.File { return c.Model().Files },
|
||||
c.Log,
|
||||
c.UserConfig.Gui.ShowFileTree,
|
||||
c.UserConfig().Gui.ShowFileTree,
|
||||
)
|
||||
|
||||
getDisplayStrings := func(_ int, _ int) [][]string {
|
||||
showFileIcons := icons.IsIconEnabled() && c.UserConfig.Gui.ShowFileIcons
|
||||
showFileIcons := icons.IsIconEnabled() && c.UserConfig().Gui.ShowFileIcons
|
||||
lines := presentation.RenderFileTree(viewModel, c.Model().Submodules, showFileIcons)
|
||||
return lo.Map(lines, func(line string, _ int) []string {
|
||||
return []string{line}
|
||||
|
@ -311,8 +311,8 @@ func (self *BasicCommitsController) canCopyCommits(selectedCommits []*models.Com
|
||||
func (self *BasicCommitsController) handleOldCherryPickKey() error {
|
||||
msg := utils.ResolvePlaceholderString(self.c.Tr.OldCherryPickKeyWarning,
|
||||
map[string]string{
|
||||
"copy": keybindings.Label(self.c.UserConfig.Keybinding.Commits.CherryPickCopy),
|
||||
"paste": keybindings.Label(self.c.UserConfig.Keybinding.Commits.PasteCommits),
|
||||
"copy": keybindings.Label(self.c.UserConfig().Keybinding.Commits.CherryPickCopy),
|
||||
"paste": keybindings.Label(self.c.UserConfig().Keybinding.Commits.PasteCommits),
|
||||
})
|
||||
|
||||
return errors.New(msg)
|
||||
|
@ -118,8 +118,8 @@ func (self *CommitMessageController) setCommitMessageAtIndex(index int) (bool, e
|
||||
}
|
||||
return false, errors.New(self.c.Tr.CommitWithoutMessageErr)
|
||||
}
|
||||
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
|
||||
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
|
||||
if self.c.UserConfig().Git.Commit.AutoWrapCommitMessage {
|
||||
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig().Git.Commit.AutoWrapWidth)
|
||||
}
|
||||
self.c.Helpers().Commits.UpdateCommitPanelView(commitMessage)
|
||||
return true, nil
|
||||
|
@ -46,7 +46,7 @@ func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) [
|
||||
// We assume that whenever things are deletable, they
|
||||
// are also editable, so we show both keybindings
|
||||
subtitle = fmt.Sprintf(self.c.Tr.SuggestionsSubtitle,
|
||||
self.c.UserConfig.Keybinding.Universal.Remove, self.c.UserConfig.Keybinding.Universal.Edit)
|
||||
self.c.UserConfig().Keybinding.Universal.Remove, self.c.UserConfig().Keybinding.Universal.Edit)
|
||||
}
|
||||
self.c.Views().Suggestions.Subtitle = subtitle
|
||||
return self.c.Context().Replace(self.c.Contexts().Suggestions)
|
||||
|
@ -258,7 +258,7 @@ func (self *FilesController) GetOnRenderToMain() func() error {
|
||||
pair = self.c.MainViewPairs().Staging
|
||||
}
|
||||
|
||||
split := self.c.UserConfig.Gui.SplitDiff == "always" || (node.GetHasUnstagedChanges() && node.GetHasStagedChanges())
|
||||
split := self.c.UserConfig().Gui.SplitDiff == "always" || (node.GetHasUnstagedChanges() && node.GetHasStagedChanges())
|
||||
mainShowsStaged := !split && node.GetHasStagedChanges()
|
||||
|
||||
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(node, false, mainShowsStaged)
|
||||
@ -1083,7 +1083,7 @@ func (self *FilesController) remove(selectedNodes []*filetree.FileNode) error {
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES, types.WORKTREES}})
|
||||
},
|
||||
Key: self.c.KeybindingsOpts().GetKey(self.c.UserConfig.Keybinding.Files.ConfirmDiscard),
|
||||
Key: self.c.KeybindingsOpts().GetKey(self.c.UserConfig().Keybinding.Files.ConfirmDiscard),
|
||||
Tooltip: utils.ResolvePlaceholderString(
|
||||
self.c.Tr.DiscardAllTooltip,
|
||||
map[string]string{
|
||||
|
@ -81,16 +81,16 @@ func (self *AppStatusHelper) HasStatus() bool {
|
||||
}
|
||||
|
||||
func (self *AppStatusHelper) GetStatusString() string {
|
||||
appStatus, _ := self.statusMgr().GetStatusString(self.c.UserConfig)
|
||||
appStatus, _ := self.statusMgr().GetStatusString(self.c.UserConfig())
|
||||
return appStatus
|
||||
}
|
||||
|
||||
func (self *AppStatusHelper) renderAppStatus() {
|
||||
self.c.OnWorker(func(_ gocui.Task) error {
|
||||
ticker := time.NewTicker(time.Millisecond * time.Duration(self.c.UserConfig.Gui.Spinner.Rate))
|
||||
ticker := time.NewTicker(time.Millisecond * time.Duration(self.c.UserConfig().Gui.Spinner.Rate))
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
appStatus, color := self.statusMgr().GetStatusString(self.c.UserConfig)
|
||||
appStatus, color := self.statusMgr().GetStatusString(self.c.UserConfig())
|
||||
self.c.Views().AppStatus.FgColor = color
|
||||
self.c.OnUIThread(func() error {
|
||||
self.c.SetViewContent(self.c.Views().AppStatus, appStatus)
|
||||
@ -124,7 +124,7 @@ func (self *AppStatusHelper) renderAppStatusSync(stop chan struct{}) {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
appStatus, color := self.statusMgr().GetStatusString(self.c.UserConfig)
|
||||
appStatus, color := self.statusMgr().GetStatusString(self.c.UserConfig())
|
||||
self.c.Views().AppStatus.FgColor = color
|
||||
self.c.SetViewContent(self.c.Views().AppStatus, appStatus)
|
||||
// Redraw all views of the bottom line:
|
||||
|
@ -173,7 +173,7 @@ func (self *ConfirmationHelper) prepareConfirmationPanel(
|
||||
suggestionsView.FgColor = theme.GocuiDefaultTextColor
|
||||
suggestionsContext.SetSuggestions(opts.FindSuggestionsFunc(""))
|
||||
suggestionsView.Visible = true
|
||||
suggestionsView.Title = fmt.Sprintf(self.c.Tr.SuggestionsTitle, self.c.UserConfig.Keybinding.Universal.TogglePanel)
|
||||
suggestionsView.Title = fmt.Sprintf(self.c.Tr.SuggestionsTitle, self.c.UserConfig().Keybinding.Universal.TogglePanel)
|
||||
suggestionsView.Subtitle = ""
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ func (self *GpgHelper) runAndStream(cmdObj oscommands.ICmdObj, waitingStatus str
|
||||
if err := cmdObj.StreamOutput().Run(); err != nil {
|
||||
_ = self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
return fmt.Errorf(
|
||||
self.c.Tr.GitCommandFailed, self.c.UserConfig.Keybinding.Universal.ExtrasMenu,
|
||||
self.c.Tr.GitCommandFailed, self.c.UserConfig().Keybinding.Universal.ExtrasMenu,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,6 @@ func (self *HostHelper) getHostingServiceMgr() (*hosting_service.HostingServiceM
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
configServices := self.c.UserConfig.Services
|
||||
configServices := self.c.UserConfig().Services
|
||||
return hosting_service.NewHostingServiceMgr(self.c.Log, self.c.Tr, remoteUrl, configServices), nil
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ func (self *InlineStatusHelper) start(opts InlineStatusOpts) {
|
||||
self.contextsWithInlineStatus[opts.ContextKey] = info
|
||||
|
||||
go utils.Safe(func() {
|
||||
ticker := time.NewTicker(time.Millisecond * time.Duration(self.c.UserConfig.Gui.Spinner.Rate))
|
||||
ticker := time.NewTicker(time.Millisecond * time.Duration(self.c.UserConfig().Gui.Spinner.Rate))
|
||||
defer ticker.Stop()
|
||||
outer:
|
||||
for {
|
||||
|
@ -112,7 +112,7 @@ func (self *MergeAndRebaseHelper) genericMergeCommand(command string) error {
|
||||
// we should end up with a command like 'git merge --continue'
|
||||
|
||||
// it's impossible for a rebase to require a commit so we'll use a subprocess only if it's a merge
|
||||
needsSubprocess := (status == enums.REBASE_MODE_MERGING && command != REBASE_OPTION_ABORT && self.c.UserConfig.Git.Merging.ManualCommit) ||
|
||||
needsSubprocess := (status == enums.REBASE_MODE_MERGING && command != REBASE_OPTION_ABORT && self.c.UserConfig().Git.Merging.ManualCommit) ||
|
||||
// but we'll also use a subprocess if we have exec todos; those are likely to be lengthy build
|
||||
// tasks whose output the user will want to see in the terminal
|
||||
(status == enums.REBASE_MODE_REBASING && command != REBASE_OPTION_ABORT && self.hasExecTodos())
|
||||
@ -435,7 +435,7 @@ func (self *MergeAndRebaseHelper) SquashMergeCommitted(refName, checkedOutBranch
|
||||
if err = self.CheckMergeOrRebase(err); err != nil {
|
||||
return err
|
||||
}
|
||||
message := utils.ResolvePlaceholderString(self.c.UserConfig.Git.Merging.SquashMergeMessage, map[string]string{
|
||||
message := utils.ResolvePlaceholderString(self.c.UserConfig().Git.Merging.SquashMergeMessage, map[string]string{
|
||||
"selectedRef": refName,
|
||||
"currentBranch": checkedOutBranchName,
|
||||
})
|
||||
|
@ -737,7 +737,7 @@ func (self *RefreshHelper) refreshStatus() {
|
||||
|
||||
repoName := self.c.Git().RepoPaths.RepoName()
|
||||
|
||||
status := presentation.FormatStatus(repoName, currentBranch, types.ItemOperationNone, linkedWorktreeName, workingTreeState, self.c.Tr, self.c.UserConfig)
|
||||
status := presentation.FormatStatus(repoName, currentBranch, types.ItemOperationNone, linkedWorktreeName, workingTreeState, self.c.Tr, self.c.UserConfig())
|
||||
|
||||
self.c.SetViewContent(self.c.Views().Status, status)
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ func (self *RefsHelper) NewBranch(from string, fromFormattedName string, suggest
|
||||
)
|
||||
|
||||
if suggestedBranchName == "" {
|
||||
suggestedBranchName = self.c.UserConfig.Git.BranchPrefix
|
||||
suggestedBranchName = self.c.UserConfig().Git.BranchPrefix
|
||||
}
|
||||
|
||||
return self.c.Prompt(types.PromptOpts{
|
||||
|
@ -76,7 +76,7 @@ func (self *SearchHelper) DisplayFilterStatus(context types.IFilterableContext)
|
||||
self.searchPrefixView().SetContent(self.c.Tr.FilterPrefix)
|
||||
|
||||
promptView := self.promptView()
|
||||
keybindingConfig := self.c.UserConfig.Keybinding
|
||||
keybindingConfig := self.c.UserConfig().Keybinding
|
||||
promptView.SetContent(fmt.Sprintf("matches for '%s' ", searchString) + theme.OptionsFgColor.Sprintf(self.c.Tr.ExitTextFilterMode, keybindings.Label(keybindingConfig.Universal.Return)))
|
||||
}
|
||||
|
||||
@ -229,7 +229,7 @@ func (self *SearchHelper) OnPromptContentChanged(searchString string) {
|
||||
case types.IFilterableContext:
|
||||
context.SetSelection(0)
|
||||
_ = context.GetView().SetOriginY(0)
|
||||
context.SetFilter(searchString, self.c.UserConfig.Gui.UseFuzzySearch())
|
||||
context.SetFilter(searchString, self.c.UserConfig().Gui.UseFuzzySearch())
|
||||
_ = self.c.PostRefreshUpdate(context)
|
||||
case types.ISearchableContext:
|
||||
// do nothing
|
||||
@ -246,7 +246,7 @@ func (self *SearchHelper) ReApplyFilter(context types.Context) {
|
||||
filterableContext.SetSelection(0)
|
||||
_ = filterableContext.GetView().SetOriginY(0)
|
||||
}
|
||||
filterableContext.ReApplyFilter(self.c.UserConfig.Gui.UseFuzzySearch())
|
||||
filterableContext.ReApplyFilter(self.c.UserConfig().Gui.UseFuzzySearch())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ func matchesToSuggestions(matches []string) []*types.Suggestion {
|
||||
func (self *SuggestionsHelper) GetRemoteSuggestionsFunc() func(string) []*types.Suggestion {
|
||||
remoteNames := self.getRemoteNames()
|
||||
|
||||
return FilterFunc(remoteNames, self.c.UserConfig.Gui.UseFuzzySearch())
|
||||
return FilterFunc(remoteNames, self.c.UserConfig().Gui.UseFuzzySearch())
|
||||
}
|
||||
|
||||
func (self *SuggestionsHelper) getBranchNames() []string {
|
||||
@ -83,7 +83,7 @@ func (self *SuggestionsHelper) GetBranchNameSuggestionsFunc() func(string) []*ty
|
||||
if input == "" {
|
||||
matchingBranchNames = branchNames
|
||||
} else {
|
||||
matchingBranchNames = utils.FilterStrings(input, branchNames, self.c.UserConfig.Gui.UseFuzzySearch())
|
||||
matchingBranchNames = utils.FilterStrings(input, branchNames, self.c.UserConfig().Gui.UseFuzzySearch())
|
||||
}
|
||||
|
||||
return lo.Map(matchingBranchNames, func(branchName string, _ int) *types.Suggestion {
|
||||
@ -129,7 +129,7 @@ func (self *SuggestionsHelper) GetFilePathSuggestionsFunc() func(string) []*type
|
||||
|
||||
return func(input string) []*types.Suggestion {
|
||||
matchingNames := []string{}
|
||||
if self.c.UserConfig.Gui.UseFuzzySearch() {
|
||||
if self.c.UserConfig().Gui.UseFuzzySearch() {
|
||||
_ = self.c.Model().FilesTrie.VisitFuzzy(patricia.Prefix(input), true, func(prefix patricia.Prefix, item patricia.Item, skipped int) error {
|
||||
matchingNames = append(matchingNames, item.(string))
|
||||
return nil
|
||||
@ -163,7 +163,7 @@ func (self *SuggestionsHelper) getRemoteBranchNames(separator string) []string {
|
||||
}
|
||||
|
||||
func (self *SuggestionsHelper) GetRemoteBranchesSuggestionsFunc(separator string) func(string) []*types.Suggestion {
|
||||
return FilterFunc(self.getRemoteBranchNames(separator), self.c.UserConfig.Gui.UseFuzzySearch())
|
||||
return FilterFunc(self.getRemoteBranchNames(separator), self.c.UserConfig().Gui.UseFuzzySearch())
|
||||
}
|
||||
|
||||
func (self *SuggestionsHelper) getTagNames() []string {
|
||||
@ -175,7 +175,7 @@ func (self *SuggestionsHelper) getTagNames() []string {
|
||||
func (self *SuggestionsHelper) GetTagsSuggestionsFunc() func(string) []*types.Suggestion {
|
||||
tagNames := self.getTagNames()
|
||||
|
||||
return FilterFunc(tagNames, self.c.UserConfig.Gui.UseFuzzySearch())
|
||||
return FilterFunc(tagNames, self.c.UserConfig().Gui.UseFuzzySearch())
|
||||
}
|
||||
|
||||
func (self *SuggestionsHelper) GetRefsSuggestionsFunc() func(string) []*types.Suggestion {
|
||||
@ -186,7 +186,7 @@ func (self *SuggestionsHelper) GetRefsSuggestionsFunc() func(string) []*types.Su
|
||||
|
||||
refNames := append(append(append(remoteBranchNames, localBranchNames...), tagNames...), additionalRefNames...)
|
||||
|
||||
return FilterFunc(refNames, self.c.UserConfig.Gui.UseFuzzySearch())
|
||||
return FilterFunc(refNames, self.c.UserConfig().Gui.UseFuzzySearch())
|
||||
}
|
||||
|
||||
func (self *SuggestionsHelper) GetAuthorsSuggestionsFunc() func(string) []*types.Suggestion {
|
||||
@ -196,7 +196,7 @@ func (self *SuggestionsHelper) GetAuthorsSuggestionsFunc() func(string) []*types
|
||||
|
||||
slices.Sort(authors)
|
||||
|
||||
return FilterFunc(authors, self.c.UserConfig.Gui.UseFuzzySearch())
|
||||
return FilterFunc(authors, self.c.UserConfig().Gui.UseFuzzySearch())
|
||||
}
|
||||
|
||||
func FilterFunc(options []string, useFuzzySearch bool) func(string) []*types.Suggestion {
|
||||
|
@ -48,8 +48,8 @@ func (self *TagsHelper) OpenCreateTagPrompt(ref string, onCreate func()) error {
|
||||
self.c.Tr.ForceTagPrompt,
|
||||
map[string]string{
|
||||
"tagName": tagName,
|
||||
"cancelKey": self.c.UserConfig.Keybinding.Universal.Return,
|
||||
"confirmKey": self.c.UserConfig.Keybinding.Universal.Confirm,
|
||||
"cancelKey": self.c.UserConfig().Keybinding.Universal.Return,
|
||||
"confirmKey": self.c.UserConfig().Keybinding.Universal.Confirm,
|
||||
},
|
||||
)
|
||||
return self.c.Confirm(types.ConfirmOpts{
|
||||
|
@ -31,7 +31,7 @@ func (self *UpdateHelper) CheckForUpdateInBackground() {
|
||||
if newVersion == "" {
|
||||
return nil
|
||||
}
|
||||
if self.c.UserConfig.Update.Method == "background" {
|
||||
if self.c.UserConfig().Update.Method == "background" {
|
||||
self.startUpdating(newVersion)
|
||||
return nil
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ func (self *WindowArrangementHelper) GetWindowDimensions(informationStr string,
|
||||
args := WindowArrangementArgs{
|
||||
Width: width,
|
||||
Height: height,
|
||||
UserConfig: self.c.UserConfig,
|
||||
UserConfig: self.c.UserConfig(),
|
||||
CurrentWindow: self.windowHelper.CurrentWindow(),
|
||||
CurrentSideWindow: self.c.Context().CurrentSide().GetWindowName(),
|
||||
CurrentStaticWindow: self.c.Context().CurrentStatic().GetWindowName(),
|
||||
|
@ -136,7 +136,7 @@ func (self *WorkingTreeHelper) HandleCommitEditorPress() error {
|
||||
}
|
||||
|
||||
func (self *WorkingTreeHelper) HandleWIPCommitPress() error {
|
||||
skipHookPrefix := self.c.UserConfig.Git.SkipHookPrefix
|
||||
skipHookPrefix := self.c.UserConfig().Git.SkipHookPrefix
|
||||
if skipHookPrefix == "" {
|
||||
return errors.New(self.c.Tr.SkipHookPrefixNotConfigured)
|
||||
}
|
||||
@ -209,7 +209,7 @@ func (self *WorkingTreeHelper) syncRefresh() error {
|
||||
|
||||
func (self *WorkingTreeHelper) prepareFilesForCommit() error {
|
||||
noStagedFiles := !self.AnyStagedFiles()
|
||||
if noStagedFiles && self.c.UserConfig.Gui.SkipNoStagedFilesWarning {
|
||||
if noStagedFiles && self.c.UserConfig().Gui.SkipNoStagedFilesWarning {
|
||||
self.c.LogAction(self.c.Tr.Actions.StageAllFiles)
|
||||
err := self.c.Git().WorkingTree.StageAll()
|
||||
if err != nil {
|
||||
@ -223,10 +223,10 @@ func (self *WorkingTreeHelper) prepareFilesForCommit() error {
|
||||
}
|
||||
|
||||
func (self *WorkingTreeHelper) commitPrefixConfigForRepo() *config.CommitPrefixConfig {
|
||||
cfg, ok := self.c.UserConfig.Git.CommitPrefixes[self.c.Git().RepoPaths.RepoName()]
|
||||
cfg, ok := self.c.UserConfig().Git.CommitPrefixes[self.c.Git().RepoPaths.RepoName()]
|
||||
if ok {
|
||||
return &cfg
|
||||
}
|
||||
|
||||
return self.c.UserConfig.Git.CommitPrefix
|
||||
return self.c.UserConfig().Git.CommitPrefix
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func (self *ListController) HandleScrollRight() error {
|
||||
}
|
||||
|
||||
func (self *ListController) HandleScrollUp() error {
|
||||
scrollHeight := self.c.UserConfig.Gui.ScrollHeight
|
||||
scrollHeight := self.c.UserConfig().Gui.ScrollHeight
|
||||
self.context.GetViewTrait().ScrollUp(scrollHeight)
|
||||
if self.context.RenderOnlyVisibleLines() {
|
||||
return self.context.HandleRender()
|
||||
@ -61,7 +61,7 @@ func (self *ListController) HandleScrollUp() error {
|
||||
}
|
||||
|
||||
func (self *ListController) HandleScrollDown() error {
|
||||
scrollHeight := self.c.UserConfig.Gui.ScrollHeight
|
||||
scrollHeight := self.c.UserConfig().Gui.ScrollHeight
|
||||
self.context.GetViewTrait().ScrollDown(scrollHeight)
|
||||
if self.context.RenderOnlyVisibleLines() {
|
||||
return self.context.HandleRender()
|
||||
@ -106,10 +106,10 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error {
|
||||
cursorMoved := before != after
|
||||
if cursorMoved {
|
||||
if change == -1 {
|
||||
checkScrollUp(self.context.GetViewTrait(), self.c.UserConfig,
|
||||
checkScrollUp(self.context.GetViewTrait(), self.c.UserConfig(),
|
||||
self.context.ModelIndexToViewIndex(before), self.context.ModelIndexToViewIndex(after))
|
||||
} else if change == 1 {
|
||||
checkScrollDown(self.context.GetViewTrait(), self.c.UserConfig,
|
||||
checkScrollDown(self.context.GetViewTrait(), self.c.UserConfig(),
|
||||
self.context.ModelIndexToViewIndex(before), self.context.ModelIndexToViewIndex(after))
|
||||
}
|
||||
}
|
||||
|
@ -357,8 +357,8 @@ func (self *LocalCommitsController) reword(commit *models.Commit) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
|
||||
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
|
||||
if self.c.UserConfig().Git.Commit.AutoWrapCommitMessage {
|
||||
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig().Git.Commit.AutoWrapWidth)
|
||||
}
|
||||
return self.c.Helpers().Commits.OpenCommitMessagePanel(
|
||||
&helpers.OpenCommitMessagePanelOpts{
|
||||
@ -438,7 +438,7 @@ func (self *LocalCommitsController) doRewordEditor() error {
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) rewordEditor(commit *models.Commit) error {
|
||||
if self.c.UserConfig.Gui.SkipRewordInEditorWarning {
|
||||
if self.c.UserConfig().Gui.SkipRewordInEditorWarning {
|
||||
return self.doRewordEditor()
|
||||
} else {
|
||||
return self.c.Confirm(types.ConfirmOpts{
|
||||
@ -564,7 +564,7 @@ func (self *LocalCommitsController) findCommitForQuickStartInteractiveRebase() (
|
||||
|
||||
if !ok || index == 0 {
|
||||
errorMsg := utils.ResolvePlaceholderString(self.c.Tr.CannotQuickStartInteractiveRebase, map[string]string{
|
||||
"editKey": keybindings.Label(self.c.UserConfig.Keybinding.Universal.Edit),
|
||||
"editKey": keybindings.Label(self.c.UserConfig().Keybinding.Universal.Edit),
|
||||
})
|
||||
|
||||
return nil, errors.New(errorMsg)
|
||||
@ -905,8 +905,8 @@ func (self *LocalCommitsController) createAmendCommit(commit *models.Commit, inc
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
|
||||
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
|
||||
if self.c.UserConfig().Git.Commit.AutoWrapCommitMessage {
|
||||
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig().Git.Commit.AutoWrapWidth)
|
||||
}
|
||||
originalSubject, _, _ := strings.Cut(commitMessage, "\n")
|
||||
return self.c.Helpers().Commits.OpenCommitMessagePanel(
|
||||
|
@ -173,14 +173,14 @@ func (self *MergeConflictsController) GetOnFocusLost() func(types.OnFocusLostOpt
|
||||
|
||||
func (self *MergeConflictsController) HandleScrollUp() error {
|
||||
self.context().SetUserScrolling(true)
|
||||
self.context().GetViewTrait().ScrollUp(self.c.UserConfig.Gui.ScrollHeight)
|
||||
self.context().GetViewTrait().ScrollUp(self.c.UserConfig().Gui.ScrollHeight)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) HandleScrollDown() error {
|
||||
self.context().SetUserScrolling(true)
|
||||
self.context().GetViewTrait().ScrollDown(self.c.UserConfig.Gui.ScrollHeight)
|
||||
self.context().GetViewTrait().ScrollDown(self.c.UserConfig().Gui.ScrollHeight)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ func (self *PatchExplorerController) HandlePrevLine() error {
|
||||
after := self.context.GetState().GetSelectedLineIdx()
|
||||
|
||||
if self.context.GetState().SelectingLine() {
|
||||
checkScrollUp(self.context.GetViewTrait(), self.c.UserConfig, before, after)
|
||||
checkScrollUp(self.context.GetViewTrait(), self.c.UserConfig(), before, after)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -185,7 +185,7 @@ func (self *PatchExplorerController) HandleNextLine() error {
|
||||
after := self.context.GetState().GetSelectedLineIdx()
|
||||
|
||||
if self.context.GetState().SelectingLine() {
|
||||
checkScrollDown(self.context.GetViewTrait(), self.c.UserConfig, before, after)
|
||||
checkScrollDown(self.context.GetViewTrait(), self.c.UserConfig(), before, after)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -25,7 +25,7 @@ func (self *QuitActions) quitAux() error {
|
||||
return self.confirmQuitDuringUpdate()
|
||||
}
|
||||
|
||||
if self.c.UserConfig.ConfirmOnQuit {
|
||||
if self.c.UserConfig().ConfirmOnQuit {
|
||||
return self.c.Confirm(types.ConfirmOpts{
|
||||
Title: "",
|
||||
Prompt: self.c.Tr.ConfirmQuit,
|
||||
@ -88,7 +88,7 @@ func (self *QuitActions) Escape() error {
|
||||
return self.c.Helpers().Repos.DispatchSwitchToRepo(repoPathStack.Pop(), context.NO_CONTEXT)
|
||||
}
|
||||
|
||||
if self.c.UserConfig.QuitOnTopLevelReturn {
|
||||
if self.c.UserConfig().QuitOnTopLevelReturn {
|
||||
return self.Quit()
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ func (self *ShellCommandAction) GetShellCommandsHistorySuggestionsFunc() func(st
|
||||
return func(input string) []*types.Suggestion {
|
||||
history := self.c.GetAppState().ShellCommandsHistory
|
||||
|
||||
return helpers.FilterFunc(history, self.c.UserConfig.Gui.UseFuzzySearch())(input)
|
||||
return helpers.FilterFunc(history, self.c.UserConfig().Gui.UseFuzzySearch())(input)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ func (self *StagingController) ToggleStaged() error {
|
||||
func (self *StagingController) DiscardSelection() error {
|
||||
reset := func() error { return self.applySelectionAndRefresh(true) }
|
||||
|
||||
if !self.staged && !self.c.UserConfig.Gui.SkipDiscardChangeWarning {
|
||||
if !self.staged && !self.c.UserConfig().Gui.SkipDiscardChangeWarning {
|
||||
return self.c.Confirm(types.ConfirmOpts{
|
||||
Title: self.c.Tr.DiscardChangeTitle,
|
||||
Prompt: self.c.Tr.DiscardChangePrompt,
|
||||
|
@ -114,7 +114,7 @@ func (self *StashController) handleStashApply(stashEntry *models.StashEntry) err
|
||||
return nil
|
||||
}
|
||||
|
||||
if self.c.UserConfig.Gui.SkipStashWarning {
|
||||
if self.c.UserConfig().Gui.SkipStashWarning {
|
||||
return apply()
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ func (self *StashController) handleStashPop(stashEntry *models.StashEntry) error
|
||||
return nil
|
||||
}
|
||||
|
||||
if self.c.UserConfig.Gui.SkipStashWarning {
|
||||
if self.c.UserConfig().Gui.SkipStashWarning {
|
||||
return pop()
|
||||
}
|
||||
|
||||
|
@ -89,15 +89,15 @@ func (self *StatusController) onClickMain(opts gocui.ViewMouseBindingOpts) error
|
||||
}
|
||||
|
||||
func (self *StatusController) GetOnRenderToMain() func() error {
|
||||
config := self.c.UserConfig.Gui
|
||||
|
||||
switch config.StatusPanelView {
|
||||
case "dashboard":
|
||||
return self.showDashboard
|
||||
case "allBranchesLog":
|
||||
return self.showAllBranchLogs
|
||||
default:
|
||||
return self.showDashboard
|
||||
return func() error {
|
||||
switch self.c.UserConfig().Gui.StatusPanelView {
|
||||
case "dashboard":
|
||||
return self.showDashboard()
|
||||
case "allBranchesLog":
|
||||
return self.showAllBranchLogs()
|
||||
default:
|
||||
return self.showDashboard()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ func (self *StatusController) onClick(opts gocui.ViewMouseBindingOpts) error {
|
||||
return err
|
||||
}
|
||||
|
||||
upstreamStatus := utils.Decolorise(presentation.BranchStatus(currentBranch, types.ItemOperationNone, self.c.Tr, time.Now(), self.c.UserConfig))
|
||||
upstreamStatus := utils.Decolorise(presentation.BranchStatus(currentBranch, types.ItemOperationNone, self.c.Tr, time.Now(), self.c.UserConfig()))
|
||||
repoName := self.c.Git().RepoPaths.RepoName()
|
||||
workingTreeState := self.c.Git().Status.WorkingTreeState()
|
||||
switch workingTreeState {
|
||||
|
@ -210,7 +210,7 @@ func (self *SyncController) pushAux(currentBranch *models.Branch, opts pushOpts)
|
||||
return errors.New(self.c.Tr.UpdatesRejected)
|
||||
}
|
||||
|
||||
forcePushDisabled := self.c.UserConfig.Git.DisableForcePushing
|
||||
forcePushDisabled := self.c.UserConfig().Git.DisableForcePushing
|
||||
if forcePushDisabled {
|
||||
return errors.New(self.c.Tr.UpdatesRejectedAndForcePushDisabled)
|
||||
}
|
||||
@ -233,7 +233,7 @@ func (self *SyncController) pushAux(currentBranch *models.Branch, opts pushOpts)
|
||||
}
|
||||
|
||||
func (self *SyncController) requestToForcePush(currentBranch *models.Branch, opts pushOpts) error {
|
||||
forcePushDisabled := self.c.UserConfig.Git.DisableForcePushing
|
||||
forcePushDisabled := self.c.UserConfig().Git.DisableForcePushing
|
||||
if forcePushDisabled {
|
||||
return errors.New(self.c.Tr.ForcePushDisabled)
|
||||
}
|
||||
@ -252,8 +252,8 @@ func (self *SyncController) forcePushPrompt() string {
|
||||
return utils.ResolvePlaceholderString(
|
||||
self.c.Tr.ForcePushPrompt,
|
||||
map[string]string{
|
||||
"cancelKey": self.c.UserConfig.Keybinding.Universal.Return,
|
||||
"confirmKey": self.c.UserConfig.Keybinding.Universal.Confirm,
|
||||
"cancelKey": self.c.UserConfig().Keybinding.Universal.Return,
|
||||
"confirmKey": self.c.UserConfig().Keybinding.Universal.Confirm,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -65,13 +65,13 @@ func (self *VerticalScrollController) GetMouseKeybindings(opts types.Keybindings
|
||||
}
|
||||
|
||||
func (self *VerticalScrollController) HandleScrollUp() error {
|
||||
self.context.GetViewTrait().ScrollUp(self.c.UserConfig.Gui.ScrollHeight)
|
||||
self.context.GetViewTrait().ScrollUp(self.c.UserConfig().Gui.ScrollHeight)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *VerticalScrollController) HandleScrollDown() error {
|
||||
scrollHeight := self.c.UserConfig.Gui.ScrollHeight
|
||||
scrollHeight := self.c.UserConfig().Gui.ScrollHeight
|
||||
self.context.GetViewTrait().ScrollDown(scrollHeight)
|
||||
|
||||
if manager, ok := (*self.viewBufferManagerMap)[self.context.GetViewName()]; ok {
|
||||
|
@ -35,7 +35,7 @@ func (self *FilesController) createResetMenu() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if self.c.UserConfig.Gui.AnimateExplosion {
|
||||
if self.c.UserConfig().Gui.AnimateExplosion {
|
||||
self.animateExplosion()
|
||||
}
|
||||
|
||||
|
@ -13,11 +13,11 @@ import (
|
||||
const HORIZONTAL_SCROLL_FACTOR = 3
|
||||
|
||||
func (gui *Gui) scrollUpView(view *gocui.View) {
|
||||
view.ScrollUp(gui.c.UserConfig.Gui.ScrollHeight)
|
||||
view.ScrollUp(gui.c.UserConfig().Gui.ScrollHeight)
|
||||
}
|
||||
|
||||
func (gui *Gui) scrollDownView(view *gocui.View) {
|
||||
scrollHeight := gui.c.UserConfig.Gui.ScrollHeight
|
||||
scrollHeight := gui.c.UserConfig().Gui.ScrollHeight
|
||||
view.ScrollDown(scrollHeight)
|
||||
|
||||
if manager, ok := gui.viewBufferManagerMap[view.Name()]; ok {
|
||||
@ -123,7 +123,7 @@ func (gui *Gui) handleCopySelectedSideContextItemToClipboard() error {
|
||||
|
||||
func (gui *Gui) handleCopySelectedSideContextItemCommitHashToClipboard() error {
|
||||
return gui.handleCopySelectedSideContextItemToClipboardWithTruncation(
|
||||
gui.UserConfig.Git.TruncateCopiedCommitHashesTo)
|
||||
gui.UserConfig().Git.TruncateCopiedCommitHashesTo)
|
||||
}
|
||||
|
||||
func (gui *Gui) handleCopySelectedSideContextItemToClipboardWithTruncation(maxWidth int) error {
|
||||
|
194
pkg/gui/gui.go
194
pkg/gui/gui.go
@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -35,6 +37,7 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/status"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/tasks"
|
||||
@ -137,6 +140,8 @@ type Gui struct {
|
||||
c *helpers.HelperCommon
|
||||
helpers *helpers.Helpers
|
||||
|
||||
previousLanguageConfig string
|
||||
|
||||
integrationTest integrationTypes.IntegrationTest
|
||||
|
||||
afterLayoutFuncs chan func() error
|
||||
@ -307,6 +312,16 @@ func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, contextKey types.Context
|
||||
return err
|
||||
}
|
||||
|
||||
err = gui.Config.ReloadUserConfigForRepo(gui.getPerRepoConfigFiles())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = gui.onUserConfigLoaded()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
contextToPush := gui.resetState(startArgs)
|
||||
|
||||
gui.resetHelpersAndControllers()
|
||||
@ -317,8 +332,28 @@ func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, contextKey types.Context
|
||||
|
||||
gui.g.SetFocusHandler(func(Focused bool) error {
|
||||
if Focused {
|
||||
oldConfig := gui.Config.GetUserConfig()
|
||||
reloadErr, didChange := gui.Config.ReloadChangedUserConfigFiles()
|
||||
if didChange && reloadErr == nil {
|
||||
gui.c.Log.Info("User config changed - reloading")
|
||||
reloadErr = gui.onUserConfigLoaded()
|
||||
if err := gui.resetKeybindings(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := gui.checkForChangedConfigsThatDontAutoReload(oldConfig, gui.Config.GetUserConfig()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
gui.c.Log.Info("Receiving focus - refreshing")
|
||||
return gui.helpers.Refresh.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
refreshErr := gui.helpers.Refresh.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
if reloadErr != nil {
|
||||
// An error from reloading the config is the more important one
|
||||
// to report to the user
|
||||
return reloadErr
|
||||
}
|
||||
return refreshErr
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -342,6 +377,119 @@ func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, contextKey types.Context
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) getPerRepoConfigFiles() []*config.ConfigFile {
|
||||
repoConfigFiles := []*config.ConfigFile{
|
||||
// TODO: add filepath.Join(gui.git.RepoPaths.RepoPath(), ".lazygit.yml"),
|
||||
// with trust prompt
|
||||
{
|
||||
Path: filepath.Join(gui.git.RepoPaths.RepoGitDirPath(), "lazygit.yml"),
|
||||
Policy: config.ConfigFilePolicySkipIfMissing,
|
||||
},
|
||||
}
|
||||
|
||||
prevDir := gui.c.Git().RepoPaths.RepoPath()
|
||||
dir := filepath.Dir(prevDir)
|
||||
for dir != prevDir {
|
||||
repoConfigFiles = utils.Prepend(repoConfigFiles, &config.ConfigFile{
|
||||
Path: filepath.Join(dir, ".lazygit.yml"),
|
||||
Policy: config.ConfigFilePolicySkipIfMissing,
|
||||
})
|
||||
prevDir = dir
|
||||
dir = filepath.Dir(dir)
|
||||
}
|
||||
return repoConfigFiles
|
||||
}
|
||||
|
||||
func (gui *Gui) onUserConfigLoaded() error {
|
||||
userConfig := gui.Config.GetUserConfig()
|
||||
gui.Common.SetUserConfig(userConfig)
|
||||
|
||||
gui.setColorScheme()
|
||||
gui.configureViewProperties()
|
||||
|
||||
gui.g.SearchEscapeKey = keybindings.GetKey(userConfig.Keybinding.Universal.Return)
|
||||
gui.g.NextSearchMatchKey = keybindings.GetKey(userConfig.Keybinding.Universal.NextMatch)
|
||||
gui.g.PrevSearchMatchKey = keybindings.GetKey(userConfig.Keybinding.Universal.PrevMatch)
|
||||
|
||||
gui.g.ShowListFooter = userConfig.Gui.ShowListFooter
|
||||
|
||||
gui.g.Mouse = userConfig.Gui.MouseEvents
|
||||
|
||||
if gui.previousLanguageConfig != userConfig.Gui.Language {
|
||||
tr, err := i18n.NewTranslationSetFromConfig(gui.Log, userConfig.Gui.Language)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gui.c.Tr = tr
|
||||
gui.previousLanguageConfig = userConfig.Gui.Language
|
||||
}
|
||||
|
||||
// originally we could only hide the command log permanently via the config
|
||||
// but now we do it via state. So we need to still support the config for the
|
||||
// sake of backwards compatibility. We're making use of short circuiting here
|
||||
gui.ShowExtrasWindow = userConfig.Gui.ShowCommandLog && !gui.c.GetAppState().HideCommandLog
|
||||
|
||||
authors.SetCustomAuthors(userConfig.Gui.AuthorColors)
|
||||
if userConfig.Gui.NerdFontsVersion != "" {
|
||||
icons.SetNerdFontsVersion(userConfig.Gui.NerdFontsVersion)
|
||||
} else if userConfig.Gui.ShowIcons {
|
||||
icons.SetNerdFontsVersion("2")
|
||||
}
|
||||
presentation.SetCustomBranches(userConfig.Gui.BranchColors)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) checkForChangedConfigsThatDontAutoReload(oldConfig *config.UserConfig, newConfig *config.UserConfig) error {
|
||||
configsThatDontAutoReload := []string{
|
||||
"Git.AutoFetch",
|
||||
"Git.AutoRefresh",
|
||||
"Refresher.RefreshInterval",
|
||||
"Refresher.FetchInterval",
|
||||
"Update.Method",
|
||||
"Update.Days",
|
||||
}
|
||||
|
||||
changedConfigs := []string{}
|
||||
for _, config := range configsThatDontAutoReload {
|
||||
old := reflect.ValueOf(oldConfig).Elem()
|
||||
new := reflect.ValueOf(newConfig).Elem()
|
||||
fieldNames := strings.Split(config, ".")
|
||||
userFacingPath := make([]string, 0, len(fieldNames))
|
||||
// navigate to the leaves in old and new config
|
||||
for _, fieldName := range fieldNames {
|
||||
f, _ := old.Type().FieldByName(fieldName)
|
||||
userFacingName := f.Tag.Get("yaml")
|
||||
if userFacingName == "" {
|
||||
userFacingName = fieldName
|
||||
}
|
||||
userFacingPath = append(userFacingPath, userFacingName)
|
||||
old = old.FieldByName(fieldName)
|
||||
new = new.FieldByName(fieldName)
|
||||
}
|
||||
// if the value has changed, ...
|
||||
if !old.Equal(new) {
|
||||
// ... append it to the list of changed configs
|
||||
changedConfigs = append(changedConfigs, strings.Join(userFacingPath, "."))
|
||||
}
|
||||
}
|
||||
|
||||
if len(changedConfigs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
message := utils.ResolvePlaceholderString(
|
||||
gui.c.Tr.NonReloadableConfigWarning,
|
||||
map[string]string{
|
||||
"configs": strings.Join(changedConfigs, "\n"),
|
||||
},
|
||||
)
|
||||
return gui.c.Confirm(types.ConfirmOpts{
|
||||
Title: gui.c.Tr.NonReloadableConfigWarningTitle,
|
||||
Prompt: message,
|
||||
})
|
||||
}
|
||||
|
||||
// resetState reuses the repo state from our repo state map, if the repo was
|
||||
// open before; otherwise it creates a new one.
|
||||
func (gui *Gui) resetState(startArgs appTypes.StartArgs) types.Context {
|
||||
@ -379,7 +527,7 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs) types.Context {
|
||||
BisectInfo: git_commands.NewNullBisectInfo(),
|
||||
FilesTrie: patricia.NewTrie(),
|
||||
Authors: map[string]*models.Author{},
|
||||
MainBranches: git_commands.NewMainBranches(gui.UserConfig.Git.MainBranches, gui.os.Cmd),
|
||||
MainBranches: git_commands.NewMainBranches(gui.c.Common, gui.os.Cmd),
|
||||
},
|
||||
Modes: &types.Modes{
|
||||
Filtering: filtering.New(startArgs.FilterPath, ""),
|
||||
@ -478,10 +626,10 @@ func NewGui(
|
||||
RepoStateMap: map[Repo]*GuiRepoState{},
|
||||
GuiLog: []string{},
|
||||
|
||||
// originally we could only hide the command log permanently via the config
|
||||
// but now we do it via state. So we need to still support the config for the
|
||||
// sake of backwards compatibility. We're making use of short circuiting here
|
||||
ShowExtrasWindow: cmn.UserConfig.Gui.ShowCommandLog && !config.GetAppState().HideCommandLog,
|
||||
// initializing this to true for the time being; it will be reset to the
|
||||
// real value after loading the user config:
|
||||
ShowExtrasWindow: true,
|
||||
|
||||
Mutexes: types.Mutexes{
|
||||
RefreshingFilesMutex: &deadlock.Mutex{},
|
||||
RefreshingBranchesMutex: &deadlock.Mutex{},
|
||||
@ -538,14 +686,6 @@ func NewGui(
|
||||
// TODO: reset these controllers upon changing repos due to state changing
|
||||
gui.c = helperCommon
|
||||
|
||||
authors.SetCustomAuthors(gui.UserConfig.Gui.AuthorColors)
|
||||
if gui.UserConfig.Gui.NerdFontsVersion != "" {
|
||||
icons.SetNerdFontsVersion(gui.UserConfig.Gui.NerdFontsVersion)
|
||||
} else if gui.UserConfig.Gui.ShowIcons {
|
||||
icons.SetNerdFontsVersion("2")
|
||||
}
|
||||
presentation.SetCustomBranches(gui.UserConfig.Gui.BranchColors)
|
||||
|
||||
gui.BackgroundRoutineMgr = &BackgroundRoutineMgr{gui: gui}
|
||||
gui.stateAccessor = &StateAccessor{gui: gui}
|
||||
|
||||
@ -658,25 +798,7 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error {
|
||||
// breakpoints and stepping through code can easily take more than 30s.
|
||||
deadlock.Opts.Disable = !gui.Debug || os.Getenv(components.WAIT_FOR_DEBUGGER_ENV_VAR) != ""
|
||||
|
||||
if err := gui.Config.ReloadUserConfig(); err != nil {
|
||||
return nil
|
||||
}
|
||||
userConfig := gui.UserConfig
|
||||
|
||||
gui.g.OnSearchEscape = func() error { gui.helpers.Search.Cancel(); return nil }
|
||||
gui.g.SearchEscapeKey = keybindings.GetKey(userConfig.Keybinding.Universal.Return)
|
||||
gui.g.NextSearchMatchKey = keybindings.GetKey(userConfig.Keybinding.Universal.NextMatch)
|
||||
gui.g.PrevSearchMatchKey = keybindings.GetKey(userConfig.Keybinding.Universal.PrevMatch)
|
||||
|
||||
gui.g.ShowListFooter = userConfig.Gui.ShowListFooter
|
||||
|
||||
if userConfig.Gui.MouseEvents {
|
||||
gui.g.Mouse = true
|
||||
}
|
||||
|
||||
if err := gui.setColorScheme(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gui.g.SetManager(gocui.ManagerFunc(gui.layout))
|
||||
|
||||
@ -735,7 +857,7 @@ func (gui *Gui) RunAndHandleError(startArgs appTypes.StartArgs) error {
|
||||
}
|
||||
|
||||
func (gui *Gui) checkForDeprecatedEditConfigs() {
|
||||
osConfig := &gui.UserConfig.OS
|
||||
osConfig := &gui.UserConfig().OS
|
||||
deprecatedConfigs := []struct {
|
||||
config string
|
||||
oldName string
|
||||
@ -934,16 +1056,14 @@ func (gui *Gui) showBreakingChangesMessage() {
|
||||
}
|
||||
|
||||
// setColorScheme sets the color scheme for the app based on the user config
|
||||
func (gui *Gui) setColorScheme() error {
|
||||
userConfig := gui.UserConfig
|
||||
func (gui *Gui) setColorScheme() {
|
||||
userConfig := gui.UserConfig()
|
||||
theme.UpdateTheme(userConfig.Gui.Theme)
|
||||
|
||||
gui.g.FgColor = theme.InactiveBorderColor
|
||||
gui.g.SelFgColor = theme.ActiveBorderColor
|
||||
gui.g.FrameColor = theme.InactiveBorderColor
|
||||
gui.g.SelFrameColor = theme.ActiveBorderColor
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) onUIThread(f func() error) {
|
||||
|
@ -60,7 +60,7 @@ func (self *Gui) GetCheatsheetKeybindings() []*types.Binding {
|
||||
}
|
||||
|
||||
func (self *Gui) keybindingOpts() types.KeybindingsOpts {
|
||||
config := self.c.UserConfig.Keybinding
|
||||
config := self.c.UserConfig().Keybinding
|
||||
|
||||
guards := types.KeybindingGuards{
|
||||
OutsideFilterMode: self.outsideFilterMode,
|
||||
|
@ -260,7 +260,7 @@ func (gui *Gui) onRepoViewReset() error {
|
||||
}
|
||||
|
||||
func (gui *Gui) onInitialViewsCreation() error {
|
||||
if !gui.c.UserConfig.DisableStartupPopups {
|
||||
if !gui.c.UserConfig().DisableStartupPopups {
|
||||
storedPopupVersion := gui.c.GetAppState().StartupPopupVersion
|
||||
if storedPopupVersion < StartupPopupVersion {
|
||||
gui.showIntroPopupMessage()
|
||||
|
@ -324,7 +324,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
||||
|
||||
for i, s := range scenarios {
|
||||
icons.SetNerdFontsVersion(lo.Ternary(s.useIcons, "3", ""))
|
||||
c.UserConfig.Gui.ShowDivergenceFromBaseBranch = s.showDivergenceCfg
|
||||
c.UserConfig().Gui.ShowDivergenceFromBaseBranch = s.showDivergenceCfg
|
||||
|
||||
worktrees := []*models.Worktree{}
|
||||
if s.checkedOutByWorktree {
|
||||
@ -332,7 +332,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run(fmt.Sprintf("getBranchDisplayStrings_%d", i), func(t *testing.T) {
|
||||
strings := getBranchDisplayStrings(s.branch, s.itemOperation, s.fullDescription, false, s.viewWidth, c.Tr, c.UserConfig, worktrees, time.Time{})
|
||||
strings := getBranchDisplayStrings(s.branch, s.itemOperation, s.fullDescription, false, s.viewWidth, c.Tr, c.UserConfig(), worktrees, time.Time{})
|
||||
assert.Equal(t, s.expected, strings)
|
||||
})
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ func GetCommitListDisplayStrings(
|
||||
// Don't show a marker for the current branch
|
||||
b.Name != currentBranchName &&
|
||||
// Don't show a marker for main branches
|
||||
!lo.Contains(common.UserConfig.Git.MainBranches, b.Name) &&
|
||||
!lo.Contains(common.UserConfig().Git.MainBranches, b.Name) &&
|
||||
// Don't show a marker for the head commit unless the
|
||||
// rebase.updateRefs config is on
|
||||
(hasRebaseUpdateRefsConfig || b.CommitHash != commits[0].Hash)
|
||||
@ -370,7 +370,7 @@ func displayCommit(
|
||||
|
||||
hashString := ""
|
||||
hashColor := getHashColor(commit, diffName, cherryPickedCommitHashSet, bisectStatus, bisectInfo)
|
||||
hashLength := common.UserConfig.Gui.CommitHashLength
|
||||
hashLength := common.UserConfig().Gui.CommitHashLength
|
||||
if hashLength >= len(commit.Hash) {
|
||||
hashString = hashColor.Sprint(commit.Hash)
|
||||
} else if hashLength > 0 {
|
||||
@ -440,9 +440,9 @@ func displayCommit(
|
||||
mark = fmt.Sprintf("%s ", willBeRebased)
|
||||
}
|
||||
|
||||
authorLength := common.UserConfig.Gui.CommitAuthorShortLength
|
||||
authorLength := common.UserConfig().Gui.CommitAuthorShortLength
|
||||
if fullDescription {
|
||||
authorLength = common.UserConfig.Gui.CommitAuthorLongLength
|
||||
authorLength = common.UserConfig().Gui.CommitAuthorLongLength
|
||||
}
|
||||
author := authors.AuthorWithLength(commit.AuthorName, authorLength)
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
@ -9,7 +9,7 @@ import (
|
||||
// Client is the entry point to this package. It returns a list of keybindings based on the config's user-defined custom commands.
|
||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Command_Keybindings.md for more info.
|
||||
type Client struct {
|
||||
customCommands []config.CustomCommand
|
||||
c *common.Common
|
||||
handlerCreator *HandlerCreator
|
||||
keybindingCreator *KeybindingCreator
|
||||
}
|
||||
@ -26,10 +26,9 @@ func NewClient(
|
||||
helpers.MergeAndRebase,
|
||||
)
|
||||
keybindingCreator := NewKeybindingCreator(c)
|
||||
customCommands := c.UserConfig.CustomCommands
|
||||
|
||||
return &Client{
|
||||
customCommands: customCommands,
|
||||
c: c.Common,
|
||||
keybindingCreator: keybindingCreator,
|
||||
handlerCreator: handlerCreator,
|
||||
}
|
||||
@ -37,7 +36,7 @@ func NewClient(
|
||||
|
||||
func (self *Client) GetCustomCommandKeybindings() ([]*types.Binding, error) {
|
||||
bindings := []*types.Binding{}
|
||||
for _, customCommand := range self.customCommands {
|
||||
for _, customCommand := range self.c.UserConfig().CustomCommands {
|
||||
handler := self.handlerCreator.call(customCommand)
|
||||
compoundBindings, err := self.keybindingCreator.call(customCommand, handler)
|
||||
if err != nil {
|
||||
|
@ -73,26 +73,12 @@ func (gui *Gui) orderedViewNameMappings() []viewNameMapping {
|
||||
}
|
||||
|
||||
func (gui *Gui) createAllViews() error {
|
||||
frameRunes := []rune{'─', '│', '┌', '┐', '└', '┘'}
|
||||
switch gui.c.UserConfig.Gui.Border {
|
||||
case "double":
|
||||
frameRunes = []rune{'═', '║', '╔', '╗', '╚', '╝'}
|
||||
case "rounded":
|
||||
frameRunes = []rune{'─', '│', '╭', '╮', '╰', '╯'}
|
||||
case "hidden":
|
||||
frameRunes = []rune{' ', ' ', ' ', ' ', ' ', ' '}
|
||||
}
|
||||
|
||||
var err error
|
||||
for _, mapping := range gui.orderedViewNameMappings() {
|
||||
*mapping.viewPtr, err = gui.prepareView(mapping.name)
|
||||
if err != nil && !gocui.IsUnknownView(err) {
|
||||
return err
|
||||
}
|
||||
(*mapping.viewPtr).FrameRunes = frameRunes
|
||||
(*mapping.viewPtr).FgColor = theme.GocuiDefaultTextColor
|
||||
(*mapping.viewPtr).SelBgColor = theme.GocuiSelectedLineBgColor
|
||||
(*mapping.viewPtr).InactiveViewSelBgColor = theme.GocuiInactiveViewSelectedLineBgColor
|
||||
}
|
||||
|
||||
gui.Views.Options.Frame = false
|
||||
@ -131,7 +117,6 @@ func (gui *Gui) createAllViews() error {
|
||||
view.Title = gui.c.Tr.DiffTitle
|
||||
view.Wrap = true
|
||||
view.IgnoreCarriageReturns = true
|
||||
view.CanScrollPastBottom = gui.c.UserConfig.Gui.ScrollPastBottom
|
||||
}
|
||||
|
||||
gui.Views.Staging.Title = gui.c.Tr.UnstagedChanges
|
||||
@ -166,11 +151,8 @@ func (gui *Gui) createAllViews() error {
|
||||
|
||||
gui.Views.CommitDescription.Visible = false
|
||||
gui.Views.CommitDescription.Title = gui.c.Tr.CommitDescriptionTitle
|
||||
gui.Views.CommitDescription.FgColor = theme.GocuiDefaultTextColor
|
||||
gui.Views.CommitDescription.Editable = true
|
||||
gui.Views.CommitDescription.Editor = gocui.EditorFunc(gui.commitDescriptionEditor)
|
||||
gui.Views.CommitDescription.TextArea.AutoWrap = gui.c.UserConfig.Git.Commit.AutoWrapCommitMessage
|
||||
gui.Views.CommitDescription.TextArea.AutoWrapWidth = gui.c.UserConfig.Git.Commit.AutoWrapWidth
|
||||
|
||||
gui.Views.Confirmation.Visible = false
|
||||
gui.Views.Confirmation.Editor = gocui.EditorFunc(gui.promptEditor)
|
||||
@ -192,8 +174,39 @@ func (gui *Gui) createAllViews() error {
|
||||
gui.Views.Snake.Title = gui.c.Tr.SnakeTitle
|
||||
gui.Views.Snake.FgColor = gocui.ColorGreen
|
||||
|
||||
if gui.c.UserConfig.Gui.ShowPanelJumps {
|
||||
jumpBindings := gui.c.UserConfig.Keybinding.Universal.JumpToBlock
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) configureViewProperties() {
|
||||
frameRunes := []rune{'─', '│', '┌', '┐', '└', '┘'}
|
||||
switch gui.c.UserConfig().Gui.Border {
|
||||
case "double":
|
||||
frameRunes = []rune{'═', '║', '╔', '╗', '╚', '╝'}
|
||||
case "rounded":
|
||||
frameRunes = []rune{'─', '│', '╭', '╮', '╰', '╯'}
|
||||
case "hidden":
|
||||
frameRunes = []rune{' ', ' ', ' ', ' ', ' ', ' '}
|
||||
}
|
||||
|
||||
for _, mapping := range gui.orderedViewNameMappings() {
|
||||
(*mapping.viewPtr).FrameRunes = frameRunes
|
||||
(*mapping.viewPtr).BgColor = gui.g.BgColor
|
||||
(*mapping.viewPtr).FgColor = theme.GocuiDefaultTextColor
|
||||
(*mapping.viewPtr).SelBgColor = theme.GocuiSelectedLineBgColor
|
||||
(*mapping.viewPtr).SelFgColor = gui.g.SelFgColor
|
||||
(*mapping.viewPtr).InactiveViewSelBgColor = theme.GocuiInactiveViewSelectedLineBgColor
|
||||
}
|
||||
|
||||
for _, view := range []*gocui.View{gui.Views.Main, gui.Views.Secondary, gui.Views.Staging, gui.Views.StagingSecondary, gui.Views.PatchBuilding, gui.Views.PatchBuildingSecondary, gui.Views.MergeConflicts} {
|
||||
view.CanScrollPastBottom = gui.c.UserConfig().Gui.ScrollPastBottom
|
||||
}
|
||||
|
||||
gui.Views.CommitDescription.FgColor = theme.GocuiDefaultTextColor
|
||||
gui.Views.CommitDescription.TextArea.AutoWrap = gui.c.UserConfig().Git.Commit.AutoWrapCommitMessage
|
||||
gui.Views.CommitDescription.TextArea.AutoWrapWidth = gui.c.UserConfig().Git.Commit.AutoWrapWidth
|
||||
|
||||
if gui.c.UserConfig().Gui.ShowPanelJumps {
|
||||
jumpBindings := gui.c.UserConfig().Keybinding.Universal.JumpToBlock
|
||||
jumpLabels := lo.Map(jumpBindings, func(binding string, _ int) string {
|
||||
return fmt.Sprintf("[%s]", binding)
|
||||
})
|
||||
@ -212,7 +225,20 @@ func (gui *Gui) createAllViews() error {
|
||||
gui.Views.ReflogCommits.TitlePrefix = jumpLabels[3]
|
||||
|
||||
gui.Views.Stash.TitlePrefix = jumpLabels[4]
|
||||
}
|
||||
} else {
|
||||
gui.Views.Status.TitlePrefix = ""
|
||||
|
||||
return nil
|
||||
gui.Views.Files.TitlePrefix = ""
|
||||
gui.Views.Worktrees.TitlePrefix = ""
|
||||
gui.Views.Submodules.TitlePrefix = ""
|
||||
|
||||
gui.Views.Branches.TitlePrefix = ""
|
||||
gui.Views.Remotes.TitlePrefix = ""
|
||||
gui.Views.Tags.TitlePrefix = ""
|
||||
|
||||
gui.Views.Commits.TitlePrefix = ""
|
||||
gui.Views.ReflogCommits.TitlePrefix = ""
|
||||
|
||||
gui.Views.Stash.TitlePrefix = ""
|
||||
}
|
||||
}
|
||||
|
@ -225,6 +225,8 @@ type TranslationSet struct {
|
||||
MergeToolPrompt string
|
||||
IntroPopupMessage string
|
||||
DeprecatedEditConfigWarning string
|
||||
NonReloadableConfigWarningTitle string
|
||||
NonReloadableConfigWarning string
|
||||
GitconfigParseErr string
|
||||
EditFile string
|
||||
EditFileTooltip string
|
||||
@ -985,6 +987,10 @@ for up-to-date information how to configure your editor.
|
||||
|
||||
`
|
||||
|
||||
const englishNonReloadableConfigWarning = `The following config settings were changed, but the change doesn't take effect immediately. Please quit and restart lazygit for changes to take effect:
|
||||
|
||||
{{configs}}`
|
||||
|
||||
// exporting this so we can use it in tests
|
||||
func EnglishTranslationSet() *TranslationSet {
|
||||
return &TranslationSet{
|
||||
@ -1199,6 +1205,8 @@ func EnglishTranslationSet() *TranslationSet {
|
||||
MergeToolPrompt: "Are you sure you want to open `git mergetool`?",
|
||||
IntroPopupMessage: englishIntroPopupMessage,
|
||||
DeprecatedEditConfigWarning: englishDeprecatedEditConfigWarning,
|
||||
NonReloadableConfigWarningTitle: "Config changed",
|
||||
NonReloadableConfigWarning: englishNonReloadableConfigWarning,
|
||||
GitconfigParseErr: `Gogit failed to parse your gitconfig file due to the presence of unquoted '\' characters. Removing these should fix the issue.`,
|
||||
EditFile: `Edit file`,
|
||||
EditFileTooltip: "Open file in external editor.",
|
||||
|
@ -15,7 +15,7 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
CreateNCommits(10)
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.AppState.GitLogShowGraph = "never"
|
||||
cfg.GetAppState().GitLogShowGraph = "never"
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
markCommitAsBad := func() {
|
||||
|
@ -15,7 +15,7 @@ var ChooseTerms = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
CreateNCommits(10)
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.AppState.GitLogShowGraph = "never"
|
||||
cfg.GetAppState().GitLogShowGraph = "never"
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
markCommitAsFixed := func() {
|
||||
|
@ -14,7 +14,7 @@ var Skip = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
CreateNCommits(10)
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.AppState.GitLogShowGraph = "never"
|
||||
cfg.GetAppState().GitLogShowGraph = "never"
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Commits().
|
||||
|
@ -11,7 +11,7 @@ var RebaseCopiedBranch = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Skip: false,
|
||||
GitVersion: AtLeast("2.38.0"),
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.AppState.GitLogShowGraph = "never"
|
||||
config.GetAppState().GitLogShowGraph = "never"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
|
@ -10,7 +10,7 @@ var RebaseOntoBaseBranch = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.UserConfig.Gui.ShowDivergenceFromBaseBranch = "arrowAndNumber"
|
||||
config.GetUserConfig().Gui.ShowDivergenceFromBaseBranch = "arrowAndNumber"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
|
@ -10,7 +10,7 @@ var ShowDivergenceFromBaseBranch = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.UserConfig.Gui.ShowDivergenceFromBaseBranch = "arrowAndNumber"
|
||||
config.GetUserConfig().Gui.ShowDivergenceFromBaseBranch = "arrowAndNumber"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
|
@ -10,7 +10,7 @@ var CherryPickDuringRebase = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.AppState.GitLogShowGraph = "never"
|
||||
config.GetAppState().GitLogShowGraph = "never"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
|
@ -11,7 +11,7 @@ var AutoWrapMessage = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
// Use a ridiculously small width so that we don't have to use so much test data
|
||||
config.UserConfig.Git.Commit.AutoWrapWidth = 20
|
||||
config.GetUserConfig().Git.Commit.AutoWrapWidth = 20
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateFile("file", "file content")
|
||||
|
@ -9,8 +9,8 @@ var CommitWipWithPrefix = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Commit with skip hook and config commitPrefix is defined. Prefix is ignored when creating WIP commits.",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(testConfig *config.AppConfig) {
|
||||
testConfig.UserConfig.Git.CommitPrefixes = map[string]config.CommitPrefixConfig{"repo": {Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[$1]: "}}
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().Git.CommitPrefixes = map[string]config.CommitPrefixConfig{"repo": {Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[$1]: "}}
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.NewBranch("feature/TEST-002")
|
||||
|
@ -9,8 +9,8 @@ var CommitWithGlobalPrefix = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Commit with defined config commitPrefix",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(testConfig *config.AppConfig) {
|
||||
testConfig.UserConfig.Git.CommitPrefix = &config.CommitPrefixConfig{Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[$1]: "}
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().Git.CommitPrefix = &config.CommitPrefixConfig{Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[$1]: "}
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.NewBranch("feature/TEST-001")
|
||||
|
@ -9,8 +9,8 @@ var CommitWithNonMatchingBranchName = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Commit with defined config commitPrefixes",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(testConfig *config.AppConfig) {
|
||||
testConfig.UserConfig.Git.CommitPrefix = &config.CommitPrefixConfig{
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().Git.CommitPrefix = &config.CommitPrefixConfig{
|
||||
Pattern: "^\\w+\\/(\\w+-\\w+).*",
|
||||
Replace: "[$1]: ",
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ var CommitWithPrefix = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Commit with defined config commitPrefixes",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(testConfig *config.AppConfig) {
|
||||
testConfig.UserConfig.Git.CommitPrefixes = map[string]config.CommitPrefixConfig{"repo": {Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[$1]: "}}
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().Git.CommitPrefixes = map[string]config.CommitPrefixConfig{"repo": {Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[$1]: "}}
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.NewBranch("feature/TEST-001")
|
||||
|
@ -10,7 +10,7 @@ var Highlight = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.AppState.GitLogShowGraph = "always"
|
||||
config.GetAppState().GitLogShowGraph = "always"
|
||||
config.GetUserConfig().Gui.AuthorColors = map[string]string{
|
||||
"CI": "red",
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ var NewBranchWithPrefix = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.Git.BranchPrefix = "myprefix/"
|
||||
cfg.GetUserConfig().Git.BranchPrefix = "myprefix/"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
|
@ -10,8 +10,8 @@ var PasteCommitMessage = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.UserConfig.OS.CopyToClipboardCmd = "echo {{text}} > ../clipboard"
|
||||
config.UserConfig.OS.ReadFromClipboardCmd = "cat ../clipboard"
|
||||
config.GetUserConfig().OS.CopyToClipboardCmd = "echo {{text}} > ../clipboard"
|
||||
config.GetUserConfig().OS.ReadFromClipboardCmd = "cat ../clipboard"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.EmptyCommit("subject\n\nbody 1st line\nbody 2nd line")
|
||||
|
@ -10,8 +10,8 @@ var PasteCommitMessageOverExisting = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.UserConfig.OS.CopyToClipboardCmd = "echo {{text}} > ../clipboard"
|
||||
config.UserConfig.OS.ReadFromClipboardCmd = "cat ../clipboard"
|
||||
config.GetUserConfig().OS.CopyToClipboardCmd = "echo {{text}} > ../clipboard"
|
||||
config.GetUserConfig().OS.ReadFromClipboardCmd = "cat ../clipboard"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.EmptyCommit("subject\n\nbody 1st line\nbody 2nd line")
|
||||
|
@ -15,7 +15,7 @@ var AccessCommitProperties = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
shell.EmptyCommit("my change")
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
cfg.GetUserConfig().CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "X",
|
||||
Context: "commits",
|
||||
|
@ -13,7 +13,7 @@ var BasicCommand = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
shell.EmptyCommit("blah")
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
cfg.GetUserConfig().CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "a",
|
||||
Context: "files",
|
||||
|
@ -14,7 +14,7 @@ var CheckForConflicts = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
shared.MergeConflictsSetup(shell)
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
cfg.GetUserConfig().CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "m",
|
||||
Context: "localBranches",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user