gclient: have git operations specify the git dir by default
If the .git/ subdir exists and mostly looks OK, but in reality git
doesn't accept it, gclient will blindly run git in the subdir and
think it's operating on the local .git/. Kind of like:
$ cd src/third_party/emoji-segmenter/src/
$ rm -rf .git && mkdir .git
# This works on the top level src/.git/.
$ git <operation>
Instead of relying on this automatic git behavior, use GIT_DIR by
default so we force git to only look at that specific checkout. If
it's broken, git will fail on us (good) instead of silently falling
back to the parent (bad).
$ cd src/third_party/emoji-segmenter/src/
$ rm -rf .git && mkdir .git
$ GIT_DIR=$PWD/.git git <operation>
<this now hard fails>
Bug: 1000825
Test: `gclient sync -j1` with a broken src/third_party/emoji-segmenter/src/.git/ caused the sync to halt
Change-Id: I777d67cd5daa354b32c424414d93a61b3b600f54
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/1785957
Commit-Queue: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Edward Lesmes <ehmaldonado@chromium.org>
diff --git a/gclient_scm.py b/gclient_scm.py
index 007c516..a10a56d 100644
--- a/gclient_scm.py
+++ b/gclient_scm.py
@@ -1259,10 +1259,18 @@
return branch
def _Capture(self, args, **kwargs):
+ set_git_dir = 'cwd' not in kwargs
kwargs.setdefault('cwd', self.checkout_path)
kwargs.setdefault('stderr', subprocess2.PIPE)
strip = kwargs.pop('strip', True)
env = scm.GIT.ApplyEnvVars(kwargs)
+ # If an explicit cwd isn't set, then default to the .git/ subdir so we get
+ # stricter behavior. This can be useful in cases of slight corruption --
+ # we don't accidentally go corrupting parent git checks too. See
+ # https://crbug.com/1000825 for an example.
+ if set_git_dir:
+ env.setdefault('GIT_DIR', os.path.abspath(os.path.join(
+ self.checkout_path, '.git')))
ret = subprocess2.check_output(
['git'] + args, env=env, **kwargs).decode('utf-8')
if strip: