Repository navigation
fix(studio): start git without the variables that name a repository - #227
Conversation
Git takes the repository GIT_DIR and its other repository variables name over -C, and it sets GIT_DIR for a hook run from a linked worktree. Studio's Changes tab and its test passed them on, so a push from a worktree ran the test against the engine's own repository. A child process can now be started without named variables, and Studio starts git without the ones `git rev-parse --local-env-vars` lists. Fixes #224.
siracozmen01
left a comment
There was a problem hiding this comment.
Review at 3b2def5: no change needed, with one search not verified below. I read the code; I did not run it. Checks were still pending when I read them.
The list. gitRepositoryVariables() has the 15 names of git's own local_repo_env, which is what git rev-parse --local-env-vars prints and the set git itself clears when it moves into another repository: GIT_ALTERNATE_OBJECT_DIRECTORIES, GIT_CONFIG, GIT_CONFIG_PARAMETERS, GIT_CONFIG_COUNT, GIT_OBJECT_DIRECTORY, GIT_DIR, GIT_WORK_TREE, GIT_IMPLICIT_WORK_TREE, GIT_GRAFT_FILE, GIT_INDEX_FILE, GIT_NO_REPLACE_OBJECTS, GIT_REPLACE_REF_BASE, GIT_PREFIX, GIT_SHALLOW_FILE, GIT_COMMON_DIR. The variables a hook is given, GIT_DIR, GIT_INDEX_FILE and GIT_PREFIX (plus GIT_WORK_TREE in a worktree), are all in it. Withholding GIT_CONFIG_COUNT also turns off its GIT_CONFIG_KEY_n and GIT_CONFIG_VALUE_n pairs.
The others named in the request are rightly kept, since none of them picks a repository:
GIT_CONFIG_GLOBAL,GIT_CONFIG_SYSTEMandGIT_CONFIG_NOSYSTEMchoose the author's own user and system settings, the identity among them.GIT_CEILING_DIRECTORIEScan only stop discovery, and-Calready names the repository.GIT_NAMESPACEapplies to fetch and push, not to status, add or commit.
Where git is started.
- In
version_control.cppthe onlyprocess::Child::startis inVersionControl::start, which now passes the list. - In
version_control_test.cppthe only start is thegithelper, which passes it too. - Not verified: whether Studio or another test starts git anywhere else. Please grep
modules/(andtools/if it matters) forChild::start,posix_spawn,CreateProcess,popenandsystem(whose program is git.
The process change.
- POSIX matches the name before the first
=exactly. - Windows matches with
CompareStringOrdinal(..., TRUE)and skips a leading=for the per-drive entries. - The new process test withholds
rawframe_withheldagainstRAWFRAME_WITHHELDon Windows, so the case rule is exercised, and the variable set beside it is still given.
The Studio test sets GIT_DIR and GIT_WORK_TREE to a directory that does not exist, so it fails without either half of the fix:
- With the helper unfixed, the setup goes elsewhere (the body shows that case).
- With
VersionControlunfixed, its git has no repository atGIT_DIR, so the trusted commit makes no hook marker andrunAlldoes not count 2. !exists(kElsewhere)checks that nothing was made there.- Both variables are cleared before the test returns.
The body has Problem, Change, Tests and Verification, and has no column-0 word( or type(scope): line.
## Problem Main's check on dff8e53 failed because the gcc-debug tree does not build. In `AChildIsNotGivenTheVariablesWithheldFromIt`, added by #227, the lambda `kRead` declares its output path as `kRead` too. gcc 14 refuses that under `-Wshadow -Werror` ("declaration of 'kRead' shadows a previous local"); clang accepts it, and a pull request's check builds only clang trees. ## Change - The output path is `kOutput`. Nothing else changes. ## Verification - In the gcc-debug tree, `rawframe_process_tests` builds and passes 5 of 5. With main's `child_test.cpp` put back, the same build fails with the error above. - `tools/check.sh changed` passed before the push. Closes #229
🤖 I have created a release *beep* *boop* --- ## [0.8.1](v0.8.0...v0.8.1) (2026-11-08) This release fixes which repository Studio's git works in. No wire, save, checkpoint or cooked format changes. ### Fixed - Studio runs git for its Changes tab in the game's directory even when `GIT_DIR`, `GIT_WORK_TREE`, `GIT_INDEX_FILE` or git's other repository variables are set, as git sets `GIT_DIR` for a hook it runs from a linked worktree. Before, git worked in the repository those variables named, so Studio's status, add and commit could act on another repository than the game's. A child process can now be started without chosen variables of its parent, through `process::ChildSettings::withheld` ([#227](#227)).
Problem
Studio runs git for its Changes tab with
-C <game directory>, and its test sets up a throwaway repository the same way. Both gave git this process's whole environment. WhenGIT_DIR,GIT_WORK_TREE,GIT_INDEX_FILEor git's other repository variables are set, git works in the repository they name:-Conly changes the working directory.Git sets
GIT_DIRfor a hook it runs from a linked worktree. So the pre-push hook'stools/check.sh changed, pushed from agit worktreecheckout, ranGitRunsOnlyInATrustedRepositoryAndNeverItsReadersProgramsagainst the engine's own repository: the test'sgit init,git configand commits wrotecore.bare = true, a file monitor program, an external diff, two diff drivers and a test author into the engine's.git/config, and put two commits that delete every file on the worktree's branch. The test then failed and the push stopped. Studio started from a shell that exportedGIT_DIRwould do the same with an author's status, add and commit.Fixes #224.
Change
process::ChildSettingsgainswithheld: environment variables of this process a child is not given, by name, in any case on Windows, whose names ignore case. Every other variable is given as before.studio::gitRepositoryVariables()lists the variablesgit rev-parse --local-env-varsprints, the ones that tell git which repository, index, objects and settings to use.VersionControlstarts git without them, so the game's directory is the repository git works in.githelper withholds them too.Tests
process:AChildIsNotGivenTheVariablesWithheldFromIt. A variable withheld by name reads as unset in the child, and another variable set beside it is given. On Windows the name is withheld in another case.studio:GitRunsOnlyInATrustedRepositoryAndNeverItsReadersProgramsnow runs withGIT_DIRandGIT_WORK_TREEnaming another directory, as a hook is started, and checks that nothing made that directory. Without the fix, it fails (see Verification).Verification
process's tests: 5 of 5, the new one among them.studio'sGitcases: 2 of 2 with the fix. With the test's owngithelper giving git the environment as before,GitRunsOnlyInATrustedRepositoryAndNeverItsReadersProgramsfails: its setup goes to the other directory, so the game's repository has no commit hook and the trusted commit leaves no marker (expected std::filesystem::exists(kMarks / "hook")).tools/check.sh changedpassed on this branch, pushed from the main checkout.rawframe-engine/.git/configwas restored by hand to its clone's settings and the two stray commits were taken off the local branch; neither reached GitHub.