Browse Source

RepoCommand: Add setRecordRemoteBranch option to record upstream branch

On a server also running Gerrit that is using RepoCommand to
convert from an XML manifest to a git submodule superproject
periodically, it would be handy to be able to use Gerrit's
submodule subscription feature[1] to update the superproject
automatically between RepoCommand runs as changes are merged
in each subprojects.

This requires setting the 'branch' field for each submodule
so that Gerrit knows what branch to watch.  Add an option to
do that.

Setting the branch field also is useful for plain Git users,
since it allows them to use "git submodule update --remote" to
manually update all submodules between RepoCommand runs.

[1] https://gerrit-review.googlesource.com/Documentation/user-submodules.html

Change-Id: I1a10861bcd0df3b3673fc2d481c8129b2bdac5f9
Signed-off-by: Stefan Beller <sbeller@google.com>
stable-4.2
Stefan Beller 9 years ago
parent
commit
cdd7c23446
  1. 1
      org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
  2. 4
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Repo.java
  3. 45
      org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java
  4. 33
      org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java

1
org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties

@ -192,6 +192,7 @@ untrackedFiles=Untracked files:
updating=Updating {0}..{1} updating=Updating {0}..{1}
usage_Aggressive=This option will cause gc to more aggressively optimize the repository at the expense of taking much more time usage_Aggressive=This option will cause gc to more aggressively optimize the repository at the expense of taking much more time
usage_bareClone=Make a bare Git repository. That is, instead of creating [DIRECTORY] and placing the administrative files in [DIRECTORY]/.git, make the [DIRECTORY] itself the $GIT_DIR. usage_bareClone=Make a bare Git repository. That is, instead of creating [DIRECTORY] and placing the administrative files in [DIRECTORY]/.git, make the [DIRECTORY] itself the $GIT_DIR.
usage_branches=Set branch field in .gitmodules
usage_Blame=Show what revision and author last modified each line usage_Blame=Show what revision and author last modified each line
usage_CommandLineClientForamazonsS3Service=Command line client for Amazon's S3 service usage_CommandLineClientForamazonsS3Service=Command line client for Amazon's S3 service
usage_CommitAll=commit all modified and deleted files usage_CommitAll=commit all modified and deleted files

4
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Repo.java

@ -58,12 +58,16 @@ class Repo extends TextBuiltin {
@Argument(required = true, usage = "usage_pathToXml") @Argument(required = true, usage = "usage_pathToXml")
private String path; private String path;
@Option(name = "--record-remote-branch", usage = "usage_branches")
private boolean branches;
@Override @Override
protected void run() throws Exception { protected void run() throws Exception {
new RepoCommand(db) new RepoCommand(db)
.setURI(uri) .setURI(uri)
.setPath(path) .setPath(path)
.setGroups(groups) .setGroups(groups)
.setRecordRemoteBranch(branches)
.call(); .call();
} }
} }

45
org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java

@ -56,6 +56,8 @@ import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.junit.Test; import org.junit.Test;
public class RepoCommandTest extends RepositoryTestCase { public class RepoCommandTest extends RepositoryTestCase {
@ -692,6 +694,49 @@ public class RepoCommandTest extends RepositoryTestCase {
} }
} }
@Test
public void testRecordRemoteBranch() 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=\"with-branch\" ")
.append("revision=\"master\" ")
.append("name=\"").append(notDefaultUri).append("\" />")
.append("<project path=\"with-long-branch\" ")
.append("revision=\"refs/heads/master\" ")
.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)
.setRecordRemoteBranch(true)
.call();
// Clone it
File directory = createTempDirectory("testBareRepo");
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("standard branches work", "master",
c.getString("submodule", "with-branch", "branch"));
assertEquals("long branches work", "refs/heads/master",
c.getString("submodule", "with-long-branch", "branch"));
}
}
private void resolveRelativeUris() { private void resolveRelativeUris() {
// Find the longest common prefix ends with "/" as rootUri. // Find the longest common prefix ends with "/" as rootUri.
defaultUri = defaultDb.getDirectory().toURI().toString(); defaultUri = defaultDb.getDirectory().toURI().toString();

33
org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java

@ -106,6 +106,7 @@ public class RepoCommand extends GitCommand<RevCommit> {
private String groups; private String groups;
private String branch; private String branch;
private String targetBranch = Constants.HEAD; private String targetBranch = Constants.HEAD;
private boolean recordRemoteBranch = false;
private PersonIdent author; private PersonIdent author;
private RemoteReader callback; private RemoteReader callback;
private InputStream inputStream; private InputStream inputStream;
@ -313,6 +314,30 @@ public class RepoCommand extends GitCommand<RevCommit> {
return this; return this;
} }
/**
* Set whether the branch name should be recorded in .gitmodules
* <p>
* Submodule entries in .gitmodules can include a "branch" field
* to indicate what remote branch each submodule tracks.
* <p>
* That field is used by "git submodule update --remote" to update
* to the tip of the tracked branch when asked and by Gerrit to
* update the superproject when a change on that branch is merged.
* <p>
* Subprojects that request a specific commit or tag will not have
* a branch name recorded.
* <p>
* Not implemented for non-bare repositories.
*
* @param record Whether to record the branch name
* @return this command
* @since 4.2
*/
public RepoCommand setRecordRemoteBranch(boolean update) {
this.recordRemoteBranch = update;
return this;
}
/** /**
* The progress monitor associated with the clone operation. By default, * The progress monitor associated with the clone operation. By default,
* this is set to <code>NullProgressMonitor</code> * this is set to <code>NullProgressMonitor</code>
@ -429,10 +454,14 @@ public class RepoCommand extends GitCommand<RevCommit> {
// create gitlink // create gitlink
DirCacheEntry dcEntry = new DirCacheEntry(name); DirCacheEntry dcEntry = new DirCacheEntry(name);
ObjectId objectId; ObjectId objectId;
if (ObjectId.isId(proj.getRevision())) if (ObjectId.isId(proj.getRevision())) {
objectId = ObjectId.fromString(proj.getRevision()); objectId = ObjectId.fromString(proj.getRevision());
else { } else {
objectId = callback.sha1(nameUri, proj.getRevision()); objectId = callback.sha1(nameUri, proj.getRevision());
if (recordRemoteBranch)
// can be branch or tag
cfg.setString("submodule", name, "branch", //$NON-NLS-1$ //$NON-NLS-2$
proj.getRevision());
} }
if (objectId == null) if (objectId == null)
throw new RemoteUnavailableException(nameUri); throw new RemoteUnavailableException(nameUri);

Loading…
Cancel
Save