Skip to content

feat: add e worktree for additional gclient working directories#836

Open
MarshallOfSound wants to merge 1 commit intomainfrom
sattard/e-worktree
Open

feat: add e worktree for additional gclient working directories#836
MarshallOfSound wants to merge 1 commit intomainfrom
sattard/e-worktree

Conversation

@MarshallOfSound
Copy link
Copy Markdown
Member

Stacked on #834.

Summary

  • e worktree add <name> <dir> wraps gclient-new-workdir.py to create a second working tree that shares git objects with an existing checkout, writes a matching build config (cloned from --source, default current), and runs e sync so it's immediately buildable. --no-sync / -o <out> / -f available.
  • e worktree clean <name> --yes removes the worktree directory and its build config. Guarded: refuses unless .gclient and src/.git/objects are symlinks (so a primary checkout can never be deleted), refuses if the config is currently active, and requires --yes.
  • Hard-bails on Windows since gclient-new-workdir.py requires symlinks.

Pairs well with per-shell active configs:

export EVM_CURRENT_FILE="$(mktemp --tmpdir evm-current.XXXXXXXX.txt)"

Test plan

  • yarn build clean
  • yarn lint:ts clean
  • yarn test (63 passing)
  • e worktree add testing2 ~/src/electron2 --no-sync creates an 18G workdir with symlinked .git/{objects,refs,config}, writes evm.testing2.json, switches to it
  • e sync in the new workdir fetches gn/clang/node and e build --gen-only produces build.ninja
  • e worktree clean testing --yes refuses (primary checkout)
  • e worktree clean <active> --yes refuses (config in use)
  • e worktree clean testing2 --yes removes dir + config

@MarshallOfSound MarshallOfSound requested review from a team and ckerr as code owners April 6, 2026 05:41
@MarshallOfSound MarshallOfSound force-pushed the sattard/e-worktree branch 2 times, most recently from e59a2b8 to 4a55cd5 Compare April 6, 2026 09:26
Base automatically changed from sam/ts-migration to main April 6, 2026 21:16
Adds `e worktree add <name> <dir>` and `e worktree clean <name>`.

`add` wraps depot_tools' gclient-new-workdir.py to create a second
working tree that shares git object stores with an existing checkout,
clones the source build config with the new root/buildtools path, and
runs `e sync` so the worktree is immediately buildable.

`clean` removes the worktree directory and its config. It refuses to
touch a directory unless `.gclient` and `src/.git/objects` are
symlinks, so it can never delete a primary checkout.

Not supported on Windows (gclient-new-workdir.py requires symlinks).
Comment on lines +160 to +164
evmConfig.remove(name);
console.log(`Removed config ${color.config(name)}`);

console.log(`Deleting ${color.path(root)}...`);
deleteDir(root);
Copy link
Copy Markdown
Member

@codebytere codebytere Apr 8, 2026

Choose a reason for hiding this comment

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

If deleteDir fails we've already nuked the config, so now you've got an orphaned worktree directory with no config pointing at it. Can we flip the order here?

Comment on lines +27 to +36
function isDerivedWorktree(root: string): boolean {
const gclient = path.join(root, '.gclient');
const gitObjects = path.join(root, 'src', '.git', 'objects');
return (
fs.existsSync(gclient) &&
fs.lstatSync(gclient).isSymbolicLink() &&
fs.existsSync(gitObjects) &&
fs.lstatSync(gitObjects).isSymbolicLink()
);
}
Copy link
Copy Markdown
Member

@codebytere codebytere Apr 8, 2026

Choose a reason for hiding this comment

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

If somebody runs git gc in the worktree, the .git/objects symlink can get replaced with a real directory, so this check would fail and they'd be unable to clean up via e worktree clean. Maybe add a --force escape hatch on clean?

console.log(
`Running ${color.cmd('e sync')} to fetch toolchains and apply patches in the new worktree...`,
);
const e = path.resolve(__dirname, 'e');
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.

import.meta.dirname?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants