diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java
index 9fc59c578..27d322079 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java
@@ -178,6 +178,41 @@ public class RepoCommandTest extends RepositoryTestCase {
assertTrue("\"all,-a\" has have b", file.exists());
}
+ @Test
+ public void testRepoManifestCopyfile() throws Exception {
+ Repository localDb = createWorkRepository();
+ StringBuilder xmlContent = new StringBuilder();
+ xmlContent.append("\n")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("");
+ 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();
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/gitrepo/internal/RepoText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/gitrepo/internal/RepoText.properties
index fb158399b..64d754de8 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/gitrepo/internal/RepoText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/gitrepo/internal/RepoText.properties
@@ -1,3 +1,4 @@
+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.
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 a7467c83d..a05dc11da 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
@@ -43,9 +43,11 @@
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;
@@ -55,6 +57,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.GitCommand;
import org.eclipse.jgit.api.SubmoduleAddCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
@@ -87,10 +90,38 @@ public class RepoCommand extends GitCommand {
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 groups;
+ final List copyfiles;
Project(String name, String path, String groups) {
this.name = name;
@@ -98,6 +129,11 @@ public class RepoCommand extends GitCommand {
this.groups = new HashSet();
if (groups != null && groups.length() > 0)
this.groups.addAll(Arrays.asList(groups.split(","))); //$NON-NLS-1$
+ copyfiles = new ArrayList();
+ }
+
+ void addCopyFile(CopyFile copyfile) {
+ copyfiles.add(copyfile);
}
}
@@ -110,6 +146,7 @@ public class RepoCommand extends GitCommand {
private final Set plusGroups;
private final Set minusGroups;
private String defaultRemote;
+ private Project currentProject;
XmlManifest(RepoCommand command, String filename, String baseUrl, String groups) {
this.command = command;
@@ -160,17 +197,34 @@ public class RepoCommand extends GitCommand {
String qName,
Attributes attributes) throws SAXException {
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$
+ 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$
- // TODO(fishywang): Handle copyfile. Do nothing for now.
+ 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;
}
}
@@ -191,6 +245,21 @@ public class RepoCommand extends GitCommand {
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 = new AddCommand(command.repo)
+ .addFilepattern(copyfile.relativeDest);
+ try {
+ add.call();
+ } catch (GitAPIException e) {
+ throw new SAXException(e);
+ }
+ }
}
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/internal/RepoText.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/internal/RepoText.java
index 519c9d156..50fc61d91 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/internal/RepoText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/internal/RepoText.java
@@ -59,6 +59,7 @@ public class RepoText extends TranslationBundle {
}
// @formatter:off
+ /***/ public String copyFileFailed;
/***/ public String errorNoDefault;
/***/ public String errorParsingManifestFile;
/***/ public String invalidManifest;