support configurable config

This commit is contained in:
Jesse Duffield 2020-10-04 22:05:39 +11:00
parent 778ca8e6f9
commit 485f6d5386
9 changed files with 222 additions and 24 deletions

1
.gitignore vendored
View file

@ -27,3 +27,4 @@ lazygit
test/git_server/data
test/integration_test/
test/integration_test_config/

View file

@ -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)
}

View 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
}

View file

@ -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
}

View file

@ -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() {

View file

@ -0,0 +1 @@
disableStartupPopups: true

View file

@ -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"

View file

@ -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"

View file

@ -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"