From: "Shawn O. Pearce" <spearce@spearce.org>
To: Robin Rosenberg <robin.rosenberg@dewire.com>
Cc: git@vger.kernel.org
Subject: [JGIT PATCH 6/6] Teach fetch to prune stale tracking branches
Date: Thu, 12 Feb 2009 15:54:40 -0800 [thread overview]
Message-ID: <1234482880-1316-7-git-send-email-spearce@spearce.org> (raw)
In-Reply-To: <1234482880-1316-6-git-send-email-spearce@spearce.org>
If the source branch for a local tracking branch has been removed
from the remote repository, users may also want (or need) to delete
it from the local repository. A good example is when a branch named
"refs/heads/bar" switches from a file to a directory, and the local
path name in "refs/remotes/origin/bar" must also change.
Local deletes are done before updates, to handle this special case
of file to directory (or directory to file) conversions with as few
errors as possible.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../org/spearce/jgit/pgm/AbstractFetchCommand.java | 8 ++-
.../src/org/spearce/jgit/pgm/Fetch.java | 9 ++++
.../org/spearce/jgit/transport/FetchProcess.java | 48 ++++++++++++++++++++
.../src/org/spearce/jgit/transport/Transport.java | 27 +++++++++++
4 files changed, 89 insertions(+), 3 deletions(-)
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/AbstractFetchCommand.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/AbstractFetchCommand.java
index ea6f277..f5a9d65 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/AbstractFetchCommand.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/AbstractFetchCommand.java
@@ -39,6 +39,7 @@
import org.kohsuke.args4j.Option;
import org.spearce.jgit.lib.Constants;
+import org.spearce.jgit.lib.ObjectId;
import org.spearce.jgit.lib.RefUpdate;
import org.spearce.jgit.transport.FetchResult;
import org.spearce.jgit.transport.TrackingRefUpdate;
@@ -75,9 +76,12 @@ private String longTypeOf(final TrackingRefUpdate u) {
final RefUpdate.Result r = u.getResult();
if (r == RefUpdate.Result.LOCK_FAILURE)
return "[lock fail]";
-
if (r == RefUpdate.Result.IO_FAILURE)
return "[i/o error]";
+ if (r == RefUpdate.Result.REJECTED)
+ return "[rejected]";
+ if (ObjectId.zeroId().equals(u.getNewObjectId()))
+ return "[deleted]";
if (r == RefUpdate.Result.NEW) {
if (u.getRemoteName().startsWith(Constants.R_HEADS))
@@ -99,8 +103,6 @@ else if (u.getLocalName().startsWith(Constants.R_TAGS))
return aOld + ".." + aNew;
}
- if (r == RefUpdate.Result.REJECTED)
- return "[rejected]";
if (r == RefUpdate.Result.NO_CHANGE)
return "[up to date]";
return "[" + r.name() + "]";
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java
index 8f3f7d5..81d6893 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java
@@ -56,6 +56,12 @@ void nofsck(final boolean ignored) {
fsck = Boolean.FALSE;
}
+ @Option(name = "--prune", usage = "prune stale tracking refs")
+ private Boolean prune;
+
+ @Option(name = "--dry-run")
+ private boolean dryRun;
+
@Option(name = "--thin", usage = "fetch thin pack")
private Boolean thin;
@@ -75,6 +81,9 @@ protected void run() throws Exception {
final Transport tn = Transport.open(db, remote);
if (fsck != null)
tn.setCheckFetchedObjects(fsck.booleanValue());
+ if (prune != null)
+ tn.setRemoveDeletedRefs(prune.booleanValue());
+ tn.setDryRun(dryRun);
if (thin != null)
tn.setFetchThin(thin.booleanValue());
final FetchResult r;
diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java
index 2ca8aeb..df64817 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java
@@ -59,6 +59,7 @@
import org.spearce.jgit.lib.ObjectId;
import org.spearce.jgit.lib.ProgressMonitor;
import org.spearce.jgit.lib.Ref;
+import org.spearce.jgit.lib.Repository;
import org.spearce.jgit.revwalk.ObjectWalk;
import org.spearce.jgit.revwalk.RevWalk;
@@ -152,6 +153,8 @@ else if (tagopt == TagOpt.FETCH_TAGS)
}
final RevWalk walk = new RevWalk(transport.local);
+ if (transport.isRemoveDeletedRefs())
+ deleteStaleTrackingRefs(result, walk);
for (TrackingRefUpdate u : localUpdates) {
try {
u.update(walk);
@@ -366,6 +369,51 @@ private TrackingRefUpdate createUpdate(final RefSpec spec,
return new TrackingRefUpdate(transport.local, spec, newId, "fetch");
}
+ private void deleteStaleTrackingRefs(final FetchResult result,
+ final RevWalk walk) throws TransportException {
+ final Repository db = transport.local;
+ for (final Ref ref : db.getAllRefs().values()) {
+ final String refname = ref.getName();
+ for (final RefSpec spec : toFetch) {
+ if (spec.matchDestination(refname)) {
+ final RefSpec s = spec.expandFromDestination(refname);
+ if (result.getAdvertisedRef(s.getSource()) == null) {
+ deleteTrackingRef(result, db, walk, s, ref);
+ }
+ }
+ }
+ }
+ }
+
+ private void deleteTrackingRef(final FetchResult result,
+ final Repository db, final RevWalk walk, final RefSpec spec,
+ final Ref localRef) throws TransportException {
+ final String name = localRef.getName();
+ try {
+ final TrackingRefUpdate u = new TrackingRefUpdate(db, name, spec
+ .getSource(), true, ObjectId.zeroId(), "deleted");
+ result.add(u);
+ if (transport.isDryRun()){
+ return;
+ }
+ u.delete(walk);
+ switch (u.getResult()) {
+ case NEW:
+ case NO_CHANGE:
+ case FAST_FORWARD:
+ case FORCED:
+ break;
+ default:
+ throw new TransportException(transport.getURI(),
+ "Cannot delete stale tracking ref " + name + ": "
+ + u.getResult().name());
+ }
+ } catch (IOException e) {
+ throw new TransportException(transport.getURI(),
+ "Cannot delete stale tracking ref " + name, e);
+ }
+ }
+
private static boolean isTag(final Ref r) {
return isTag(r.getName());
}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/Transport.java b/org.spearce.jgit/src/org/spearce/jgit/transport/Transport.java
index e58b72a..3aec5ca 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/transport/Transport.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/Transport.java
@@ -355,6 +355,9 @@ private static String findTrackingRefName(final String remoteName,
/** Should an incoming (fetch) transfer validate objects? */
private boolean checkFetchedObjects;
+ /** Should refs no longer on the source be pruned from the destination? */
+ private boolean removeDeletedRefs;
+
/**
* Create a new transport instance.
*
@@ -516,6 +519,30 @@ public void setPushThin(final boolean pushThin) {
}
/**
+ * @return true if destination refs should be removed if they no longer
+ * exist at the source repository.
+ */
+ public boolean isRemoveDeletedRefs() {
+ return removeDeletedRefs;
+ }
+
+ /**
+ * Set whether or not to remove refs which no longer exist in the source.
+ * <p>
+ * If true, refs at the destination repository (local for fetch, remote for
+ * push) are deleted if they no longer exist on the source side (remote for
+ * fetch, local for push).
+ * <p>
+ * False by default, as this may cause data to become unreachable, and
+ * eventually be deleted on the next GC.
+ *
+ * @param remove true to remove refs that no longer exist.
+ */
+ public void setRemoveDeletedRefs(final boolean remove) {
+ removeDeletedRefs = remove;
+ }
+
+ /**
* Apply provided remote configuration on this transport.
*
* @param cfg
--
1.6.2.rc0.226.gf08f
next prev parent reply other threads:[~2009-02-12 23:56 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-12 23:54 [JGIT PATCH 0/6] Add prune of stale tracking branches to fetch Shawn O. Pearce
2009-02-12 23:54 ` [JGIT PATCH 1/6] Fix RefUpdate.delete to update the result status Shawn O. Pearce
2009-02-12 23:54 ` [JGIT PATCH 2/6] Add setBoolean, setInt to RepositoryConfig Shawn O. Pearce
2009-02-12 23:54 ` [JGIT PATCH 3/6] Add RefSpec.expandFromDestination for reverse mappings Shawn O. Pearce
2009-02-12 23:54 ` [JGIT PATCH 4/6] Add the remote.name.mirror flag to RemoteConfig Shawn O. Pearce
2009-02-12 23:54 ` [JGIT PATCH 5/6] Don't pass TagOpt to FetchProcess, get it from the Transport Shawn O. Pearce
2009-02-12 23:54 ` Shawn O. Pearce [this message]
2009-02-13 0:37 ` [JGIT PATCH 0/6] Add prune of stale tracking branches to fetch Junio C Hamano
2009-02-13 0:42 ` Shawn O. Pearce
2009-02-13 0:48 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1234482880-1316-7-git-send-email-spearce@spearce.org \
--to=spearce@spearce.org \
--cc=git@vger.kernel.org \
--cc=robin.rosenberg@dewire.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).