RepoCommand: Preserve executable bit in <copyfile>

The copyfile entry in the manifest file copies the contents of the file
but doesn't keep the executable flag. This is inconsistent with repo
tool behaviour, plus is natural to expect that the copy of a executable
file is executable.

Transfer the executable bit when copying the file, aligning the
RepoCommand with repo tool and user expectations.

Change-Id: I01b24f482d5939e01d496f032388b3a5c02a912a
Signed-off-by: Ivan Frade <ifrade@google.com>
This commit is contained in:
Ivan Frade 2018-10-26 17:03:40 -07:00
parent f648a3bd81
commit e64ce267f8
3 changed files with 123 additions and 3 deletions

View File

@ -577,13 +577,69 @@ public void testRepoManifestCopyFile() throws Exception {
// The original file should exist
File hello = new File(localDb.getWorkTree(), "foo/hello.txt");
assertTrue("The original file should exist", hello.exists());
assertFalse("The original file should not be executable",
hello.canExecute());
assertContents(hello.toPath(), "master world");
// The dest file should also exist
hello = new File(localDb.getWorkTree(), "Hello");
assertTrue("The destination file should exist", hello.exists());
assertFalse("The destination file should not be executable",
hello.canExecute());
assertContents(hello.toPath(), "master world");
}
@Test
public void testRepoManifestCopyFile_executable() throws Exception {
try (Git git = new Git(defaultDb)) {
git.checkout().setName("master").call();
File f = JGitTestUtil.writeTrashFile(defaultDb, "hello.sh",
"content of the executable file");
f.setExecutable(true);
git.add().addFilepattern("hello.sh").call();
git.commit().setMessage("Add binary file").call();
}
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.sh\" dest=\"copy-hello.sh\" />")
.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 and be an executable
File hello = new File(localDb.getWorkTree(), "foo/hello.sh");
assertTrue("The original file should exist", hello.exists());
assertTrue("The original file must be executable", hello.canExecute());
try (BufferedReader reader = Files.newBufferedReader(hello.toPath(),
UTF_8)) {
String content = reader.readLine();
assertEquals("The original file should have expected content",
"content of the executable file", content);
}
// The destination file should also exist and be an executable
hello = new File(localDb.getWorkTree(), "copy-hello.sh");
assertTrue("The destination file should exist", hello.exists());
assertTrue("The destination file must be executable",
hello.canExecute());
try (BufferedReader reader = Files.newBufferedReader(hello.toPath(),
UTF_8)) {
String content = reader.readLine();
assertEquals("The destination file should have expected content",
"content of the executable file", content);
}
}
@Test
public void testBareRepo() throws Exception {
Repository remoteDb = createBareRepository();
@ -767,6 +823,68 @@ public void testCopyFileBare() throws Exception {
}
}
@Test
public void testCopyFileBare_executable() throws Exception {
try (Git git = new Git(defaultDb)) {
git.checkout().setName(BRANCH).call();
File f = JGitTestUtil.writeTrashFile(defaultDb, "hello.sh",
"content of the executable file");
f.setExecutable(true);
git.add().addFilepattern("hello.sh").call();
git.commit().setMessage("Add binary file").call();
}
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("<copyfile src=\"hello.txt\" dest=\"foo/Hello\" />")
.append("<copyfile src=\"hello.sh\" dest=\"copy-hello.sh\" />")
.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");
try (Repository localDb = Git.cloneRepository().setDirectory(directory)
.setURI(remoteDb.getDirectory().toURI().toString()).call()
.getRepository()) {
// The Hello file should exist
File hello = new File(localDb.getWorkTree(), "Hello");
assertTrue("The Hello file should exist", hello.exists());
// The foo/Hello file should be skipped.
File foohello = new File(localDb.getWorkTree(), "foo/Hello");
assertFalse("The foo/Hello file should be skipped",
foohello.exists());
// The content of Hello file should be expected
try (BufferedReader reader = Files.newBufferedReader(hello.toPath(),
UTF_8)) {
String content = reader.readLine();
assertEquals("The Hello file should have expected content",
"branch world", content);
}
// The executable file must be there and preserve the executable bit
File helloSh = new File(localDb.getWorkTree(), "copy-hello.sh");
assertTrue("Destination file should exist", helloSh.exists());
assertContents(helloSh.toPath(), "content of the executable file");
assertTrue("Destination file should be executable",
helloSh.canExecute());
}
}
@Test
public void testReplaceManifestBare() throws Exception {
Repository remoteDb = createBareRepository();

View File

@ -663,12 +663,13 @@ public RevCommit call() throws GitAPIException {
builder.add(dcEntry);
for (CopyFile copyfile : proj.getCopyFiles()) {
byte[] src = callback.readFile(
RemoteFile rf = callback.readFileWithMode(
url, proj.getRevision(), copyfile.src);
objectId = inserter.insert(Constants.OBJ_BLOB, src);
objectId = inserter.insert(Constants.OBJ_BLOB,
rf.getContents());
dcEntry = new DirCacheEntry(copyfile.dest);
dcEntry.setObjectId(objectId);
dcEntry.setFileMode(FileMode.REGULAR_FILE);
dcEntry.setFileMode(rf.getFileMode());
builder.add(dcEntry);
}
for (LinkFile linkfile : proj.getLinkFiles()) {

View File

@ -136,6 +136,7 @@ public void copy() throws IOException {
FileChannel channel = input.getChannel();
output.getChannel().transferFrom(channel, 0, channel.size());
}
destFile.setExecutable(srcFile.canExecute());
}
}