Commit 9219d356 authored by Aaron Gable's avatar Aaron Gable Committed by Commit Bot

Use core.quotePath=false when git is listing files

This prevents git from putting quotes around some file names
(those that have astral-plane characters) and not around others.

R=maruel

Bug: 792302
Recipe-Nontrivial-Roll: build
Recipe-Nontrivial-Roll: build_limited_scripts_slave
Change-Id: I3b6a6b36c4720116de811b40177b59aa25c263db
Reviewed-on: https://chromium-review.googlesource.com/815454
Commit-Queue: Aaron Gable <agable@chromium.org>
Reviewed-by: 's avatarMarc-Antoine Ruel <maruel@chromium.org>
parent e8856eea
...@@ -305,7 +305,8 @@ class GitWrapper(SCMWrapper): ...@@ -305,7 +305,8 @@ class GitWrapper(SCMWrapper):
# actually in a broken state here. The index will have both 'a' and 'A', # actually in a broken state here. The index will have both 'a' and 'A',
# but only one of them will exist on the disk. To progress, we delete # but only one of them will exist on the disk. To progress, we delete
# everything that status thinks is modified. # everything that status thinks is modified.
output = self._Capture(['status', '--porcelain'], strip=False) output = self._Capture([
'-c', 'core.quotePath=false', 'status', '--porcelain'], strip=False)
for line in output.splitlines(): for line in output.splitlines():
# --porcelain (v1) looks like: # --porcelain (v1) looks like:
# XY filename # XY filename
...@@ -324,7 +325,8 @@ class GitWrapper(SCMWrapper): ...@@ -324,7 +325,8 @@ class GitWrapper(SCMWrapper):
self._Fetch(options, prune=True, quiet=options.verbose) self._Fetch(options, prune=True, quiet=options.verbose)
self._Scrub(revision, options) self._Scrub(revision, options)
if file_list is not None: if file_list is not None:
files = self._Capture(['ls-files']).splitlines() files = self._Capture(
['-c', 'core.quotePath=false', 'ls-files']).splitlines()
file_list.extend([os.path.join(self.checkout_path, f) for f in files]) file_list.extend([os.path.join(self.checkout_path, f) for f in files])
def _DisableHooks(self): def _DisableHooks(self):
...@@ -440,7 +442,8 @@ class GitWrapper(SCMWrapper): ...@@ -440,7 +442,8 @@ class GitWrapper(SCMWrapper):
self._DeleteOrMove(options.force) self._DeleteOrMove(options.force)
self._Clone(revision, url, options) self._Clone(revision, url, options)
if file_list is not None: if file_list is not None:
files = self._Capture(['ls-files']).splitlines() files = self._Capture(
['-c', 'core.quotePath=false', 'ls-files']).splitlines()
file_list.extend([os.path.join(self.checkout_path, f) for f in files]) file_list.extend([os.path.join(self.checkout_path, f) for f in files])
if not verbose: if not verbose:
# Make the output a little prettier. It's nice to have some whitespace # Make the output a little prettier. It's nice to have some whitespace
...@@ -719,7 +722,8 @@ class GitWrapper(SCMWrapper): ...@@ -719,7 +722,8 @@ class GitWrapper(SCMWrapper):
# merge-base by default), so doesn't include untracked files. So we use # merge-base by default), so doesn't include untracked files. So we use
# 'git ls-files --directory --others --exclude-standard' here directly. # 'git ls-files --directory --others --exclude-standard' here directly.
paths = scm.GIT.Capture( paths = scm.GIT.Capture(
['ls-files', '--directory', '--others', '--exclude-standard'], ['-c', 'core.quotePath=false', 'ls-files',
'--directory', '--others', '--exclude-standard'],
self.checkout_path) self.checkout_path)
for path in (p for p in paths.splitlines() if p.endswith('/')): for path in (p for p in paths.splitlines() if p.endswith('/')):
full_path = os.path.join(self.checkout_path, path) full_path = os.path.join(self.checkout_path, path)
......
...@@ -5359,7 +5359,8 @@ def PushToGitWithAutoRebase(remote, branch, original_description, ...@@ -5359,7 +5359,8 @@ def PushToGitWithAutoRebase(remote, branch, original_description,
print('Your patch doesn\'t apply cleanly to \'%s\' HEAD @ %s, ' print('Your patch doesn\'t apply cleanly to \'%s\' HEAD @ %s, '
'the following files have merge conflicts:' % 'the following files have merge conflicts:' %
(branch, parent_hash)) (branch, parent_hash))
print(RunGit(['diff', '--name-status', '--diff-filter=U']).strip()) print(RunGit(['-c', 'core.quotePath=false', 'diff',
'--name-status', '--diff-filter=U']).strip())
print('Please rebase your patch and try again.') print('Please rebase your patch and try again.')
RunGitWithCode(['cherry-pick', '--abort']) RunGitWithCode(['cherry-pick', '--abort'])
break break
......
...@@ -262,7 +262,8 @@ class _Drover(object): ...@@ -262,7 +262,8 @@ class _Drover(object):
# Files that have been deleted between branch and cherry-pick will not have # Files that have been deleted between branch and cherry-pick will not have
# their skip-worktree bit set so set it manually for those files to avoid # their skip-worktree bit set so set it manually for those files to avoid
# git status incorrectly listing them as unstaged deletes. # git status incorrectly listing them as unstaged deletes.
repo_status = self._run_git_command(['status', '--porcelain']).splitlines() repo_status = self._run_git_command(
['-c', 'core.quotePath=false', 'status', '--porcelain']).splitlines()
extra_files = [f[3:] for f in repo_status if f[:2] == ' D'] extra_files = [f[3:] for f in repo_status if f[:2] == ' D']
if extra_files: if extra_files:
self._run_git_command_with_stdin( self._run_git_command_with_stdin(
......
...@@ -1038,7 +1038,8 @@ class GitChange(Change): ...@@ -1038,7 +1038,8 @@ class GitChange(Change):
"""List all files under source control in the repo.""" """List all files under source control in the repo."""
root = root or self.RepositoryRoot() root = root or self.RepositoryRoot()
return subprocess.check_output( return subprocess.check_output(
['git', 'ls-files', '--', '.'], cwd=root).splitlines() ['git', '-c', 'core,quotePath=false', 'ls-files', '--', '.'],
cwd=root).splitlines()
def ListRelevantPresubmitFiles(files, root): def ListRelevantPresubmitFiles(files, root):
......
...@@ -663,7 +663,7 @@ Returns: ...@@ -663,7 +663,7 @@ Returns:
#### **class [TryserverApi](/recipes/recipe_modules/tryserver/api.py#12)([RecipeApi][recipe_engine/wkt/RecipeApi]):** #### **class [TryserverApi](/recipes/recipe_modules/tryserver/api.py#12)([RecipeApi][recipe_engine/wkt/RecipeApi]):**
&mdash; **def [add\_failure\_reason](/recipes/recipe_modules/tryserver/api.py#146)(self, reason):** &mdash; **def [add\_failure\_reason](/recipes/recipe_modules/tryserver/api.py#148)(self, reason):**
Records a more detailed reason why build is failing. Records a more detailed reason why build is failing.
...@@ -687,11 +687,11 @@ TODO(tandrii): remove this doc. ...@@ -687,11 +687,11 @@ TODO(tandrii): remove this doc.
Unless you use patch_root=None, in which case old behavior is used Unless you use patch_root=None, in which case old behavior is used
which returns paths relative to checkout aka solution[0].name. which returns paths relative to checkout aka solution[0].name.
&mdash; **def [get\_footer](/recipes/recipe_modules/tryserver/api.py#209)(self, tag, patch_text=None):** &mdash; **def [get\_footer](/recipes/recipe_modules/tryserver/api.py#211)(self, tag, patch_text=None):**
Gets a specific tag from a CL description Gets a specific tag from a CL description
&mdash; **def [get\_footers](/recipes/recipe_modules/tryserver/api.py#182)(self, patch_text=None):** &mdash; **def [get\_footers](/recipes/recipe_modules/tryserver/api.py#184)(self, patch_text=None):**
Retrieves footers from the patch description. Retrieves footers from the patch description.
...@@ -708,13 +708,13 @@ Returns true iff the properties exist to match a Gerrit issue. ...@@ -708,13 +708,13 @@ Returns true iff the properties exist to match a Gerrit issue.
Returns true iff we can apply_issue or patch. Returns true iff we can apply_issue or patch.
&mdash; **def [normalize\_footer\_name](/recipes/recipe_modules/tryserver/api.py#213)(self, footer):** &mdash; **def [normalize\_footer\_name](/recipes/recipe_modules/tryserver/api.py#215)(self, footer):**
&mdash; **def [set\_compile\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#125)(self):** &mdash; **def [set\_compile\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#127)(self):**
Mark the tryjob result as a compile failure. Mark the tryjob result as a compile failure.
&emsp; **@contextlib.contextmanager**<br>&mdash; **def [set\_failure\_hash](/recipes/recipe_modules/tryserver/api.py#155)(self):** &emsp; **@contextlib.contextmanager**<br>&mdash; **def [set\_failure\_hash](/recipes/recipe_modules/tryserver/api.py#157)(self):**
Context manager that sets a failure_hash build property on StepFailure. Context manager that sets a failure_hash build property on StepFailure.
...@@ -723,7 +723,7 @@ for the same reason. For example, if a patch is bad (breaks something), ...@@ -723,7 +723,7 @@ for the same reason. For example, if a patch is bad (breaks something),
we'd expect it to always break in the same way. Different failures we'd expect it to always break in the same way. Different failures
for the same patch are usually a sign of flakiness. for the same patch are usually a sign of flakiness.
&mdash; **def [set\_invalid\_test\_results\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#137)(self):** &mdash; **def [set\_invalid\_test\_results\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#139)(self):**
Mark the tryjob result as having invalid test results. Mark the tryjob result as having invalid test results.
...@@ -731,18 +731,18 @@ This means we run some tests, but the results were not valid ...@@ -731,18 +731,18 @@ This means we run some tests, but the results were not valid
(e.g. no list of specific test cases that failed, or too many (e.g. no list of specific test cases that failed, or too many
tests failing, etc). tests failing, etc).
&mdash; **def [set\_patch\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#121)(self):** &mdash; **def [set\_patch\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#123)(self):**
Mark the tryjob result as failure to apply the patch. Mark the tryjob result as failure to apply the patch.
&mdash; **def [set\_subproject\_tag](/recipes/recipe_modules/tryserver/api.py#103)(self, subproject_tag):** &mdash; **def [set\_subproject\_tag](/recipes/recipe_modules/tryserver/api.py#105)(self, subproject_tag):**
Adds a subproject tag to the build. Adds a subproject tag to the build.
This can be used to distinguish between builds that execute different steps This can be used to distinguish between builds that execute different steps
depending on what was patched, e.g. blink vs. pure chromium patches. depending on what was patched, e.g. blink vs. pure chromium patches.
&mdash; **def [set\_test\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#129)(self):** &mdash; **def [set\_test\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#131)(self):**
Mark the tryjob result as a test failure. Mark the tryjob result as a test failure.
......
...@@ -63,12 +63,13 @@ class TryserverApi(recipe_api.RecipeApi): ...@@ -63,12 +63,13 @@ class TryserverApi(recipe_api.RecipeApi):
cwd = self.m.context.cwd or self.m.path['start_dir'].join(patch_root) cwd = self.m.context.cwd or self.m.path['start_dir'].join(patch_root)
with self.m.context(cwd=cwd): with self.m.context(cwd=cwd):
step_result = self.m.git('diff', '--cached', '--name-only', step_result = self.m.git(
name='git diff to analyze patch', '-c', 'core.quotePath=false', 'diff', '--cached', '--name-only',
stdout=self.m.raw_io.output(), name='git diff to analyze patch',
step_test_data=lambda: stdout=self.m.raw_io.output(),
self.m.raw_io.test_api.stream_output('foo.cc'), step_test_data=lambda:
**kwargs) self.m.raw_io.test_api.stream_output('foo.cc'),
**kwargs)
paths = [self.m.path.join(patch_root, p) for p in paths = [self.m.path.join(patch_root, p) for p in
step_result.stdout.split()] step_result.stdout.split()]
if self.m.platform.is_win: if self.m.platform.is_win:
...@@ -84,11 +85,12 @@ class TryserverApi(recipe_api.RecipeApi): ...@@ -84,11 +85,12 @@ class TryserverApi(recipe_api.RecipeApi):
cwd = self.m.path['checkout'].join(issue_root) if issue_root else None cwd = self.m.path['checkout'].join(issue_root) if issue_root else None
with self.m.context(cwd=cwd): with self.m.context(cwd=cwd):
step_result = self.m.git('diff', '--cached', '--name-only', step_result = self.m.git(
name='git diff to analyze patch', '-c', 'core.quotePath=false', 'diff', '--cached', '--name-only',
stdout=self.m.raw_io.output(), name='git diff to analyze patch',
step_test_data=lambda: stdout=self.m.raw_io.output(),
self.m.raw_io.test_api.stream_output('foo.cc')) step_test_data=lambda:
self.m.raw_io.test_api.stream_output('foo.cc'))
paths = step_result.stdout.split() paths = step_result.stdout.split()
if issue_root: if issue_root:
paths = [self.m.path.join(issue_root, path) for path in paths] paths = [self.m.path.join(issue_root, path) for path in paths]
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
{ {
"cmd": [ "cmd": [
"git", "git",
"-c",
"core.quotePath=false",
"diff", "diff",
"--cached", "--cached",
"--name-only" "--name-only"
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
{ {
"cmd": [ "cmd": [
"git", "git",
"-c",
"core.quotePath=false",
"diff", "diff",
"--cached", "--cached",
"--name-only" "--name-only"
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
{ {
"cmd": [ "cmd": [
"git", "git",
"-c",
"core.quotePath=false",
"diff", "diff",
"--cached", "--cached",
"--name-only" "--name-only"
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
{ {
"cmd": [ "cmd": [
"git", "git",
"-c",
"core.quotePath=false",
"diff", "diff",
"--cached", "--cached",
"--name-only" "--name-only"
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
{ {
"cmd": [ "cmd": [
"git", "git",
"-c",
"core.quotePath=false",
"diff", "diff",
"--cached", "--cached",
"--name-only" "--name-only"
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
{ {
"cmd": [ "cmd": [
"git", "git",
"-c",
"core.quotePath=false",
"diff", "diff",
"--cached", "--cached",
"--name-only" "--name-only"
......
...@@ -131,8 +131,8 @@ class GIT(object): ...@@ -131,8 +131,8 @@ class GIT(object):
upstream_branch = GIT.GetUpstreamBranch(cwd) upstream_branch = GIT.GetUpstreamBranch(cwd)
if upstream_branch is None: if upstream_branch is None:
raise gclient_utils.Error('Cannot determine upstream branch') raise gclient_utils.Error('Cannot determine upstream branch')
command = ['diff', '--name-status', '--no-renames', command = ['-c', 'core.quotePath=false', 'diff',
'-r', '%s...' % upstream_branch] '--name-status', '--no-renames', '-r', '%s...' % upstream_branch]
if not files: if not files:
pass pass
elif isinstance(files, basestring): elif isinstance(files, basestring):
......
...@@ -631,7 +631,7 @@ class ManagedGitWrapperTestCaseMox(BaseTestCase): ...@@ -631,7 +631,7 @@ class ManagedGitWrapperTestCaseMox(BaseTestCase):
options) options)
self.mox.StubOutWithMock(gclient_scm.subprocess2, 'check_output', True) self.mox.StubOutWithMock(gclient_scm.subprocess2, 'check_output', True)
gclient_scm.subprocess2.check_output( gclient_scm.subprocess2.check_output(
['git', 'ls-files'], cwd=self.base_path, ['git', '-c', 'core.quotePath=false', 'ls-files'], cwd=self.base_path,
env=gclient_scm.scm.GIT.ApplyEnvVars({}), stderr=-1,).AndReturn('') env=gclient_scm.scm.GIT.ApplyEnvVars({}), stderr=-1,).AndReturn('')
gclient_scm.subprocess2.check_output( gclient_scm.subprocess2.check_output(
['git', 'rev-parse', '--verify', 'HEAD'], ['git', 'rev-parse', '--verify', 'HEAD'],
...@@ -668,7 +668,7 @@ class ManagedGitWrapperTestCaseMox(BaseTestCase): ...@@ -668,7 +668,7 @@ class ManagedGitWrapperTestCaseMox(BaseTestCase):
options) options)
self.mox.StubOutWithMock(gclient_scm.subprocess2, 'check_output', True) self.mox.StubOutWithMock(gclient_scm.subprocess2, 'check_output', True)
gclient_scm.subprocess2.check_output( gclient_scm.subprocess2.check_output(
['git', 'ls-files'], cwd=self.base_path, ['git', '-c', 'core.quotePath=false', 'ls-files'], cwd=self.base_path,
env=gclient_scm.scm.GIT.ApplyEnvVars({}), stderr=-1,).AndReturn('') env=gclient_scm.scm.GIT.ApplyEnvVars({}), stderr=-1,).AndReturn('')
gclient_scm.subprocess2.check_output( gclient_scm.subprocess2.check_output(
['git', 'rev-parse', '--verify', 'HEAD'], ['git', 'rev-parse', '--verify', 'HEAD'],
......
...@@ -813,8 +813,8 @@ class TestGitCl(TestCase): ...@@ -813,8 +813,8 @@ class TestGitCl(TestCase):
] + cls._git_sanity_checks('fake_ancestor_sha', 'master') + [ ] + cls._git_sanity_checks('fake_ancestor_sha', 'master') + [
((['git', 'rev-parse', '--show-cdup'],), ''), ((['git', 'rev-parse', '--show-cdup'],), ''),
((['git', 'rev-parse', 'HEAD'],), '12345'), ((['git', 'rev-parse', 'HEAD'],), '12345'),
((['git', 'diff', '--name-status', '--no-renames', '-r', ((['git', '-c', 'core.quotePath=false', 'diff',
'fake_ancestor_sha...', '.'],), '--name-status', '--no-renames', '-r', 'fake_ancestor_sha...', '.'],),
'M\t.gitignore\n'), 'M\t.gitignore\n'),
((['git', 'config', 'branch.master.rietveldpatchset'],), CERR1), ((['git', 'config', 'branch.master.rietveldpatchset'],), CERR1),
((['git', 'log', '--pretty=format:%s%n%n%b', ((['git', 'log', '--pretty=format:%s%n%n%b',
...@@ -1110,8 +1110,8 @@ class TestGitCl(TestCase): ...@@ -1110,8 +1110,8 @@ class TestGitCl(TestCase):
] + self._git_sanity_checks('fake_ancestor_sha', 'feature') + [ ] + self._git_sanity_checks('fake_ancestor_sha', 'feature') + [
((['git', 'rev-parse', '--show-cdup'],), ''), ((['git', 'rev-parse', '--show-cdup'],), ''),
((['git', 'rev-parse', 'HEAD'],), 'fake_sha'), ((['git', 'rev-parse', 'HEAD'],), 'fake_sha'),
((['git', 'diff', '--name-status', '--no-renames', '-r', ((['git', '-c', 'core.quotePath=false', 'diff',
'fake_ancestor_sha...', '.'],), '--name-status', '--no-renames', '-r', 'fake_ancestor_sha...', '.'],),
'M\tfile1.cpp'), 'M\tfile1.cpp'),
((['git', 'config', 'branch.feature.rietveldpatchset'],), '20001'), ((['git', 'config', 'branch.feature.rietveldpatchset'],), '20001'),
((['git', 'config', 'branch.feature.rietveldserver'],), ((['git', 'config', 'branch.feature.rietveldserver'],),
...@@ -1228,7 +1228,8 @@ class TestGitCl(TestCase): ...@@ -1228,7 +1228,8 @@ class TestGitCl(TestCase):
fail_cherry_pick=True, fail_cherry_pick=True,
debug=False) debug=False)
self.calls += [ self.calls += [
((['git', 'diff', '--name-status', '--diff-filter=U'],), ((['git', '-c', 'core.quotePath=false', 'diff',
'--name-status', '--diff-filter=U'],),
'U path/file1\n' 'U path/file1\n'
'U file2.cpp\n'), 'U file2.cpp\n'),
((['git', 'cherry-pick', '--abort'],), ''), ((['git', 'cherry-pick', '--abort'],), ''),
...@@ -1445,8 +1446,8 @@ class TestGitCl(TestCase): ...@@ -1445,8 +1446,8 @@ class TestGitCl(TestCase):
((['git', 'rev-parse', '--show-cdup'],), ''), ((['git', 'rev-parse', '--show-cdup'],), ''),
((['git', 'rev-parse', 'HEAD'],), '12345'), ((['git', 'rev-parse', 'HEAD'],), '12345'),
((['git', 'diff', '--name-status', '--no-renames', '-r', ((['git', '-c', 'core.quotePath=false', 'diff', '--name-status',
ancestor_revision + '...', '.'],), '--no-renames', '-r', ancestor_revision + '...', '.'],),
'M\t.gitignore\n'), 'M\t.gitignore\n'),
((['git', 'config', 'branch.master.gerritpatchset'],), CERR1), ((['git', 'config', 'branch.master.gerritpatchset'],), CERR1),
] ]
......
...@@ -79,7 +79,8 @@ class GitDroverTest(auto_stub.TestCase): ...@@ -79,7 +79,8 @@ class GitDroverTest(auto_stub.TestCase):
(['git', 'branch', '-D', 'drover_branch_123'], self._parent_repo), (['git', 'branch', '-D', 'drover_branch_123'], self._parent_repo),
] ]
self.MANUAL_RESOLVE_PREPARATION_COMMANDS = [ self.MANUAL_RESOLVE_PREPARATION_COMMANDS = [
(['git', 'status', '--porcelain'], self._target_repo), (['git', '-c', 'core.quotePath=false', 'status', '--porcelain'],
self._target_repo),
(['git', 'update-index', '--skip-worktree', '--stdin'], (['git', 'update-index', '--skip-worktree', '--stdin'],
self._target_repo), self._target_repo),
] ]
...@@ -114,7 +115,7 @@ class GitDroverTest(auto_stub.TestCase): ...@@ -114,7 +115,7 @@ class GitDroverTest(auto_stub.TestCase):
raise subprocess.CalledProcessError(1, args[0]) raise subprocess.CalledProcessError(1, args[0])
if args == ['git', 'rev-parse', '--git-dir']: if args == ['git', 'rev-parse', '--git-dir']:
return os.path.join(self._parent_repo, '.git') return os.path.join(self._parent_repo, '.git')
if args == ['git', 'status', '--porcelain']: if args == ['git', '-c', 'core.quotePath=false', 'status', '--porcelain']:
return ' D foo\nUU baz\n D bar\n' return ' D foo\nUU baz\n D bar\n'
if args == ['git', 'log', '-1', '--format=%ae']: if args == ['git', 'log', '-1', '--format=%ae']:
return 'author@domain.org' return 'author@domain.org'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment