fix(git): git doesnt show branch suggesstion properly
This commit is contained in:
@@ -64,7 +64,7 @@ jobs:
|
|||||||
tag_name: nightly
|
tag_name: nightly
|
||||||
name: ${{ steps.version.outputs.version }}
|
name: ${{ steps.version.outputs.version }}
|
||||||
body: |
|
body: |
|
||||||
🌙 **Nightly build** — `${{ steps.version.outputs.version }}`
|
🌙 **Nightly build** - `${{ steps.version.outputs.version }}`
|
||||||
|
|
||||||
auto-built from commit `${{ github.sha }}`
|
auto-built from commit `${{ github.sha }}`
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func Register(s *Spec) {
|
|||||||
Registry[s.Name] = s
|
Registry[s.Name] = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetRegistry clears all registered specs — use in tests only
|
// ResetRegistry clears all registered specs - use in tests only
|
||||||
func ResetRegistry() {
|
func ResetRegistry() {
|
||||||
Registry = make(map[string]*Spec)
|
Registry = make(map[string]*Spec)
|
||||||
}
|
}
|
||||||
|
|||||||
+81
-39
@@ -9,16 +9,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// GitRemoteGenerator suggests git remotes
|
// GitRemoteGenerator suggests git remotes
|
||||||
func GitRemoteGenerator(tokens []string, prefix string, partial string) []core.Suggestion {
|
func GitRemoteGenerator(tokens []string, prefix string, _ string) []core.Suggestion {
|
||||||
return getGitResults(prefix, "remote")
|
return getGitResults(tokens, prefix, "remote")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GitStashGenerator suggests git stashes
|
// GitStashGenerator suggests git stashes
|
||||||
func GitStashGenerator(tokens []string, prefix string, partial string) []core.Suggestion {
|
func GitStashGenerator(tokens []string, prefix string, _ string) []core.Suggestion {
|
||||||
return getGitResults(prefix, "stash", "list", "--format=%gd: %gs")
|
return getGitResults(tokens, prefix, "stash", "list", "--format=%gd: %gs")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGitResults(prefix string, args ...string) []core.Suggestion {
|
func getGitResults(tokens []string, _ string, args ...string) []core.Suggestion {
|
||||||
|
return getGitResultsFiltered(tokens, "_", false, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGitResultsFiltered(tokens []string, _ string, localOnly bool, args ...string) []core.Suggestion {
|
||||||
cwd := core.GetCWD()
|
cwd := core.GetCWD()
|
||||||
cmd := exec.CommandContext(context.Background(), "git", args...)
|
cmd := exec.CommandContext(context.Background(), "git", args...)
|
||||||
cmd.Dir = cwd
|
cmd.Dir = cwd
|
||||||
@@ -28,9 +32,7 @@ func getGitResults(prefix string, args ...string) []core.Suggestion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
activeBranch := ""
|
activeBranch := ""
|
||||||
switch args[0] {
|
if args[0] == "branch" {
|
||||||
case "branch":
|
|
||||||
// Try to find the current active branch to filter it out later
|
|
||||||
activeCmd := exec.CommandContext(context.Background(), "git", "rev-parse", "--abbrev-ref", "HEAD")
|
activeCmd := exec.CommandContext(context.Background(), "git", "rev-parse", "--abbrev-ref", "HEAD")
|
||||||
activeCmd.Dir = cwd
|
activeCmd.Dir = cwd
|
||||||
if activeOut, err := activeCmd.Output(); err == nil {
|
if activeOut, err := activeCmd.Output(); err == nil {
|
||||||
@@ -38,24 +40,52 @@ func getGitResults(prefix string, args ...string) []core.Suggestion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seen := make(map[string]bool)
|
||||||
lines := strings.Split(string(out), "\n")
|
lines := strings.Split(string(out), "\n")
|
||||||
var results []core.Suggestion
|
var results []core.Suggestion
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
if line == "" || strings.HasPrefix(line, "*") { // skip active branch marker if any
|
if line == "" {
|
||||||
line = strings.TrimSpace(strings.TrimPrefix(line, "*"))
|
|
||||||
}
|
|
||||||
if line == "" || line == activeBranch {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle remote branches that look like "remotes/origin/main"
|
isRemote := strings.HasPrefix(line, "remotes/")
|
||||||
line = strings.TrimPrefix(line, "remotes/")
|
|
||||||
|
// skip remote tracking branches if localOnly mode
|
||||||
|
if localOnly && isRemote {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// strip remotes/ prefix to get the usable form: origin/main
|
||||||
|
if isRemote {
|
||||||
|
line = strings.TrimPrefix(line, "remotes/")
|
||||||
|
}
|
||||||
|
|
||||||
|
// only skip active branch for checkout/switch commands
|
||||||
|
isCheckoutOrSwitch := false
|
||||||
|
if len(tokens) > 1 && (tokens[1] == "checkout" || tokens[1] == "switch") {
|
||||||
|
isCheckoutOrSwitch = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if isCheckoutOrSwitch {
|
||||||
|
if line == activeBranch || line == "origin/"+activeBranch {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dedup: origin/dev and dev would both appear with -a; skip if already seen the short name
|
||||||
|
shortName := line
|
||||||
|
if idx := strings.Index(line, "/"); isRemote && idx != -1 {
|
||||||
|
shortName = line[idx+1:] // "origin/dev" → "dev"
|
||||||
|
}
|
||||||
|
if seen[shortName] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[shortName] = true
|
||||||
|
|
||||||
suggestionCmd := line
|
suggestionCmd := line
|
||||||
suggestionDesc := args[0]
|
suggestionDesc := args[0]
|
||||||
|
|
||||||
// for stash list, the format is "stash@{0}: message"
|
|
||||||
if args[0] == "stash" {
|
if args[0] == "stash" {
|
||||||
parts := strings.SplitN(line, ": ", 2)
|
parts := strings.SplitN(line, ": ", 2)
|
||||||
if len(parts) == 2 {
|
if len(parts) == 2 {
|
||||||
@@ -65,15 +95,16 @@ func getGitResults(prefix string, args ...string) []core.Suggestion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
results = append(results, core.Suggestion{
|
results = append(results, core.Suggestion{
|
||||||
Cmd: prefix + " " + suggestionCmd,
|
Cmd: suggestionCmd,
|
||||||
Desc: suggestionDesc,
|
Desc: suggestionDesc,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
// GitBranchGenerator suggests git branches
|
|
||||||
func GitBranchGenerator(tokens []string, prefix string, partial string) []core.Suggestion {
|
// GitBranchGenerator suggests git branches (local + remote, deduped)
|
||||||
|
func GitBranchGenerator(tokens []string, prefix string, _ string) []core.Suggestion {
|
||||||
// check if we are in "create" mode (-b or -B or -c)
|
// check if we are in "create" mode (-b or -B or -c)
|
||||||
isCreateMode := false
|
isCreateMode := false
|
||||||
for _, t := range tokens {
|
for _, t := range tokens {
|
||||||
@@ -87,35 +118,46 @@ func GitBranchGenerator(tokens []string, prefix string, partial string) []core.S
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return getGitResults(prefix, "branch", "-a", "--format=%(refname:short)")
|
return getGitResults(tokens, prefix, "branch", "-a", "--format=%(refname:short)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GitPushPullGenerator suggests remotes for the first arg, and branches for the second
|
// gitLocalBranchGenerator is like GitBranchGenerator but only local branches
|
||||||
func GitPushPullGenerator(tokens []string, prefix string, partial string) []core.Suggestion {
|
// used for push/pull where remote tracking branches cause duplicates
|
||||||
// Filter out flags to find positional arguments
|
func gitLocalBranchGenerator(tokens []string, prefix string, _ string) []core.Suggestion {
|
||||||
args := []string{}
|
isCreateMode := false
|
||||||
for i := 1; i < len(tokens); i++ {
|
for _, t := range tokens {
|
||||||
t := tokens[i]
|
if t == "-b" || t == "-B" || t == "-c" || t == "-C" {
|
||||||
if t != "" && !strings.HasPrefix(t, "-") {
|
isCreateMode = true
|
||||||
args = append(args, t)
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if isCreateMode {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return getGitResultsFiltered(tokens, prefix, true, "branch", "-a", "--format=%(refname:short)")
|
||||||
|
}
|
||||||
|
|
||||||
// args[0] is subcommand (push/pull)
|
|
||||||
// args[1] should be remote
|
|
||||||
// args[2] should be branch
|
|
||||||
|
|
||||||
// If we only have subcommand, suggest remotes
|
func GitPushPullGenerator(tokens []string, prefix string, partial string) []core.Suggestion {
|
||||||
if len(args) == 1 {
|
// count completed positional args (not flags, not the partial being typed)
|
||||||
|
// tokens[0] = "git", tokens[1] = "push"/"pull", so start at 2
|
||||||
|
// exclude tokens[len-1] because that's the partial being typed
|
||||||
|
pArgs := []string{}
|
||||||
|
for i := 2; i < len(tokens)-1; i++ {
|
||||||
|
t := tokens[i]
|
||||||
|
if t == "" || strings.HasPrefix(t, "-") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pArgs = append(pArgs, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// no remote confirmed yet, suggest remotes
|
||||||
|
if len(pArgs) == 0 {
|
||||||
return GitRemoteGenerator(tokens, prefix, partial)
|
return GitRemoteGenerator(tokens, prefix, partial)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have subcommand + remote, suggest branches
|
// remote is set, suggest local branches only (no duplicates with origin/xxx)
|
||||||
if len(args) == 2 {
|
return gitLocalBranchGenerator(tokens, prefix, partial)
|
||||||
return GitBranchGenerator(tokens, prefix, partial)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -279,7 +321,7 @@ func init() {
|
|||||||
{
|
{
|
||||||
Name: "tag",
|
Name: "tag",
|
||||||
Description: "manage tags",
|
Description: "manage tags",
|
||||||
Generator: func(tokens []string, prefix string, partial string) []core.Suggestion { return getGitResults(prefix, "tag", "-l") },
|
Generator: func(tokens []string, prefix string, partial string) []core.Suggestion { return getGitResults(tokens, prefix, "tag", "-l") },
|
||||||
Options: []core.Option{
|
Options: []core.Option{
|
||||||
{Name: "-a", Description: "annotated tag"},
|
{Name: "-a", Description: "annotated tag"},
|
||||||
{Name: "-d", Description: "delete tag"},
|
{Name: "-d", Description: "delete tag"},
|
||||||
|
|||||||
+227
-86
@@ -12,42 +12,101 @@ import (
|
|||||||
_ "github.com/versenilvis/iris/commands/dev"
|
_ "github.com/versenilvis/iris/commands/dev"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGitSuggestions(t *testing.T) {
|
// setupGitRepo creates a real git repo in a temp dir with:
|
||||||
// Setup a real git repo in temp dir for testing branch generators
|
// - local branches: main (HEAD), dev, feature/login, stable
|
||||||
tmp := t.TempDir()
|
// - remote branches: origin/main, origin/dev (written directly to .git/refs)
|
||||||
oldWd, _ := os.Getwd()
|
// - a tag: v1.0
|
||||||
_ = os.Chdir(tmp)
|
// - a stash entry
|
||||||
defer func() { _ = os.Chdir(oldWd) }()
|
func setupGitRepo(t *testing.T) (tmp string, cleanup func()) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
tmp = t.TempDir()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
// Initialize git repo
|
|
||||||
_ = exec.CommandContext(ctx, "git", "init").Run()
|
|
||||||
|
|
||||||
_ = exec.CommandContext(ctx, "git", "config", "user.email", "iris-test@example.com").Run() // this is for ci/cd
|
run := func(args ...string) {
|
||||||
_ = exec.CommandContext(ctx, "git", "config", "user.name", "Iris Test").Run() // this is for ci/cd
|
t.Helper()
|
||||||
|
out, err := exec.CommandContext(ctx, args[0], args[1:]...).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("git cmd %v: %s", args, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ = os.WriteFile(filepath.Join(tmp, "file.go"), []byte("package main"), 0644)
|
run("git", "-C", tmp, "init", "--initial-branch=main")
|
||||||
_ = exec.CommandContext(ctx, "git", "add", ".").Run()
|
|
||||||
_ = exec.CommandContext(ctx, "git", "commit", "-m", "initial").Run()
|
|
||||||
|
|
||||||
// Create branches
|
// use fallback for older git that doesn't support --initial-branch
|
||||||
_ = exec.CommandContext(ctx, "git", "branch", "feature/login").Run()
|
if _, err := os.Stat(filepath.Join(tmp, ".git", "refs", "heads", "main")); err != nil {
|
||||||
_ = exec.CommandContext(ctx, "git", "branch", "dev").Run()
|
run("git", "-C", tmp, "init")
|
||||||
_ = exec.CommandContext(ctx, "git", "tag", "v1.0").Run()
|
}
|
||||||
|
|
||||||
// Setup stash
|
run("git", "-C", tmp, "config", "user.email", "iris-test@example.com") // this is for ci/cd
|
||||||
_ = os.WriteFile(filepath.Join(tmp, "dirty.go"), []byte("dirty"), 0644)
|
run("git", "-C", tmp, "config", "user.name", "Iris Test") // this is for ci/cd
|
||||||
_ = exec.CommandContext(ctx, "git", "add", ".").Run()
|
|
||||||
_ = exec.CommandContext(ctx, "git", "stash").Run()
|
// initial commit so branches can be created
|
||||||
|
if err := os.WriteFile(filepath.Join(tmp, "file.go"), []byte("package main"), 0644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
run("git", "-C", tmp, "add", ".")
|
||||||
|
run("git", "-C", tmp, "commit", "-m", "initial")
|
||||||
|
|
||||||
|
// local branches (incl. slash branch to test tokenization)
|
||||||
|
run("git", "-C", tmp, "branch", "dev")
|
||||||
|
run("git", "-C", tmp, "branch", "stable")
|
||||||
|
run("git", "-C", tmp, "branch", "feature/login")
|
||||||
|
|
||||||
|
// tag
|
||||||
|
run("git", "-C", tmp, "tag", "v1.0")
|
||||||
|
|
||||||
|
// add a real remote in config
|
||||||
|
run("git", "-C", tmp, "remote", "add", "origin", "https://github.com/versenilvis/iris.git")
|
||||||
|
|
||||||
|
// write fake remote refs directly (no need for actual remote server)
|
||||||
|
for _, ref := range []string{"main", "dev"} {
|
||||||
|
dir := filepath.Join(tmp, ".git", "refs", "remotes", "origin")
|
||||||
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// point them to the same commit as HEAD for simplicity
|
||||||
|
headBytes, err := os.ReadFile(filepath.Join(tmp, ".git", "refs", "heads", "main"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := os.WriteFile(filepath.Join(dir, ref), headBytes, 0644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stash entry
|
||||||
|
if err := os.WriteFile(filepath.Join(tmp, "dirty.go"), []byte("dirty"), 0644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
run("git", "-C", tmp, "add", ".")
|
||||||
|
run("git", "-C", tmp, "stash")
|
||||||
|
|
||||||
|
// chdir into repo so generators can run git commands
|
||||||
|
oldWd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := os.Chdir(tmp); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup = func() { _ = os.Chdir(oldWd) }
|
||||||
|
return tmp, cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGitSuggestions(t *testing.T) {
|
||||||
|
tmp, cleanup := setupGitRepo(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
t.Run("git top-level", func(t *testing.T) {
|
t.Run("git top-level", func(t *testing.T) {
|
||||||
res := core.Lookup("git ")
|
res := core.Lookup("git ")
|
||||||
if len(res) < 10 {
|
if len(res) < 10 {
|
||||||
t.Errorf("Expected many git subcommands, got %d", len(res))
|
t.Errorf("expected many git subcommands, got %d", len(res))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("git tag -d show tags", func(t *testing.T) {
|
t.Run("tag -d shows tags", func(t *testing.T) {
|
||||||
res := core.Lookup("git tag -d ")
|
res := core.Lookup("git tag -d ")
|
||||||
found := false
|
found := false
|
||||||
for _, r := range res {
|
for _, r := range res {
|
||||||
@@ -56,12 +115,11 @@ func TestGitSuggestions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
t.Error("git tag -d should suggest existing tags")
|
t.Error("git tag -d should suggest v1.0")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("git push HEAD options", func(t *testing.T) {
|
t.Run("push HEAD options", func(t *testing.T) {
|
||||||
// git push origin HEAD --force -> should show --force
|
|
||||||
res := core.Lookup("git push origin HEAD --")
|
res := core.Lookup("git push origin HEAD --")
|
||||||
found := false
|
found := false
|
||||||
for _, r := range res {
|
for _, r := range res {
|
||||||
@@ -74,8 +132,7 @@ func TestGitSuggestions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("git push upstream options", func(t *testing.T) {
|
t.Run("push -u origin suggests branches", func(t *testing.T) {
|
||||||
// git push -u origin -> show branches
|
|
||||||
res := core.Lookup("git push -u origin ")
|
res := core.Lookup("git push -u origin ")
|
||||||
found := false
|
found := false
|
||||||
for _, r := range res {
|
for _, r := range res {
|
||||||
@@ -84,15 +141,152 @@ func TestGitSuggestions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
t.Error("git push -u origin should suggest branches")
|
t.Errorf("git push -u origin should suggest branches, got: %v", res)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("git reset options", func(t *testing.T) {
|
t.Run("push origin suggests active branch", func(t *testing.T) {
|
||||||
// git reset --soft origin/main -> should be accepted (just testing lookup doesn't crash)
|
ctx := context.Background()
|
||||||
_ = core.Lookup("git reset --soft origin/main ")
|
out, err := exec.CommandContext(ctx, "git", "rev-parse", "--abbrev-ref", "HEAD").Output()
|
||||||
|
if err != nil {
|
||||||
|
t.Skip("can't determine HEAD branch")
|
||||||
|
}
|
||||||
|
activeBranch := strings.TrimSpace(string(out))
|
||||||
|
res := core.Lookup("git push origin ")
|
||||||
|
found := false
|
||||||
|
for _, r := range res {
|
||||||
|
parts := strings.Fields(r.Cmd)
|
||||||
|
if len(parts) > 0 && parts[len(parts)-1] == activeBranch {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Errorf("git push origin should suggest active branch '%s'", activeBranch)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// git reset HEAD -> show files
|
t.Run("push origin no duplicate branches", func(t *testing.T) {
|
||||||
|
res := core.Lookup("git push origin ")
|
||||||
|
seen := make(map[string]int)
|
||||||
|
for _, r := range res {
|
||||||
|
parts := strings.Fields(r.Cmd)
|
||||||
|
if len(parts) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
branch := parts[len(parts)-1]
|
||||||
|
seen[branch]++
|
||||||
|
if seen[branch] > 1 {
|
||||||
|
t.Errorf("duplicate branch suggestion: %s", branch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
t.Run("branch with slash is suggested correctly", func(t *testing.T) {
|
||||||
|
res := core.Lookup("git checkout ")
|
||||||
|
found := false
|
||||||
|
for _, r := range res {
|
||||||
|
if strings.Contains(r.Cmd, "feature/login") {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Error("git checkout should suggest 'feature/login'")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("remote branches suggested for push", func(t *testing.T) {
|
||||||
|
res := core.Lookup("git push origin ")
|
||||||
|
cmdStr := ""
|
||||||
|
for _, r := range res {
|
||||||
|
cmdStr += r.Cmd + " "
|
||||||
|
}
|
||||||
|
// should have at least dev or main from branch list
|
||||||
|
if !strings.Contains(cmdStr, "dev") && !strings.Contains(cmdStr, "main") {
|
||||||
|
t.Errorf("git push origin should suggest local branches, got: %s", cmdStr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("active branch not suggested for checkout", func(t *testing.T) {
|
||||||
|
// find actual active branch
|
||||||
|
ctx := context.Background()
|
||||||
|
out, err := exec.CommandContext(ctx, "git", "rev-parse", "--abbrev-ref", "HEAD").Output()
|
||||||
|
if err != nil {
|
||||||
|
t.Skip("can't determine HEAD branch")
|
||||||
|
}
|
||||||
|
activeBranch := strings.TrimSpace(string(out))
|
||||||
|
|
||||||
|
res := core.Lookup("git checkout ")
|
||||||
|
for _, r := range res {
|
||||||
|
// the suggestion should not contain the active branch as a standalone word
|
||||||
|
parts := strings.Fields(r.Cmd)
|
||||||
|
for _, p := range parts {
|
||||||
|
if p == activeBranch {
|
||||||
|
t.Errorf("git checkout should not suggest active branch '%s', got: %s", activeBranch, r.Cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("checkout -b no suggest", func(t *testing.T) {
|
||||||
|
res := core.Lookup("git checkout -b ")
|
||||||
|
for _, r := range res {
|
||||||
|
if strings.Contains(r.Cmd, "dev") {
|
||||||
|
t.Error("git checkout -b should not suggest existing branches")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("switch -c no suggest", func(t *testing.T) {
|
||||||
|
res := core.Lookup("git switch -c ")
|
||||||
|
for _, r := range res {
|
||||||
|
if strings.Contains(r.Cmd, "dev") {
|
||||||
|
t.Error("git switch -c should not suggest existing branches")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("stash variants suggest entries", func(t *testing.T) {
|
||||||
|
for _, cmd := range []string{"apply", "drop", "pop"} {
|
||||||
|
res := core.Lookup("git stash " + cmd + " ")
|
||||||
|
found := false
|
||||||
|
for _, r := range res {
|
||||||
|
if strings.Contains(r.Cmd, "stash@{0}") {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Errorf("git stash %s should suggest stash@{0}", cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("remote subcommands suggest remotes", func(t *testing.T) {
|
||||||
|
for _, cmd := range []string{"remove", "rename", "set-url"} {
|
||||||
|
res := core.Lookup("git remote " + cmd + " ")
|
||||||
|
found := false
|
||||||
|
for _, r := range res {
|
||||||
|
// origin is our fake remote
|
||||||
|
if strings.Contains(r.Cmd, "origin") {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Errorf("git remote %s should suggest origin", cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("not a git repo no crash", func(t *testing.T) {
|
||||||
|
emptyDir := t.TempDir()
|
||||||
|
_ = os.Chdir(emptyDir)
|
||||||
|
defer func() { _ = os.Chdir(tmp) }()
|
||||||
|
_ = core.Lookup("git status ")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("reset options", func(t *testing.T) {
|
||||||
|
_ = core.Lookup("git reset --soft origin/main ")
|
||||||
res := core.Lookup("git reset HEAD ")
|
res := core.Lookup("git reset HEAD ")
|
||||||
found := false
|
found := false
|
||||||
for _, r := range res {
|
for _, r := range res {
|
||||||
@@ -104,57 +298,4 @@ func TestGitSuggestions(t *testing.T) {
|
|||||||
t.Error("git reset HEAD should suggest file.go")
|
t.Error("git reset HEAD should suggest file.go")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("git checkout -b no suggest", func(t *testing.T) {
|
|
||||||
// git checkout -b -> should NOT suggest branches
|
|
||||||
res := core.Lookup("git checkout -b ")
|
|
||||||
for _, r := range res {
|
|
||||||
if strings.Contains(r.Cmd, "dev") {
|
|
||||||
t.Error("git checkout -b should not suggest existing branches")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("git switch -c no suggest", func(t *testing.T) {
|
|
||||||
res := core.Lookup("git switch -c ")
|
|
||||||
for _, r := range res {
|
|
||||||
if strings.Contains(r.Cmd, "dev") {
|
|
||||||
t.Error("git switch -c should not suggest existing branches")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("stash entries", func(t *testing.T) {
|
|
||||||
res := core.Lookup("git stash pop ")
|
|
||||||
found := false
|
|
||||||
for _, r := range res {
|
|
||||||
if strings.Contains(r.Cmd, "stash@{0}") {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
t.Error("git stash pop should suggest stash@{0}")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("not a git repo", func(t *testing.T) {
|
|
||||||
emptyDir := t.TempDir()
|
|
||||||
_ = os.Chdir(emptyDir)
|
|
||||||
// Should not crash
|
|
||||||
_ = core.Lookup("git status ")
|
|
||||||
_ = os.Chdir(tmp)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("active branch filter", func(t *testing.T) {
|
|
||||||
// find current branch
|
|
||||||
out, _ := exec.CommandContext(ctx, "git", "rev-parse", "--abbrev-ref", "HEAD").Output()
|
|
||||||
current := strings.TrimSpace(string(out))
|
|
||||||
|
|
||||||
res := core.Lookup("git checkout ")
|
|
||||||
for _, r := range res {
|
|
||||||
if strings.Contains(r.Cmd, current) && !strings.Contains(r.Cmd, "remotes/") {
|
|
||||||
t.Errorf("Should not suggest active branch '%s'", current)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user