* [JGIT PATCH 0/6] Add prune of stale tracking branches to fetch @ 2009-02-12 23:54 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-13 0:37 ` [JGIT PATCH 0/6] Add prune of stale tracking branches to fetch Junio C Hamano 0 siblings, 2 replies; 10+ messages in thread From: Shawn O. Pearce @ 2009-02-12 23:54 UTC (permalink / raw) To: Robin Rosenberg; +Cc: git This series teaches "jgit fetch" how to prune stale tracking branches that have been removed from the remote repository. We can now do both a fetch and a prune in a single network connection. I wanted to also add this for push, but its going to be more complex. The RefSpec data I need isn't available in the PushProcess code path, and the Transport.push() method isn't doing me any favors at making it available to me. I need to move on to some other things today, so I'm posting this fetch series now as this looks good as-is. Shawn O. Pearce (6): Fix RefUpdate.delete to update the result status Add setBoolean, setInt to RepositoryConfig Add RefSpec.expandFromDestination for reverse mappings Add the remote.name.mirror flag to RemoteConfig Don't pass TagOpt to FetchProcess, get it from the Transport Teach fetch to prune stale tracking branches .../org/spearce/jgit/pgm/AbstractFetchCommand.java | 8 ++- .../src/org/spearce/jgit/pgm/Fetch.java | 9 +++ .../spearce/jgit/transport/RefSpecTestCase.java | 22 ++++++ .../src/org/spearce/jgit/lib/RefUpdate.java | 4 +- .../src/org/spearce/jgit/lib/RepositoryConfig.java | 57 +++++++++++++++ .../org/spearce/jgit/transport/FetchProcess.java | 55 +++++++++++++-- .../src/org/spearce/jgit/transport/RefSpec.java | 73 ++++++++++++++------ .../org/spearce/jgit/transport/RemoteConfig.java | 40 +++++++++++- .../src/org/spearce/jgit/transport/Transport.java | 29 ++++++++- 9 files changed, 265 insertions(+), 32 deletions(-) ^ permalink raw reply [flat|nested] 10+ messages in thread
* [JGIT PATCH 1/6] Fix RefUpdate.delete to update the result status 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 ` Shawn O. Pearce 2009-02-12 23:54 ` [JGIT PATCH 2/6] Add setBoolean, setInt to RepositoryConfig Shawn O. Pearce 2009-02-13 0:37 ` [JGIT PATCH 0/6] Add prune of stale tracking branches to fetch Junio C Hamano 1 sibling, 1 reply; 10+ messages in thread From: Shawn O. Pearce @ 2009-02-12 23:54 UTC (permalink / raw) To: Robin Rosenberg; +Cc: git Some applications may want to use getResult() to obtain the status of the delete operation, as perhaps they lost access to the return value. This makes delete() more consistent in use with update(). Signed-off-by: Shawn O. Pearce <spearce@spearce.org> --- .../src/org/spearce/jgit/lib/RefUpdate.java | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java index 7ad2bab..d1820da 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java @@ -401,11 +401,11 @@ public Result delete(final RevWalk walk) throws IOException { if (getName().startsWith(Constants.R_HEADS)) { final Ref head = db.readRef(Constants.HEAD); if (head != null && getName().equals(head.getName())) - return Result.REJECTED_CURRENT_BRANCH; + return result = Result.REJECTED_CURRENT_BRANCH; } try { - return updateImpl(walk, new DeleteStore()); + return result = updateImpl(walk, new DeleteStore()); } catch (IOException x) { result = Result.IO_FAILURE; throw x; -- 1.6.2.rc0.226.gf08f ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [JGIT PATCH 2/6] Add setBoolean, setInt to RepositoryConfig 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 ` Shawn O. Pearce 2009-02-12 23:54 ` [JGIT PATCH 3/6] Add RefSpec.expandFromDestination for reverse mappings Shawn O. Pearce 0 siblings, 1 reply; 10+ messages in thread From: Shawn O. Pearce @ 2009-02-12 23:54 UTC (permalink / raw) To: Robin Rosenberg; +Cc: git This makes it easier for application level code to make edits to the configuration file, especially when setting boolean or integers into any property. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> --- .../src/org/spearce/jgit/lib/RepositoryConfig.java | 57 ++++++++++++++++++++ 1 files changed, 57 insertions(+), 0 deletions(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java index 821d8be..87535d1 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java @@ -439,6 +439,63 @@ private Object getRawEntry(final String section, final String subsection, /** * Add or modify a configuration value. The parameters will result in a * configuration entry like this. + * + * <pre> + * [section "subsection"] + * name = value + * </pre> + * + * @param section + * section name, e.g "branch" + * @param subsection + * optional subsection value, e.g. a branch name + * @param name + * parameter name, e.g. "filemode" + * @param value + * parameter value + */ + public void setInt(final String section, final String subsection, + final String name, final int value) { + final String s; + + if ((value % (1024 * 1024 * 1024)) == 0) + s = String.valueOf(value / (1024 * 1024 * 1024)) + " g"; + else if ((value % (1024 * 1024)) == 0) + s = String.valueOf(value / (1024 * 1024)) + " m"; + else if ((value % 1024) == 0) + s = String.valueOf(value / 1024) + " k"; + else + s = String.valueOf(value); + + setString(section, subsection, name, s); + } + + /** + * Add or modify a configuration value. The parameters will result in a + * configuration entry like this. + * + * <pre> + * [section "subsection"] + * name = value + * </pre> + * + * @param section + * section name, e.g "branch" + * @param subsection + * optional subsection value, e.g. a branch name + * @param name + * parameter name, e.g. "filemode" + * @param value + * parameter value + */ + public void setBoolean(final String section, final String subsection, + final String name, final boolean value) { + setString(section, subsection, name, value ? "true" : "false"); + } + + /** + * Add or modify a configuration value. The parameters will result in a + * configuration entry like this. * * <pre> * [section "subsection"] -- 1.6.2.rc0.226.gf08f ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [JGIT PATCH 3/6] Add RefSpec.expandFromDestination for reverse mappings 2009-02-12 23:54 ` [JGIT PATCH 2/6] Add setBoolean, setInt to RepositoryConfig Shawn O. Pearce @ 2009-02-12 23:54 ` Shawn O. Pearce 2009-02-12 23:54 ` [JGIT PATCH 4/6] Add the remote.name.mirror flag to RemoteConfig Shawn O. Pearce 0 siblings, 1 reply; 10+ messages in thread From: Shawn O. Pearce @ 2009-02-12 23:54 UTC (permalink / raw) To: Robin Rosenberg; +Cc: git This makes it easy to loop through the destination's refs and see if any match up to a source name which doesn't actually exist in the set of available source refs. In such cases, we may want to delete the destination ref. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> --- .../spearce/jgit/transport/RefSpecTestCase.java | 22 ++++++ .../src/org/spearce/jgit/transport/RefSpec.java | 73 ++++++++++++++------ 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/transport/RefSpecTestCase.java b/org.spearce.jgit.test/tst/org/spearce/jgit/transport/RefSpecTestCase.java index 341b4a4..11e7cdb 100644 --- a/org.spearce.jgit.test/tst/org/spearce/jgit/transport/RefSpecTestCase.java +++ b/org.spearce.jgit.test/tst/org/spearce/jgit/transport/RefSpecTestCase.java @@ -232,4 +232,26 @@ public void testSetSourceDestination() { assertEquals("HEAD", a.toString()); assertEquals("refs/heads/*:refs/remotes/origin/*", b.toString()); } + + public void testExpandFromDestination_NonWildcard() { + final String src = "refs/heads/master"; + final String dst = "refs/remotes/origin/master"; + final RefSpec a = new RefSpec(src + ":" + dst); + final RefSpec r = a.expandFromDestination(dst); + assertSame(a, r); + assertFalse(r.isWildcard()); + assertEquals(src, r.getSource()); + assertEquals(dst, r.getDestination()); + } + + public void testExpandFromDestination_Wildcard() { + final String src = "refs/heads/master"; + final String dst = "refs/remotes/origin/master"; + final RefSpec a = new RefSpec("refs/heads/*:refs/remotes/origin/*"); + final RefSpec r = a.expandFromDestination(dst); + assertNotSame(a, r); + assertFalse(r.isWildcard()); + assertEquals(src, r.getSource()); + assertEquals(dst, r.getDestination()); + } } diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/RefSpec.java b/org.spearce.jgit/src/org/spearce/jgit/transport/RefSpec.java index 521110b..bc6ea3a 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/RefSpec.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/RefSpec.java @@ -135,24 +135,6 @@ else if (isWildcard(srcName) || isWildcard(dstName)) } } - /** - * Expand a wildcard specification. - * - * @param p - * the wildcard specification we should base ourselves on. - * @param name - * actual name that matched the source of <code>p</code>. - */ - protected RefSpec(final RefSpec p, final String name) { - final String pdst = p.getDestination(); - if (p.getSource() == null || pdst == null) - throw new IllegalArgumentException("Cannot expand from " + p); - force = p.isForceUpdate(); - srcName = name; - dstName = pdst.substring(0, pdst.length() - 1) - + name.substring(p.getSource().length() - 1); - } - private RefSpec(final RefSpec p) { force = p.isForceUpdate(); wildcard = p.isWildcard(); @@ -349,7 +331,16 @@ public boolean matchDestination(final Ref r) { * wildcard. */ public RefSpec expandFromSource(final String r) { - return isWildcard() ? new RefSpec(this, r) : this; + return isWildcard() ? new RefSpec(this).expandFromSourceImp(r) : this; + } + + private RefSpec expandFromSourceImp(final String name) { + final String psrc = srcName, pdst = dstName; + wildcard = false; + srcName = name; + dstName = pdst.substring(0, pdst.length() - 1) + + name.substring(psrc.length() - 1); + return this; } /** @@ -366,7 +357,49 @@ public RefSpec expandFromSource(final String r) { * wildcard. */ public RefSpec expandFromSource(final Ref r) { - return isWildcard() ? new RefSpec(this, r.getName()) : this; + return expandFromSource(r.getName()); + } + + /** + * Expand this specification to exactly match a ref name. + * <p> + * Callers must first verify the passed ref name matches this specification, + * otherwise expansion results may be unpredictable. + * + * @param r + * a ref name that matched our destination specification. Could + * be a wildcard also. + * @return a new specification expanded from provided ref name. Result + * specification is wildcard if and only if provided ref name is + * wildcard. + */ + public RefSpec expandFromDestination(final String r) { + return isWildcard() ? new RefSpec(this).expandFromDstImp(r) : this; + } + + private RefSpec expandFromDstImp(final String name) { + final String psrc = srcName, pdst = dstName; + wildcard = false; + srcName = psrc.substring(0, psrc.length() - 1) + + name.substring(pdst.length() - 1); + dstName = name; + return this; + } + + /** + * Expand this specification to exactly match a ref. + * <p> + * Callers must first verify the passed ref matches this specification, + * otherwise expansion results may be unpredictable. + * + * @param r + * a ref that matched our destination specification. + * @return a new specification expanded from provided ref name. Result + * specification is wildcard if and only if provided ref name is + * wildcard. + */ + public RefSpec expandFromDestination(final Ref r) { + return expandFromDestination(r.getName()); } private boolean match(final String refName, final String s) { -- 1.6.2.rc0.226.gf08f ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [JGIT PATCH 4/6] Add the remote.name.mirror flag to RemoteConfig 2009-02-12 23:54 ` [JGIT PATCH 3/6] Add RefSpec.expandFromDestination for reverse mappings Shawn O. Pearce @ 2009-02-12 23:54 ` 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 0 siblings, 1 reply; 10+ messages in thread From: Shawn O. Pearce @ 2009-02-12 23:54 UTC (permalink / raw) To: Robin Rosenberg; +Cc: git This flag is currently only honored by "git push" to delete remote refs if they are also gone on the source side. It also causes the default push spec to be "+refs/*:refs/*" if the user hasn't given us any other push specs. This change only implements the config file parsing for the mirror flag, as there's still a chunk of code needed on the transport to actually honor it. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> --- .../org/spearce/jgit/transport/RemoteConfig.java | 40 +++++++++++++++++++- 1 files changed, 39 insertions(+), 1 deletions(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java b/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java index 5bbf664..519a8a5 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java @@ -68,6 +68,10 @@ private static final String KEY_TAGOPT = "tagopt"; + private static final String KEY_MIRROR = "mirror"; + + private static final boolean DEFAULT_MIRROR = false; + /** Default value for {@link #getUploadPack()} if not specified. */ public static final String DEFAULT_UPLOAD_PACK = "git-upload-pack"; @@ -114,6 +118,8 @@ private TagOpt tagopt; + private boolean mirror; + /** * Parse a remote block from an existing configuration file. * <p> @@ -163,6 +169,7 @@ public RemoteConfig(final RepositoryConfig rc, final String remoteName) val = rc.getString(SECTION, name, KEY_TAGOPT); tagopt = TagOpt.fromOption(val); + mirror = rc.getBoolean(SECTION, name, KEY_MIRROR, DEFAULT_MIRROR); } /** @@ -192,16 +199,29 @@ public void update(final RepositoryConfig rc) { set(rc, KEY_UPLOADPACK, getUploadPack(), DEFAULT_UPLOAD_PACK); set(rc, KEY_RECEIVEPACK, getReceivePack(), DEFAULT_RECEIVE_PACK); set(rc, KEY_TAGOPT, getTagOpt().option(), TagOpt.AUTO_FOLLOW.option()); + set(rc, KEY_MIRROR, mirror, DEFAULT_MIRROR); } private void set(final RepositoryConfig rc, final String key, final String currentValue, final String defaultValue) { if (defaultValue.equals(currentValue)) - rc.unsetString(SECTION, getName(), key); + unset(rc, key); else rc.setString(SECTION, getName(), key, currentValue); } + private void set(final RepositoryConfig rc, final String key, + final boolean currentValue, final boolean defaultValue) { + if (defaultValue == currentValue) + unset(rc, key); + else + rc.setBoolean(SECTION, getName(), key, currentValue); + } + + private void unset(final RepositoryConfig rc, final String key) { + rc.unsetString(SECTION, getName(), key); + } + /** * Get the local name this remote configuration is recognized as. * @@ -382,4 +402,22 @@ public TagOpt getTagOpt() { public void setTagOpt(final TagOpt option) { tagopt = option != null ? option : TagOpt.AUTO_FOLLOW; } + + /** + * @return true if pushing to the remote automatically deletes remote refs + * which don't exist on the source side. + */ + public boolean isMirror() { + return mirror; + } + + /** + * Set the mirror flag to automatically delete remote refs. + * + * @param m + * true to automatically delete remote refs during push. + */ + public void setMirror(final boolean m) { + mirror = m; + } } -- 1.6.2.rc0.226.gf08f ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [JGIT PATCH 5/6] Don't pass TagOpt to FetchProcess, get it from the Transport 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 ` Shawn O. Pearce 2009-02-12 23:54 ` [JGIT PATCH 6/6] Teach fetch to prune stale tracking branches Shawn O. Pearce 0 siblings, 1 reply; 10+ messages in thread From: Shawn O. Pearce @ 2009-02-12 23:54 UTC (permalink / raw) To: Robin Rosenberg; +Cc: git We are already passing the transport down. Its just easier to get the tagopt off the transport than it is to pass it as an argument to the constructor. In the future as we add more options into the Transport we will also need to obtain those in the FetchProcess, so directly querying the Transport will be more consistent. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> --- .../org/spearce/jgit/transport/FetchProcess.java | 7 ++----- .../src/org/spearce/jgit/transport/Transport.java | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) 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 09718eb..2ca8aeb 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java @@ -69,9 +69,6 @@ /** List of things we want to fetch from the remote repository. */ private final Collection<RefSpec> toFetch; - /** How to handle annotated tags, if any are advertised. */ - private final TagOpt tagopt; - /** Set of refs we will actually wind up asking to obtain. */ private final HashMap<ObjectId, Ref> askFor = new HashMap<ObjectId, Ref>(); @@ -86,10 +83,9 @@ private FetchConnection conn; - FetchProcess(final Transport t, final Collection<RefSpec> f, final TagOpt o) { + FetchProcess(final Transport t, final Collection<RefSpec> f) { transport = t; toFetch = f; - tagopt = o; } void execute(final ProgressMonitor monitor, final FetchResult result) @@ -114,6 +110,7 @@ void execute(final ProgressMonitor monitor, final FetchResult result) } Collection<Ref> additionalTags = Collections.<Ref> emptyList(); + final TagOpt tagopt = transport.getTagOpt(); if (tagopt == TagOpt.AUTO_FOLLOW) additionalTags = expandAutoFollowTags(); else if (tagopt == TagOpt.FETCH_TAGS) 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 28700b7..e58b72a 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/Transport.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/Transport.java @@ -606,7 +606,7 @@ public FetchResult fetch(final ProgressMonitor monitor, } final FetchResult result = new FetchResult(); - new FetchProcess(this, toFetch, tagopt).execute(monitor, result); + new FetchProcess(this, toFetch).execute(monitor, result); return result; } -- 1.6.2.rc0.226.gf08f ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [JGIT PATCH 6/6] Teach fetch to prune stale tracking branches 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 0 siblings, 0 replies; 10+ messages in thread From: Shawn O. Pearce @ 2009-02-12 23:54 UTC (permalink / raw) To: Robin Rosenberg; +Cc: git 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 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [JGIT PATCH 0/6] Add prune of stale tracking branches to fetch 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-13 0:37 ` Junio C Hamano 2009-02-13 0:42 ` Shawn O. Pearce 1 sibling, 1 reply; 10+ messages in thread From: Junio C Hamano @ 2009-02-13 0:37 UTC (permalink / raw) To: Shawn O. Pearce; +Cc: Robin Rosenberg, git "Shawn O. Pearce" <spearce@spearce.org> writes: > This series teaches "jgit fetch" how to prune stale tracking branches > that have been removed from the remote repository. We can now do > both a fetch and a prune in a single network connection. I am not sure if that is a good feature. The user at the local side may well be using the (now stale) tracking branch as an achoring point to remember where his own development forked from, and that may be the reason he is fetching but not running "remote prune", not to lose that anchor. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [JGIT PATCH 0/6] Add prune of stale tracking branches to fetch 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 0 siblings, 1 reply; 10+ messages in thread From: Shawn O. Pearce @ 2009-02-13 0:42 UTC (permalink / raw) To: Junio C Hamano; +Cc: Robin Rosenberg, git Junio C Hamano <gitster@pobox.com> wrote: > "Shawn O. Pearce" <spearce@spearce.org> writes: > > > This series teaches "jgit fetch" how to prune stale tracking branches > > that have been removed from the remote repository. We can now do > > both a fetch and a prune in a single network connection. > > I am not sure if that is a good feature. > > The user at the local side may well be using the (now stale) tracking > branch as an achoring point to remember where his own development forked > from, and that may be the reason he is fetching but not running "remote > prune", not to lose that anchor. Well. Its off by default. You have to ask for it with "jgit fetch --prune origin". Compare to asking for it with "git remote prune origin". We're already opening a #@!*@!* network connection to perform either fetch or prune, so we might as well let the user perform both in one step. Which is what this patch does. -- Shawn. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [JGIT PATCH 0/6] Add prune of stale tracking branches to fetch 2009-02-13 0:42 ` Shawn O. Pearce @ 2009-02-13 0:48 ` Junio C Hamano 0 siblings, 0 replies; 10+ messages in thread From: Junio C Hamano @ 2009-02-13 0:48 UTC (permalink / raw) To: Shawn O. Pearce; +Cc: Robin Rosenberg, git "Shawn O. Pearce" <spearce@spearce.org> writes: > Junio C Hamano <gitster@pobox.com> wrote: >> "Shawn O. Pearce" <spearce@spearce.org> writes: >> >> > This series teaches "jgit fetch" how to prune stale tracking branches >> > that have been removed from the remote repository. We can now do >> > both a fetch and a prune in a single network connection. >> >> I am not sure if that is a good feature. >> >> The user at the local side may well be using the (now stale) tracking >> branch as an achoring point to remember where his own development forked >> from, and that may be the reason he is fetching but not running "remote >> prune", not to lose that anchor. > > Well. > > Its off by default. > > You have to ask for it with "jgit fetch --prune origin". Ok, then. Sorry for the noise. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-02-13 0:49 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 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 ` [JGIT PATCH 6/6] Teach fetch to prune stale tracking branches Shawn O. Pearce 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
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).