Compare commits

..

13 Commits
v0.25 ... v0.26

Author SHA1 Message Date
Jesse Duffield
8288de0c84 update release notes 2021-03-13 11:46:48 +11:00
Ryooooooga
1da2afd450 Fix edit remote name message 2021-03-13 11:04:38 +11:00
Jesse Duffield
03de51747e remove redundant addition 2021-03-13 11:03:34 +11:00
Ryooooooga
3d698cd7c1 Fix tests 2021-03-13 11:02:31 +11:00
Ryooooooga
a48cc245e7 Support multibyte characters in pane 2021-03-13 11:02:31 +11:00
Ryooooooga
9ed3a8ee05 Fix staging/unstaging filenames that starts with - or -- 2021-03-13 11:02:31 +11:00
Ryooooooga
64daf1310d Fix staging/unstaging files containing " in paths 2021-03-13 11:02:31 +11:00
Ryooooooga
e5ba0d9d9c Support multibyte characters in Files pane 2021-03-13 11:02:31 +11:00
Ryooooooga
50e4e9d58d fix command escaping 2021-03-13 10:49:40 +11:00
István Donkó
03b9db5e0a Fix the linux config path (related: #913, #1059) 2021-03-12 12:45:48 +11:00
Jesse Duffield
043cb2ea44 reload config whenever returning to gui 2021-02-24 02:45:05 -08:00
Dawid Dziurla
a62d70fbd5 Merge pull request #1172 from jesseduffield/dawidd6-patch-1
gui: ReplaceAll -> Replace
2021-02-24 00:14:24 +01:00
Dawid Dziurla
053e80a08e gui: ReplaceAll -> Replace 2021-02-24 00:09:05 +01:00
15 changed files with 110 additions and 66 deletions

View File

@@ -2,7 +2,7 @@
Default path for the config file:
* Linux: `~/.config/jesseduffield/lazygit/config.yml`
* Linux: `~/.config/lazygit/config.yml`
* MacOS: `~/Library/Application Support/jesseduffield/lazygit/config.yml`
* Windows: `%APPDATA%\jesseduffield\lazygit\config.yml`

View File

@@ -3,7 +3,6 @@ package commands
import (
"fmt"
"os/exec"
"strconv"
"strings"
"github.com/jesseduffield/lazygit/pkg/commands/models"
@@ -25,7 +24,7 @@ func (c *GitCommand) Commit(message string, flags string) (*exec.Cmd, error) {
splitMessage := strings.Split(message, "\n")
lineArgs := ""
for _, line := range splitMessage {
lineArgs += fmt.Sprintf(" -m %s", strconv.Quote(line))
lineArgs += fmt.Sprintf(" -m %s", c.OSCommand.Quote(line))
}
command := fmt.Sprintf("git commit %s%s", flags, lineArgs)

View File

@@ -22,7 +22,7 @@ func (c *GitCommand) CatFile(fileName string) (string, error) {
func (c *GitCommand) StageFile(fileName string) error {
// renamed files look like "file1 -> file2"
fileNames := strings.Split(fileName, " -> ")
return c.OSCommand.RunCommand("git add %s", c.OSCommand.Quote(fileNames[len(fileNames)-1]))
return c.OSCommand.RunCommand("git add -- %s", c.OSCommand.Quote(fileNames[len(fileNames)-1]))
}
// StageAll stages all files
@@ -37,9 +37,9 @@ func (c *GitCommand) UnstageAll() error {
// UnStageFile unstages a file
func (c *GitCommand) UnStageFile(fileName string, tracked bool) error {
command := "git rm --cached --force %s"
command := "git rm --cached --force -- %s"
if tracked {
command = "git reset HEAD %s"
command = "git reset HEAD -- %s"
}
// renamed files look like "file1 -> file2"
@@ -149,7 +149,7 @@ func (c *GitCommand) WorktreeFileDiffCmdStr(file *models.File, plain bool, cache
cachedArg = "--cached"
}
if !file.Tracked && !file.HasStagedChanges && !cached {
trackedArg = "--no-index /dev/null"
trackedArg = "--no-index -- /dev/null"
}
if plain {
colorArg = "never"

View File

@@ -1037,7 +1037,7 @@ func TestGitCommandStageFile(t *testing.T) {
gitCmd := NewDummyGitCommand()
gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "git", cmd)
assert.EqualValues(t, []string{"add", "test.txt"}, args)
assert.EqualValues(t, []string{"add", "--", "test.txt"}, args)
return secureexec.Command("echo")
}
@@ -1059,7 +1059,7 @@ func TestGitCommandUnstageFile(t *testing.T) {
"Remove an untracked file from staging",
func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "git", cmd)
assert.EqualValues(t, []string{"rm", "--cached", "--force", "test.txt"}, args)
assert.EqualValues(t, []string{"rm", "--cached", "--force", "--", "test.txt"}, args)
return secureexec.Command("echo")
},
@@ -1072,7 +1072,7 @@ func TestGitCommandUnstageFile(t *testing.T) {
"Remove a tracked file from staging",
func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "git", cmd)
assert.EqualValues(t, []string{"reset", "HEAD", "test.txt"}, args)
assert.EqualValues(t, []string{"reset", "HEAD", "--", "test.txt"}, args)
return secureexec.Command("echo")
},
@@ -1455,7 +1455,7 @@ func TestGitCommandDiff(t *testing.T) {
"File not tracked and file has no staged changes",
func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "git", cmd)
assert.EqualValues(t, []string{"diff", "--submodule", "--no-ext-diff", "--color=always", "--no-index", "/dev/null", "test.txt"}, args)
assert.EqualValues(t, []string{"diff", "--submodule", "--no-ext-diff", "--color=always", "--no-index", "--", "/dev/null", "test.txt"}, args)
return secureexec.Command("echo")
},

View File

@@ -14,7 +14,7 @@ func (c *GitCommand) GetFilesInDiff(from string, to string, reverse bool, patchM
reverseFlag = " -R "
}
filenames, err := c.OSCommand.RunCommandWithOutput("git diff --submodule --no-ext-diff --name-status %s %s %s", reverseFlag, from, to)
filenames, err := c.OSCommand.RunCommandWithOutput("git diff --submodule --no-ext-diff --name-status -z %s %s %s", reverseFlag, from, to)
if err != nil {
return nil, err
}
@@ -26,13 +26,12 @@ func (c *GitCommand) GetFilesInDiff(from string, to string, reverse bool, patchM
func (c *GitCommand) getCommitFilesFromFilenames(filenames string, parent string, patchManager *patch.PatchManager) []*models.CommitFile {
commitFiles := make([]*models.CommitFile, 0)
for _, line := range strings.Split(strings.TrimRight(filenames, "\n"), "\n") {
lines := strings.Split(strings.TrimRight(filenames, "\x00"), "\x00")
n := len(lines)
for i := 0; i < n-1; i += 2 {
// typical result looks like 'A my_file' meaning my_file was added
if line == "" {
continue
}
changeStatus := line[0:1]
name := line[2:]
changeStatus := lines[i]
name := lines[i+1]
status := patch.UNSELECTED
if patchManager != nil && patchManager.To == parent {
status = patchManager.GetFileStatus(name)

View File

@@ -37,7 +37,7 @@ func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*models.File {
change := statusString[0:2]
stagedChange := change[0:1]
unstagedChange := statusString[1:2]
filename := c.OSCommand.Unquote(statusString[3:])
filename := statusString[3:]
untracked := utils.IncludesString([]string{"??", "A ", "AM"}, change)
hasNoStagedChanges := utils.IncludesString([]string{" ", "U", "?"}, stagedChange)
hasMergeConflicts := utils.IncludesString([]string{"DD", "AA", "UU", "AU", "UA", "UD", "DU"}, change)
@@ -72,7 +72,13 @@ func (c *GitCommand) GitStatus(opts GitStatusOptions) (string, error) {
noRenamesFlag = "--no-renames"
}
return c.OSCommand.RunCommandWithOutput("git status %s --porcelain %s", opts.UntrackedFilesArg, noRenamesFlag)
statusLines, err := c.OSCommand.RunCommandWithOutput("git status %s --porcelain -z %s", opts.UntrackedFilesArg, noRenamesFlag)
if err != nil {
return "", err
}
statusLines = strings.Replace(statusLines, "\x00", "\n", -1)
return statusLines, nil
}
// MergeStatusFiles merge status files

View File

@@ -8,7 +8,6 @@ import (
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
@@ -24,14 +23,13 @@ import (
// Platform stores the os state
type Platform struct {
OS string
CatCmd string
Shell string
ShellArg string
EscapedQuote string
OpenCommand string
OpenLinkCommand string
FallbackEscapedQuote string
OS string
CatCmd string
Shell string
ShellArg string
EscapedQuote string
OpenCommand string
OpenLinkCommand string
}
// OSCommand holds all the os commands
@@ -129,7 +127,7 @@ func (c *OSCommand) ShellCommandFromString(commandStr string) *exec.Cmd {
if c.Platform.OS == "windows" {
quotedCommand = commandStr
} else {
quotedCommand = strconv.Quote(commandStr)
quotedCommand = c.Quote(commandStr)
}
shellCommand := fmt.Sprintf("%s %s %s", c.Platform.Shell, c.Platform.ShellArg, quotedCommand)
@@ -245,20 +243,19 @@ func (c *OSCommand) PrepareSubProcess(cmdName string, commandArgs ...string) *ex
// Quote wraps a message in platform-specific quotation marks
func (c *OSCommand) Quote(message string) string {
message = strings.Replace(message, "`", "\\`", -1)
escapedQuote := c.Platform.EscapedQuote
if strings.Contains(message, c.Platform.EscapedQuote) {
escapedQuote = c.Platform.FallbackEscapedQuote
if c.Platform.OS == "windows" {
message = strings.Replace(message, `"`, `"'"'"`, -1)
message = strings.Replace(message, `\"`, `\\"`, -1)
} else {
message = strings.Replace(message, `\`, `\\`, -1)
message = strings.Replace(message, `"`, `\"`, -1)
message = strings.Replace(message, "`", "\\`", -1)
message = strings.Replace(message, "$", "\\$", -1)
}
escapedQuote := c.Platform.EscapedQuote
return escapedQuote + message + escapedQuote
}
// Unquote removes wrapping quotations marks if they are present
// this is needed for removing quotes from staged filenames with spaces
func (c *OSCommand) Unquote(message string) string {
return strings.Replace(message, `"`, "", -1)
}
// AppendLineToFile adds a new line in file
func (c *OSCommand) AppendLineToFile(filename, line string) error {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)

View File

@@ -8,13 +8,12 @@ import (
func getPlatform() *Platform {
return &Platform{
OS: runtime.GOOS,
CatCmd: "cat",
Shell: "bash",
ShellArg: "-c",
EscapedQuote: "'",
OpenCommand: "open {{filename}}",
OpenLinkCommand: "open {{link}}",
FallbackEscapedQuote: "\"",
OS: runtime.GOOS,
CatCmd: "cat",
Shell: "bash",
ShellArg: "-c",
EscapedQuote: `"`,
OpenCommand: "open {{filename}}",
OpenLinkCommand: "open {{link}}",
}
}

View File

@@ -114,6 +114,8 @@ func TestOSCommandOpenFile(t *testing.T) {
func TestOSCommandQuote(t *testing.T) {
osCommand := NewDummyOSCommand()
osCommand.Platform.OS = "linux"
actual := osCommand.Quote("hello `test`")
expected := osCommand.Platform.EscapedQuote + "hello \\`test\\`" + osCommand.Platform.EscapedQuote
@@ -129,7 +131,7 @@ func TestOSCommandQuoteSingleQuote(t *testing.T) {
actual := osCommand.Quote("hello 'test'")
expected := osCommand.Platform.FallbackEscapedQuote + "hello 'test'" + osCommand.Platform.FallbackEscapedQuote
expected := osCommand.Platform.EscapedQuote + "hello 'test'" + osCommand.Platform.EscapedQuote
assert.EqualValues(t, expected, actual)
}
@@ -142,18 +144,20 @@ func TestOSCommandQuoteDoubleQuote(t *testing.T) {
actual := osCommand.Quote(`hello "test"`)
expected := osCommand.Platform.EscapedQuote + "hello \"test\"" + osCommand.Platform.EscapedQuote
expected := osCommand.Platform.EscapedQuote + `hello \"test\"` + osCommand.Platform.EscapedQuote
assert.EqualValues(t, expected, actual)
}
// TestOSCommandUnquote is a function.
func TestOSCommandUnquote(t *testing.T) {
// TestOSCommandQuoteWindows tests the quote function for Windows
func TestOSCommandQuoteWindows(t *testing.T) {
osCommand := NewDummyOSCommand()
actual := osCommand.Unquote(`hello "test"`)
osCommand.Platform.OS = "windows"
expected := "hello test"
actual := osCommand.Quote(`hello "test"`)
expected := osCommand.Platform.EscapedQuote + `hello "'"'"test"'"'"` + osCommand.Platform.EscapedQuote
assert.EqualValues(t, expected, actual)
}

View File

@@ -2,11 +2,10 @@ package oscommands
func getPlatform() *Platform {
return &Platform{
OS: "windows",
CatCmd: "cmd /c type",
Shell: "cmd",
ShellArg: "/c",
EscapedQuote: `\"`,
FallbackEscapedQuote: "\\'",
OS: "windows",
CatCmd: "cmd /c type",
Shell: "cmd",
ShellArg: "/c",
EscapedQuote: `\"`,
}
}

View File

@@ -41,6 +41,7 @@ type AppConfigurer interface {
SaveAppState() error
SetIsNewRepo(bool)
GetIsNewRepo() bool
ReloadUserConfig() error
}
// NewAppConfig makes a new app config
@@ -203,6 +204,16 @@ func (c *AppConfig) GetUserConfigDir() string {
return c.UserConfigDir
}
func (c *AppConfig) ReloadUserConfig() error {
userConfig, err := loadUserConfigWithDefaults(c.UserConfigDir)
if err != nil {
return err
}
c.UserConfig = userConfig
return nil
}
func configFilePath(filename string) (string, error) {
folder, err := findOrCreateConfigDir()
if err != nil {

View File

@@ -550,5 +550,5 @@ func (gui *Gui) findBranchNameSuggestions(input string) []*types.Suggestion {
// sanitizedBranchName will remove all spaces in favor of a dash "-" to meet
// git's branch naming requirement.
func sanitizedBranchName(input string) string {
return strings.ReplaceAll(input, " ", "-")
return strings.Replace(input, " ", "-", -1)
}

View File

@@ -464,6 +464,9 @@ func (gui *Gui) Run() error {
}
g.OnSearchEscape = gui.onSearchEscape
if err := gui.Config.ReloadUserConfig(); err != nil {
return nil
}
userConfig := gui.Config.GetUserConfig()
g.SearchEscapeKey = gui.getKey(userConfig.Keybinding.Universal.Return)
g.NextSearchMatchKey = gui.getKey(userConfig.Keybinding.Universal.NextMatch)

View File

@@ -303,8 +303,8 @@ func dutchTranslationSet() TranslationSet {
LcAddNewRemote: `voeg een nieuwe remote toe`,
LcNewRemoteName: `Nieuwe remote name:`,
LcNewRemoteUrl: `Nieuwe remote url:`,
LcEditRemoteName: `Enter updated remote naam voor {{ .remoteName }}:`,
LcEditRemoteUrl: `Enter updated remote url voor {{ .remoteName }}:`,
LcEditRemoteName: `Enter updated remote naam voor {{.remoteName}}:`,
LcEditRemoteUrl: `Enter updated remote url voor {{.remoteName}}:`,
LcRemoveRemote: `verwijder remote`,
LcRemoveRemotePrompt: "Weet je zeker dat je deze remote wilt verwijderen",
DeleteRemoteBranch: "Verwijder Remote Branch",

View File

@@ -437,7 +437,34 @@ type TranslationSet struct {
LcCopiedToClipboard string
}
const englishReleaseNotes = `## lazygit 0.24 Release Notes
const englishReleaseNotes = `## lazygit 0.26 Release Notes
- Config changes applied after editing from within lazygit, no reload required.
- LOTS of fixes for rendering filenames with strange characters, escaped
characters, and UI fixes, by the amazing @Ryooooooga!
- Also thanks to @Isti115
## lazygit 0.25 Release Notes
- Fixes for windows, thanks @murphy66!
- Allow mapping spaces to dashes when creating a branch, thanks @caquillo07!
- Allow configuring file refresh and fetch frequency, thanks @Liberatys!
- Minor security improvement
- Wide characters supported when entering commit messages, thanks @Ryooooooga!
- Original branch name appears when renaming, thanks piresrui!
- Better menus, thanks @1jz!
- Also thanks to @snipem, @dbast, and @dawidd6
## lazygit 0.24 Release Notes
- Suggestions now shown when checking out branch by name
@@ -844,8 +871,8 @@ func englishTranslationSet() TranslationSet {
LcAddNewRemote: `add new remote`,
LcNewRemoteName: `New remote name:`,
LcNewRemoteUrl: `New remote url:`,
LcEditRemoteName: `Enter updated remote name for {{ .remoteName }}:`,
LcEditRemoteUrl: `Enter updated remote url for {{ .remoteName }}:`,
LcEditRemoteName: `Enter updated remote name for {{.remoteName}}:`,
LcEditRemoteUrl: `Enter updated remote url for {{.remoteName}}:`,
LcRemoveRemote: `remove remote`,
LcRemoveRemotePrompt: "Are you sure you want to remove remote",
DeleteRemoteBranch: "Delete Remote Branch",