Skip to content

Commit

Permalink
fix: compatibility with submodules (#48)
Browse files Browse the repository at this point in the history
Previously githubinator couldn't find git data for files inside a submodule.
Now it generates URLs, for the correct repositories.

There's a new test for `dir` function, but the actual blame URL generation was tested manually on https://github.com/discourse/all-the-plugins and its submodules.
  • Loading branch information
CvX committed Jun 25, 2021
1 parent 747d344 commit 8dfbef1
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 9 deletions.
11 changes: 8 additions & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,15 @@ async function githubinator({
return err("could not find file")
}

const gitDir = git.dir(editorConfig.uri.fsPath)
if (gitDir == null) {
const gitDirectories = git.dir(editorConfig.uri.fsPath)

if (gitDirectories == null) {
return err("Could not find .git directory.")
}

const gitDir = gitDirectories.git
const repoDir = gitDirectories.repository

let headBranch: [string, string | null] | null = null
if (mainBranch) {
const res = await findShaForBranches(gitDir)
Expand Down Expand Up @@ -204,7 +209,7 @@ async function githubinator({
? createSha(head)
: createBranch(branchName),
relativeFilePath: editorConfig.fileName
? getRelativeFilePath(gitDir, editorConfig.fileName)
? getRelativeFilePath(repoDir, editorConfig.fileName)
: null,
})
if (parsedUrl != null) {
Expand Down
27 changes: 25 additions & 2 deletions src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ interface IRemote {
url?: string
}

interface IGitDirectories {
git: string
repository: string
}

export async function origin(
gitDir: string,
remote: string,
Expand Down Expand Up @@ -100,12 +105,30 @@ export function dir(filePath: string) {
function walkUpDirectories(
file_path: string,
file_or_folder: string,
): string | null {
): IGitDirectories | null {
let directory = file_path
while (true) {
const newPath = path.resolve(directory, file_or_folder)
if (fs.existsSync(newPath)) {
return newPath
if (fs.lstatSync(newPath).isFile()) {
const submoduleMatch = fs
.readFileSync(newPath, "utf8")
.match(/gitdir: (.+)/)

if (submoduleMatch) {
return {
git: path.resolve(path.join(directory, submoduleMatch[1])),
repository: directory,
}
} else {
return null
}
} else {
return {
git: newPath,
repository: directory,
}
}
}
const newDirectory = path.dirname(directory)
if (newDirectory === directory) {
Expand Down
30 changes: 30 additions & 0 deletions src/test/suite/git.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { dir } from "../../git"
import * as assert from "assert"
import * as path from "path"
import * as fs from "fs"

suite("git", async () => {
test("dir", () => {
const repoPath = path.normalize(path.join(__dirname, "../../.."))
const gitPath = path.join(repoPath, ".git")

assert.deepStrictEqual(dir(__dirname), {
git: gitPath,
repository: repoPath,
})
assert.deepStrictEqual(dir(repoPath), {
git: gitPath,
repository: repoPath,
})

const contents = "gitdir: ../../../../.git/modules/test_submodule"
const submodulePath = path.join(__dirname, "test_submodule")
fs.mkdirSync(submodulePath, { recursive: true })
fs.writeFileSync(path.join(submodulePath, ".git"), contents)

assert.deepStrictEqual(dir(submodulePath), {
git: path.join(repoPath, ".git/modules/test_submodule"),
repository: submodulePath,
})
})
})
10 changes: 6 additions & 4 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import * as path from "path"
import * as fs from "fs"
/** Get path of file relative to git root. */
export function getRelativeFilePath(gitDir: string, fileName: string): string {
/** Get path of file relative to repository root. */
export function getRelativeFilePath(
repositoryDir: string,
fileName: string,
): string {
const resolvedFileName = fs.realpathSync(fileName)
const gitProjectRoot = path.dirname(gitDir) + "/"
return resolvedFileName.replace(gitProjectRoot, "")
return resolvedFileName.replace(repositoryDir, "")
}

/** Convert url/hostname to hostname
Expand Down

0 comments on commit 8dfbef1

Please sign in to comment.