mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-10 20:05:50 +02:00
support configurable config
This commit is contained in:
parent
778ca8e6f9
commit
485f6d5386
9 changed files with 222 additions and 24 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -27,3 +27,4 @@ lazygit
|
|||
|
||||
test/git_server/data
|
||||
test/integration_test/
|
||||
test/integration_test_config/
|
||||
|
|
9
main.go
9
main.go
|
@ -49,7 +49,10 @@ func main() {
|
|||
flaggy.Bool(&configFlag, "c", "config", "Print the default config")
|
||||
|
||||
configDirFlag := false
|
||||
flaggy.Bool(&configDirFlag, "cd", "config-dir", "Print the config directory")
|
||||
flaggy.Bool(&configDirFlag, "cd", "print-config-dir", "Print the config directory")
|
||||
|
||||
useConfigDir := ""
|
||||
flaggy.String(&useConfigDir, "ucd", "use-config-dir", "override default config directory with provided directory")
|
||||
|
||||
workTree := ""
|
||||
flaggy.String(&workTree, "w", "work-tree", "equivalent of the --work-tree git argument")
|
||||
|
@ -68,6 +71,10 @@ func main() {
|
|||
gitDir = filepath.Join(repoPath, ".git")
|
||||
}
|
||||
|
||||
if useConfigDir != "" {
|
||||
os.Setenv("CONFIG_DIR", useConfigDir)
|
||||
}
|
||||
|
||||
if workTree != "" {
|
||||
env.SetGitWorkTreeEnv(workTree)
|
||||
}
|
||||
|
|
134
pkg/commands/oscommands/copy.go
Normal file
134
pkg/commands/oscommands/copy.go
Normal file
|
@ -0,0 +1,134 @@
|
|||
package oscommands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
/* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 Roland Singer [roland.singer@desertbit.com]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
// CopyFile copies the contents of the file named src to the file named
|
||||
// by dst. The file will be created if it does not already exist. If the
|
||||
// destination file exists, all it's contents will be replaced by the contents
|
||||
// of the source file. The file mode will be copied from the source and
|
||||
// the copied data is synced/flushed to stable storage.
|
||||
func CopyFile(src, dst string) (err error) {
|
||||
in, err := os.Open(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if e := out.Close(); e != nil {
|
||||
err = e
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = io.Copy(out, in)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = out.Sync()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
si, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = os.Chmod(dst, si.Mode())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CopyDir recursively copies a directory tree, attempting to preserve permissions.
|
||||
// Source directory must exist, destination directory must *not* exist.
|
||||
// Symlinks are ignored and skipped.
|
||||
func CopyDir(src string, dst string) (err error) {
|
||||
src = filepath.Clean(src)
|
||||
dst = filepath.Clean(dst)
|
||||
|
||||
si, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !si.IsDir() {
|
||||
return fmt.Errorf("source is not a directory")
|
||||
}
|
||||
|
||||
_, err = os.Stat(dst)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
return fmt.Errorf("destination already exists")
|
||||
}
|
||||
|
||||
err = os.MkdirAll(dst, si.Mode())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
entries, err := ioutil.ReadDir(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
srcPath := filepath.Join(src, entry.Name())
|
||||
dstPath := filepath.Join(dst, entry.Name())
|
||||
|
||||
if entry.IsDir() {
|
||||
err = CopyDir(srcPath, dstPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Skip symlinks.
|
||||
if entry.Mode()&os.ModeSymlink != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
err = CopyFile(srcPath, dstPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -81,6 +81,11 @@ func NewAppConfig(name, version, commit, date string, buildSource string, debugg
|
|||
}
|
||||
|
||||
func ConfigDir() string {
|
||||
envConfigDir := os.Getenv("CONFIG_DIR")
|
||||
if envConfigDir != "" {
|
||||
return envConfigDir
|
||||
}
|
||||
|
||||
// chucking my name there is not for vanity purposes, the xdg spec (and that
|
||||
// function) requires a vendor name. May as well line up with github
|
||||
configDirs := xdg.New("jesseduffield", "lazygit")
|
||||
|
@ -226,7 +231,7 @@ func loadAppState() (*AppState, error) {
|
|||
}
|
||||
|
||||
appStateBytes, err := ioutil.ReadFile(filepath)
|
||||
if err != nil {
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,14 @@ package gui
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/creack/pty"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -34,6 +36,23 @@ type integrationTest struct {
|
|||
fixture string
|
||||
}
|
||||
|
||||
func tests() []integrationTest {
|
||||
return []integrationTest{
|
||||
{
|
||||
name: "commit",
|
||||
fixture: "newFile",
|
||||
},
|
||||
{
|
||||
name: "squash",
|
||||
fixture: "manyCommits",
|
||||
},
|
||||
{
|
||||
name: "patchBuilding",
|
||||
fixture: "updatedFile",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func generateSnapshot(t *testing.T) string {
|
||||
osCommand := oscommands.NewDummyOSCommand()
|
||||
cmd := `sh -c "git status; cat ./*; git log --pretty=%B -p"`
|
||||
|
@ -59,20 +78,7 @@ func findOrCreateDir(path string) {
|
|||
}
|
||||
|
||||
func Test(t *testing.T) {
|
||||
tests := []integrationTest{
|
||||
{
|
||||
name: "commit",
|
||||
fixture: "newFile",
|
||||
},
|
||||
{
|
||||
name: "squash",
|
||||
fixture: "manyCommits",
|
||||
},
|
||||
{
|
||||
name: "patchBuilding",
|
||||
fixture: "updatedFile",
|
||||
},
|
||||
}
|
||||
tests := tests()
|
||||
|
||||
gotoRootDirectory()
|
||||
|
||||
|
@ -87,7 +93,6 @@ func Test(t *testing.T) {
|
|||
testPath := filepath.Join(rootDir, "test", "integration", test.name)
|
||||
findOrCreateDir(testPath)
|
||||
|
||||
replayPath := filepath.Join(testPath, "recording.json")
|
||||
snapshotPath := filepath.Join(testPath, "snapshot.txt")
|
||||
|
||||
err := os.Chdir(rootDir)
|
||||
|
@ -99,7 +104,7 @@ func Test(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
record := os.Getenv("RECORD_EVENTS") != ""
|
||||
runLazygit(t, replayPath, record)
|
||||
runLazygit(t, testPath, rootDir, record)
|
||||
|
||||
updateSnapshot := record || os.Getenv("UPDATE_SNAPSHOT") != ""
|
||||
|
||||
|
@ -148,25 +153,55 @@ func gotoRootDirectory() {
|
|||
}
|
||||
}
|
||||
|
||||
func runLazygit(t *testing.T, replayPath string, record bool) {
|
||||
func runLazygit(t *testing.T, testPath string, rootDir string, record bool) {
|
||||
osCommand := oscommands.NewDummyOSCommand()
|
||||
|
||||
var cmd *exec.Cmd
|
||||
replayPath := filepath.Join(testPath, "recording.json")
|
||||
cmdStr := fmt.Sprintf("go run %s", filepath.Join(rootDir, "main.go"))
|
||||
templateConfigDir := filepath.Join(rootDir, "test", "default_test_config")
|
||||
|
||||
exists, err := osCommand.FileExists(filepath.Join(testPath, "config"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
if exists {
|
||||
templateConfigDir = filepath.Join(testPath, "config")
|
||||
}
|
||||
|
||||
configDir := filepath.Join(rootDir, "test", "integration_test_config")
|
||||
|
||||
err = os.RemoveAll(configDir)
|
||||
assert.NoError(t, err)
|
||||
err = oscommands.CopyDir(templateConfigDir, configDir)
|
||||
assert.NoError(t, err)
|
||||
|
||||
cmdStr = fmt.Sprintf("%s --use-config-dir=%s", cmdStr, configDir)
|
||||
|
||||
cmd := osCommand.ExecutableFromString(cmdStr)
|
||||
if record {
|
||||
cmd = osCommand.ExecutableFromString("lazygit")
|
||||
cmd.Env = append(
|
||||
cmd.Env,
|
||||
fmt.Sprintf("RECORD_EVENTS_TO=%s", replayPath),
|
||||
)
|
||||
} else {
|
||||
cmd = osCommand.ExecutableFromString("lazygit")
|
||||
cmd.Env = append(
|
||||
cmd.Env,
|
||||
fmt.Sprintf("REPLAY_EVENTS_FROM=%s", replayPath),
|
||||
)
|
||||
}
|
||||
err := osCommand.RunExecutable(cmd)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// if we're on CI we'll need to use a PTY. We can work that out by seeing if the 'TERM' env is defined.
|
||||
if os.Getenv("TERM") == "" {
|
||||
cmd.Env = append(cmd.Env, "TERM=xterm")
|
||||
|
||||
f, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: 100, Cols: 100})
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = io.Copy(os.Stdout, f)
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
err := osCommand.RunExecutable(cmd)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func prepareIntegrationTestDir() {
|
||||
|
|
1
test/default_test_config/config.yml
Normal file
1
test/default_test_config/config.yml
Normal file
|
@ -0,0 +1 @@
|
|||
disableStartupPopups: true
|
5
test/fixtures/manyCommits.sh
vendored
5
test/fixtures/manyCommits.sh
vendored
|
@ -1,5 +1,10 @@
|
|||
#!/bin/sh
|
||||
|
||||
git init
|
||||
|
||||
git config user.email "CI@example.com"
|
||||
git config user.name "CI"
|
||||
|
||||
echo test1 > myfile1
|
||||
git add .
|
||||
git commit -am "myfile1"
|
||||
|
|
5
test/fixtures/newFile.sh
vendored
5
test/fixtures/newFile.sh
vendored
|
@ -1,5 +1,10 @@
|
|||
#!/bin/sh
|
||||
|
||||
git init
|
||||
|
||||
git config user.email "CI@example.com"
|
||||
git config user.name "CI"
|
||||
|
||||
echo test1 > myfile1
|
||||
git add .
|
||||
git commit -am "myfile1"
|
||||
|
|
5
test/fixtures/updatedFile.sh
vendored
5
test/fixtures/updatedFile.sh
vendored
|
@ -1,5 +1,10 @@
|
|||
#!/bin/sh
|
||||
|
||||
git init
|
||||
|
||||
git config user.email "CI@example.com"
|
||||
git config user.name "CI"
|
||||
|
||||
echo test1 > myfile1
|
||||
git add .
|
||||
git commit -am "myfile1"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue