@@ -7,6 +7,12 @@ final class DiffusionCommitController extends DiffusionController {
77 private $ auditAuthorityPHIDs ;
88 private $ highlightedAudits ;
99
10+ private $ commitParents ;
11+ private $ commitRefs ;
12+ private $ commitMerges ;
13+ private $ commitErrors ;
14+ private $ commitExists ;
15+
1016 public function shouldAllowPublic () {
1117 return true ;
1218 }
@@ -17,6 +23,7 @@ protected function shouldLoadDiffusionRequest() {
1723
1824 protected function processDiffusionRequest (AphrontRequest $ request ) {
1925 $ user = $ request ->getUser ();
26+
2027 // This controller doesn't use blob/path stuff, just pass the dictionary
2128 // in directly instead of using the AphrontRequest parsing mechanism.
2229 $ data = $ request ->getURIMap ();
@@ -45,10 +52,7 @@ protected function processDiffusionRequest(AphrontRequest $request) {
4552 ));
4653
4754 if (!$ commit ) {
48- $ exists = $ this ->callConduitWithDiffusionRequest (
49- 'diffusion.existsquery ' ,
50- array ('commit ' => $ drequest ->getCommit ()));
51- if (!$ exists ) {
55+ if (!$ this ->getCommitExists ()) {
5256 return new Aphront404Response ();
5357 }
5458
@@ -95,18 +99,6 @@ protected function processDiffusionRequest(AphrontRequest $request) {
9599
96100 require_celerity_resource ('phabricator-remarkup-css ' );
97101
98- $ parents = $ this ->callConduitWithDiffusionRequest (
99- 'diffusion.commitparentsquery ' ,
100- array ('commit ' => $ drequest ->getCommit ()));
101-
102- if ($ parents ) {
103- $ parents = id (new DiffusionCommitQuery ())
104- ->setViewer ($ user )
105- ->withRepository ($ repository )
106- ->withIdentifiers ($ parents )
107- ->execute ();
108- }
109-
110102 $ headsup_view = id (new PHUIHeaderView ())
111103 ->setHeader (nonempty ($ commit ->getSummary (), pht ('Commit Detail ' )));
112104
@@ -115,7 +107,6 @@ protected function processDiffusionRequest(AphrontRequest $request) {
115107 $ commit_properties = $ this ->loadCommitProperties (
116108 $ commit ,
117109 $ commit_data ,
118- $ parents ,
119110 $ audit_requests );
120111 $ property_list = id (new PHUIPropertyListView ())
121112 ->setHasKeyboardShortcuts (true )
@@ -148,8 +139,10 @@ protected function processDiffusionRequest(AphrontRequest $request) {
148139 $ message ));
149140
150141 $ headsup_view ->setTall (true );
142+
151143 $ object_box = id (new PHUIObjectBoxView ())
152144 ->setHeader ($ headsup_view )
145+ ->setFormErrors ($ this ->getCommitErrors ())
153146 ->addPropertyList ($ property_list )
154147 ->addPropertyList ($ detail_list );
155148
@@ -216,6 +209,10 @@ protected function processDiffusionRequest(AphrontRequest $request) {
216209 'This commit is enormous, and affects more than %d files. ' .
217210 'Changes are not shown. ' ,
218211 $ hard_limit ));
212+ } else if (!$ this ->getCommitExists ()) {
213+ $ content [] = $ this ->renderStatusMessage (
214+ pht ('Commit No Longer Exists ' ),
215+ pht ('This commit no longer exists in the repository. ' ));
219216 } else {
220217 $ show_changesets = true ;
221218
@@ -382,10 +379,8 @@ protected function processDiffusionRequest(AphrontRequest $request) {
382379 private function loadCommitProperties (
383380 PhabricatorRepositoryCommit $ commit ,
384381 PhabricatorRepositoryCommitData $ data ,
385- array $ parents ,
386382 array $ audit_requests ) {
387383
388- assert_instances_of ($ parents , 'PhabricatorRepositoryCommit ' );
389384 $ viewer = $ this ->getRequest ()->getUser ();
390385 $ commit_phid = $ commit ->getPHID ();
391386 $ drequest = $ this ->getDiffusionRequest ();
@@ -423,11 +418,6 @@ private function loadCommitProperties(
423418 if ($ data ->getCommitDetail ('committerPHID ' )) {
424419 $ phids [] = $ data ->getCommitDetail ('committerPHID ' );
425420 }
426- if ($ parents ) {
427- foreach ($ parents as $ parent ) {
428- $ phids [] = $ parent ->getPHID ();
429- }
430- }
431421
432422 // NOTE: We should never normally have more than a single push log, but
433423 // it can occur naturally if a commit is pushed, then the branch it was
@@ -564,39 +554,47 @@ private function loadCommitProperties(
564554 $ props ['Differential Revision ' ] = $ handles [$ revision_phid ]->renderLink ();
565555 }
566556
557+ $ parents = $ this ->getCommitParents ();
567558 if ($ parents ) {
568- $ parent_links = array ();
569- foreach ($ parents as $ parent ) {
570- $ parent_links [] = $ handles [$ parent ->getPHID ()]->renderLink ();
571- }
572- $ props ['Parents ' ] = phutil_implode_html (" \xC2\xB7 " , $ parent_links );
559+ $ props ['Parents ' ] = $ viewer ->renderHandleList (mpull ($ parents , 'getPHID ' ));
573560 }
574561
575- $ props ['Branches ' ] = phutil_tag (
576- 'span ' ,
577- array (
578- 'id ' => 'commit-branches ' ,
579- ),
580- pht ('Unknown ' ));
581- $ props ['Tags ' ] = phutil_tag (
582- 'span ' ,
583- array (
584- 'id ' => 'commit-tags ' ,
585- ),
586- pht ('Unknown ' ));
562+ if ($ this ->getCommitExists ()) {
563+ $ props ['Branches ' ] = phutil_tag (
564+ 'span ' ,
565+ array (
566+ 'id ' => 'commit-branches ' ,
567+ ),
568+ pht ('Unknown ' ));
569+ $ props ['Tags ' ] = phutil_tag (
570+ 'span ' ,
571+ array (
572+ 'id ' => 'commit-tags ' ,
573+ ),
574+ pht ('Unknown ' ));
587575
588- $ callsign = $ repository ->getCallsign ();
589- $ root = '/diffusion/ ' .$ callsign .'/commit/ ' .$ commit ->getCommitIdentifier ();
590- Javelin::initBehavior (
591- 'diffusion-commit-branches ' ,
592- array (
593- $ root .'/branches/ ' => 'commit-branches ' ,
594- $ root .'/tags/ ' => 'commit-tags ' ,
595- ));
576+ $ callsign = $ repository ->getCallsign ();
577+ $ root = '/diffusion/ ' .$ callsign .'/commit/ ' .$ commit ->getCommitIdentifier ();
578+ Javelin::initBehavior (
579+ 'diffusion-commit-branches ' ,
580+ array (
581+ $ root .'/branches/ ' => 'commit-branches ' ,
582+ $ root .'/tags/ ' => 'commit-tags ' ,
583+ ));
584+ }
596585
597- $ refs = $ this ->buildRefs ( $ drequest );
586+ $ refs = $ this ->getCommitRefs ( );
598587 if ($ refs ) {
599- $ props ['References ' ] = $ refs ;
588+ $ ref_links = array ();
589+ foreach ($ refs as $ ref_data ) {
590+ $ ref_links [] = phutil_tag (
591+ 'a ' ,
592+ array (
593+ 'href ' => $ ref_data ['href ' ],
594+ ),
595+ $ ref_data ['ref ' ]);
596+ }
597+ $ props ['References ' ] = phutil_implode_html (', ' , $ ref_links );
600598 }
601599
602600 if ($ reverts_phids ) {
@@ -860,26 +858,12 @@ private function buildMergesTable(PhabricatorRepositoryCommit $commit) {
860858 $ drequest = $ this ->getDiffusionRequest ();
861859 $ repository = $ drequest ->getRepository ();
862860
863- $ vcs = $ repository ->getVersionControlSystem ();
864- switch ($ vcs ) {
865- case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN :
866- // These aren't supported under SVN.
867- return null ;
868- }
869-
870- $ limit = 50 ;
871-
872- $ merges = $ this ->callConduitWithDiffusionRequest (
873- 'diffusion.mergedcommitsquery ' ,
874- array (
875- 'commit ' => $ drequest ->getCommit (),
876- 'limit ' => $ limit + 1 ,
877- ));
878-
861+ $ merges = $ this ->getCommitMerges ();
879862 if (!$ merges ) {
880863 return null ;
881864 }
882- $ merges = DiffusionPathChange::newFromConduit ($ merges );
865+
866+ $ limit = $ this ->getMergeDisplayLimit ();
883867
884868 $ caption = null ;
885869 if (count ($ merges ) > $ limit ) {
@@ -961,27 +945,6 @@ private function renderHeadsupActionList(
961945 return $ actions ;
962946 }
963947
964- private function buildRefs (DiffusionRequest $ request ) {
965- // this is git-only, so save a conduit round trip and just get out of
966- // here if the repository isn't git
967- $ type_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT ;
968- $ repository = $ request ->getRepository ();
969- if ($ repository ->getVersionControlSystem () != $ type_git ) {
970- return null ;
971- }
972-
973- $ results = $ this ->callConduitWithDiffusionRequest (
974- 'diffusion.refsquery ' ,
975- array ('commit ' => $ request ->getCommit ()));
976- $ ref_links = array ();
977- foreach ($ results as $ ref_data ) {
978- $ ref_links [] = phutil_tag ('a ' ,
979- array ('href ' => $ ref_data ['href ' ]),
980- $ ref_data ['ref ' ]);
981- }
982- return phutil_implode_html (', ' , $ ref_links );
983- }
984-
985948 private function buildRawDiffResponse (DiffusionRequest $ drequest ) {
986949 $ raw_diff = $ this ->callConduitWithDiffusionRequest (
987950 'diffusion.rawdiffquery ' ,
@@ -1137,4 +1100,140 @@ private function buildTableOfContents(array $changesets) {
11371100 return $ toc_view ;
11381101 }
11391102
1103+ private function loadCommitState () {
1104+ $ viewer = $ this ->getViewer ();
1105+ $ drequest = $ this ->getDiffusionRequest ();
1106+ $ repository = $ drequest ->getRepository ();
1107+ $ commit = $ drequest ->getCommit ();
1108+
1109+ // TODO: We could use futures here and resolve these calls in parallel.
1110+
1111+ $ exceptions = array ();
1112+
1113+ try {
1114+ $ parent_refs = $ this ->callConduitWithDiffusionRequest (
1115+ 'diffusion.commitparentsquery ' ,
1116+ array (
1117+ 'commit ' => $ commit ,
1118+ ));
1119+
1120+ if ($ parent_refs ) {
1121+ $ parents = id (new DiffusionCommitQuery ())
1122+ ->setViewer ($ viewer )
1123+ ->withRepository ($ repository )
1124+ ->withIdentifiers ($ parent_refs )
1125+ ->execute ();
1126+ } else {
1127+ $ parents = array ();
1128+ }
1129+
1130+ $ this ->commitParents = $ parents ;
1131+ } catch (Exception $ ex ) {
1132+ $ this ->commitParents = false ;
1133+ $ exceptions [] = $ ex ;
1134+ }
1135+
1136+ $ merge_limit = $ this ->getMergeDisplayLimit ();
1137+
1138+ try {
1139+ $ merges = $ this ->callConduitWithDiffusionRequest (
1140+ 'diffusion.mergedcommitsquery ' ,
1141+ array (
1142+ 'commit ' => $ commit ,
1143+ 'limit ' => $ merge_limit + 1 ,
1144+ ));
1145+
1146+ $ this ->commitMerges = DiffusionPathChange::newFromConduit ($ merges );
1147+ } catch (Exception $ ex ) {
1148+ $ this ->commitMerges = false ;
1149+ $ exceptions [] = $ ex ;
1150+ }
1151+
1152+
1153+ try {
1154+ if ($ repository ->isGit ()) {
1155+ $ refs = $ this ->callConduitWithDiffusionRequest (
1156+ 'diffusion.refsquery ' ,
1157+ array (
1158+ 'commit ' => $ commit ,
1159+ ));
1160+ } else {
1161+ $ refs = array ();
1162+ }
1163+
1164+ $ this ->commitRefs = $ refs ;
1165+ } catch (Exception $ ex ) {
1166+ $ this ->commitRefs = false ;
1167+ $ exceptions [] = $ ex ;
1168+ }
1169+
1170+ if ($ exceptions ) {
1171+ $ exists = $ this ->callConduitWithDiffusionRequest (
1172+ 'diffusion.existsquery ' ,
1173+ array (
1174+ 'commit ' => $ commit ,
1175+ ));
1176+
1177+ if ($ exists ) {
1178+ $ this ->commitExists = true ;
1179+ foreach ($ exceptions as $ exception ) {
1180+ $ this ->commitErrors [] = $ exception ->getMessage ();
1181+ }
1182+ } else {
1183+ $ this ->commitExists = false ;
1184+ $ this ->commitErrors [] = pht (
1185+ 'This commit no longer exists in the repository. It may have ' .
1186+ 'been part of a branch which was deleted. ' );
1187+ }
1188+ } else {
1189+ $ this ->commitExists = true ;
1190+ $ this ->commitErrors = array ();
1191+ }
1192+ }
1193+
1194+ private function getMergeDisplayLimit () {
1195+ return 50 ;
1196+ }
1197+
1198+ private function getCommitExists () {
1199+ if ($ this ->commitExists === null ) {
1200+ $ this ->loadCommitState ();
1201+ }
1202+
1203+ return $ this ->commitExists ;
1204+ }
1205+
1206+ private function getCommitParents () {
1207+ if ($ this ->commitParents === null ) {
1208+ $ this ->loadCommitState ();
1209+ }
1210+
1211+ return $ this ->commitParents ;
1212+ }
1213+
1214+ private function getCommitRefs () {
1215+ if ($ this ->commitRefs === null ) {
1216+ $ this ->loadCommitState ();
1217+ }
1218+
1219+ return $ this ->commitRefs ;
1220+ }
1221+
1222+ private function getCommitMerges () {
1223+ if ($ this ->commitMerges === null ) {
1224+ $ this ->loadCommitState ();
1225+ }
1226+
1227+ return $ this ->commitMerges ;
1228+ }
1229+
1230+ private function getCommitErrors () {
1231+ if ($ this ->commitErrors === null ) {
1232+ $ this ->loadCommitState ();
1233+ }
1234+
1235+ return $ this ->commitErrors ;
1236+ }
1237+
1238+
11401239}
0 commit comments