Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright 2011 Facebook, Inc.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Interfaces with the Mercurial working copies.
|
|
|
|
*
|
|
|
|
* @group workingcopy
|
|
|
|
*/
|
|
|
|
class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
|
|
|
|
|
|
|
|
private $status;
|
|
|
|
private $base;
|
2011-08-09 18:54:10 -07:00
|
|
|
private $relativeCommit;
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
|
|
|
|
public function getSourceControlSystemName() {
|
|
|
|
return 'hg';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getSourceControlBaseRevision() {
|
|
|
|
list($stdout) = execx(
|
|
|
|
'(cd %s && hg id -ir %s)',
|
|
|
|
$this->getPath(),
|
|
|
|
$this->getRelativeCommit());
|
|
|
|
return $stdout;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getSourceControlPath() {
|
|
|
|
return '/';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getBranchName() {
|
|
|
|
// TODO: I have nearly no idea how hg local branches work.
|
|
|
|
list($stdout) = execx(
|
|
|
|
'(cd %s && hg branch)',
|
|
|
|
$this->getPath());
|
|
|
|
return $stdout;
|
|
|
|
}
|
|
|
|
|
2011-08-09 18:54:10 -07:00
|
|
|
public function setRelativeCommit($commit) {
|
|
|
|
list($err) = exec_manual(
|
|
|
|
'(cd %s && hg id -ir %s)',
|
|
|
|
$this->getPath(),
|
|
|
|
$commit);
|
|
|
|
|
|
|
|
if ($err) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"Commit '{$commit}' is not a valid Mercurial commit identifier.");
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->relativeCommit = $commit;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
public function getRelativeCommit() {
|
2011-08-09 18:54:10 -07:00
|
|
|
if (empty($this->relativeCommit)) {
|
|
|
|
list($stdout) = execx(
|
2011-09-14 18:11:00 -07:00
|
|
|
'(cd %s && hg outgoing --branch `hg branch` --limit 1 --style default)',
|
2011-08-09 18:54:10 -07:00
|
|
|
$this->getPath());
|
2011-09-16 03:53:52 -07:00
|
|
|
$logs = ArcanistMercurialParser::parseMercurialLog($stdout);
|
2011-08-09 18:54:10 -07:00
|
|
|
if (!count($logs)) {
|
|
|
|
throw new ArcanistUsageException("You have no outgoing changes!");
|
|
|
|
}
|
|
|
|
$oldest_log = head($logs);
|
2011-09-14 18:11:00 -07:00
|
|
|
$oldest_rev = $oldest_log['rev'];
|
2011-08-09 18:54:10 -07:00
|
|
|
|
2011-09-14 18:11:00 -07:00
|
|
|
// NOTE: The "^" and "~" syntaxes were only added in hg 1.9, which is new
|
|
|
|
// as of July 2011, so do this in a compatible way. Also, "hg log" and
|
|
|
|
// "hg outgoing" don't necessarily show parents (even if given an explicit
|
|
|
|
// template consisting of just the parents token) so we need to separately
|
|
|
|
// execute "hg parents".
|
|
|
|
|
|
|
|
list($stdout) = execx(
|
|
|
|
'(cd %s && hg parents --style default --rev %s)',
|
|
|
|
$this->getPath(),
|
|
|
|
$oldest_rev);
|
2011-09-16 03:53:52 -07:00
|
|
|
$parents_logs = ArcanistMercurialParser::parseMercurialLog($stdout);
|
2011-09-14 18:11:00 -07:00
|
|
|
$first_parent = head($parents_logs);
|
|
|
|
if (!$first_parent) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"Oldest outgoing change has no parent revision!");
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->relativeCommit = $first_parent['rev'];
|
2011-08-09 18:54:10 -07:00
|
|
|
}
|
|
|
|
return $this->relativeCommit;
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
}
|
|
|
|
|
2011-08-23 18:48:55 -07:00
|
|
|
public function getLocalCommitInformation() {
|
|
|
|
list($info) = execx(
|
2011-09-14 18:11:00 -07:00
|
|
|
'(cd %s && hg log --style default --rev %s..%s --)',
|
2011-08-23 18:48:55 -07:00
|
|
|
$this->getPath(),
|
|
|
|
$this->getRelativeCommit(),
|
2011-09-14 19:08:16 -07:00
|
|
|
$this->getWorkingCopyRevision());
|
2011-09-16 03:53:52 -07:00
|
|
|
$logs = ArcanistMercurialParser::parseMercurialLog($info);
|
2011-08-31 11:51:56 -07:00
|
|
|
|
|
|
|
// Get rid of the first log, it's not actually part of the diff. "hg log"
|
|
|
|
// is inclusive, while "hg diff" is exclusive.
|
|
|
|
array_shift($logs);
|
|
|
|
|
2011-09-26 14:35:42 -07:00
|
|
|
// Expand short hashes (12 characters) to full hashes (40 characters) by
|
|
|
|
// issuing a big "hg log" command. Possibly we should do this with parents
|
|
|
|
// too, but nothing uses them directly at the moment.
|
|
|
|
if ($logs) {
|
|
|
|
$cmd = array();
|
|
|
|
foreach (ipull($logs, 'rev') as $rev) {
|
|
|
|
$cmd[] = csprintf('--rev %s', $rev);
|
|
|
|
}
|
|
|
|
|
|
|
|
list($full) = execx(
|
|
|
|
'(cd %s && hg log --template %s %C --)',
|
|
|
|
$this->getPath(),
|
|
|
|
'{node}\\n',
|
|
|
|
implode(' ', $cmd));
|
|
|
|
|
|
|
|
$full = explode("\n", trim($full));
|
|
|
|
foreach ($logs as $key => $dict) {
|
|
|
|
$logs[$key]['rev'] = array_pop($full);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-31 11:51:56 -07:00
|
|
|
return $logs;
|
2011-08-23 18:48:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
public function getBlame($path) {
|
|
|
|
list($stdout) = execx(
|
|
|
|
'(cd %s && hg blame -u -v -c --rev %s -- %s)',
|
|
|
|
$this->getPath(),
|
|
|
|
$this->getRelativeCommit(),
|
|
|
|
$path);
|
|
|
|
|
|
|
|
$blame = array();
|
|
|
|
foreach (explode("\n", trim($stdout)) as $line) {
|
|
|
|
if (!strlen($line)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$matches = null;
|
|
|
|
$ok = preg_match('^/\s*([^:]+?) [a-f0-9]{12}: (.*)$/', $line, $matches);
|
|
|
|
|
|
|
|
if (!$ok) {
|
|
|
|
throw new Exception("Unable to parse Mercurial blame line: {$line}");
|
|
|
|
}
|
|
|
|
|
|
|
|
$revision = $matches[2];
|
|
|
|
$author = trim($matches[1]);
|
|
|
|
$blame[] = array($author, $revision);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $blame;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getWorkingCopyStatus() {
|
|
|
|
|
2011-09-14 18:11:00 -07:00
|
|
|
if (!isset($this->status)) {
|
|
|
|
// A reviewable revision spans multiple local commits in Mercurial, but
|
|
|
|
// there is no way to get file change status across multiple commits, so
|
|
|
|
// just take the entire diff and parse it to figure out what's changed.
|
|
|
|
|
|
|
|
$diff = $this->getFullMercurialDiff();
|
|
|
|
$parser = new ArcanistDiffParser();
|
|
|
|
$changes = $parser->parseDiff($diff);
|
|
|
|
|
|
|
|
$status_map = array();
|
|
|
|
|
|
|
|
foreach ($changes as $change) {
|
|
|
|
$flags = 0;
|
|
|
|
switch ($change->getType()) {
|
|
|
|
case ArcanistDiffChangeType::TYPE_ADD:
|
|
|
|
case ArcanistDiffChangeType::TYPE_MOVE_HERE:
|
|
|
|
case ArcanistDiffChangeType::TYPE_COPY_HERE:
|
|
|
|
$flags |= self::FLAG_ADDED;
|
|
|
|
break;
|
|
|
|
case ArcanistDiffChangeType::TYPE_CHANGE:
|
|
|
|
case ArcanistDiffChangeType::TYPE_COPY_AWAY: // Check for changes?
|
|
|
|
$flags |= self::FLAG_MODIFIED;
|
|
|
|
break;
|
|
|
|
case ArcanistDiffChangeType::TYPE_DELETE:
|
|
|
|
case ArcanistDiffChangeType::TYPE_MOVE_AWAY:
|
|
|
|
case ArcanistDiffChangeType::TYPE_MULTICOPY:
|
|
|
|
$flags |= self::FLAG_DELETED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
$status_map[$change->getCurrentPath()] = $flags;
|
2011-08-09 18:54:10 -07:00
|
|
|
}
|
|
|
|
|
2011-09-14 18:11:00 -07:00
|
|
|
list($stdout) = execx(
|
|
|
|
'(cd %s && hg status)',
|
|
|
|
$this->getPath());
|
2011-08-09 18:54:10 -07:00
|
|
|
|
2011-09-16 03:53:52 -07:00
|
|
|
$working_status = ArcanistMercurialParser::parseMercurialStatus($stdout);
|
2011-09-14 18:11:00 -07:00
|
|
|
foreach ($working_status as $path => $status) {
|
2011-11-01 17:10:48 -07:00
|
|
|
if ($status & ArcanistRepositoryAPI::FLAG_UNTRACKED) {
|
|
|
|
// If the file is untracked, don't mark it uncommitted.
|
|
|
|
continue;
|
|
|
|
}
|
2011-09-14 18:11:00 -07:00
|
|
|
$status |= self::FLAG_UNCOMMITTED;
|
|
|
|
if (!empty($status_map[$path])) {
|
|
|
|
$status_map[$path] |= $status;
|
|
|
|
} else {
|
|
|
|
$status_map[$path] = $status;
|
|
|
|
}
|
2011-08-09 18:54:10 -07:00
|
|
|
}
|
2011-09-14 18:11:00 -07:00
|
|
|
|
|
|
|
$this->status = $status_map;
|
2011-08-09 18:54:10 -07:00
|
|
|
}
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
|
2011-09-14 18:11:00 -07:00
|
|
|
return $this->status;
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private function getDiffOptions() {
|
|
|
|
$options = array(
|
2011-09-14 18:11:00 -07:00
|
|
|
'--git',
|
2011-11-08 18:21:19 -08:00
|
|
|
// NOTE: We can't use "--color never" because that flag is provided
|
|
|
|
// by the color extension, which may or may not be enabled. Instead,
|
|
|
|
// set the color mode configuration so that color is disabled regardless
|
|
|
|
// of whether the extension is present or not.
|
|
|
|
'--config color.mode=off',
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
'-U'.$this->getDiffLinesOfContext(),
|
|
|
|
);
|
|
|
|
return implode(' ', $options);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getRawDiffText($path) {
|
|
|
|
$options = $this->getDiffOptions();
|
|
|
|
|
|
|
|
list($stdout) = execx(
|
2011-09-14 19:08:16 -07:00
|
|
|
'(cd %s && hg diff %C --rev %s --rev %s -- %s)',
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
$this->getPath(),
|
|
|
|
$options,
|
|
|
|
$this->getRelativeCommit(),
|
2011-09-14 19:08:16 -07:00
|
|
|
$this->getWorkingCopyRevision(),
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
$path);
|
|
|
|
|
|
|
|
return $stdout;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getFullMercurialDiff() {
|
|
|
|
$options = $this->getDiffOptions();
|
|
|
|
|
|
|
|
list($stdout) = execx(
|
2011-09-14 19:08:16 -07:00
|
|
|
'(cd %s && hg diff %C --rev %s --rev %s --)',
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
$this->getPath(),
|
|
|
|
$options,
|
2011-09-14 19:08:16 -07:00
|
|
|
$this->getRelativeCommit(),
|
|
|
|
$this->getWorkingCopyRevision());
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
|
|
|
|
return $stdout;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getOriginalFileData($path) {
|
|
|
|
return $this->getFileDataAtRevision($path, $this->getRelativeCommit());
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCurrentFileData($path) {
|
2011-09-14 19:08:16 -07:00
|
|
|
return $this->getFileDataAtRevision(
|
|
|
|
$path,
|
|
|
|
$this->getWorkingCopyRevision());
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private function getFileDataAtRevision($path, $revision) {
|
2011-11-01 17:21:39 -07:00
|
|
|
list($err, $stdout) = exec_manual(
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
'(cd %s && hg cat --rev %s -- %s)',
|
|
|
|
$this->getPath(),
|
2011-11-01 17:21:39 -07:00
|
|
|
$revision,
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
$path);
|
2011-11-01 17:21:39 -07:00
|
|
|
if ($err) {
|
|
|
|
// Assume this is "no file at revision", i.e. a deleted or added file.
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
return $stdout;
|
|
|
|
}
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
}
|
|
|
|
|
2011-09-14 19:08:16 -07:00
|
|
|
private function getWorkingCopyRevision() {
|
|
|
|
// In Mercurial, "tip" means the tip of the current branch, not what's in
|
|
|
|
// the working copy. The tip may be ahead of the working copy. We need to
|
|
|
|
// use "hg summary" to figure out what is actually in the working copy.
|
|
|
|
// For instance, "hg up 4 && arc diff" should not show commits 5 and above.
|
|
|
|
|
2011-09-26 14:35:42 -07:00
|
|
|
// Without arguments, "hg id" shows the current working directory's commit,
|
|
|
|
// and "--debug" expands it to a 40-character hash.
|
2011-09-14 19:08:16 -07:00
|
|
|
list($stdout) = execx(
|
2011-09-26 14:35:42 -07:00
|
|
|
'(cd %s && hg --debug id --id)',
|
2011-09-14 19:08:16 -07:00
|
|
|
$this->getPath());
|
2011-11-01 15:07:39 -07:00
|
|
|
|
|
|
|
// Even with "--id", "hg id" will print a trailing "+" after the hash
|
|
|
|
// if the working copy is dirty (has uncommitted changes). We'll explicitly
|
|
|
|
// detect this later by calling getWorkingCopyStatus(); ignore it for now.
|
|
|
|
$stdout = trim($stdout);
|
|
|
|
return rtrim($stdout, '+');
|
2011-09-14 19:08:16 -07:00
|
|
|
}
|
|
|
|
|
2011-09-14 18:44:54 -07:00
|
|
|
public function supportsRelativeLocalCommits() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function parseRelativeLocalCommit(array $argv) {
|
|
|
|
if (count($argv) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (count($argv) != 1) {
|
|
|
|
throw new ArcanistUsageException("Specify only one commit.");
|
|
|
|
}
|
|
|
|
// This does the "hg id" call we need to normalize/validate the revision
|
|
|
|
// identifier.
|
|
|
|
$this->setRelativeCommit(reset($argv));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAllLocalChanges() {
|
|
|
|
$diff = $this->getFullMercurialDiff();
|
|
|
|
$parser = new ArcanistDiffParser();
|
|
|
|
return $parser->parseDiff($diff);
|
|
|
|
}
|
|
|
|
|
Add an "arc merge" workflow
Summary:
This should support conservative rewrite policies in git fairly well, under an
assumed workflow of:
- Develop in local branches, never rewrite history.
- Commit with "-m" or by typing a brief, non-template commit message
describing the checkpoint.
- Provide rich information in the web console (reviewers, etc.)
- Finalize with "git checkout master && arc merge branch && git push" or some
flavor thereof.
This supports Mercurial somewhat. The major problem is that "hg merge" fails if
the local is a fastforward of the remote, at which point there's nowhere we can
throw the commit message. Oh well. Just push it and we'll do our best to link
them up based on local commit info.
I am increasingly forming an opinion that Mercurial is "saftey-scissors git".
But also maybe I have no clue what I'm doing. I just don't understand why anyone
would think it's a good idea to have a trunk consisting of ~50% known-broken
revisions, random checkpoint parts, whitespace changes, typo fixes, etc. If you
use git with branching you can avoid this by making a trunk out of merges or
with rebase/amend, but there seems to be no way to have "one commit = one idea"
in any real sense in Mercurial.
Test Plan: Execute "arc merge" in git and mercurial.
Reviewers: fratrik, Makinde, aran, jungejason, tuomaspelkonen
Reviewed By: Makinde
CC: aran, epriestley, Makinde
Differential Revision: 860
2011-08-25 16:02:03 -07:00
|
|
|
public function supportsLocalBranchMerge() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function performLocalBranchMerge($branch, $message) {
|
|
|
|
if ($branch) {
|
|
|
|
$err = phutil_passthru(
|
|
|
|
'(cd %s && hg merge --rev %s && hg commit -m %s)',
|
|
|
|
$this->getPath(),
|
|
|
|
$branch,
|
|
|
|
$message);
|
|
|
|
} else {
|
|
|
|
$err = phutil_passthru(
|
|
|
|
'(cd %s && hg merge && hg commit -m %s)',
|
|
|
|
$this->getPath(),
|
|
|
|
$message);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($err) {
|
|
|
|
throw new ArcanistUsageException("Merge failed!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getFinalizedRevisionMessage() {
|
|
|
|
return "You may now push this commit upstream, as appropriate (e.g. with ".
|
|
|
|
"'hg push' or by printing and faxing it).";
|
|
|
|
}
|
|
|
|
|
Basic Mercurial support for Arcanist
Summary:
There's a lot of ground left to cover but this makes "arc diff" work (on one
trivial diff) in my sandbox, at least, and supports parsing of Mercurial native
diffs (which are unified + a custom header). Piles of missing features, still.
Some of this is blocked by me not understanding the mercurial model well yet.
This is also a really good opportunity for cleanup (especially, reducing the
level of "instanceof" in the diff workflow), I'll try to do a bunch of that in
followup diffs.
Test Plan: Ran "arc diff" in a mercurial repository, got a diff out of it.
Reviewed By: aran
Reviewers: Makinde, jungejason, tuomaspelkonen, aran, codeblock
CC: aran, epriestley, codeblock, fratrik
Differential Revision: 792
2011-08-09 09:00:29 -07:00
|
|
|
}
|