]> source.dussan.org Git - jgit.git/commitdiff
RepoCommand: record manifest shallow recommendation in .gitmodules 40/73840/7
authorStefan Beller <sbeller@google.com>
Tue, 31 May 2016 22:19:52 +0000 (15:19 -0700)
committerStefan Beller <sbeller@google.com>
Tue, 31 May 2016 22:19:52 +0000 (15:19 -0700)
Git core learned about the submodule.<name>.shallow option in
.gitmodules files, which is a recommendation to clone a submodule
shallow. A repo manifest may record a clone depth recommendation as
an optional field, which contains more information than a binary
shallow/nonshallow recommendation, so any attempted conversion may be
lossy. In practice the clone depth recommendation is either '1' or doesn't
exist, which is the binary behavior we have in Git core.

Change-Id: I51aa9cb6d1d9660dae6ab6d21ad7bae9bc5325e6
Signed-off-by: Stefan Beller <sbeller@google.com>
org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java
org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java
org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoProject.java

index d12e5fc0e2ac6e45de1e7a8b30fa01fa8e303f7c..80a0250de1b1fb3b37af466cf422d25c1db813d9 100644 (file)
@@ -44,6 +44,7 @@ package org.eclipse.jgit.gitrepo;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.io.BufferedReader;
@@ -800,6 +801,53 @@ public class RepoCommandTest extends RepositoryTestCase {
                }
        }
 
+       @Test
+       public void testRecordShallowRecommendation() throws Exception {
+               try (
+                               Repository remoteDb = createBareRepository();
+                               Repository tempDb = createWorkRepository()) {
+                       StringBuilder xmlContent = new StringBuilder();
+                       xmlContent
+                               .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+                               .append("<manifest>")
+                               .append("<remote name=\"remote1\" fetch=\".\" />")
+                               .append("<default revision=\"master\" remote=\"remote1\" />")
+                               .append("<project path=\"shallow-please\" ")
+                                       .append("name=\"").append(defaultUri).append("\" ")
+                                       .append("clone-depth=\"1\" />")
+                               .append("<project path=\"non-shallow\" ")
+                                       .append("name=\"").append(defaultUri).append("\" />")
+                               .append("</manifest>");
+                       JGitTestUtil.writeTrashFile(tempDb, "manifest.xml",
+                               xmlContent.toString());
+
+                       RepoCommand command = new RepoCommand(remoteDb);
+                       command.setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
+                               .setURI(rootUri)
+                               .setRecommendShallow(true)
+                               .call();
+                       // Clone it
+                       File directory = createTempDirectory("testBareRepo");
+                       try (Repository localDb = Git.cloneRepository()
+                                       .setDirectory(directory)
+                                       .setURI(remoteDb.getDirectory().toURI().toString()).call()
+                                       .getRepository();) {
+                               // The .gitmodules file should exist
+                               File gitmodules = new File(localDb.getWorkTree(),
+                                               ".gitmodules");
+                               assertTrue("The .gitmodules file should exist",
+                                               gitmodules.exists());
+                               FileBasedConfig c = new FileBasedConfig(gitmodules,
+                                               FS.DETECTED);
+                               c.load();
+                               assertEquals("Recording shallow configuration should work", "true",
+                                               c.getString("submodule", "shallow-please", "shallow"));
+                               assertNull("Recording non shallow configuration should work",
+                                               c.getString("submodule", "non-shallow", "shallow"));
+                       }
+               }
+       }
+
        @Test
        public void testRemoteRevision() throws Exception {
                StringBuilder xmlContent = new StringBuilder();
index 796b422bb211b72de9a45c4021f59a596e919725..2370ae14c7608df2ec85783753436a3a7939c15d 100644 (file)
@@ -192,6 +192,8 @@ public class ManifestParser extends DefaultHandler {
                                        attributes.getValue("revision"), //$NON-NLS-1$
                                        attributes.getValue("remote"), //$NON-NLS-1$
                                        attributes.getValue("groups")); //$NON-NLS-1$
+                       currentProject.setRecommendShallow(
+                               attributes.getValue("clone-depth")); //$NON-NLS-1$
                } else if ("remote".equals(qName)) { //$NON-NLS-1$
                        String alias = attributes.getValue("alias"); //$NON-NLS-1$
                        String fetch = attributes.getValue("fetch"); //$NON-NLS-1$
index 6f682ee987af5d265b826428c133cf16d02218dd..ef634f3d6001e5f90b684ad47c80f656b2676df1 100644 (file)
@@ -113,6 +113,7 @@ public class RepoCommand extends GitCommand<RevCommit> {
        private String targetBranch = Constants.HEAD;
        private boolean recordRemoteBranch = false;
        private boolean recordSubmoduleLabels = false;
+       private boolean recordShallowSubmodules = false;
        private PersonIdent author;
        private RemoteReader callback;
        private InputStream inputStream;
@@ -362,6 +363,21 @@ public class RepoCommand extends GitCommand<RevCommit> {
                return this;
        }
 
+       /**
+        * Set whether the clone-depth field should be recorded as a shallow
+        * recommendation in .gitmodules.
+        * <p>
+        * Not implemented for non-bare repositories.
+        *
+        * @param enable Whether to record the shallow recommendation.
+        * @return this command
+        * @since 4.4
+        */
+       public RepoCommand setRecommendShallow(boolean enable) {
+               this.recordShallowSubmodules = enable;
+               return this;
+       }
+
        /**
         * The progress monitor associated with the clone operation. By default,
         * this is set to <code>NullProgressMonitor</code>
@@ -471,7 +487,8 @@ public class RepoCommand extends GitCommand<RevCommit> {
                                                        proj.getPath(),
                                                        proj.getRevision(),
                                                        proj.getCopyFiles(),
-                                                       proj.getGroups());
+                                                       proj.getGroups(),
+                                                       proj.getRecommendShallow());
                                }
                        } catch (GitAPIException | IOException e) {
                                throw new ManifestErrorException(e);
@@ -512,6 +529,16 @@ public class RepoCommand extends GitCommand<RevCommit> {
                                                        cfg.setString("submodule", name, "branch", //$NON-NLS-1$ //$NON-NLS-2$
                                                                        proj.getRevision());
                                                }
+
+                                               if (recordShallowSubmodules && proj.getRecommendShallow() != null) {
+                                                       // The shallow recommendation is losing information.
+                                                       // As the repo manifests stores the recommended
+                                                       // depth in the 'clone-depth' field, while
+                                                       // git core only uses a binary 'shallow = true/false'
+                                                       // hint, we'll map any depth to 'shallow = true'
+                                                       cfg.setBoolean("submodule", name, "shallow", //$NON-NLS-1$ //$NON-NLS-2$
+                                                                       true);
+                                               }
                                        }
                                        if (recordSubmoduleLabels) {
                                                StringBuilder rec = new StringBuilder();
@@ -616,10 +643,10 @@ public class RepoCommand extends GitCommand<RevCommit> {
        }
 
        private void addSubmodule(String url, String name, String revision,
-                       List<CopyFile> copyfiles, Set<String> groups)
+                       List<CopyFile> copyfiles, Set<String> groups, String recommendShallow)
                        throws GitAPIException, IOException {
                if (repo.isBare()) {
-                       RepoProject proj = new RepoProject(url, name, revision, null, groups);
+                       RepoProject proj = new RepoProject(url, name, revision, null, groups, recommendShallow);
                        proj.addCopyFiles(copyfiles);
                        bareProjects.add(proj);
                } else {
index 1b251368dee3bbc4f98394033df793295d452d5f..bcc7ffc21cd25f01ba84e859a3521e6a51c1be19 100644 (file)
@@ -70,6 +70,7 @@ public class RepoProject implements Comparable<RepoProject> {
        private final String remote;
        private final Set<String> groups;
        private final List<CopyFile> copyfiles;
+       private String recommendShallow;
        private String url;
        private String defaultRevision;
 
@@ -138,7 +139,8 @@ public class RepoProject implements Comparable<RepoProject> {
         * @since 4.4
         */
        public RepoProject(String name, String path, String revision,
-                       String remote, Set<String> groups) {
+                       String remote, Set<String> groups,
+                       String recommendShallow) {
                if (name == null) {
                        throw new NullPointerException();
                }
@@ -150,6 +152,7 @@ public class RepoProject implements Comparable<RepoProject> {
                this.revision = revision;
                this.remote = remote;
                this.groups = groups;
+               this.recommendShallow = recommendShallow;
                copyfiles = new ArrayList<CopyFile>();
        }
 
@@ -167,7 +170,7 @@ public class RepoProject implements Comparable<RepoProject> {
         */
        public RepoProject(String name, String path, String revision,
                        String remote, String groups) {
-               this(name, path, revision, remote, new HashSet<String>());
+               this(name, path, revision, remote, new HashSet<String>(), null);
                if (groups != null && groups.length() > 0)
                        this.setGroups(groups);
        }
@@ -281,6 +284,25 @@ public class RepoProject implements Comparable<RepoProject> {
                return groups;
        }
 
+       /**
+        * Return the recommendation for shallowness.
+        *
+        * @return the String of "clone-depth"
+        * @since 4.4
+        */
+       public String getRecommendShallow() {
+               return recommendShallow;
+       }
+
+       /**
+        * Sets the recommendation for shallowness.
+        *
+        * @since 4.4
+        */
+       public void setRecommendShallow(String recommendShallow) {
+               this.recommendShallow = recommendShallow;
+       }
+
        /**
         * Add a copy file configuration.
         *