| // Copyright (C) 2016 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package com.googlesource.gerrit.plugins.supermanifest; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| import static com.google.common.truth.Truth.assertWithMessage; |
| import static com.google.gerrit.testing.GerritJUnit.assertThrows; |
| import static java.nio.charset.StandardCharsets.UTF_8; |
| |
| import com.google.gerrit.acceptance.GitUtil; |
| import com.google.gerrit.acceptance.LightweightPluginDaemonTest; |
| import com.google.gerrit.acceptance.PushOneCommit; |
| import com.google.gerrit.acceptance.PushOneCommit.Result; |
| import com.google.gerrit.acceptance.TestPlugin; |
| import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; |
| import com.google.gerrit.entities.Project; |
| import com.google.gerrit.entities.RefNames; |
| import com.google.gerrit.extensions.api.projects.BranchApi; |
| import com.google.gerrit.extensions.config.DownloadScheme; |
| import com.google.gerrit.extensions.registration.DynamicMap; |
| import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl; |
| import com.google.gerrit.extensions.restapi.ResourceNotFoundException; |
| import com.google.inject.Inject; |
| import com.google.inject.util.Providers; |
| import java.net.URI; |
| import java.util.Arrays; |
| import org.apache.commons.lang3.RandomStringUtils; |
| import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; |
| import org.eclipse.jgit.junit.TestRepository; |
| import org.eclipse.jgit.lib.BlobBasedConfig; |
| import org.eclipse.jgit.lib.Config; |
| import org.eclipse.jgit.revwalk.RevCommit; |
| import org.junit.Test; |
| |
| @TestPlugin( |
| name = "supermanifest", |
| sysModule = "com.googlesource.gerrit.plugins.supermanifest.SuperManifestModule") |
| public class JiriSuperManifestIT extends LightweightPluginDaemonTest { |
| |
| Project.NameKey[] testRepoKeys; |
| |
| @Inject private ProjectOperations projectOperations; |
| @Inject private DynamicMap<DownloadScheme> downloadScheme; |
| |
| void setupTestRepos(String prefix) throws Exception { |
| // Set up download schemes for test repos. |
| PrivateInternals_DynamicMapImpl<DownloadScheme> downloadSchemeImpl = |
| (PrivateInternals_DynamicMapImpl<DownloadScheme>) downloadScheme; |
| String host = URI.create(canonicalWebUrl.get()).getHost(); |
| downloadSchemeImpl.put("supermanifest", "https", Providers.of(new TestDownloadScheme(host))); |
| |
| testRepoKeys = new Project.NameKey[2]; |
| for (int i = 0; i < 2; i++) { |
| testRepoKeys[i] = |
| projectOperations |
| .newProject() |
| .name(RandomStringUtils.randomAlphabetic(8) + prefix + i) |
| .create(); |
| |
| TestRepository<InMemoryRepository> repo = cloneProject(testRepoKeys[i], admin); |
| |
| PushOneCommit push = |
| pushFactory.create(admin.newIdent(), repo, "Subject", "file" + i, "file"); |
| push.to("refs/heads/master").assertOkStatus(); |
| } |
| } |
| |
| void pushConfig(String config) throws Exception { |
| // This will trigger a configuration reload. |
| TestRepository<InMemoryRepository> allProjectRepo = cloneProject(allProjects, admin); |
| GitUtil.fetch(allProjectRepo, RefNames.REFS_CONFIG + ":config"); |
| allProjectRepo.reset("config"); |
| PushOneCommit push = |
| pushFactory.create( |
| admin.newIdent(), allProjectRepo, "Subject", "supermanifest.config", config); |
| PushOneCommit.Result res = push.to("refs/meta/config"); |
| res.assertOkStatus(); |
| } |
| |
| @Test |
| public void basicFunctionalityWorks() throws Exception { |
| setupTestRepos("project"); |
| |
| // Make sure the manifest exists so the configuration loads successfully. |
| Project.NameKey manifestKey = projectOperations.newProject().name(name("manifest")).create(); |
| TestRepository<InMemoryRepository> manifestRepo = cloneProject(manifestKey, admin); |
| |
| Project.NameKey superKey = projectOperations.newProject().name(name("superproject")).create(); |
| cloneProject(superKey, admin); |
| |
| pushConfig( |
| "[superproject \"" |
| + superKey.get() |
| + ":refs/heads/destbranch\"]\n" |
| + " srcRepo = " |
| + manifestKey.get() |
| + "\n" |
| + " srcRef = refs/heads/srcbranch\n" |
| + " srcPath = default\n" |
| + " toolType = jiri\n"); |
| |
| // XML change will trigger commit to superproject. |
| String xml = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + "<project name=\"" |
| + testRepoKeys[0].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[0].get() |
| + "\" path=\"project1\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "default", xml) |
| .to("refs/heads/srcbranch") |
| .assertOkStatus(); |
| |
| BranchApi branch = gApi.projects().name(superKey.get()).branch("refs/heads/destbranch"); |
| assertThat(branch.file("project1").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| Config base = new Config(); |
| BlobBasedConfig cfg = |
| new BlobBasedConfig(base, branch.file(".gitmodules").asString().getBytes(UTF_8)); |
| assertThat(cfg.getString("submodule", "project1", "branch")).isEqualTo("master"); |
| assertThrows(ResourceNotFoundException.class, () -> branch.file("project2")); |
| |
| xml = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + " <project name=\"" |
| + testRepoKeys[0].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[0].get() |
| + "\" path=\"project1\" />\n" |
| + " <project name=\"" |
| + testRepoKeys[1].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[1].get() |
| + "\" path=\"project2\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "default", xml) |
| .to("refs/heads/srcbranch") |
| .assertOkStatus(); |
| |
| BranchApi branch2 = gApi.projects().name(superKey.get()).branch("refs/heads/destbranch"); |
| assertThat(branch2.file("project2").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| |
| // Make sure config change gets picked up. |
| pushConfig( |
| "[superproject \"" |
| + superKey.get() |
| + ":refs/heads/other\"]\n" |
| + " srcRepo = " |
| + manifestKey.get() |
| + "\n" |
| + " srcRef = refs/heads/srcbranch\n" |
| + " srcPath = default\n" |
| + " toolType = jiri\n"); |
| |
| // Push another XML change; this should trigger a commit using the new config. |
| xml = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + " <project name=\"" |
| + testRepoKeys[1].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[1].get() |
| + "\" path=\"project3\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "default", xml) |
| .to("refs/heads/srcbranch") |
| .assertOkStatus(); |
| |
| BranchApi branch3 = gApi.projects().name(superKey.get()).branch("refs/heads/other"); |
| assertThat(branch3.file("project3").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| } |
| |
| @Test |
| public void ImportTagWorks() throws Exception { |
| setupTestRepos("project"); |
| |
| // Make sure the manifest exists so the configuration loads successfully. |
| Project.NameKey manifest1Key = projectOperations.newProject().name(name("manifest1")).create(); |
| TestRepository<InMemoryRepository> manifest1Repo = cloneProject(manifest1Key, admin); |
| |
| Project.NameKey manifest2Key = projectOperations.newProject().name(name("manifest2")).create(); |
| TestRepository<InMemoryRepository> manifest2Repo = cloneProject(manifest2Key, admin); |
| |
| Project.NameKey superKey = projectOperations.newProject().name(name("superproject")).create(); |
| cloneProject(superKey, admin); |
| |
| pushConfig( |
| "[superproject \"" |
| + superKey.get() |
| + ":refs/heads/destbranch\"]\n" |
| + " srcRepo = " |
| + manifest1Key.get() |
| + "\n" |
| + " srcRef = refs/heads/srcbranch\n" |
| + " srcPath = default\n" |
| + " toolType = jiri\n"); |
| |
| // XML change will trigger commit to superproject. |
| String xml1 = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<imports>\n" |
| + "<import name=\"" |
| + manifest2Key.get() |
| + "\" manifest=\"default\" remote=\"" |
| + canonicalWebUrl.get() |
| + manifest2Key.get() |
| + "\" />\n</imports>" |
| + "<projects>\n" |
| + "<project name=\"" |
| + testRepoKeys[0].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[0].get() |
| + "\" path=\"project1\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| String xml2 = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + "<project name=\"" |
| + manifest2Key.get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + manifest2Key.get() |
| + "\" path=\"manifest2\" />\n" |
| + "</projects>\n</manifest>\n"; |
| pushFactory |
| .create(admin.newIdent(), manifest2Repo, "Subject", "default", xml2) |
| .to("refs/heads/master") |
| .assertOkStatus(); |
| pushFactory |
| .create(admin.newIdent(), manifest1Repo, "Subject", "default", xml1) |
| .to("refs/heads/srcbranch") |
| .assertOkStatus(); |
| |
| BranchApi branch = gApi.projects().name(superKey.get()).branch("refs/heads/destbranch"); |
| assertThat(branch.file("project1").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| assertThat(branch.file("manifest2").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| } |
| |
| @Test |
| public void ImportTagWithRevisionWorks() throws Exception { |
| setupTestRepos("project"); |
| |
| // Make sure the manifest exists so the configuration loads successfully. |
| Project.NameKey manifest1Key = projectOperations.newProject().name(name("manifest1")).create(); |
| TestRepository<InMemoryRepository> manifest1Repo = cloneProject(manifest1Key, admin); |
| |
| Project.NameKey manifest2Key = projectOperations.newProject().name(name("manifest2")).create(); |
| TestRepository<InMemoryRepository> manifest2Repo = cloneProject(manifest2Key, admin); |
| |
| Project.NameKey superKey = projectOperations.newProject().name(name("superproject")).create(); |
| cloneProject(superKey, admin); |
| |
| pushConfig( |
| "[superproject \"" |
| + superKey.get() |
| + ":refs/heads/destbranch\"]\n" |
| + " srcRepo = " |
| + manifest1Key.get() |
| + "\n" |
| + " srcRef = refs/heads/srcbranch\n" |
| + " srcPath = default\n" |
| + " toolType = jiri\n"); |
| |
| String xml2 = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + "<project name=\"" |
| + manifest2Key.get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + manifest2Key.get() |
| + "\" path=\"manifest2\" />\n" |
| + "</projects>\n</manifest>\n"; |
| Result c = |
| pushFactory |
| .create(admin.newIdent(), manifest2Repo, "Subject", "default", xml2) |
| .to("refs/heads/master"); |
| c.assertOkStatus(); |
| RevCommit commit = c.getCommit(); |
| |
| // Add new project, that should not be imported |
| xml2 = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + "<project name=\"" |
| + manifest2Key.get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + manifest2Key.get() |
| + "\" path=\"manifest2\" />\n" |
| + "<project name=\"" |
| + testRepoKeys[1].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[1].get() |
| + "\" path=\"project2\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifest2Repo, "Subject", "default", xml2) |
| .to("refs/heads/master") |
| .assertOkStatus(); |
| |
| // XML change will trigger commit to superproject. |
| String xml1 = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<imports>\n" |
| + "<import name=\"" |
| + manifest2Key.get() |
| + "\" manifest=\"default\" remote=\"" |
| + canonicalWebUrl.get() |
| + manifest2Key.get() |
| + "\" revision=\"" |
| + commit.name() |
| + "\"/>\n</imports>" |
| + "<projects>\n" |
| + "<project name=\"" |
| + testRepoKeys[0].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[0].get() |
| + "\" path=\"project1\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifest1Repo, "Subject", "default", xml1) |
| .to("refs/heads/srcbranch") |
| .assertOkStatus(); |
| |
| BranchApi branch = gApi.projects().name(superKey.get()).branch("refs/heads/destbranch"); |
| assertThat(branch.file("project1").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| assertThat(branch.file("manifest2").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| assertThat(branch.file("manifest2").asString()).contains(commit.name()); |
| assertThrows(ResourceNotFoundException.class, () -> branch.file("project2")); |
| } |
| |
| @Test |
| public void ImportTagWithRemoteBranchWorks() throws Exception { |
| setupTestRepos("project"); |
| |
| // Make sure the manifest exists so the configuration loads successfully. |
| Project.NameKey manifest1Key = projectOperations.newProject().name(name("manifest1")).create(); |
| TestRepository<InMemoryRepository> manifest1Repo = cloneProject(manifest1Key, admin); |
| |
| Project.NameKey manifest2Key = projectOperations.newProject().name(name("manifest2")).create(); |
| TestRepository<InMemoryRepository> manifest2Repo = cloneProject(manifest2Key, admin); |
| |
| Project.NameKey superKey = projectOperations.newProject().name(name("superproject")).create(); |
| cloneProject(superKey, admin); |
| |
| pushConfig( |
| "[superproject \"" |
| + superKey.get() |
| + ":refs/heads/destbranch\"]\n" |
| + " srcRepo = " |
| + manifest1Key.get() |
| + "\n" |
| + " srcRef = refs/heads/srcbranch\n" |
| + " srcPath = default\n" |
| + " toolType = jiri\n"); |
| |
| String xml2 = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + "<project name=\"" |
| + manifest2Key.get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + manifest2Key.get() |
| + "\" path=\"manifest2\" />\n" |
| + "</projects>\n</manifest>\n"; |
| pushFactory |
| .create(admin.newIdent(), manifest2Repo, "Subject", "default", xml2) |
| .to("refs/heads/b1") |
| .assertOkStatus(); |
| |
| // Add new project, that should not be imported |
| xml2 = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + "<project name=\"" |
| + manifest2Key.get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + manifest2Key.get() |
| + "\" path=\"manifest2\" />\n" |
| + "<project name=\"" |
| + testRepoKeys[1].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[1].get() |
| + "\" path=\"project2\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifest2Repo, "Subject", "default", xml2) |
| .to("refs/heads/master") |
| .assertOkStatus(); |
| |
| // XML change will trigger commit to superproject. |
| String xml1 = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<imports>\n" |
| + "<import name=\"" |
| + manifest2Key.get() |
| + "\" manifest=\"default\" remote=\"" |
| + canonicalWebUrl.get() |
| + manifest2Key.get() |
| + "\" remotebranch=\"b1\" />\n</imports>" |
| + "<projects>\n" |
| + "<project name=\"" |
| + testRepoKeys[0].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[0].get() |
| + "\" path=\"project1\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifest1Repo, "Subject", "default", xml1) |
| .to("refs/heads/srcbranch") |
| .assertOkStatus(); |
| |
| BranchApi branch = gApi.projects().name(superKey.get()).branch("refs/heads/destbranch"); |
| assertThat(branch.file("project1").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| assertThat(branch.file("manifest2").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| assertThrows(ResourceNotFoundException.class, () -> branch.file("project2")); |
| } |
| |
| private void outer() throws Exception { |
| inner(); |
| } |
| |
| private void inner() { |
| throw new IllegalStateException(); |
| } |
| |
| private void innerTest() throws Exception { |
| IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> outer()); |
| StackTraceElement[] trimmed = |
| SuperManifestRefUpdatedListener.trimStack( |
| thrown.getStackTrace(), Thread.currentThread().getStackTrace()[1]); |
| String str = Arrays.toString(trimmed); |
| assertThat(str).doesNotContain("trimStackTrace"); |
| assertThat(str).contains("innerTest"); |
| } |
| |
| @Test |
| public void trimStackTrace() throws Exception { |
| innerTest(); |
| } |
| |
| @Test |
| public void wildcardDestBranchWorks() throws Exception { |
| setupTestRepos("project"); |
| |
| // Make sure the manifest exists so the configuration loads successfully. |
| Project.NameKey manifestKey = projectOperations.newProject().name(name("manifest")).create(); |
| TestRepository<InMemoryRepository> manifestRepo = cloneProject(manifestKey, admin); |
| |
| Project.NameKey superKey = projectOperations.newProject().name(name("superproject")).create(); |
| cloneProject(superKey, admin); |
| |
| pushConfig( |
| "[superproject \"" |
| + superKey.get() |
| + ":refs/heads/*\"]\n" |
| + " srcRepo = " |
| + manifestKey.get() |
| + "\n" |
| + " srcRef = blablabla\n" |
| + " srcPath = default\n" |
| + " toolType = jiri\n"); |
| |
| // XML change will trigger commit to superproject. |
| String xml = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + " <project name=\"" |
| + testRepoKeys[0].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[0].get() |
| + "\" path=\"project1\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "default", xml) |
| .to("refs/heads/src1") |
| .assertOkStatus(); |
| |
| xml = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + " <project name=\"" |
| + testRepoKeys[1].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[1].get() |
| + "\" path=\"project2\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "default", xml) |
| .to("refs/heads/src2") |
| .assertOkStatus(); |
| |
| BranchApi branch1 = gApi.projects().name(superKey.get()).branch("refs/heads/src1"); |
| assertThat(branch1.file("project1").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| assertThrows(ResourceNotFoundException.class, () -> branch1.file("project2")); |
| |
| BranchApi branch2 = gApi.projects().name(superKey.get()).branch("refs/heads/src2"); |
| assertThat(branch2.file("project2").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| assertThrows(ResourceNotFoundException.class, () -> branch2.file("project1")); |
| } |
| |
| @Test |
| public void relativeFetch() throws Exception { |
| // Test that first party gerrit repos are represented by relative URLs in supermanifest and |
| // external repos by their absolute URLs. |
| setupTestRepos("platform/project"); |
| |
| String realPrefix = testRepoKeys[0].get().split("/")[0]; |
| |
| Project.NameKey manifestKey = |
| projectOperations.newProject().name(name(realPrefix + "/manifest")).create(); |
| TestRepository<InMemoryRepository> manifestRepo = cloneProject(manifestKey, admin); |
| |
| Project.NameKey superKey = projectOperations.newProject().name(name("superproject")).create(); |
| pushConfig( |
| "[superproject \"" |
| + superKey.get() |
| + ":refs/heads/destbranch\"]\n" |
| + " srcRepo = " |
| + manifestKey.get() |
| + "\n" |
| + " srcRef = refs/heads/srcbranch\n" |
| + " srcPath = default\n" |
| + " toolType = jiri\n"); |
| |
| // XML change will trigger commit to superproject. |
| String xml = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + "<project name=\"" |
| + testRepoKeys[0].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[0].get() |
| + "\" path=\"project1\" />\n" |
| + "<project name=\"external1\"" |
| + " remote=\"https://external/repo\"" |
| + " revision=\"c438d02cdf08a08fe29550cb11cb6ae8190919f1\"" |
| + " path=\"project2\" />\n" |
| + "<project name=\"external2\"" |
| + " remote=\"https://external/" |
| + testRepoKeys[1].get() |
| + "\"" |
| + " revision=\"c438d02cdf08a08fe29550cb11cb6ae8190919f1\"" |
| + " path=\"project3\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "default", xml) |
| .to("refs/heads/srcbranch") |
| .assertOkStatus(); |
| |
| BranchApi branch = gApi.projects().name(superKey.get()).branch("refs/heads/destbranch"); |
| assertThat(branch.file("project1").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| assertThat(branch.file("project2").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| |
| Config base = new Config(); |
| BlobBasedConfig cfg = |
| new BlobBasedConfig(base, branch.file(".gitmodules").asString().getBytes(UTF_8)); |
| |
| String subUrl = cfg.getString("submodule", "project1", "url"); |
| |
| // URL is valid. |
| URI.create(subUrl); |
| |
| // The suburl 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).isEqualTo("../" + realPrefix + "/project0"); |
| |
| subUrl = cfg.getString("submodule", "project2", "url"); |
| |
| // URL is valid. |
| URI.create(subUrl); |
| |
| // The suburl must be absolute as this is external repo |
| |
| assertThat(subUrl).isEqualTo("https://external/repo"); |
| |
| subUrl = cfg.getString("submodule", "project3", "url"); |
| |
| // URL is valid. |
| URI.create(subUrl); |
| |
| // Though the this project has the same name as a local repo, the subUrl must be absolute |
| // as this is an external repo. |
| assertThat(subUrl).isEqualTo("https://external/" + testRepoKeys[1].get()); |
| |
| assertThat(cfg.getString("submodule", "project1", "branch")).isEqualTo("master"); |
| assertThat(cfg.getString("submodule", "project2", "branch")).isNull(); |
| assertThat(cfg.getString("submodule", "project3", "branch")).isNull(); |
| } |
| |
| @Test |
| public void manifestIncludesOtherManifest() throws Exception { |
| setupTestRepos("project"); |
| |
| String xml = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + "<project name=\"" |
| + testRepoKeys[0].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[0].get() |
| + "\" path=\"project1\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| Project.NameKey manifestKey = projectOperations.newProject().name(name("manifest")).create(); |
| TestRepository<InMemoryRepository> manifestRepo = cloneProject(manifestKey, admin); |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "default", xml) |
| .to("refs/heads/master") |
| .assertOkStatus(); |
| |
| String superXml = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" |
| + "<manifest>\n<imports>\n" |
| + " <localimport file=\"default\"/>" |
| + "</imports>\n</manifest>"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "super", superXml) |
| .to("refs/heads/master") |
| .assertOkStatus(); |
| |
| Project.NameKey superKey = projectOperations.newProject().name(name("superproject")).create(); |
| cloneProject(superKey, admin); |
| |
| pushConfig( |
| "[superproject \"" |
| + superKey.get() |
| + ":refs/heads/master\"]\n" |
| + " srcRepo = " |
| + manifestKey.get() |
| + "\n" |
| + " srcRef = refs/heads/master\n" |
| + " srcPath = super\n" |
| + " toolType = jiri\n"); |
| |
| // Push a change to the source branch. We intentionally change the included XML file |
| // (rather than the one mentioned in srcPath), to double check that we don't try to be too |
| // smart about eluding nops. |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "default", xml + " ") |
| .to("refs/heads/master") |
| .assertOkStatus(); |
| |
| BranchApi branch = gApi.projects().name(superKey.get()).branch("refs/heads/master"); |
| assertThat(branch.file("project1").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8"); |
| } |
| |
| @Test |
| public void remoteImportFails() throws Exception { |
| setupTestRepos("project"); |
| |
| String xml = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<manifest>\n<projects>\n" |
| + "<project name=\"" |
| + testRepoKeys[0].get() |
| + "\" remote=\"" |
| + canonicalWebUrl.get() |
| + testRepoKeys[0].get() |
| + "\" path=\"project1\" />\n" |
| + "</projects>\n</manifest>\n"; |
| |
| Project.NameKey manifestKey = projectOperations.newProject().name(name("manifest")).create(); |
| Project.NameKey superKey = projectOperations.newProject().name(name("superproject")).create(); |
| |
| cloneProject(superKey, admin); |
| |
| pushConfig( |
| "[superproject \"" |
| + superKey.get() |
| + ":refs/heads/master\"]\n" |
| + " srcRepo = " |
| + manifestKey.get() |
| + "\n" |
| + " srcRef = refs/heads/master\n" |
| + " srcPath = super\n" |
| + " toolType = jiri\n"); |
| TestRepository<InMemoryRepository> manifestRepo = cloneProject(manifestKey, admin); |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "default", xml) |
| .to("refs/heads/master") |
| .assertOkStatus(); |
| |
| String superXml = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" |
| + "<manifest>\n<imports>\n" |
| + "<import manifest=\"" |
| + manifestKey.get() |
| + "\" name=\"default\" remote=\"" |
| + canonicalWebUrl.get() |
| + manifestKey.get() |
| + "\"/>" |
| + "</imports>\n</manifest>"; |
| |
| pushFactory |
| .create(admin.newIdent(), manifestRepo, "Subject", "super", superXml) |
| .to("refs/heads/master") |
| .assertOkStatus(); |
| |
| BranchApi branch = gApi.projects().name(superKey.get()).branch("refs/heads/master"); |
| assertThrows(ResourceNotFoundException.class, () -> branch.file("project1")); |
| } |
| |
| void testRelative(String a, String b, String want) throws Exception { |
| String got = JiriUpdater.relativize(URI.create(a), URI.create(b)).toString(); |
| |
| assertWithMessage("relative('%s', '%s')", a, b).that(got).isEqualTo(want); |
| } |
| |
| @Test |
| public void relative() throws Exception { |
| testRelative("a/b/", "a/", "../"); |
| // Normalization: |
| testRelative("a/p/..//b/", "a/", "../"); |
| testRelative("a/b", "a/", ""); |
| testRelative("a/", "a/b/", "b/"); |
| testRelative("a/", "a/b", "b"); |
| testRelative("/a/b/c", "/b/c", "../../b/c"); |
| testRelative("/abc", "bcd", "bcd"); |
| testRelative("abc", "def", "def"); |
| testRelative("abc", "/bcd", "/bcd"); |
| testRelative("http://a", "a/b", "a/b"); |
| testRelative("http://base.com/a/", "http://child.com/a/b", "http://child.com/a/b"); |
| } |
| |
| // Modified from com.google.gerrit.acceptance.api.accounts.GeneralPreferencesIT.TestDownloadScheme |
| private static class TestDownloadScheme extends DownloadScheme { |
| |
| private String host; |
| |
| public TestDownloadScheme(String host) { |
| this.host = host; |
| } |
| |
| @Override |
| public String getUrl(String project) { |
| return "https://" + this.host + "/" + project; |
| } |
| |
| @Override |
| public boolean isAuthRequired() { |
| return false; |
| } |
| |
| @Override |
| public boolean isAuthSupported() { |
| return false; |
| } |
| |
| @Override |
| public boolean isEnabled() { |
| return true; |
| } |
| |
| @Override |
| public boolean isHidden() { |
| return false; |
| } |
| } |
| } |