1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-29 02:02:40 +01:00

Correctly parse git status --porcelain=2 output with filenames with spaces

Summary:
Filenames are last in `git status --porcelain=2` lines; they
are not escaped in any way, despite the fields being
whitespace-delimited.  `explode` thus happily chops apart filenames
with spaces in them, causing later git operations to operate only on
the filename up to the first space.

Split the lines into the right number of elements -- in all cases,
this is one more than the index we're using, since filenames come last.

Test Plan:
Altering a file with a space in its path, and running `arc diff -a`.

Added tests.

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: Korvin, epriestley

Differential Revision: https://secure.phabricator.com/D19389
This commit is contained in:
Alex Vandiver 2018-04-19 17:52:21 -07:00
parent 73f5afd441
commit ad3087e5e1
3 changed files with 17 additions and 1 deletions

View file

@ -660,14 +660,18 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
$parts = explode("\0", $stdout); $parts = explode("\0", $stdout);
while (count($parts) > 1) { while (count($parts) > 1) {
$entry = array_shift($parts); $entry = array_shift($parts);
$entry_parts = explode(' ', $entry); $entry_parts = explode(' ', $entry, 2);
if ($entry_parts[0] == '1') { if ($entry_parts[0] == '1') {
$entry_parts = explode(' ', $entry, 9);
$path = $entry_parts[8]; $path = $entry_parts[8];
} else if ($entry_parts[0] == '2') { } else if ($entry_parts[0] == '2') {
$entry_parts = explode(' ', $entry, 10);
$path = $entry_parts[9]; $path = $entry_parts[9];
} else if ($entry_parts[0] == 'u') { } else if ($entry_parts[0] == 'u') {
$entry_parts = explode(' ', $entry, 11);
$path = $entry_parts[10]; $path = $entry_parts[10];
} else if ($entry_parts[0] == '?') { } else if ($entry_parts[0] == '?') {
$entry_parts = explode(' ', $entry, 2);
$result[$entry_parts[1]] = self::FLAG_UNTRACKED; $result[$entry_parts[1]] = self::FLAG_UNTRACKED;
continue; continue;
} }

View file

@ -7,6 +7,7 @@ final class ArcanistRepositoryAPIStateTestCase extends PhutilTestCase {
$this->parseState('git_basic.git.tgz'); $this->parseState('git_basic.git.tgz');
$this->parseState('git_submodules_dirty.git.tgz'); $this->parseState('git_submodules_dirty.git.tgz');
$this->parseState('git_submodules_staged.git.tgz'); $this->parseState('git_submodules_staged.git.tgz');
$this->parseState('git_spaces.git.tgz');
} else { } else {
$this->assertSkipped(pht('Git is not installed')); $this->assertSkipped(pht('Git is not installed'));
} }
@ -156,6 +157,17 @@ final class ArcanistRepositoryAPIStateTestCase extends PhutilTestCase {
); );
$this->assertEqual($expect_uncommitted, $api->getUncommittedStatus()); $this->assertEqual($expect_uncommitted, $api->getUncommittedStatus());
break; break;
case 'git_spaces.git.tgz':
$expect_working = array(
'SPACES ADDED' => $f_add,
'SPACES DELETED' => $f_del,
'SPACES MODIFIED' => $f_mod,
'SPACES UNCOMMITTED' => $f_add | $f_unc,
'SPACES UNSTAGED' => $f_add | $f_mod | $f_uns | $f_unc,
'SPACES UNTRACKED' => $f_unt,
);
$this->assertEqual($expect_working, $api->getWorkingCopyStatus());
break;
case 'hg_basic.hg.tgz': case 'hg_basic.hg.tgz':
$expect_uncommitted = array( $expect_uncommitted = array(
'UNCOMMITTED' => $f_mod | $f_unc, 'UNCOMMITTED' => $f_mod | $f_unc,

Binary file not shown.