{"thread":{"id":"15002","subject":"[PATCH 0/7] jgit: Branch command now supports deletion","startedAt":"2008-08-14T10:13:42Z","lastAt":"2008-08-15T00:25:57Z","messageCount":11,"participants":["Charles O'Farrell","Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"87175","messageId":"1218708829-8175-1-git-send-email-charleso@charleso.org","threadId":"15002","inReplyTo":null,"subject":"[PATCH 0/7] jgit: Branch command now supports deletion","fromName":"Charles O'Farrell","fromEmail":"charleso@charleso.org","sentAt":"2008-08-14T10:13:42Z","receivedAt":"2008-08-14T10:13:42Z","isPatch":true,"sender":{"key":"charleso@charleso.org","avatar":"https://gravatar.com/avatar/ce96d531daa37646a38a81e48113865af86a6d290ad92931f3b217896bdf86ea?d=mp&s=160"},"body":"Implement branch deletion for jgit, reusing previous packed-refs writing\n\nCharles O'Farrell (7):\n  Refactor of WalkRemoteObjectDatabase ref writing into common class\n  Refactor of RefUpdate force to call common updateImpl instead of\n    duplication\n  Minor refactor of constants, including log and ROOT_DIR\n  Extract lockAndWriteFile method in RefDatabase for reuse\n  Added removePackedRef method to RefDatabase for packed branch\n    deletion\n  Added ref deletion to RefUpdate\n  jgit: Added branch deletion to jgit command\n\n .../src/org/spearce/jgit/pgm/Branch.java           |   57 ++++++-\n .../src/org/spearce/jgit/lib/Constants.java        |    9 +\n .../src/org/spearce/jgit/lib/RefDatabase.java      |   41 ++++--\n .../src/org/spearce/jgit/lib/RefLogWriter.java     |    2 +-\n .../src/org/spearce/jgit/lib/RefUpdate.java        |  106 ++++++++----\n .../src/org/spearce/jgit/lib/RefWriter.java        |  175 ++++++++++++++++++++\n .../src/org/spearce/jgit/lib/Repository.java       |    2 +-\n .../spearce/jgit/transport/TransportAmazonS3.java  |   10 +-\n .../org/spearce/jgit/transport/TransportSftp.java  |    6 +-\n .../spearce/jgit/transport/WalkPushConnection.java |   18 ++-\n .../jgit/transport/WalkRemoteObjectDatabase.java   |  110 +-----------\n 11 files changed, 374 insertions(+), 162 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RefWriter.java\n"},{"id":"87177","messageId":"1218708829-8175-2-git-send-email-charleso@charleso.org","threadId":"15002","inReplyTo":"1218708829-8175-1-git-send-email-charleso@charleso.org","subject":"[PATCH 1/7] Refactor of WalkRemoteObjectDatabase ref writing into common class","fromName":"Charles O'Farrell","fromEmail":"charleso@charleso.org","sentAt":"2008-08-14T10:13:43Z","receivedAt":"2008-08-14T10:13:43Z","isPatch":true,"sender":{"key":"charleso@charleso.org","avatar":"https://gravatar.com/avatar/ce96d531daa37646a38a81e48113865af86a6d290ad92931f3b217896bdf86ea?d=mp&s=160"},"body":"In particular writeInfoRefs and writePackedRefs into common RefWriter\nclass for reuse with branch deletion in jgit.\n\nSigned-off-by: Charles O'Farrell <charleso@charleso.org>\n---\n .../src/org/spearce/jgit/lib/Constants.java        |    6 +\n .../src/org/spearce/jgit/lib/RefWriter.java        |  175 ++++++++++++++++++++\n .../spearce/jgit/transport/WalkPushConnection.java |   12 +-\n .../jgit/transport/WalkRemoteObjectDatabase.java   |   94 -----------\n 4 files changed, 191 insertions(+), 96 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RefWriter.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\nindex 7c2cef9..7bbd88e 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n@@ -214,6 +214,12 @@ public final class Constants {\n \t/** Prefix for tag refs */\n \tpublic static final String TAGS_PREFIX = \"refs/tags\";\n \n+\t/** Info refs folder */\n+\tpublic static final String INFO_REFS = \"info/refs\";\n+\n+\t/** Packed refs file */\n+\tpublic static final String PACKED_REFS = \"packed-refs\";\n+\n \t/**\n \t * Create a new digest function for objects.\n \t * \ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefWriter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefWriter.java\nnew file mode 100644\nindex 0000000..9c784d5\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefWriter.java\n@@ -0,0 +1,175 @@\n+/*\n+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\n+ * Copyright (C) 2008, Charles O'Farrell <charleso@charleso.org>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.lib;\n+\n+import java.io.IOException;\n+import java.io.StringWriter;\n+import java.util.Collection;\n+import java.util.Comparator;\n+import java.util.TreeSet;\n+\n+/**\n+ * Writes out refs to the {@link Constants#INFO_REFS} and\n+ * {@link Constants#PACKED_REFS} files.\n+ * \n+ * This class is abstract as the writing of the files must be handled by the\n+ * caller. This is because it is used by transport classes as well.\n+ */\n+public abstract class RefWriter {\n+\n+\tprivate final Collection<Ref> refs;\n+\n+\t/**\n+\t * @param refs\n+\t *            the complete set of references. This should have been computed\n+\t *            by applying updates to the advertised refs already discovered.\n+\t */\n+\tpublic RefWriter(Collection<Ref> refs) {\n+\t\tthis.refs = new TreeSet<Ref>(RefComparator.INSTANCE);\n+\t\tthis.refs.addAll(refs);\n+\t}\n+\n+\t/**\n+\t * Rebuild the {@link Constants#INFO_REFS}.\n+\t * <p>\n+\t * This method rebuilds the contents of the {@link Constants#INFO_REFS} file\n+\t * to match the passed list of references.\n+\t * \n+\t * \n+\t * @throws IOException\n+\t *             writing is not supported, or attempting to write the file\n+\t *             failed, possibly due to permissions or remote disk full, etc.\n+\t */\n+\tpublic void writeInfoRefs() throws IOException {\n+\t\tfinal StringWriter w = new StringWriter();\n+\t\tfinal char[] tmp = new char[Constants.OBJECT_ID_LENGTH * 2];\n+\t\tfor (final Ref r : refs) {\n+\t\t\tif (Constants.HEAD.equals(r.getName())) {\n+\t\t\t\t// Historically HEAD has never been published through\n+\t\t\t\t// the INFO_REFS file. This is a mistake, but its the\n+\t\t\t\t// way things are.\n+\t\t\t\t//\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tr.getObjectId().copyTo(tmp, w);\n+\t\t\tw.write('\\t');\n+\t\t\tw.write(r.getName());\n+\t\t\tw.write('\\n');\n+\n+\t\t\tif (r.getPeeledObjectId() != null) {\n+\t\t\t\tr.getPeeledObjectId().copyTo(tmp, w);\n+\t\t\t\tw.write('\\t');\n+\t\t\t\tw.write(r.getName());\n+\t\t\t\tw.write(\"^{}\\n\");\n+\t\t\t}\n+\t\t}\n+\t\twriteFile(Constants.INFO_REFS, Constants.encodeASCII(w.toString()));\n+\t}\n+\n+\t/**\n+\t * Rebuild the {@link Constants#PACKED_REFS} file.\n+\t * <p>\n+\t * This method rebuilds the contents of the {@link Constants#PACKED_REFS}\n+\t * file to match the passed list of references, including only those refs\n+\t * that have a storage type of {@link Ref.Storage#PACKED}.\n+\t * \n+\t * @throws IOException\n+\t *             writing is not supported, or attempting to write the file\n+\t *             failed, possibly due to permissions or remote disk full, etc.\n+\t */\n+\tpublic void writePackedRefs() throws IOException {\n+\t\tboolean peeled = false;\n+\n+\t\tfor (final Ref r : refs) {\n+\t\t\tif (r.getStorage() != Ref.Storage.PACKED)\n+\t\t\t\tcontinue;\n+\t\t\tif (r.getPeeledObjectId() != null)\n+\t\t\t\tpeeled = true;\n+\t\t}\n+\n+\t\tfinal StringWriter w = new StringWriter();\n+\t\tif (peeled) {\n+\t\t\tw.write(\"# pack-refs with:\");\n+\t\t\tif (peeled)\n+\t\t\t\tw.write(\" peeled\");\n+\t\t\tw.write('\\n');\n+\t\t}\n+\n+\t\tfinal char[] tmp = new char[Constants.OBJECT_ID_LENGTH * 2];\n+\t\tfor (final Ref r : refs) {\n+\t\t\tif (r.getStorage() != Ref.Storage.PACKED)\n+\t\t\t\tcontinue;\n+\n+\t\t\tr.getObjectId().copyTo(tmp, w);\n+\t\t\tw.write(' ');\n+\t\t\tw.write(r.getName());\n+\t\t\tw.write('\\n');\n+\n+\t\t\tif (r.getPeeledObjectId() != null) {\n+\t\t\t\tw.write('^');\n+\t\t\t\tr.getPeeledObjectId().copyTo(tmp, w);\n+\t\t\t\tw.write('\\n');\n+\t\t\t}\n+\t\t}\n+\t\twriteFile(Constants.PACKED_REFS, Constants.encodeASCII(w.toString()));\n+\t}\n+\n+\t/**\n+\t * Handles actual writing of ref files to the git repository, which may\n+\t * differ slightly depending on the destination and transport.\n+\t * \n+\t * @param file\n+\t *            path to ref file.\n+\t * @param content\n+\t *            byte content of file to be written.\n+\t * @throws IOException\n+\t */\n+\tprotected abstract void writeFile(String file, byte[] content)\n+\t\t\tthrows IOException;\n+\n+\tprivate static class RefComparator implements Comparator<Ref> {\n+\n+\t\tprivate static final RefComparator INSTANCE = new RefComparator();\n+\n+\t\tpublic int compare(Ref o1, Ref o2) {\n+\t\t\treturn o1.getName().compareTo(o2.getName());\n+\t\t}\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java\nindex 904a699..19071d7 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java\n@@ -53,6 +53,7 @@ import org.spearce.jgit.lib.ObjectId;\n import org.spearce.jgit.lib.PackWriter;\n import org.spearce.jgit.lib.ProgressMonitor;\n import org.spearce.jgit.lib.Ref;\n+import org.spearce.jgit.lib.RefWriter;\n import org.spearce.jgit.lib.Repository;\n import org.spearce.jgit.lib.Ref.Storage;\n import org.spearce.jgit.transport.RemoteRefUpdate.Status;\n@@ -158,9 +159,16 @@ class WalkPushConnection extends BaseConnection implements PushConnection {\n \t\tif (!updates.isEmpty() && isNewRepository())\n \t\t\tcreateNewRepository(updates);\n \n+\t\tRefWriter refWriter = new RefWriter(newRefs.values()) {\n+\t\t\t@Override\n+\t\t\tprotected void writeFile(String file, byte[] content)\n+\t\t\t\t\tthrows IOException {\n+\t\t\t\tdest.writeFile(\"../\" + file, content);\n+\t\t\t}\n+\t\t};\n \t\tif (!packedRefUpdates.isEmpty()) {\n \t\t\ttry {\n-\t\t\t\tdest.writePackedRefs(newRefs.values());\n+\t\t\t\trefWriter.writePackedRefs();\n \t\t\t\tfor (final RemoteRefUpdate u : packedRefUpdates)\n \t\t\t\t\tu.setStatus(Status.OK);\n \t\t\t} catch (IOException err) {\n@@ -173,7 +181,7 @@ class WalkPushConnection extends BaseConnection implements PushConnection {\n \t\t}\n \n \t\ttry {\n-\t\t\tdest.writeInfoRefs(newRefs.values());\n+\t\t\trefWriter.writeInfoRefs();\n \t\t} catch (IOException err) {\n \t\t\tthrow new TransportException(uri, \"failed updating refs\", err);\n \t\t}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java\nindex c5a5199..25640dc 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java\n@@ -44,7 +44,6 @@ import java.io.IOException;\n import java.io.InputStream;\n import java.io.InputStreamReader;\n import java.io.OutputStream;\n-import java.io.StringWriter;\n import java.util.ArrayList;\n import java.util.Collection;\n import java.util.Map;\n@@ -337,99 +336,6 @@ abstract class WalkRemoteObjectDatabase {\n \t}\n \n \t/**\n-\t * Rebuild the {@link #INFO_REFS} for dumb transport clients.\n-\t * <p>\n-\t * This method rebuilds the contents of the {@link #INFO_REFS} file to match\n-\t * the passed list of references.\n-\t *\n-\t * @param refs\n-\t *            the complete set of references the remote side now has. This\n-\t *            should have been computed by applying updates to the\n-\t *            advertised refs already discovered.\n-\t * @throws IOException\n-\t *             writing is not supported, or attempting to write the file\n-\t *             failed, possibly due to permissions or remote disk full, etc.\n-\t */\n-\tvoid writeInfoRefs(final Collection<Ref> refs) throws IOException {\n-\t\tfinal StringWriter w = new StringWriter();\n-\t\tfinal char[] tmp = new char[Constants.OBJECT_ID_LENGTH * 2];\n-\t\tfor (final Ref r : refs) {\n-\t\t\tif (Constants.HEAD.equals(r.getName())) {\n-\t\t\t\t// Historically HEAD has never been published through\n-\t\t\t\t// the INFO_REFS file. This is a mistake, but its the\n-\t\t\t\t// way things are.\n-\t\t\t\t//\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n-\t\t\tr.getObjectId().copyTo(tmp, w);\n-\t\t\tw.write('\\t');\n-\t\t\tw.write(r.getName());\n-\t\t\tw.write('\\n');\n-\n-\t\t\tif (r.getPeeledObjectId() != null) {\n-\t\t\t\tr.getPeeledObjectId().copyTo(tmp, w);\n-\t\t\t\tw.write('\\t');\n-\t\t\t\tw.write(r.getName());\n-\t\t\t\tw.write(\"^{}\\n\");\n-\t\t\t}\n-\t\t}\n-\t\twriteFile(INFO_REFS, Constants.encodeASCII(w.toString()));\n-\t}\n-\n-\t/**\n-\t * Rebuild the {@link #PACKED_REFS} file.\n-\t * <p>\n-\t * This method rebuilds the contents of the {@link #PACKED_REFS} file to\n-\t * match the passed list of references, including only those refs that have\n-\t * a storage type of {@link Ref.Storage#PACKED}.\n-\t *\n-\t * @param refs\n-\t *            the complete set of references the remote side now has. This\n-\t *            should have been computed by applying updates to the\n-\t *            advertised refs already discovered.\n-\t * @throws IOException\n-\t *             writing is not supported, or attempting to write the file\n-\t *             failed, possibly due to permissions or remote disk full, etc.\n-\t */\n-\tvoid writePackedRefs(final Collection<Ref> refs) throws IOException {\n-\t\tboolean peeled = false;\n-\n-\t\tfor (final Ref r : refs) {\n-\t\t\tif (r.getStorage() != Ref.Storage.PACKED)\n-\t\t\t\tcontinue;\n-\t\t\tif (r.getPeeledObjectId() != null)\n-\t\t\t\tpeeled = true;\n-\t\t}\n-\n-\t\tfinal StringWriter w = new StringWriter();\n-\t\tif (peeled) {\n-\t\t\tw.write(\"# pack-refs with:\");\n-\t\t\tif (peeled)\n-\t\t\t\tw.write(\" peeled\");\n-\t\t\tw.write('\\n');\n-\t\t}\n-\n-\t\tfinal char[] tmp = new char[Constants.OBJECT_ID_LENGTH * 2];\n-\t\tfor (final Ref r : refs) {\n-\t\t\tif (r.getStorage() != Ref.Storage.PACKED)\n-\t\t\t\tcontinue;\n-\n-\t\t\tr.getObjectId().copyTo(tmp, w);\n-\t\t\tw.write(' ');\n-\t\t\tw.write(r.getName());\n-\t\t\tw.write('\\n');\n-\n-\t\t\tif (r.getPeeledObjectId() != null) {\n-\t\t\t\tw.write('^');\n-\t\t\t\tr.getPeeledObjectId().copyTo(tmp, w);\n-\t\t\t\tw.write('\\n');\n-\t\t\t}\n-\t\t}\n-\t\twriteFile(PACKED_REFS, Constants.encodeASCII(w.toString()));\n-\t}\n-\n-\t/**\n \t * Open a buffered reader around a file.\n \t * <p>\n \t * This is shorthand for calling {@link #open(String)} and then wrapping it\n-- \n1.6.0.rc2.35.g04c6e\n"},{"id":"87176","messageId":"1218708829-8175-3-git-send-email-charleso@charleso.org","threadId":"15002","inReplyTo":"1218708829-8175-2-git-send-email-charleso@charleso.org","subject":"[PATCH 2/7] Refactor of RefUpdate force to call common updateImpl instead of duplication","fromName":"Charles O'Farrell","fromEmail":"charleso@charleso.org","sentAt":"2008-08-14T10:13:44Z","receivedAt":"2008-08-14T10:13:44Z","isPatch":true,"sender":{"key":"charleso@charleso.org","avatar":"https://gravatar.com/avatar/ce96d531daa37646a38a81e48113865af86a6d290ad92931f3b217896bdf86ea?d=mp&s=160"},"body":"Signed-off-by: Charles O'Farrell <charleso@charleso.org>\n---\n .../src/org/spearce/jgit/lib/RefUpdate.java        |   38 ++++---------------\n 1 files changed, 8 insertions(+), 30 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\nindex 369cb37..1b38fce 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n@@ -266,31 +266,8 @@ public class RefUpdate {\n \t *             an unexpected IO error occurred while writing changes.\n \t */\n \tpublic Result forceUpdate() throws IOException {\n-\t\trequireCanDoUpdate();\n-\t\ttry {\n-\t\t\treturn result = forceUpdateImpl();\n-\t\t} catch (IOException x) {\n-\t\t\tresult = Result.IO_FAILURE;\n-\t\t\tthrow x;\n-\t\t}\n-\t}\n-\n-\tprivate Result forceUpdateImpl() throws IOException {\n-\t\tfinal LockFile lock;\n-\n-\t\tlock = new LockFile(looseFile);\n-\t\tif (!lock.lock())\n-\t\t\treturn Result.LOCK_FAILURE;\n-\t\ttry {\n-\t\t\toldValue = db.idOf(name);\n-\t\t\tif (oldValue == null)\n-\t\t\t\treturn store(lock, Result.NEW);\n-\t\t\tif (oldValue.equals(newValue))\n-\t\t\t\treturn Result.NO_CHANGE;\n-\t\t\treturn store(lock, Result.FORCED);\n-\t\t} finally {\n-\t\t\tlock.unlock();\n-\t\t}\n+\t\tforce = true;\n+\t\treturn update();\n \t}\n \n \t/**\n@@ -347,6 +324,12 @@ public class RefUpdate {\n \t\t\tif (oldValue == null)\n \t\t\t\treturn store(lock, Result.NEW);\n \n+\t\t\tif (isForceUpdate()) {\n+\t\t\t\tif (oldValue.equals(newValue))\n+\t\t\t\t\treturn Result.NO_CHANGE;\n+\t\t\t\treturn store(lock, Result.FORCED);\n+\t\t\t}\n+\n \t\t\tnewObj = walk.parseAny(newValue);\n \t\t\toldObj = walk.parseAny(oldValue);\n \t\t\tif (newObj == oldObj)\n@@ -355,13 +338,8 @@ public class RefUpdate {\n \t\t\tif (newObj instanceof RevCommit && oldObj instanceof RevCommit) {\n \t\t\t\tif (walk.isMergedInto((RevCommit) oldObj, (RevCommit) newObj))\n \t\t\t\t\treturn store(lock, Result.FAST_FORWARD);\n-\t\t\t\tif (isForceUpdate())\n-\t\t\t\t\treturn store(lock, Result.FORCED);\n-\t\t\t\treturn Result.REJECTED;\n \t\t\t}\n \n-\t\t\tif (isForceUpdate())\n-\t\t\t\treturn store(lock, Result.FORCED);\n \t\t\treturn Result.REJECTED;\n \t\t} finally {\n \t\t\tlock.unlock();\n-- \n1.6.0.rc2.35.g04c6e\n"},{"id":"87178","messageId":"1218708829-8175-4-git-send-email-charleso@charleso.org","threadId":"15002","inReplyTo":"1218708829-8175-3-git-send-email-charleso@charleso.org","subject":"[PATCH 3/7] Minor refactor of constants, including log and ROOT_DIR","fromName":"Charles O'Farrell","fromEmail":"charleso@charleso.org","sentAt":"2008-08-14T10:13:45Z","receivedAt":"2008-08-14T10:13:45Z","isPatch":true,"sender":{"key":"charleso@charleso.org","avatar":"https://gravatar.com/avatar/ce96d531daa37646a38a81e48113865af86a6d290ad92931f3b217896bdf86ea?d=mp&s=160"},"body":"Signed-off-by: Charles O'Farrell <charleso@charleso.org>\n---\n .../src/org/spearce/jgit/lib/Constants.java        |    3 +++\n .../src/org/spearce/jgit/lib/RefLogWriter.java     |    2 +-\n .../spearce/jgit/transport/TransportAmazonS3.java  |   10 ++++++----\n .../org/spearce/jgit/transport/TransportSftp.java  |    6 +++---\n .../spearce/jgit/transport/WalkPushConnection.java |    8 +++++---\n .../jgit/transport/WalkRemoteObjectDatabase.java   |   16 +++++++++-------\n 6 files changed, 27 insertions(+), 18 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\nindex 7bbd88e..9ae3c1d 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n@@ -214,6 +214,9 @@ public final class Constants {\n \t/** Prefix for tag refs */\n \tpublic static final String TAGS_PREFIX = \"refs/tags\";\n \n+\t/** Logs folder name */\n+\tpublic static final String LOGS = \"logs\";\n+\n \t/** Info refs folder */\n \tpublic static final String INFO_REFS = \"info/refs\";\n \ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefLogWriter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefLogWriter.java\nindex 8256d70..3aecaf2 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefLogWriter.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefLogWriter.java\n@@ -70,7 +70,7 @@ public class RefLogWriter {\n \t\tString entry = buildReflogString(repo, oldCommit, commit, message);\n \n \t\tFile directory = repo.getDirectory();\n-\t\tFile reflogfile = new File(directory, \"logs/\" + refName);\n+\t\tFile reflogfile = new File(directory, Constants.LOGS + \"/\" + refName);\n \t\tFile reflogdir = reflogfile.getParentFile();\n \t\tif (!reflogdir.exists())\n \t\t\tif (!reflogdir.mkdirs())\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java\nindex 9aa2567..f9df36d 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java\n@@ -178,7 +178,7 @@ class TransportAmazonS3 extends WalkTransport {\n \t\t\tif (subpath.endsWith(\"/\"))\n \t\t\t\tsubpath = subpath.substring(0, subpath.length() - 1);\n \t\t\tString k = objectsKey;\n-\t\t\twhile (subpath.startsWith(\"../\")) {\n+\t\t\twhile (subpath.startsWith(ROOT_DIR)) {\n \t\t\t\tk = k.substring(0, k.lastIndexOf('/'));\n \t\t\t\tsubpath = subpath.substring(3);\n \t\t\t}\n@@ -264,7 +264,8 @@ class TransportAmazonS3 extends WalkTransport {\n \t\tprivate void readLooseRefs(final TreeMap<String, Ref> avail)\n \t\t\t\tthrows TransportException {\n \t\t\ttry {\n-\t\t\t\tfor (final String n : s3.list(bucket, resolveKey(\"../refs\")))\n+\t\t\t\tfor (final String n : s3.list(bucket, resolveKey(ROOT_DIR\n+\t\t\t\t\t\t+ \"refs\")))\n \t\t\t\t\treadRef(avail, \"refs/\" + n);\n \t\t\t} catch (IOException e) {\n \t\t\t\tthrow new TransportException(getURI(), \"cannot list refs\", e);\n@@ -274,8 +275,9 @@ class TransportAmazonS3 extends WalkTransport {\n \t\tprivate Ref readRef(final TreeMap<String, Ref> avail, final String rn)\n \t\t\t\tthrows TransportException {\n \t\t\tfinal String s;\n+\t\t\tString ref = ROOT_DIR + rn;\n \t\t\ttry {\n-\t\t\t\tfinal BufferedReader br = openReader(\"../\" + rn);\n+\t\t\t\tfinal BufferedReader br = openReader(ref);\n \t\t\t\ttry {\n \t\t\t\t\ts = br.readLine();\n \t\t\t\t} finally {\n@@ -284,7 +286,7 @@ class TransportAmazonS3 extends WalkTransport {\n \t\t\t} catch (FileNotFoundException noRef) {\n \t\t\t\treturn null;\n \t\t\t} catch (IOException err) {\n-\t\t\t\tthrow new TransportException(getURI(), \"read ../\" + rn, err);\n+\t\t\t\tthrow new TransportException(getURI(), \"read \" + ref, err);\n \t\t\t}\n \n \t\t\tif (s == null)\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java\nindex 6a5df07..78f4ad8 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java\n@@ -372,8 +372,8 @@ class TransportSftp extends WalkTransport {\n \t\tMap<String, Ref> readAdvertisedRefs() throws TransportException {\n \t\t\tfinal TreeMap<String, Ref> avail = new TreeMap<String, Ref>();\n \t\t\treadPackedRefs(avail);\n-\t\t\treadRef(avail, \"../HEAD\", \"HEAD\");\n-\t\t\treadLooseRefs(avail, \"../refs\", \"refs/\");\n+\t\t\treadRef(avail, ROOT_DIR + \"HEAD\", \"HEAD\");\n+\t\t\treadLooseRefs(avail, ROOT_DIR + \"refs\", \"refs/\");\n \t\t\treturn avail;\n \t\t}\n \n@@ -423,7 +423,7 @@ class TransportSftp extends WalkTransport {\n \n \t\t\tif (line.startsWith(\"ref: \")) {\n \t\t\t\tfinal String p = line.substring(\"ref: \".length());\n-\t\t\t\tRef r = readRef(avail, \"../\" + p, p);\n+\t\t\t\tRef r = readRef(avail, ROOT_DIR + p, p);\n \t\t\t\tif (r == null)\n \t\t\t\t\tr = avail.get(p);\n \t\t\t\tif (r != null) {\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java\nindex 19071d7..39b967c 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java\n@@ -37,6 +37,8 @@\n \n package org.spearce.jgit.transport;\n \n+import static org.spearce.jgit.transport.WalkRemoteObjectDatabase.ROOT_DIR;\n+\n import java.io.IOException;\n import java.io.OutputStream;\n import java.util.ArrayList;\n@@ -163,7 +165,7 @@ class WalkPushConnection extends BaseConnection implements PushConnection {\n \t\t\t@Override\n \t\t\tprotected void writeFile(String file, byte[] content)\n \t\t\t\t\tthrows IOException {\n-\t\t\t\tdest.writeFile(\"../\" + file, content);\n+\t\t\t\tdest.writeFile(ROOT_DIR + file, content);\n \t\t\t}\n \t\t};\n \t\tif (!packedRefUpdates.isEmpty()) {\n@@ -334,7 +336,7 @@ class WalkPushConnection extends BaseConnection implements PushConnection {\n \t\ttry {\n \t\t\tfinal String ref = \"ref: \" + pickHEAD(updates) + \"\\n\";\n \t\t\tfinal byte[] bytes = ref.getBytes(Constants.CHARACTER_ENCODING);\n-\t\t\tdest.writeFile(\"../HEAD\", bytes);\n+\t\t\tdest.writeFile(ROOT_DIR + \"HEAD\", bytes);\n \t\t} catch (IOException e) {\n \t\t\tthrow new TransportException(uri, \"cannot create HEAD\", e);\n \t\t}\n@@ -343,7 +345,7 @@ class WalkPushConnection extends BaseConnection implements PushConnection {\n \t\t\tfinal String config = \"[core]\\n\"\n \t\t\t\t\t+ \"\\trepositoryformatversion = 0\\n\";\n \t\t\tfinal byte[] bytes = config.getBytes(Constants.CHARACTER_ENCODING);\n-\t\t\tdest.writeFile(\"../config\", bytes);\n+\t\t\tdest.writeFile(ROOT_DIR + \"config\", bytes);\n \t\t} catch (IOException e) {\n \t\t\tthrow new TransportException(uri, \"cannot create config\", e);\n \t\t}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java\nindex 25640dc..8fb5e1e 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java\n@@ -66,6 +66,9 @@ import org.spearce.jgit.util.NB;\n  * independent {@link WalkFetchConnection}.\n  */\n abstract class WalkRemoteObjectDatabase {\n+\n+\tstatic final String ROOT_DIR = \"../\";\n+\n \tstatic final String CHARENC = Constants.CHARACTER_ENCODING;\n \n \tstatic final String INFO_PACKS = \"info/packs\";\n@@ -74,9 +77,7 @@ abstract class WalkRemoteObjectDatabase {\n \n \tstatic final String INFO_HTTP_ALTERNATES = \"info/http-alternates\";\n \n-\tstatic final String INFO_REFS = \"../info/refs\";\n-\n-\tstatic final String PACKED_REFS = \"../packed-refs\";\n+\tstatic final String INFO_REFS = ROOT_DIR + Constants.INFO_REFS;\n \n \tabstract URIish getURI();\n \n@@ -271,7 +272,7 @@ abstract class WalkRemoteObjectDatabase {\n \t *             deletion is not supported, or deletion failed.\n \t */\n \tvoid deleteRef(final String name) throws IOException {\n-\t\tdeleteFile(\"../\" + name);\n+\t\tdeleteFile(ROOT_DIR + name);\n \t}\n \n \t/**\n@@ -284,7 +285,7 @@ abstract class WalkRemoteObjectDatabase {\n \t *             deletion is not supported, or deletion failed.\n \t */\n \tvoid deleteRefLog(final String name) throws IOException {\n-\t\tdeleteFile(\"../logs/\" + name);\n+\t\tdeleteFile(ROOT_DIR + Constants.LOGS + \"/\" + name);\n \t}\n \n \t/**\n@@ -308,7 +309,7 @@ abstract class WalkRemoteObjectDatabase {\n \t\tvalue.copyTo(b);\n \t\tb.write('\\n');\n \n-\t\twriteFile(\"../\" + name, b.toByteArray());\n+\t\twriteFile(ROOT_DIR + name, b.toByteArray());\n \t}\n \n \t/**\n@@ -411,7 +412,8 @@ abstract class WalkRemoteObjectDatabase {\n \tprotected void readPackedRefs(final Map<String, Ref> avail)\n \t\t\tthrows TransportException {\n \t\ttry {\n-\t\t\tfinal BufferedReader br = openReader(PACKED_REFS);\n+\t\t\tfinal BufferedReader br = openReader(ROOT_DIR\n+\t\t\t\t\t+ Constants.PACKED_REFS);\n \t\t\ttry {\n \t\t\t\treadPackedRefsImpl(avail, br);\n \t\t\t} finally {\n-- \n1.6.0.rc2.35.g04c6e\n"},{"id":"87179","messageId":"1218708829-8175-5-git-send-email-charleso@charleso.org","threadId":"15002","inReplyTo":"1218708829-8175-4-git-send-email-charleso@charleso.org","subject":"[PATCH 4/7] Extract lockAndWriteFile method in RefDatabase for reuse","fromName":"Charles O'Farrell","fromEmail":"charleso@charleso.org","sentAt":"2008-08-14T10:13:46Z","receivedAt":"2008-08-14T10:13:46Z","isPatch":true,"sender":{"key":"charleso@charleso.org","avatar":"https://gravatar.com/avatar/ce96d531daa37646a38a81e48113865af86a6d290ad92931f3b217896bdf86ea?d=mp&s=160"},"body":"Signed-off-by: Charles O'Farrell <charleso@charleso.org>\n---\n .../src/org/spearce/jgit/lib/RefDatabase.java      |   25 ++++++++++++--------\n 1 files changed, 15 insertions(+), 10 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\nindex 3e68a8d..3d8280d 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n@@ -158,16 +158,7 @@ class RefDatabase {\n \t */\n \tvoid link(final String name, final String target) throws IOException {\n \t\tfinal byte[] content = (\"ref: \" + target + \"\\n\").getBytes(CHAR_ENC);\n-\t\tfinal LockFile lck = new LockFile(fileForRef(name));\n-\t\tif (!lck.lock())\n-\t\t\tthrow new ObjectWritingException(\"Unable to lock \" + name);\n-\t\ttry {\n-\t\t\tlck.write(content);\n-\t\t} catch (IOException ioe) {\n-\t\t\tthrow new ObjectWritingException(\"Unable to write \" + name, ioe);\n-\t\t}\n-\t\tif (!lck.commit())\n-\t\t\tthrow new ObjectWritingException(\"Unable to write \" + name);\n+\t\tlockAndWriteFile(fileForRef(name), content);\n \t\tsetModified();\n \t\tdb.fireRefsMaybeChanged();\n \t}\n@@ -427,6 +418,20 @@ class RefDatabase {\n \t\t}\n \t}\n \n+\tprivate void lockAndWriteFile(File file, byte[] content) throws IOException {\n+\t\tString name = file.getName();\n+\t\tfinal LockFile lck = new LockFile(file);\n+\t\tif (!lck.lock())\n+\t\t\tthrow new ObjectWritingException(\"Unable to lock \" + name);\n+\t\ttry {\n+\t\t\tlck.write(content);\n+\t\t} catch (IOException ioe) {\n+\t\t\tthrow new ObjectWritingException(\"Unable to write \" + name, ioe);\n+\t\t}\n+\t\tif (!lck.commit())\n+\t\t\tthrow new ObjectWritingException(\"Unable to write \" + name);\n+\t}\n+\n \tprivate static String readLine(final File file)\n \t\t\tthrows FileNotFoundException, IOException {\n \t\tfinal BufferedReader br = openReader(file);\n-- \n1.6.0.rc2.35.g04c6e\n"},{"id":"87182","messageId":"1218708829-8175-6-git-send-email-charleso@charleso.org","threadId":"15002","inReplyTo":"1218708829-8175-5-git-send-email-charleso@charleso.org","subject":"[PATCH 5/7] Added removePackedRef method to RefDatabase for packed branch deletion","fromName":"Charles O'Farrell","fromEmail":"charleso@charleso.org","sentAt":"2008-08-14T10:13:47Z","receivedAt":"2008-08-14T10:13:47Z","isPatch":true,"sender":{"key":"charleso@charleso.org","avatar":"https://gravatar.com/avatar/ce96d531daa37646a38a81e48113865af86a6d290ad92931f3b217896bdf86ea?d=mp&s=160"},"body":"Signed-off-by: Charles O'Farrell <charleso@charleso.org>\n---\n .../src/org/spearce/jgit/lib/RefDatabase.java      |   16 +++++++++++++++-\n .../src/org/spearce/jgit/lib/Repository.java       |    2 +-\n 2 files changed, 16 insertions(+), 2 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\nindex 3d8280d..0293ace 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n@@ -121,7 +121,7 @@ class RefDatabase {\n \t}\n \n \t/**\n-\t * Create a command to update (or create) a ref in this repository.\n+\t * Create a command to update, create or delete a ref in this repository.\n \t * \n \t * @param name\n \t *            name of the ref the caller wants to modify.\n@@ -432,6 +432,20 @@ class RefDatabase {\n \t\t\tthrow new ObjectWritingException(\"Unable to write \" + name);\n \t}\n \n+\tvoid removePackedRef(String name) throws IOException {\n+\t\tpackedRefs.remove(name);\n+\t\twritePackedRefs();\n+\t}\n+\n+\tprivate void writePackedRefs() throws IOException {\n+\t\tnew RefWriter(packedRefs.values()) {\n+\t\t\t@Override\n+\t\t\tprotected void writeFile(String name, byte[] content) throws IOException {\n+\t\t\t\tlockAndWriteFile(new File(db.getDirectory(), name), content);\n+\t\t\t}\n+\t\t}.writePackedRefs();\n+\t}\n+\n \tprivate static String readLine(final File file)\n \t\t\tthrows FileNotFoundException, IOException {\n \t\tfinal BufferedReader br = openReader(file);\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\nindex 6f7961e..7679e53 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n@@ -493,7 +493,7 @@ public class Repository {\n \t}\n \n \t/**\n-\t * Create a command to update (or create) a ref in this repository.\n+\t * Create a command to update, create or delete a ref in this repository.\n \t * \n \t * @param ref\n \t *            name of the ref the caller wants to modify.\n-- \n1.6.0.rc2.35.g04c6e\n"},{"id":"87181","messageId":"1218708829-8175-7-git-send-email-charleso@charleso.org","threadId":"15002","inReplyTo":"1218708829-8175-6-git-send-email-charleso@charleso.org","subject":"[PATCH 6/7] Added ref deletion to RefUpdate","fromName":"Charles O'Farrell","fromEmail":"charleso@charleso.org","sentAt":"2008-08-14T10:13:48Z","receivedAt":"2008-08-14T10:13:48Z","isPatch":true,"sender":{"key":"charleso@charleso.org","avatar":"https://gravatar.com/avatar/ce96d531daa37646a38a81e48113865af86a6d290ad92931f3b217896bdf86ea?d=mp&s=160"},"body":"This is mixed in with the update code as they as they are common in\ntheir general behaviour, differing only in the storing of the changes.\n\nSigned-off-by: Charles O'Farrell <charleso@charleso.org>\n---\n .../src/org/spearce/jgit/lib/RefUpdate.java        |   70 ++++++++++++++++++--\n 1 files changed, 64 insertions(+), 6 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\nindex 1b38fce..e7560e9 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n@@ -40,6 +40,7 @@ package org.spearce.jgit.lib;\n import java.io.File;\n import java.io.IOException;\n \n+import org.spearce.jgit.lib.Ref.Storage;\n import org.spearce.jgit.revwalk.RevCommit;\n import org.spearce.jgit.revwalk.RevObject;\n import org.spearce.jgit.revwalk.RevWalk;\n@@ -146,8 +147,11 @@ public class RefUpdate {\n \t/** Result of the update operation. */\n \tprivate Result result = Result.NOT_ATTEMPTED;\n \n+\tprivate final Ref ref;\n+\n \tRefUpdate(final RefDatabase r, final Ref ref, final File f) {\n \t\tdb = r;\n+\t\tthis.ref = ref;\n \t\tname = ref.getName();\n \t\toldValue = ref.getObjectId();\n \t\tlooseFile = f;\n@@ -304,14 +308,31 @@ public class RefUpdate {\n \tpublic Result update(final RevWalk walk) throws IOException {\n \t\trequireCanDoUpdate();\n \t\ttry {\n-\t\t\treturn result = updateImpl(walk);\n+\t\t\treturn result = updateImpl(walk, new UpdateStore());\n+\t\t} catch (IOException x) {\n+\t\t\tresult = Result.IO_FAILURE;\n+\t\t\tthrow x;\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Delete the ref.\n+\t * \n+\t * @return the result status of the delete.\n+\t * @throws IOException\n+\t */\n+\tpublic Result delete() throws IOException {\n+\t\ttry {\n+\t\t\treturn updateImpl(new RevWalk(db.getRepository()),\n+\t\t\t\t\tnew DeleteStore());\n \t\t} catch (IOException x) {\n \t\t\tresult = Result.IO_FAILURE;\n \t\t\tthrow x;\n \t\t}\n \t}\n \n-\tprivate Result updateImpl(final RevWalk walk) throws IOException {\n+\tprivate Result updateImpl(final RevWalk walk, final Store store)\n+\t\t\tthrows IOException {\n \t\tfinal LockFile lock;\n \t\tRevObject newObj;\n \t\tRevObject oldObj;\n@@ -322,12 +343,12 @@ public class RefUpdate {\n \t\ttry {\n \t\t\toldValue = db.idOf(name);\n \t\t\tif (oldValue == null)\n-\t\t\t\treturn store(lock, Result.NEW);\n+\t\t\t\treturn store.store(lock, Result.NEW);\n \n \t\t\tif (isForceUpdate()) {\n \t\t\t\tif (oldValue.equals(newValue))\n \t\t\t\t\treturn Result.NO_CHANGE;\n-\t\t\t\treturn store(lock, Result.FORCED);\n+\t\t\t\treturn store.store(lock, Result.FORCED);\n \t\t\t}\n \n \t\t\tnewObj = walk.parseAny(newValue);\n@@ -337,7 +358,7 @@ public class RefUpdate {\n \n \t\t\tif (newObj instanceof RevCommit && oldObj instanceof RevCommit) {\n \t\t\t\tif (walk.isMergedInto((RevCommit) oldObj, (RevCommit) newObj))\n-\t\t\t\t\treturn store(lock, Result.FAST_FORWARD);\n+\t\t\t\t\treturn store.store(lock, Result.FAST_FORWARD);\n \t\t\t}\n \n \t\t\treturn Result.REJECTED;\n@@ -346,7 +367,7 @@ public class RefUpdate {\n \t\t}\n \t}\n \n-\tprivate Result store(final LockFile lock, final Result status)\n+\tprivate Result updateStore(final LockFile lock, final Result status)\n \t\t\tthrows IOException {\n \t\tlock.setNeedStatInformation(true);\n \t\tlock.write(newValue);\n@@ -366,4 +387,41 @@ public class RefUpdate {\n \t\tdb.stored(name, newValue, lock.getCommitLastModified());\n \t\treturn status;\n \t}\n+\n+\t/**\n+\t * Handle the abstraction of storing a ref update. This is because both\n+\t * updating and deleting of a ref have merge testing in common.\n+\t */\n+\tprivate abstract class Store {\n+\t\tabstract Result store(final LockFile lock, final Result status)\n+\t\t\t\tthrows IOException;\n+\t}\n+\n+\tprivate class UpdateStore extends Store {\n+\n+\t\t@Override\n+\t\tResult store(final LockFile lock, final Result status)\n+\t\t\t\tthrows IOException {\n+\t\t\treturn updateStore(lock, status);\n+\t\t}\n+\t}\n+\n+\tprivate class DeleteStore extends Store {\n+\n+\t\t@Override\n+\t\tResult store(LockFile lock, Result status) throws IOException {\n+\t\t\tStorage storage = ref.getStorage();\n+\t\t\tif (storage == Storage.NEW)\n+\t\t\t\treturn status;\n+\t\t\tif (storage.isPacked())\n+\t\t\t\tdb.removePackedRef(ref.getName());\n+\t\t\tif (storage.isLoose())\n+\t\t\t\tif (!looseFile.delete())\n+\t\t\t\t\tthrow new IOException(\"File cannot be deleted: \"\n+\t\t\t\t\t\t\t+ looseFile);\n+\t\t\tnew File(db.getRepository().getDirectory(), Constants.LOGS + \"/\"\n+\t\t\t\t\t+ ref.getName()).delete();\n+\t\t\treturn status;\n+\t\t}\n+\t}\n }\n-- \n1.6.0.rc2.35.g04c6e\n"},{"id":"87180","messageId":"1218708829-8175-8-git-send-email-charleso@charleso.org","threadId":"15002","inReplyTo":"1218708829-8175-7-git-send-email-charleso@charleso.org","subject":"[PATCH 7/7] jgit: Added branch deletion to jgit command","fromName":"Charles O'Farrell","fromEmail":"charleso@charleso.org","sentAt":"2008-08-14T10:13:49Z","receivedAt":"2008-08-14T10:13:49Z","isPatch":true,"sender":{"key":"charleso@charleso.org","avatar":"https://gravatar.com/avatar/ce96d531daa37646a38a81e48113865af86a6d290ad92931f3b217896bdf86ea?d=mp&s=160"},"body":"Signed-off-by: Charles O'Farrell <charleso@charleso.org>\n---\n .../src/org/spearce/jgit/pgm/Branch.java           |   57 +++++++++++++++++++-\n 1 files changed, 55 insertions(+), 2 deletions(-)\n\ndiff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Branch.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Branch.java\nindex 8415fe2..c89f510 100644\n--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Branch.java\n+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Branch.java\n@@ -37,24 +37,50 @@\n \n package org.spearce.jgit.pgm;\n \n+import java.io.IOException;\n+import java.util.ArrayList;\n+import java.util.List;\n import java.util.Map;\n import java.util.TreeSet;\n \n+import org.kohsuke.args4j.Argument;\n import org.kohsuke.args4j.Option;\n import org.spearce.jgit.lib.Constants;\n+import org.spearce.jgit.lib.ObjectId;\n import org.spearce.jgit.lib.Ref;\n+import org.spearce.jgit.lib.RefUpdate;\n+import org.spearce.jgit.lib.RefUpdate.Result;\n \n @Command(common = true, usage = \"List, create, or delete branches\")\n class Branch extends TextBuiltin {\n \n \t@Option(name = \"--remote\", aliases = { \"-r\" }, usage = \"act on remote-tracking branches\")\n-\tboolean remote = false;\n+\tprivate boolean remote = false;\n \n \t@Option(name = \"--all\", aliases = { \"-a\" }, usage = \"list both remote-tracking and local branches\")\n-\tboolean all = false;\n+\tprivate boolean all = false;\n+\n+\t@Option(name = \"--delete\", aliases = { \"-d\" }, usage = \"delete fully merged branch\")\n+\tprivate boolean delete = false;\n+\n+\t@Option(name = \"--delete-force\", aliases = { \"-D\" }, usage = \"delete branch (even if not merged)\")\n+\tprivate boolean deleteForce = false;\n+\n+\t@Option(name = \"--verbose\", aliases = { \"-v\" }, usage = \"be verbose\")\n+\tprivate boolean verbose = false;\n+\n+\t@Argument\n+\tprivate List<String> branches = new ArrayList<String>();\n \n \t@Override\n \tprotected void run() throws Exception {\n+\t\tif (delete || deleteForce)\n+\t\t\tdelete(deleteForce);\n+\t\telse\n+\t\t\tlist();\n+\t}\n+\n+\tprivate void list() {\n \t\tMap<String, Ref> refs = db.getAllRefs();\n \t\tRef head = refs.get(Constants.HEAD);\n \t\t// This can happen if HEAD is stillborn\n@@ -80,4 +106,31 @@ class Branch extends TextBuiltin {\n \t\tref = ref.substring(ref.indexOf('/', 5) + 1);\n \t\tout.println(ref);\n \t}\n+\n+\tprivate void delete(boolean force) throws IOException {\n+\t\tString current = db.getBranch();\n+\t\tObjectId head = db.resolve(Constants.HEAD);\n+\t\tfor (String branch : branches) {\n+\t\t\tif (current.equals(branch)) {\n+\t\t\t\tString err = \"Cannot delete the branch '%s' which you are currently on.\";\n+\t\t\t\tthrow die(String.format(err, branch));\n+\t\t\t}\n+\t\t\tRefUpdate update = db.updateRef((remote ? Constants.REMOTES_PREFIX\n+\t\t\t\t\t: Constants.HEADS_PREFIX)\n+\t\t\t\t\t+ '/' + branch);\n+\t\t\tupdate.setNewObjectId(head);\n+\t\t\tupdate.setForceUpdate(force || remote);\n+\t\t\tResult result = update.delete();\n+\t\t\tif (result == Result.REJECTED) {\n+\t\t\t\tString err = \"The branch '%s' is not an ancestor of your current HEAD.\\n\"\n+\t\t\t\t\t\t+ \"If you are sure you want to delete it, run 'jgit branch -D %1$s'.\";\n+\t\t\t\tthrow die(String.format(err, branch));\n+\t\t\t} else if (result == Result.NEW)\n+\t\t\t\tthrow die(String.format(\"branch '%s' not found.\", branch));\n+\t\t\tif (remote)\n+\t\t\t\tout.println(String.format(\"Deleted remote branch %s\", branch));\n+\t\t\telse if (verbose)\n+\t\t\t\tout.println(String.format(\"Deleted branch %s\", branch));\n+\t\t}\n+\t}\n }\n-- \n1.6.0.rc2.35.g04c6e\n"},{"id":"87254","messageId":"20080814222345.GU3782@spearce.org","threadId":"15002","inReplyTo":"1218708829-8175-3-git-send-email-charleso@charleso.org","subject":"Re: [PATCH 2/7] Refactor of RefUpdate force to call common updateImpl instead of duplication","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-14T22:23:45Z","receivedAt":"2008-08-14T22:23:45Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Charles O'Farrell <charleso@charleso.org> wrote:\n> @@ -266,31 +266,8 @@ public class RefUpdate {\n>  \t *             an unexpected IO error occurred while writing changes.\n>  \t */\n>  \tpublic Result forceUpdate() throws IOException {\n[clipped uinteresting deletions to show only the postimage]\n> +\t\tforce = true;\n> +\t\treturn update();\n>  \t}\n>  \n>  \t/**\n> @@ -347,6 +324,12 @@ public class RefUpdate {\n>  \t\t\tif (oldValue == null)\n>  \t\t\t\treturn store(lock, Result.NEW);\n>  \n> +\t\t\tif (isForceUpdate()) {\n> +\t\t\t\tif (oldValue.equals(newValue))\n> +\t\t\t\t\treturn Result.NO_CHANGE;\n> +\t\t\t\treturn store(lock, Result.FORCED);\n> +\t\t\t}\n> +\n>  \t\t\tnewObj = walk.parseAny(newValue);\n>  \t\t\toldObj = walk.parseAny(oldValue);\n>  \t\t\tif (newObj == oldObj)\n> @@ -355,13 +338,8 @@ public class RefUpdate {\n>  \t\t\tif (newObj instanceof RevCommit && oldObj instanceof RevCommit) {\n>  \t\t\t\tif (walk.isMergedInto((RevCommit) oldObj, (RevCommit) newObj))\n>  \t\t\t\t\treturn store(lock, Result.FAST_FORWARD);\n> -\t\t\t\tif (isForceUpdate())\n> -\t\t\t\t\treturn store(lock, Result.FORCED);\n> -\t\t\t\treturn Result.REJECTED;\n\nThe problem with this change is that calls to just update() which\nhave isForceUpdate() true but actually turn out to be FAST_FORWARD\ntypes of updates now report FORCED as the result.  We don't want\nto always report FORCED if the application is using just update().\n\nIts nice to know that the remote side didn't rewind since we last\nsaw them (for example).\n\n-- \nShawn.\n"},{"id":"87281","messageId":"1218759957-16735-1-git-send-email-charleso@charleso.org","threadId":"15002","inReplyTo":"1218708829-8175-1-git-send-email-charleso@charleso.org","subject":"[JGIT PATCH v2 2/7] Refactor of RefUpdate force to call common updateImpl instead of duplication","fromName":"Charles O'Farrell","fromEmail":"charleso@charleso.org","sentAt":"2008-08-15T00:25:56Z","receivedAt":"2008-08-15T00:25:56Z","isPatch":true,"sender":{"key":"charleso@charleso.org","avatar":"https://gravatar.com/avatar/ce96d531daa37646a38a81e48113865af86a6d290ad92931f3b217896bdf86ea?d=mp&s=160"},"body":"Signed-off-by: Charles O'Farrell <charleso@charleso.org>\n---\n .../src/org/spearce/jgit/lib/RefUpdate.java        |   34 ++-----------------\n 1 files changed, 4 insertions(+), 30 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\nindex 369cb37..4587fc1 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n@@ -258,39 +258,16 @@ public class RefUpdate {\n \t/**\n \t * Force the ref to take the new value.\n \t * <p>\n-\t * No merge tests are performed, so the value of {@link #isForceUpdate()}\n-\t * will not be honored.\n+\t * This is just a convenient helper for setting the force flag, and as such\n+\t * the merge test is performed.\n \t * \n \t * @return the result status of the update.\n \t * @throws IOException\n \t *             an unexpected IO error occurred while writing changes.\n \t */\n \tpublic Result forceUpdate() throws IOException {\n-\t\trequireCanDoUpdate();\n-\t\ttry {\n-\t\t\treturn result = forceUpdateImpl();\n-\t\t} catch (IOException x) {\n-\t\t\tresult = Result.IO_FAILURE;\n-\t\t\tthrow x;\n-\t\t}\n-\t}\n-\n-\tprivate Result forceUpdateImpl() throws IOException {\n-\t\tfinal LockFile lock;\n-\n-\t\tlock = new LockFile(looseFile);\n-\t\tif (!lock.lock())\n-\t\t\treturn Result.LOCK_FAILURE;\n-\t\ttry {\n-\t\t\toldValue = db.idOf(name);\n-\t\t\tif (oldValue == null)\n-\t\t\t\treturn store(lock, Result.NEW);\n-\t\t\tif (oldValue.equals(newValue))\n-\t\t\t\treturn Result.NO_CHANGE;\n-\t\t\treturn store(lock, Result.FORCED);\n-\t\t} finally {\n-\t\t\tlock.unlock();\n-\t\t}\n+\t\tforce = true;\n+\t\treturn update();\n \t}\n \n \t/**\n@@ -355,9 +332,6 @@ public class RefUpdate {\n \t\t\tif (newObj instanceof RevCommit && oldObj instanceof RevCommit) {\n \t\t\t\tif (walk.isMergedInto((RevCommit) oldObj, (RevCommit) newObj))\n \t\t\t\t\treturn store(lock, Result.FAST_FORWARD);\n-\t\t\t\tif (isForceUpdate())\n-\t\t\t\t\treturn store(lock, Result.FORCED);\n-\t\t\t\treturn Result.REJECTED;\n \t\t\t}\n \n \t\t\tif (isForceUpdate())\n-- \n1.6.0.rc2.35.g04c6e\n"},{"id":"87282","messageId":"1218759957-16735-2-git-send-email-charleso@charleso.org","threadId":"15002","inReplyTo":"1218759957-16735-1-git-send-email-charleso@charleso.org","subject":"[JGIT PATCH v2 6/7] Added ref deletion to RefUpdate","fromName":"Charles O'Farrell","fromEmail":"charleso@charleso.org","sentAt":"2008-08-15T00:25:57Z","receivedAt":"2008-08-15T00:25:57Z","isPatch":true,"sender":{"key":"charleso@charleso.org","avatar":"https://gravatar.com/avatar/ce96d531daa37646a38a81e48113865af86a6d290ad92931f3b217896bdf86ea?d=mp&s=160"},"body":"This is mixed in with the update code as they as they are common in\ntheir general behaviour, differing only in the storing of the changes.\n\nSigned-off-by: Charles O'Farrell <charleso@charleso.org>\n---\n .../src/org/spearce/jgit/lib/RefUpdate.java        |   70 ++++++++++++++++++--\n 1 files changed, 64 insertions(+), 6 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\nindex 4587fc1..858ba46 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n@@ -40,6 +40,7 @@ package org.spearce.jgit.lib;\n import java.io.File;\n import java.io.IOException;\n \n+import org.spearce.jgit.lib.Ref.Storage;\n import org.spearce.jgit.revwalk.RevCommit;\n import org.spearce.jgit.revwalk.RevObject;\n import org.spearce.jgit.revwalk.RevWalk;\n@@ -146,8 +147,11 @@ public class RefUpdate {\n \t/** Result of the update operation. */\n \tprivate Result result = Result.NOT_ATTEMPTED;\n \n+\tprivate final Ref ref;\n+\n \tRefUpdate(final RefDatabase r, final Ref ref, final File f) {\n \t\tdb = r;\n+\t\tthis.ref = ref;\n \t\tname = ref.getName();\n \t\toldValue = ref.getObjectId();\n \t\tlooseFile = f;\n@@ -304,14 +308,31 @@ public class RefUpdate {\n \tpublic Result update(final RevWalk walk) throws IOException {\n \t\trequireCanDoUpdate();\n \t\ttry {\n-\t\t\treturn result = updateImpl(walk);\n+\t\t\treturn result = updateImpl(walk, new UpdateStore());\n+\t\t} catch (IOException x) {\n+\t\t\tresult = Result.IO_FAILURE;\n+\t\t\tthrow x;\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Delete the ref.\n+\t * \n+\t * @return the result status of the delete.\n+\t * @throws IOException\n+\t */\n+\tpublic Result delete() throws IOException {\n+\t\ttry {\n+\t\t\treturn updateImpl(new RevWalk(db.getRepository()),\n+\t\t\t\t\tnew DeleteStore());\n \t\t} catch (IOException x) {\n \t\t\tresult = Result.IO_FAILURE;\n \t\t\tthrow x;\n \t\t}\n \t}\n \n-\tprivate Result updateImpl(final RevWalk walk) throws IOException {\n+\tprivate Result updateImpl(final RevWalk walk, final Store store)\n+\t\t\tthrows IOException {\n \t\tfinal LockFile lock;\n \t\tRevObject newObj;\n \t\tRevObject oldObj;\n@@ -322,7 +343,7 @@ public class RefUpdate {\n \t\ttry {\n \t\t\toldValue = db.idOf(name);\n \t\t\tif (oldValue == null)\n-\t\t\t\treturn store(lock, Result.NEW);\n+\t\t\t\treturn store.store(lock, Result.NEW);\n \n \t\t\tnewObj = walk.parseAny(newValue);\n \t\t\toldObj = walk.parseAny(oldValue);\n@@ -331,18 +352,18 @@ public class RefUpdate {\n \n \t\t\tif (newObj instanceof RevCommit && oldObj instanceof RevCommit) {\n \t\t\t\tif (walk.isMergedInto((RevCommit) oldObj, (RevCommit) newObj))\n-\t\t\t\t\treturn store(lock, Result.FAST_FORWARD);\n+\t\t\t\t\treturn store.store(lock, Result.FAST_FORWARD);\n \t\t\t}\n \n \t\t\tif (isForceUpdate())\n-\t\t\t\treturn store(lock, Result.FORCED);\n+\t\t\t\treturn store.store(lock, Result.FORCED);\n \t\t\treturn Result.REJECTED;\n \t\t} finally {\n \t\t\tlock.unlock();\n \t\t}\n \t}\n \n-\tprivate Result store(final LockFile lock, final Result status)\n+\tprivate Result updateStore(final LockFile lock, final Result status)\n \t\t\tthrows IOException {\n \t\tlock.setNeedStatInformation(true);\n \t\tlock.write(newValue);\n@@ -362,4 +383,41 @@ public class RefUpdate {\n \t\tdb.stored(name, newValue, lock.getCommitLastModified());\n \t\treturn status;\n \t}\n+\n+\t/**\n+\t * Handle the abstraction of storing a ref update. This is because both\n+\t * updating and deleting of a ref have merge testing in common.\n+\t */\n+\tprivate abstract class Store {\n+\t\tabstract Result store(final LockFile lock, final Result status)\n+\t\t\t\tthrows IOException;\n+\t}\n+\n+\tprivate class UpdateStore extends Store {\n+\n+\t\t@Override\n+\t\tResult store(final LockFile lock, final Result status)\n+\t\t\t\tthrows IOException {\n+\t\t\treturn updateStore(lock, status);\n+\t\t}\n+\t}\n+\n+\tprivate class DeleteStore extends Store {\n+\n+\t\t@Override\n+\t\tResult store(LockFile lock, Result status) throws IOException {\n+\t\t\tStorage storage = ref.getStorage();\n+\t\t\tif (storage == Storage.NEW)\n+\t\t\t\treturn status;\n+\t\t\tif (storage.isPacked())\n+\t\t\t\tdb.removePackedRef(ref.getName());\n+\t\t\tif (storage.isLoose())\n+\t\t\t\tif (!looseFile.delete())\n+\t\t\t\t\tthrow new IOException(\"File cannot be deleted: \"\n+\t\t\t\t\t\t\t+ looseFile);\n+\t\t\tnew File(db.getRepository().getDirectory(), Constants.LOGS + \"/\"\n+\t\t\t\t\t+ ref.getName()).delete();\n+\t\t\treturn status;\n+\t\t}\n+\t}\n }\n-- \n1.6.0.rc2.35.g04c6e\n"}]}