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
|
|
|
|
|
|
|
|
/*
|
2012-01-06 13:14:41 -08:00
|
|
|
* Copyright 2012 Facebook, Inc.
|
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
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
2012-01-31 12:07:05 -08:00
|
|
|
final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
|
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 $status;
|
|
|
|
private $base;
|
2011-08-09 18:54:10 -07:00
|
|
|
private $relativeCommit;
|
2012-02-28 16:59:40 -08:00
|
|
|
private $workingCopyRevision;
|
|
|
|
private $localCommitInfo;
|
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
|
|
|
|
2012-03-02 16:47:34 -08:00
|
|
|
protected function buildLocalFuture(array $argv) {
|
2012-02-28 16:56:57 -08:00
|
|
|
|
|
|
|
// Mercurial has a "defaults" feature which basically breaks automation by
|
|
|
|
// allowing the user to add random flags to any command. This feature is
|
|
|
|
// "deprecated" and "a bad idea" that you should "forget ... existed"
|
|
|
|
// according to project lead Matt Mackall:
|
|
|
|
//
|
|
|
|
// http://markmail.org/message/hl3d6eprubmkkqh5
|
|
|
|
//
|
|
|
|
// There is an HGPLAIN environmental variable which enables "plain mode"
|
|
|
|
// and hopefully disables this stuff.
|
|
|
|
|
|
|
|
$argv[0] = 'HGPLAIN=1 hg '.$argv[0];
|
|
|
|
|
|
|
|
$future = newv('ExecFuture', $argv);
|
|
|
|
$future->setCWD($this->getPath());
|
|
|
|
return $future;
|
|
|
|
}
|
|
|
|
|
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() {
|
2012-02-28 16:56:57 -08:00
|
|
|
list($stdout) = $this->execxLocal(
|
|
|
|
'log -l 1 --template %s -r %s',
|
2012-01-16 17:12:34 -08:00
|
|
|
'{node}\\n',
|
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->getRelativeCommit());
|
2012-01-16 17:12:34 -08:00
|
|
|
return rtrim($stdout, "\n");
|
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 getSourceControlPath() {
|
|
|
|
return '/';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getBranchName() {
|
2012-01-24 08:07:38 -08:00
|
|
|
// TODO: I have nearly no idea how hg branches work.
|
2012-02-28 16:56:57 -08:00
|
|
|
list($stdout) = $this->execxLocal('branch');
|
2012-01-24 08:07:38 -08:00
|
|
|
return trim($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-08-09 18:54:10 -07:00
|
|
|
public function setRelativeCommit($commit) {
|
2012-02-28 16:56:57 -08:00
|
|
|
list($err) = $this->execManualLocal('id -ir %s', $commit);
|
2011-08-09 18:54:10 -07:00
|
|
|
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)) {
|
2012-02-28 16:56:57 -08:00
|
|
|
list($stdout) = $this->execxLocal(
|
|
|
|
'outgoing --branch `hg branch` --style default');
|
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!");
|
|
|
|
}
|
|
|
|
|
2012-01-06 13:14:41 -08:00
|
|
|
$outgoing_revs = ipull($logs, 'rev');
|
|
|
|
|
|
|
|
// This is essentially an implementation of a theoretical `hg merge-base`
|
|
|
|
// command.
|
|
|
|
$against = 'tip';
|
|
|
|
while (true) {
|
|
|
|
// 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".
|
|
|
|
|
2012-02-28 16:56:57 -08:00
|
|
|
list($stdout) = $this->execxLocal(
|
|
|
|
'parents --style default --rev %s',
|
2012-01-06 13:14:41 -08:00
|
|
|
$against);
|
|
|
|
$parents_logs = ArcanistMercurialParser::parseMercurialLog($stdout);
|
|
|
|
|
|
|
|
list($p1, $p2) = array_merge($parents_logs, array(null, null));
|
|
|
|
|
|
|
|
if ($p1 && !in_array($p1['rev'], $outgoing_revs)) {
|
|
|
|
$against = $p1['rev'];
|
|
|
|
break;
|
|
|
|
} else if ($p2 && !in_array($p2['rev'], $outgoing_revs)) {
|
|
|
|
$against = $p2['rev'];
|
|
|
|
break;
|
|
|
|
} else if ($p1) {
|
|
|
|
$against = $p1['rev'];
|
|
|
|
} else {
|
|
|
|
// This is the case where you have a new repository and the entire
|
|
|
|
// thing is outgoing; Mercurial literally accepts "--rev null" as
|
|
|
|
// meaning "diff against the empty state".
|
|
|
|
$against = 'null';
|
|
|
|
break;
|
|
|
|
}
|
2011-09-14 18:11:00 -07:00
|
|
|
}
|
|
|
|
|
2012-01-06 13:14:41 -08:00
|
|
|
$this->relativeCommit = $against;
|
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() {
|
2012-02-28 16:59:40 -08:00
|
|
|
if ($this->localCommitInfo === null) {
|
|
|
|
list($info) = $this->execxLocal(
|
|
|
|
'log --style default --rev %s..%s --',
|
|
|
|
$this->getRelativeCommit(),
|
|
|
|
$this->getWorkingCopyRevision());
|
|
|
|
$logs = ArcanistMercurialParser::parseMercurialLog($info);
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
2011-09-26 14:35:42 -07:00
|
|
|
|
2012-02-28 16:59:40 -08:00
|
|
|
list($full) = $this->execxLocal(
|
|
|
|
'log --template %s %C --',
|
|
|
|
'{node}\\n',
|
|
|
|
implode(' ', $cmd));
|
2011-09-26 14:35:42 -07:00
|
|
|
|
2012-02-28 16:59:40 -08:00
|
|
|
$full = explode("\n", trim($full));
|
|
|
|
foreach ($logs as $key => $dict) {
|
|
|
|
$logs[$key]['rev'] = array_pop($full);
|
|
|
|
}
|
2011-09-26 14:35:42 -07:00
|
|
|
}
|
2012-02-28 16:59:40 -08:00
|
|
|
$this->localCommitInfo = $logs;
|
2011-09-26 14:35:42 -07:00
|
|
|
}
|
|
|
|
|
2012-02-28 16:59:40 -08:00
|
|
|
return $this->localCommitInfo;
|
2011-08-23 18:48:55 -07:00
|
|
|
}
|
|
|
|
|
2011-12-13 09:44:31 -08:00
|
|
|
public function getBlame($path) {
|
2012-02-28 16:56:57 -08:00
|
|
|
list($stdout) = $this->execxLocal(
|
|
|
|
'annotate -u -v -c --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->getRelativeCommit(),
|
|
|
|
$path);
|
|
|
|
|
|
|
|
$blame = array();
|
|
|
|
foreach (explode("\n", trim($stdout)) as $line) {
|
|
|
|
if (!strlen($line)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$matches = null;
|
2011-12-12 14:28:34 -08:00
|
|
|
$ok = preg_match('/^\s*([^:]+?) [a-f0-9]{12}: (.*)$/', $line, $matches);
|
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
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-02-28 16:56:57 -08:00
|
|
|
list($stdout) = $this->execxLocal('status');
|
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();
|
|
|
|
|
2012-02-28 16:56:57 -08:00
|
|
|
list($stdout) = $this->execxLocal(
|
|
|
|
'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
|
|
|
$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();
|
|
|
|
|
2012-02-28 16:56:57 -08:00
|
|
|
list($stdout) = $this->execxLocal(
|
|
|
|
'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
|
|
|
$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) {
|
2012-02-28 16:56:57 -08:00
|
|
|
list($err, $stdout) = $this->execManualLocal(
|
|
|
|
'cat --rev %s -- %s',
|
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-12-02 16:21:14 -08:00
|
|
|
public function getWorkingCopyRevision() {
|
2012-02-28 16:59:40 -08:00
|
|
|
if ($this->workingCopyRevision === null) {
|
|
|
|
// 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.
|
|
|
|
|
|
|
|
// Without arguments, "hg id" shows the current working directory's
|
|
|
|
// commit, and "--debug" expands it to a 40-character hash.
|
|
|
|
list($stdout) = $this->execxLocal('--debug id --id');
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
$this->workingCopyRevision = rtrim($stdout, '+');
|
|
|
|
}
|
|
|
|
return $this->workingCopyRevision;
|
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();
|
2012-02-29 12:18:46 -08:00
|
|
|
if (!strlen(trim($diff))) {
|
|
|
|
return array();
|
|
|
|
}
|
2011-09-14 18:44:54 -07:00
|
|
|
$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(
|
2012-02-28 16:56:57 -08:00
|
|
|
'(cd %s && HGPLAIN=1 hg merge --rev %s && hg commit -m %s)',
|
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
|
|
|
$this->getPath(),
|
|
|
|
$branch,
|
|
|
|
$message);
|
|
|
|
} else {
|
|
|
|
$err = phutil_passthru(
|
2012-02-28 16:56:57 -08:00
|
|
|
'(cd %s && HGPLAIN=1 hg merge && hg commit -m %s)',
|
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
|
|
|
$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).";
|
|
|
|
}
|
|
|
|
|
2012-02-28 16:59:40 -08:00
|
|
|
public function getCommitMessageLog() {
|
|
|
|
list($stdout) = $this->execxLocal(
|
|
|
|
"log --template '{node}\\1{desc}\\0' --rev %s..%s --",
|
|
|
|
$this->getRelativeCommit(),
|
|
|
|
$this->getWorkingCopyRevision());
|
|
|
|
|
|
|
|
$map = array();
|
|
|
|
|
|
|
|
$logs = explode("\0", trim($stdout));
|
|
|
|
foreach (array_filter($logs) as $log) {
|
|
|
|
list($node, $desc) = explode("\1", $log);
|
|
|
|
$map[$node] = $desc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return array_reverse($map);
|
|
|
|
}
|
|
|
|
|
2012-01-24 08:07:38 -08:00
|
|
|
public function loadWorkingCopyDifferentialRevisions(
|
|
|
|
ConduitClient $conduit,
|
|
|
|
array $query) {
|
|
|
|
|
|
|
|
// Try to find revisions by hash.
|
|
|
|
$hashes = array();
|
|
|
|
foreach ($this->getLocalCommitInformation() as $commit) {
|
|
|
|
$hashes[] = array('hgcm', $commit['rev']);
|
|
|
|
}
|
|
|
|
|
|
|
|
$results = $conduit->callMethodSynchronous(
|
|
|
|
'differential.query',
|
|
|
|
$query + array(
|
|
|
|
'commitHashes' => $hashes,
|
|
|
|
));
|
|
|
|
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|