* [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).