Page MenuHomePhabricator

D20892.id.diff
No OneTemporary

D20892.id.diff

diff --git a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
--- a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
+++ b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
@@ -353,13 +353,56 @@
// Load the refs we're planning to fetch from the remote repository.
$remote_refs = $this->loadGitRemoteRefs(
$repository,
- $repository->getRemoteURIEnvelope());
+ $repository->getRemoteURIEnvelope(),
+ $is_local = false);
// Load the refs we're planning to fetch from the local repository, by
// using the local working copy path as the "remote" repository URI.
$local_refs = $this->loadGitRemoteRefs(
$repository,
- new PhutilOpaqueEnvelope($path));
+ new PhutilOpaqueEnvelope($path),
+ $is_local = true);
+
+ // See T13448. The "git fetch --prune ..." flag only prunes local refs
+ // matching the refspecs we pass it. If "Fetch Refs" is configured, we'll
+ // pass it a very narrow list of refspecs, and it won't prune older refs
+ // that aren't currently subject to fetching.
+
+ // Since we want to prune everything that isn't (a) on the fetch list and
+ // (b) in the remote, handle pruning of any surplus leftover refs ourselves
+ // before we fetch anything.
+
+ // (We don't have to do this if "Fetch Refs" isn't set up, since "--prune"
+ // will work in that case, but it's a little simpler to always go down the
+ // same code path.)
+
+ $surplus_refs = array();
+ foreach ($local_refs as $local_ref => $local_hash) {
+ $remote_hash = idx($remote_refs, $local_ref);
+ if ($remote_hash === null) {
+ $surplus_refs[] = $local_ref;
+ }
+ }
+
+ if ($surplus_refs) {
+ $this->log(
+ pht(
+ 'Found %s surplus local ref(s) to delete.',
+ phutil_count($surplus_refs)));
+ foreach ($surplus_refs as $surplus_ref) {
+ $this->log(
+ pht(
+ 'Deleting surplus local ref "%s" ("%s").',
+ $surplus_ref,
+ $local_refs[$surplus_ref]));
+
+ $repository->execLocalCommand(
+ 'update-ref -d %R --',
+ $surplus_ref);
+
+ unset($local_refs[$surplus_ref]);
+ }
+ }
if ($remote_refs === $local_refs) {
$this->log(
@@ -378,7 +421,7 @@
// checked out. See T13280.
$future = $repository->getRemoteCommandFuture(
- 'fetch --prune --update-head-ok -- %P %Ls',
+ 'fetch --update-head-ok -- %P %Ls',
$repository->getRemoteURIEnvelope(),
$fetch_rules);
@@ -474,21 +517,32 @@
private function loadGitRemoteRefs(
PhabricatorRepository $repository,
- PhutilOpaqueEnvelope $remote_envelope) {
+ PhutilOpaqueEnvelope $remote_envelope,
+ $is_local) {
- $ref_rules = $this->getGitRefRules($repository);
+ // See T13448. When listing local remotes, we want to list everything,
+ // not just refs we expect to fetch. This allows us to detect that we have
+ // undesirable refs (which have been deleted in the remote, but are still
+ // present locally) so we can update our state to reflect the correct
+ // remote state.
- // NOTE: "git ls-remote" does not support "--" until circa January 2016.
- // See T12416. None of the flags to "ls-remote" appear dangerous, but
- // refuse to list any refs beginning with "-" just in case.
+ if ($is_local) {
+ $ref_rules = array();
+ } else {
+ $ref_rules = $this->getGitRefRules($repository);
- foreach ($ref_rules as $ref_rule) {
- if (preg_match('/^-/', $ref_rule)) {
- throw new Exception(
- pht(
- 'Refusing to list potentially dangerous ref ("%s") beginning '.
- 'with "-".',
- $ref_rule));
+ // NOTE: "git ls-remote" does not support "--" until circa January 2016.
+ // See T12416. None of the flags to "ls-remote" appear dangerous, but
+ // refuse to list any refs beginning with "-" just in case.
+
+ foreach ($ref_rules as $ref_rule) {
+ if (preg_match('/^-/', $ref_rule)) {
+ throw new Exception(
+ pht(
+ 'Refusing to list potentially dangerous ref ("%s") beginning '.
+ 'with "-".',
+ $ref_rule));
+ }
}
}

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 21, 2:08 PM (2 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7589009
Default Alt Text
D20892.id.diff (4 KB)

Event Timeline