@@ -24,6 +24,7 @@ final class DiffusionCommitHookEngine extends Phobject {
24
24
private $ remoteAddress ;
25
25
private $ remoteProtocol ;
26
26
private $ transactionKey ;
27
+ private $ mercurialHook ;
27
28
28
29
29
30
/* -( Config )------------------------------------------------------------- */
@@ -97,6 +98,15 @@ public function getViewer() {
97
98
return $ this ->viewer ;
98
99
}
99
100
101
+ public function setMercurialHook ($ mercurial_hook ) {
102
+ $ this ->mercurialHook = $ mercurial_hook ;
103
+ return $ this ;
104
+ }
105
+
106
+ public function getMercurialHook () {
107
+ return $ this ->mercurialHook ;
108
+ }
109
+
100
110
101
111
/* -( Hook Execution )----------------------------------------------------- */
102
112
@@ -239,7 +249,10 @@ private function findGitRefUpdates() {
239
249
} else if (preg_match ('(^refs/tags/) ' , $ ref_raw )) {
240
250
$ ref_type = PhabricatorRepositoryPushLog::REFTYPE_TAG ;
241
251
} else {
242
- $ ref_type = PhabricatorRepositoryPushLog::REFTYPE_UNKNOWN ;
252
+ throw new Exception (
253
+ pht (
254
+ "Unable to identify the reftype of '%s'. Rejecting push. " ,
255
+ $ ref_raw ));
243
256
}
244
257
245
258
$ ref_update = $ this ->newPushLog ()
@@ -413,6 +426,20 @@ private function findGitContentUpdates(array $ref_updates) {
413
426
414
427
415
428
private function findMercurialRefUpdates () {
429
+ $ hook = $ this ->getMercurialHook ();
430
+ switch ($ hook ) {
431
+ case 'pretxnchangegroup ' :
432
+ return $ this ->findMercurialChangegroupRefUpdates ();
433
+ case 'prepushkey ' :
434
+ return $ this ->findMercurialPushKeyRefUpdates ();
435
+ case 'pretag ' :
436
+ return $ this ->findMercurialPreTagRefUpdates ();
437
+ default :
438
+ throw new Exception (pht ('Unrecognized hook "%s"! ' , $ hook ));
439
+ }
440
+ }
441
+
442
+ private function findMercurialChangegroupRefUpdates () {
416
443
$ hg_node = getenv ('HG_NODE ' );
417
444
if (!$ hg_node ) {
418
445
throw new Exception (pht ('Expected HG_NODE in environment! ' ));
@@ -594,6 +621,87 @@ private function findMercurialRefUpdates() {
594
621
return $ ref_updates ;
595
622
}
596
623
624
+ private function findMercurialPushKeyRefUpdates () {
625
+ $ key_namespace = getenv ('HG_NAMESPACE ' );
626
+
627
+ if ($ key_namespace === 'phases ' ) {
628
+ // Mercurial changes commit phases as part of normal push operations. We
629
+ // just ignore these, as they don't seem to represent anything
630
+ // interesting.
631
+ return array ();
632
+ }
633
+
634
+ $ key_name = getenv ('HG_KEY ' );
635
+
636
+ $ key_old = getenv ('HG_OLD ' );
637
+ if (!strlen ($ key_old )) {
638
+ $ key_old = null ;
639
+ }
640
+
641
+ $ key_new = getenv ('HG_NEW ' );
642
+ if (!strlen ($ key_new )) {
643
+ $ key_new = null ;
644
+ }
645
+
646
+ if ($ key_namespace !== 'bookmarks ' ) {
647
+ throw new Exception (
648
+ pht (
649
+ "Unknown Mercurial key namespace '%s', with key '%s' (%s -> %s). " .
650
+ "Rejecting push. " ,
651
+ $ key_namespace ,
652
+ $ key_name ,
653
+ coalesce ($ key_old , pht ('null ' )),
654
+ coalesce ($ key_new , pht ('null ' ))));
655
+ }
656
+
657
+ if ($ key_old === $ key_new ) {
658
+ // We get a callback when the bookmark doesn't change. Just ignore this,
659
+ // as it's a no-op.
660
+ return array ();
661
+ }
662
+
663
+ $ ref_flags = 0 ;
664
+ $ merge_base = null ;
665
+ if ($ key_old === null ) {
666
+ $ ref_flags |= PhabricatorRepositoryPushLog::CHANGEFLAG_ADD ;
667
+ } else if ($ key_new === null ) {
668
+ $ ref_flags |= PhabricatorRepositoryPushLog::CHANGEFLAG_DELETE ;
669
+ } else {
670
+ list ($ merge_base_raw ) = $ this ->getRepository ()->execxLocalCommand (
671
+ 'log --template %s --rev %s ' ,
672
+ '{node} ' ,
673
+ hgsprintf ('ancestor(%s, %s) ' , $ key_old , $ key_new ));
674
+
675
+ if (strlen (trim ($ merge_base_raw ))) {
676
+ $ merge_base = trim ($ merge_base_raw );
677
+ }
678
+
679
+ if ($ merge_base && ($ merge_base === $ key_old )) {
680
+ $ ref_flags |= PhabricatorRepositoryPushLog::CHANGEFLAG_APPEND ;
681
+ } else {
682
+ $ ref_flags |= PhabricatorRepositoryPushLog::CHANGEFLAG_REWRITE ;
683
+ }
684
+ }
685
+
686
+ $ ref_update = $ this ->newPushLog ()
687
+ ->setRefType (PhabricatorRepositoryPushLog::REFTYPE_BOOKMARK )
688
+ ->setRefName ($ key_name )
689
+ ->setRefOld (coalesce ($ key_old , self ::EMPTY_HASH ))
690
+ ->setRefNew (coalesce ($ key_new , self ::EMPTY_HASH ))
691
+ ->setChangeFlags ($ ref_flags );
692
+
693
+ return array ($ ref_update );
694
+ }
695
+
696
+ private function findMercurialPreTagRefUpdates () {
697
+ return array ();
698
+ }
699
+
700
+ private function findMercurialContentUpdates (array $ ref_updates ) {
701
+ // TODO: Implement.
702
+ return array ();
703
+ }
704
+
597
705
private function parseMercurialCommits ($ raw ) {
598
706
$ commits_lines = explode ("\2" , $ raw );
599
707
$ commits_lines = array_filter ($ commits_lines );
@@ -626,11 +734,6 @@ private function parseMercurialHeads($raw) {
626
734
return $ heads ;
627
735
}
628
736
629
- private function findMercurialContentUpdates (array $ ref_updates ) {
630
- // TODO: Implement.
631
- return array ();
632
- }
633
-
634
737
635
738
/* -( Subversion )--------------------------------------------------------- */
636
739
0 commit comments