]> source.dussan.org Git - gitblit.git/commitdiff
Documentation. Moved clone and fetch into JGitUtils. Create bare only.
authorJames Moger <james.moger@gitblit.com>
Tue, 7 Jun 2011 23:08:24 +0000 (19:08 -0400)
committerJames Moger <james.moger@gitblit.com>
Tue, 7 Jun 2011 23:08:24 +0000 (19:08 -0400)
docs/00_index.mkd
docs/00_setup.mkd
docs/01_faq.mkd
docs/architecture.odg
docs/architecture.png
src/com/gitblit/GitBlit.java
src/com/gitblit/utils/JGitUtils.java
tests/com/gitblit/tests/GitBlitSuite.java
tests/com/gitblit/tests/JGitUtilsTest.java

index 0902733942c3511e4c64a634c88de4ad07fb050c..8c8f9322821a6fa17466b179616954d3dd62cdd0 100644 (file)
@@ -31,6 +31,7 @@ sources @ [Github][gitbltsrc]
 - Repository Owners may edit repositories through the web UI\r
 - Automatically generates a self-signed certificate for https communications\r
 - Git-notes support\r
+- Branch-selectable metrics\r
 - Dates can optionally be displayed using the browser's reported timezone\r
 - Author and Committer email address display can be controlled\r
 - Dynamic zip downloads feature\r
@@ -57,6 +58,7 @@ sources @ [Github][gitbltsrc]
 - Unit testing\r
 - Branch selector on Metrics\r
 - Blame\r
+- Clone remote repository\r
 \r
 ### Idea List\r
 - Ticgit activity/timeline\r
index 48e02b7a9112b5250dfe247a5c2856ee012ff32d..fc2fd852c3c7ed2a34cd7b08ed9e539d1e4cb1ae 100644 (file)
@@ -9,7 +9,7 @@ Open `gitblit.properties` in your favorite text editor and make sure to review a
     - *server.httpBindInterface* and *server.httpsBindInterface*<br/>\r
 **NOTE:** Consider using **https** exclusively because passwords for authentication are transmitted as clear text!     \r
     - *server.storePassword*<br/>\r
-**NOTE:** The certificate password AND the keystore password must match!     \r
+**NOTE:** If you manually generate an ssl certificate, the certificate password AND the keystore password must match!     \r
 3. Execute `gitblit.cmd` or `java -jar gitblit.jar` from a command-line\r
 4. Wait a minute or two while all dependencies are downloaded and your self-signed certificate is generated.\r
 5. Open your browser to <http://localhost> or <https://localhost> depending on your chosen configuration.\r
@@ -35,9 +35,9 @@ All repository settings are stored within the repository `.git/config` file unde
 Repository names must be unique and are CASE-SENSITIVE ON CASE-SENSITIVE FILESYSTEMS.  The name must be composed of letters, digits, or `/ _ - .`<br/>\r
 Whitespace is illegal.\r
 \r
-Repositories can be grouped by folders.  e.g. *libraries/mycoollib.git* and *libraries/myotherlib.git*\r
+Repositories can be grouped within subfolders.  e.g. *libraries/mycoollib.git* and *libraries/myotherlib.git*\r
 \r
-Repository names will automatically have *.git* appended to the name at creation time, if not already specified. \r
+All created repositories are *bare* and will automatically have *.git* appended to the name at creation time, if not already specified. \r
 \r
 #### Repository Owner\r
 The *Repository Owner* has the special permission of being able to edit a repository through the web UI.  The Repository Owner is not permitted to rename the repository, delete the repository, or reassign ownership to another user.\r
@@ -61,7 +61,7 @@ There is only one actual *role* in Gitblit and that is *#admin* which grants adm
 ### Creating your own Self-Signed Certificate\r
 \r
 Review the contents of the `makekeystore.cmd` or `makekeystore_jdk.cmd` script and execute it.<br/>\r
-**NOTE:** The certificate password AND the keystore password must match!\r
+**NOTE:** If you manually generate an ssl certificate, the certificate password AND the keystore password must match!\r
 \r
 ### Running as a Service\r
 Review the contents of the `installService.cmd` or `installService64.cmd`, as appropriate for your installed Java Virtual Machine.<br/>\r
index 5068e79a6cdfdd53b1265fc00bcc03a0aa5a323d..a80e4e29da11ebf53e2736008ca1d8a6cf216c36 100644 (file)
@@ -27,10 +27,30 @@ It's a phonetic play on [bitblt][bitblt] which is an image processing operation
 ### Why use Gitblit?\r
 It's a small tool that allows you to easily manage shared repositories and doesn't require alot of setup or git kung-foo.\r
 \r
+### Who is the target user for Gitblit?\r
+Small workgroups that require centralized repositories.\r
+\r
+Gitblit is not meant to be a social coding resource like [Github](http://github.com) or [Bitbucket](http://bitbucket.com) with 100s or 1000s of users.  Gitblit is designed to fulfill the same function as your centralized Subversion or CVS server.\r
+\r
+### Why does Gitblit exist?\r
+As a Java developer I prefer that as much of my tooling as possible is Java.<br/>\r
+Originally, I was going to use [Mercurial](http://mercurial.selenic.com) but...\r
+\r
+- MercurialEclipse [shells to Python and captures System.in](http://mercurial.808500.n3.nabble.com/Hg4J-Mercurial-pure-Java-library-tp2693090p2694555.html)<br/>\r
+Parsing command-line output is fragile and suboptimal.<br/>Unfortunately this is necessary because Mercurial is an application, not a library.\r
+- Mercurial seems to [frown](http://mercurial.808500.n3.nabble.com/Hg4J-Mercurial-pure-Java-library-tp2693090p2695051.html) on the fledgling [Hg4j][hg4j] (pure Java Mercurial) project.\r
+- Mercurial HTTP/HTTPS needs to run as CGI through Apache/IIS/etc, as mod_python through Apache, or served with a built-in http server.<br/>\r
+This requires setup and maintenance of multiple, mixed 3rd party components.\r
+\r
+Gitblit eliminates all that complication with its 100% Java stack and simple single configuration file.\r
+\r
 ### Do I need real Git?\r
 No.  Gitblit is based on [JGit][jgit] which is a pure Java implementation of the [Git version control system][git].<br/>\r
 Everything you need for Gitblit is either in the zip distribution file or automatically downloaded on execution.\r
 \r
+### Can I run Gitblit in conjunction with my existing Git tooling?\r
+Yes.  You can configure Gitblit to only be a repository viewer.\r
+\r
 ### Do I need a JDK or can I use a JRE?\r
 Gitblit will run just fine with a JRE.  Gitblit can optionally use `keytool` from the JDK to generate self-signed certificates, but normally Gitblit uses [BouncyCastle][bouncycastle] for that need.\r
 \r
@@ -73,4 +93,5 @@ Currently blame is not implemented.  Those links are placeholders to remind me w
 [jgit]: http://eclipse.org/jgit "Eclipse JGit Site"\r
 [git]: http://git-scm.com "Official Git Site"\r
 [mina]: http://mina.apache.org "Apache Mina"\r
-[bouncycastle]: http://bouncycastle.org "The Legion of the Bouncy Castle"
\ No newline at end of file
+[bouncycastle]: http://bouncycastle.org "The Legion of the Bouncy Castle"\r
+[hg4j]: http://code.google.com/p/hg4j/ "hg4j"
\ No newline at end of file
index c2fc25c0cf76b7ac05707e9365d2ab10856d9429..fd35f655ffda42121ca237ef5d2834744c6d6344 100644 (file)
Binary files a/docs/architecture.odg and b/docs/architecture.odg differ
index 0dd7ddc21ec60c603ada8a2a97a420f428af2367..c61881c32d36e14e085e03ff40b73a5a742a4772 100644 (file)
Binary files a/docs/architecture.png and b/docs/architecture.png differ
index 595a5ee1e45422f1f4f2d3cadd73f2c66b158ee0..dcf5a6b2ca59d5e307c86a184c7ee5107dd82e27 100644 (file)
@@ -226,7 +226,7 @@ public class GitBlit implements ServletContextListener {
                Repository r = null;\r
                if (isCreate) {\r
                        // ensure created repository name ends with .git\r
-                       if (!repository.name.endsWith(org.eclipse.jgit.lib.Constants.DOT_GIT_EXT)) {\r
+                       if (!repository.name.toLowerCase().endsWith(org.eclipse.jgit.lib.Constants.DOT_GIT_EXT)) {\r
                                repository.name += org.eclipse.jgit.lib.Constants.DOT_GIT_EXT;\r
                        }\r
                        if (new File(repositoriesFolder, repository.name).exists()) {\r
@@ -236,7 +236,7 @@ public class GitBlit implements ServletContextListener {
                        }\r
                        // create repository\r
                        logger.info("create repository " + repository.name);\r
-                       r = JGitUtils.createRepository(repositoriesFolder, repository.name, true);\r
+                       r = JGitUtils.createRepository(repositoriesFolder, repository.name);\r
                } else {\r
                        // rename repository\r
                        if (!repositoryName.equalsIgnoreCase(repository.name)) {\r
index 6e02b9c490e37347523e90ec6a0820324c288731..f6d7108b72feab7e1a1390020d95554b481eb0b9 100644 (file)
@@ -22,6 +22,7 @@ import java.io.InputStream;
 import java.io.OutputStream;\r
 import java.nio.charset.Charset;\r
 import java.util.ArrayList;\r
+import java.util.Arrays;\r
 import java.util.Collection;\r
 import java.util.Collections;\r
 import java.util.Date;\r
@@ -32,6 +33,8 @@ import java.util.Map.Entry;
 import java.util.zip.ZipEntry;\r
 import java.util.zip.ZipOutputStream;\r
 \r
+import org.eclipse.jgit.api.CloneCommand;\r
+import org.eclipse.jgit.api.FetchCommand;\r
 import org.eclipse.jgit.api.Git;\r
 import org.eclipse.jgit.diff.DiffEntry;\r
 import org.eclipse.jgit.diff.DiffEntry.ChangeType;\r
@@ -57,6 +60,9 @@ import org.eclipse.jgit.revwalk.RevSort;
 import org.eclipse.jgit.revwalk.RevTree;\r
 import org.eclipse.jgit.revwalk.RevWalk;\r
 import org.eclipse.jgit.revwalk.filter.RevFilter;\r
+import org.eclipse.jgit.storage.file.FileRepository;\r
+import org.eclipse.jgit.transport.FetchResult;\r
+import org.eclipse.jgit.transport.RefSpec;\r
 import org.eclipse.jgit.treewalk.TreeWalk;\r
 import org.eclipse.jgit.treewalk.filter.AndTreeFilter;\r
 import org.eclipse.jgit.treewalk.filter.OrTreeFilter;\r
@@ -90,8 +96,54 @@ public class JGitUtils {
                return r.toString().trim();\r
        }\r
 \r
-       public static Repository createRepository(File repositoriesFolder, String name, boolean bare) {\r
-               Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(bare).call();\r
+       public static FetchResult cloneRepository(File repositoriesFolder, String name, String fromUrl) throws Exception {\r
+               FetchResult result = null;\r
+               if (!name.toLowerCase().endsWith(Constants.DOT_GIT_EXT)) {\r
+                       name += Constants.DOT_GIT_EXT;\r
+               }\r
+               File folder = new File(repositoriesFolder, name);\r
+               if (folder.exists()) {\r
+                       File gitDir = FileKey.resolve(new File(repositoriesFolder, name), FS.DETECTED);\r
+                       FileRepository repository = new FileRepository(gitDir);\r
+                       result = fetchRepository(repository);\r
+                       repository.close();\r
+               } else {\r
+                       CloneCommand clone = new CloneCommand();\r
+                       clone.setBare(true);\r
+                       clone.setCloneAllBranches(true);\r
+                       clone.setURI(fromUrl);\r
+                       clone.setDirectory(folder);\r
+                       clone.call();\r
+                       // Now we have to fetch because CloneCommand doesn't fetch\r
+                       // refs/notes nor does it allow manual RefSpec.\r
+                       File gitDir = FileKey.resolve(new File(repositoriesFolder, name), FS.DETECTED);\r
+                       FileRepository repository = new FileRepository(gitDir);\r
+                       result = fetchRepository(repository);\r
+                       repository.close();\r
+               }\r
+               return result;\r
+       }\r
+\r
+       public static FetchResult fetchRepository(Repository repository, RefSpec... refSpecs)\r
+                       throws Exception {\r
+               Git git = new Git(repository);\r
+               FetchCommand fetch = git.fetch();\r
+               List<RefSpec> specs = new ArrayList<RefSpec>();\r
+               if (refSpecs == null || refSpecs.length == 0) {\r
+                       specs.add(new RefSpec("+refs/heads/*:refs/remotes/origin/*"));\r
+                       specs.add(new RefSpec("+refs/tags/*:refs/tags/*"));\r
+                       specs.add(new RefSpec("+refs/notes/*:refs/notes/*"));\r
+               } else {\r
+                       specs.addAll(Arrays.asList(refSpecs));\r
+               }\r
+               fetch.setRefSpecs(specs);\r
+               FetchResult result = fetch.call();\r
+               repository.close();\r
+               return result;\r
+       }\r
+\r
+       public static Repository createRepository(File repositoriesFolder, String name) {\r
+               Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(true).call();\r
                return git.getRepository();\r
        }\r
 \r
@@ -219,7 +271,7 @@ public class JGitUtils {
                                refs.put(objectid, new ArrayList<RefModel>());\r
                        }\r
                        refs.get(objectid).add(ref);\r
-               }               \r
+               }\r
                return refs;\r
        }\r
 \r
index fe201b8b06d9c115aeff224fead6f46a5743e91c..e13e1bbfd4d84b2bc5f90fc5d4f5cadbe18ee7a0 100644 (file)
 package com.gitblit.tests;\r
 \r
 import java.io.File;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
 \r
 import junit.extensions.TestSetup;\r
 import junit.framework.Test;\r
 import junit.framework.TestSuite;\r
 \r
-import org.eclipse.jgit.api.CloneCommand;\r
-import org.eclipse.jgit.api.FetchCommand;\r
-import org.eclipse.jgit.api.Git;\r
 import org.eclipse.jgit.lib.Repository;\r
 import org.eclipse.jgit.storage.file.FileRepository;\r
-import org.eclipse.jgit.transport.RefSpec;\r
 \r
 import com.gitblit.FileSettings;\r
 import com.gitblit.GitBlit;\r
 import com.gitblit.GitBlitException;\r
 import com.gitblit.JettyLoginService;\r
 import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.utils.JGitUtils;\r
 \r
 public class GitBlitSuite extends TestSetup {\r
        public static final File REPOSITORIES = new File("git");\r
@@ -66,11 +61,11 @@ public class GitBlitSuite extends TestSetup {
        }\r
 \r
        public static Repository getJGitRepository() throws Exception {\r
-               return new FileRepository(new File(REPOSITORIES, "nested/jgit.git"));\r
+               return new FileRepository(new File(REPOSITORIES, "test/jgit.git"));\r
        }\r
 \r
        public static Repository getBluezGnomeRepository() throws Exception {\r
-               return new FileRepository(new File(REPOSITORIES, "nested/bluez-gnome.git"));\r
+               return new FileRepository(new File(REPOSITORIES, "test/bluez-gnome.git"));\r
        }\r
 \r
        @Override\r
@@ -82,51 +77,24 @@ public class GitBlitSuite extends TestSetup {
                GitBlit.self().setLoginService(loginService);\r
 \r
                if (REPOSITORIES.exists() || REPOSITORIES.mkdirs()) {\r
-                       cloneOrFetch("helloworld.git", "https://github.com/git/hello-world.git", true);\r
-                       cloneOrFetch("ticgit.git", "https://github.com/jeffWelling/ticgit.git", true);\r
-                       cloneOrFetch("nested/bluez-gnome.git", "https://git.kernel.org/pub/scm/bluetooth/bluez-gnome.git", true);\r
-                       cloneOrFetch("nested/jgit.git", "https://github.com/eclipse/jgit.git", true);\r
-                       cloneOrFetch("nested/helloworld.git", "https://github.com/git/hello-world.git", true);\r
+                       cloneOrFetch("helloworld.git", "https://github.com/git/hello-world.git");\r
+                       cloneOrFetch("ticgit.git", "https://github.com/jeffWelling/ticgit.git");\r
+                       cloneOrFetch("test/bluez-gnome.git",\r
+                                       "https://git.kernel.org/pub/scm/bluetooth/bluez-gnome.git");\r
+                       cloneOrFetch("test/jgit.git", "https://github.com/eclipse/jgit.git");\r
+                       cloneOrFetch("test/helloworld.git", "https://github.com/git/hello-world.git");\r
 \r
                        enableTickets("ticgit.git");\r
                        enableDocs("ticgit.git");\r
                        showRemoteBranches("ticgit.git");\r
-                       showRemoteBranches("nested/jgit.git");\r
+                       showRemoteBranches("test/jgit.git");\r
                }\r
        }\r
 \r
-       private void cloneOrFetch(String toFolder, String fromUrl, boolean bare) throws Exception {\r
-               File folder = new File(REPOSITORIES, toFolder + (bare ? "" : "/.git"));\r
-               if (folder.exists()) {\r
-                       System.out.print("Updating " + (bare ? "bare " : " ") + toFolder + "... ");\r
-                       fetch(toFolder);\r
-                       System.out.println("done.");\r
-               } else {\r
-                       System.out.println("Cloning " + (bare ? "bare " : " ") + toFolder + "... ");\r
-                       CloneCommand clone = new CloneCommand();\r
-                       clone.setBare(bare);\r
-                       clone.setCloneAllBranches(true);                        \r
-                       clone.setURI(fromUrl);\r
-                       clone.setDirectory(folder);\r
-                       clone.call();\r
-                       // Now we have to fetch because CloneCommand doesn't fetch\r
-                       // Notes nor does it allow manual RefSpec.\r
-                       fetch(toFolder);\r
-                       System.out.println("done.");\r
-               }\r
-       }\r
-       \r
-       private void fetch(String toFolder) throws Exception {\r
-               FileRepository repository = new FileRepository(new File(REPOSITORIES, toFolder));\r
-               Git git = new Git(repository);\r
-               FetchCommand fetch = git.fetch();\r
-               List<RefSpec> specs = new ArrayList<RefSpec>();\r
-               specs.add(new RefSpec("+refs/heads/*:refs/remotes/origin/*"));\r
-               specs.add(new RefSpec("+refs/tags/*:refs/tags/*"));\r
-               specs.add(new RefSpec("+refs/notes/*:refs/notes/*"));\r
-               fetch.setRefSpecs(specs);\r
-               fetch.call();\r
-               repository.close();\r
+       private void cloneOrFetch(String name, String fromUrl) throws Exception {\r
+               System.out.print("Fetching " + name + "... ");\r
+               JGitUtils.cloneRepository(REPOSITORIES, name, fromUrl);\r
+               System.out.println("done.");\r
        }\r
 \r
        private void enableTickets(String repositoryName) {\r
@@ -138,7 +106,7 @@ public class GitBlitSuite extends TestSetup {
                        g.printStackTrace();\r
                }\r
        }\r
-       \r
+\r
        private void enableDocs(String repositoryName) {\r
                try {\r
                        RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);\r
@@ -148,7 +116,7 @@ public class GitBlitSuite extends TestSetup {
                        g.printStackTrace();\r
                }\r
        }\r
-       \r
+\r
        private void showRemoteBranches(String repositoryName) {\r
                try {\r
                        RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);\r
index 6646bf807a70167aefdb38cb865c63a5f8a5c08a..277166cfe78fd937d45203f51834420534b2c842 100644 (file)
@@ -30,7 +30,9 @@ import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.ObjectId;\r
 import org.eclipse.jgit.lib.PersonIdent;\r
 import org.eclipse.jgit.lib.Repository;\r
+import org.eclipse.jgit.lib.RepositoryCache.FileKey;\r
 import org.eclipse.jgit.revwalk.RevCommit;\r
+import org.eclipse.jgit.util.FS;\r
 \r
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
@@ -94,16 +96,10 @@ public class JGitUtilsTest extends TestCase {
 \r
        public void testCreateRepository() throws Exception {\r
                String[] repositories = { "NewTestRepository.git", "NewTestRepository" };\r
-               for (String repositoryName : repositories) {\r
-                       boolean isBare = repositoryName.endsWith(".git");\r
+               for (String repositoryName : repositories) {                    \r
                        Repository repository = JGitUtils.createRepository(GitBlitSuite.REPOSITORIES,\r
-                                       repositoryName, isBare);\r
-                       File folder;\r
-                       if (isBare) {\r
-                               folder = new File(GitBlitSuite.REPOSITORIES, repositoryName);\r
-                       } else {\r
-                               folder = new File(GitBlitSuite.REPOSITORIES, repositoryName + "/.git");\r
-                       }\r
+                                       repositoryName);\r
+                       File folder = FileKey.resolve(new File(GitBlitSuite.REPOSITORIES, repositoryName), FS.DETECTED);\r
                        assertTrue(repository != null);\r
                        assertFalse(JGitUtils.hasCommits(repository));\r
                        assertTrue(JGitUtils.getFirstCommit(repository, null) == null);\r
@@ -138,7 +134,7 @@ public class JGitUtilsTest extends TestCase {
        }\r
 \r
        public void testBranches() throws Exception {\r
-               Repository repository = GitBlitSuite.getTicgitRepository();\r
+               Repository repository = GitBlitSuite.getJGitRepository();\r
                for (RefModel model : JGitUtils.getLocalBranches(repository, true, -1)) {\r
                        assertTrue(model.getName().startsWith(Constants.R_HEADS));\r
                        assertTrue(model.equals(model));\r
@@ -155,14 +151,14 @@ public class JGitUtilsTest extends TestCase {
                                        + model.getName().hashCode());\r
                        assertTrue(model.getShortMessage().equals(model.getShortMessage()));\r
                }\r
-               assertTrue(JGitUtils.getRemoteBranches(repository, true, 10).size() == 10);\r
+               assertTrue(JGitUtils.getRemoteBranches(repository, true, 8).size() == 8);\r
                repository.close();\r
        }\r
 \r
        public void testTags() throws Exception {\r
-               Repository repository = GitBlitSuite.getTicgitRepository();\r
+               Repository repository = GitBlitSuite.getJGitRepository();\r
                for (RefModel model : JGitUtils.getTags(repository, true, -1)) {\r
-                       if (model.getObjectId().getName().equals("283035e4848054ff1803cb0e690270787dc92399")) {\r
+                       if (model.getObjectId().getName().equals("d28091fb2977077471138fe97da1440e0e8ae0da")) {\r
                                assertTrue("Not an annotated tag!", model.isAnnotatedTag());\r
                        }\r
                        assertTrue(model.getName().startsWith(Constants.R_TAGS));\r