@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at recaptime-dev/main 219 lines 6.0 kB view raw
1<?php 2 3abstract class DiffusionQuery extends PhabricatorQuery { 4 5 private $request; 6 7 final protected function __construct() { 8 // <protected> 9 } 10 11 protected static function newQueryObject( 12 $base_class, 13 DiffusionRequest $request) { 14 15 $repository = $request->getRepository(); 16 17 $obj = self::initQueryObject($base_class, $repository); 18 $obj->request = $request; 19 20 return $obj; 21 } 22 23 final protected static function initQueryObject( 24 $base_class, 25 PhabricatorRepository $repository) { 26 27 $map = array( 28 PhabricatorRepositoryType::REPOSITORY_TYPE_GIT => 'Git', 29 PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL => 'Mercurial', 30 PhabricatorRepositoryType::REPOSITORY_TYPE_SVN => 'Svn', 31 ); 32 33 $name = idx($map, $repository->getVersionControlSystem()); 34 if (!$name) { 35 throw new Exception(pht('Unsupported VCS!')); 36 } 37 38 $class = str_replace('Diffusion', 'Diffusion'.$name, $base_class); 39 $obj = new $class(); 40 return $obj; 41 } 42 43 final protected function getRequest() { 44 return $this->request; 45 } 46 47 final public static function callConduitWithDiffusionRequest( 48 PhabricatorUser $user, 49 DiffusionRequest $drequest, 50 $method, 51 array $params = array(), 52 $return_future = false) { 53 54 $repository = $drequest->getRepository(); 55 56 $core_params = array( 57 'repository' => $repository->getPHID(), 58 ); 59 60 if ($drequest->getBranch() !== null) { 61 $core_params['branch'] = $drequest->getBranch(); 62 } 63 64 // If the method we're calling doesn't actually take some of the implicit 65 // parameters we derive from the DiffusionRequest, omit them. 66 $method_object = ConduitAPIMethod::getConduitMethod($method); 67 $method_params = $method_object->getParamTypes(); 68 foreach ($core_params as $key => $value) { 69 if (empty($method_params[$key])) { 70 unset($core_params[$key]); 71 } 72 } 73 74 $params = $params + $core_params; 75 76 $future = $repository->newConduitFuture( 77 $user, 78 $method, 79 $params, 80 $drequest->getIsClusterRequest()); 81 82 if (!$return_future) { 83 return $future->resolve(); 84 } 85 86 return $future; 87 } 88 89 public function execute() { 90 return $this->executeQuery(); 91 } 92 93 abstract protected function executeQuery(); 94 95 96/* -( Query Utilities )---------------------------------------------------- */ 97 98 99 final public static function loadCommitsByIdentifiers( 100 array $identifiers, 101 DiffusionRequest $drequest) { 102 if (!$identifiers) { 103 return array(); 104 } 105 106 $commits = array(); 107 $commit_data = array(); 108 109 $repository = $drequest->getRepository(); 110 111 $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere( 112 'repositoryID = %d AND commitIdentifier IN (%Ls)', 113 $repository->getID(), 114 $identifiers); 115 $commits = mpull($commits, null, 'getCommitIdentifier'); 116 117 // Build empty commit objects for every commit, so we can show unparsed 118 // commits in history views (as "Importing") instead of not showing them. 119 // This makes the process of importing and parsing commits clearer to the 120 // user. 121 122 $commit_list = array(); 123 foreach ($identifiers as $identifier) { 124 $commit_obj = idx($commits, $identifier); 125 if (!$commit_obj) { 126 $commit_obj = new PhabricatorRepositoryCommit(); 127 $commit_obj->setRepositoryID($repository->getID()); 128 $commit_obj->setCommitIdentifier($identifier); 129 $commit_obj->makeEphemeral(); 130 } 131 $commit_list[$identifier] = $commit_obj; 132 } 133 $commits = $commit_list; 134 135 $commit_ids = array_filter(mpull($commits, 'getID')); 136 if ($commit_ids) { 137 $commit_data = id(new PhabricatorRepositoryCommitData())->loadAllWhere( 138 'commitID in (%Ld)', 139 $commit_ids); 140 $commit_data = mpull($commit_data, null, 'getCommitID'); 141 } 142 143 foreach ($commits as $commit) { 144 if (!$commit->getID()) { 145 continue; 146 } 147 if (idx($commit_data, $commit->getID())) { 148 $commit->attachCommitData($commit_data[$commit->getID()]); 149 } 150 } 151 152 return $commits; 153 } 154 155 final public static function loadHistoryForCommitIdentifiers( 156 array $identifiers, 157 DiffusionRequest $drequest) { 158 159 if (!$identifiers) { 160 return array(); 161 } 162 163 $repository = $drequest->getRepository(); 164 $commits = self::loadCommitsByIdentifiers($identifiers, $drequest); 165 166 if (!$commits) { 167 return array(); 168 } 169 170 $path = $drequest->getPath(); 171 172 $conn_r = $repository->establishConnection('r'); 173 174 $path_normal = DiffusionPathIDQuery::normalizePath($path); 175 $paths = queryfx_all( 176 $conn_r, 177 'SELECT id, path FROM %T WHERE pathHash IN (%Ls)', 178 PhabricatorRepository::TABLE_PATH, 179 array(md5($path_normal))); 180 $paths = ipull($paths, 'id', 'path'); 181 $path_id = idx($paths, $path_normal); 182 183 $commit_ids = array_filter(mpull($commits, 'getID')); 184 185 $path_changes = array(); 186 if ($path_id && $commit_ids) { 187 $path_changes = queryfx_all( 188 $conn_r, 189 'SELECT * FROM %T WHERE commitID IN (%Ld) AND pathID = %d', 190 PhabricatorRepository::TABLE_PATHCHANGE, 191 $commit_ids, 192 $path_id); 193 $path_changes = ipull($path_changes, null, 'commitID'); 194 } 195 196 $history = array(); 197 foreach ($identifiers as $identifier) { 198 $item = new DiffusionPathChange(); 199 $item->setCommitIdentifier($identifier); 200 $commit = idx($commits, $identifier); 201 if ($commit) { 202 $item->setCommit($commit); 203 try { 204 $item->setCommitData($commit->getCommitData()); 205 } catch (Exception $ex) { 206 // Ignore, commit just doesn't have data. 207 } 208 $change = idx($path_changes, $commit->getID()); 209 if ($change) { 210 $item->setChangeType($change['changeType']); 211 $item->setFileType($change['fileType']); 212 } 213 } 214 $history[] = $item; 215 } 216 217 return $history; 218 } 219}