{"thread":{"id":"21191","subject":"[Sample-Conversion-PATCH 1/2] Add JGit IO module as dependency to the main module","startedAt":"2009-10-11T14:10:12Z","lastAt":"2009-10-11T14:10:13Z","messageCount":2,"participants":["imyousuf@gmail.com"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"124616","messageId":"1255270213-14514-1-git-send-email-imyousuf@gmail.com","threadId":"21191","inReplyTo":null,"subject":"[Sample-Conversion-PATCH 1/2] Add JGit IO module as dependency to the main module","fromName":"","fromEmail":"imyousuf@gmail.com","sentAt":"2009-10-11T14:10:12Z","receivedAt":"2009-10-11T14:10:12Z","isPatch":true,"sender":{"key":"imyousuf@gmail.com","avatar":"https://gravatar.com/avatar/fda3c870262849d03c7b9c4d288842e128d6d80769fa7bc2d22731b7597928be?d=mp&s=160"},"body":"From: Imran M Yousuf <imyousuf@smartitengineering.com>\n\nSigned-off-by: Imran M Yousuf <imyousuf@smartitengineering.com>\n---\n jgit-maven/jgit/pom.xml |    6 ++++++\n 1 files changed, 6 insertions(+), 0 deletions(-)\n\ndiff --git a/jgit-maven/jgit/pom.xml b/jgit-maven/jgit/pom.xml\nindex 9eb5758..7176db9 100644\n--- a/jgit-maven/jgit/pom.xml\n+++ b/jgit-maven/jgit/pom.xml\n@@ -62,6 +62,12 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n             <scope>test</scope>\n         </dependency>\n         <dependency>\n+            <groupId>org.eclipse</groupId>\n+            <artifactId>jgit-io</artifactId>\n+            <version>${project.version}</version>\n+            <scope>compile</scope>\n+        </dependency>\n+        <dependency>\n             <groupId>com.jcraft</groupId>\n             <artifactId>jsch</artifactId>\n             <version>0.1.41</version>\n-- \n1.6.2.1\n"},{"id":"124617","messageId":"1255270213-14514-2-git-send-email-imyousuf@gmail.com","threadId":"21191","inReplyTo":"1255270213-14514-1-git-send-email-imyousuf@gmail.com","subject":"[Sample-Conversion-PATCH 2/2] Introduce IO SPI usage in RepositoryConfig","fromName":"","fromEmail":"imyousuf@gmail.com","sentAt":"2009-10-11T14:10:13Z","receivedAt":"2009-10-11T14:10:13Z","isPatch":true,"sender":{"key":"imyousuf@gmail.com","avatar":"https://gravatar.com/avatar/fda3c870262849d03c7b9c4d288842e128d6d80769fa7bc2d22731b7597928be?d=mp&s=160"},"body":"From: Imran M Yousuf <imyousuf@smartitengineering.com>\n\nIn order to introduce IO SPI in repository config class file based config,\nfile lock and NB is converted to use the IO SPI instead of java.io.File\n\nNext is object directory.\n\nSigned-off-by: Imran M Yousuf <imyousuf@smartitengineering.com>\n---\n .../src/org/eclipse/jgit/lib/FileBasedConfig.java  |   12 +-\n .../src/org/eclipse/jgit/lib/LockFile.java         |  839 ++++++++++----------\n .../src/org/eclipse/jgit/lib/RepositoryConfig.java |    4 +-\n org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java |   54 ++-\n 4 files changed, 495 insertions(+), 414 deletions(-)\n rewrite org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java (78%)\n\ndiff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileBasedConfig.java\nindex 1300d85..a952be5 100644\n--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileBasedConfig.java\n+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileBasedConfig.java\n@@ -40,11 +40,11 @@\n  */\n package org.eclipse.jgit.lib;\n \n-import java.io.File;\n import java.io.FileNotFoundException;\n import java.io.IOException;\n \n import org.eclipse.jgit.errors.ConfigInvalidException;\n+import org.eclipse.jgit.io.Entry;\n import org.eclipse.jgit.util.NB;\n import org.eclipse.jgit.util.RawParseUtils;\n \n@@ -52,7 +52,7 @@\n  * The configuration file that is stored in the file of the file system.\n  */\n public class FileBasedConfig extends Config {\n-\tprivate final File configFile;\n+\tprivate final Entry configFile;\n \n \t/**\n \t * Create a configuration with no default fallback.\n@@ -60,7 +60,7 @@\n \t * @param cfgLocation\n \t *            the location of the configuration file on the file system\n \t */\n-\tpublic FileBasedConfig(File cfgLocation) {\n+\tpublic FileBasedConfig(Entry cfgLocation) {\n \t\tthis(null, cfgLocation);\n \t}\n \n@@ -72,13 +72,13 @@ public FileBasedConfig(File cfgLocation) {\n \t * @param cfgLocation\n \t *            the location of the configuration file on the file system\n \t */\n-\tpublic FileBasedConfig(Config base, File cfgLocation) {\n+\tpublic FileBasedConfig(Config base, Entry cfgLocation) {\n \t\tsuper(base);\n \t\tconfigFile = cfgLocation;\n \t}\n \n \t/** @return location of the configuration file on disk */\n-\tpublic final File getFile() {\n+\tpublic final Entry getFile() {\n \t\treturn configFile;\n \t}\n \n@@ -135,6 +135,6 @@ public void save() throws IOException {\n \n \t@Override\n \tpublic String toString() {\n-\t\treturn getClass().getSimpleName() + \"[\" + getFile().getPath() + \"]\";\n+\t\treturn getClass().getSimpleName() + \"[\" + getFile().getName() + \"]\";\n \t}\n }\n\\ No newline at end of file\ndiff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java\ndissimilarity index 78%\nindex a2d8469..b852ddf 100644\n--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java\n+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java\n@@ -1,405 +1,434 @@\n-/*\n- * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>\n- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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 Eclipse Foundation, Inc. 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.eclipse.jgit.lib;\n-\n-import java.io.BufferedOutputStream;\n-import java.io.File;\n-import java.io.FileInputStream;\n-import java.io.FileNotFoundException;\n-import java.io.FileOutputStream;\n-import java.io.IOException;\n-import java.io.OutputStream;\n-import java.nio.channels.FileLock;\n-import java.nio.channels.OverlappingFileLockException;\n-\n-/**\n- * Git style file locking and replacement.\n- * <p>\n- * To modify a ref file Git tries to use an atomic update approach: we write the\n- * new data into a brand new file, then rename it in place over the old name.\n- * This way we can just delete the temporary file if anything goes wrong, and\n- * nothing has been damaged. To coordinate access from multiple processes at\n- * once Git tries to atomically create the new temporary file under a well-known\n- * name.\n- */\n-public class LockFile {\n-\tprivate final File ref;\n-\n-\tprivate final File lck;\n-\n-\tprivate FileLock fLck;\n-\n-\tprivate boolean haveLck;\n-\n-\tprivate FileOutputStream os;\n-\n-\tprivate boolean needStatInformation;\n-\n-\tprivate long commitLastModified;\n-\n-\t/**\n-\t * Create a new lock for any file.\n-\t * \n-\t * @param f\n-\t *            the file that will be locked.\n-\t */\n-\tpublic LockFile(final File f) {\n-\t\tref = f;\n-\t\tlck = new File(ref.getParentFile(), ref.getName() + \".lock\");\n-\t}\n-\n-\t/**\n-\t * Try to establish the lock.\n-\t * \n-\t * @return true if the lock is now held by the caller; false if it is held\n-\t *         by someone else.\n-\t * @throws IOException\n-\t *             the temporary output file could not be created. The caller\n-\t *             does not hold the lock.\n-\t */\n-\tpublic boolean lock() throws IOException {\n-\t\tlck.getParentFile().mkdirs();\n-\t\tif (lck.createNewFile()) {\n-\t\t\thaveLck = true;\n-\t\t\ttry {\n-\t\t\t\tos = new FileOutputStream(lck);\n-\t\t\t\ttry {\n-\t\t\t\t\tfLck = os.getChannel().tryLock();\n-\t\t\t\t\tif (fLck == null)\n-\t\t\t\t\t\tthrow new OverlappingFileLockException();\n-\t\t\t\t} catch (OverlappingFileLockException ofle) {\n-\t\t\t\t\t// We cannot use unlock() here as this file is not\n-\t\t\t\t\t// held by us, but we thought we created it. We must\n-\t\t\t\t\t// not delete it, as it belongs to some other process.\n-\t\t\t\t\t//\n-\t\t\t\t\thaveLck = false;\n-\t\t\t\t\ttry {\n-\t\t\t\t\t\tos.close();\n-\t\t\t\t\t} catch (IOException ioe) {\n-\t\t\t\t\t\t// Fail by returning haveLck = false.\n-\t\t\t\t\t}\n-\t\t\t\t\tos = null;\n-\t\t\t\t}\n-\t\t\t} catch (IOException ioe) {\n-\t\t\t\tunlock();\n-\t\t\t\tthrow ioe;\n-\t\t\t}\n-\t\t}\n-\t\treturn haveLck;\n-\t}\n-\n-\t/**\n-\t * Try to establish the lock for appending.\n-\t * \n-\t * @return true if the lock is now held by the caller; false if it is held\n-\t *         by someone else.\n-\t * @throws IOException\n-\t *             the temporary output file could not be created. The caller\n-\t *             does not hold the lock.\n-\t */\n-\tpublic boolean lockForAppend() throws IOException {\n-\t\tif (!lock())\n-\t\t\treturn false;\n-\t\tcopyCurrentContent();\n-\t\treturn true;\n-\t}\n-\n-\t/**\n-\t * Copy the current file content into the temporary file.\n-\t * <p>\n-\t * This method saves the current file content by inserting it into the\n-\t * temporary file, so that the caller can safely append rather than replace\n-\t * the primary file.\n-\t * <p>\n-\t * This method does nothing if the current file does not exist, or exists\n-\t * but is empty.\n-\t * \n-\t * @throws IOException\n-\t *             the temporary file could not be written, or a read error\n-\t *             occurred while reading from the current file. The lock is\n-\t *             released before throwing the underlying IO exception to the\n-\t *             caller.\n-\t * @throws RuntimeException\n-\t *             the temporary file could not be written. The lock is released\n-\t *             before throwing the underlying exception to the caller.\n-\t */\n-\tpublic void copyCurrentContent() throws IOException {\n-\t\trequireLock();\n-\t\ttry {\n-\t\t\tfinal FileInputStream fis = new FileInputStream(ref);\n-\t\t\ttry {\n-\t\t\t\tfinal byte[] buf = new byte[2048];\n-\t\t\t\tint r;\n-\t\t\t\twhile ((r = fis.read(buf)) >= 0)\n-\t\t\t\t\tos.write(buf, 0, r);\n-\t\t\t} finally {\n-\t\t\t\tfis.close();\n-\t\t\t}\n-\t\t} catch (FileNotFoundException fnfe) {\n-\t\t\t// Don't worry about a file that doesn't exist yet, it\n-\t\t\t// conceptually has no current content to copy.\n-\t\t\t//\n-\t\t} catch (IOException ioe) {\n-\t\t\tunlock();\n-\t\t\tthrow ioe;\n-\t\t} catch (RuntimeException ioe) {\n-\t\t\tunlock();\n-\t\t\tthrow ioe;\n-\t\t} catch (Error ioe) {\n-\t\t\tunlock();\n-\t\t\tthrow ioe;\n-\t\t}\n-\t}\n-\n-\t/**\n-\t * Write an ObjectId and LF to the temporary file.\n-\t * \n-\t * @param id\n-\t *            the id to store in the file. The id will be written in hex,\n-\t *            followed by a sole LF.\n-\t * @throws IOException\n-\t *             the temporary file could not be written. The lock is released\n-\t *             before throwing the underlying IO exception to the caller.\n-\t * @throws RuntimeException\n-\t *             the temporary file could not be written. The lock is released\n-\t *             before throwing the underlying exception to the caller.\n-\t */\n-\tpublic void write(final ObjectId id) throws IOException {\n-\t\trequireLock();\n-\t\ttry {\n-\t\t\tfinal BufferedOutputStream b;\n-\t\t\tb = new BufferedOutputStream(os, Constants.OBJECT_ID_LENGTH * 2 + 1);\n-\t\t\tid.copyTo(b);\n-\t\t\tb.write('\\n');\n-\t\t\tb.flush();\n-\t\t\tfLck.release();\n-\t\t\tb.close();\n-\t\t\tos = null;\n-\t\t} catch (IOException ioe) {\n-\t\t\tunlock();\n-\t\t\tthrow ioe;\n-\t\t} catch (RuntimeException ioe) {\n-\t\t\tunlock();\n-\t\t\tthrow ioe;\n-\t\t} catch (Error ioe) {\n-\t\t\tunlock();\n-\t\t\tthrow ioe;\n-\t\t}\n-\t}\n-\n-\t/**\n-\t * Write arbitrary data to the temporary file.\n-\t * \n-\t * @param content\n-\t *            the bytes to store in the temporary file. No additional bytes\n-\t *            are added, so if the file must end with an LF it must appear\n-\t *            at the end of the byte array.\n-\t * @throws IOException\n-\t *             the temporary file could not be written. The lock is released\n-\t *             before throwing the underlying IO exception to the caller.\n-\t * @throws RuntimeException\n-\t *             the temporary file could not be written. The lock is released\n-\t *             before throwing the underlying exception to the caller.\n-\t */\n-\tpublic void write(final byte[] content) throws IOException {\n-\t\trequireLock();\n-\t\ttry {\n-\t\t\tos.write(content);\n-\t\t\tos.flush();\n-\t\t\tfLck.release();\n-\t\t\tos.close();\n-\t\t\tos = null;\n-\t\t} catch (IOException ioe) {\n-\t\t\tunlock();\n-\t\t\tthrow ioe;\n-\t\t} catch (RuntimeException ioe) {\n-\t\t\tunlock();\n-\t\t\tthrow ioe;\n-\t\t} catch (Error ioe) {\n-\t\t\tunlock();\n-\t\t\tthrow ioe;\n-\t\t}\n-\t}\n-\n-\t/**\n-\t * Obtain the direct output stream for this lock.\n-\t * <p>\n-\t * The stream may only be accessed once, and only after {@link #lock()} has\n-\t * been successfully invoked and returned true. Callers must close the\n-\t * stream prior to calling {@link #commit()} to commit the change.\n-\t * \n-\t * @return a stream to write to the new file. The stream is unbuffered.\n-\t */\n-\tpublic OutputStream getOutputStream() {\n-\t\trequireLock();\n-\t\treturn new OutputStream() {\n-\t\t\t@Override\n-\t\t\tpublic void write(final byte[] b, final int o, final int n)\n-\t\t\t\t\tthrows IOException {\n-\t\t\t\tos.write(b, o, n);\n-\t\t\t}\n-\n-\t\t\t@Override\n-\t\t\tpublic void write(final byte[] b) throws IOException {\n-\t\t\t\tos.write(b);\n-\t\t\t}\n-\n-\t\t\t@Override\n-\t\t\tpublic void write(final int b) throws IOException {\n-\t\t\t\tos.write(b);\n-\t\t\t}\n-\n-\t\t\t@Override\n-\t\t\tpublic void flush() throws IOException {\n-\t\t\t\tos.flush();\n-\t\t\t}\n-\n-\t\t\t@Override\n-\t\t\tpublic void close() throws IOException {\n-\t\t\t\ttry {\n-\t\t\t\t\tos.flush();\n-\t\t\t\t\tfLck.release();\n-\t\t\t\t\tos.close();\n-\t\t\t\t\tos = null;\n-\t\t\t\t} catch (IOException ioe) {\n-\t\t\t\t\tunlock();\n-\t\t\t\t\tthrow ioe;\n-\t\t\t\t} catch (RuntimeException ioe) {\n-\t\t\t\t\tunlock();\n-\t\t\t\t\tthrow ioe;\n-\t\t\t\t} catch (Error ioe) {\n-\t\t\t\t\tunlock();\n-\t\t\t\t\tthrow ioe;\n-\t\t\t\t}\n-\t\t\t}\n-\t\t};\n-\t}\n-\n-\tprivate void requireLock() {\n-\t\tif (os == null) {\n-\t\t\tunlock();\n-\t\t\tthrow new IllegalStateException(\"Lock on \" + ref + \" not held.\");\n-\t\t}\n-\t}\n-\n-\t/**\n-\t * Request that {@link #commit()} remember modification time.\n-\t * \n-\t * @param on\n-\t *            true if the commit method must remember the modification time.\n-\t */\n-\tpublic void setNeedStatInformation(final boolean on) {\n-\t\tneedStatInformation = on;\n-\t}\n-\n-\t/**\n-\t * Commit this change and release the lock.\n-\t * <p>\n-\t * If this method fails (returns false) the lock is still released.\n-\t * \n-\t * @return true if the commit was successful and the file contains the new\n-\t *         data; false if the commit failed and the file remains with the\n-\t *         old data.\n-\t * @throws IllegalStateException\n-\t *             the lock is not held.\n-\t */\n-\tpublic boolean commit() {\n-\t\tif (os != null) {\n-\t\t\tunlock();\n-\t\t\tthrow new IllegalStateException(\"Lock on \" + ref + \" not closed.\");\n-\t\t}\n-\n-\t\tsaveStatInformation();\n-\t\tif (lck.renameTo(ref))\n-\t\t\treturn true;\n-\t\tif (!ref.exists() || ref.delete())\n-\t\t\tif (lck.renameTo(ref))\n-\t\t\t\treturn true;\n-\t\tunlock();\n-\t\treturn false;\n-\t}\n-\n-\tprivate void saveStatInformation() {\n-\t\tif (needStatInformation)\n-\t\t\tcommitLastModified = lck.lastModified();\n-\t}\n-\n-\t/**\n-\t * Get the modification time of the output file when it was committed.\n-\t * \n-\t * @return modification time of the lock file right before we committed it.\n-\t */\n-\tpublic long getCommitLastModified() {\n-\t\treturn commitLastModified;\n-\t}\n-\n-\t/**\n-\t * Unlock this file and abort this change.\n-\t * <p>\n-\t * The temporary file (if created) is deleted before returning.\n-\t */\n-\tpublic void unlock() {\n-\t\tif (os != null) {\n-\t\t\tif (fLck != null) {\n-\t\t\t\ttry {\n-\t\t\t\t\tfLck.release();\n-\t\t\t\t} catch (IOException ioe) {\n-\t\t\t\t\t// Huh?\n-\t\t\t\t}\n-\t\t\t\tfLck = null;\n-\t\t\t}\n-\t\t\ttry {\n-\t\t\t\tos.close();\n-\t\t\t} catch (IOException ioe) {\n-\t\t\t\t// Ignore this\n-\t\t\t}\n-\t\t\tos = null;\n-\t\t}\n-\n-\t\tif (haveLck) {\n-\t\t\thaveLck = false;\n-\t\t\tlck.delete();\n-\t\t}\n-\t}\n-\n-\t@Override\n-\tpublic String toString() {\n-\t\treturn \"LockFile[\" + lck + \", haveLck=\" + haveLck + \"]\";\n-\t}\n-}\n+/*\n+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>\n+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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 Eclipse Foundation, Inc. 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+package org.eclipse.jgit.lib;\n+\n+import java.io.BufferedOutputStream;\n+import java.io.FileNotFoundException;\n+import java.io.IOException;\n+import java.io.InputStream;\n+import java.io.OutputStream;\n+import java.nio.channels.OverlappingFileLockException;\n+import org.eclipse.jgit.io.Entry;\n+\n+/**\n+ * Git style file locking and replacement.\n+ * <p>\n+ * To modify a ref file Git tries to use an atomic update approach: we write the\n+ * new data into a brand new file, then rename it in place over the old name.\n+ * This way we can just delete the temporary file if anything goes wrong, and\n+ * nothing has been damaged. To coordinate access from multiple processes at\n+ * once Git tries to atomically create the new temporary file under a well-known\n+ * name.\n+ */\n+public class LockFile {\n+\n+  public static final int DEFAULT_BUFFER_SIZE = 500;\n+\n+  private final Entry ref;\n+  private Entry lck;\n+  private boolean haveLck;\n+  private OutputStream os;\n+  private boolean needStatInformation;\n+  private long commitLastModified;\n+\n+  /**\n+   * Create a new lock for any file.\n+   *\n+   * @param f\n+   *            the file that will be locked.\n+   */\n+  public LockFile(final Entry f) {\n+    ref = f;\n+    lck = null;\n+  }\n+\n+  /**\n+   * Try to establish the lock.\n+   *\n+   * @return true if the lock is now held by the caller; false if it is held\n+   *         by someone else.\n+   * @throws IOException\n+   *             the temporary output file could not be created. The caller\n+   *             does not hold the lock.\n+   */\n+  public boolean lock()\n+          throws IOException {\n+    boolean locked = ref.tryLock();\n+    if (locked) {\n+      haveLck = true;\n+      try {\n+        lck = ref.getLockEntry();\n+        try {\n+          os = lck.getOutputStream(false, true);\n+        }\n+        catch (OverlappingFileLockException ofle) {\n+          // We cannot use unlock() here as this file is not\n+          // held by us, but we thought we created it. We must\n+          // not delete it, as it belongs to some other process.\n+          //\n+          haveLck = false;\n+          os = null;\n+        }\n+      }\n+      catch (IOException ioe) {\n+        unlock();\n+        throw ioe;\n+      }\n+    }\n+    return haveLck;\n+  }\n+\n+  /**\n+   * Try to establish the lock for appending.\n+   *\n+   * @return true if the lock is now held by the caller; false if it is held\n+   *         by someone else.\n+   * @throws IOException\n+   *             the temporary output file could not be created. The caller\n+   *             does not hold the lock.\n+   */\n+  public boolean lockForAppend()\n+          throws IOException {\n+    if (!lock()) {\n+      return false;\n+    }\n+    copyCurrentContent();\n+    return true;\n+  }\n+\n+  /**\n+   * Copy the current file content into the temporary file.\n+   * <p>\n+   * This method saves the current file content by inserting it into the\n+   * temporary file, so that the caller can safely append rather than replace\n+   * the primary file.\n+   * <p>\n+   * This method does nothing if the current file does not exist, or exists\n+   * but is empty.\n+   *\n+   * @throws IOException\n+   *             the temporary file could not be written, or a read error\n+   *             occurred while reading from the current file. The lock is\n+   *             released before throwing the underlying IO exception to the\n+   *             caller.\n+   * @throws RuntimeException\n+   *             the temporary file could not be written. The lock is released\n+   *             before throwing the underlying exception to the caller.\n+   */\n+  public void copyCurrentContent()\n+          throws IOException {\n+    requireLock();\n+    try {\n+      final InputStream fis = ref.getInputStream();\n+      try {\n+        final byte[] buf = new byte[2048];\n+        int r;\n+        while ((r = fis.read(buf)) >= 0) {\n+          os.write(buf, 0, r);\n+        }\n+      }\n+      finally {\n+        fis.close();\n+      }\n+    }\n+    catch (FileNotFoundException fnfe) {\n+      // Don't worry about a file that doesn't exist yet, it\n+      // conceptually has no current content to copy.\n+      //\n+    }\n+    catch (IOException ioe) {\n+      unlock();\n+      throw ioe;\n+    }\n+    catch (RuntimeException ioe) {\n+      unlock();\n+      throw ioe;\n+    }\n+    catch (Error ioe) {\n+      unlock();\n+      throw ioe;\n+    }\n+  }\n+\n+  /**\n+   * Write an ObjectId and LF to the temporary file.\n+   *\n+   * @param id\n+   *            the id to store in the file. The id will be written in hex,\n+   *            followed by a sole LF.\n+   * @throws IOException\n+   *             the temporary file could not be written. The lock is released\n+   *             before throwing the underlying IO exception to the caller.\n+   * @throws RuntimeException\n+   *             the temporary file could not be written. The lock is released\n+   *             before throwing the underlying exception to the caller.\n+   */\n+  public void write(final ObjectId id)\n+          throws IOException {\n+    requireLock();\n+    try {\n+      final BufferedOutputStream b;\n+      b = new BufferedOutputStream(os, Constants.OBJECT_ID_LENGTH * 2 + 1);\n+      id.copyTo(b);\n+      b.write('\\n');\n+      b.flush();\n+      b.close();\n+      os = null;\n+    }\n+    catch (IOException ioe) {\n+      unlock();\n+      throw ioe;\n+    }\n+    catch (RuntimeException ioe) {\n+      unlock();\n+      throw ioe;\n+    }\n+    catch (Error ioe) {\n+      unlock();\n+      throw ioe;\n+    }\n+  }\n+\n+  /**\n+   * Write arbitrary data to the temporary file.\n+   *\n+   * @param content\n+   *            the bytes to store in the temporary file. No additional bytes\n+   *            are added, so if the file must end with an LF it must appear\n+   *            at the end of the byte array.\n+   * @throws IOException\n+   *             the temporary file could not be written. The lock is released\n+   *             before throwing the underlying IO exception to the caller.\n+   * @throws RuntimeException\n+   *             the temporary file could not be written. The lock is released\n+   *             before throwing the underlying exception to the caller.\n+   */\n+  public void write(final byte[] content)\n+          throws IOException {\n+    requireLock();\n+    try {\n+      os.write(content);\n+      os.flush();\n+      os.close();\n+      os = null;\n+    }\n+    catch (IOException ioe) {\n+      unlock();\n+      throw ioe;\n+    }\n+    catch (RuntimeException ioe) {\n+      unlock();\n+      throw ioe;\n+    }\n+    catch (Error ioe) {\n+      unlock();\n+      throw ioe;\n+    }\n+  }\n+\n+  /**\n+   * Obtain the direct output stream for this lock.\n+   * <p>\n+   * The stream may only be accessed once, and only after {@link #lock()} has\n+   * been successfully invoked and returned true. Callers must close the\n+   * stream prior to calling {@link #commit()} to commit the change.\n+   *\n+   * @return a stream to write to the new file. The stream is unbuffered.\n+   */\n+  public OutputStream getOutputStream() {\n+    requireLock();\n+    return new OutputStream() {\n+\n+      @Override\n+      public void write(final byte[] b,\n+                        final int o,\n+                        final int n)\n+              throws IOException {\n+        os.write(b, o, n);\n+      }\n+\n+      @Override\n+      public void write(final byte[] b)\n+              throws IOException {\n+        os.write(b);\n+      }\n+\n+      @Override\n+      public void write(final int b)\n+              throws IOException {\n+        os.write(b);\n+      }\n+\n+      @Override\n+      public void flush()\n+              throws IOException {\n+        os.flush();\n+      }\n+\n+      @Override\n+      public void close()\n+              throws IOException {\n+        try {\n+          os.flush();\n+          os.close();\n+          os = null;\n+        }\n+        catch (IOException ioe) {\n+          unlock();\n+          throw ioe;\n+        }\n+        catch (RuntimeException ioe) {\n+          unlock();\n+          throw ioe;\n+        }\n+        catch (Error ioe) {\n+          unlock();\n+          throw ioe;\n+        }\n+      }\n+    };\n+  }\n+\n+  private void requireLock() {\n+    if (os == null) {\n+      unlock();\n+      throw new IllegalStateException(\"Lock on \" + ref + \" not held.\");\n+    }\n+  }\n+\n+  /**\n+   * Request that {@link #commit()} remember modification time.\n+   *\n+   * @param on\n+   *            true if the commit method must remember the modification time.\n+   */\n+  public void setNeedStatInformation(final boolean on) {\n+    needStatInformation = on;\n+  }\n+\n+  /**\n+   * Commit this change and release the lock.\n+   * <p>\n+   * If this method fails (returns false) the lock is still released.\n+   *\n+   * @return true if the commit was successful and the file contains the new\n+   *         data; false if the commit failed and the file remains with the\n+   *         old data.\n+   * @throws IllegalStateException\n+   *             the lock is not held.\n+   */\n+  public boolean commit() {\n+    if (os != null) {\n+      unlock();\n+      throw new IllegalStateException(\"Lock on \" + ref + \" not closed.\");\n+    }\n+\n+    saveStatInformation();\n+    try {\n+      if (!ref.isExists()) {\n+        ref.createNew();\n+      }\n+      OutputStream contentWriter = ref.getOutputStream(true, false);\n+      InputStream contentReader = lck.getInputStream();\n+      copy(contentReader, contentWriter);\n+      contentReader.close();\n+      contentWriter.close();\n+      unlock();\n+      return true;\n+    }\n+    catch (Exception ex) {\n+      //ignore\n+    }\n+    return false;\n+  }\n+\n+  public static int copy(\n+          InputStream input,\n+          OutputStream output)\n+          throws IOException {\n+    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];\n+    int count = 0;\n+    int n = 0;\n+    while (-1 != (n = input.read(buffer))) {\n+      output.write(buffer, 0, n);\n+      count += n;\n+    }\n+    return count;\n+  }\n+\n+  private void saveStatInformation() {\n+    if (needStatInformation) {\n+      commitLastModified = System.currentTimeMillis();\n+    }\n+  }\n+\n+  /**\n+   * Get the modification time of the output file when it was committed.\n+   *\n+   * @return modification time of the lock file right before we committed it.\n+   */\n+  public long getCommitLastModified() {\n+    return commitLastModified;\n+  }\n+\n+  /**\n+   * Unlock this file and abort this change.\n+   * <p>\n+   * The temporary file (if created) is deleted before returning.\n+   */\n+  public void unlock() {\n+    if (os != null) {\n+      try {\n+        os.close();\n+      }\n+      catch (IOException ioe) {\n+        // Ignore this\n+      }\n+      os = null;\n+    }\n+    if (haveLck) {\n+      haveLck = false;\n+      ref.unlock();\n+    }\n+  }\n+\n+  @Override\n+  public String toString() {\n+    return \"LockFile[\" + lck + \", haveLck=\" + haveLck + \"]\";\n+  }\n+}\ndiff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java\nindex 117e44a..851998e 100644\n--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java\n+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java\n@@ -41,7 +41,7 @@\n \n package org.eclipse.jgit.lib;\n \n-import java.io.File;\n+import org.eclipse.jgit.io.Entry;\n \n /**\n  * An object representing the Git config file.\n@@ -63,7 +63,7 @@\n \t * @param cfgLocation\n \t *            path of the file to load (or save).\n \t */\n-\tpublic RepositoryConfig(final Config base, final File cfgLocation) {\n+\tpublic RepositoryConfig(final Config base, final Entry cfgLocation) {\n \t\tsuper(base, cfgLocation);\n \t}\n \ndiff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java\nindex 261e3d1..a8c0758 100644\n--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java\n+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java\n@@ -37,14 +37,17 @@\n \n package org.eclipse.jgit.util;\n \n+import java.io.ByteArrayOutputStream;\n import java.io.EOFException;\n import java.io.File;\n import java.io.FileInputStream;\n import java.io.FileNotFoundException;\n import java.io.IOException;\n import java.io.InputStream;\n+import java.io.OutputStream;\n import java.nio.ByteBuffer;\n import java.nio.channels.FileChannel;\n+import org.eclipse.jgit.io.Entry;\n \n /** Conversion utilities for network byte order handling. */\n public final class NB {\n@@ -97,6 +100,38 @@\n \t\t}\n \t}\n \n+  public static final byte[] readFully(final Entry path)\n+\t\t\tthrows IOException {\n+    return readFully(path, Integer.MAX_VALUE);\n+  }\n+\n+\tpublic static final byte[] readFully(final Entry path, final int max)\n+\t\t\tthrows IOException {\n+\t\tfinal InputStream in = path.getInputStream();\n+\t\ttry {\n+\t\t\tfinal long sz = path.length();\n+      byte[] buf;\n+      if(sz > -1) {\n+        if (sz > max)\n+          throw new IOException(\"File is too large: \" + path);\n+        buf = new byte[(int) sz];\n+        readFully(in, buf, 0, buf.length);\n+      }\n+      else {\n+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();\n+        read(in, outputStream);\n+        buf = outputStream.toByteArray();\n+      }\n+\t\t\treturn buf;\n+\t\t} finally {\n+\t\t\ttry {\n+\t\t\t\tin.close();\n+\t\t\t} catch (IOException ignored) {\n+\t\t\t\t// ignore any close errors, this was a read only stream\n+\t\t\t}\n+\t\t}\n+\t}\n+\n \t/**\n \t * Read the entire byte array into memory, or throw an exception.\n \t * \n@@ -113,8 +148,9 @@\n \t * @throws IOException\n \t *             there was an error reading from the stream.\n \t */\n-\tpublic static void readFully(final InputStream fd, final byte[] dst,\n+\tpublic static int readFully(final InputStream fd, final byte[] dst,\n \t\t\tint off, int len) throws IOException {\n+    int initOff = off;\n \t\twhile (len > 0) {\n \t\t\tfinal int r = fd.read(dst, off, len);\n \t\t\tif (r <= 0)\n@@ -122,6 +158,22 @@ public static void readFully(final InputStream fd, final byte[] dst,\n \t\t\toff += r;\n \t\t\tlen -= r;\n \t\t}\n+    return off - initOff;\n+\t}\n+\n+\tpublic static int read(final InputStream fd, final OutputStream dst)\n+          throws IOException {\n+    int size = 0;\n+    int r = 1;\n+    byte[] bytes = new byte[1000];\n+\t\twhile (r > 0) {\n+\t\t\tr = fd.read(bytes, 0, 1000);\n+      if(r > 0) {\n+        dst.write(bytes, 0, r);\n+        size += r;\n+      }\n+\t\t}\n+    return size;\n \t}\n \n \t/**\n-- \n1.6.2.1\n"}]}