From e5de37d57f5b0760873d5d42cdce84fc20c4492d Mon Sep 17 00:00:00 2001 From: Zaq? Wiedmann Date: Mon, 15 Jan 2018 17:39:48 -0800 Subject: [PATCH] [#98] (snippet,fix) use /tmp for personal snippets when editing outside of a git repo before this would just cause a fatal error indicating "not a git repository" --- cmd/snippet.go | 6 ++++ cmd/snippetCreate_test.go | 61 +++++++++++++++++++++++++++++++++++++-- internal/git/edit.go | 23 +++++++++++---- internal/git/git.go | 10 +++++++ internal/git/git_test.go | 4 +++ 5 files changed, 96 insertions(+), 8 deletions(-) diff --git a/cmd/snippet.go b/cmd/snippet.go index 279fdf12..b9e7adee 100644 --- a/cmd/snippet.go +++ b/cmd/snippet.go @@ -27,6 +27,12 @@ var snippetCmd = &cobra.Command{ snippetDeleteCmd.Run(cmd, append(args, deleteID)) return } + + if global, _ := cmd.Flags().GetBool("global"); global { + snippetCreateCmd.Run(cmd, args) + return + } + if len(args) == 0 && file == "" { cmd.Help() return diff --git a/cmd/snippetCreate_test.go b/cmd/snippetCreate_test.go index 7842296f..3ea234fb 100644 --- a/cmd/snippetCreate_test.go +++ b/cmd/snippetCreate_test.go @@ -2,7 +2,9 @@ package cmd import ( "io/ioutil" + "os" "os/exec" + "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -43,11 +45,20 @@ func Test_snippetCreate(t *testing.T) { func Test_snippetCreate_Global(t *testing.T) { t.Parallel() repo := copyTestRepo(t) - cmd := exec.Command("../lab_bin", "snippet", "create", "-g", + + // Remove .git dir forcing the cmd to exec outside of a git repo + cmd := exec.Command("rm", "-rf", ".git") + cmd.Dir = repo + err := cmd.Run() + if err != nil { + t.Fatal(err) + } + + cmd = exec.Command("../lab_bin", "snippet", "create", "-g", "-m", "personal snippet title", "-m", "personal snippet description") - cmd.Dir = repo + cmd.Dir = repo rc, err := cmd.StdinPipe() if err != nil { t.Fatal(err) @@ -71,6 +82,52 @@ func Test_snippetCreate_Global(t *testing.T) { require.Contains(t, string(b), "https://gitlab.com/snippets/") } +// This test is a little ridiculus, if we find it doesn't work well on other +// envionments, we can just remove it. Its sole purpose is to test that a personal snippet can be created (with the users git editor) outside of a git repo. issue #98 +func Test_snippetCreate_Global_Editor(t *testing.T) { + t.Parallel() + repo := copyTestRepo(t) + + err := os.Rename(repo, "/tmp/testdata-6810350901254661225") + if err != nil { + t.Fatal(err) + } + repo = "/tmp/testdata-6810350901254661225" + defer func() { + coveragePath, _ := filepath.Glob("/tmp/coverage-*") + os.Rename(coveragePath[0], "../coverage-6810350901254661225.out") + os.RemoveAll(repo) + }() + + // Write the editor file here, since its tricky to get a file with + // contents in it otherwise. We need a file with contents to + // successfully create the snippet + err = ioutil.WriteFile("/tmp/SNIPCODE_EDITMSG", []byte("test personal snippet contents outside repo"), 0644) + if err != nil { + t.Fatal(err) + } + + // Remove .git dir forcing the cmd to exec outside of a git repo + cmd := exec.Command("rm", "-rf", ".git") + cmd.Dir = repo + err = cmd.Run() + if err != nil { + t.Fatal(err) + } + + cmd = exec.Command(os.ExpandEnv("$GOPATH/src/github.com/zaquestion/lab/lab_bin"), "snippet", "-g") + cmd.Env = []string{"PATH=/usr/local/bin:/usr/bin:/bin", "EDITOR=test -f"} + cmd.Dir = repo + + b, err := cmd.CombinedOutput() + if err != nil { + t.Log(string(b)) + t.Fatal(err) + } + + require.Contains(t, string(b), "https://gitlab.com/snippets/") +} + func Test_snipMsg(t *testing.T) { title, desc, err := snipMsg(nil, "snip title\nthis should be dropped") if err != nil { diff --git a/internal/git/edit.go b/internal/git/edit.go index 61dd8c0f..894ebba8 100644 --- a/internal/git/edit.go +++ b/internal/git/edit.go @@ -10,20 +10,31 @@ import ( "strings" ) -// Edit opens a file in the users editor and returns the title and body +// Edit opens a file in the users editor and returns the title and body. It +// store a temporary file in your .git directory or /tmp if accessed outside of +// a git repo. func Edit(filePrefix, message string) (string, string, error) { - gitDir, err := GitDir() - if err != nil { - return "", "", err + var ( + dir string + err error + ) + if InsideGitRepo() { + dir, err = GitDir() + if err != nil { + return "", "", err + } + } else { + dir = "/tmp" } - filePath := filepath.Join(gitDir, fmt.Sprintf("%s_EDITMSG", filePrefix)) + filePath := filepath.Join(dir, fmt.Sprintf("%s_EDITMSG", filePrefix)) + fmt.Println(filePath) editorPath, err := editorPath() if err != nil { return "", "", err } defer os.Remove(filePath) - // Write generated/tempate message to file + // Write generated/template message to file if _, err := os.Stat(filePath); os.IsNotExist(err) && message != "" { err = ioutil.WriteFile(filePath, []byte(message), 0644) if err != nil { diff --git a/internal/git/git.go b/internal/git/git.go index 6473e60b..a97dc880 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -186,3 +186,13 @@ func IsRemote(remote string) (bool, error) { return bytes.Contains(remotes, []byte(remote+"\n")), nil } + +// InsideGitRepo returns true when the current working directory is inside the +// working tree of a git repo +func InsideGitRepo() bool { + cmd := New("rev-parse", "--is-inside-work-tree") + cmd.Stdout = nil + cmd.Stderr = nil + out, _ := cmd.CombinedOutput() + return bytes.Contains(out, []byte("true\n")) +} diff --git a/internal/git/git_test.go b/internal/git/git_test.go index 8ab014cc..02a02c7f 100644 --- a/internal/git/git_test.go +++ b/internal/git/git_test.go @@ -94,3 +94,7 @@ func TestIsRemote(t *testing.T) { } require.True(t, res) } + +func TestInsideGitRepo(t *testing.T) { + require.True(t, InsideGitRepo()) +}