Browse Source

Handle repo copyfile in bare repositories.

Change-Id: Ie06f0c3d1bc9b2123102efaa5542ec3c232b72cd
Signed-off-by: Yuxuan 'fishy' Wang <fishywang@google.com>
stable-3.4
Yuxuan 'fishy' Wang 11 years ago
parent
commit
0b15b48f74
  1. 40
      org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java
  2. 1
      org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
  3. 113
      org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
  4. 1
      org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
  5. 25
      org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java

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

@ -193,7 +193,7 @@ public class RepoCommandTest extends RepositoryTestCase {
} }
@Test @Test
public void testRepoManifestCopyfile() throws Exception { public void testRepoManifestCopyFile() throws Exception {
Repository localDb = createWorkRepository(); Repository localDb = createWorkRepository();
StringBuilder xmlContent = new StringBuilder(); StringBuilder xmlContent = new StringBuilder();
xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
@ -373,6 +373,44 @@ public class RepoCommandTest extends RepositoryTestCase {
oldCommitId.name(), gitlink); oldCommitId.name(), gitlink);
} }
@Test
public void testCopyFileBare() throws Exception {
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=\"foo\" name=\"")
.append(defaultUri)
.append("\" revision=\"")
.append(BRANCH)
.append("\" >")
.append("<copyfile src=\"hello.txt\" dest=\"Hello\" />")
.append("</project>")
.append("</manifest>");
JGitTestUtil.writeTrashFile(tempDb, "manifest.xml", xmlContent.toString());
RepoCommand command = new RepoCommand(remoteDb);
command.setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
.setURI(rootUri)
.call();
// Clone it
File directory = createTempDirectory("testCopyFileBare");
CloneCommand clone = Git.cloneRepository();
clone.setDirectory(directory);
clone.setURI(remoteDb.getDirectory().toURI().toString());
Repository localDb = clone.call().getRepository();
// The Hello file should exist
File hello = new File(localDb.getWorkTree(), "Hello");
assertTrue("The Hello file exists", hello.exists());
// The content of Hello file should be expected
BufferedReader reader = new BufferedReader(new FileReader(hello));
String content = reader.readLine();
reader.close();
assertEquals("The Hello file has expected content", "branch world", content);
}
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();

1
org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties

@ -51,6 +51,7 @@ cannotCreateConfig=cannot create config
cannotCreateDirectory=Cannot create directory {0} cannotCreateDirectory=Cannot create directory {0}
cannotCreateHEAD=cannot create HEAD cannotCreateHEAD=cannot create HEAD
cannotCreateIndexfile=Cannot create an index file with name {0} cannotCreateIndexfile=Cannot create an index file with name {0}
cannotCreateTempDir=Cannot create a temp dir
cannotDeleteCheckedOutBranch=Branch {0} is checked out and can not be deleted cannotDeleteCheckedOutBranch=Branch {0} is checked out and can not be deleted
cannotDeleteFile=Cannot delete file: {0} cannotDeleteFile=Cannot delete file: {0}
cannotDeleteStaleTrackingRef=Cannot delete stale tracking ref {0} cannotDeleteStaleTrackingRef=Cannot delete stale tracking ref {0}

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

@ -42,13 +42,13 @@
*/ */
package org.eclipse.jgit.gitrepo; package org.eclipse.jgit.gitrepo;
import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -59,8 +59,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.LsRemoteCommand;
import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.GitCommand; import org.eclipse.jgit.api.GitCommand;
import org.eclipse.jgit.api.SubmoduleAddCommand; import org.eclipse.jgit.api.SubmoduleAddCommand;
@ -78,6 +76,7 @@ import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter; import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
@ -87,6 +86,7 @@ import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.FileUtils;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
@ -121,8 +121,11 @@ public class RepoCommand extends GitCommand<RevCommit> {
* A callback to get ref sha1 of a repository from its uri. * A callback to get ref sha1 of a repository from its uri.
* *
* We provided a default implementation {@link DefaultRemoteReader} to * We provided a default implementation {@link DefaultRemoteReader} to
* use ls-remote command to read the sha1 from the repository. Callers may * use ls-remote command to read the sha1 from the repository and clone the
* have their own quicker implementation. * repository to read the file. Callers may have their own quicker
* implementation.
*
* @since 3.4
*/ */
public interface RemoteReader { public interface RemoteReader {
/** /**
@ -135,6 +138,20 @@ public class RepoCommand extends GitCommand<RevCommit> {
* @return the sha1 of the remote repository * @return the sha1 of the remote repository
*/ */
public ObjectId sha1(String uri, String ref) throws GitAPIException; public ObjectId sha1(String uri, String ref) throws GitAPIException;
/**
* Read a file from a remote repository.
*
* @param uri
* The URI of the remote repository
* @param ref
* The ref (branch/tag/etc.) to read
* @param path
* The relative path (inside the repo) to the file to read
* @return the file content.
*/
public byte[] readFile(String uri, String ref, String path)
throws GitAPIException, IOException;
} }
/** A default implementation of {@link RemoteReader} callback. */ /** A default implementation of {@link RemoteReader} callback. */
@ -153,23 +170,50 @@ public class RepoCommand extends GitCommand<RevCommit> {
Ref r = RefDatabase.findRef(map, ref); Ref r = RefDatabase.findRef(map, ref);
return r != null ? r.getObjectId() : null; return r != null ? r.getObjectId() : null;
} }
public byte[] readFile(String uri, String ref, String path)
throws GitAPIException, IOException {
File dir = FileUtils.createTempDir("jgit_", ".git", null); //$NON-NLS-1$ //$NON-NLS-2$
Repository repo = Git
.cloneRepository()
.setBare(true)
.setDirectory(dir)
.setURI(uri)
.call()
.getRepository();
ObjectReader reader = repo.newObjectReader();
byte[] result;
try {
ObjectId oid = repo.resolve(ref + ":" + path); //$NON-NLS-1$
result = reader.open(oid).getBytes(Integer.MAX_VALUE);
} finally {
reader.release();
FileUtils.delete(dir, FileUtils.RECURSIVE);
}
return result;
}
} }
private static class CopyFile { private static class CopyFile {
final Repository repo;
final String path;
final String src; final String src;
final String dest; final String dest;
final String relativeDest;
CopyFile(Repository repo, String path, String src, String dest) { CopyFile(Repository repo, String path, String src, String dest) {
this.src = repo.getWorkTree() + "/" + path + "/" + src; //$NON-NLS-1$ //$NON-NLS-2$ this.repo = repo;
this.relativeDest = dest; this.path = path;
this.dest = repo.getWorkTree() + "/" + dest; //$NON-NLS-1$ this.src = src;
this.dest = dest;
} }
void copy() throws IOException { void copy() throws IOException {
FileInputStream input = new FileInputStream(src); File srcFile = new File(repo.getWorkTree(),
path + "/" + src); //$NON-NLS-1$
File destFile = new File(repo.getWorkTree(), dest);
FileInputStream input = new FileInputStream(srcFile);
try { try {
FileOutputStream output = new FileOutputStream(dest); FileOutputStream output = new FileOutputStream(destFile);
try { try {
FileChannel channel = input.getChannel(); FileChannel channel = input.getChannel();
output.getChannel().transferFrom(channel, 0, channel.size()); output.getChannel().transferFrom(channel, 0, channel.size());
@ -185,9 +229,9 @@ public class RepoCommand extends GitCommand<RevCommit> {
private static class Project { private static class Project {
final String name; final String name;
final String path; final String path;
final String revision;
final Set<String> groups; final Set<String> groups;
final List<CopyFile> copyfiles; final List<CopyFile> copyfiles;
String revision;
Project(String name, String path, String revision, String groups) { Project(String name, String path, String revision, String groups) {
this.name = name; this.name = name;
@ -315,26 +359,11 @@ public class RepoCommand extends GitCommand<RevCommit> {
} }
for (Project proj : projects) { for (Project proj : projects) {
if (inGroups(proj)) { if (inGroups(proj)) {
if (proj.revision == null) command.addSubmodule(remoteUrl + proj.name,
proj.revision = defaultRevision; proj.path,
String url = remoteUrl + proj.name; proj.revision == null ?
command.addSubmodule(url, proj.path, proj.revision); defaultRevision : proj.revision,
for (CopyFile copyfile : proj.copyfiles) { 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);
}
}
} }
} }
} }
@ -503,7 +532,7 @@ public class RepoCommand extends GitCommand<RevCommit> {
cfg.setString("submodule", name, "path", name); //$NON-NLS-1$ //$NON-NLS-2$ cfg.setString("submodule", name, "path", name); //$NON-NLS-1$ //$NON-NLS-2$
cfg.setString("submodule", name, "url", uri); //$NON-NLS-1$ //$NON-NLS-2$ cfg.setString("submodule", name, "url", uri); //$NON-NLS-1$ //$NON-NLS-2$
// create gitlink // create gitlink
final DirCacheEntry dcEntry = new DirCacheEntry(name); DirCacheEntry dcEntry = new DirCacheEntry(name);
ObjectId objectId; ObjectId objectId;
if (ObjectId.isId(proj.revision)) if (ObjectId.isId(proj.revision))
objectId = ObjectId.fromString(proj.revision); objectId = ObjectId.fromString(proj.revision);
@ -515,6 +544,16 @@ public class RepoCommand extends GitCommand<RevCommit> {
dcEntry.setObjectId(objectId); dcEntry.setObjectId(objectId);
dcEntry.setFileMode(FileMode.GITLINK); dcEntry.setFileMode(FileMode.GITLINK);
builder.add(dcEntry); builder.add(dcEntry);
for (CopyFile copyfile : proj.copyfiles) {
byte[] src = callback.readFile(
uri, proj.revision, copyfile.src);
objectId = inserter.insert(Constants.OBJ_BLOB, src);
dcEntry = new DirCacheEntry(copyfile.dest);
dcEntry.setObjectId(objectId);
dcEntry.setFileMode(FileMode.REGULAR_FILE);
builder.add(dcEntry);
}
} }
String content = cfg.toText(); String content = cfg.toText();
@ -578,9 +617,11 @@ public class RepoCommand extends GitCommand<RevCommit> {
} }
} }
private void addSubmodule(String url, String name, String revision) throws SAXException { private void addSubmodule(String url, String name, String revision,
List<CopyFile> copyfiles) throws SAXException {
if (repo.isBare()) { if (repo.isBare()) {
Project proj = new Project(url, name, revision, null); Project proj = new Project(url, name, revision, null);
proj.copyfiles.addAll(copyfiles);
bareProjects.add(proj); bareProjects.add(proj);
} else { } else {
SubmoduleAddCommand add = git SubmoduleAddCommand add = git
@ -597,6 +638,10 @@ public class RepoCommand extends GitCommand<RevCommit> {
sub.checkout().setName(findRef(revision, subRepo)).call(); sub.checkout().setName(findRef(revision, subRepo)).call();
git.add().addFilepattern(name).call(); git.add().addFilepattern(name).call();
} }
for (CopyFile copyfile : copyfiles) {
copyfile.copy();
git.add().addFilepattern(copyfile.dest).call();
}
} catch (GitAPIException e) { } catch (GitAPIException e) {
throw new SAXException(e); throw new SAXException(e);
} catch (IOException e) { } catch (IOException e) {

1
org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java

@ -113,6 +113,7 @@ public class JGitText extends TranslationBundle {
/***/ public String cannotCreateDirectory; /***/ public String cannotCreateDirectory;
/***/ public String cannotCreateHEAD; /***/ public String cannotCreateHEAD;
/***/ public String cannotCreateIndexfile; /***/ public String cannotCreateIndexfile;
/***/ public String cannotCreateTempDir;
/***/ public String cannotDeleteCheckedOutBranch; /***/ public String cannotDeleteCheckedOutBranch;
/***/ public String cannotDeleteFile; /***/ public String cannotDeleteFile;
/***/ public String cannotDeleteStaleTrackingRef; /***/ public String cannotDeleteStaleTrackingRef;

25
org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java

@ -362,4 +362,29 @@ public class FileUtils {
public static String readSymLink(File path) throws IOException { public static String readSymLink(File path) throws IOException {
return FS.DETECTED.readSymLink(path); return FS.DETECTED.readSymLink(path);
} }
/**
* Create a temporary directory.
*
* @param prefix
* @param suffix
* @param dir
* The parent dir, can be null to use system default temp dir.
* @return the temp dir created.
* @throws IOException
* @since 3.4
*/
public static File createTempDir(String prefix, String suffix, File dir)
throws IOException {
final int RETRY = 1; // When something bad happens, retry once.
for (int i = 0; i < RETRY; i++) {
File tmp = File.createTempFile(prefix, suffix, dir);
if (!tmp.delete())
continue;
if (!tmp.mkdir())
continue;
return tmp;
}
throw new IOException(JGitText.get().cannotCreateTempDir);
}
} }

Loading…
Cancel
Save