-
Notifications
You must be signed in to change notification settings - Fork 951
chore(git): find the closer .git #4588
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| import { test, expect } from "vitest"; | ||
| import fs from "fs/promises"; | ||
| import path from "node:path"; | ||
| import os from "node:os"; | ||
| import { git } from "@commitlint/test"; | ||
|
|
||
| import toplevel from "./index.js"; | ||
|
|
||
| test("should find git toplevel from repo root", async () => { | ||
| const cwd = await git.bootstrap(); | ||
| const result = await toplevel(cwd); | ||
| expect(result).toBe(cwd); | ||
| }); | ||
|
|
||
| test("should find git toplevel from subdirectory", async () => { | ||
| const cwd = await git.bootstrap(); | ||
| const subdir = path.join(cwd, "subdir"); | ||
| await fs.mkdir(subdir); | ||
|
|
||
| const result = await toplevel(subdir); | ||
| expect(result).toBe(cwd); | ||
| }); | ||
|
|
||
| test("should prefer closer .git directory over farther .git file", async () => { | ||
| // Create a parent directory with a .git file (simulating dotfiles bare repo) | ||
| const parentDir = await fs.mkdtemp(path.join(os.tmpdir(), "parent-")); | ||
| const gitFileContent = `gitdir: ${path.join(parentDir, ".rcfiles")}`; | ||
| await fs.writeFile(path.join(parentDir, ".git"), gitFileContent); | ||
| await fs.mkdir(path.join(parentDir, ".rcfiles")); | ||
|
|
||
| // Create a child git repo inside the parent | ||
| const childDir = path.join(parentDir, "child-repo"); | ||
| await fs.mkdir(childDir); | ||
| await fs.mkdir(path.join(childDir, ".git")); | ||
|
|
||
| // The toplevel should be the child repo, not the parent | ||
| const result = await toplevel(childDir); | ||
| expect(result).toBe(childDir); | ||
|
|
||
| // Cleanup | ||
| await fs.rm(parentDir, { recursive: true }); | ||
| }); | ||
|
|
||
| test("should handle .git file (submodule) correctly", async () => { | ||
| const cwd = await git.bootstrap(); | ||
|
|
||
| // Create a submodule-like structure with a .git file | ||
| const submoduleDir = path.join(cwd, "submodule"); | ||
| await fs.mkdir(submoduleDir); | ||
| const gitFileContent = `gitdir: ${path.join(cwd, ".git", "modules", "submodule")}`; | ||
| await fs.writeFile(path.join(submoduleDir, ".git"), gitFileContent); | ||
|
|
||
| const result = await toplevel(submoduleDir); | ||
| expect(result).toBe(submoduleDir); | ||
| }); | ||
|
|
||
| test("should return undefined when no .git found", async () => { | ||
| const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "no-git-")); | ||
|
|
||
| const result = await toplevel(tmpDir); | ||
| expect(result).toBeUndefined(); | ||
|
|
||
| await fs.rm(tmpDir, { recursive: true }); | ||
| }); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,5 +23,10 @@ async function searchDotGit(cwd?: string) { | |||||||||||||||
| const foundFile = await findUp(".git", { cwd, type: "file" }); | ||||||||||||||||
| const foundDir = await findUp(".git", { cwd, type: "directory" }); | ||||||||||||||||
|
|
||||||||||||||||
| if (foundFile && foundDir) { | ||||||||||||||||
| // Return whichever is deeper (closer to cwd) by comparing path lengths | ||||||||||||||||
| return foundFile.length > foundDir.length ? foundFile : foundDir; | ||||||||||||||||
|
Comment on lines
+27
to
+28
|
||||||||||||||||
| // Return whichever is deeper (closer to cwd) by comparing path lengths | |
| return foundFile.length > foundDir.length ? foundFile : foundDir; | |
| // Return whichever is deeper (closer to cwd) by comparing path segment counts | |
| const fileDepth = path.resolve(foundFile).split(path.sep).length; | |
| const dirDepth = path.resolve(foundDir).split(path.sep).length; | |
| return fileDepth > dirDepth ? foundFile : foundDir; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says "whichever is deeper (closer to cwd)" but the code returns the longer path. In the context of file paths, "deeper" typically means more nested (more path segments), not a longer string. This mismatch between comment and implementation could be confusing.