| @@ -9,6 +9,12 @@ Fixed bugs: | |||
| the shorter alias names. | |||
| Bugzilla Report 65539 | |||
| Other changes: | |||
| -------------- | |||
| * The tar task now preserves symlinks of nested tarfilesets. | |||
| Github Pull Request #142 | |||
| Changes from Ant 1.9.15 TO Ant 1.9.16 | |||
| ===================================== | |||
| @@ -197,4 +197,12 @@ | |||
| <untar src="${output}/testout/test.tar" dest="${output}/untar"/> | |||
| </target> | |||
| <target name="testTarFilesetWithSymlinks"> | |||
| <gunzip src="../testtarwithsymlinks.tar.gz" dest="${output}/source.tar"/> | |||
| <tar destfile="${output}/result.tar"> | |||
| <tarfileset prefix="pre" src="${output}/source.tar"/> | |||
| </tar> | |||
| <echo message="asd ${output}"/> | |||
| </target> | |||
| </project> | |||
| @@ -412,12 +412,7 @@ public class Tar extends MatchingTask { | |||
| return; | |||
| } | |||
| String prefix = tarFileSet.getPrefix(this.getProject()); | |||
| // '/' is appended for compatibility with the zip task. | |||
| if (prefix.length() > 0 && !prefix.endsWith("/")) { | |||
| prefix = prefix + "/"; | |||
| } | |||
| vPath = prefix + vPath; | |||
| vPath = getCanonicalPrefix(tarFileSet, this.getProject()) + vPath; | |||
| } | |||
| preserveLeadingSlashes = tarFileSet.getPreserveLeadingSlashes(); | |||
| @@ -469,6 +464,14 @@ public class Tar extends MatchingTask { | |||
| te.setUserId(tr.getUid()); | |||
| te.setGroupName(tr.getGroup()); | |||
| te.setGroupId(tr.getGid()); | |||
| String linkName = tr.getLinkName(); | |||
| byte linkFlag = tr.getLinkFlag(); | |||
| if (linkFlag == TarConstants.LF_LINK && | |||
| linkName != null && linkName.length() > 0 && !linkName.startsWith("/")) { | |||
| linkName = getCanonicalPrefix(tarFileSet, this.getProject()) + linkName; | |||
| } | |||
| te.setLinkName(linkName); | |||
| te.setLinkFlag(linkFlag); | |||
| } | |||
| } | |||
| @@ -799,6 +802,15 @@ public class Tar extends MatchingTask { | |||
| return tfs; | |||
| } | |||
| private static String getCanonicalPrefix(TarFileSet tarFileSet, Project project) { | |||
| String prefix = tarFileSet.getPrefix(project); | |||
| // '/' is appended for compatibility with the zip task. | |||
| if (prefix.isEmpty() || prefix.endsWith("/")) { | |||
| return prefix; | |||
| } | |||
| return prefix += "/"; | |||
| } | |||
| /** | |||
| * This is a FileSet with the option to specify permissions | |||
| * and other attributes. | |||
| @@ -26,6 +26,7 @@ import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| import org.apache.tools.tar.TarConstants; | |||
| import org.apache.tools.tar.TarEntry; | |||
| import org.apache.tools.tar.TarInputStream; | |||
| @@ -39,6 +40,8 @@ public class TarResource extends ArchiveResource { | |||
| private String groupName = ""; | |||
| private int uid; | |||
| private int gid; | |||
| private byte linkFlag = TarConstants.LF_NORMAL; | |||
| private String linkName = ""; | |||
| /** | |||
| * Default constructor. | |||
| @@ -152,6 +155,22 @@ public class TarResource extends ArchiveResource { | |||
| return gid; | |||
| } | |||
| /** | |||
| * @return the link "name" (=path) of this entry; an empty string if this is no link | |||
| * @since 1.9.17 | |||
| */ | |||
| public String getLinkName() { | |||
| return linkName; | |||
| } | |||
| /** | |||
| * @return the link "flag" (=type) of this entry | |||
| * @since 1.9.17 | |||
| */ | |||
| public byte getLinkFlag() { | |||
| return linkFlag; | |||
| } | |||
| /** | |||
| * fetches information from the named entry inside the archive. | |||
| */ | |||
| @@ -191,6 +210,8 @@ public class TarResource extends ArchiveResource { | |||
| groupName = e.getGroupName(); | |||
| uid = e.getUserId(); | |||
| gid = e.getGroupId(); | |||
| linkName = e.getLinkName(); | |||
| linkFlag = e.getLinkFlag(); | |||
| } | |||
| } | |||
| @@ -398,6 +398,26 @@ public class TarEntry implements TarConstants { | |||
| this.mode = mode; | |||
| } | |||
| /** | |||
| * Get this entry's link flag. | |||
| * | |||
| * @return This entry's link flag. | |||
| * @since 1.9.17 | |||
| */ | |||
| public byte getLinkFlag() { | |||
| return linkFlag; | |||
| } | |||
| /** | |||
| * Set this entry's link flag. | |||
| * | |||
| * @param link the link flag to use. | |||
| * @since 1.9.17 | |||
| */ | |||
| public void setLinkFlag(byte linkFlag) { | |||
| this.linkFlag = linkFlag; | |||
| } | |||
| /** | |||
| * Get this entry's link name. | |||
| * | |||
| @@ -20,16 +20,20 @@ package org.apache.tools.ant.taskdefs; | |||
| import java.io.IOException; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.BuildFileRule; | |||
| import org.apache.tools.ant.FileUtilities; | |||
| import org.apache.tools.tar.TarEntry; | |||
| import org.apache.tools.tar.TarInputStream; | |||
| import org.junit.Before; | |||
| import org.junit.Rule; | |||
| import org.junit.Test; | |||
| import static org.junit.Assert.assertEquals; | |||
| import static org.junit.Assert.fail; | |||
| import static org.junit.Assert.assertNull; | |||
| public class TarTest { | |||
| @@ -206,5 +210,26 @@ public class TarTest { | |||
| FileUtilities.getFileContents(new File(buildRule.getProject().getProperty("output"), "untar/asf-logo.gif.gz"))); | |||
| } | |||
| @Test | |||
| public void testTarFilesetWithSymlinks() throws IOException { | |||
| buildRule.executeTarget("testTarFilesetWithSymlinks"); | |||
| final File f = new File(buildRule.getProject().getProperty("output"), "result.tar"); | |||
| final TarInputStream tis = new TarInputStream(new FileInputStream(f)); | |||
| try { | |||
| final TarEntry e1 = tis.getNextEntry(); | |||
| assertEquals("pre/dir/file", e1.getName()); | |||
| assertEquals("", e1.getLinkName()); | |||
| assertEquals(48, e1.getLinkFlag()); | |||
| final TarEntry e2 = tis.getNextEntry(); | |||
| assertEquals("pre/sub/file", e2.getName()); | |||
| assertEquals("../dir/file", e2.getLinkName()); | |||
| assertEquals(50, e2.getLinkFlag()); | |||
| assertNull(tis.getNextEntry()); | |||
| } | |||
| finally { | |||
| tis.close(); | |||
| } | |||
| } | |||
| } | |||