Skip to content

Commit

Permalink
Merge branch 'master' into refactor-better-encapsulation
Browse files Browse the repository at this point in the history
  • Loading branch information
jesseduffield committed May 11, 2023
2 parents 5dacbb6 + 5c95d23 commit 2b30085
Show file tree
Hide file tree
Showing 14 changed files with 263 additions and 31 deletions.
12 changes: 6 additions & 6 deletions docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,21 +252,21 @@ keybinding:

```yaml
os:
openCommand: 'start "" {{filename}}'
open: 'start "" {{filename}}'
```

### Linux

```yaml
os:
openCommand: 'xdg-open {{filename}} >/dev/null'
open: 'xdg-open {{filename}} >/dev/null'
```

### OSX

```yaml
os:
openCommand: 'open {{filename}}'
open: 'open {{filename}}'
```

### Configuring File Editing
Expand All @@ -285,9 +285,9 @@ os:
editPreset: 'vscode'
```

Supported presets are `vim`, `emacs`, `nano`, `vscode`, `sublime`, `bbedit`, and
`xcode`. In many cases lazygit will be able to guess the right preset from your
$(git config core.editor), or an environment variable such as $VISUAL or $EDITOR.
Supported presets are `vim`, `nvim`, `emacs`, `nano`, `vscode`, `sublime`, `bbedit`,
`kakoune` and `xcode`. In many cases lazygit will be able to guess the right preset
from your $(git config core.editor), or an environment variable such as $VISUAL or $EDITOR.

If for some reason you are not happy with the default commands from a preset, or
there simply is no preset for your editor, you can customize the commands by
Expand Down
10 changes: 8 additions & 2 deletions pkg/commands/git_commands/rebase.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,18 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteract
debug = "TRUE"
}

emptyArg := " --empty=keep"
if self.version.IsOlderThan(2, 26, 0) {
emptyArg = ""
}

rebaseMergesArg := " --rebase-merges"
if self.version.IsOlderThan(2, 22, 0) {
rebaseMergesArg = ""
}
cmdStr := fmt.Sprintf("git rebase --interactive --autostash --keep-empty --empty=keep --no-autosquash%s %s",
rebaseMergesArg, opts.baseShaOrRoot)

cmdStr := fmt.Sprintf("git rebase --interactive --autostash --keep-empty%s --no-autosquash%s %s",
emptyArg, rebaseMergesArg, opts.baseShaOrRoot)
self.Log.WithField("command", cmdStr).Debug("RunCommand")

cmdObj := self.cmd.New(cmdStr)
Expand Down
52 changes: 38 additions & 14 deletions pkg/commands/git_commands/rebase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,60 @@ import (

func TestRebaseRebaseBranch(t *testing.T) {
type scenario struct {
testName string
arg string
runner *oscommands.FakeCmdObjRunner
test func(error)
testName string
arg string
gitVersion *GitVersion
runner *oscommands.FakeCmdObjRunner
test func(error)
}

scenarios := []scenario{
{
testName: "successful rebase",
arg: "master",
testName: "successful rebase",
arg: "master",
gitVersion: &GitVersion{2, 26, 0, ""},
runner: oscommands.NewFakeRunner(t).
Expect(`git rebase --interactive --autostash --keep-empty --empty=keep --no-autosquash master`, "", nil),
Expect(`git rebase --interactive --autostash --keep-empty --empty=keep --no-autosquash --rebase-merges master`, "", nil),
test: func(err error) {
assert.NoError(t, err)
},
},
{
testName: "unsuccessful rebase",
arg: "master",
testName: "unsuccessful rebase",
arg: "master",
gitVersion: &GitVersion{2, 26, 0, ""},
runner: oscommands.NewFakeRunner(t).
Expect(`git rebase --interactive --autostash --keep-empty --empty=keep --no-autosquash master`, "", errors.New("error")),
Expect(`git rebase --interactive --autostash --keep-empty --empty=keep --no-autosquash --rebase-merges master`, "", errors.New("error")),
test: func(err error) {
assert.Error(t, err)
},
},
{
testName: "successful rebase (< 2.26.0)",
arg: "master",
gitVersion: &GitVersion{2, 25, 5, ""},
runner: oscommands.NewFakeRunner(t).
Expect(`git rebase --interactive --autostash --keep-empty --no-autosquash --rebase-merges master`, "", nil),
test: func(err error) {
assert.NoError(t, err)
},
},
{
testName: "successful rebase (< 2.22.0)",
arg: "master",
gitVersion: &GitVersion{2, 21, 9, ""},
runner: oscommands.NewFakeRunner(t).
Expect(`git rebase --interactive --autostash --keep-empty --no-autosquash master`, "", nil),
test: func(err error) {
assert.NoError(t, err)
},
},
}

for _, s := range scenarios {
s := s
t.Run(s.testName, func(t *testing.T) {
instance := buildRebaseCommands(commonDeps{runner: s.runner})
instance := buildRebaseCommands(commonDeps{runner: s.runner, gitVersion: s.gitVersion})
s.test(instance.RebaseBranch(s.arg))
})
}
Expand Down Expand Up @@ -126,7 +149,7 @@ func TestRebaseDiscardOldFileChanges(t *testing.T) {
commitIndex: 0,
fileName: "test999.txt",
runner: oscommands.NewFakeRunner(t).
Expect(`git rebase --interactive --autostash --keep-empty --empty=keep --no-autosquash abcdef`, "", nil).
Expect(`git rebase --interactive --autostash --keep-empty --empty=keep --no-autosquash --rebase-merges abcdef`, "", nil).
Expect(`git cat-file -e HEAD^:"test999.txt"`, "", nil).
Expect(`git checkout HEAD^ -- "test999.txt"`, "", nil).
Expect(`git commit --amend --no-edit --allow-empty`, "", nil).
Expand All @@ -143,8 +166,9 @@ func TestRebaseDiscardOldFileChanges(t *testing.T) {
s := s
t.Run(s.testName, func(t *testing.T) {
instance := buildRebaseCommands(commonDeps{
runner: s.runner,
gitConfig: git_config.NewFakeGitConfig(s.gitConfigMockResponses),
runner: s.runner,
gitVersion: &GitVersion{2, 26, 0, ""},
gitConfig: git_config.NewFakeGitConfig(s.gitConfigMockResponses),
})

s.test(instance.DiscardOldFileChanges(s.commits, s.commitIndex, s.fileName))
Expand Down
1 change: 1 addition & 0 deletions pkg/config/editor_presets.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type editPreset struct {
editInTerminal bool
}

// IF YOU ADD A PRESET TO THIS FUNCTION YOU MUST UPDATE THE `Supported presets` SECTION OF docs/Config.md
func getPreset(osConfig *OSConfig, guessDefaultEditor func() string) *editPreset {
presets := map[string]*editPreset{
"vi": standardTerminalEditorPreset("vi"),
Expand Down
4 changes: 4 additions & 0 deletions pkg/gui/gui_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ func (self *guiCommon) ActivateContext(context types.Context) error {
return self.gui.State.ContextMgr.ActivateContext(context, types.OnFocusOpts{})
}

func (self *guiCommon) ActivateContext(context types.Context) error {
return self.gui.activateContext(context, types.OnFocusOpts{})
}

func (self *guiCommon) GetAppState() *config.AppState {
return self.gui.Config.GetAppState()
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/integration/components/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ type GitVersionRestriction struct {
}

// Verifies the version is at least the given version (inclusive)
func From(version string) GitVersionRestriction {
func AtLeast(version string) GitVersionRestriction {
return GitVersionRestriction{from: version}
}

Expand Down
12 changes: 6 additions & 6 deletions pkg/integration/components/test_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,18 @@ func TestGitVersionRestriction(t *testing.T) {
expectedShouldRun bool
}{
{
testName: "From, current is newer",
gitVersion: From("2.24.9"),
testName: "AtLeast, current is newer",
gitVersion: AtLeast("2.24.9"),
expectedShouldRun: true,
},
{
testName: "From, current is same",
gitVersion: From("2.25.0"),
testName: "AtLeast, current is same",
gitVersion: AtLeast("2.25.0"),
expectedShouldRun: true,
},
{
testName: "From, current is older",
gitVersion: From("2.26.0"),
testName: "AtLeast, current is older",
gitVersion: AtLeast("2.26.0"),
expectedShouldRun: false,
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var DropTodoCommitWithUpdateRef = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Drops a commit during interactive rebase when there is an update-ref in the git-rebase-todo file",
ExtraCmdArgs: "",
Skip: false,
GitVersion: From("2.38.0"),
GitVersion: AtLeast("2.38.0"),
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var DropTodoCommitWithUpdateRefShowBranchHeads = NewIntegrationTest(NewIntegrati
Description: "Drops a commit during interactive rebase when there is an update-ref in the git-rebase-todo file (with experimentalShowBranchHeads on)",
ExtraCmdArgs: "",
Skip: false,
GitVersion: From("2.38.0"),
GitVersion: AtLeast("2.38.0"),
SetupConfig: func(config *config.AppConfig) {
config.UserConfig.Gui.ExperimentalShowBranchHeads = true
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var MoveToEarlierCommit = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Move a patch from a commit to an earlier commit",
ExtraCmdArgs: "",
Skip: false,
GitVersion: AtLeast("2.26.0"),
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.CreateDir("dir")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package patch_building

import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)

var MoveToEarlierCommitNoKeepEmpty = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Move a patch from a commit to an earlier commit, for older git versions that don't keep the empty commit",
ExtraCmdArgs: "",
Skip: false,
GitVersion: Before("2.26.0"),
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.CreateDir("dir")
shell.CreateFileAndAdd("dir/file1", "file1 content")
shell.CreateFileAndAdd("dir/file2", "file2 content")
shell.Commit("first commit")

shell.CreateFileAndAdd("unrelated-file", "")
shell.Commit("destination commit")

shell.UpdateFileAndAdd("dir/file1", "file1 content with old changes")
shell.DeleteFileAndAdd("dir/file2")
shell.CreateFileAndAdd("dir/file3", "file3 content")
shell.Commit("commit to move from")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("commit to move from").IsSelected(),
Contains("destination commit"),
Contains("first commit"),
).
PressEnter()

t.Views().CommitFiles().
IsFocused().
Lines(
Contains("dir").IsSelected(),
Contains(" M file1"),
Contains(" D file2"),
Contains(" A file3"),
).
PressPrimaryAction().
PressEscape()

t.Views().Information().Content(Contains("building patch"))

t.Views().Commits().
IsFocused().
SelectNextItem()

t.Common().SelectPatchOption(Contains("move patch to selected commit"))

t.Views().Commits().
IsFocused().
Lines(
Contains("destination commit"),
Contains("first commit").IsSelected(),
).
SelectPreviousItem().
PressEnter()

t.Views().CommitFiles().
IsFocused().
Lines(
Contains("dir").IsSelected(),
Contains(" M file1"),
Contains(" D file2"),
Contains(" A file3"),
Contains("A unrelated-file"),
).
PressEscape()
},
})
1 change: 1 addition & 0 deletions pkg/integration/tests/test_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ var tests = []*components.IntegrationTest{
patch_building.ApplyInReverseWithConflict,
patch_building.CopyPatchToClipboard,
patch_building.MoveToEarlierCommit,
patch_building.MoveToEarlierCommitNoKeepEmpty,
patch_building.MoveToIndex,
patch_building.MoveToIndexPartOfAdjacentAddedLines,
patch_building.MoveToIndexPartial,
Expand Down
54 changes: 54 additions & 0 deletions pkg/utils/yaml_utils/yaml_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package yaml_utils

import (
"fmt"

"gopkg.in/yaml.v3"
)

// takes a yaml document in bytes, a path to a key, and a value to set. The value must be a scalar.
func UpdateYaml(yamlBytes []byte, path []string, value string) ([]byte, error) {
// Parse the YAML file.
var node yaml.Node
err := yaml.Unmarshal(yamlBytes, &node)
if err != nil {
return nil, fmt.Errorf("failed to parse YAML: %w", err)
}

body := node.Content[0]

updateYamlNode(body, path, value)

// Convert the updated YAML node back to YAML bytes.
updatedYAMLBytes, err := yaml.Marshal(body)
if err != nil {
return nil, fmt.Errorf("failed to convert YAML node to bytes: %w", err)
}

return updatedYAMLBytes, nil
}

// Recursive function to update the YAML node.
func updateYamlNode(node *yaml.Node, path []string, value string) {
if len(path) == 0 {
node.Value = value
return
}

key := path[0]
for i := 0; i < len(node.Content)-1; i += 2 {
if node.Content[i].Value == key {
updateYamlNode(node.Content[i+1], path[1:], value)
return
}
}

// if the key doesn't exist, we'll add it
node.Content = append(node.Content, &yaml.Node{
Kind: yaml.ScalarNode,
Value: key,
}, &yaml.Node{
Kind: yaml.ScalarNode,
Value: value,
})
}
Loading

0 comments on commit 2b30085

Please sign in to comment.