Added groups support to repo subcommand.
Change-Id: Id0e7663b6ac4f6938fdcacaf2158107b6285fc25 Signed-off-by: Yuxuan 'fishy' Wang <fishywang@google.com>
This commit is contained in:
parent
1f3b75c9ee
commit
a44a687fed
|
@ -43,6 +43,7 @@
|
|||
package org.eclipse.jgit.pgm;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
@ -57,17 +58,47 @@
|
|||
import org.junit.Test;
|
||||
|
||||
public class RepoTest extends CLIRepositoryTestCase {
|
||||
private Repository remoteDb;
|
||||
private Repository defaultDb;
|
||||
private Repository notDefaultDb;
|
||||
private Repository groupADb;
|
||||
private Repository groupBDb;
|
||||
|
||||
private String rootUri;
|
||||
private String defaultUri;
|
||||
private String notDefaultUri;
|
||||
private String groupAUri;
|
||||
private String groupBUri;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
remoteDb = createWorkRepository();
|
||||
Git git = new Git(remoteDb);
|
||||
JGitTestUtil.writeTrashFile(remoteDb, "hello.txt", "world");
|
||||
|
||||
defaultDb = createWorkRepository();
|
||||
Git git = new Git(defaultDb);
|
||||
JGitTestUtil.writeTrashFile(defaultDb, "hello.txt", "world");
|
||||
git.add().addFilepattern("hello.txt").call();
|
||||
git.commit().setMessage("Initial commit").call();
|
||||
|
||||
notDefaultDb = createWorkRepository();
|
||||
git = new Git(notDefaultDb);
|
||||
JGitTestUtil.writeTrashFile(notDefaultDb, "world.txt", "hello");
|
||||
git.add().addFilepattern("world.txt").call();
|
||||
git.commit().setMessage("Initial commit").call();
|
||||
|
||||
groupADb = createWorkRepository();
|
||||
git = new Git(groupADb);
|
||||
JGitTestUtil.writeTrashFile(groupADb, "a.txt", "world");
|
||||
git.add().addFilepattern("a.txt").call();
|
||||
git.commit().setMessage("Initial commit").call();
|
||||
|
||||
groupBDb = createWorkRepository();
|
||||
git = new Git(groupBDb);
|
||||
JGitTestUtil.writeTrashFile(groupBDb, "b.txt", "world");
|
||||
git.add().addFilepattern("b.txt").call();
|
||||
git.commit().setMessage("Initial commit").call();
|
||||
|
||||
resolveRelativeUris();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -77,20 +108,59 @@ public void testAddRepoManifest() throws Exception {
|
|||
.append("<manifest>")
|
||||
.append("<remote name=\"remote1\" fetch=\".\" />")
|
||||
.append("<default revision=\"master\" remote=\"remote1\" />")
|
||||
.append("<project path=\"foo\" name=\".\" />")
|
||||
.append("<project path=\"foo\" name=\"")
|
||||
.append(defaultUri)
|
||||
.append("\" groups=\"a,test\" />")
|
||||
.append("<project path=\"bar\" name=\"")
|
||||
.append(notDefaultUri)
|
||||
.append("\" groups=\"notdefault\" />")
|
||||
.append("<project path=\"a\" name=\"")
|
||||
.append(groupAUri)
|
||||
.append("\" groups=\"a\" />")
|
||||
.append("<project path=\"b\" name=\"")
|
||||
.append(groupBUri)
|
||||
.append("\" groups=\"b\" />")
|
||||
.append("</manifest>");
|
||||
writeTrashFile("manifest.xml", xmlContent.toString());
|
||||
StringBuilder cmd = new StringBuilder("git repo --base-uri=\"")
|
||||
.append(remoteDb.getDirectory().toURI().toString())
|
||||
.append("\" \"")
|
||||
.append(rootUri)
|
||||
.append("\" --groups=\"all,-a\" \"")
|
||||
.append(db.getWorkTree().getAbsolutePath())
|
||||
.append("/manifest.xml\"");
|
||||
execute(cmd.toString());
|
||||
File hello = new File(db.getWorkTree(), "foo/hello.txt");
|
||||
assertTrue("submodule was checked out.", hello.exists());
|
||||
BufferedReader reader = new BufferedReader(new FileReader(hello));
|
||||
String content = reader.readLine();
|
||||
reader.close();
|
||||
assertEquals("submodule content is as expected.", "world", content);
|
||||
|
||||
File file = new File(db.getWorkTree(), "foo/hello.txt");
|
||||
assertFalse("\"all,-a\" doesn't have foo", file.exists());
|
||||
file = new File(db.getWorkTree(), "bar/world.txt");
|
||||
assertTrue("\"all,-a\" has bar", file.exists());
|
||||
file = new File(db.getWorkTree(), "a/a.txt");
|
||||
assertFalse("\"all,-a\" doesn't have a", file.exists());
|
||||
file = new File(db.getWorkTree(), "b/b.txt");
|
||||
assertTrue("\"all,-a\" has have b", file.exists());
|
||||
}
|
||||
|
||||
private void resolveRelativeUris() {
|
||||
// Find the longest common prefix ends with "/" as rootUri.
|
||||
defaultUri = defaultDb.getDirectory().toURI().toString();
|
||||
notDefaultUri = notDefaultDb.getDirectory().toURI().toString();
|
||||
groupAUri = groupADb.getDirectory().toURI().toString();
|
||||
groupBUri = groupBDb.getDirectory().toURI().toString();
|
||||
int start = 0;
|
||||
while (start <= defaultUri.length()) {
|
||||
int newStart = defaultUri.indexOf('/', start + 1);
|
||||
String prefix = defaultUri.substring(0, newStart);
|
||||
if (!notDefaultUri.startsWith(prefix) ||
|
||||
!groupAUri.startsWith(prefix) ||
|
||||
!groupBUri.startsWith(prefix)) {
|
||||
start++;
|
||||
rootUri = defaultUri.substring(0, start);
|
||||
defaultUri = defaultUri.substring(start);
|
||||
notDefaultUri = notDefaultUri.substring(start);
|
||||
groupAUri = groupAUri.substring(start);
|
||||
groupBUri = groupBUri.substring(start);
|
||||
return;
|
||||
}
|
||||
start = newStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -278,6 +278,7 @@ usage_forceCheckout=when switching branches, proceed even if the index or the wo
|
|||
usage_forceCreateBranchEvenExists=force create branch even exists
|
||||
usage_forceReplacingAnExistingTag=force replacing an existing tag
|
||||
usage_getAndSetOptions=Get and set repository or global options
|
||||
usage_groups=Restrict manifest projects to ones with specified group(s), use "-" for excluding [default|all|G1,G2,G3|G4,-G5,-G6]
|
||||
usage_hostnameOrIpToListenOn=hostname (or ip) to listen on
|
||||
usage_indexFileFormatToCreate=index file format to create
|
||||
usage_ignoreWhitespace=ignore all whitespace
|
||||
|
|
|
@ -52,6 +52,9 @@ class Repo extends TextBuiltin {
|
|||
@Option(name = "--base-uri", aliases = { "-u" }, usage = "usage_baseUri")
|
||||
private String uri;
|
||||
|
||||
@Option(name = "--groups", aliases = { "-g" }, usage = "usage_groups")
|
||||
private String groups = "default"; //$NON-NLS-1$
|
||||
|
||||
@Argument(required = true, usage = "usage_pathToXml")
|
||||
private String path;
|
||||
|
||||
|
@ -60,6 +63,7 @@ protected void run() throws Exception {
|
|||
new RepoCommand(db)
|
||||
.setURI(uri)
|
||||
.setPath(path)
|
||||
.setGroups(groups)
|
||||
.call();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
package org.eclipse.jgit.gitrepo;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
@ -57,16 +58,45 @@
|
|||
|
||||
public class RepoCommandTest extends RepositoryTestCase {
|
||||
|
||||
private Repository remoteDb;
|
||||
private Repository defaultDb;
|
||||
private Repository notDefaultDb;
|
||||
private Repository groupADb;
|
||||
private Repository groupBDb;
|
||||
|
||||
private String rootUri;
|
||||
private String defaultUri;
|
||||
private String notDefaultUri;
|
||||
private String groupAUri;
|
||||
private String groupBUri;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
remoteDb = createWorkRepository();
|
||||
Git git = new Git(remoteDb);
|
||||
JGitTestUtil.writeTrashFile(remoteDb, "hello.txt", "world");
|
||||
defaultDb = createWorkRepository();
|
||||
Git git = new Git(defaultDb);
|
||||
JGitTestUtil.writeTrashFile(defaultDb, "hello.txt", "world");
|
||||
git.add().addFilepattern("hello.txt").call();
|
||||
git.commit().setMessage("Initial commit").call();
|
||||
|
||||
notDefaultDb = createWorkRepository();
|
||||
git = new Git(notDefaultDb);
|
||||
JGitTestUtil.writeTrashFile(notDefaultDb, "world.txt", "hello");
|
||||
git.add().addFilepattern("world.txt").call();
|
||||
git.commit().setMessage("Initial commit").call();
|
||||
|
||||
groupADb = createWorkRepository();
|
||||
git = new Git(groupADb);
|
||||
JGitTestUtil.writeTrashFile(groupADb, "a.txt", "world");
|
||||
git.add().addFilepattern("a.txt").call();
|
||||
git.commit().setMessage("Initial commit").call();
|
||||
|
||||
groupBDb = createWorkRepository();
|
||||
git = new Git(groupBDb);
|
||||
JGitTestUtil.writeTrashFile(groupBDb, "b.txt", "world");
|
||||
git.add().addFilepattern("b.txt").call();
|
||||
git.commit().setMessage("Initial commit").call();
|
||||
|
||||
resolveRelativeUris();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -76,12 +106,14 @@ public void testAddRepoManifest() throws Exception {
|
|||
.append("<manifest>")
|
||||
.append("<remote name=\"remote1\" fetch=\".\" />")
|
||||
.append("<default revision=\"master\" remote=\"remote1\" />")
|
||||
.append("<project path=\"foo\" name=\".\" />")
|
||||
.append("<project path=\"foo\" name=\"")
|
||||
.append(defaultUri)
|
||||
.append("\" />")
|
||||
.append("</manifest>");
|
||||
writeTrashFile("manifest.xml", xmlContent.toString());
|
||||
RepoCommand command = new RepoCommand(db);
|
||||
command.setPath(db.getWorkTree().getAbsolutePath() + "/manifest.xml")
|
||||
.setURI(remoteDb.getDirectory().toURI().toString())
|
||||
.setURI(rootUri)
|
||||
.call();
|
||||
File hello = new File(db.getWorkTree(), "foo/hello.txt");
|
||||
assertTrue("submodule was checked out", hello.exists());
|
||||
|
@ -90,4 +122,84 @@ public void testAddRepoManifest() throws Exception {
|
|||
reader.close();
|
||||
assertEquals("submodule content is as expected.", "world", content);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRepoManifestGroups() throws Exception {
|
||||
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=\"foo\" name=\"")
|
||||
.append(defaultUri)
|
||||
.append("\" groups=\"a,test\" />")
|
||||
.append("<project path=\"bar\" name=\"")
|
||||
.append(notDefaultUri)
|
||||
.append("\" groups=\"notdefault\" />")
|
||||
.append("<project path=\"a\" name=\"")
|
||||
.append(groupAUri)
|
||||
.append("\" groups=\"a\" />")
|
||||
.append("<project path=\"b\" name=\"")
|
||||
.append(groupBUri)
|
||||
.append("\" groups=\"b\" />")
|
||||
.append("</manifest>");
|
||||
|
||||
// default should have foo, a & b
|
||||
Repository localDb = createWorkRepository();
|
||||
JGitTestUtil.writeTrashFile(localDb, "manifest.xml", xmlContent.toString());
|
||||
RepoCommand command = new RepoCommand(localDb);
|
||||
command.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
|
||||
.setURI(rootUri)
|
||||
.call();
|
||||
File file = new File(localDb.getWorkTree(), "foo/hello.txt");
|
||||
assertTrue("default has foo", file.exists());
|
||||
file = new File(localDb.getWorkTree(), "bar/world.txt");
|
||||
assertFalse("default doesn't have bar", file.exists());
|
||||
file = new File(localDb.getWorkTree(), "a/a.txt");
|
||||
assertTrue("default has a", file.exists());
|
||||
file = new File(localDb.getWorkTree(), "b/b.txt");
|
||||
assertTrue("default has b", file.exists());
|
||||
|
||||
// all,-a should have bar & b
|
||||
localDb = createWorkRepository();
|
||||
JGitTestUtil.writeTrashFile(localDb, "manifest.xml", xmlContent.toString());
|
||||
command = new RepoCommand(localDb);
|
||||
command.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
|
||||
.setURI(rootUri)
|
||||
.setGroups("all,-a")
|
||||
.call();
|
||||
file = new File(localDb.getWorkTree(), "foo/hello.txt");
|
||||
assertFalse("\"all,-a\" doesn't have foo", file.exists());
|
||||
file = new File(localDb.getWorkTree(), "bar/world.txt");
|
||||
assertTrue("\"all,-a\" has bar", file.exists());
|
||||
file = new File(localDb.getWorkTree(), "a/a.txt");
|
||||
assertFalse("\"all,-a\" doesn't have a", file.exists());
|
||||
file = new File(localDb.getWorkTree(), "b/b.txt");
|
||||
assertTrue("\"all,-a\" has have b", file.exists());
|
||||
}
|
||||
|
||||
private void resolveRelativeUris() {
|
||||
// Find the longest common prefix ends with "/" as rootUri.
|
||||
defaultUri = defaultDb.getDirectory().toURI().toString();
|
||||
notDefaultUri = notDefaultDb.getDirectory().toURI().toString();
|
||||
groupAUri = groupADb.getDirectory().toURI().toString();
|
||||
groupBUri = groupBDb.getDirectory().toURI().toString();
|
||||
int start = 0;
|
||||
while (start <= defaultUri.length()) {
|
||||
int newStart = defaultUri.indexOf('/', start + 1);
|
||||
String prefix = defaultUri.substring(0, newStart);
|
||||
if (!notDefaultUri.startsWith(prefix) ||
|
||||
!groupAUri.startsWith(prefix) ||
|
||||
!groupBUri.startsWith(prefix)) {
|
||||
start++;
|
||||
rootUri = defaultUri.substring(0, start);
|
||||
defaultUri = defaultUri.substring(start);
|
||||
notDefaultUri = notDefaultUri.substring(start);
|
||||
groupAUri = groupAUri.substring(start);
|
||||
groupBUri = groupBUri.substring(start);
|
||||
return;
|
||||
}
|
||||
start = newStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,9 +48,12 @@
|
|||
import java.net.URISyntaxException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jgit.api.GitCommand;
|
||||
import org.eclipse.jgit.api.SubmoduleAddCommand;
|
||||
|
@ -79,18 +82,22 @@
|
|||
public class RepoCommand extends GitCommand<Void> {
|
||||
|
||||
private String path;
|
||||
|
||||
private String uri;
|
||||
private String groups;
|
||||
|
||||
private ProgressMonitor monitor;
|
||||
|
||||
private static class Project {
|
||||
final String name;
|
||||
final String path;
|
||||
final Set<String> groups;
|
||||
|
||||
Project(String name, String path) {
|
||||
Project(String name, String path, String groups) {
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
this.groups = new HashSet<String>();
|
||||
if (groups != null && groups.length() > 0)
|
||||
this.groups.addAll(Arrays.asList(groups.split(","))); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,14 +107,29 @@ private static class XmlManifest extends DefaultHandler {
|
|||
private final String baseUrl;
|
||||
private final Map<String, String> remotes;
|
||||
private final List<Project> projects;
|
||||
private final Set<String> plusGroups;
|
||||
private final Set<String> minusGroups;
|
||||
private String defaultRemote;
|
||||
|
||||
XmlManifest(RepoCommand command, String filename, String baseUrl) {
|
||||
XmlManifest(RepoCommand command, String filename, String baseUrl, String groups) {
|
||||
this.command = command;
|
||||
this.filename = filename;
|
||||
this.baseUrl = baseUrl;
|
||||
remotes = new HashMap<String, String>();
|
||||
projects = new ArrayList<Project>();
|
||||
plusGroups = new HashSet<String>();
|
||||
minusGroups = new HashSet<String>();
|
||||
if (groups == null || groups.length() == 0 || groups.equals("default")) { //$NON-NLS-1$
|
||||
// default means "all,-notdefault"
|
||||
minusGroups.add("notdefault"); //$NON-NLS-1$
|
||||
} else {
|
||||
for (String group : groups.split(",")) { //$NON-NLS-1$
|
||||
if (group.startsWith("-")) //$NON-NLS-1$
|
||||
minusGroups.add(group.substring(1));
|
||||
else
|
||||
plusGroups.add(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void read() throws IOException {
|
||||
|
@ -137,13 +159,17 @@ public void startElement(
|
|||
String localName,
|
||||
String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if ("project".equals(qName)) //$NON-NLS-1$
|
||||
projects.add(new Project(attributes.getValue("name"), attributes.getValue("path"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
else if ("remote".equals(qName)) //$NON-NLS-1$
|
||||
remotes.put(attributes.getValue("name"), attributes.getValue("fetch")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
else if ("default".equals(qName)) //$NON-NLS-1$
|
||||
if ("project".equals(qName)) { //$NON-NLS-1$
|
||||
projects.add(new Project( //$NON-NLS-1$
|
||||
attributes.getValue("name"), //$NON-NLS-1$
|
||||
attributes.getValue("path"), //$NON-NLS-1$
|
||||
attributes.getValue("groups"))); //$NON-NLS-1$
|
||||
} else if ("remote".equals(qName)) { //$NON-NLS-1$
|
||||
remotes.put(attributes.getValue("name"), //$NON-NLS-1$
|
||||
attributes.getValue("fetch")); //$NON-NLS-1$
|
||||
} else if ("default".equals(qName)) { //$NON-NLS-1$
|
||||
defaultRemote = attributes.getValue("remote"); //$NON-NLS-1$
|
||||
else if ("copyfile".equals(qName)) { //$NON-NLS-1$
|
||||
} else if ("copyfile".equals(qName)) { //$NON-NLS-1$
|
||||
// TODO(fishywang): Handle copyfile. Do nothing for now.
|
||||
}
|
||||
}
|
||||
|
@ -162,10 +188,30 @@ public void endDocument() throws SAXException {
|
|||
throw new SAXException(e);
|
||||
}
|
||||
for (Project proj : projects) {
|
||||
String url = remoteUrl + proj.name;
|
||||
command.addSubmodule(url, proj.path);
|
||||
if (inGroups(proj)) {
|
||||
String url = remoteUrl + proj.name;
|
||||
command.addSubmodule(url, proj.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean inGroups(Project proj) {
|
||||
for (String group : minusGroups) {
|
||||
if (proj.groups.contains(group)) {
|
||||
// minus groups have highest priority.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (plusGroups.isEmpty() || plusGroups.contains("all")) { //$NON-NLS-1$
|
||||
// empty plus groups means "all"
|
||||
return true;
|
||||
}
|
||||
for (String group : plusGroups) {
|
||||
if (proj.groups.contains(group))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ManifestErrorException extends GitAPIException {
|
||||
|
@ -204,6 +250,17 @@ public RepoCommand setURI(final String uri) {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set groups to sync
|
||||
*
|
||||
* @param groups groups separated by comma, examples: default|all|G1,-G2,-G3
|
||||
* @return this command
|
||||
*/
|
||||
public RepoCommand setGroups(final String groups) {
|
||||
this.groups = groups;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The progress monitor associated with the clone operation. By default,
|
||||
* this is set to <code>NullProgressMonitor</code>
|
||||
|
@ -225,7 +282,7 @@ public Void call() throws GitAPIException {
|
|||
if (uri == null || uri.length() == 0)
|
||||
throw new IllegalArgumentException(JGitText.get().uriNotConfigured);
|
||||
|
||||
XmlManifest manifest = new XmlManifest(this, path, uri);
|
||||
XmlManifest manifest = new XmlManifest(this, path, uri, groups);
|
||||
try {
|
||||
manifest.read();
|
||||
} catch (IOException e) {
|
||||
|
@ -236,11 +293,13 @@ public Void call() throws GitAPIException {
|
|||
}
|
||||
|
||||
private void addSubmodule(String url, String name) throws SAXException {
|
||||
SubmoduleAddCommand add = new SubmoduleAddCommand(repo);
|
||||
SubmoduleAddCommand add = new SubmoduleAddCommand(repo)
|
||||
.setPath(name)
|
||||
.setURI(url);
|
||||
if (monitor != null)
|
||||
add.setProgressMonitor(monitor);
|
||||
try {
|
||||
add.setPath(name).setURI(url).call();
|
||||
add.call();
|
||||
} catch (GitAPIException e) {
|
||||
throw new SAXException(e);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue