Page MenuHomePhabricator

D7984.id.diff
No OneTemporary

D7984.id.diff

Index: src/applications/repository/engine/PhabricatorRepositoryRefEngine.php
===================================================================
--- src/applications/repository/engine/PhabricatorRepositoryRefEngine.php
+++ src/applications/repository/engine/PhabricatorRepositoryRefEngine.php
@@ -9,10 +9,13 @@
private $newRefs = array();
private $deadRefs = array();
+ private $closeCommits = array();
+ private $hasNoCursors;
public function updateRefs() {
$this->newRefs = array();
$this->deadRefs = array();
+ $this->closeCommits = array();
$repository = $this->getRepository();
@@ -50,9 +53,24 @@
->execute();
$cursor_groups = mgroup($all_cursors, 'getRefType');
+ $this->hasNoCursors = (!$all_cursors);
+
+ // Find all the heads of closing refs.
+ $all_closing_heads = array();
+ foreach ($all_cursors as $cursor) {
+ if ($this->shouldCloseRef($cursor->getRefType(), $cursor->getRefName())) {
+ $all_closing_heads[] = $cursor->getCommitIdentifier();
+ }
+ }
+ $all_closing_heads = array_unique($all_closing_heads);
+
foreach ($maps as $type => $refs) {
$cursor_group = idx($cursor_groups, $type, array());
- $this->updateCursors($cursor_group, $refs, $type);
+ $this->updateCursors($cursor_group, $refs, $type, $all_closing_heads);
+ }
+
+ if ($this->closeCommits) {
+ $this->setCloseFlagOnCommits($this->closeCommits);
}
if ($this->newRefs || $this->deadRefs) {
@@ -80,10 +98,18 @@
return $this;
}
+ private function markCloseCommits(array $identifiers) {
+ foreach ($identifiers as $identifier) {
+ $this->closeCommits[$identifier] = $identifier;
+ }
+ return $this;
+ }
+
private function updateCursors(
array $cursors,
array $new_refs,
- $ref_type) {
+ $ref_type,
+ array $all_closing_heads) {
$repository = $this->getRepository();
// NOTE: Mercurial branches may have multiple branch heads; this logic
@@ -149,8 +175,14 @@
->setCommitIdentifier($identifier));
}
- foreach ($added_commits as $identifier) {
- // TODO: Do autoclose stuff here.
+ if ($this->shouldCloseRef($ref_type, $name)) {
+ foreach ($added_commits as $identifier) {
+ $new_identifiers = $this->loadNewCommitIdentifiers(
+ $identifier,
+ $all_closing_heads);
+
+ $this->markCloseCommits($new_identifiers);
+ }
}
}
@@ -171,6 +203,133 @@
}
}
+ private function shouldCloseRef($ref_type, $ref_name) {
+ if ($ref_type !== PhabricatorRepositoryRefCursor::TYPE_BRANCH) {
+ return false;
+ }
+
+ if ($this->hasNoCursors) {
+ // If we don't have any cursors, don't close things. Particularly, this
+ // corresponds to the case where you've just updated to this code on an
+ // existing repository: we don't want to requeue message steps for every
+ // commit on a closeable ref.
+ return false;
+ }
+
+ return $this->getRepository()->shouldAutocloseBranch($ref_name);
+ }
+
+ /**
+ * Find all ancestors of a new closing branch head which are not ancestors
+ * of any old closing branch head.
+ */
+ private function loadNewCommitIdentifiers(
+ $new_head,
+ array $all_closing_heads) {
+
+ $repository = $this->getRepository();
+ $vcs = $repository->getVersionControlSystem();
+ switch ($vcs) {
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
+ if ($all_closing_heads) {
+ $escheads = array();
+ foreach ($all_closing_heads as $head) {
+ $escheads[] = hgsprintf('%s', $head);
+ }
+ $escheads = implode(' or ', $escheads);
+ list($stdout) = $this->getRepository()->execxLocalCommand(
+ 'log --template %s --rev %s',
+ '{node}\n',
+ hgsprintf('%s', $new_head).' - ('.$escheads.')');
+ } else {
+ list($stdout) = $this->getRepository()->execxLocalCommand(
+ 'log --template %s --rev %s',
+ '{node}\n',
+ hgsprintf('%s', $new_head));
+ }
+ return phutil_split_lines($stdout, $retain_newlines = false);
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
+ if ($all_closing_heads) {
+ list($stdout) = $this->getRepository()->execxLocalCommand(
+ 'log --format=%s %s --not %Ls',
+ '%H',
+ $new_head,
+ $all_closing_heads);
+ } else {
+ list($stdout) = $this->getRepository()->execxLocalCommand(
+ 'log --format=%s %s',
+ '%H',
+ $new_head);
+ }
+ return phutil_split_lines($stdout, $retain_newlines = false);
+ default:
+ throw new Exception(pht('Unsupported VCS "%s"!', $vcs));
+ }
+ }
+
+ /**
+ * Mark a list of commits as closeable, and queue workers for those commits
+ * which don't already have the flag.
+ */
+ private function setCloseFlagOnCommits(array $identifiers) {
+ $repository = $this->getRepository();
+ $commit_table = new PhabricatorRepositoryCommit();
+ $conn_w = $commit_table->establishConnection('w');
+
+ $vcs = $repository->getVersionControlSystem();
+ switch ($vcs) {
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
+ $class = 'PhabricatorRepositoryGitCommitMessageParserWorker';
+ break;
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
+ $class = 'PhabricatorRepositorySvnCommitMessageParserWorker';
+ break;
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
+ $class = 'PhabricatorRepositoryMercurialCommitMessageParserWorker';
+ break;
+ default:
+ throw new Exception("Unknown repository type '{$vcs}'!");
+ }
+
+ $all_commits = queryfx_all(
+ $conn_w,
+ 'SELECT id, commitIdentifier, importStatus FROM %T
+ WHERE commitIdentifier IN (%Ls)',
+ $commit_table->getTableName(),
+ $identifiers);
+
+ $closeable_flag = PhabricatorRepositoryCommit::IMPORTED_CLOSEABLE;
+
+ $all_commits = ipull($all_commits, null, 'commitIdentifier');
+ foreach ($identifiers as $identifier) {
+ $row = idx($all_commits, $identifier);
+
+ if (!$row) {
+ throw new Exception(
+ pht(
+ 'Commit "%s" has not been discovered yet! Run discovery before '.
+ 'updating refs.',
+ $identifier));
+ }
+
+ if (!($row['importStatus'] & $closeable_flag)) {
+ queryfx(
+ $conn_w,
+ 'UPDATE %T SET importStatus = (importStatus | %d) WHERE id = %d',
+ $commit_table->getTableName(),
+ $closeable_flag,
+ $row['id']);
+
+ $data = array(
+ 'commitID' => $row['id'],
+ 'only' => true,
+ );
+
+ PhabricatorWorker::scheduleTask($class, $data);
+ }
+ }
+ }
+
/* -( Updating Git Refs )-------------------------------------------------- */
Index: src/applications/repository/storage/PhabricatorRepository.php
===================================================================
--- src/applications/repository/storage/PhabricatorRepository.php
+++ src/applications/repository/storage/PhabricatorRepository.php
@@ -552,6 +552,11 @@
throw new Exception("Unrecognized version control system.");
}
+ $closeable_flag = PhabricatorRepositoryCommit::IMPORTED_CLOSEABLE;
+ if ($commit->isPartiallyImported($closeable_flag)) {
+ return true;
+ }
+
$branches = $data->getCommitDetail('seenOnBranches', array());
foreach ($branches as $branch) {
if ($this->shouldAutocloseBranch($branch)) {

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 17, 9:27 AM (6 d, 20 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7708195
Default Alt Text
D7984.id.diff (7 KB)

Event Timeline