Currently the repo sub-command only "works", but the submodules will have .git directories themselves, and lacks group support. Change-Id: I88a6ee07109187c6c9bfd92a044775fcfb5befa6 Signed-off-by: Yuxuan 'fishy' Wang <fishywang@google.com>tags/v3.4.0.201405051725-m7
@@ -18,6 +18,7 @@ Import-Package: com.googlecode.javaewah;version="[0.7.9,0.8.0)", | |||
org.eclipse.jgit.errors;version="[3.4.0,3.5.0)", | |||
org.eclipse.jgit.events;version="[3.4.0,3.5.0)", | |||
org.eclipse.jgit.fnmatch;version="[3.4.0,3.5.0)", | |||
org.eclipse.jgit.gitrepo;version="[3.4.0,3.5.0)", | |||
org.eclipse.jgit.ignore;version="[3.4.0,3.5.0)", | |||
org.eclipse.jgit.internal;version="[3.4.0,3.5.0)", | |||
org.eclipse.jgit.internal.storage.dfs;version="[3.4.0,3.5.0)", |
@@ -0,0 +1,93 @@ | |||
/* | |||
* Copyright (C) 2014, Google Inc. | |||
* and other copyright owners as documented in the project's IP log. | |||
* | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Distribution License v1.0 which | |||
* accompanies this distribution, is reproduced below, and is | |||
* available at http://www.eclipse.org/org/documents/edl-v10.php | |||
* | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or | |||
* without modification, are permitted provided that the following | |||
* conditions are met: | |||
* | |||
* - Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* - Redistributions in binary form must reproduce the above | |||
* copyright notice, this list of conditions and the following | |||
* disclaimer in the documentation and/or other materials provided | |||
* with the distribution. | |||
* | |||
* - Neither the name of the Eclipse Foundation, Inc. nor the | |||
* names of its contributors may be used to endorse or promote | |||
* products derived from this software without specific prior | |||
* written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
package org.eclipse.jgit.gitrepo; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.BufferedReader; | |||
import java.io.File; | |||
import java.io.FileReader; | |||
import org.eclipse.jgit.api.Git; | |||
import org.eclipse.jgit.junit.JGitTestUtil; | |||
import org.eclipse.jgit.junit.RepositoryTestCase; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.junit.Test; | |||
public class RepoCommandTest extends RepositoryTestCase { | |||
private Repository remoteDb; | |||
public void setUp() throws Exception { | |||
super.setUp(); | |||
remoteDb = createWorkRepository(); | |||
Git git = new Git(remoteDb); | |||
JGitTestUtil.writeTrashFile(remoteDb, "hello.txt", "world"); | |||
git.add().addFilepattern("hello.txt").call(); | |||
git.commit().setMessage("Initial commit").call(); | |||
} | |||
@Test | |||
public void testAddRepoManifest() 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("</manifest>"); | |||
writeTrashFile("manifest.xml", xmlContent.toString()); | |||
RepoCommand command = new RepoCommand(db); | |||
command.setPath(db.getWorkTree().getAbsolutePath() + "/manifest.xml") | |||
.setURI(remoteDb.getDirectory().toURI().toString()) | |||
.call(); | |||
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); | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
errorNoDefault=Error: no default remote in file {0}. | |||
errorParsingManifestFile=Error occurred during parsing manifest file {0}. | |||
invalidManifest=Invalid manifest. |
@@ -0,0 +1,248 @@ | |||
/* | |||
* Copyright (C) 2014, Google Inc. | |||
* and other copyright owners as documented in the project's IP log. | |||
* | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Distribution License v1.0 which | |||
* accompanies this distribution, is reproduced below, and is | |||
* available at http://www.eclipse.org/org/documents/edl-v10.php | |||
* | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or | |||
* without modification, are permitted provided that the following | |||
* conditions are met: | |||
* | |||
* - Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* - Redistributions in binary form must reproduce the above | |||
* copyright notice, this list of conditions and the following | |||
* disclaimer in the documentation and/or other materials provided | |||
* with the distribution. | |||
* | |||
* - Neither the name of the Eclipse Foundation, Inc. nor the | |||
* names of its contributors may be used to endorse or promote | |||
* products derived from this software without specific prior | |||
* written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
package org.eclipse.jgit.gitrepo; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
import java.text.MessageFormat; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.eclipse.jgit.api.GitCommand; | |||
import org.eclipse.jgit.api.SubmoduleAddCommand; | |||
import org.eclipse.jgit.api.errors.GitAPIException; | |||
import org.eclipse.jgit.gitrepo.internal.RepoText; | |||
import org.eclipse.jgit.internal.JGitText; | |||
import org.eclipse.jgit.lib.ProgressMonitor; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.xml.sax.Attributes; | |||
import org.xml.sax.InputSource; | |||
import org.xml.sax.SAXException; | |||
import org.xml.sax.XMLReader; | |||
import org.xml.sax.helpers.DefaultHandler; | |||
import org.xml.sax.helpers.XMLReaderFactory; | |||
/** | |||
* A class used to execute a repo command. | |||
* | |||
* This will parse a repo XML manifest, convert it into .gitmodules file and the | |||
* repository config file. | |||
* | |||
* @see <a href="https://code.google.com/p/git-repo/">git-repo project page</a> | |||
* @since 3.4 | |||
*/ | |||
public class RepoCommand extends GitCommand<Void> { | |||
private String path; | |||
private String uri; | |||
private ProgressMonitor monitor; | |||
private static class Project { | |||
final String name; | |||
final String path; | |||
Project(String name, String path) { | |||
this.name = name; | |||
this.path = path; | |||
} | |||
} | |||
private static class XmlManifest extends DefaultHandler { | |||
private final RepoCommand command; | |||
private final String filename; | |||
private final String baseUrl; | |||
private final Map<String, String> remotes; | |||
private final List<Project> projects; | |||
private String defaultRemote; | |||
XmlManifest(RepoCommand command, String filename, String baseUrl) { | |||
this.command = command; | |||
this.filename = filename; | |||
this.baseUrl = baseUrl; | |||
remotes = new HashMap<String, String>(); | |||
projects = new ArrayList<Project>(); | |||
} | |||
void read() throws IOException { | |||
final XMLReader xr; | |||
try { | |||
xr = XMLReaderFactory.createXMLReader(); | |||
} catch (SAXException e) { | |||
throw new IOException(JGitText.get().noXMLParserAvailable); | |||
} | |||
xr.setContentHandler(this); | |||
final FileInputStream in = new FileInputStream(filename); | |||
try { | |||
xr.parse(new InputSource(in)); | |||
} catch (SAXException e) { | |||
IOException error = new IOException(MessageFormat.format( | |||
RepoText.get().errorParsingManifestFile, filename)); | |||
error.initCause(e); | |||
throw error; | |||
} finally { | |||
in.close(); | |||
} | |||
} | |||
@Override | |||
public void startElement( | |||
String uri, | |||
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$ | |||
defaultRemote = attributes.getValue("remote"); //$NON-NLS-1$ | |||
else if ("copyfile".equals(qName)) { //$NON-NLS-1$ | |||
// TODO(fishywang): Handle copyfile. Do nothing for now. | |||
} | |||
} | |||
@Override | |||
public void endDocument() throws SAXException { | |||
if (defaultRemote == null) { | |||
throw new SAXException(MessageFormat.format( | |||
RepoText.get().errorNoDefault, filename)); | |||
} | |||
final String remoteUrl; | |||
try { | |||
URI uri = new URI(String.format("%s/%s/", baseUrl, remotes.get(defaultRemote))); //$NON-NLS-1$ | |||
remoteUrl = uri.normalize().toString(); | |||
} catch (URISyntaxException e) { | |||
throw new SAXException(e); | |||
} | |||
for (Project proj : projects) { | |||
String url = remoteUrl + proj.name; | |||
command.addSubmodule(url, proj.path); | |||
} | |||
} | |||
} | |||
private static class ManifestErrorException extends GitAPIException { | |||
ManifestErrorException(Throwable cause) { | |||
super(RepoText.get().invalidManifest, cause); | |||
} | |||
} | |||
/** | |||
* @param repo | |||
*/ | |||
public RepoCommand(final Repository repo) { | |||
super(repo); | |||
} | |||
/** | |||
* Set path to the manifest XML file | |||
* | |||
* @param path | |||
* (with <code>/</code> as separator) | |||
* @return this command | |||
*/ | |||
public RepoCommand setPath(final String path) { | |||
this.path = path; | |||
return this; | |||
} | |||
/** | |||
* Set base URI of the pathes inside the XML | |||
* | |||
* @param uri | |||
* @return this command | |||
*/ | |||
public RepoCommand setURI(final String uri) { | |||
this.uri = uri; | |||
return this; | |||
} | |||
/** | |||
* The progress monitor associated with the clone operation. By default, | |||
* this is set to <code>NullProgressMonitor</code> | |||
* | |||
* @see org.eclipse.jgit.lib.NullProgressMonitor | |||
* @param monitor | |||
* @return this command | |||
*/ | |||
public RepoCommand setProgressMonitor(final ProgressMonitor monitor) { | |||
this.monitor = monitor; | |||
return this; | |||
} | |||
@Override | |||
public Void call() throws GitAPIException { | |||
checkCallable(); | |||
if (path == null || path.length() == 0) | |||
throw new IllegalArgumentException(JGitText.get().pathNotConfigured); | |||
if (uri == null || uri.length() == 0) | |||
throw new IllegalArgumentException(JGitText.get().uriNotConfigured); | |||
XmlManifest manifest = new XmlManifest(this, path, uri); | |||
try { | |||
manifest.read(); | |||
} catch (IOException e) { | |||
throw new ManifestErrorException(e); | |||
} | |||
return null; | |||
} | |||
private void addSubmodule(String url, String name) throws SAXException { | |||
SubmoduleAddCommand add = new SubmoduleAddCommand(repo); | |||
if (monitor != null) | |||
add.setProgressMonitor(monitor); | |||
try { | |||
add.setPath(name).setURI(url).call(); | |||
} catch (GitAPIException e) { | |||
throw new SAXException(e); | |||
} | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
/* | |||
* Copyright (C) 2014, Google Inc. | |||
* and other copyright owners as documented in the project's IP log. | |||
* | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Distribution License v1.0 which | |||
* accompanies this distribution, is reproduced below, and is | |||
* available at http://www.eclipse.org/org/documents/edl-v10.php | |||
* | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or | |||
* without modification, are permitted provided that the following | |||
* conditions are met: | |||
* | |||
* - Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* - Redistributions in binary form must reproduce the above | |||
* copyright notice, this list of conditions and the following | |||
* disclaimer in the documentation and/or other materials provided | |||
* with the distribution. | |||
* | |||
* - Neither the name of the Eclipse Foundation, Inc. nor the | |||
* names of its contributors may be used to endorse or promote | |||
* products derived from this software without specific prior | |||
* written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
package org.eclipse.jgit.gitrepo.internal; | |||
import org.eclipse.jgit.nls.NLS; | |||
import org.eclipse.jgit.nls.TranslationBundle; | |||
/** | |||
* Translation bundle for repo command | |||
*/ | |||
public class RepoText extends TranslationBundle { | |||
/** | |||
* @return an instance of this translation bundle | |||
*/ | |||
public static RepoText get() { | |||
return NLS.getBundleFor(RepoText.class); | |||
} | |||
// @formatter:off | |||
/***/ public String errorNoDefault; | |||
/***/ public String errorParsingManifestFile; | |||
/***/ public String invalidManifest; | |||
} |