summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-08-08 00:03:28 +1000
committerGitHub <noreply@github.com>2023-08-08 00:03:28 +1000
commit4c89f9fba58d401540cc10e896be7f7dd4266a80 (patch)
tree704f0165708291f331af17f7e12f38a717778558
parent579791e7bc8261e9ed578f882f4b8b11a486bf78 (diff)
parent8e7958f78b0dcdbbeeb39972d47544edfe61d42f (diff)
Fix seg-fault when opening submodule in nested folder (#2903)
-rw-r--r--pkg/commands/git_commands/repo_paths.go31
-rw-r--r--pkg/commands/git_commands/repo_paths_test.go29
2 files changed, 52 insertions, 8 deletions
diff --git a/pkg/commands/git_commands/repo_paths.go b/pkg/commands/git_commands/repo_paths.go
index 6921c21b6..1fdc016d8 100644
--- a/pkg/commands/git_commands/repo_paths.go
+++ b/pkg/commands/git_commands/repo_paths.go
@@ -157,6 +157,10 @@ func linkedWorktreeGitDirPath(fs afero.Fs, worktreePath string) (string, error)
}
gitDir := strings.TrimPrefix(gitDirLine[0], "gitdir: ")
+
+ // For windows support
+ gitDir = filepath.ToSlash(gitDir)
+
return gitDir, nil
}
@@ -194,19 +198,32 @@ func getCurrentRepoGitDirPath(
return "", "", errors.Errorf("could not find git dir for %s: %v", currentPath, err)
}
- // confirm whether the next directory up is the worktrees/submodules directory
+ _, err = fs.Stat(worktreeGitPath)
+ if err != nil {
+ if os.IsNotExist(err) {
+ // hardcoding error to get around windows-specific error message
+ return "", "", errors.Errorf("could not find git dir for %s. %s does not exist", currentPath, worktreeGitPath)
+ }
+ return "", "", errors.Errorf("could not find git dir for %s: %v", currentPath, err)
+ }
+
+ // confirm whether the next directory up is the worktrees directory
parent := path.Dir(worktreeGitPath)
- if path.Base(parent) != "worktrees" && path.Base(parent) != "modules" {
- return "", "", errors.Errorf("could not find git dir for %s", currentPath)
+ if path.Base(parent) == "worktrees" {
+ gitDirPath := path.Dir(parent)
+ return gitDirPath, path.Dir(gitDirPath), nil
}
- // if it's a submodule, we treat it as its own repo
- if path.Base(parent) == "modules" {
+ // Unlike worktrees, submodules can be nested arbitrarily deep, so we check
+ // if the `modules` directory is anywhere up the chain.
+ if strings.Contains(worktreeGitPath, "/modules/") {
+ // For submodules, we just return the path directly
return worktreeGitPath, currentPath, nil
}
- gitDirPath := path.Dir(parent)
- return gitDirPath, path.Dir(gitDirPath), nil
+ // If this error causes issues, we could relax the constraint and just always
+ // return the path
+ return "", "", errors.Errorf("could not find git dir for %s: path is not under `worktrees` or `modules` directories", currentPath)
}
// takes a path containing a symlink and returns the true path
diff --git a/pkg/commands/git_commands/repo_paths_test.go b/pkg/commands/git_commands/repo_paths_test.go
index 52ad9bd8f..6533b733d 100644
--- a/pkg/commands/git_commands/repo_paths_test.go
+++ b/pkg/commands/git_commands/repo_paths_test.go
@@ -73,7 +73,7 @@ func TestGetRepoPathsAux(t *testing.T) {
},
Path: "/path/to/repo/worktree2",
Expected: nil,
- Err: errors.New("failed to get repo git dir path: could not find git dir for /path/to/repo/worktree2"),
+ Err: errors.New("failed to get repo git dir path: could not find git dir for /path/to/repo/worktree2. /nonexistant does not exist"),
},
{
Name: "submodule",
@@ -92,6 +92,33 @@ func TestGetRepoPathsAux(t *testing.T) {
},
Err: nil,
},
+ {
+ Name: "submodule in nested directory",
+ BeforeFunc: func(fs afero.Fs) {
+ _ = fs.MkdirAll("/path/to/repo/.git/modules/my/submodule1", 0o755)
+ _ = afero.WriteFile(fs, "/path/to/repo/my/submodule1/.git", []byte("gitdir: /path/to/repo/.git/modules/my/submodule1"), 0o644)
+ },
+ Path: "/path/to/repo/my/submodule1",
+ Expected: &RepoPaths{
+ currentPath: "/path/to/repo/my/submodule1",
+ worktreePath: "/path/to/repo/my/submodule1",
+ worktreeGitDirPath: "/path/to/repo/.git/modules/my/submodule1",
+ repoPath: "/path/to/repo/my/submodule1",
+ repoGitDirPath: "/path/to/repo/.git/modules/my/submodule1",
+ repoName: "submodule1",
+ },
+ Err: nil,
+ },
+ {
+ Name: "submodule git dir not under .git/modules",
+ BeforeFunc: func(fs afero.Fs) {
+ _ = fs.MkdirAll("/random/submodule1", 0o755)
+ _ = afero.WriteFile(fs, "/path/to/repo/my/submodule1/.git", []byte("gitdir: /random/submodule1"), 0o644)
+ },
+ Path: "/path/to/repo/my/submodule1",
+ Expected: nil,
+ Err: errors.New("failed to get repo git dir path: could not find git dir for /path/to/repo/my/submodule1: path is not under `worktrees` or `modules` directories"),
+ },
}
for _, s := range scenarios {