Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "Fix build cache failures when running inside a git linked worktree via a pre-commit hook, caused by GIT_DIR being set to the per-worktree metadata directory",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generate another changelog (with type "none") for @microsoft/rush so we can do a Rush publish with this change.

"type": "patch",
"packageName": "@rushstack/package-deps-hash"
}
],
"packageName": "@rushstack/package-deps-hash",
"email": "kfleischman@squarespace.com"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"email": "kfleischman@squarespace.com"
"email": "istateside@users.noreply.github.com"

}
42 changes: 36 additions & 6 deletions libraries/package-deps-hash/src/getRepoState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,28 @@ const STANDARD_GIT_OPTIONS: readonly string[] = [
// `git hash-object` aborts the process. Such files are typically untracked artifacts left behind
// by tooling (e.g. stray `nul` from a shell redirect).
const WINDOWS_RESERVED_BASENAMES: ReadonlySet<string> = new Set([
'CON', 'PRN', 'AUX', 'NUL',
'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9',
'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9'
'CON',
'PRN',
'AUX',
'NUL',
'COM1',
'COM2',
'COM3',
'COM4',
'COM5',
'COM6',
'COM7',
'COM8',
'COM9',
'LPT1',
'LPT2',
'LPT3',
'LPT4',
'LPT5',
'LPT6',
'LPT7',
'LPT8',
'LPT9'
Comment on lines +36 to +57
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change came from the pre-commit prettier script - not sure if my dev environment isn't set up correctly, but I can revert this specific change if needed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. Don't worry about it.

]);

/**
Expand Down Expand Up @@ -254,6 +273,14 @@ export function parseGitStatus(output: string): Map<string, boolean> {

const repoRootCache: Map<string, string> = new Map();

// Strip GIT_DIR/GIT_WORK_TREE: git hooks in linked worktrees set GIT_DIR to the per-worktree metadata dir, causing rev-parse --show-toplevel to return CWD instead of the worktree root.
function getCleanGitEnvironment(): NodeJS.ProcessEnv {
const env: NodeJS.ProcessEnv = { ...process.env };
delete env.GIT_DIR;
delete env.GIT_WORK_TREE;
return env;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete is an expensive operation.

Suggested change
return env;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { GIT_DIR, GIT_WORK_TREE, ...trimmedEnv } = process.env;
return trimmedEnv;

}

/**
* Finds the root of the current Git repository
*
Expand All @@ -270,7 +297,8 @@ export function getRepoRoot(currentWorkingDirectory: string, gitPath?: string):
gitPath || 'git',
['--no-optional-locks', 'rev-parse', '--show-toplevel'],
{
currentWorkingDirectory
currentWorkingDirectory,
environment: getCleanGitEnvironment()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we strip those env vars iff they point to nonexistent locations/locations without a rush.json?

Also note that AFAIK rush.json doesn't have to be at the repo root.

}
);

Expand Down Expand Up @@ -305,7 +333,8 @@ async function spawnGitAsync(
): Promise<string> {
const spawnOptions: IExecutableSpawnOptions = {
currentWorkingDirectory,
stdio: ['pipe', 'pipe', 'pipe']
stdio: ['pipe', 'pipe', 'pipe'],
environment: getCleanGitEnvironment()
};

let stdout: string = '';
Expand Down Expand Up @@ -591,7 +620,8 @@ export function getRepoChanges(
'--'
]),
{
currentWorkingDirectory: rootDirectory
currentWorkingDirectory: rootDirectory,
environment: getCleanGitEnvironment()
}
);

Expand Down
18 changes: 18 additions & 0 deletions libraries/package-deps-hash/src/test/getRepoDeps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ describe(getRepoRoot.name, () => {
const expectedRoot: string = path.resolve(__dirname, '../../../..').replace(/\\/g, '/');
expect(root).toEqual(expectedRoot);
});

it(`ignores GIT_DIR set by git hooks in linked worktrees`, () => {
// GIT_DIR pointing to a non-existent path causes git rev-parse to fail unless stripped.
const originalGitDir: string | undefined = process.env.GIT_DIR;
try {
process.env.GIT_DIR = '/nonexistent-fake-gitdir-worktrees-for-testing';
const testCwd: string = path.resolve(SOURCE_PATH, '..');
const root: string = getRepoRoot(testCwd);
const expectedRoot: string = path.resolve(__dirname, '../../../..').replace(/\\/g, '/');
expect(root).toEqual(expectedRoot);
} finally {
if (originalGitDir === undefined) {
delete process.env.GIT_DIR;
} else {
process.env.GIT_DIR = originalGitDir;
}
}
});
});

describe(parseGitLsTree.name, () => {
Expand Down
Loading