1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-04-11 11:42:12 +02:00

Merge pull request #2027 from jesseduffield/gozes-jesse

Attempt at fixing CI
This commit is contained in:
Jesse Duffield 2022-07-05 19:37:09 +10:00 committed by GitHub
commit c087dca60a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 297 additions and 72 deletions

View File

@ -31,6 +31,11 @@ git add .
git commit -am "myfile1"
```
Be sure to:
- ensure that by the end of the test you've got at least one commit in the repo, as we've had issues in the past when that wasn't the case.
- set the git user email and name as above so that your own user details aren't included in the snapshot.
## Running tests
### From a TUI

View File

@ -102,7 +102,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>C</kbd>: commit changes using git editor
<kbd>e</kbd>: edit file
<kbd>o</kbd>: open file
<kbd>i</kbd>: add to .gitignore
<kbd>i</kbd>: Ignore or Exclude file
<kbd>r</kbd>: refresh files
<kbd>s</kbd>: stash all changes
<kbd>S</kbd>: view stash options

View File

@ -161,7 +161,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>C</kbd>: gitエディタを使用して変更をコミット
<kbd>e</kbd>: ファイルを編集
<kbd>o</kbd>: ファイルを開く
<kbd>i</kbd>: .gitignoreに追加
<kbd>i</kbd>: ファイルをignore
<kbd>r</kbd>: ファイルをリフレッシュ
<kbd>s</kbd>: 変更をstash
<kbd>S</kbd>: view stash options

View File

@ -280,7 +280,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>C</kbd>: Git 편집기를 사용하여 변경 내용을 커밋합니다.
<kbd>e</kbd>: 파일 편집
<kbd>o</kbd>: 파일 닫기
<kbd>i</kbd>: .gitignore에 추가
<kbd>i</kbd>: Ignore file
<kbd>r</kbd>: 파일 새로고침
<kbd>s</kbd>: 변경사항을 Stash
<kbd>S</kbd>: Stash 옵션 보기

View File

@ -55,7 +55,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>C</kbd>: commit veranderingen met de git editor
<kbd>e</kbd>: verander bestand
<kbd>o</kbd>: open bestand
<kbd>i</kbd>: voeg toe aan .gitignore
<kbd>i</kbd>: Ignore or Exclude file
<kbd>r</kbd>: refresh bestanden
<kbd>s</kbd>: stash-bestanden
<kbd>S</kbd>: bekijk stash opties

View File

@ -126,7 +126,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>C</kbd>: Zatwierdź zmiany używając edytora
<kbd>e</kbd>: edytuj plik
<kbd>o</kbd>: otwórz plik
<kbd>i</kbd>: dodaj do .gitignore
<kbd>i</kbd>: Ignore or Exclude file
<kbd>r</kbd>: odśwież pliki
<kbd>s</kbd>: przechowaj zmiany
<kbd>S</kbd>: wyświetl opcje schowka

View File

@ -167,7 +167,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>C</kbd>: 提交更改(使用编辑器编辑提交信息)
<kbd>e</kbd>: 编辑文件
<kbd>o</kbd>: 打开文件
<kbd>i</kbd>: 添加到 .gitignore
<kbd>i</kbd>: 忽略文件
<kbd>r</kbd>: 刷新文件
<kbd>s</kbd>: 将所有更改加入贮藏
<kbd>S</kbd>: 查看贮藏选项

View File

@ -218,6 +218,11 @@ func (self *WorkingTreeCommands) Ignore(filename string) error {
return self.os.AppendLineToFile(".gitignore", filename)
}
// Exclude adds a file to the .git/info/exclude for the repo
func (self *WorkingTreeCommands) Exclude(filename string) error {
return self.os.AppendLineToFile(".git/info/exclude", filename)
}
// WorktreeFileDiff returns the diff of a file
func (self *WorkingTreeCommands) WorktreeFileDiff(file *models.File, plain bool, cached bool, ignoreWhitespace bool) string {
// for now we assume an error means the file was deleted

View File

@ -210,7 +210,7 @@ type KeybindingFilesConfig struct {
CommitChangesWithoutHook string `yaml:"commitChangesWithoutHook"`
AmendLastCommit string `yaml:"amendLastCommit"`
CommitChangesWithEditor string `yaml:"commitChangesWithEditor"`
IgnoreFile string `yaml:"ignoreFile"`
IgnoreOrExcludeFile string `yaml:"IgnoreOrExcludeFile"`
RefreshFiles string `yaml:"refreshFiles"`
StashAllChanges string `yaml:"stashAllChanges"`
ViewStashOptions string `yaml:"viewStashOptions"`
@ -490,7 +490,7 @@ func GetDefaultConfig() *UserConfig {
CommitChangesWithoutHook: "w",
AmendLastCommit: "A",
CommitChangesWithEditor: "C",
IgnoreFile: "i",
IgnoreOrExcludeFile: "i",
RefreshFiles: "r",
StashAllChanges: "s",
ViewStashOptions: "S",

View File

@ -86,9 +86,9 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
Description: self.c.Tr.LcOpenFile,
},
{
Key: opts.GetKey(opts.Config.Files.IgnoreFile),
Handler: self.checkSelectedFileNode(self.ignore),
Description: self.c.Tr.LcIgnoreFile,
Key: opts.GetKey(opts.Config.Files.IgnoreOrExcludeFile),
Handler: self.checkSelectedFileNode(self.ignoreOrExcludeMenu),
Description: self.c.Tr.Actions.IgnoreExcludeFile,
},
{
Key: opts.GetKey(opts.Config.Files.RefreshFiles),
@ -302,59 +302,115 @@ func (self *FilesController) stageAll() error {
return self.contexts.Files.HandleFocus()
}
func (self *FilesController) ignore(node *filetree.FileNode) error {
if node.GetPath() == ".gitignore" {
return self.c.ErrorMsg("Cannot ignore .gitignore")
}
unstageFiles := func() error {
return node.ForEachFile(func(file *models.File) error {
if file.HasStagedChanges {
if err := self.git.WorkingTree.UnStageFile(file.Names(), file.Tracked); err != nil {
return err
}
func (self *FilesController) unstageFiles(node *filetree.FileNode) error {
return node.ForEachFile(func(file *models.File) error {
if file.HasStagedChanges {
if err := self.git.WorkingTree.UnStageFile(file.Names(), file.Tracked); err != nil {
return err
}
}
return nil
})
}
return nil
})
}
if node.GetIsTracked() {
return self.c.Confirm(types.ConfirmOpts{
Title: self.c.Tr.IgnoreTracked,
Prompt: self.c.Tr.IgnoreTrackedPrompt,
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.IgnoreFile)
// not 100% sure if this is necessary but I'll assume it is
if err := unstageFiles(); err != nil {
return err
}
if err := self.git.WorkingTree.RemoveTrackedFiles(node.GetPath()); err != nil {
return err
}
if err := self.git.WorkingTree.Ignore(node.GetPath()); err != nil {
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES}})
},
})
}
self.c.LogAction(self.c.Tr.Actions.IgnoreFile)
if err := unstageFiles(); err != nil {
func (self *FilesController) ignoreOrExcludeTracked(node *filetree.FileNode, trAction string, f func(string) error) error {
self.c.LogAction(trAction)
// not 100% sure if this is necessary but I'll assume it is
if err := self.unstageFiles(node); err != nil {
return err
}
if err := self.git.WorkingTree.Ignore(node.GetPath()); err != nil {
return self.c.Error(err)
if err := self.git.WorkingTree.RemoveTrackedFiles(node.GetPath()); err != nil {
return err
}
if err := f(node.GetPath()); err != nil {
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES}})
}
func (self *FilesController) ignoreOrExcludeUntracked(node *filetree.FileNode, trAction string, f func(string) error) error {
self.c.LogAction(trAction)
if err := f(node.GetPath()); err != nil {
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES}})
}
func (self *FilesController) ignoreOrExcludeFile(node *filetree.FileNode, trText string, trPrompt string, trAction string, f func(string) error) error {
if node.GetIsTracked() {
return self.c.Confirm(types.ConfirmOpts{
Title: trText,
Prompt: trPrompt,
HandleConfirm: func() error {
return self.ignoreOrExcludeTracked(node, trAction, f)
},
})
}
return self.ignoreOrExcludeUntracked(node, trAction, f)
}
func (self *FilesController) ignore(node *filetree.FileNode) error {
if node.GetPath() == ".gitignore" {
return self.c.ErrorMsg(self.c.Tr.Actions.IgnoreFileErr)
}
err := self.ignoreOrExcludeFile(node, self.c.Tr.IgnoreTracked, self.c.Tr.IgnoreTrackedPrompt, self.c.Tr.Actions.IgnoreExcludeFile, self.git.WorkingTree.Ignore)
if err != nil {
return err
}
return nil
}
func (self *FilesController) exclude(node *filetree.FileNode) error {
if node.GetPath() == ".git/info/exclude" {
return self.c.ErrorMsg(self.c.Tr.Actions.ExcludeFileErr)
}
if node.GetPath() == ".gitignore" {
return self.c.ErrorMsg(self.c.Tr.Actions.ExcludeGitIgnoreErr)
}
err := self.ignoreOrExcludeFile(node, self.c.Tr.ExcludeTracked, self.c.Tr.ExcludeTrackedPrompt, self.c.Tr.Actions.ExcludeFile, self.git.WorkingTree.Exclude)
if err != nil {
return err
}
return nil
}
func (self *FilesController) ignoreOrExcludeMenu(node *filetree.FileNode) error {
return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.Actions.IgnoreExcludeFile,
Items: []*types.MenuItem{
{
LabelColumns: []string{self.c.Tr.LcIgnoreFile},
OnPress: func() error {
if err := self.ignore(node); err != nil {
return self.c.Error(err)
}
return nil
},
Key: 'i',
},
{
LabelColumns: []string{self.c.Tr.LcExcludeFile},
OnPress: func() error {
if err := self.exclude(node); err != nil {
return self.c.Error(err)
}
return nil
},
Key: 'e',
},
},
})
}
func (self *FilesController) HandleWIPCommitPress() error {
skipHookPrefix := self.c.UserConfig.Git.SkipHookPrefix
if skipHookPrefix == "" {

View File

@ -507,7 +507,7 @@ func chineseTranslationSet() TranslationSet {
UnstageFile: "取消暂存文件",
UnstageAllFiles: "取消暂存所有文件",
StageAllFiles: "暂存所有文件",
IgnoreFile: "忽略文件",
IgnoreExcludeFile: "忽略文件",
Commit: "提交 (Commit)",
EditFile: "编辑文件",
Push: "推送 (Push)",

View File

@ -155,6 +155,7 @@ type TranslationSet struct {
LcEditFile string
LcOpenFile string
LcIgnoreFile string
LcExcludeFile string
LcRefreshFiles string
LcMergeIntoCurrentBranch string
ConfirmQuit string
@ -346,7 +347,9 @@ type TranslationSet struct {
NotAGitFlowBranch string
NewBranchNamePrompt string
IgnoreTracked string
ExcludeTracked string
IgnoreTrackedPrompt string
ExcludeTrackedPrompt string
LcViewResetToUpstreamOptions string
LcNextScreenMode string
LcPrevScreenMode string
@ -561,7 +564,12 @@ type Actions struct {
UnstageFile string
UnstageAllFiles string
StageAllFiles string
IgnoreExcludeFile string
IgnoreFile string
IgnoreFileErr string
ExcludeFile string
ExcludeFileErr string
ExcludeGitIgnoreErr string
Commit string
EditFile string
Push string
@ -781,6 +789,7 @@ func EnglishTranslationSet() TranslationSet {
LcEditFile: `edit file`,
LcOpenFile: `open file`,
LcIgnoreFile: `add to .gitignore`,
LcExcludeFile: `add to .git/info/exclude`,
LcRefreshFiles: `refresh files`,
LcMergeIntoCurrentBranch: `merge into currently checked out branch`,
ConfirmQuit: `Are you sure you want to quit?`,
@ -974,6 +983,8 @@ func EnglishTranslationSet() TranslationSet {
NewGitFlowBranchPrompt: "new {{.branchType}} name:",
IgnoreTracked: "Ignore tracked file",
IgnoreTrackedPrompt: "Are you sure you want to ignore a tracked file?",
ExcludeTracked: "Exclude tracked file",
ExcludeTrackedPrompt: "Are you sure you want to exclude a tracked file?",
LcViewResetToUpstreamOptions: "view upstream reset options",
LcNextScreenMode: "next screen mode (normal/half/fullscreen)",
LcPrevScreenMode: "prev screen mode",
@ -1171,7 +1182,12 @@ func EnglishTranslationSet() TranslationSet {
UnstageFile: "Unstage file",
UnstageAllFiles: "Unstage all files",
StageAllFiles: "Stage all files",
IgnoreFile: "Ignore file",
IgnoreExcludeFile: "Ignore or Exclude file",
IgnoreFile: "Ignore or Exclude file",
IgnoreFileErr: "Cannot ignore .gitignore",
ExcludeFile: "Exclude file",
ExcludeFileErr: "Cannot exclude .git/info/exclude",
ExcludeGitIgnoreErr: "Cannot exclude .gitignore",
Commit: "Commit",
EditFile: "Edit file",
Push: "Push",

View File

@ -533,7 +533,7 @@ func japaneseTranslationSet() TranslationSet {
UnstageFile: "ファイルをアンステージ",
UnstageAllFiles: "すべてのファイルをアンステージ",
StageAllFiles: "すべてのファイルをステージ",
IgnoreFile: "ファイルをignore",
IgnoreExcludeFile: "ファイルをignore",
Commit: "コミット",
EditFile: "ファイルを編集",
Push: "Push",

View File

@ -536,7 +536,7 @@ func koreanTranslationSet() TranslationSet {
UnstageFile: "Unstage file",
UnstageAllFiles: "Unstage all files",
StageAllFiles: "Stage all files",
IgnoreFile: "Ignore file",
IgnoreExcludeFile: "Ignore file",
Commit: "커밋",
EditFile: "파일 수정",
Push: "푸시",

View File

@ -137,7 +137,7 @@ func RunTests(
return err
}
if err := renameGitDirs(expectedDir); err != nil {
if err := renameSpecialPaths(expectedDir); err != nil {
return err
}
@ -441,7 +441,7 @@ func generateSnapshots(actualDir string, expectedDir string) (string, string, er
return "", "", err
}
if err := restoreGitDirs(expectedDirCopyDir); err != nil {
if err := restoreSpecialPaths(expectedDirCopyDir); err != nil {
return "", "", err
}
@ -458,7 +458,7 @@ func generateSnapshots(actualDir string, expectedDir string) (string, string, er
return actual, expected, nil
}
func getPathsToRename(dir string, needle string) []string {
func getPathsToRename(dir string, needle string, contains string) []string {
pathsToRename := []string{}
err := filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
@ -466,7 +466,7 @@ func getPathsToRename(dir string, needle string) []string {
return err
}
if f.Name() == needle {
if f.Name() == needle && (contains == "" || strings.Contains(path, contains)) {
pathsToRename = append(pathsToRename, path)
}
@ -479,14 +479,22 @@ func getPathsToRename(dir string, needle string) []string {
return pathsToRename
}
// Git refuses to track .git and .gitmodules folders in subdirectories so we need to rename it
// to git_keep after running a test, and then change it back again
var untrackedGitDirs []string = []string{".git", ".gitmodules"}
var specialPathMappings = []struct{ original, new, contains string }{
// git refuses to track .git or .gitmodules in subdirectories so we need to rename them
{".git", ".git_keep", ""},
{".gitmodules", ".gitmodules_keep", ""},
// we also need git to ignore the contents of our test gitignore files so that
// we actually commit files that are ignored within the test.
{".gitignore", "lg_ignore_file", ""},
// this is the .git/info/exclude file. We're being a little more specific here
// so that we don't accidentally mess with some other file named 'exclude' in the test.
{"exclude", "lg_exclude_file", ".git/info/exclude"},
}
func renameGitDirs(dir string) error {
for _, untrackedGitDir := range untrackedGitDirs {
for _, path := range getPathsToRename(dir, untrackedGitDir) {
err := os.Rename(path, path+"_keep")
func renameSpecialPaths(dir string) error {
for _, specialPath := range specialPathMappings {
for _, path := range getPathsToRename(dir, specialPath.original, specialPath.contains) {
err := os.Rename(path, filepath.Join(filepath.Dir(path), specialPath.new))
if err != nil {
return err
}
@ -496,10 +504,10 @@ func renameGitDirs(dir string) error {
return nil
}
func restoreGitDirs(dir string) error {
for _, untrackedGitDir := range untrackedGitDirs {
for _, path := range getPathsToRename(dir, untrackedGitDir+"_keep") {
err := os.Rename(path, strings.TrimSuffix(path, "_keep"))
func restoreSpecialPaths(dir string) error {
for _, specialPath := range specialPathMappings {
for _, path := range getPathsToRename(dir, specialPath.new, specialPath.contains) {
err := os.Rename(path, filepath.Join(filepath.Dir(path), specialPath.original))
if err != nil {
return err
}

View File

@ -0,0 +1 @@
Initial commit

View File

@ -0,0 +1 @@
ref: refs/heads/master

View File

@ -0,0 +1,10 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[user]
email = CI@example.com
name = CI

View File

@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@ -0,0 +1,7 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
.DS_Store

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 e976bc07c8784964cf239ac9fbdc3535df55269c CI <CI@example.com> 1657012812 +1000 commit (initial): Initial commit

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 e976bc07c8784964cf239ac9fbdc3535df55269c CI <CI@example.com> 1657012812 +1000 commit (initial): Initial commit

View File

@ -0,0 +1 @@
e976bc07c8784964cf239ac9fbdc3535df55269c

View File

@ -0,0 +1 @@
test1

View File

@ -0,0 +1 @@
{"KeyEvents":[{"Timestamp":642,"Mod":0,"Key":256,"Ch":105},{"Timestamp":1529,"Mod":0,"Key":256,"Ch":101},{"Timestamp":2522,"Mod":0,"Key":27,"Ch":0},{"Timestamp":2962,"Mod":0,"Key":256,"Ch":113}],"ResizeEvents":[{"Timestamp":0,"Width":238,"Height":61}]}

View File

@ -0,0 +1,15 @@
#!/bin/sh
set -e
cd $1
git init
git config user.email "CI@example.com"
git config user.name "CI"
git commit --allow-empty -m "Initial commit"
echo test1 > .gitignore

View File

@ -0,0 +1,4 @@
{
"description": "In this test we attempt to add .gitignore to .git/info/exclude to ensure lazygit rejects the action",
"speed": 5
}

View File

@ -0,0 +1 @@
Initial commit

View File

@ -0,0 +1 @@
ref: refs/heads/master

View File

@ -0,0 +1,10 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[user]
email = CI@example.com
name = CI

View File

@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@ -0,0 +1,9 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
.DS_Store
myfile1

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 129cdae0c4ccd050e8398bcb18b2ce1e4a5626f9 CI <CI@example.com> 1657012793 +1000 commit (initial): Initial commit

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 129cdae0c4ccd050e8398bcb18b2ce1e4a5626f9 CI <CI@example.com> 1657012793 +1000 commit (initial): Initial commit

View File

@ -0,0 +1 @@
129cdae0c4ccd050e8398bcb18b2ce1e4a5626f9

View File

@ -0,0 +1 @@
test1

View File

@ -0,0 +1 @@
{"KeyEvents":[{"Timestamp":788,"Mod":0,"Key":256,"Ch":105},{"Timestamp":2342,"Mod":0,"Key":256,"Ch":101},{"Timestamp":3429,"Mod":0,"Key":256,"Ch":113}],"ResizeEvents":[{"Timestamp":0,"Width":238,"Height":61}]}

View File

@ -0,0 +1,15 @@
#!/bin/sh
set -e
cd $1
git init
git config user.email "CI@example.com"
git config user.name "CI"
git commit --allow-empty -m "Initial commit"
echo test1 > myfile1

View File

@ -0,0 +1,4 @@
{
"description": "In this test a file is added to .git/info/exclude using the ignore or exclude menu",
"speed": 5
}

View File

@ -0,0 +1 @@
Initial commit

View File

@ -0,0 +1 @@
ref: refs/heads/master

View File

@ -0,0 +1,10 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[user]
email = CI@example.com
name = CI

View File

@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@ -0,0 +1,7 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
.DS_Store

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 9dd04ee245b7d6f1f80aa2b428111cbac4a4e37d CI <CI@example.com> 1657012500 +1000 commit (initial): Initial commit

View File

@ -0,0 +1 @@
0000000000000000000000000000000000000000 9dd04ee245b7d6f1f80aa2b428111cbac4a4e37d CI <CI@example.com> 1657012500 +1000 commit (initial): Initial commit

View File

@ -0,0 +1 @@
9dd04ee245b7d6f1f80aa2b428111cbac4a4e37d

View File

@ -0,0 +1,2 @@
myfile1

View File

@ -0,0 +1 @@
test1

View File

@ -0,0 +1 @@
{"KeyEvents":[{"Timestamp":1133,"Mod":0,"Key":256,"Ch":105},{"Timestamp":1927,"Mod":0,"Key":13,"Ch":13},{"Timestamp":2735,"Mod":0,"Key":256,"Ch":113}],"ResizeEvents":[{"Timestamp":0,"Width":238,"Height":61}]}

View File

@ -0,0 +1,14 @@
#!/bin/sh
set -e
cd $1
git init
git config user.email "CI@example.com"
git config user.name "CI"
git commit --allow-empty -m "Initial commit"
echo test1 > myfile1

View File

@ -0,0 +1,4 @@
{
"description": "In this test a file is added to .gitingnore using the ignore or exclude menu",
"speed": 5
}