Add support to <include> tag in repo manifest xml.

Change-Id: I32d468f92e24701ea680435bf3417e3850857303
Signed-off-by: Yuxuan 'fishy' Wang <fishywang@google.com>
This commit is contained in:
Yuxuan 'fishy' Wang 2014-08-06 22:01:08 -07:00
parent b1bea54113
commit 34dd64f6fe
4 changed files with 117 additions and 6 deletions

View File

@ -571,6 +571,46 @@ public void testRemoveOverlappingBare() throws Exception {
assertTrue("The a submodule should exist", a);
}
@Test
public void testIncludeTag() throws Exception {
Repository localDb = createWorkRepository();
Repository tempDb = createWorkRepository();
StringBuilder xmlContent = new StringBuilder();
xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
.append("<manifest>")
.append("<include name=\"_include.xml\" />")
.append("<default revision=\"master\" remote=\"remote1\" />")
.append("</manifest>");
JGitTestUtil.writeTrashFile(
tempDb, "manifest.xml", xmlContent.toString());
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>");
JGitTestUtil.writeTrashFile(
tempDb, "_include.xml", xmlContent.toString());
RepoCommand command = new RepoCommand(localDb);
command
.setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
.setURI(rootUri)
.call();
File hello = new File(localDb.getWorkTree(), "foo/hello.txt");
assertTrue("submodule should be checked out", hello.exists());
BufferedReader reader = new BufferedReader(new FileReader(hello));
String content = reader.readLine();
reader.close();
assertEquals("submodule content should be as expected",
"master world", content);
}
private void resolveRelativeUris() {
// Find the longest common prefix ends with "/" as rootUri.
defaultUri = defaultDb.getDirectory().toURI().toString();

View File

@ -1,4 +1,6 @@
copyFileFailed=Error occurred during execution of copyfile rule.
errorIncludeFile=Error: unable to read include file {0}
errorIncludeNotImplemented=Error: <include> tag not supported as no callback defined.
errorNoDefault=Error: no default remote in manifest file.
errorNoDefaultFilename=Error: no default remote in manifest file {0}.
errorParsingManifestFile=Error occurred during parsing manifest file.

View File

@ -123,6 +123,7 @@ public class RepoCommand extends GitCommand<RevCommit> {
private PersonIdent author;
private RemoteReader callback;
private InputStream inputStream;
private IncludedFileReader includedReader;
private List<Project> bareProjects;
private Git git;
@ -163,6 +164,7 @@ public interface RemoteReader {
* @return the file content.
* @throws GitAPIException
* @throws IOException
* @since 3.5
*/
public byte[] readFile(String uri, String ref, String path)
throws GitAPIException, IOException;
@ -224,6 +226,25 @@ protected byte[] readFileFromRepo(Repository repo,
}
}
/**
* A callback to read included xml files.
*
* @since 3.5
*/
public interface IncludedFileReader {
/**
* Read a file from the same base dir of the manifest xml file.
*
* @param path
* The relative path to the file to read
* @return the {@code InputStream} of the file.
* @throws GitAPIException
* @throws IOException
*/
public InputStream readIncludeFile(String path)
throws GitAPIException, IOException;
}
private static class CopyFile {
final Repository repo;
final String path;
@ -309,7 +330,6 @@ public int compareTo(Project that) {
private static class XmlManifest extends DefaultHandler {
private final RepoCommand command;
private final InputStream inputStream;
private final String filename;
private final String baseUrl;
private final Map<String, String> remotes;
@ -318,12 +338,14 @@ private static class XmlManifest extends DefaultHandler {
private List<Project> projects;
private String defaultRemote;
private String defaultRevision;
private IncludedFileReader includedReader;
private int xmlInRead;
private Project currentProject;
XmlManifest(RepoCommand command, InputStream inputStream,
XmlManifest(RepoCommand command, IncludedFileReader includedReader,
String filename, String baseUrl, String groups) {
this.command = command;
this.inputStream = inputStream;
this.includedReader = includedReader;
this.filename = filename;
// Strip trailing /s to match repo behavior.
@ -349,7 +371,8 @@ private static class XmlManifest extends DefaultHandler {
}
}
void read() throws IOException {
void read(InputStream inputStream) throws IOException {
xmlInRead++;
final XMLReader xr;
try {
xr = XMLReaderFactory.createXMLReader();
@ -395,6 +418,35 @@ public void startElement(
currentProject.path,
attributes.getValue("src"), //$NON-NLS-1$
attributes.getValue("dest"))); //$NON-NLS-1$
} else if ("include".equals(qName)) { //$NON_NLS-1$
String name = attributes.getValue("name");
InputStream is = null;
if (includedReader != null) {
try {
is = includedReader.readIncludeFile(name);
} catch (Exception e) {
throw new SAXException(MessageFormat.format(
RepoText.get().errorIncludeFile, name), e);
}
} else if (filename != null) {
int index = filename.lastIndexOf('/');
String path = filename.substring(0, index + 1) + name;
try {
is = new FileInputStream(path);
} catch (IOException e) {
throw new SAXException(MessageFormat.format(
RepoText.get().errorIncludeFile, path), e);
}
}
if (is == null) {
throw new SAXException(
RepoText.get().errorIncludeNotImplemented);
}
try {
read(is);
} catch (IOException e) {
throw new SAXException(e);
}
}
}
@ -411,6 +463,10 @@ public void endElement(
@Override
public void endDocument() throws SAXException {
xmlInRead--;
if (xmlInRead != 0)
return;
// Only do the following after we finished reading everything.
if (defaultRemote == null) {
if (filename != null)
throw new SAXException(MessageFormat.format(
@ -606,6 +662,17 @@ public RepoCommand setRemoteReader(final RemoteReader callback) {
return this;
}
/**
* Set the IncludedFileReader callback.
*
* @param reader
* @return this command
*/
public RepoCommand setIncludedFileReader(IncludedFileReader reader) {
this.includedReader = reader;
return this;
}
@Override
public RevCommit call() throws GitAPIException {
try {
@ -635,9 +702,9 @@ public RevCommit call() throws GitAPIException {
git = new Git(repo);
XmlManifest manifest = new XmlManifest(
this, inputStream, path, uri, groups);
this, includedReader, path, uri, groups);
try {
manifest.read();
manifest.read(inputStream);
} catch (IOException e) {
throw new ManifestErrorException(e);
}

View File

@ -60,6 +60,8 @@ public static RepoText get() {
// @formatter:off
/***/ public String copyFileFailed;
/***/ public String errorIncludeFile;
/***/ public String errorIncludeNotImplemented;
/***/ public String errorNoDefault;
/***/ public String errorNoDefaultFilename;
/***/ public String errorParsingManifestFile;