Handle repo copyfile in bare repositories.
Change-Id: Ie06f0c3d1bc9b2123102efaa5542ec3c232b72cd Signed-off-by: Yuxuan 'fishy' Wang <fishywang@google.com>
This commit is contained in:
parent
d998bc938a
commit
0b15b48f74
|
@ -193,7 +193,7 @@ public void testRepoManifestGroups() throws Exception {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testRepoManifestCopyfile() throws Exception {
|
||||
public void testRepoManifestCopyFile() throws Exception {
|
||||
Repository localDb = createWorkRepository();
|
||||
StringBuilder xmlContent = new StringBuilder();
|
||||
xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
|
||||
|
@ -373,6 +373,44 @@ public void testRevisionBare() throws Exception {
|
|||
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() {
|
||||
// Find the longest common prefix ends with "/" as rootUri.
|
||||
defaultUri = defaultDb.getDirectory().toURI().toString();
|
||||
|
|
|
@ -51,6 +51,7 @@ cannotCreateConfig=cannot create config
|
|||
cannotCreateDirectory=Cannot create directory {0}
|
||||
cannotCreateHEAD=cannot create HEAD
|
||||
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
|
||||
cannotDeleteFile=Cannot delete file: {0}
|
||||
cannotDeleteStaleTrackingRef=Cannot delete stale tracking ref {0}
|
||||
|
|
|
@ -42,13 +42,13 @@
|
|||
*/
|
||||
package org.eclipse.jgit.gitrepo;
|
||||
|
||||
import java.io.File;
|
||||
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.nio.charset.Charset;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -59,8 +59,6 @@
|
|||
import java.util.Map;
|
||||
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.GitCommand;
|
||||
import org.eclipse.jgit.api.SubmoduleAddCommand;
|
||||
|
@ -78,6 +76,7 @@
|
|||
import org.eclipse.jgit.lib.FileMode;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.ObjectReader;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.ProgressMonitor;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
|
@ -87,6 +86,7 @@
|
|||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
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.
|
||||
*
|
||||
* We provided a default implementation {@link DefaultRemoteReader} to
|
||||
* use ls-remote command to read the sha1 from the repository. Callers may
|
||||
* have their own quicker implementation.
|
||||
* use ls-remote command to read the sha1 from the repository and clone the
|
||||
* repository to read the file. Callers may have their own quicker
|
||||
* implementation.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public interface RemoteReader {
|
||||
/**
|
||||
|
@ -135,6 +138,20 @@ public interface RemoteReader {
|
|||
* @return the sha1 of the remote repository
|
||||
*/
|
||||
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. */
|
||||
|
@ -153,23 +170,50 @@ public ObjectId sha1(String uri, String ref) throws GitAPIException {
|
|||
Ref r = RefDatabase.findRef(map, ref);
|
||||
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 {
|
||||
final Repository repo;
|
||||
final String path;
|
||||
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$
|
||||
this.repo = repo;
|
||||
this.path = path;
|
||||
this.src = src;
|
||||
this.dest = dest;
|
||||
}
|
||||
|
||||
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 {
|
||||
FileOutputStream output = new FileOutputStream(dest);
|
||||
FileOutputStream output = new FileOutputStream(destFile);
|
||||
try {
|
||||
FileChannel channel = input.getChannel();
|
||||
output.getChannel().transferFrom(channel, 0, channel.size());
|
||||
|
@ -185,9 +229,9 @@ void copy() throws IOException {
|
|||
private static class Project {
|
||||
final String name;
|
||||
final String path;
|
||||
final String revision;
|
||||
final Set<String> groups;
|
||||
final List<CopyFile> copyfiles;
|
||||
String revision;
|
||||
|
||||
Project(String name, String path, String revision, String groups) {
|
||||
this.name = name;
|
||||
|
@ -315,26 +359,11 @@ public void endDocument() throws SAXException {
|
|||
}
|
||||
for (Project proj : projects) {
|
||||
if (inGroups(proj)) {
|
||||
if (proj.revision == null)
|
||||
proj.revision = defaultRevision;
|
||||
String url = remoteUrl + proj.name;
|
||||
command.addSubmodule(url, proj.path, proj.revision);
|
||||
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);
|
||||
}
|
||||
}
|
||||
command.addSubmodule(remoteUrl + proj.name,
|
||||
proj.path,
|
||||
proj.revision == null ?
|
||||
defaultRevision : proj.revision,
|
||||
proj.copyfiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -503,7 +532,7 @@ public RevCommit call() throws GitAPIException {
|
|||
cfg.setString("submodule", name, "path", name); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
cfg.setString("submodule", name, "url", uri); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
// create gitlink
|
||||
final DirCacheEntry dcEntry = new DirCacheEntry(name);
|
||||
DirCacheEntry dcEntry = new DirCacheEntry(name);
|
||||
ObjectId objectId;
|
||||
if (ObjectId.isId(proj.revision))
|
||||
objectId = ObjectId.fromString(proj.revision);
|
||||
|
@ -515,6 +544,16 @@ public RevCommit call() throws GitAPIException {
|
|||
dcEntry.setObjectId(objectId);
|
||||
dcEntry.setFileMode(FileMode.GITLINK);
|
||||
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();
|
||||
|
||||
|
@ -578,9 +617,11 @@ public RevCommit call() throws GitAPIException {
|
|||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
Project proj = new Project(url, name, revision, null);
|
||||
proj.copyfiles.addAll(copyfiles);
|
||||
bareProjects.add(proj);
|
||||
} else {
|
||||
SubmoduleAddCommand add = git
|
||||
|
@ -597,6 +638,10 @@ private void addSubmodule(String url, String name, String revision) throws SAXEx
|
|||
sub.checkout().setName(findRef(revision, subRepo)).call();
|
||||
git.add().addFilepattern(name).call();
|
||||
}
|
||||
for (CopyFile copyfile : copyfiles) {
|
||||
copyfile.copy();
|
||||
git.add().addFilepattern(copyfile.dest).call();
|
||||
}
|
||||
} catch (GitAPIException e) {
|
||||
throw new SAXException(e);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -113,6 +113,7 @@ public static JGitText get() {
|
|||
/***/ public String cannotCreateDirectory;
|
||||
/***/ public String cannotCreateHEAD;
|
||||
/***/ public String cannotCreateIndexfile;
|
||||
/***/ public String cannotCreateTempDir;
|
||||
/***/ public String cannotDeleteCheckedOutBranch;
|
||||
/***/ public String cannotDeleteFile;
|
||||
/***/ public String cannotDeleteStaleTrackingRef;
|
||||
|
|
|
@ -362,4 +362,29 @@ public static void createSymLink(File path, String target)
|
|||
public static String readSymLink(File path) throws IOException {
|
||||
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…
Reference in New Issue