Git development
 help / color / mirror / Atom feed
* Re: Installing full fledged git on solaris?
From: Dilip M @ 2009-10-11 13:38 UTC (permalink / raw)
  To: Ben Walton; +Cc: git
In-Reply-To: <1255265817-sup-4123@ntdws12.chass.utoronto.ca>

On Sun, Oct 11, 2009 at 6:42 PM, Ben Walton <bwalton@artsci.utoronto.ca> wrote:
...snip...

> If your intent is to build it yourself, let me know and I'll share
> with you the build recipe I use, which will outline (within the CSW
> stack) which packages are used for compilation and which for runtime
> dependencies.  You should be able to translate it to use the
> libs/tools available to solaris 10 (that aren't in 8, which we also
> support).

Please share...

-- 
Dilip

^ permalink raw reply

* Re: combine git repo historically
From: Christian Couder @ 2009-10-11 13:43 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Jakub Narebski, bill lam, git, Christian Couder
In-Reply-To: <200910111507.06926.j.sixt@viscovery.net>

On Sunday 11 October 2009, Johannes Sixt wrote:
> On Sonntag, 11. Oktober 2009, Jakub Narebski wrote:
> > Christian Couder <chriscool@tuxfamily.org> writes:
> > > $ git checkout -b repo1-branch1 remote/repo1/branch1
> > > $ git checkout N -- .
> > > $ export GIT_AUTHOR_NAME=<author name of commit N>
> > > $ export GIT_AUTHOR_EMAIL=<author email of commit N>
> > > $ export GIT_AUTHOR_DATE=<date of commit N>
> > > $ git commit -a
>
> This would not preserver the committer, but in particular the committer
> date is rather important for history traversal. You really don't want to
> change it. I used a much more elaborate pipleine involving
> git-commit-tree because I
>
> did not think about this simple procedure:
> >  $ git cat-file commit N > COMMIT_N
> >[ $ edit COMMIT_N  ]
> >  $ git hash-object -t commit -w COMMIT_N
>
> Thanks for this tip, Jakub.
>
> Christian, one thing that worries me is that 'git cat-file commit foo'
> returns the replacement (bar) instead of the original (foo). Is it
> intended? 

Yes it is intended. "git replace" was designed so that the original objects 
are not replaced only when reachability traversal (prune, pack transfer and 
fsck) wants to read the commit. See:

http://article.gmane.org/gmane.comp.version-control.git/104776/

> There is no way to retrieve the original commit using plumbing 
> unless the replacement is removed. Am I right?

I think you are right, but a flag could be easily added to some commands to 
retreive original objects. Or you can remove the replacement, retrieve the 
object and then put back the replacement.

Best regards,
Christian.

^ permalink raw reply

* [PATCH] Makefile: clean block-sha1/ directory instead of mozilla-sha1/
From: Carlos R. Mafra @ 2009-10-11 13:32 UTC (permalink / raw)
  To: git


'make clean' should remove the object files from block-sha1/
instead of the non-existent mozilla-sha1/ directory.

Signed-off-by: Carlos R. Mafra <crmafra@aei.mpg.de>
---
 Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Makefile b/Makefile
index fea237b..42b7d60 100644
--- a/Makefile
+++ b/Makefile
@@ -1827,7 +1827,7 @@ distclean: clean
 	$(RM) configure
 
 clean:
-	$(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o \
+	$(RM) *.o block-sha1/*.o arm/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o \
 		$(LIB_FILE) $(XDIFF_LIB)
 	$(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
 	$(RM) $(TEST_PROGRAMS)
-- 
1.6.5

^ permalink raw reply related

* [JGit-io-RFC-PATCH v2 1/4] Introduce a new module for IO SPI of JGit
From: imyousuf @ 2009-10-11 14:07 UTC (permalink / raw)
  To: git; +Cc: spearce, egit-dev, Imran M Yousuf

From: Imran M Yousuf <imyousuf@smartitengineering.com>

The reason for having a separate module is quite obvious, the IO SPI
providers need not have to depend on the whole JGit but rather only on
the SPI itself. As of the initial implementation the SPI will also contain
the default implementation - local file system provider.

Extract maven POM file to a common file to encapsulate the common setting
and configuration to be used across all maven modules for JGit.

Signed-off-by: Imran M Yousuf <imyousuf@smartitengineering.com>
---
 jgit-maven/jgit-io/pom.xml    |   65 +++++++++
 jgit-maven/jgit/pom.xml       |  287 ++++++++++-------------------------------
 jgit-maven/{jgit => }/pom.xml |   31 +----
 3 files changed, 143 insertions(+), 240 deletions(-)
 create mode 100644 jgit-maven/jgit-io/pom.xml
 rewrite jgit-maven/jgit/pom.xml (68%)
 rename jgit-maven/{jgit => }/pom.xml (90%)

diff --git a/jgit-maven/jgit-io/pom.xml b/jgit-maven/jgit-io/pom.xml
new file mode 100644
index 0000000..f197f58
--- /dev/null
+++ b/jgit-maven/jgit-io/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+All rights reserved.
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following
+conditions are met:
+
+Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided
+with the distribution.
+
+Neither the name of the Eclipse Foundation, Inc. nor the
+names of its contributors may be used to endorse or promote
+products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.eclipse</groupId>
+        <artifactId>jgit-parent</artifactId>
+        <version>0.6.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.eclipse</groupId>
+    <artifactId>jgit-io</artifactId>
+    <packaging>jar</packaging>
+    <name>jgit-io</name>
+    <build>
+        <sourceDirectory>../../org.eclipse.jgit.io/src/</sourceDirectory>
+        <testResources>
+            <testResource>
+                <directory>../../org.eclipse.jgit.test/tst-rsrc/</directory>
+            </testResource>
+        </testResources>
+        <testSourceDirectory>../../org.eclipse.jgit.io/tst/</testSourceDirectory>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/jgit-maven/jgit/pom.xml b/jgit-maven/jgit/pom.xml
dissimilarity index 68%
index d8772ad..9eb5758 100644
--- a/jgit-maven/jgit/pom.xml
+++ b/jgit-maven/jgit/pom.xml
@@ -1,216 +1,71 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-All rights reserved.
-Redistribution and use in source and binary forms, with or
-without modification, are permitted provided that the following
-conditions are met:
-
-Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following
-disclaimer in the documentation and/or other materials provided
-with the distribution.
-
-Neither the name of the Eclipse Foundation, Inc. nor the
-names of its contributors may be used to endorse or promote
-products derived from this software without specific prior
-written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
-CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.eclipse</groupId>
-    <artifactId>jgit</artifactId>
-    <packaging>jar</packaging>
-    <version>0.6.0-SNAPSHOT</version>
-    <name>jgit</name>
-    <url>http://repo.or.cz/w/jgit.git</url>
-    <mailingLists>
-        <mailingList>
-            <name>GIT Mailing List</name>
-            <post>git@vger.kernel.org</post>
-            <archive>http://marc.info/?l=git</archive>
-        </mailingList>
-    </mailingLists>
-    <description>Pure Java implementation of Git</description>
-    <developers>
-        <developer>
-            <name>Shawn O. Pearce</name>
-            <email>spearce@spearce.org</email>
-            <roles>
-                <role>Maintainer</role>
-            </roles>
-        </developer>
-        <developer>
-            <name>Robin Rosenberg</name>
-            <email>robin.rosenberg@dewire.com</email>
-            <roles>
-                <role>Maintainer</role>
-            </roles>
-        </developer>
-        <developer>
-            <name>Dave Watson</name>
-            <email>dwatson@mimvista.com</email>
-            <roles>
-                <role>Developer</role>
-            </roles>
-        </developer>
-        <developer>
-            <name>Roger C. Soares</name>
-            <email>rogersoares@intelinet.com.br</email>
-            <roles>
-                <role>Developer</role>
-            </roles>
-	</developer>
-	<developer>
-            <name>Marek Zawirski</name>
-            <email>marek.zawirski@gmail.com</email>
-            <roles>
-                <role>Developer</role>
-            </roles>
-        </developer>
-        <developer>
-            <name>Charles O'Farrell</name>
-            <email>charleso@charleso.org</email>
-            <roles>
-                <role>Contributor</role>
-            </roles>
-        </developer>
-        <developer>
-            <name>Imran M Yousuf</name>
-            <email>imyousuf@smartitengineering.com</email>
-            <organization>Smart IT Engineering</organization>
-            <roles>
-                <role>Contributor</role>
-            </roles>
-        </developer>
-    </developers>
-    <licenses>
-        <license>
-            <name>Eclipse Distribution License (New BSD License)</name>
-            <comments>
-                All rights reserved.
-                Redistribution and use in source and binary forms, with or
-                without modification, are permitted provided that the following
-                conditions are met:
-
-                Redistributions of source code must retain the above copyright
-                notice, this list of conditions and the following disclaimer.
-
-                Redistributions in binary form must reproduce the above
-                copyright notice, this list of conditions and the following
-                disclaimer in the documentation and/or other materials provided
-                with the distribution.
-
-                Neither the name of the Eclipse Foundation, Inc. nor the
-                names of its contributors may be used to endorse or promote
-                products derived from this software without specific prior
-                written permission.
-
-                THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
-                CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-                INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-                OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-                ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-                CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-                SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-                NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-                LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-                CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-                STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-                ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-                ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-            </comments>
-        </license>
-    </licenses>
-    <build>
-        <sourceDirectory>../../org.eclipse.jgit/src/</sourceDirectory>
-        <testResources>
-            <testResource>
-                <directory>../../org.eclipse.jgit.test/tst-rsrc/</directory>
-            </testResource>
-        </testResources>
-        <testSourceDirectory>../../org.eclipse.jgit.test/tst/</testSourceDirectory>
-        <plugins>
-            <plugin>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <version>2.0.2</version>
-                <configuration>
-                    <source>1.5</source>
-                    <target>1.5</target>
-                    <encoding>UTF-8</encoding>
-                </configuration>
-            </plugin>
-            <plugin>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <version>2.4.2</version>
-                <configuration>
-                    <includes>
-                        <include>**/*Test.java</include>
-                        <include>**/*TestCase.java</include>
-                        <include>**/T000*.java</include>
-                    </includes>
-                </configuration>
-           </plugin>
-           <plugin>
-               <artifactId>maven-source-plugin</artifactId>
-               <executions>
-                   <execution>
-                       <goals>
-                           <goal>jar</goal>
-                       </goals>
-                   </execution>
-               </executions>
-            </plugin>
-            <plugin>
-                <artifactId>maven-javadoc-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-    <dependencies>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>3.8.1</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.jcraft</groupId>
-            <artifactId>jsch</artifactId>
-            <version>0.1.41</version>
-            <scope>compile</scope>
-        </dependency>
-    </dependencies>
-    <distributionManagement>
-        <snapshotRepository>
-            <id>jgit-maven-snapshot-repository</id>
-            <name>JGit Maven Snapshot Repository</name>
-            <url>dav:https://egit.googlecode.com/svn/maven/snapshot-repository/</url>
-            <uniqueVersion>true</uniqueVersion>
-        </snapshotRepository>
-    </distributionManagement>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+All rights reserved.
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following
+conditions are met:
+
+Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided
+with the distribution.
+
+Neither the name of the Eclipse Foundation, Inc. nor the
+names of its contributors may be used to endorse or promote
+products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.eclipse</groupId>
+        <artifactId>jgit-parent</artifactId>
+        <version>0.6.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.eclipse</groupId>
+    <artifactId>jgit</artifactId>
+    <packaging>jar</packaging>
+    <name>jgit</name>
+    <build>
+        <sourceDirectory>../../org.eclipse.jgit/src/</sourceDirectory>
+        <testResources>
+            <testResource>
+                <directory>../../org.eclipse.jgit.test/tst-rsrc/</directory>
+            </testResource>
+        </testResources>
+        <testSourceDirectory>../../org.eclipse.jgit.test/tst/</testSourceDirectory>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.jcraft</groupId>
+            <artifactId>jsch</artifactId>
+            <version>0.1.41</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/jgit-maven/jgit/pom.xml b/jgit-maven/pom.xml
similarity index 90%
rename from jgit-maven/jgit/pom.xml
rename to jgit-maven/pom.xml
index d8772ad..bac9629 100644
--- a/jgit-maven/jgit/pom.xml
+++ b/jgit-maven/pom.xml
@@ -37,10 +37,10 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.eclipse</groupId>
-    <artifactId>jgit</artifactId>
-    <packaging>jar</packaging>
+    <artifactId>jgit-parent</artifactId>
+    <packaging>pom</packaging>
     <version>0.6.0-SNAPSHOT</version>
-    <name>jgit</name>
+    <name>JGit</name>
     <url>http://repo.or.cz/w/jgit.git</url>
     <mailingLists>
         <mailingList>
@@ -141,13 +141,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         </license>
     </licenses>
     <build>
-        <sourceDirectory>../../org.eclipse.jgit/src/</sourceDirectory>
-        <testResources>
-            <testResource>
-                <directory>../../org.eclipse.jgit.test/tst-rsrc/</directory>
-            </testResource>
-        </testResources>
-        <testSourceDirectory>../../org.eclipse.jgit.test/tst/</testSourceDirectory>
         <plugins>
             <plugin>
                 <artifactId>maven-compiler-plugin</artifactId>
@@ -191,20 +184,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
             </plugin>
         </plugins>
     </build>
-    <dependencies>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>3.8.1</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.jcraft</groupId>
-            <artifactId>jsch</artifactId>
-            <version>0.1.41</version>
-            <scope>compile</scope>
-        </dependency>
-    </dependencies>
     <distributionManagement>
         <snapshotRepository>
             <id>jgit-maven-snapshot-repository</id>
@@ -213,4 +192,8 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
             <uniqueVersion>true</uniqueVersion>
         </snapshotRepository>
     </distributionManagement>
+    <modules>
+        <module>jgit</module>
+        <module>jgit-io</module>
+    </modules>
 </project>
-- 
1.6.2.1

^ permalink raw reply related

* [JGit-io-RFC-PATCH v2 2/4] Add JGit IO SPI and default implementation
From: imyousuf @ 2009-10-11 14:07 UTC (permalink / raw)
  To: git; +Cc: spearce, egit-dev, Imran M Yousuf
In-Reply-To: <1255270073-14205-1-git-send-email-imyousuf@gmail.com>

From: Imran M Yousuf <imyousuf@smartitengineering.com>

The SPI mainly focus's in providing an API to JGit to be able to perform
similar operations to that of java.io.File. All direct I/O is based on the
java.io.Input/OutputStream classes.

Different JGit IO SPI provider is designed to be URI scheme based and thus
the default implementation is that of "file" scheme. SPI provider will be
integrated by their respective users in a manner similar to that of JDBC
driver registration. There is a SystemStorageManager that has similar
registration capabilities and the system storage providers should be
registered with the manager in one of the provided ways.

This SPI is based on the initial requirements for switching to it and thus
this SPI will change as required during full migration to it.

Signed-off-by: Imran M Yousuf <imyousuf@smartitengineering.com>
---
 .../src/org/eclipse/jgit/io/Entry.java             |  148 +++++++++++++
 .../src/org/eclipse/jgit/io/StorageSystem.java     |   57 +++---
 .../org/eclipse/jgit/io/StorageSystemManager.java  |  154 ++++++++++++++
 .../eclipse/jgit/io/localfs/LocalFileEntry.java    |  219 ++++++++++++++++++++
 .../eclipse/jgit/io/localfs/LocalFileSystem.java   |   51 +++--
 5 files changed, 577 insertions(+), 52 deletions(-)
 create mode 100644 org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
 copy org.eclipse.jgit.test/tst/org/eclipse/jgit/util/JGitTestUtil.java => org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java (62%)
 create mode 100644 org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystemManager.java
 create mode 100644 org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
 copy org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java => org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java (65%)

diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
new file mode 100644
index 0000000..cd69172
--- /dev/null
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2009, Imran M Yousuf <imyousuf@smartitengineering.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+
+/**
+ * Represents each entry in a storage system. For example, in a local filesystem
+ * storage it would represent {@link java.io.File}. Here the storage system
+ * mainly refers to where repository meta data such as git objects, ref logs,
+ * packs are stored; for example a '.git' directory and all its contents in a
+ * clone repo would correspond to an entry.
+ * @author Imran M Yousuf (imyousuf at smartitengineering.com)
+ * @since 0.6
+ */
+public interface Entry {
+
+  /**
+   * Retrieves the name of the entry
+   * @return Name of the entry
+   */
+  public String getName();
+
+  /**
+   * Retrieves the absolute path of the entry.
+   * @return Absoluth path
+   */
+  public String getAbsolutePath();
+
+  /**
+   * Retrieves whether the entry represents a directory or not
+   * @return True if represents a directory else false
+   */
+  public boolean isDirectory();
+
+  /**
+   * Signifies whether the entry is a new one or being read from the
+   * persistent storage
+   * @return True if being read form storage else false
+   */
+  public boolean isExists();
+
+  /**
+   * Make directories upto the entry represented by this instance, provided
+   * that this instance itself is a directory.
+   * @return True if directories were created.
+   */
+  public boolean mkdirs();
+
+  /**
+   * Retrieves the URI of this entry. URI in this case acts as a primary key
+   * to identify an entry.
+   * @return URI to identify this entry instance
+   */
+  public URI getURI();
+
+  /**
+   * Retrieves the length of the entry if its predictable.
+   * @return < 0 if the length is unpredictable else the length of the entry's
+   *         content
+   */
+  public long length();
+
+  /**
+   * Retrieves the InputStream for reading the content of the entry
+   * @return Input stream to read entry content
+   * @throws IOException If no such file exists or there is any other error
+   */
+  public InputStream getInputStream()
+          throws IOException;
+
+  /**
+   * Retrieves the OutputStream for writing content into the entry. It can be
+   * opened to either overwrite it or append to it.
+   * @param overwrite False if to write in append mode else true
+   * @return Output stream to write content to
+   * @throws IOException If no such file exists in append mode or there is any
+   *                     error in retrieving it.
+   */
+  public OutputStream getOutputStream(boolean overwrite)
+          throws IOException;
+
+  /**
+   * Retrieve all the child entries of this entries if its a directory.
+   * @return If not a directory then a empty array else array of sub-entries.
+   */
+  public Entry[] getChildren();
+
+  /**
+   * Retrieve a specific child of an entry. It will basically match
+   * {@link Entry#getName() name} of the children to find and that too only
+   * the direct children.
+   * @param name Name of the child to find
+   * @return If child is not found then NULL or else the child specified by
+   *         the name
+   */
+  public Entry getChild(String name);
+
+  /**
+   * Retrieve the parent entry of the current entry.
+   * @return NULL if no parent or else the direct parent of the current entry
+   */
+  public Entry getParent();
+
+  /**
+   * Retrieve the storage system this entry either is from or will be
+   * persisted to.
+   * @return Storage system of the entry, will never be NULL.
+   */
+  public StorageSystem getStorageSystem();
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/JGitTestUtil.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
similarity index 62%
copy from org.eclipse.jgit.test/tst/org/eclipse/jgit/util/JGitTestUtil.java
copy to org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
index b259185..9f45cb3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/JGitTestUtil.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com>
+ * Copyright (C) 2009, Imran M Yousuf <imyousuf@smartitengineering.com>
  *
  * All rights reserved.
  *
@@ -34,38 +34,35 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+package org.eclipse.jgit.io;
 
-package org.eclipse.jgit.util;
+import java.net.URI;
 
-import java.io.File;
-import java.net.URISyntaxException;
-import java.net.URL;
-
-public abstract class JGitTestUtil {
-	public static final String CLASSPATH_TO_RESOURCES = "org/eclipse/jgit/test/resources/";
+/**
+ * SPI providing access to the underlying storage system. Each provider is
+ * differentiated using their {@link StorageSystem#getURIProtocol() URI Protocol}.
+ * @author Imran M Yousuf (imyousuf at smartitengineering.com)
+ * @since 0.6
+ */
+public interface StorageSystem {
 
-	private JGitTestUtil() {
-		throw new UnsupportedOperationException();
-	}
+  /**
+   * Returns the supported scheme of this storage system.
+   * @return Scheme supported by this storage system.
+   * @see {@link http://tr.im/BiQ0 URI Scheme}
+   */
+  public String getURIScheme();
 
-	public static File getTestResourceFile(final String fileName) {
-		if (fileName == null || fileName.length() <= 0) {
-			return null;
-		}
-		final URL url = cl().getResource(CLASSPATH_TO_RESOURCES + fileName);
-		if (url == null) {
-			// If URL is null then try to load it as it was being
-			// loaded previously
-			return new File("tst", fileName);
-		}
-		try {
-			return new File(url.toURI());
-		} catch(URISyntaxException e) {
-			return new File(url.getPath());
-		}
-	}
+  /**
+   * Retrieve an entry using its URI
+   * @param uri URI to retrieve the entry for.
+   * @return Entry representing the URI
+   */
+  public Entry getEntry(URI uri);
 
-	private static ClassLoader cl() {
-		return JGitTestUtil.class.getClassLoader();
-	}
+  /**
+   * Retrieve the current working directory from the file system if any.
+   * @return Entry for current working directory.
+   */
+  public Entry getWorkingDirectory();
 }
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystemManager.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystemManager.java
new file mode 100644
index 0000000..999122e
--- /dev/null
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystemManager.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2009, Imran M Yousuf <imyousuf@smartitengineering.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.io;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Hashtable;
+import java.util.Map;
+import org.eclipse.jgit.io.localfs.LocalFileSystem;
+
+/**
+ * Manager that registers different storage system for different {@link URI}
+ * schemes and serves users with {@link Entry} or {@link StorageSystem} as URI
+ * schemes request.
+ * @author Imran M Yousuf (imyousuf at smartitengineering.com)
+ * @since 0.6
+ */
+public class StorageSystemManager {
+
+  /**
+   * Map to act as registrar for all registered schemes
+   */
+  private static Map<String, StorageSystem> storageSystemMap;
+
+  /**
+   * Initialize the registrar and and load the instance for default storage,
+   * i.e. the local file system.
+   */
+  static {
+    storageSystemMap = new Hashtable<String, StorageSystem>();
+    try {
+      register(LocalFileSystem.class);
+    }
+    catch (Exception ex) {
+      ex.printStackTrace();
+    }
+  }
+
+  /**
+   * Retrieves the storage system for a given scheme from the registrar.
+   * @param scheme Scheme to retrieve; it should never be null
+   * @return Storage system representing the scheme.
+   * @throws IOException If scheme is null or scheme does not exist.
+   */
+  public static StorageSystem getStorageSystem(String scheme)
+          throws IOException {
+    if (scheme != null && storageSystemMap.containsKey(scheme)) {
+      return storageSystemMap.get(scheme);
+    }
+    else {
+      throw new IOException("Scheme ( " + scheme +
+                            " ) not registered with manager!");
+    }
+  }
+
+  /**
+   * Load an storage system entry using its respective URI.
+   * @param uri URI to retrieve the storage system entity for
+   * @return The entry in the storage system for the requested URI
+   * @throws IOException If scheme does not exist.
+   * @throws NullPointerException If uri is null
+   */
+  public static Entry getEntry(URI uri)
+          throws IOException,
+                 NullPointerException {
+    String scheme = uri.getScheme();
+    return getStorageSystem(scheme).getEntry(uri);
+  }
+
+  /**
+   * Registers a {@link StorageSystem} implementaiton against its schema into
+   * the registrar using the implementions fully qualified class name and its
+   * non-args constructor.
+   * @param storageSystemClassName The class names representation is string.
+   * @throws ClassNotFoundException If no class is found with the name specified
+   * @throws InstantiationException If there is any exception during
+   *                                initialization
+   * @throws IllegalAccessException If the class dpes not have a public
+   *                                non-args constructor
+   * @throws ClassCastException If the class does implement {@link StorageSystem}
+   */
+  public static void register(String storageSystemClassName)
+          throws ClassNotFoundException,
+                 InstantiationException,
+                 IllegalAccessException,
+                 ClassCastException {
+    register((Class<? extends StorageSystem>) Class.forName(
+            storageSystemClassName));
+  }
+
+  /**
+   * Registers a {@link StorageSystem} implementaiton against its schema into
+   * the registrar using the implemention class name and its non-args constructor.
+   * @param storageSystemClassName The class names representation is string.
+   * @throws InstantiationException If there is any exception during
+   *                                initialization
+   * @throws IllegalAccessException If the class dpes not have a public
+   *                                non-args constructor
+   */
+  public static void register(
+          Class<? extends StorageSystem> storageSystemClass)
+          throws InstantiationException,
+                 IllegalAccessException {
+    if (storageSystemClass != null) {
+      StorageSystem system = storageSystemClass.newInstance();
+      register(system);
+    }
+  }
+
+  /**
+   * Registers a {@link StorageSystem} instance into the reigstrar. It would be
+   * particularly useful if system does not have a non-args constructor.
+   * @param system System to register in the manager
+   */
+  public static void register(StorageSystem system) {
+    if (system != null) {
+      storageSystemMap.put(system.getURIScheme(), system);
+    }
+  }
+}
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
new file mode 100644
index 0000000..99df831
--- /dev/null
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2009, Imran M Yousuf <imyousuf@smartitengineering.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.io.localfs;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import org.eclipse.jgit.io.Entry;
+import org.eclipse.jgit.io.StorageSystem;
+import org.eclipse.jgit.io.StorageSystemManager;
+
+/**
+ * Entry implementation for local file system. This class should not be
+ * initialized directly unless its a {@link LocalFileSystem}. SPI users should
+ * use {@link StorageSystemManager#getEntry(java.net.URI)} to get the first
+ * {@link Entry} and then traverse from there onwards.
+ * @author Imran M Yousuf (imyousuf at smartitengineering.com)
+ * @since 0.6
+ */
+public class LocalFileEntry
+        implements Entry {
+
+  private File localFile;
+  private StorageSystem storageSystem;
+
+  /**
+   * Contructs an entry based of on the local file system storage and a file
+   * that will be represented by this entry.
+   * @param localFile File represented by this entry
+   * @param storageSystem Storage system of the entry
+   * @throws IllegalArgumentException If either argument is NULL
+   */
+  protected LocalFileEntry(File localFile,
+                           StorageSystem storageSystem)
+          throws IllegalArgumentException {
+    setLocalFile(localFile);
+    setStorageSystem(storageSystem);
+  }
+
+  /**
+   * Sets the storage system instance for this entry.
+   * @param storageSystem Storage system
+   * @throws IllegalArgumentException IF storageSystem is null
+   */
+  protected void setStorageSystem(StorageSystem storageSystem)
+          throws IllegalArgumentException {
+    if (storageSystem == null) {
+      throw new IllegalArgumentException("Storage system can't be NULL!");
+    }
+    this.storageSystem = storageSystem;
+  }
+
+  /**
+   * Retrieves the file being adapted by this entry.
+   * @return File being adapted
+   */
+  public File getLocalFile() {
+    return localFile;
+  }
+
+  /**
+   * Sets the file which is to be used as adapt from this instance by this
+   * implementation
+   * @param localFile Local file being adapted by this instance
+   * @throws IllegalArgumentException If localFile is null
+   */
+  protected void setLocalFile(File localFile)
+          throws IllegalArgumentException {
+    if (localFile == null) {
+      throw new IllegalArgumentException(
+              "Local file to be set can't be NULL");
+    }
+    this.localFile = localFile;
+  }
+
+  public String getName() {
+    return getLocalFile().getName();
+  }
+
+  public String getAbsolutePath() {
+    return getLocalFile().getAbsolutePath();
+  }
+
+  public boolean isDirectory() {
+    return getLocalFile().isDirectory();
+  }
+
+  public boolean isExists() {
+    return getLocalFile().exists();
+  }
+
+  public boolean mkdirs() {
+    return getLocalFile().mkdirs();
+  }
+
+  public URI getURI() {
+    return getLocalFile().toURI();
+  }
+
+  public InputStream getInputStream()
+          throws IOException {
+    if (getLocalFile().exists()) {
+      try {
+        return new FileInputStream(getLocalFile());
+      }
+      catch (FileNotFoundException ex) {
+        throw ex;
+      }
+    }
+    else {
+      throw new FileNotFoundException("File does not exists!");
+    }
+  }
+
+  public OutputStream getOutputStream(boolean overwrite)
+          throws IOException {
+    try {
+      if (!isExists()) {
+
+        return new FileOutputStream(getLocalFile());
+      }
+      else {
+        if (overwrite) {
+          return new FileOutputStream(getLocalFile());
+        }
+        else {
+          return new FileOutputStream(getLocalFile(), true);
+        }
+      }
+    }
+    catch (FileNotFoundException ex) {
+      throw ex;
+    }
+  }
+
+  public Entry[] getChildren() {
+    File[] children = getLocalFile().listFiles();
+    if (children == null || children.length == 0) {
+      return new Entry[0];
+    }
+    else {
+      Entry[] entries = new Entry[children.length];
+      for (int i = 0; i < children.length; ++i) {
+        entries[i] = getStorageSystem().getEntry(children[i].toURI());
+      }
+      return entries;
+    }
+  }
+
+  public Entry getChild(String name) {
+    if (name == null || name.length() == 0) {
+      return null;
+    }
+    Entry[] children = getChildren();
+    for (Entry entry : children) {
+      if (name.equals(entry.getName())) {
+        return entry;
+      }
+    }
+    return null;
+  }
+
+  public Entry getParent() {
+    File parent = getLocalFile().getParentFile();
+    if (parent == null) {
+      return null;
+    }
+    else {
+      return getStorageSystem().getEntry(parent.toURI());
+    }
+  }
+
+  public StorageSystem getStorageSystem() {
+    return storageSystem;
+  }
+
+  public long length() {
+    return getLocalFile().length();
+  }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
similarity index 65%
copy from org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java
copy to org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
index 49aa418..d0cb536 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, Google Inc.
+ * Copyright (C) 2009, Imran M Yousuf <imyousuf@smartitengineering.com>
  *
  * All rights reserved.
  *
@@ -34,31 +34,38 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
-package org.eclipse.jgit.pgm;
+package org.eclipse.jgit.io.localfs;
 
 import java.io.File;
+import java.net.URI;
+import org.eclipse.jgit.io.Entry;
+import org.eclipse.jgit.io.StorageSystem;
+
+/**
+ * Implementation of storage system for the local file system.
+ * @author Imran M Yousuf (imyousuf at smartitengineering.com)
+ * @since 0.6
+ */
+public class LocalFileSystem
+        implements StorageSystem {
 
-import org.kohsuke.args4j.Option;
-import org.eclipse.jgit.lib.Repository;
+  public static final String PROTOCOL_FILE = "file";
 
-@Command(common = true, usage = "Create an empty git repository")
-class Init extends TextBuiltin {
-	@Option(name = "--bare", usage = "Create a bare repository")
-	private boolean bare;
+  public String getURIScheme() {
+    return PROTOCOL_FILE;
+  }
 
-	@Override
-	protected final boolean requiresRepository() {
-		return false;
-	}
+  public Entry getEntry(URI uri) {
+    if (uri == null) {
+      return null;
+    }
+    else {
+      return new LocalFileEntry(new File(uri), this);
+    }
+  }
 
-	@Override
-	protected void run() throws Exception {
-		if (gitdir == null)
-			gitdir = new File(bare ? "." : ".git");
-		db = new Repository(gitdir);
-		db.create(bare);
-		out.println("Initialized empty Git repository in "
-				+ gitdir.getAbsolutePath());
-	}
+  public Entry getWorkingDirectory() {
+    String curDir = System.getProperty("user.dir");
+    return new LocalFileEntry(new File(curDir), this);
+  }
 }
-- 
1.6.2.1

^ permalink raw reply related

* [JGit-io-RFC-PATCH v2 4/4] Add locking capability to the IO SPI based on Java Concurrency Lock API
From: imyousuf @ 2009-10-11 14:07 UTC (permalink / raw)
  To: git; +Cc: spearce, egit-dev, Imran M Yousuf
In-Reply-To: <1255270073-14205-3-git-send-email-imyousuf@gmail.com>

From: Imran M Yousuf <imyousuf@smartitengineering.com>

The lock implementation for local FS has 2 layer for locking, first JVM
level using the Java Concurrency API and second level is in local FS and
its Git specific *.lock files.

This change basically replaces the LockFile implementation in JGit Lib.

Signed-off-by: Imran M Yousuf <imyousuf@smartitengineering.com>
---
 .../src/org/eclipse/jgit/io/Entry.java             |   44 ++++-
 .../eclipse/jgit/io/localfs/LocalFileEntry.java    |  177 +++++++++++++++++-
 .../org/eclipse/jgit/io/lock/AbstractLockable.java |  199 ++++++++++++++++++++
 .../{StorageSystem.java => lock/LockManager.java}  |   96 ++++++----
 .../src/org/eclipse/jgit/io/lock/Lockable.java     |   26 ++--
 5 files changed, 486 insertions(+), 56 deletions(-)
 create mode 100644 org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/AbstractLockable.java
 copy org.eclipse.jgit.io/src/org/eclipse/jgit/io/{StorageSystem.java => lock/LockManager.java} (53%)
 copy org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryAdapter.java => org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/Lockable.java (77%)

diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
index 5256815..4c264db 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
@@ -36,6 +36,7 @@
  */
 package org.eclipse.jgit.io;
 
+import org.eclipse.jgit.io.lock.Lockable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -50,7 +51,8 @@
  * @author Imran M Yousuf (imyousuf at smartitengineering.com)
  * @since 0.6
  */
-public interface Entry {
+public interface Entry
+        extends Lockable {
 
   /**
    * Retrieves the name of the entry
@@ -138,12 +140,26 @@ public InputStream getInputStream()
           throws IOException;
 
   /**
-   * Retrieves the OutputStream for writing content into the entry. It can be
-   * opened to either overwrite it or append to it.
+   * Retrieves a locked channeled output stream. When the output stream is closed
+   * the channel is released automatically.
+   * @param overwrite False if to write in append mode else true
+   * @param lock Whether to attain lock or not
+   * @return Output stream to write content to
+   * @throws IOException If no such entry exists in append mode or there is any
+   *                     error in retrieving it or retrieving the lock.
+   */
+  public OutputStream getOutputStream(boolean overwrite,
+                                      boolean lock)
+          throws IOException;
+
+  /**
+   * Behaves in as if {@link Entry#getOutputStream(boolean, boolean)} is called
+   * with lock param as false.
    * @param overwrite False if to write in append mode else true
    * @return Output stream to write content to
    * @throws IOException If no such entry exists in append mode or there is any
    *                     error in retrieving it.
+   * @see Entry#getOutputStream(boolean, boolean) 
    */
   public OutputStream getOutputStream(boolean overwrite)
           throws IOException;
@@ -171,6 +187,28 @@ public OutputStream getOutputStream(boolean overwrite)
   public Entry getParent();
 
   /**
+   * Create this entry in the underlying system storage.
+   * @return True if created else false
+   * @throws IOException If any I/O during creation
+   */
+  public boolean createNew()
+          throws IOException;
+
+  /**
+   * Delete current entry
+   * @return True if deleted successfully else false
+   * @throws IOException If any error during writing
+   */
+  public boolean delete()
+          throws IOException;
+
+  /**
+   * Retrieve the entry for lock file
+   * @return Null if lock is attained else null
+   */
+  public Entry getLockEntry();
+
+  /**
    * Retrieve the storage system this entry either is from or will be
    * persisted to.
    * @return Storage system of the entry, will never be NULL.
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
index 4ef3076..f6c84c1 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
@@ -45,9 +45,13 @@
 import java.io.OutputStream;
 import java.lang.reflect.InvocationTargetException;
 import java.net.URI;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+import java.util.concurrent.TimeUnit;
 import org.eclipse.jgit.io.Entry;
 import org.eclipse.jgit.io.StorageSystem;
 import org.eclipse.jgit.io.StorageSystemManager;
+import org.eclipse.jgit.io.lock.AbstractLockable;
 
 /**
  * Entry implementation for local file system. This class should not be
@@ -58,10 +62,15 @@
  * @since 0.6
  */
 public class LocalFileEntry
+        extends AbstractLockable
         implements Entry {
 
+  public static final String LOCK_FILE_EXT = ".lock";
+  public static final long DEFAULT_WAIT_TIME_MS = 200;
   private File localFile;
   private LocalFileSystem storageSystem;
+  private File localLockFile;
+  private String lockFileName;
 
   /**
    * Contructs an entry based of on the local file system storage and a file
@@ -152,25 +161,86 @@ public InputStream getInputStream()
     }
   }
 
-  public OutputStream getOutputStream(boolean overwrite)
+  public OutputStream getOutputStream(boolean overwrite,
+                                      boolean lock)
           throws IOException {
+    final FileOutputStream fileOutputStream;
     try {
       if (!isExists()) {
-
-        return new FileOutputStream(getLocalFile());
+        fileOutputStream = new FileOutputStream(getLocalFile());
       }
       else {
         if (overwrite) {
-          return new FileOutputStream(getLocalFile());
+          fileOutputStream = new FileOutputStream(getLocalFile());
         }
         else {
-          return new FileOutputStream(getLocalFile(), true);
+          fileOutputStream = new FileOutputStream(getLocalFile(), true);
+        }
+      }
+      if (lock) {
+        final FileLock fileLock;
+        try {
+          fileLock = fileOutputStream.getChannel().lock();
+        }
+        catch (IOException ex) {
+          fileOutputStream.close();
+          throw ex;
+        }
+        catch (Exception ex) {
+          fileOutputStream.close();
+          throw new IOException(ex);
+        }
+        if (fileLock == null) {
+          fileOutputStream.close();
+          throw new OverlappingFileLockException();
         }
+        return new OutputStream() {
+
+          @Override
+          public void write(int b)
+                  throws IOException {
+            fileOutputStream.write(b);
+          }
+
+          @Override
+          public void close()
+                  throws IOException {
+            fileLock.release();
+            fileOutputStream.close();
+          }
+
+          @Override
+          public void flush()
+                  throws IOException {
+            fileOutputStream.flush();
+          }
+
+          @Override
+          public void write(byte[] b)
+                  throws IOException {
+            fileOutputStream.write(b);
+          }
+
+          @Override
+          public void write(byte[] b,
+                            int off,
+                            int len)
+                  throws IOException {
+            fileOutputStream.write(b, off, len);
+          }
+        };
       }
+      return fileOutputStream;
     }
     catch (FileNotFoundException ex) {
       throw ex;
     }
+
+  }
+
+  public OutputStream getOutputStream(boolean overwrite)
+          throws IOException {
+    return getOutputStream(overwrite, false);
   }
 
   public Entry[] getChildren() {
@@ -262,4 +332,101 @@ public boolean setExecutable(boolean executable) {
       throw new Error(e);
     }
   }
+
+  public boolean createNew()
+          throws IOException {
+    return getLocalFile().createNewFile();
+  }
+
+  public boolean delete()
+          throws IOException {
+    return getLocalFile().delete();
+  }
+
+  public Entry getLockEntry() {
+    if (localLockFile == null) {
+      return null;
+    }
+    else {
+      return getStorageSystem().getEntry(localLockFile.toURI());
+    }
+  }
+
+  @Override
+  protected void performLock()
+          throws Exception {
+    boolean lock = performTryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+    if (!lock) {
+      throw new IOException("Could not attain lock!");
+    }
+  }
+
+  @Override
+  protected boolean performTryLock(long time,
+                                   TimeUnit unit) {
+    final long milliSecTime = TimeUnit.MILLISECONDS.convert(time, unit);
+    long waitLeft = milliSecTime;
+    boolean tryAgain = true;
+    do {
+      long nextWaitDuration = Math.min(waitLeft, DEFAULT_WAIT_TIME_MS);
+      waitLeft = waitLeft - nextWaitDuration;
+      boolean success = performTryLock();
+      if (success) {
+        return success;
+      }
+      else {
+        if (nextWaitDuration > 0) {
+          try {
+            Thread.sleep(nextWaitDuration);
+          }
+          catch (InterruptedException ex) {
+          }
+        }
+        else {
+          tryAgain = false;
+        }
+      }
+    }
+    while (tryAgain);
+    return false;
+  }
+
+  @Override
+  protected boolean performTryLock() {
+    StringBuilder lockFileNameBuilder = new StringBuilder();
+    if (this.lockFileName == null) {
+      lockFileNameBuilder.append(getLocalFile().getName());
+      lockFileNameBuilder.append(LOCK_FILE_EXT);
+      this.lockFileName = lockFileNameBuilder.toString();
+    }
+    final File parent = getLocalFile().getParentFile();
+    if (parent != null) {
+      parent.mkdirs();
+    }
+    localLockFile = new File(parent, this.lockFileName);
+    if (localLockFile.exists()) {
+      localLockFile = null;
+      return false;
+    }
+    else {
+      boolean createNewFile;
+      try {
+        createNewFile = localLockFile.createNewFile();
+      }
+      catch (IOException ex) {
+        createNewFile = false;
+      }
+      if (!createNewFile) {
+        localLockFile = null;
+      }
+      return createNewFile;
+    }
+  }
+
+  @Override
+  protected void performUnlock() {
+    if (localLockFile != null) {
+      localLockFile.delete();
+    }
+  }
 }
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/AbstractLockable.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/AbstractLockable.java
new file mode 100644
index 0000000..1e95494
--- /dev/null
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/AbstractLockable.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2009, Imran M Yousuf <imyousuf@smartitengineering.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.io.lock;
+
+import java.net.URI;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Abstract implementation of lockable
+ * @author Imran M Yousuf (imyousuf at smartitengineering.com)
+ * @since 0.6
+ */
+public abstract class AbstractLockable
+        implements Lockable {
+
+  private ReentrantLock lock;
+  private boolean attainedCompleteLock;
+
+  protected AbstractLockable() {
+  }
+
+  @Override
+  protected void finalize()
+          throws Throwable {
+    LockManager.getInstance().unregister(getURI());
+    super.finalize();
+  }
+
+  /**
+   * Retrieve the URI of this instance.
+   * @return The URI to identify this instance. Should never be NULL
+   */
+  public abstract URI getURI();
+
+  protected boolean isInternalLockHeldOnly() {
+    return getLock().isHeldByCurrentThread();
+  }
+
+  public boolean isHeldByCurrentThread() {
+    return isInternalLockHeldOnly() && attainedCompleteLock;
+  }
+
+  public void lock() {
+    getLock().lock();
+    childLock();
+  }
+
+  public void lockInterruptibly()
+          throws InterruptedException {
+    getLock().lockInterruptibly();
+    childLock();
+  }
+
+  public Condition newCondition() {
+    return getLock().newCondition();
+  }
+
+  public boolean tryLock() {
+    if (isHeldByCurrentThread()) {
+      return true;
+    }
+    final boolean tryLock = getLock().tryLock();
+    if (tryLock) {
+      final boolean performTryLock = performTryLock();
+      if (!performTryLock) {
+        unlock();
+      }
+      else {
+        attainedCompleteLock = true;
+      }
+    }
+    return tryLock;
+  }
+
+  public boolean tryLock(long time,
+                         TimeUnit unit)
+          throws InterruptedException {
+    if (isHeldByCurrentThread()) {
+      return true;
+    }
+    final boolean tryLock;
+    long currentTime = System.currentTimeMillis();
+    tryLock = getLock().tryLock(time, unit);
+    long duration = unit.convert(System.currentTimeMillis() - currentTime,
+            TimeUnit.MILLISECONDS);
+    if (tryLock) {
+      final boolean performTryLock = performTryLock(duration, unit);
+      if (!performTryLock) {
+        unlock();
+      }
+      else {
+        attainedCompleteLock = true;
+      }
+      return performTryLock;
+    }
+    return tryLock;
+  }
+
+  public void unlock() {
+    if (isInternalLockHeldOnly()) {
+      if (attainedCompleteLock) {
+        performUnlock();
+      }
+      attainedCompleteLock = false;
+      getLock().unlock();
+    }
+  }
+
+  /**
+   * Retrieves the {@link ReentrantLock lock} based on this instances URI. It is
+   * to be noted that all instances of this URI will share the same lock.
+   * @return The lock for this lockable instance
+   */
+  protected ReentrantLock getLock() {
+    if (lock == null) {
+      lock = LockManager.getInstance().register(getURI());
+    }
+    return lock;
+  }
+
+  /**
+   * Performs additional lock operations if required by children. It will wait
+   * until it can avail for lock, but it will not wait for ever and will then
+   * throw and exception.
+   * @throws Exception If lock could be attained
+   */
+  protected abstract void performLock()
+          throws Exception;
+
+  /**
+   * Performs additional lock operations if required by children, but it will
+   * not wait for lock until beyond the time unit specified.
+   * @param time Number to wait for lock
+   * @param unit Unit of the time number
+   * @return True if lock was attained else false
+   */
+  protected abstract boolean performTryLock(long time,
+                                            TimeUnit unit);
+
+  /**
+   * Performs additional lock operations if required by children, but it will
+   * not wait for lock at all.
+   * @return True if lock was attained else false
+   */
+  protected abstract boolean performTryLock();
+
+  /**
+   * Performs additional unlock operations if required by children.
+   */
+  protected abstract void performUnlock();
+
+  private void childLock() {
+    try {
+      performLock();
+      attainedCompleteLock = true;
+    }
+    catch (Exception ex) {
+      unlock();
+      attainedCompleteLock = false;
+      throw new RuntimeException("Could not attain lock!", ex);
+    }
+  }
+}
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/LockManager.java
similarity index 53%
copy from org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
copy to org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/LockManager.java
index 15af614..dfdcf21 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/LockManager.java
@@ -34,51 +34,77 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package org.eclipse.jgit.io;
+package org.eclipse.jgit.io.lock;
 
 import java.net.URI;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
- * SPI providing access to the underlying storage system. Each provider is
- * differentiated using their {@link StorageSystem#getURIProtocol() URI Protocol}.
+ * Manages reentrant lock per URI
  * @author Imran M Yousuf (imyousuf at smartitengineering.com)
  * @since 0.6
  */
-public interface StorageSystem {
+public final class LockManager {
 
-  /**
-   * Returns the supported scheme of this storage system.
-   * @return Scheme supported by this storage system.
-   * @see {@link http://tr.im/BiQ0 URI Scheme}
-   */
-  public String getURIScheme();
+  private static LockManager lockManager;
 
-  /**
-   * Retrieve an entry using its URI
-   * @param uri URI to retrieve the entry for.
-   * @return Entry representing the URI
-   */
-  public Entry getEntry(URI uri);
+  public static LockManager getInstance() {
+    if (lockManager == null) {
+      lockManager = new LockManager();
+    }
+    return lockManager;
+  }
+  private final Map<URI, LockProvider> locks;
 
-  /**
-   * Retrieve the current working directory from the file system if any.
-   * @return Entry for current working directory.
-   */
-  public Entry getWorkingDirectory();
+  private LockManager() {
+    locks = new Hashtable<URI, LockProvider>();
+  }
 
-  /**
-   * Retrieve the home directory of the current user
-   * @return Home directory
-   */
-  public Entry getHomeDirectory();
+  public synchronized ReentrantLock register(URI key) {
+    if (!locks.containsKey(key)) {
+      locks.put(key, new LockProvider(
+              new ReentrantLock()));
+    }
+    return locks.get(key).get();
+  }
 
-  /**
-   * Resolve relative path with respect to a path and return the absolute
-   * entry representing the relative path.
-   * @param entry The point of reference for the relative path
-   * @param path The relative path
-   * @return The absolute entry representing the relative path entry
-   */
-  public Entry resolve(Entry entry,
-                       String path);
+  public synchronized void unregister(URI key) {
+    if (locks.containsKey(key)) {
+      LockProvider provider = locks.get(key);
+      if (provider != null) {
+        provider.decreateCount();
+        if (provider.getRegisterCount() < 1) {
+          locks.remove(key);
+        }
+      }
+    }
+  }
+
+  private static class LockProvider {
+
+    private int registerCount = 0;
+    private ReentrantLock lock;
+
+    public LockProvider(ReentrantLock lock) {
+      this.lock = lock;
+    }
+
+    public ReentrantLock get() {
+      registerCount += 1;
+      return lock;
+    }
+
+    public void decreateCount() {
+      if (lock.isHeldByCurrentThread()) {
+        lock.unlock();
+      }
+      registerCount -= 1;
+    }
+
+    public int getRegisterCount() {
+      return registerCount;
+    }
+  }
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryAdapter.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/Lockable.java
similarity index 77%
copy from org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryAdapter.java
copy to org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/Lockable.java
index 008fef8..d2bb039 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryAdapter.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/lock/Lockable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2009, Imran M Yousuf <imyousuf@smartitengineering.com>
  *
  * All rights reserved.
  *
@@ -34,21 +34,21 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+package org.eclipse.jgit.io.lock;
 
-package org.eclipse.jgit.lib;
+import java.util.concurrent.locks.Lock;
 
 /**
- * A default {@link RepositoryListener} that does nothing except invoke an
- * optional general method for any repository change.
+ * For objects wanting to make themselves lockable.
+ * @author Imran M Yousuf (imyousuf at smartitengineering.com)
+ * @since 0.6
  */
-public class RepositoryAdapter implements RepositoryListener {
-
-	public void indexChanged(final IndexChangedEvent e) {
-		// Empty
-	}
-
-	public void refsChanged(final RefsChangedEvent e) {
-		// Empty
-	}
+public interface Lockable
+        extends Lock {
 
+  /**
+   * Retrieves whether the current thread owns the object lock or not.
+   * @return
+   */
+  public boolean isHeldByCurrentThread();
 }
-- 
1.6.2.1

^ permalink raw reply related

* [JGit-io-RFC-PATCH v2 3/4] Incorporate current FileSystem Util implementations to the SPI
From: imyousuf @ 2009-10-11 14:07 UTC (permalink / raw)
  To: git; +Cc: spearce, egit-dev, Imran M Yousuf
In-Reply-To: <1255270073-14205-2-git-send-email-imyousuf@gmail.com>

From: Imran M Yousuf <imyousuf@smartitengineering.com>

Operations such as setting executable bits if supported and resolving
relative path is incorporated with this change, as a result now it should
be possible to completely replace the currently being used util FS and
java.io.File.

Signed-off-by: Imran M Yousuf <imyousuf@smartitengineering.com>
---
 .../src/org/eclipse/jgit/io/Entry.java             |   35 ++++-
 .../src/org/eclipse/jgit/io/StorageSystem.java     |   16 ++
 .../eclipse/jgit/io/localfs/LocalFileEntry.java    |   52 ++++++-
 .../eclipse/jgit/io/localfs/LocalFileSystem.java   |  159 ++++++++++++++++++++
 4 files changed, 257 insertions(+), 5 deletions(-)

diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
index cd69172..5256815 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
@@ -78,6 +78,24 @@
   public boolean isExists();
 
   /**
+   * Does this operating system and JRE support the execute flag on entries?
+   *
+   * @return true if this implementation can provide reasonably accurate
+   *         executable bit information; false otherwise.
+   */
+  public boolean isExecutableSupported();
+
+  /**
+   * Determine if the entry is executable (or not).
+   * <p>
+   * Not all platforms and JREs support executable flags on entries. If the
+   * feature is unsupported this method will always return false.
+   *
+   * @return true if the entry is believed to be executable by the user.
+   */
+  public boolean isExecutable();
+
+  /**
    * Make directories upto the entry represented by this instance, provided
    * that this instance itself is a directory.
    * @return True if directories were created.
@@ -85,6 +103,19 @@
   public boolean mkdirs();
 
   /**
+   * Set an entry to be executable by the user.
+   * <p>
+   * Not all platforms and JREs support executable flags on entries. If the
+   * feature is unsupported this method will always return false and no
+   * changes will be made to the entry specified.
+   *
+   * @param executable
+   *            true to enable execution; false to disable it.
+   * @return true if the change succeeded; false otherwise.
+   */
+  public boolean setExecutable(boolean executable);
+
+  /**
    * Retrieves the URI of this entry. URI in this case acts as a primary key
    * to identify an entry.
    * @return URI to identify this entry instance
@@ -101,7 +132,7 @@
   /**
    * Retrieves the InputStream for reading the content of the entry
    * @return Input stream to read entry content
-   * @throws IOException If no such file exists or there is any other error
+   * @throws IOException If no such entry exists or there is any other error
    */
   public InputStream getInputStream()
           throws IOException;
@@ -111,7 +142,7 @@ public InputStream getInputStream()
    * opened to either overwrite it or append to it.
    * @param overwrite False if to write in append mode else true
    * @return Output stream to write content to
-   * @throws IOException If no such file exists in append mode or there is any
+   * @throws IOException If no such entry exists in append mode or there is any
    *                     error in retrieving it.
    */
   public OutputStream getOutputStream(boolean overwrite)
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
index 9f45cb3..15af614 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
@@ -65,4 +65,20 @@
    * @return Entry for current working directory.
    */
   public Entry getWorkingDirectory();
+
+  /**
+   * Retrieve the home directory of the current user
+   * @return Home directory
+   */
+  public Entry getHomeDirectory();
+
+  /**
+   * Resolve relative path with respect to a path and return the absolute
+   * entry representing the relative path.
+   * @param entry The point of reference for the relative path
+   * @param path The relative path
+   * @return The absolute entry representing the relative path entry
+   */
+  public Entry resolve(Entry entry,
+                       String path);
 }
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
index 99df831..4ef3076 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
@@ -43,6 +43,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
 import java.net.URI;
 import org.eclipse.jgit.io.Entry;
 import org.eclipse.jgit.io.StorageSystem;
@@ -60,7 +61,7 @@
         implements Entry {
 
   private File localFile;
-  private StorageSystem storageSystem;
+  private LocalFileSystem storageSystem;
 
   /**
    * Contructs an entry based of on the local file system storage and a file
@@ -70,7 +71,7 @@
    * @throws IllegalArgumentException If either argument is NULL
    */
   protected LocalFileEntry(File localFile,
-                           StorageSystem storageSystem)
+                           LocalFileSystem storageSystem)
           throws IllegalArgumentException {
     setLocalFile(localFile);
     setStorageSystem(storageSystem);
@@ -81,7 +82,7 @@ protected LocalFileEntry(File localFile,
    * @param storageSystem Storage system
    * @throws IllegalArgumentException IF storageSystem is null
    */
-  protected void setStorageSystem(StorageSystem storageSystem)
+  protected void setStorageSystem(LocalFileSystem storageSystem)
           throws IllegalArgumentException {
     if (storageSystem == null) {
       throw new IllegalArgumentException("Storage system can't be NULL!");
@@ -216,4 +217,49 @@ public StorageSystem getStorageSystem() {
   public long length() {
     return getLocalFile().length();
   }
+
+  public boolean isExecutableSupported() {
+    return LocalFileSystem.platform.isExecutableSupproted();
+  }
+
+  public boolean isExecutable() {
+    if (LocalFileSystem.platform.isExecutableSupproted()) {
+      try {
+        final Object r = LocalFileSystem.canExecute.invoke(
+                getLocalFile(),
+                (Object[]) null);
+        return ((Boolean) r).booleanValue();
+      }
+      catch (IllegalArgumentException e) {
+        throw new Error(e);
+      }
+      catch (IllegalAccessException e) {
+        throw new Error(e);
+      }
+      catch (InvocationTargetException e) {
+        throw new Error(e);
+      }
+    }
+    else {
+      return false;
+    }
+  }
+
+  public boolean setExecutable(boolean executable) {
+    try {
+      final Object r;
+      r = LocalFileSystem.setExecute.invoke(getLocalFile(), new Object[] {
+                Boolean.valueOf(executable)});
+      return ((Boolean) r).booleanValue();
+    }
+    catch (IllegalArgumentException e) {
+      throw new Error(e);
+    }
+    catch (IllegalAccessException e) {
+      throw new Error(e);
+    }
+    catch (InvocationTargetException e) {
+      throw new Error(e);
+    }
+  }
 }
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
index d0cb536..7cef2d8 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
@@ -36,8 +36,14 @@
  */
 package org.eclipse.jgit.io.localfs;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Method;
 import java.net.URI;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import org.eclipse.jgit.io.Entry;
 import org.eclipse.jgit.io.StorageSystem;
 
@@ -50,6 +56,14 @@
         implements StorageSystem {
 
   public static final String PROTOCOL_FILE = "file";
+  public static final Platform platform;
+  public static Method canExecute;
+  public static Method setExecute;
+  public static String cygpath;
+
+  static {
+    platform = Platform.detect();
+  }
 
   public String getURIScheme() {
     return PROTOCOL_FILE;
@@ -68,4 +82,149 @@ public Entry getWorkingDirectory() {
     String curDir = System.getProperty("user.dir");
     return new LocalFileEntry(new File(curDir), this);
   }
+
+  public Entry resolve(Entry entry,
+                       String path) {
+    if (!(entry instanceof LocalFileEntry)) {
+      return null;
+    }
+    LocalFileEntry fileEntry = (LocalFileEntry) entry;
+    File localFile = fileEntry.getLocalFile();
+    if (platform.equals(Platform.WIN32_CYGWIN)) {
+      try {
+        final Process p;
+
+        p = Runtime.getRuntime().exec(
+                new String[] {cygpath, "--windows", "--absolute", path},
+                null, localFile);
+        p.getOutputStream().close();
+
+        final BufferedReader lineRead = new BufferedReader(
+                new InputStreamReader(p.getInputStream(), "UTF-8"));
+        String r = null;
+        try {
+          r = lineRead.readLine();
+        }
+        finally {
+          lineRead.close();
+        }
+
+        for (;;) {
+          try {
+            if (p.waitFor() == 0 && r != null && r.length() > 0) {
+              return new LocalFileEntry(new File(r), this);
+            }
+            break;
+          }
+          catch (InterruptedException ie) {
+            // Stop bothering me, I have a zombie to reap.
+          }
+        }
+      }
+      catch (IOException ioe) {
+        // Fall through and use the default return.
+      }
+
+    }
+    final File abspn = new File(path);
+    if (abspn.isAbsolute()) {
+      return new LocalFileEntry(abspn, this);
+    }
+    return new LocalFileEntry(new File(localFile, path), this);
+  }
+
+  public Entry getHomeDirectory() {
+    if (platform.equals(Platform.WIN32_CYGWIN)) {
+      final String home = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+        public String run() {
+          return System.getenv("HOME");
+        }
+      });
+      if (!(home == null || home.length() == 0)) {
+        return resolve(new LocalFileEntry(new File("."), this), home);
+      }
+    }
+    final String home = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+      public String run() {
+        return System.getProperty("user.home");
+      }
+    });
+    if (home == null || home.length() == 0) {
+      return null;
+    }
+    return new LocalFileEntry(new File(home).getAbsoluteFile(), this);
+  }
+
+  public enum Platform {
+
+    WIN32_CYGWIN(false),
+    WIN32(false),
+    POSIX_JAVA5(false),
+    POSIX_JAVA6(true);
+    private boolean executableSupproted;
+
+    private Platform(boolean executableSupproted) {
+      this.executableSupproted = executableSupproted;
+    }
+
+    public boolean isExecutableSupproted() {
+      return executableSupproted;
+    }
+
+    public static Platform detect() {
+      final String osDotName = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+        public String run() {
+          return System.getProperty("os.name");
+        }
+      });
+      if (osDotName != null &&
+          osDotName.toLowerCase().indexOf("windows") != -1) {
+        final String path = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+          public String run() {
+            return System.getProperty("java.library.path");
+          }
+        });
+        if (path == null) {
+          return WIN32;
+        }
+        for (final String p : path.split(";")) {
+          final File e = new File(p, "cygpath.exe");
+          if (e.isFile()) {
+            cygpath = e.getAbsolutePath();
+            return WIN32_CYGWIN;
+          }
+        }
+        return WIN32;
+      }
+      else {
+        canExecute = needMethod(File.class, "canExecute");
+        setExecute = needMethod(File.class, "setExecutable",
+                Boolean.TYPE);
+        if (canExecute != null && setExecute != null) {
+          return POSIX_JAVA6;
+        }
+        else {
+          return POSIX_JAVA5;
+        }
+      }
+    }
+
+    private static Method needMethod(final Class<?> on,
+                                     final String name,
+                                     final Class<?>... args) {
+      try {
+        return on.getMethod(name, args);
+      }
+      catch (SecurityException e) {
+        return null;
+      }
+      catch (NoSuchMethodException e) {
+        return null;
+      }
+    }
+  }
 }
-- 
1.6.2.1

^ permalink raw reply related

* [Sample-Conversion-PATCH 1/2] Add JGit IO module as dependency to the main module
From: imyousuf @ 2009-10-11 14:10 UTC (permalink / raw)
  To: git; +Cc: spearce, egit-dev, Imran M Yousuf

From: Imran M Yousuf <imyousuf@smartitengineering.com>

Signed-off-by: Imran M Yousuf <imyousuf@smartitengineering.com>
---
 jgit-maven/jgit/pom.xml |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/jgit-maven/jgit/pom.xml b/jgit-maven/jgit/pom.xml
index 9eb5758..7176db9 100644
--- a/jgit-maven/jgit/pom.xml
+++ b/jgit-maven/jgit/pom.xml
@@ -62,6 +62,12 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.eclipse</groupId>
+            <artifactId>jgit-io</artifactId>
+            <version>${project.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
             <groupId>com.jcraft</groupId>
             <artifactId>jsch</artifactId>
             <version>0.1.41</version>
-- 
1.6.2.1

^ permalink raw reply related

* [Sample-Conversion-PATCH 2/2] Introduce IO SPI usage in RepositoryConfig
From: imyousuf @ 2009-10-11 14:10 UTC (permalink / raw)
  To: git; +Cc: spearce, egit-dev, Imran M Yousuf
In-Reply-To: <1255270213-14514-1-git-send-email-imyousuf@gmail.com>

From: Imran M Yousuf <imyousuf@smartitengineering.com>

In order to introduce IO SPI in repository config class file based config,
file lock and NB is converted to use the IO SPI instead of java.io.File

Next is object directory.

Signed-off-by: Imran M Yousuf <imyousuf@smartitengineering.com>
---
 .../src/org/eclipse/jgit/lib/FileBasedConfig.java  |   12 +-
 .../src/org/eclipse/jgit/lib/LockFile.java         |  839 ++++++++++----------
 .../src/org/eclipse/jgit/lib/RepositoryConfig.java |    4 +-
 org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java |   54 ++-
 4 files changed, 495 insertions(+), 414 deletions(-)
 rewrite org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java (78%)

diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileBasedConfig.java
index 1300d85..a952be5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileBasedConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileBasedConfig.java
@@ -40,11 +40,11 @@
  */
 package org.eclipse.jgit.lib;
 
-import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 
 import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.io.Entry;
 import org.eclipse.jgit.util.NB;
 import org.eclipse.jgit.util.RawParseUtils;
 
@@ -52,7 +52,7 @@
  * The configuration file that is stored in the file of the file system.
  */
 public class FileBasedConfig extends Config {
-	private final File configFile;
+	private final Entry configFile;
 
 	/**
 	 * Create a configuration with no default fallback.
@@ -60,7 +60,7 @@
 	 * @param cfgLocation
 	 *            the location of the configuration file on the file system
 	 */
-	public FileBasedConfig(File cfgLocation) {
+	public FileBasedConfig(Entry cfgLocation) {
 		this(null, cfgLocation);
 	}
 
@@ -72,13 +72,13 @@ public FileBasedConfig(File cfgLocation) {
 	 * @param cfgLocation
 	 *            the location of the configuration file on the file system
 	 */
-	public FileBasedConfig(Config base, File cfgLocation) {
+	public FileBasedConfig(Config base, Entry cfgLocation) {
 		super(base);
 		configFile = cfgLocation;
 	}
 
 	/** @return location of the configuration file on disk */
-	public final File getFile() {
+	public final Entry getFile() {
 		return configFile;
 	}
 
@@ -135,6 +135,6 @@ public void save() throws IOException {
 
 	@Override
 	public String toString() {
-		return getClass().getSimpleName() + "[" + getFile().getPath() + "]";
+		return getClass().getSimpleName() + "[" + getFile().getName() + "]";
 	}
 }
\ No newline at end of file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java
dissimilarity index 78%
index a2d8469..b852ddf 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java
@@ -1,405 +1,434 @@
-/*
- * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.channels.FileLock;
-import java.nio.channels.OverlappingFileLockException;
-
-/**
- * Git style file locking and replacement.
- * <p>
- * To modify a ref file Git tries to use an atomic update approach: we write the
- * new data into a brand new file, then rename it in place over the old name.
- * This way we can just delete the temporary file if anything goes wrong, and
- * nothing has been damaged. To coordinate access from multiple processes at
- * once Git tries to atomically create the new temporary file under a well-known
- * name.
- */
-public class LockFile {
-	private final File ref;
-
-	private final File lck;
-
-	private FileLock fLck;
-
-	private boolean haveLck;
-
-	private FileOutputStream os;
-
-	private boolean needStatInformation;
-
-	private long commitLastModified;
-
-	/**
-	 * Create a new lock for any file.
-	 * 
-	 * @param f
-	 *            the file that will be locked.
-	 */
-	public LockFile(final File f) {
-		ref = f;
-		lck = new File(ref.getParentFile(), ref.getName() + ".lock");
-	}
-
-	/**
-	 * Try to establish the lock.
-	 * 
-	 * @return true if the lock is now held by the caller; false if it is held
-	 *         by someone else.
-	 * @throws IOException
-	 *             the temporary output file could not be created. The caller
-	 *             does not hold the lock.
-	 */
-	public boolean lock() throws IOException {
-		lck.getParentFile().mkdirs();
-		if (lck.createNewFile()) {
-			haveLck = true;
-			try {
-				os = new FileOutputStream(lck);
-				try {
-					fLck = os.getChannel().tryLock();
-					if (fLck == null)
-						throw new OverlappingFileLockException();
-				} catch (OverlappingFileLockException ofle) {
-					// We cannot use unlock() here as this file is not
-					// held by us, but we thought we created it. We must
-					// not delete it, as it belongs to some other process.
-					//
-					haveLck = false;
-					try {
-						os.close();
-					} catch (IOException ioe) {
-						// Fail by returning haveLck = false.
-					}
-					os = null;
-				}
-			} catch (IOException ioe) {
-				unlock();
-				throw ioe;
-			}
-		}
-		return haveLck;
-	}
-
-	/**
-	 * Try to establish the lock for appending.
-	 * 
-	 * @return true if the lock is now held by the caller; false if it is held
-	 *         by someone else.
-	 * @throws IOException
-	 *             the temporary output file could not be created. The caller
-	 *             does not hold the lock.
-	 */
-	public boolean lockForAppend() throws IOException {
-		if (!lock())
-			return false;
-		copyCurrentContent();
-		return true;
-	}
-
-	/**
-	 * Copy the current file content into the temporary file.
-	 * <p>
-	 * This method saves the current file content by inserting it into the
-	 * temporary file, so that the caller can safely append rather than replace
-	 * the primary file.
-	 * <p>
-	 * This method does nothing if the current file does not exist, or exists
-	 * but is empty.
-	 * 
-	 * @throws IOException
-	 *             the temporary file could not be written, or a read error
-	 *             occurred while reading from the current file. The lock is
-	 *             released before throwing the underlying IO exception to the
-	 *             caller.
-	 * @throws RuntimeException
-	 *             the temporary file could not be written. The lock is released
-	 *             before throwing the underlying exception to the caller.
-	 */
-	public void copyCurrentContent() throws IOException {
-		requireLock();
-		try {
-			final FileInputStream fis = new FileInputStream(ref);
-			try {
-				final byte[] buf = new byte[2048];
-				int r;
-				while ((r = fis.read(buf)) >= 0)
-					os.write(buf, 0, r);
-			} finally {
-				fis.close();
-			}
-		} catch (FileNotFoundException fnfe) {
-			// Don't worry about a file that doesn't exist yet, it
-			// conceptually has no current content to copy.
-			//
-		} catch (IOException ioe) {
-			unlock();
-			throw ioe;
-		} catch (RuntimeException ioe) {
-			unlock();
-			throw ioe;
-		} catch (Error ioe) {
-			unlock();
-			throw ioe;
-		}
-	}
-
-	/**
-	 * Write an ObjectId and LF to the temporary file.
-	 * 
-	 * @param id
-	 *            the id to store in the file. The id will be written in hex,
-	 *            followed by a sole LF.
-	 * @throws IOException
-	 *             the temporary file could not be written. The lock is released
-	 *             before throwing the underlying IO exception to the caller.
-	 * @throws RuntimeException
-	 *             the temporary file could not be written. The lock is released
-	 *             before throwing the underlying exception to the caller.
-	 */
-	public void write(final ObjectId id) throws IOException {
-		requireLock();
-		try {
-			final BufferedOutputStream b;
-			b = new BufferedOutputStream(os, Constants.OBJECT_ID_LENGTH * 2 + 1);
-			id.copyTo(b);
-			b.write('\n');
-			b.flush();
-			fLck.release();
-			b.close();
-			os = null;
-		} catch (IOException ioe) {
-			unlock();
-			throw ioe;
-		} catch (RuntimeException ioe) {
-			unlock();
-			throw ioe;
-		} catch (Error ioe) {
-			unlock();
-			throw ioe;
-		}
-	}
-
-	/**
-	 * Write arbitrary data to the temporary file.
-	 * 
-	 * @param content
-	 *            the bytes to store in the temporary file. No additional bytes
-	 *            are added, so if the file must end with an LF it must appear
-	 *            at the end of the byte array.
-	 * @throws IOException
-	 *             the temporary file could not be written. The lock is released
-	 *             before throwing the underlying IO exception to the caller.
-	 * @throws RuntimeException
-	 *             the temporary file could not be written. The lock is released
-	 *             before throwing the underlying exception to the caller.
-	 */
-	public void write(final byte[] content) throws IOException {
-		requireLock();
-		try {
-			os.write(content);
-			os.flush();
-			fLck.release();
-			os.close();
-			os = null;
-		} catch (IOException ioe) {
-			unlock();
-			throw ioe;
-		} catch (RuntimeException ioe) {
-			unlock();
-			throw ioe;
-		} catch (Error ioe) {
-			unlock();
-			throw ioe;
-		}
-	}
-
-	/**
-	 * Obtain the direct output stream for this lock.
-	 * <p>
-	 * The stream may only be accessed once, and only after {@link #lock()} has
-	 * been successfully invoked and returned true. Callers must close the
-	 * stream prior to calling {@link #commit()} to commit the change.
-	 * 
-	 * @return a stream to write to the new file. The stream is unbuffered.
-	 */
-	public OutputStream getOutputStream() {
-		requireLock();
-		return new OutputStream() {
-			@Override
-			public void write(final byte[] b, final int o, final int n)
-					throws IOException {
-				os.write(b, o, n);
-			}
-
-			@Override
-			public void write(final byte[] b) throws IOException {
-				os.write(b);
-			}
-
-			@Override
-			public void write(final int b) throws IOException {
-				os.write(b);
-			}
-
-			@Override
-			public void flush() throws IOException {
-				os.flush();
-			}
-
-			@Override
-			public void close() throws IOException {
-				try {
-					os.flush();
-					fLck.release();
-					os.close();
-					os = null;
-				} catch (IOException ioe) {
-					unlock();
-					throw ioe;
-				} catch (RuntimeException ioe) {
-					unlock();
-					throw ioe;
-				} catch (Error ioe) {
-					unlock();
-					throw ioe;
-				}
-			}
-		};
-	}
-
-	private void requireLock() {
-		if (os == null) {
-			unlock();
-			throw new IllegalStateException("Lock on " + ref + " not held.");
-		}
-	}
-
-	/**
-	 * Request that {@link #commit()} remember modification time.
-	 * 
-	 * @param on
-	 *            true if the commit method must remember the modification time.
-	 */
-	public void setNeedStatInformation(final boolean on) {
-		needStatInformation = on;
-	}
-
-	/**
-	 * Commit this change and release the lock.
-	 * <p>
-	 * If this method fails (returns false) the lock is still released.
-	 * 
-	 * @return true if the commit was successful and the file contains the new
-	 *         data; false if the commit failed and the file remains with the
-	 *         old data.
-	 * @throws IllegalStateException
-	 *             the lock is not held.
-	 */
-	public boolean commit() {
-		if (os != null) {
-			unlock();
-			throw new IllegalStateException("Lock on " + ref + " not closed.");
-		}
-
-		saveStatInformation();
-		if (lck.renameTo(ref))
-			return true;
-		if (!ref.exists() || ref.delete())
-			if (lck.renameTo(ref))
-				return true;
-		unlock();
-		return false;
-	}
-
-	private void saveStatInformation() {
-		if (needStatInformation)
-			commitLastModified = lck.lastModified();
-	}
-
-	/**
-	 * Get the modification time of the output file when it was committed.
-	 * 
-	 * @return modification time of the lock file right before we committed it.
-	 */
-	public long getCommitLastModified() {
-		return commitLastModified;
-	}
-
-	/**
-	 * Unlock this file and abort this change.
-	 * <p>
-	 * The temporary file (if created) is deleted before returning.
-	 */
-	public void unlock() {
-		if (os != null) {
-			if (fLck != null) {
-				try {
-					fLck.release();
-				} catch (IOException ioe) {
-					// Huh?
-				}
-				fLck = null;
-			}
-			try {
-				os.close();
-			} catch (IOException ioe) {
-				// Ignore this
-			}
-			os = null;
-		}
-
-		if (haveLck) {
-			haveLck = false;
-			lck.delete();
-		}
-	}
-
-	@Override
-	public String toString() {
-		return "LockFile[" + lck + ", haveLck=" + haveLck + "]";
-	}
-}
+/*
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.lib;
+
+import java.io.BufferedOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.channels.OverlappingFileLockException;
+import org.eclipse.jgit.io.Entry;
+
+/**
+ * Git style file locking and replacement.
+ * <p>
+ * To modify a ref file Git tries to use an atomic update approach: we write the
+ * new data into a brand new file, then rename it in place over the old name.
+ * This way we can just delete the temporary file if anything goes wrong, and
+ * nothing has been damaged. To coordinate access from multiple processes at
+ * once Git tries to atomically create the new temporary file under a well-known
+ * name.
+ */
+public class LockFile {
+
+  public static final int DEFAULT_BUFFER_SIZE = 500;
+
+  private final Entry ref;
+  private Entry lck;
+  private boolean haveLck;
+  private OutputStream os;
+  private boolean needStatInformation;
+  private long commitLastModified;
+
+  /**
+   * Create a new lock for any file.
+   *
+   * @param f
+   *            the file that will be locked.
+   */
+  public LockFile(final Entry f) {
+    ref = f;
+    lck = null;
+  }
+
+  /**
+   * Try to establish the lock.
+   *
+   * @return true if the lock is now held by the caller; false if it is held
+   *         by someone else.
+   * @throws IOException
+   *             the temporary output file could not be created. The caller
+   *             does not hold the lock.
+   */
+  public boolean lock()
+          throws IOException {
+    boolean locked = ref.tryLock();
+    if (locked) {
+      haveLck = true;
+      try {
+        lck = ref.getLockEntry();
+        try {
+          os = lck.getOutputStream(false, true);
+        }
+        catch (OverlappingFileLockException ofle) {
+          // We cannot use unlock() here as this file is not
+          // held by us, but we thought we created it. We must
+          // not delete it, as it belongs to some other process.
+          //
+          haveLck = false;
+          os = null;
+        }
+      }
+      catch (IOException ioe) {
+        unlock();
+        throw ioe;
+      }
+    }
+    return haveLck;
+  }
+
+  /**
+   * Try to establish the lock for appending.
+   *
+   * @return true if the lock is now held by the caller; false if it is held
+   *         by someone else.
+   * @throws IOException
+   *             the temporary output file could not be created. The caller
+   *             does not hold the lock.
+   */
+  public boolean lockForAppend()
+          throws IOException {
+    if (!lock()) {
+      return false;
+    }
+    copyCurrentContent();
+    return true;
+  }
+
+  /**
+   * Copy the current file content into the temporary file.
+   * <p>
+   * This method saves the current file content by inserting it into the
+   * temporary file, so that the caller can safely append rather than replace
+   * the primary file.
+   * <p>
+   * This method does nothing if the current file does not exist, or exists
+   * but is empty.
+   *
+   * @throws IOException
+   *             the temporary file could not be written, or a read error
+   *             occurred while reading from the current file. The lock is
+   *             released before throwing the underlying IO exception to the
+   *             caller.
+   * @throws RuntimeException
+   *             the temporary file could not be written. The lock is released
+   *             before throwing the underlying exception to the caller.
+   */
+  public void copyCurrentContent()
+          throws IOException {
+    requireLock();
+    try {
+      final InputStream fis = ref.getInputStream();
+      try {
+        final byte[] buf = new byte[2048];
+        int r;
+        while ((r = fis.read(buf)) >= 0) {
+          os.write(buf, 0, r);
+        }
+      }
+      finally {
+        fis.close();
+      }
+    }
+    catch (FileNotFoundException fnfe) {
+      // Don't worry about a file that doesn't exist yet, it
+      // conceptually has no current content to copy.
+      //
+    }
+    catch (IOException ioe) {
+      unlock();
+      throw ioe;
+    }
+    catch (RuntimeException ioe) {
+      unlock();
+      throw ioe;
+    }
+    catch (Error ioe) {
+      unlock();
+      throw ioe;
+    }
+  }
+
+  /**
+   * Write an ObjectId and LF to the temporary file.
+   *
+   * @param id
+   *            the id to store in the file. The id will be written in hex,
+   *            followed by a sole LF.
+   * @throws IOException
+   *             the temporary file could not be written. The lock is released
+   *             before throwing the underlying IO exception to the caller.
+   * @throws RuntimeException
+   *             the temporary file could not be written. The lock is released
+   *             before throwing the underlying exception to the caller.
+   */
+  public void write(final ObjectId id)
+          throws IOException {
+    requireLock();
+    try {
+      final BufferedOutputStream b;
+      b = new BufferedOutputStream(os, Constants.OBJECT_ID_LENGTH * 2 + 1);
+      id.copyTo(b);
+      b.write('\n');
+      b.flush();
+      b.close();
+      os = null;
+    }
+    catch (IOException ioe) {
+      unlock();
+      throw ioe;
+    }
+    catch (RuntimeException ioe) {
+      unlock();
+      throw ioe;
+    }
+    catch (Error ioe) {
+      unlock();
+      throw ioe;
+    }
+  }
+
+  /**
+   * Write arbitrary data to the temporary file.
+   *
+   * @param content
+   *            the bytes to store in the temporary file. No additional bytes
+   *            are added, so if the file must end with an LF it must appear
+   *            at the end of the byte array.
+   * @throws IOException
+   *             the temporary file could not be written. The lock is released
+   *             before throwing the underlying IO exception to the caller.
+   * @throws RuntimeException
+   *             the temporary file could not be written. The lock is released
+   *             before throwing the underlying exception to the caller.
+   */
+  public void write(final byte[] content)
+          throws IOException {
+    requireLock();
+    try {
+      os.write(content);
+      os.flush();
+      os.close();
+      os = null;
+    }
+    catch (IOException ioe) {
+      unlock();
+      throw ioe;
+    }
+    catch (RuntimeException ioe) {
+      unlock();
+      throw ioe;
+    }
+    catch (Error ioe) {
+      unlock();
+      throw ioe;
+    }
+  }
+
+  /**
+   * Obtain the direct output stream for this lock.
+   * <p>
+   * The stream may only be accessed once, and only after {@link #lock()} has
+   * been successfully invoked and returned true. Callers must close the
+   * stream prior to calling {@link #commit()} to commit the change.
+   *
+   * @return a stream to write to the new file. The stream is unbuffered.
+   */
+  public OutputStream getOutputStream() {
+    requireLock();
+    return new OutputStream() {
+
+      @Override
+      public void write(final byte[] b,
+                        final int o,
+                        final int n)
+              throws IOException {
+        os.write(b, o, n);
+      }
+
+      @Override
+      public void write(final byte[] b)
+              throws IOException {
+        os.write(b);
+      }
+
+      @Override
+      public void write(final int b)
+              throws IOException {
+        os.write(b);
+      }
+
+      @Override
+      public void flush()
+              throws IOException {
+        os.flush();
+      }
+
+      @Override
+      public void close()
+              throws IOException {
+        try {
+          os.flush();
+          os.close();
+          os = null;
+        }
+        catch (IOException ioe) {
+          unlock();
+          throw ioe;
+        }
+        catch (RuntimeException ioe) {
+          unlock();
+          throw ioe;
+        }
+        catch (Error ioe) {
+          unlock();
+          throw ioe;
+        }
+      }
+    };
+  }
+
+  private void requireLock() {
+    if (os == null) {
+      unlock();
+      throw new IllegalStateException("Lock on " + ref + " not held.");
+    }
+  }
+
+  /**
+   * Request that {@link #commit()} remember modification time.
+   *
+   * @param on
+   *            true if the commit method must remember the modification time.
+   */
+  public void setNeedStatInformation(final boolean on) {
+    needStatInformation = on;
+  }
+
+  /**
+   * Commit this change and release the lock.
+   * <p>
+   * If this method fails (returns false) the lock is still released.
+   *
+   * @return true if the commit was successful and the file contains the new
+   *         data; false if the commit failed and the file remains with the
+   *         old data.
+   * @throws IllegalStateException
+   *             the lock is not held.
+   */
+  public boolean commit() {
+    if (os != null) {
+      unlock();
+      throw new IllegalStateException("Lock on " + ref + " not closed.");
+    }
+
+    saveStatInformation();
+    try {
+      if (!ref.isExists()) {
+        ref.createNew();
+      }
+      OutputStream contentWriter = ref.getOutputStream(true, false);
+      InputStream contentReader = lck.getInputStream();
+      copy(contentReader, contentWriter);
+      contentReader.close();
+      contentWriter.close();
+      unlock();
+      return true;
+    }
+    catch (Exception ex) {
+      //ignore
+    }
+    return false;
+  }
+
+  public static int copy(
+          InputStream input,
+          OutputStream output)
+          throws IOException {
+    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+    int count = 0;
+    int n = 0;
+    while (-1 != (n = input.read(buffer))) {
+      output.write(buffer, 0, n);
+      count += n;
+    }
+    return count;
+  }
+
+  private void saveStatInformation() {
+    if (needStatInformation) {
+      commitLastModified = System.currentTimeMillis();
+    }
+  }
+
+  /**
+   * Get the modification time of the output file when it was committed.
+   *
+   * @return modification time of the lock file right before we committed it.
+   */
+  public long getCommitLastModified() {
+    return commitLastModified;
+  }
+
+  /**
+   * Unlock this file and abort this change.
+   * <p>
+   * The temporary file (if created) is deleted before returning.
+   */
+  public void unlock() {
+    if (os != null) {
+      try {
+        os.close();
+      }
+      catch (IOException ioe) {
+        // Ignore this
+      }
+      os = null;
+    }
+    if (haveLck) {
+      haveLck = false;
+      ref.unlock();
+    }
+  }
+
+  @Override
+  public String toString() {
+    return "LockFile[" + lck + ", haveLck=" + haveLck + "]";
+  }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java
index 117e44a..851998e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java
@@ -41,7 +41,7 @@
 
 package org.eclipse.jgit.lib;
 
-import java.io.File;
+import org.eclipse.jgit.io.Entry;
 
 /**
  * An object representing the Git config file.
@@ -63,7 +63,7 @@
 	 * @param cfgLocation
 	 *            path of the file to load (or save).
 	 */
-	public RepositoryConfig(final Config base, final File cfgLocation) {
+	public RepositoryConfig(final Config base, final Entry cfgLocation) {
 		super(base, cfgLocation);
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java
index 261e3d1..a8c0758 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java
@@ -37,14 +37,17 @@
 
 package org.eclipse.jgit.util;
 
+import java.io.ByteArrayOutputStream;
 import java.io.EOFException;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
+import org.eclipse.jgit.io.Entry;
 
 /** Conversion utilities for network byte order handling. */
 public final class NB {
@@ -97,6 +100,38 @@
 		}
 	}
 
+  public static final byte[] readFully(final Entry path)
+			throws IOException {
+    return readFully(path, Integer.MAX_VALUE);
+  }
+
+	public static final byte[] readFully(final Entry path, final int max)
+			throws IOException {
+		final InputStream in = path.getInputStream();
+		try {
+			final long sz = path.length();
+      byte[] buf;
+      if(sz > -1) {
+        if (sz > max)
+          throw new IOException("File is too large: " + path);
+        buf = new byte[(int) sz];
+        readFully(in, buf, 0, buf.length);
+      }
+      else {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        read(in, outputStream);
+        buf = outputStream.toByteArray();
+      }
+			return buf;
+		} finally {
+			try {
+				in.close();
+			} catch (IOException ignored) {
+				// ignore any close errors, this was a read only stream
+			}
+		}
+	}
+
 	/**
 	 * Read the entire byte array into memory, or throw an exception.
 	 * 
@@ -113,8 +148,9 @@
 	 * @throws IOException
 	 *             there was an error reading from the stream.
 	 */
-	public static void readFully(final InputStream fd, final byte[] dst,
+	public static int readFully(final InputStream fd, final byte[] dst,
 			int off, int len) throws IOException {
+    int initOff = off;
 		while (len > 0) {
 			final int r = fd.read(dst, off, len);
 			if (r <= 0)
@@ -122,6 +158,22 @@ public static void readFully(final InputStream fd, final byte[] dst,
 			off += r;
 			len -= r;
 		}
+    return off - initOff;
+	}
+
+	public static int read(final InputStream fd, final OutputStream dst)
+          throws IOException {
+    int size = 0;
+    int r = 1;
+    byte[] bytes = new byte[1000];
+		while (r > 0) {
+			r = fd.read(bytes, 0, 1000);
+      if(r > 0) {
+        dst.write(bytes, 0, r);
+        size += r;
+      }
+		}
+    return size;
 	}
 
 	/**
-- 
1.6.2.1

^ permalink raw reply related

* Re: combine git repo historically
From: Jakub Narebski @ 2009-10-11 14:29 UTC (permalink / raw)
  To: Christian Couder; +Cc: Johannes Sixt, bill lam, git, Christian Couder
In-Reply-To: <200910111543.39327.chriscool@tuxfamily.org>

Dnia niedziela 11. października 2009 15:43, Christian Couder napisał:
> On Sunday 11 October 2009, Johannes Sixt wrote:

> > There is no way to retrieve the original commit using plumbing 
> > unless the replacement is removed. Am I right?
> 
> I think you are right, but a flag could be easily added to some commands to 
> retreive original objects. Or you can remove the replacement, retrieve the 
> object and then put back the replacement.

Wouldn't it be better for this option to be option for git wrapper,
i.e.

 $ git --no-replace cat-file -p N

and not

 $ git cat-file --no-replace -p N

-- 
Jakub Narebski
Poland

^ permalink raw reply

* Re: Merging non-git releases of a project
From: Avery Pennarun @ 2009-10-11 15:32 UTC (permalink / raw)
  To: Howard Miller; +Cc: git
In-Reply-To: <26ae428a0910100158s5233841byd303377aa20eb45f@mail.gmail.com>

On Sat, Oct 10, 2009 at 4:58 AM, Howard Miller
<howard@e-learndesign.co.uk> wrote:
> I don't have cp -a (on a mac) but, IIRC, that's just -rp or somesuch?

You can obtain a non-stupid version of 'cp' (as well as 'ls' and
'grep' and 'find' and other useful tools) for your mac by using fink.
But yes.

Have fun,

Avery

^ permalink raw reply

* Re: [ANNOUNCE] GIT 1.6.5
From: Steven Noonan @ 2009-10-11 16:30 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <f488382f0910110930u1af92299ld5d72dbb31ed1914@mail.gmail.com>

On Sun, Oct 11, 2009 at 9:30 AM, Steven Noonan <steven@uplinklabs.net> wrote:
> Uh-oh.
>
> Alcarin:crisscross steven$ git remote update
> Updating origin
> fatal: 'git@github.com/tycho/crisscross.git' does not appear to be a
> git repository
> fatal: The remote end hung up unexpectedly
> error: Could not fetch origin
>
> Alcarin:crisscross steven$ nano -w .git/config
> Alcarin:crisscross steven$ git remote update
> Updating origin

Er, meant to say before this that I edited the URI to include the
'ssh://' and then it worked fine.

>
> The 'ssh://' part is omitted in numerous places on github.com. I
> realize github.com isn't the final authority on the syntax of the URI,
> but was this an intentional change or a regression?
>
> - Steven
>
> On Sun, Oct 11, 2009 at 1:40 AM, Junio C Hamano <gitster@pobox.com> wrote:
>> The latest feature release GIT 1.6.5 is available at the usual
>> places:
>>
>>  http://www.kernel.org/pub/software/scm/git/
>>
>>  git-1.6.5.tar.{gz,bz2}                        (source tarball)
>>  git-htmldocs-1.6.5.tar.{gz,bz2}               (preformatted docs)
>>  git-manpages-1.6.5.tar.{gz,bz2}               (preformatted docs)
>>
>> The RPM binary packages for a few architectures are found in:
>>
>>  RPMS/$arch/git-*-1.6.5-1.fc9.$arch.rpm        (RPM)
>>
>> This cycle took a bit longer than I hoped, but here it is.  We already
>> have some new features cooking in 'next', and I expect we may be able to
>> have 1.6.6 by the end of the year.
>>
>> Enjoy.
>>
>> ----------------------------------------------------------------
>>
>> GIT v1.6.5 Release Notes
>> ========================
>>
>> In git 1.7.0, which was planned to be the release after 1.6.5, "git
>> push" into a branch that is currently checked out will be refused by
>> default.
>>
>> You can choose what should happen upon such a push by setting the
>> configuration variable receive.denyCurrentBranch in the receiving
>> repository.
>>
>> Also, "git push $there :$killed" to delete the branch $killed in a remote
>> repository $there, when $killed branch is the current branch pointed at by
>> its HEAD, will be refused by default.
>>
>> You can choose what should happen upon such a push by setting the
>> configuration variable receive.denyDeleteCurrent in the receiving
>> repository.
>>
>> To ease the transition plan, the receiving repository of such a
>> push running this release will issue a big warning when the
>> configuration variable is missing.  Please refer to:
>>
>>  http://git.or.cz/gitwiki/GitFaq#non-bare
>>  http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007
>>
>> for more details on the reason why this change is needed and the
>> transition plan.
>>
>> Updates since v1.6.4
>> --------------------
>>
>> (subsystems)
>>
>>  * various updates to gitk, git-svn and gitweb.
>>
>> (portability)
>>
>>  * more improvements on mingw port.
>>
>>  * mingw will also give FRSX as the default value for the LESS
>>   environment variable when the user does not have one.
>>
>>  * initial support to compile git on Windows with MSVC.
>>
>> (performance)
>>
>>  * On major platforms, the system can be compiled to use with Linus's
>>   block-sha1 implementation of the SHA-1 hash algorithm, which
>>   outperforms the default fallback implementation we borrowed from
>>   Mozilla.
>>
>>  * Unnecessary inefficiency in deepening of a shallow repository has
>>   been removed.
>>
>>  * "git clone" does not grab objects that it does not need (i.e.
>>   referenced only from refs outside refs/heads and refs/tags
>>   hierarchy) anymore.
>>
>>  * The "git" main binary used to link with libcurl, which then dragged
>>   in a large number of external libraries.  When using basic plumbing
>>   commands in scripts, this unnecessarily slowed things down.  We now
>>   implement http/https/ftp transfer as a separate executable as we
>>   used to.
>>
>>  * "git clone" run locally hardlinks or copies the files in .git/ to
>>   newly created repository.  It used to give new mtime to copied files,
>>   but this delayed garbage collection to trigger unnecessarily in the
>>   cloned repository.  We now preserve mtime for these files to avoid
>>   this issue.
>>
>> (usability, bells and whistles)
>>
>>  * Human writable date format to various options, e.g. --since=yesterday,
>>   master@{2000.09.17}, are taught to infer some omitted input properly.
>>
>>  * A few programs gave verbose "advice" messages to help uninitiated
>>   people when issuing error messages.  An infrastructure to allow
>>   users to squelch them has been introduced, and a few such messages
>>   can be silenced now.
>>
>>  * refs/replace/ hierarchy is designed to be usable as a replacement
>>   of the "grafts" mechanism, with the added advantage that it can be
>>   transferred across repositories.
>>
>>  * "git am" learned to optionally ignore whitespace differences.
>>
>>  * "git am" handles input e-mail files that has CRLF line endings sensibly.
>>
>>  * "git am" learned "--scissors" option to allow you to discard early part
>>   of an incoming e-mail.
>>
>>  * "git archive -o output.zip" works without being told what format to
>>   use with an explicit "--format=zip".option.
>>
>>  * "git checkout", "git reset" and "git stash" learned to pick and
>>   choose to use selected changes you made, similar to "git add -p".
>>
>>  * "git clone" learned a "-b" option to pick a HEAD to check out
>>   different from the remote's default branch.
>>
>>  * "git clone" learned --recursive option.
>>
>>  * "git clone" from a local repository on a different filesystem used to
>>   copy individual object files without preserving the old timestamp, giving
>>   them extra lifetime in the new repository until they gc'ed.
>>
>>  * "git commit --dry-run $args" is a new recommended way to ask "what would
>>   happen if I try to commit with these arguments."
>>
>>  * "git commit --dry-run" and "git status" shows conflicted paths in a
>>   separate section to make them easier to spot during a merge.
>>
>>  * "git cvsimport" now supports password-protected pserver access even
>>   when the password is not taken from ~/.cvspass file.
>>
>>  * "git fast-export" learned --no-data option that can be useful when
>>   reordering commits and trees without touching the contents of
>>   blobs.
>>
>>  * "git fast-import" has a pair of new front-end in contrib/ area.
>>
>>  * "git init" learned to mkdir/chdir into a directory when given an
>>   extra argument (i.e. "git init this").
>>
>>  * "git instaweb" optionally can use mongoose as the web server.
>>
>>  * "git log --decorate" can optionally be told with --decorate=full to
>>   give the reference name in full.
>>
>>  * "git merge" issued an unnecessarily scary message when it detected
>>   that the merge may have to touch the path that the user has local
>>   uncommitted changes to. The message has been reworded to make it
>>   clear that the command aborted, without doing any harm.
>>
>>  * "git push" can be told to be --quiet.
>>
>>  * "git push" pays attention to url.$base.pushInsteadOf and uses a URL
>>   that is derived from the URL used for fetching.
>>
>>  * informational output from "git reset" that lists the locally modified
>>   paths is made consistent with that of "git checkout $another_branch".
>>
>>  * "git submodule" learned to give submodule name to scripts run with
>>   "foreach" subcommand.
>>
>>  * various subcommands to "git submodule" learned --recursive option.
>>
>>  * "git submodule summary" learned --files option to compare the work
>>   tree vs the commit bound at submodule path, instead of comparing
>>   the index.
>>
>>  * "git upload-pack", which is the server side support for "git clone" and
>>   "git fetch", can call a new post-upload-pack hook for statistics purposes.
>>
>> (developers)
>>
>>  * With GIT_TEST_OPTS="--root=/p/a/t/h", tests can be run outside the
>>   source directory; using tmpfs may give faster turnaround.
>>
>>  * With NO_PERL_MAKEMAKER set, DESTDIR= is now honoured, so you can
>>   build for one location, and install into another location to tar it
>>   up.
>>
>> Fixes since v1.6.4
>> ------------------
>>
>> All of the fixes in v1.6.4.X maintenance series are included in this
>> release, unless otherwise noted.
>> --
>> To unsubscribe from this list: send the line "unsubscribe git" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>

^ permalink raw reply

* Re: [ANNOUNCE] GIT 1.6.5
From: Steven Noonan @ 2009-10-11 16:30 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v8wfi1fya.fsf@alter.siamese.dyndns.org>

Uh-oh.

Alcarin:crisscross steven$ git remote update
Updating origin
fatal: 'git@github.com/tycho/crisscross.git' does not appear to be a
git repository
fatal: The remote end hung up unexpectedly
error: Could not fetch origin

Alcarin:crisscross steven$ nano -w .git/config
Alcarin:crisscross steven$ git remote update
Updating origin

The 'ssh://' part is omitted in numerous places on github.com. I
realize github.com isn't the final authority on the syntax of the URI,
but was this an intentional change or a regression?

- Steven

On Sun, Oct 11, 2009 at 1:40 AM, Junio C Hamano <gitster@pobox.com> wrote:
> The latest feature release GIT 1.6.5 is available at the usual
> places:
>
>  http://www.kernel.org/pub/software/scm/git/
>
>  git-1.6.5.tar.{gz,bz2}                        (source tarball)
>  git-htmldocs-1.6.5.tar.{gz,bz2}               (preformatted docs)
>  git-manpages-1.6.5.tar.{gz,bz2}               (preformatted docs)
>
> The RPM binary packages for a few architectures are found in:
>
>  RPMS/$arch/git-*-1.6.5-1.fc9.$arch.rpm        (RPM)
>
> This cycle took a bit longer than I hoped, but here it is.  We already
> have some new features cooking in 'next', and I expect we may be able to
> have 1.6.6 by the end of the year.
>
> Enjoy.
>
> ----------------------------------------------------------------
>
> GIT v1.6.5 Release Notes
> ========================
>
> In git 1.7.0, which was planned to be the release after 1.6.5, "git
> push" into a branch that is currently checked out will be refused by
> default.
>
> You can choose what should happen upon such a push by setting the
> configuration variable receive.denyCurrentBranch in the receiving
> repository.
>
> Also, "git push $there :$killed" to delete the branch $killed in a remote
> repository $there, when $killed branch is the current branch pointed at by
> its HEAD, will be refused by default.
>
> You can choose what should happen upon such a push by setting the
> configuration variable receive.denyDeleteCurrent in the receiving
> repository.
>
> To ease the transition plan, the receiving repository of such a
> push running this release will issue a big warning when the
> configuration variable is missing.  Please refer to:
>
>  http://git.or.cz/gitwiki/GitFaq#non-bare
>  http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007
>
> for more details on the reason why this change is needed and the
> transition plan.
>
> Updates since v1.6.4
> --------------------
>
> (subsystems)
>
>  * various updates to gitk, git-svn and gitweb.
>
> (portability)
>
>  * more improvements on mingw port.
>
>  * mingw will also give FRSX as the default value for the LESS
>   environment variable when the user does not have one.
>
>  * initial support to compile git on Windows with MSVC.
>
> (performance)
>
>  * On major platforms, the system can be compiled to use with Linus's
>   block-sha1 implementation of the SHA-1 hash algorithm, which
>   outperforms the default fallback implementation we borrowed from
>   Mozilla.
>
>  * Unnecessary inefficiency in deepening of a shallow repository has
>   been removed.
>
>  * "git clone" does not grab objects that it does not need (i.e.
>   referenced only from refs outside refs/heads and refs/tags
>   hierarchy) anymore.
>
>  * The "git" main binary used to link with libcurl, which then dragged
>   in a large number of external libraries.  When using basic plumbing
>   commands in scripts, this unnecessarily slowed things down.  We now
>   implement http/https/ftp transfer as a separate executable as we
>   used to.
>
>  * "git clone" run locally hardlinks or copies the files in .git/ to
>   newly created repository.  It used to give new mtime to copied files,
>   but this delayed garbage collection to trigger unnecessarily in the
>   cloned repository.  We now preserve mtime for these files to avoid
>   this issue.
>
> (usability, bells and whistles)
>
>  * Human writable date format to various options, e.g. --since=yesterday,
>   master@{2000.09.17}, are taught to infer some omitted input properly.
>
>  * A few programs gave verbose "advice" messages to help uninitiated
>   people when issuing error messages.  An infrastructure to allow
>   users to squelch them has been introduced, and a few such messages
>   can be silenced now.
>
>  * refs/replace/ hierarchy is designed to be usable as a replacement
>   of the "grafts" mechanism, with the added advantage that it can be
>   transferred across repositories.
>
>  * "git am" learned to optionally ignore whitespace differences.
>
>  * "git am" handles input e-mail files that has CRLF line endings sensibly.
>
>  * "git am" learned "--scissors" option to allow you to discard early part
>   of an incoming e-mail.
>
>  * "git archive -o output.zip" works without being told what format to
>   use with an explicit "--format=zip".option.
>
>  * "git checkout", "git reset" and "git stash" learned to pick and
>   choose to use selected changes you made, similar to "git add -p".
>
>  * "git clone" learned a "-b" option to pick a HEAD to check out
>   different from the remote's default branch.
>
>  * "git clone" learned --recursive option.
>
>  * "git clone" from a local repository on a different filesystem used to
>   copy individual object files without preserving the old timestamp, giving
>   them extra lifetime in the new repository until they gc'ed.
>
>  * "git commit --dry-run $args" is a new recommended way to ask "what would
>   happen if I try to commit with these arguments."
>
>  * "git commit --dry-run" and "git status" shows conflicted paths in a
>   separate section to make them easier to spot during a merge.
>
>  * "git cvsimport" now supports password-protected pserver access even
>   when the password is not taken from ~/.cvspass file.
>
>  * "git fast-export" learned --no-data option that can be useful when
>   reordering commits and trees without touching the contents of
>   blobs.
>
>  * "git fast-import" has a pair of new front-end in contrib/ area.
>
>  * "git init" learned to mkdir/chdir into a directory when given an
>   extra argument (i.e. "git init this").
>
>  * "git instaweb" optionally can use mongoose as the web server.
>
>  * "git log --decorate" can optionally be told with --decorate=full to
>   give the reference name in full.
>
>  * "git merge" issued an unnecessarily scary message when it detected
>   that the merge may have to touch the path that the user has local
>   uncommitted changes to. The message has been reworded to make it
>   clear that the command aborted, without doing any harm.
>
>  * "git push" can be told to be --quiet.
>
>  * "git push" pays attention to url.$base.pushInsteadOf and uses a URL
>   that is derived from the URL used for fetching.
>
>  * informational output from "git reset" that lists the locally modified
>   paths is made consistent with that of "git checkout $another_branch".
>
>  * "git submodule" learned to give submodule name to scripts run with
>   "foreach" subcommand.
>
>  * various subcommands to "git submodule" learned --recursive option.
>
>  * "git submodule summary" learned --files option to compare the work
>   tree vs the commit bound at submodule path, instead of comparing
>   the index.
>
>  * "git upload-pack", which is the server side support for "git clone" and
>   "git fetch", can call a new post-upload-pack hook for statistics purposes.
>
> (developers)
>
>  * With GIT_TEST_OPTS="--root=/p/a/t/h", tests can be run outside the
>   source directory; using tmpfs may give faster turnaround.
>
>  * With NO_PERL_MAKEMAKER set, DESTDIR= is now honoured, so you can
>   build for one location, and install into another location to tar it
>   up.
>
> Fixes since v1.6.4
> ------------------
>
> All of the fixes in v1.6.4.X maintenance series are included in this
> release, unless otherwise noted.
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* Re: Installing full fledged git on solaris? - solved
From: Dilip M @ 2009-10-11 16:38 UTC (permalink / raw)
  To: Ben Walton; +Cc: git

On Sun, Oct 11, 2009 at 6:42 PM, Ben Walton <bwalton@artsci.utoronto.ca> wrote:
> Excerpts from Dilip M's message of Sun Oct 11 08:26:10 -0400 2009:
>
> Hi Dilip,
>
>> Has anyone has the list of pkg's to be installed on solaris 10 sparc,
>> to get the GIT compiled (with all features)..
>
> This may not be what you want, but if you use the CSW package stack,
> you can get git easily.  This is, I believe, a very complete git
> installation.  There will soon be an update to 1.6.5.
>
> http://www.opencsw.org/packages/git
>
> If your intent is to build it yourself, let me know and I'll share
> with you the build recipe I use, which will outline (within the CSW
> stack) which packages are used for compilation and which for runtime
> dependencies.  You should be able to translate it to use the
> libs/tools available to solaris 10 (that aren't in 8, which we also
> support).

Thank Ben.  You saved my day!

BTW, any info on making tig package available! Just asking...


-- 
Dilip

^ permalink raw reply

* ident pattern match is incorrect
From: Bruce Korb @ 2009-10-11 16:52 UTC (permalink / raw)
  To: git; +Cc: Bruce Korb

The git attribute "ident" fails here:

  sed '2,/and the template file/d
      /\$Id:/d
      /Last template edit:/d' getopt-test_${testname}.c

The pattern match for ident should be (shell syntax):

   $'\$Id(:[^$\n]+\$|\$)'

In other words, it is not a multi-line pattern.
I was looking for a bugzilla entry here:
   http://git-scm.com/

but I did not see a bug reporting method.

^ permalink raw reply

* git log --graph
From: Dilip M @ 2009-10-11 18:27 UTC (permalink / raw)
  To: git

I am using: git version 1.6.3.2

Somehow not getting text graph as mentioned in
http://www.gitready.com/intermediate/2009/01/26/text-based-graph.html

Any hints would really help..

I am trying git log --graph. (has commits in two branches...). But
always see one line :(




-- 
Dilip

^ permalink raw reply

* Re: git log --graph
From: Sverre Rabbelier @ 2009-10-11 18:35 UTC (permalink / raw)
  To: Dilip M; +Cc: git
In-Reply-To: <c94f8e120910111127q102aa6a1qc3c0850f8a8a1509@mail.gmail.com>

Heya,

On Sun, Oct 11, 2009 at 20:27, Dilip M <dilipm79@gmail.com> wrote:
> I am trying git log --graph. (has commits in two branches...). But
> always see one line :(

It'll show you the history of one branch at a time online, you won't
get the demo-ed multiple lines unless the branch you're looking at
contains merges.


-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* [RFC/PATCH] git: add --no-replace option to disable replacing
From: Christian Couder @ 2009-10-11 15:32 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Jakub Narebski, Johannes Sixt, bill lam, Andreas Schwab

Commit dae556b (environment: add global variable to disable replacement)
adds a variable to enable/disable replacement, and it is enabled by
default for most commands.

So there is no way to disable it for some commands, which is annoying
when we want to get information about a commit that has been replaced.

For example:

$ git cat-file -p N

would output information about the replacement commit if commit N is
replaced.

With the "--no-replace" option that this patch adds it is possible to
get information about the original commit using:

$ git --no-replace cat-file -p N

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
 git.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

	Jakub Narebski wrote:

	> Wouldn't it be better for this option to be option for git
	> wrapper, i.e.
	>
	>  $ git --no-replace cat-file -p N
	>
	> and not
	>
	>  $ git cat-file --no-replace -p N

	You mean something like this patch?

	This is untested yet. I will add some tests and documentation
	later if it's ok to add this option.


diff --git a/git.c b/git.c
index 9883009..cfef7ac 100644
--- a/git.c
+++ b/git.c
@@ -6,7 +6,7 @@
 
 const char git_usage_string[] =
 	"git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n"
-	"           [-p|--paginate|--no-pager]\n"
+	"           [-p|--paginate|--no-pager] [--no-replace]\n"
 	"           [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n"
 	"           [--help] COMMAND [ARGS]";
 
@@ -87,6 +87,8 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 			use_pager = 0;
 			if (envchanged)
 				*envchanged = 1;
+		} else if (!strcmp(cmd, "--no-replace")) {
+			read_replace_refs = 0;
 		} else if (!strcmp(cmd, "--git-dir")) {
 			if (*argc < 2) {
 				fprintf(stderr, "No directory given for --git-dir.\n" );
-- 
1.6.5.1.g31b53

^ permalink raw reply related

* Re: [ANNOUNCE] GIT 1.6.5
From: Junio C Hamano @ 2009-10-11 18:47 UTC (permalink / raw)
  To: Steven Noonan; +Cc: git
In-Reply-To: <f488382f0910110930u1af92299ld5d72dbb31ed1914@mail.gmail.com>

Steven Noonan <steven@uplinklabs.net> writes:

> Uh-oh.
>
> Alcarin:crisscross steven$ git remote update
> Updating origin
> fatal: 'git@github.com/tycho/crisscross.git' does not appear to be a
> git repository
> fatal: The remote end hung up unexpectedly
> error: Could not fetch origin

Try user@site:path/to/repo.git with a colon.  As you mentioned already,
you could also use ssh://user@site/full/path/to/repo.git

> The 'ssh://' part is omitted in numerous places on github.com. I
> realize github.com isn't the final authority on the syntax of the URI,

What do you mean by "final authority"?

Your misconfigured URL is diagnosed by the local client on your end and I
do not think it has anything to do with github.  Do you mean github.com
documentation primarily uses scp syntax (i.e. [user@]site:path/to/repo)
instead of the fake URI syntax (i.e. ssh://user@site/full/path/to/repo),
*but* misspells the former without colon (i.e. [user@]site/path/to/repo)?

If that is the case, it is something github folks need to fix, but I doubt
they have such a breakage.

> but was this an intentional change or a regression?

I do not think older clients ever allowed your colon-less scp syntax.  Do
you really see any *change*?  IOW, not the difference between the ssh://
syntax and a misspelled scp syntax, but a difference between versions of
git working and not working with a misspelled scp syntax?

Which version of git worked with "git@github.com/tycho/crisscross.git" for
you?

^ permalink raw reply

* Re: [PATCH] disallow refs containing successive slashes
From: Junio C Hamano @ 2009-10-11 18:52 UTC (permalink / raw)
  To: Jens Lehmann; +Cc: git
In-Reply-To: <4AD1B6A4.8060405@web.de>

Jens Lehmann <Jens.Lehmann@web.de> writes:

>>> I became aware of this issue while looking into problems occuring
>>> when a user created a branch starting with a '/' in git gui (e.g.
>>> "/foo"). Strange things happen, while git gui shows the current
>>> branch as "/foo" under the hood a branch "foo" (without the slash)
>>> had been created. But then you can't delete "/foo" from git gui,
>>> because a branch of that name doesn't exist.
>> 
>> Perhaps an interface to give a cleaned-up version, e.g.
>> 
>>     $ git check-ref-format --print refs/heads//foo/bar
>>     refs/heads/foo/bar
>> 
>> is what you want in order to fix git-gui?  I dunno.
>
> Yes, one solution could be to fix every application handling branch, tag
> or repo names to mimic the namechange done in the bowels of git. But i
> think it is not worth the hassle.

That cuts both ways.

When the users make typoes (e.g. /foo//bar) you can accept the only sane
correction (e.g. foo/bar) instead of rejecting, since the only thing the
user can do after getting such a rejection is to correct it to that
corrected name (e.g. foo/bar) himself and re-issue the command anyway.
You can push the "hassle" down to the user, or you can fix the tool to
remove the hassle from the user.

Besides, by rejecting what we used to accept you are breaking people's
expectations.  So I am moderately negative, unless you can say your "every
application" is literally _tons_.

^ permalink raw reply

* Re: [PATCH] git-add--interactive: never skip files included in index
From: Junio C Hamano @ 2009-10-11 18:52 UTC (permalink / raw)
  To: Pauli Virtanen; +Cc: git
In-Reply-To: <1255189906-16049-1-git-send-email-pav@iki.fi>

Thanks.

The change looks innocent enough and I do not expect to see any unexpected
regressions from it, but it is a bit too late for 1.6.5 cycle, so let's
queue this fix and aim for 1.6.5.1.

^ permalink raw reply

* Re: [ANNOUNCE] GIT 1.6.5
From: Steven Noonan @ 2009-10-11 18:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfx9pydhk.fsf@alter.siamese.dyndns.org>

On Sun, Oct 11, 2009 at 11:47 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Steven Noonan <steven@uplinklabs.net> writes:
>
>> Uh-oh.
>>
>> Alcarin:crisscross steven$ git remote update
>> Updating origin
>> fatal: 'git@github.com/tycho/crisscross.git' does not appear to be a
>> git repository
>> fatal: The remote end hung up unexpectedly
>> error: Could not fetch origin
>
> Try user@site:path/to/repo.git with a colon.  As you mentioned already,
> you could also use ssh://user@site/full/path/to/repo.git

Oops. You're right, of course. I'm going on 4 hours of sleep in 2
days, so needless to say I'm not at my best right now. Sorry for the
noise.

>
>> The 'ssh://' part is omitted in numerous places on github.com. I
>> realize github.com isn't the final authority on the syntax of the URI,
>
> What do you mean by "final authority"?

I didn't want to imply that "github says to do it this way, so git
should follow".

^ permalink raw reply

* Re: git svn with non-standard svn layout
From: Fabian Molder @ 2009-10-11 19:00 UTC (permalink / raw)
  To: git
In-Reply-To: <20091011070937.GC16264@dcvr.yhbt.net>

Eric Wong <normalperson <at> yhbt.net> writes:

...
> 
> Hi Fabian,
> 
> Since you don't want to track the entire repo and these seem like
> unrelated (history-wise) trees, you probably want the simplest cases:
> 
>   git svn clone svn://example.com/path/to/xapplication2
>   git svn clone svn://example.com/path/to/aa/bb/cc/xapplication1
> 
> These commands are like doing the following with plain old svn:
> 
>   svn co svn://example.com/path/to/xapplication2
>   svn co svn://example.com/path/to/aa/bb/cc/xapplication1
> 
> > I tried to use "git config svn-remote.svn.branches" to do this,
> >  please see in function "do_git_svn" in bash-script - but no success
> 
> svn-remote.svn.branches and tags are really only for repos with
> standard layouts.
> 

Hello Eric,
  hmm, understand,
  but this just does an checkout to the working dir

  the reason for using git is:
    - work offline, with (at least read) access to all the svn branches
    - have some more (privat, not commit back to svn) branches for experiments
    - all the nice git stuff ..
regards,
Fabian

^ permalink raw reply

* Re: [PATCH] git-add--interactive: never skip files included in index
From: Jeff King @ 2009-10-11 19:14 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Pauli Virtanen, git
In-Reply-To: <7viqelwyp1.fsf@alter.siamese.dyndns.org>

On Sun, Oct 11, 2009 at 11:52:10AM -0700, Junio C Hamano wrote:

> Thanks.
> 
> The change looks innocent enough and I do not expect to see any unexpected
> regressions from it, but it is a bit too late for 1.6.5 cycle, so let's
> queue this fix and aim for 1.6.5.1.

I think this patch is good to apply, as there is no conceivable reason
to even look at excludes when listing modified files.

But this triggered my spider sense; shouldn't --exclude-standard simply
be a no-op for ls-files when we are not listing untracked files? And
bisecting, it seems that it is a very old regression caused by 63d285c
(per-directory-exclude: lazily read .gitignore files, 2007-11-29).

I don't know if it is worth fixing now or not. It does seem a bit
inconsistent to me (since everything else is very clear that .gitignore
is only about untracked files), but nobody seems to have been
complaining for the last two years (and they may have, in fact, been
coding to the new behavior).

-Peff

^ permalink raw reply

* Re: git log --graph
From: Matthieu Moy @ 2009-10-11 19:40 UTC (permalink / raw)
  To: Sverre Rabbelier; +Cc: Dilip M, git
In-Reply-To: <fabb9a1e0910111135v4f3c75a7v6657f5dcfacf13ac@mail.gmail.com>

Sverre Rabbelier <srabbelier@gmail.com> writes:

> Heya,
>
> On Sun, Oct 11, 2009 at 20:27, Dilip M <dilipm79@gmail.com> wrote:
>> I am trying git log --graph. (has commits in two branches...). But
>> always see one line :(
>
> It'll show you the history of one branch at a time online, you won't
> get the demo-ed multiple lines unless the branch you're looking at
> contains merges.

That said, git log --graph --all will show multiple branches.

I personnally like the format of
git log --graph --pretty=oneline --abbrev-commit
with ui.color set to true in ~/.gitconfig.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox