From f7497e12d754041d3ef15b019ce6769cb4f1fec3 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 12 May 2008 22:03:38 -0400 Subject: [PATCH] Add tagopt parsing support to RemoteConfig C Git permits the user to specify how tags should be handled during fetch by setting remote.*.tagopt in their .git/config. Our TagOpt enum represents this same range of values, along with the translation to/from the C Git preferred setting, which for historical reasons is a GNU style --long-option rather than a simple string. We don't actually honor this setting yet in our fetch implementation, but we can read and write it now. Signed-off-by: Shawn O. Pearce --- .../spearce/jgit/transport/RemoteConfigTest.java | 52 ++++++++++++++ .../org/spearce/jgit/transport/RemoteConfig.java | 27 +++++++ .../src/org/spearce/jgit/transport/TagOpt.java | 82 ++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/TagOpt.java diff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/transport/RemoteConfigTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/transport/RemoteConfigTest.java index 675f6353..f9a5ae44 100644 --- a/org.spearce.jgit.test/tst/org/spearce/jgit/transport/RemoteConfigTest.java +++ b/org.spearce.jgit.test/tst/org/spearce/jgit/transport/RemoteConfigTest.java @@ -55,6 +55,8 @@ public class RemoteConfigTest extends RepositoryTestCase { assertNotNull(allURIs); assertNotNull(rc.getFetchRefSpecs()); assertNotNull(rc.getPushRefSpecs()); + assertNotNull(rc.getTagOpt()); + assertSame(TagOpt.AUTO_FOLLOW, rc.getTagOpt()); assertEquals(1, allURIs.size()); assertEquals("http://www.spearce.org/egit.git", allURIs.get(0)); @@ -69,6 +71,24 @@ public class RemoteConfigTest extends RepositoryTestCase { assertEquals(0, rc.getPushRefSpecs().size()); } + public void testSimpleNoTags() throws Exception { + writeConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n" + + "tagopt = --no-tags\n"); + final RemoteConfig rc = new RemoteConfig(db.getConfig(), "spearce"); + assertSame(TagOpt.NO_TAGS, rc.getTagOpt()); + } + + public void testSimpleAlwaysTags() throws Exception { + writeConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n" + + "tagopt = --tags\n"); + final RemoteConfig rc = new RemoteConfig(db.getConfig(), "spearce"); + assertSame(TagOpt.FETCH_TAGS, rc.getTagOpt()); + } + public void testMirror() throws Exception { writeConfig("[remote \"spearce\"]\n" + "url = http://www.spearce.org/egit.git\n" @@ -349,4 +369,36 @@ public class RemoteConfigTest extends RepositoryTestCase { + "[remote \"spearce\"]\n" + "\turl = /some/dir\n" + "\tfetch = +refs/heads/*:refs/remotes/spearce/*\n"); } + + public void testSaveNoTags() throws Exception { + final RemoteConfig rc = new RemoteConfig(db.getConfig(), "origin"); + rc.addURI(new URIish("/some/dir")); + rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/" + + rc.getName() + "/*")); + rc.setTagOpt(TagOpt.NO_TAGS); + rc.update(db.getConfig()); + db.getConfig().save(); + + checkFile(new File(db.getDirectory(), "config"), "[core]\n" + + "\trepositoryformatversion = 0\n" + "\tfilemode = true\n" + + "[remote \"origin\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n" + + "\ttagopt = --no-tags\n"); + } + + public void testSaveAllTags() throws Exception { + final RemoteConfig rc = new RemoteConfig(db.getConfig(), "origin"); + rc.addURI(new URIish("/some/dir")); + rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/" + + rc.getName() + "/*")); + rc.setTagOpt(TagOpt.FETCH_TAGS); + rc.update(db.getConfig()); + db.getConfig().save(); + + checkFile(new File(db.getDirectory(), "config"), "[core]\n" + + "\trepositoryformatversion = 0\n" + "\tfilemode = true\n" + + "[remote \"origin\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n" + + "\ttagopt = --tags\n"); + } } diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java b/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java index cded69c9..fe663a9f 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java @@ -44,6 +44,8 @@ public class RemoteConfig { private static final String KEY_RECEIVEPACK = "receivepack"; + private static final String KEY_TAGOPT = "tagopt"; + /** Default value for {@link #getUploadPack()} if not specified. */ public static final String DEFAULT_UPLOAD_PACK = "git-upload-pack"; @@ -62,6 +64,8 @@ public class RemoteConfig { private String receivepack; + private TagOpt tagopt; + /** * Parse a remote block from an existing configuration file. *

@@ -108,6 +112,9 @@ public class RemoteConfig { if (val == null) val = DEFAULT_RECEIVE_PACK; receivepack = val; + + val = rc.getString(SECTION, name, KEY_TAGOPT); + tagopt = TagOpt.fromOption(val); } /** @@ -136,6 +143,7 @@ public class RemoteConfig { set(rc, KEY_UPLOADPACK, getUploadPack(), DEFAULT_UPLOAD_PACK); set(rc, KEY_RECEIVEPACK, getReceivePack(), DEFAULT_RECEIVE_PACK); + set(rc, KEY_TAGOPT, getTagOpt().option(), TagOpt.AUTO_FOLLOW.option()); } private void set(final RepositoryConfig rc, final String key, @@ -283,4 +291,23 @@ public class RemoteConfig { public String getReceivePack() { return receivepack; } + + /** + * Get the description of how annotated tags should be treated during fetch. + * + * @return option indicating the behavior of annotated tags in fetch. + */ + public TagOpt getTagOpt() { + return tagopt; + } + + /** + * Set the description of how annotated tags should be treated on fetch. + * + * @param option + * method to use when handling annotated tags. + */ + public void setTagOpt(final TagOpt option) { + tagopt = option != null ? option : TagOpt.AUTO_FOLLOW; + } } diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TagOpt.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TagOpt.java new file mode 100644 index 00000000..21cbf4d5 --- /dev/null +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TagOpt.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008 Shawn Pearce + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + */ +package org.spearce.jgit.transport; + +/** Specification of annotated tag behavior during fetch. */ +public enum TagOpt { + /** + * Automatically follow tags if we fetch the thing they point at. + *

+ * This is the default behavior and tries to balance the benefit of having + * an annotated tag against the cost of possibly objects that are only on + * branches we care nothing about. Annotated tags are fetched only if we can + * prove that we already have (or will have when the fetch completes) the + * object the annotated tag peels (dereferences) to. + */ + AUTO_FOLLOW(""), + + /** + * Never fetch tags, even if we have the thing it points at. + *

+ * This option must be requested by the user and always avoids fetching + * annotated tags. It is most useful if the location you are fetching from + * publishes annotated tags, but you are not interested in the tags and only + * want their branches. + */ + NO_TAGS("--no-tags"), + + /** + * Always fetch tags, even if we do not have the thing it points at. + *

+ * Unlike {@link #AUTO_FOLLOW} the tag is always obtained. This may cause + * hundreds of megabytes of objects to be fetched if the receiving + * repository does not yet have the necessary dependencies. + */ + FETCH_TAGS("--tags"); + + private final String option; + + private TagOpt(final String o) { + option = o; + } + + /** + * Get the command line/configuration file text for this value. + * + * @return text that appears in the configuration file to activate this. + */ + public String option() { + return option; + } + + /** + * Convert a command line/configuration file text into a value instance. + * + * @param o + * the configuration file text value. + * @return the option that matches the passed parameter. + */ + public static TagOpt fromOption(final String o) { + if (o == null || o.length() == 0) + return AUTO_FOLLOW; + for (final TagOpt tagopt : values()) { + if (tagopt.option().equals(o)) + return tagopt; + } + throw new IllegalArgumentException("Invald tag option: " + o); + } +} -- 2.11.4.GIT