@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 136 lines 3.6 kB view raw
1<?php 2 3final class DifferentialAffectedPathEngine 4 extends Phobject { 5 6 private $revision; 7 private $diff; 8 9 public function setRevision(DifferentialRevision $revision) { 10 $this->revision = $revision; 11 return $this; 12 } 13 14 public function getRevision() { 15 return $this->revision; 16 } 17 18 public function setDiff(DifferentialDiff $diff) { 19 $this->diff = $diff; 20 return $this; 21 } 22 23 public function getDiff() { 24 return $this->diff; 25 } 26 27 public function updateAffectedPaths() { 28 $revision = $this->getRevision(); 29 $diff = $this->getDiff(); 30 $repository = $revision->getRepository(); 31 32 if ($repository) { 33 $repository_id = $repository->getID(); 34 } else { 35 $repository_id = null; 36 } 37 38 $paths = $this->getAffectedPaths(); 39 40 $path_ids = 41 PhabricatorRepositoryCommitChangeParserWorker::lookupOrCreatePaths( 42 $paths); 43 44 $table = new DifferentialAffectedPath(); 45 $conn = $table->establishConnection('w'); 46 47 $sql = array(); 48 foreach ($path_ids as $path_id) { 49 $sql[] = qsprintf( 50 $conn, 51 '(%nd, %d, %d)', 52 $repository_id, 53 $path_id, 54 $revision->getID()); 55 } 56 57 queryfx( 58 $conn, 59 'DELETE FROM %R WHERE revisionID = %d', 60 $table, 61 $revision->getID()); 62 if ($sql) { 63 foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) { 64 queryfx( 65 $conn, 66 'INSERT INTO %R (repositoryID, pathID, revisionID) VALUES %LQ', 67 $table, 68 $chunk); 69 } 70 } 71 } 72 73 public function destroyAffectedPaths() { 74 $revision = $this->getRevision(); 75 76 $table = new DifferentialAffectedPath(); 77 $conn = $table->establishConnection('w'); 78 79 queryfx( 80 $conn, 81 'DELETE FROM %R WHERE revisionID = %d', 82 $table, 83 $revision->getID()); 84 } 85 86 public function getAffectedPaths() { 87 $revision = $this->getRevision(); 88 $diff = $this->getDiff(); 89 $repository = $revision->getRepository(); 90 91 $path_prefix = null; 92 if ($repository) { 93 $local_root = $diff->getSourceControlPath(); 94 if ($local_root) { 95 // We're in a working copy which supports subdirectory checkouts (e.g., 96 // SVN) so we need to figure out what prefix we should add to each path 97 // (e.g., trunk/projects/example/) to get the absolute path from the 98 // root of the repository. DVCS systems like Git and Mercurial are not 99 // affected. 100 101 // Normalize both paths and check if the repository root is a prefix of 102 // the local root. If so, throw it away. Note that this correctly 103 // handles the case where the remote path is "/". 104 $local_root = id(new PhutilURI($local_root))->getPath(); 105 $local_root = rtrim($local_root, '/'); 106 107 $repo_root = id(new PhutilURI($repository->getRemoteURI()))->getPath(); 108 $repo_root = rtrim($repo_root, '/'); 109 110 if (!strncmp($repo_root, $local_root, strlen($repo_root))) { 111 $path_prefix = substr($local_root, strlen($repo_root)); 112 } 113 } 114 } 115 116 $changesets = $diff->getChangesets(); 117 118 $paths = array(); 119 foreach ($changesets as $changeset) { 120 $paths[] = $path_prefix.'/'.$changeset->getFilename(); 121 } 122 123 // Mark this as also touching all parent paths, so you can see all pending 124 // changes to any file within a directory. 125 $all_paths = array(); 126 foreach ($paths as $local) { 127 foreach (DiffusionPathIDQuery::expandPathToRoot($local) as $path) { 128 $all_paths[$path] = true; 129 } 130 } 131 $all_paths = array_keys($all_paths); 132 133 return $all_paths; 134 } 135 136}