Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15423966
D7764.id17599.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D7764.id17599.diff
View Options
Index: scripts/repository/commit_hook.php
===================================================================
--- scripts/repository/commit_hook.php
+++ scripts/repository/commit_hook.php
@@ -36,9 +36,10 @@
pht('usage: %s should be defined!', DiffusionCommitHookEngine::ENV_USER));
}
- // TODO: If this is a Mercurial repository, the hook we're responding to
- // is available in $argv[2]. It's unclear if we actually need this, or if
- // we can block all actions we care about with just pretxnchangegroup.
+ if ($repository->isHg()) {
+ // We respond to several different hooks in Mercurial.
+ $engine->setMercurialHook($argv[2]);
+ }
} else if ($repository->isSVN()) {
// NOTE: In Subversion, the entire environment gets wiped so we can't read
Index: src/applications/diffusion/engine/DiffusionCommitHookEngine.php
===================================================================
--- src/applications/diffusion/engine/DiffusionCommitHookEngine.php
+++ src/applications/diffusion/engine/DiffusionCommitHookEngine.php
@@ -24,6 +24,7 @@
private $remoteAddress;
private $remoteProtocol;
private $transactionKey;
+ private $mercurialHook;
/* -( Config )------------------------------------------------------------- */
@@ -97,6 +98,15 @@
return $this->viewer;
}
+ public function setMercurialHook($mercurial_hook) {
+ $this->mercurialHook = $mercurial_hook;
+ return $this;
+ }
+
+ public function getMercurialHook() {
+ return $this->mercurialHook;
+ }
+
/* -( Hook Execution )----------------------------------------------------- */
@@ -239,7 +249,10 @@
} else if (preg_match('(^refs/tags/)', $ref_raw)) {
$ref_type = PhabricatorRepositoryPushLog::REFTYPE_TAG;
} else {
- $ref_type = PhabricatorRepositoryPushLog::REFTYPE_UNKNOWN;
+ throw new Exception(
+ pht(
+ "Unable to identify the reftype of '%s'. Rejecting push.",
+ $ref_raw));
}
$ref_update = $this->newPushLog()
@@ -413,6 +426,20 @@
private function findMercurialRefUpdates() {
+ $hook = $this->getMercurialHook();
+ switch ($hook) {
+ case 'pretxnchangegroup':
+ return $this->findMercurialChangegroupRefUpdates();
+ case 'prepushkey':
+ return $this->findMercurialPushKeyRefUpdates();
+ case 'pretag':
+ return $this->findMercurialPreTagRefUpdates();
+ default:
+ throw new Exception(pht('Unrecognized hook "%s"!', $hook));
+ }
+ }
+
+ private function findMercurialChangegroupRefUpdates() {
$hg_node = getenv('HG_NODE');
if (!$hg_node) {
throw new Exception(pht('Expected HG_NODE in environment!'));
@@ -594,6 +621,87 @@
return $ref_updates;
}
+ private function findMercurialPushKeyRefUpdates() {
+ $key_namespace = getenv('HG_NAMESPACE');
+
+ if ($key_namespace === 'phases') {
+ // Mercurial changes commit phases as part of normal push operations. We
+ // just ignore these, as they don't seem to represent anything
+ // interesting.
+ return array();
+ }
+
+ $key_name = getenv('HG_KEY');
+
+ $key_old = getenv('HG_OLD');
+ if (!strlen($key_old)) {
+ $key_old = null;
+ }
+
+ $key_new = getenv('HG_NEW');
+ if (!strlen($key_new)) {
+ $key_new = null;
+ }
+
+ if ($key_namespace !== 'bookmarks') {
+ throw new Exception(
+ pht(
+ "Unknown Mercurial key namespace '%s', with key '%s' (%s -> %s). ".
+ "Rejecting push.",
+ $key_namespace,
+ $key_name,
+ coalesce($key_old, pht('null')),
+ coalesce($key_new, pht('null'))));
+ }
+
+ if ($key_old === $key_new) {
+ // We get a callback when the bookmark doesn't change. Just ignore this,
+ // as it's a no-op.
+ return array();
+ }
+
+ $ref_flags = 0;
+ $merge_base = null;
+ if ($key_old === null) {
+ $ref_flags |= PhabricatorRepositoryPushLog::CHANGEFLAG_ADD;
+ } else if ($key_new === null) {
+ $ref_flags |= PhabricatorRepositoryPushLog::CHANGEFLAG_DELETE;
+ } else {
+ list($merge_base_raw) = $this->getRepository()->execxLocalCommand(
+ 'log --template %s --rev %s',
+ '{node}',
+ hgsprintf('ancestor(%s, %s)', $key_old, $key_new));
+
+ if (strlen(trim($merge_base_raw))) {
+ $merge_base = trim($merge_base_raw);
+ }
+
+ if ($merge_base && ($merge_base === $key_old)) {
+ $ref_flags |= PhabricatorRepositoryPushLog::CHANGEFLAG_APPEND;
+ } else {
+ $ref_flags |= PhabricatorRepositoryPushLog::CHANGEFLAG_REWRITE;
+ }
+ }
+
+ $ref_update = $this->newPushLog()
+ ->setRefType(PhabricatorRepositoryPushLog::REFTYPE_BOOKMARK)
+ ->setRefName($key_name)
+ ->setRefOld(coalesce($key_old, self::EMPTY_HASH))
+ ->setRefNew(coalesce($key_new, self::EMPTY_HASH))
+ ->setChangeFlags($ref_flags);
+
+ return array($ref_update);
+ }
+
+ private function findMercurialPreTagRefUpdates() {
+ return array();
+ }
+
+ private function findMercurialContentUpdates(array $ref_updates) {
+ // TODO: Implement.
+ return array();
+ }
+
private function parseMercurialCommits($raw) {
$commits_lines = explode("\2", $raw);
$commits_lines = array_filter($commits_lines);
@@ -626,11 +734,6 @@
return $heads;
}
- private function findMercurialContentUpdates(array $ref_updates) {
- // TODO: Implement.
- return array();
- }
-
/* -( Subversion )--------------------------------------------------------- */
Index: src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
===================================================================
--- src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
+++ src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
@@ -397,11 +397,27 @@
$data = array();
$data[] = '[hooks]';
+
+ // This hook handles normal pushes.
$data[] = csprintf(
'pretxnchangegroup.phabricator = %s %s %s',
$bin,
$repository->getCallsign(),
'pretxnchangegroup');
+
+ // This one handles creating bookmarks.
+ $data[] = csprintf(
+ 'prepushkey.phabricator = %s %s %s',
+ $bin,
+ $repository->getCallsign(),
+ 'prepushkey');
+
+ // This one handles creating tags.
+ $data[] = csprintf(
+ 'pretag.phabricator = %s %s %s',
+ $bin,
+ $repository->getCallsign(),
+ 'pretag');
$data[] = null;
$data = implode("\n", $data);
Index: src/applications/repository/storage/PhabricatorRepositoryPushLog.php
===================================================================
--- src/applications/repository/storage/PhabricatorRepositoryPushLog.php
+++ src/applications/repository/storage/PhabricatorRepositoryPushLog.php
@@ -18,7 +18,6 @@
const REFTYPE_BOOKMARK = 'bookmark';
const REFTYPE_SVN = 'svn';
const REFTYPE_COMMIT = 'commit';
- const REFTYPE_UNKNOWN = 'unknown';
const CHANGEFLAG_ADD = 1;
const CHANGEFLAG_DELETE = 2;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 23, 7:42 PM (1 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7388492
Default Alt Text
D7764.id17599.diff (6 KB)
Attached To
Mode
D7764: Support bookmark hook operations in Mercurial
Attached
Detach File
Event Timeline
Log In to Comment