From dee4240ce86f21d262ac071ed80838223bf4d516 Mon Sep 17 00:00:00 2001 From: Ivan Frade Date: Thu, 26 Aug 2021 13:19:01 -0700 Subject: RepoCommand: Move bare/regular superproject writing to their own classes RepoCommand parses the manifest to get a list of projects, clears up conflicts and then writes to the superproject. The first steps are common but the writing is completely different for bare or "regular" (with working dir) repository. Split writing to bare and regular repos into its own classes. This simplifies RepoCommand class and makes clearer what happens on each side (e.g. many options apply only to bare repos). Change-Id: I256e15729bd53ee15fc56de88bce86a2edb2417a --- .../jgit/gitrepo/BareSuperprojectWriterTest.java | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/BareSuperprojectWriterTest.java (limited to 'org.eclipse.jgit.test/tst/org/eclipse') diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/BareSuperprojectWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/BareSuperprojectWriterTest.java new file mode 100644 index 0000000000..d52292dc97 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/BareSuperprojectWriterTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2021, Google Inc. and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.gitrepo; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jgit.gitrepo.BareSuperprojectWriter.BareWriterConfig; +import org.eclipse.jgit.gitrepo.RepoCommand.RemoteReader; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectReader; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.junit.Test; + +public class BareSuperprojectWriterTest extends RepositoryTestCase { + + private static final String SHA1_A = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + + @Override + public void setUp() throws Exception { + super.setUp(); + } + + @Test + public void write_setGitModulesContents() throws Exception { + try (Repository bareRepo = createBareRepository()) { + RepoProject repoProject = new RepoProject("subprojectX", "path/to", + "refs/heads/branch-x", "remote", ""); + repoProject.setUrl("http://example.com/a"); + + RemoteReader mockRemoteReader = mock(RemoteReader.class); + when(mockRemoteReader.sha1("http://example.com/a", + "refs/heads/branch-x")) + .thenReturn(ObjectId.fromString(SHA1_A)); + + BareSuperprojectWriter w = new BareSuperprojectWriter(bareRepo, + null, "refs/heads/master", author, mockRemoteReader, + BareWriterConfig.getDefault()); + + RevCommit commit = w.write(Arrays.asList(repoProject)); + + String contents = readContents(bareRepo, commit, ".gitmodules"); + List contentLines = Arrays + .asList(contents.split("\n")); + assertThat(contentLines.get(0), + is("[submodule \"subprojectX\"]")); + assertThat(contentLines.subList(1, contentLines.size()), + containsInAnyOrder(is("\tbranch = refs/heads/branch-x"), + is("\tpath = path/to"), + is("\turl = http://example.com/a"))); + } + } + + private String readContents(Repository repo, RevCommit commit, + String path) throws Exception { + String idStr = commit.getId().name() + ":" + path; + ObjectId modId = repo.resolve(idStr); + try (ObjectReader reader = repo.newObjectReader()) { + return new String( + reader.open(modId).getCachedBytes(Integer.MAX_VALUE)); + + } + } +} -- cgit v1.2.3 From dba66dbfce4dfa173ab884ba2d5c0bdf5f1b219c Mon Sep 17 00:00:00 2001 From: Ivan Frade Date: Tue, 23 Nov 2021 14:42:01 -0800 Subject: RepoCommand: Offer to set extra files in the destination repository We want to save in the destination repository what manifest created its structure. This helps to detect and debug failures in the manifest -> superproject translations. The src commit should be easily readable from the superproject tip. Offer an API to write a file in the destination repository. RepoCommand callers (e.g. gerrit supermanifest plugin) can use this to add a file with the repo/ref/hash of the manifest. Alternatives considered to write the source repo/ref/hash: * .gitattributes of the .gitmodules file. Some updates in the manifest don't touch the .gitmodules (e.g. a linkfile change), so it can fall out of sync. * commit message. Caller would need to follow the commit history to find the latest modification by repo command. This is not helpful e.g. for build bots that want to get the value in one call. Change-Id: I113662734a7ccd39cbc60b46ad3f73038c807682 --- .../jgit/gitrepo/BareSuperprojectWriterTest.java | 27 +++++++++++++++++++++- .../jgit/gitrepo/BareSuperprojectWriter.java | 27 +++++++++++++++++++++- .../src/org/eclipse/jgit/gitrepo/RepoCommand.java | 22 ++++++++++++++++-- 3 files changed, 72 insertions(+), 4 deletions(-) (limited to 'org.eclipse.jgit.test/tst/org/eclipse') diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/BareSuperprojectWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/BareSuperprojectWriterTest.java index d52292dc97..17fc8db35e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/BareSuperprojectWriterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/BareSuperprojectWriterTest.java @@ -50,7 +50,7 @@ public class BareSuperprojectWriterTest extends RepositoryTestCase { BareSuperprojectWriter w = new BareSuperprojectWriter(bareRepo, null, "refs/heads/master", author, mockRemoteReader, - BareWriterConfig.getDefault()); + BareWriterConfig.getDefault(), List.of()); RevCommit commit = w.write(Arrays.asList(repoProject)); @@ -66,6 +66,31 @@ public class BareSuperprojectWriterTest extends RepositoryTestCase { } } + @Test + public void write_setExtraContents() throws Exception { + try (Repository bareRepo = createBareRepository()) { + RepoProject repoProject = new RepoProject("subprojectX", "path/to", + "refs/heads/branch-x", "remote", ""); + repoProject.setUrl("http://example.com/a"); + + RemoteReader mockRemoteReader = mock(RemoteReader.class); + when(mockRemoteReader.sha1("http://example.com/a", + "refs/heads/branch-x")) + .thenReturn(ObjectId.fromString(SHA1_A)); + + BareSuperprojectWriter w = new BareSuperprojectWriter(bareRepo, + null, "refs/heads/master", author, mockRemoteReader, + BareWriterConfig.getDefault(), + List.of(new BareSuperprojectWriter.ExtraContent("x", + "extra-content"))); + + RevCommit commit = w.write(Arrays.asList(repoProject)); + + String contents = readContents(bareRepo, commit, "x"); + assertThat(contents, is("extra-content")); + } + } + private String readContents(Repository repo, RevCommit commit, String path) throws Exception { String idStr = commit.getId().name() + ":" + path; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/BareSuperprojectWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/BareSuperprojectWriter.java index d6482968fe..e6626aece3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/BareSuperprojectWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/BareSuperprojectWriter.java @@ -71,6 +71,8 @@ class BareSuperprojectWriter { private final PersonIdent author; + private List extraContents; + static class BareWriterConfig { boolean ignoreRemoteFailures = false; @@ -88,10 +90,22 @@ class BareSuperprojectWriter { } } + static class ExtraContent { + final String path; + + final String content; + + ExtraContent(String path, String content) { + this.path = path; + this.content = content; + } + } + BareSuperprojectWriter(Repository repo, URI targetUri, String targetBranch, PersonIdent author, RemoteReader callback, - BareWriterConfig config) { + BareWriterConfig config, + List extraContents) { assert (repo.isBare()); this.repo = repo; this.targetUri = targetUri; @@ -99,6 +113,7 @@ class BareSuperprojectWriter { this.author = author; this.callback = callback; this.config = config; + this.extraContents = extraContents; } RevCommit write(List repoProjects) @@ -244,6 +259,16 @@ class BareSuperprojectWriter { builder.add(dcEntryAttr); } + for (ExtraContent ec : extraContents) { + DirCacheEntry extraDcEntry = new DirCacheEntry(ec.path); + + ObjectId oid = inserter.insert(Constants.OBJ_BLOB, + ec.content.getBytes(UTF_8)); + extraDcEntry.setObjectId(oid); + extraDcEntry.setFileMode(FileMode.REGULAR_FILE); + builder.add(extraDcEntry); + } + builder.finish(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java index 30b8626730..6e943e5d36 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java @@ -28,6 +28,7 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.GitCommand; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRefNameException; +import org.eclipse.jgit.gitrepo.BareSuperprojectWriter.ExtraContent; import org.eclipse.jgit.gitrepo.ManifestParser.IncludedFileReader; import org.eclipse.jgit.gitrepo.internal.RepoText; import org.eclipse.jgit.internal.JGitText; @@ -79,6 +80,8 @@ public class RepoCommand extends GitCommand { private ProgressMonitor monitor; + private final List extraContents = new ArrayList<>(); + /** * A callback to get ref sha1 of a repository from its uri. * @@ -509,6 +512,22 @@ public class RepoCommand extends GitCommand { return this; } + /** + * Create a file with the given content in the destination repository + * + * @param path + * where to create the file in the destination repository + * @param contents + * content for the create file + * @return this command + * + * @since 6.1 + */ + public RepoCommand addToDestination(String path, String contents) { + this.extraContents.add(new ExtraContent(path, contents)); + return this; + } + /** {@inheritDoc} */ @Override public RevCommit call() throws GitAPIException { @@ -550,7 +569,7 @@ public class RepoCommand extends GitCommand { targetBranch, author == null ? new PersonIdent(repo) : author, callback == null ? new DefaultRemoteReader() : callback, - bareWriterConfig); + bareWriterConfig, extraContents); return writer.write(renamedProjects); } @@ -663,5 +682,4 @@ public class RepoCommand extends GitCommand { return URI.create(j.toString()); } - } -- cgit v1.2.3