Browse Source
* changes: Commit changes generated during repo command Added implementation of copyfile rule. Added groups support to repo subcommand. Added the command line of jgit repo. Implemented first part of the repo sub-command.stable-3.4
Shawn Pearce
11 years ago
committed by
Gerrit Code Review @ Eclipse.org
11 changed files with 942 additions and 0 deletions
@ -0,0 +1,166 @@
|
||||
/* |
||||
* 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.pgm; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertFalse; |
||||
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.lib.CLIRepositoryTestCase; |
||||
import org.eclipse.jgit.lib.Repository; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
|
||||
public class RepoTest extends CLIRepositoryTestCase { |
||||
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(); |
||||
|
||||
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 |
||||
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(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(rootUri) |
||||
.append("\" --groups=\"all,-a\" \"") |
||||
.append(db.getWorkTree().getAbsolutePath()) |
||||
.append("/manifest.xml\""); |
||||
execute(cmd.toString()); |
||||
|
||||
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; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,69 @@
|
||||
/* |
||||
* 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.pgm; |
||||
|
||||
import org.eclipse.jgit.gitrepo.RepoCommand; |
||||
import org.kohsuke.args4j.Argument; |
||||
import org.kohsuke.args4j.Option; |
||||
|
||||
@Command(common = true, usage = "usage_parseRepoManifest") |
||||
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; |
||||
|
||||
@Override |
||||
protected void run() throws Exception { |
||||
new RepoCommand(db) |
||||
.setURI(uri) |
||||
.setPath(path) |
||||
.setGroups(groups) |
||||
.call(); |
||||
} |
||||
} |
@ -0,0 +1,240 @@
|
||||
/* |
||||
* 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.assertFalse; |
||||
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 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(); |
||||
|
||||
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 |
||||
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(defaultUri) |
||||
.append("\" />") |
||||
.append("</manifest>"); |
||||
writeTrashFile("manifest.xml", xmlContent.toString()); |
||||
RepoCommand command = new RepoCommand(db); |
||||
command.setPath(db.getWorkTree().getAbsolutePath() + "/manifest.xml") |
||||
.setURI(rootUri) |
||||
.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); |
||||
} |
||||
|
||||
@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()); |
||||
} |
||||
|
||||
@Test |
||||
public void testRepoManifestCopyfile() throws Exception { |
||||
Repository localDb = 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=\"foo\" name=\"") |
||||
.append(defaultUri) |
||||
.append("\">") |
||||
.append("<copyfile src=\"hello.txt\" dest=\"Hello\" />") |
||||
.append("</project>") |
||||
.append("</manifest>"); |
||||
JGitTestUtil.writeTrashFile(localDb, "manifest.xml", xmlContent.toString()); |
||||
RepoCommand command = new RepoCommand(localDb); |
||||
command.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml") |
||||
.setURI(rootUri) |
||||
.call(); |
||||
// The original file should exist
|
||||
File hello = new File(localDb.getWorkTree(), "foo/hello.txt"); |
||||
assertTrue("The original file exists", hello.exists()); |
||||
BufferedReader reader = new BufferedReader(new FileReader(hello)); |
||||
String content = reader.readLine(); |
||||
reader.close(); |
||||
assertEquals("The original file has expected content", "world", content); |
||||
// The dest file should also exist
|
||||
hello = new File(localDb.getWorkTree(), "Hello"); |
||||
assertTrue("The destination file exists", hello.exists()); |
||||
reader = new BufferedReader(new FileReader(hello)); |
||||
content = reader.readLine(); |
||||
reader.close(); |
||||
assertEquals("The destination file has expected content", "world", content); |
||||
} |
||||
|
||||
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; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,5 @@
|
||||
copyFileFailed=Error occurred during execution of copyfile rule. |
||||
errorNoDefault=Error: no default remote in file {0}. |
||||
errorParsingManifestFile=Error occurred during parsing manifest file {0}. |
||||
invalidManifest=Invalid manifest. |
||||
repoCommitMessage=Added repo manifest. |
@ -0,0 +1,385 @@
|
||||
/* |
||||
* 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.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.net.URISyntaxException; |
||||
import java.nio.channels.FileChannel; |
||||
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.AddCommand; |
||||
import org.eclipse.jgit.api.Git; |
||||
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.eclipse.jgit.revwalk.RevCommit; |
||||
|
||||
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<RevCommit> { |
||||
|
||||
private String path; |
||||
private String uri; |
||||
private String groups; |
||||
|
||||
private Git git; |
||||
private ProgressMonitor monitor; |
||||
|
||||
private static class CopyFile { |
||||
final String src; |
||||
final String dest; |
||||
final String relativeDest; |
||||
|
||||
CopyFile(Repository repo, String path, String src, String dest) { |
||||
this.src = repo.getWorkTree() + "/" + path + "/" + src; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
this.relativeDest = dest; |
||||
this.dest = repo.getWorkTree() + "/" + dest; //$NON-NLS-1$
|
||||
} |
||||
|
||||
void copy() throws IOException { |
||||
FileInputStream input = new FileInputStream(src); |
||||
try { |
||||
FileOutputStream output = new FileOutputStream(dest); |
||||
try { |
||||
FileChannel channel = input.getChannel(); |
||||
output.getChannel().transferFrom(channel, 0, channel.size()); |
||||
} finally { |
||||
output.close(); |
||||
} |
||||
} finally { |
||||
input.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private static class Project { |
||||
final String name; |
||||
final String path; |
||||
final Set<String> groups; |
||||
final List<CopyFile> copyfiles; |
||||
|
||||
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$
|
||||
copyfiles = new ArrayList<CopyFile>(); |
||||
} |
||||
|
||||
void addCopyFile(CopyFile copyfile) { |
||||
copyfiles.add(copyfile); |
||||
} |
||||
} |
||||
|
||||
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 final Set<String> plusGroups; |
||||
private final Set<String> minusGroups; |
||||
private String defaultRemote; |
||||
private Project currentProject; |
||||
|
||||
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 { |
||||
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$
|
||||
currentProject = 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$
|
||||
if (currentProject == null) |
||||
throw new SAXException(RepoText.get().invalidManifest); |
||||
currentProject.addCopyFile(new CopyFile( |
||||
command.repo, |
||||
currentProject.path, |
||||
attributes.getValue("src"), //$NON-NLS-1$
|
||||
attributes.getValue("dest"))); //$NON-NLS-1$
|
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void endElement( |
||||
String uri, |
||||
String localName, |
||||
String qName) throws SAXException { |
||||
if ("project".equals(qName)) { //$NON-NLS-1$
|
||||
projects.add(currentProject); |
||||
currentProject = null; |
||||
} |
||||
} |
||||
|
||||
@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) { |
||||
if (inGroups(proj)) { |
||||
String url = remoteUrl + proj.name; |
||||
command.addSubmodule(url, proj.path); |
||||
for (CopyFile copyfile : proj.copyfiles) { |
||||
try { |
||||
copyfile.copy(); |
||||
} catch (IOException e) { |
||||
throw new SAXException( |
||||
RepoText.get().copyFileFailed, e); |
||||
} |
||||
AddCommand add = command.git |
||||
.add() |
||||
.addFilepattern(copyfile.relativeDest); |
||||
try { |
||||
add.call(); |
||||
} catch (GitAPIException e) { |
||||
throw new SAXException(e); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
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 { |
||||
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; |
||||
} |
||||
|
||||
/** |
||||
* 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> |
||||
* |
||||
* @see org.eclipse.jgit.lib.NullProgressMonitor |
||||
* @param monitor |
||||
* @return this command |
||||
*/ |
||||
public RepoCommand setProgressMonitor(final ProgressMonitor monitor) { |
||||
this.monitor = monitor; |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public RevCommit 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); |
||||
|
||||
git = new Git(repo); |
||||
XmlManifest manifest = new XmlManifest(this, path, uri, groups); |
||||
try { |
||||
manifest.read(); |
||||
} catch (IOException e) { |
||||
throw new ManifestErrorException(e); |
||||
} |
||||
|
||||
return git |
||||
.commit() |
||||
.setMessage(RepoText.get().repoCommitMessage) |
||||
.call(); |
||||
} |
||||
|
||||
private void addSubmodule(String url, String name) throws SAXException { |
||||
SubmoduleAddCommand add = git |
||||
.submoduleAdd() |
||||
.setPath(name) |
||||
.setURI(url); |
||||
if (monitor != null) |
||||
add.setProgressMonitor(monitor); |
||||
try { |
||||
add.call(); |
||||
} catch (GitAPIException e) { |
||||
throw new SAXException(e); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,67 @@
|
||||
/* |
||||
* 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 copyFileFailed; |
||||
/***/ public String errorNoDefault; |
||||
/***/ public String errorParsingManifestFile; |
||||
/***/ public String invalidManifest; |
||||
/***/ public String repoCommitMessage; |
||||
} |
Loading…
Reference in new issue