Generate relative submodule URLs
Requires JGit version that includes
https://git.eclipse.org/r/#/c/94158.
Change-Id: Ibc213946c0e8e0235127d8c6c982a388ea1541c7
diff --git a/BUILD b/BUILD
index a32ce35..b9d6b89 100644
--- a/BUILD
+++ b/BUILD
@@ -26,5 +26,6 @@
":supermanifest__plugin",
"//gerrit-acceptance-framework:lib",
"//gerrit-plugin-api:lib",
+ "//lib/bouncycastle:bcprov",
],
)
diff --git a/src/main/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestRefUpdatedListener.java b/src/main/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestRefUpdatedListener.java
index 2a97570..9d56187 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestRefUpdatedListener.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestRefUpdatedListener.java
@@ -119,7 +119,7 @@
private static class ConfigEntry {
Project.NameKey srcRepoKey;
String srcRef;
- URI srcRepoUrl;
+ URI baseUri;
String xmlPath;
Project.NameKey destRepoKey;
boolean recordSubmoduleLabels;
@@ -127,6 +127,72 @@
// destBranch can be "*" in which case srcRef is ignored.
String destBranch;
+ ConfigEntry(Config cfg, String name) throws ConfigInvalidException {
+ String[] parts = name.split(":");
+ if (parts.length != 2) {
+ throw new ConfigInvalidException(
+ String.format("pluginName '%s' must have form REPO:BRANCH", name));
+ }
+
+ String destRepo = parts[0];
+ String destRef = parts[1];
+
+ if (!destRef.startsWith(REFS_HEADS)) {
+ throw new ConfigInvalidException(
+ String.format("invalid destination '%s'. Must specify refs/heads/", destRef));
+ }
+
+ if (destRef.contains("*") && !destRef.equals(REFS_HEADS + "*")) {
+ throw new ConfigInvalidException(
+ String.format("invalid destination '%s'. Use just '*' for all branches.", destRef));
+ }
+
+ String srcRepo = cfg.getString(SECTION_NAME, name, "srcRepo");
+ if (srcRepo == null) {
+ throw new ConfigInvalidException(String.format("entry %s did not specify srcRepo", name));
+ }
+
+ // TODO(hanwen): sanity check repo names.
+ srcRepoKey = new Project.NameKey(srcRepo);
+
+ if (destRef.equals(REFS_HEADS + "*")) {
+ srcRef = "";
+ } else {
+ if (!Repository.isValidRefName(destRef)) {
+ throw new ConfigInvalidException(String.format("destination branch '%s' invalid", destRef));
+ }
+
+ srcRef = cfg.getString(SECTION_NAME, name, "srcRef");
+ if (!Repository.isValidRefName(srcRef)) {
+ throw new ConfigInvalidException(String.format("source ref '%s' invalid", srcRef));
+ }
+
+ if (srcRef == null) {
+ throw new ConfigInvalidException(String.format("entry %s did not specify srcRef", name));
+ }
+ }
+
+ xmlPath = cfg.getString(SECTION_NAME, name, "srcPath");
+ if (xmlPath == null) {
+ throw new ConfigInvalidException(String.format("entry %s did not specify srcPath", name));
+ }
+
+ destRepoKey = new Project.NameKey(destRepo);
+
+ // The external format is chosen so we can support copying over tags as well.
+ destBranch = destRef.substring(REFS_HEADS.length());
+
+ recordSubmoduleLabels = cfg.getBoolean(SECTION_NAME, name, "recordSubmoduleLabels", false);
+
+
+ try {
+ // http://foo/platform/manifest => http://foo/platform/
+ baseUri = new URI(srcRepoKey.toString()).resolve("");
+ } catch (URISyntaxException exception) {
+ throw new ConfigInvalidException("could not build src URL", exception);
+ }
+ }
+
public String src() {
String src = srcRef;
if (destBranch.equals("*")) {
@@ -165,7 +231,6 @@
srcRepo = platforms/manifest
srcRef = refs/heads/nyc
srcPath = manifest.xml
-
*/
private Set<ConfigEntry> parseConfiguration(PluginConfigFactory cfgFactory, String name) {
Config cfg = null;
@@ -187,7 +252,7 @@
}
for (String subsect : cfg.getSubsections(SECTION_NAME)) {
try {
- ConfigEntry configEntry = newConfigEntry(cfg, subsect);
+ ConfigEntry configEntry = new ConfigEntry(cfg, subsect);
if (destinations.contains(configEntry.srcRepoKey.get())
|| sources.contains(configEntry.destRepoKey.get())) {
// Don't want cyclic dependencies.
@@ -217,76 +282,6 @@
return newConf;
}
- private ConfigEntry newConfigEntry(Config cfg, String name) throws ConfigInvalidException {
- String[] parts = name.split(":");
- if (parts.length != 2) {
- throw new ConfigInvalidException(
- String.format("pluginName '%s' must have form REPO:BRANCH", name));
- }
-
- String destRepo = parts[0];
- String destRef = parts[1];
-
- if (!destRef.startsWith(REFS_HEADS)) {
- throw new ConfigInvalidException(
- String.format("invalid destination '%s'. Must specify refs/heads/", destRef));
- }
-
- if (destRef.contains("*") && !destRef.equals(REFS_HEADS + "*")) {
- throw new ConfigInvalidException(
- String.format("invalid destination '%s'. Use just '*' for all branches.", destRef));
- }
-
- ConfigEntry e = new ConfigEntry();
- String srcRepo = cfg.getString(SECTION_NAME, name, "srcRepo");
- if (srcRepo == null) {
- throw new ConfigInvalidException(String.format("entry %s did not specify srcRepo", name));
- }
-
- // TODO(hanwen): sanity check repo names.
- e.srcRepoKey = new Project.NameKey(srcRepo);
-
- if (destRef.equals(REFS_HEADS + "*")) {
- e.srcRef = "";
- } else {
- if (!Repository.isValidRefName(destRef)) {
- throw new ConfigInvalidException(String.format("destination branch '%s' invalid", destRef));
- }
-
- e.srcRef = cfg.getString(SECTION_NAME, name, "srcRef");
- if (!Repository.isValidRefName(e.srcRef)) {
- throw new ConfigInvalidException(String.format("source ref '%s' invalid", e.srcRef));
- }
-
- if (e.srcRef == null) {
- throw new ConfigInvalidException(String.format("entry %s did not specify srcRef", name));
- }
- }
-
- e.xmlPath = cfg.getString(SECTION_NAME, name, "srcPath");
- if (e.xmlPath == null) {
- throw new ConfigInvalidException(String.format("entry %s did not specify srcPath", name));
- }
-
- e.destRepoKey = new Project.NameKey(destRepo);
-
- // The external format is chosen so we can support copying over tags as well.
- e.destBranch = destRef.substring(REFS_HEADS.length());
-
- e.recordSubmoduleLabels = cfg.getBoolean(SECTION_NAME, name, "recordSubmoduleLabels", false);
-
-
- try {
- String newPath = canonicalWebUrl.getPath() + "/" + e.srcRepoKey.toString();
- e.srcRepoUrl =
- new URIBuilder(canonicalWebUrl).setPath(newPath).build().normalize();
- } catch (URISyntaxException exception) {
- throw new ConfigInvalidException("could not build src URL", exception);
- }
-
- return e;
- }
-
private boolean checkRepoExists(Project.NameKey id) {
return projectCache.get(id) != null;
}
@@ -400,7 +395,8 @@
.setInputStream(manifestStream)
.setRecommendShallow(true)
.setRemoteReader(reader)
- .setURI(c.srcRepoUrl.toString());
+ .setTargetURI(c.destRepoKey.toString())
+ .setURI(c.baseUri.toString());
// Must setup a included file reader; the default is to read the file from the filesystem
// otherwise, which would leak data from the serving machine.
@@ -484,11 +480,11 @@
}
@VisibleForTesting
- static String urlToRepoKey(URI baseUrl, String name) {
- if (name.startsWith(baseUrl.toString())) {
+ static String urlToRepoKey(URI baseUri, String name) {
+ if (name.startsWith(baseUri.toString())) {
// It would be nice to parse the URL and do relativize on the Path, but
// I am lazy, and nio.Path considers the file system and symlinks.
- name = name.substring(baseUrl.toString().length());
+ name = name.substring(baseUri.toString().length());
while (name.startsWith("/")) {
name = name.substring(1);
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestIT.java b/src/test/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestIT.java
index 4618996..7a19516 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestIT.java
@@ -354,8 +354,11 @@
// URL is valid.
URI.create(subUrl);
+ // The suburls must be interpreted as relative to the parent project as a directory, i.e.
+ // to go from superproject/ to platform/project0, you have to do ../platform/project0
+
// URL is clean.
- assertThat(subUrl).doesNotContain("../");
+ assertThat(subUrl).isEqualTo("../" + realPrefix + "/project0");
}
@Test