| @@ -9,6 +9,12 @@ Fixed bugs: | |||||
| the shorter alias names. | the shorter alias names. | ||||
| Bugzilla Report 65539 | 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 | Changes from Ant 1.9.15 TO Ant 1.9.16 | ||||
| ===================================== | ===================================== | ||||
| @@ -197,4 +197,12 @@ | |||||
| <untar src="${output}/testout/test.tar" dest="${output}/untar"/> | <untar src="${output}/testout/test.tar" dest="${output}/untar"/> | ||||
| </target> | </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> | </project> | ||||
| @@ -412,12 +412,7 @@ public class Tar extends MatchingTask { | |||||
| return; | 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(); | preserveLeadingSlashes = tarFileSet.getPreserveLeadingSlashes(); | ||||
| @@ -469,6 +464,14 @@ public class Tar extends MatchingTask { | |||||
| te.setUserId(tr.getUid()); | te.setUserId(tr.getUid()); | ||||
| te.setGroupName(tr.getGroup()); | te.setGroupName(tr.getGroup()); | ||||
| te.setGroupId(tr.getGid()); | 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; | 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 | * This is a FileSet with the option to specify permissions | ||||
| * and other attributes. | * and other attributes. | ||||
| @@ -26,6 +26,7 @@ import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| import org.apache.tools.ant.types.Resource; | import org.apache.tools.ant.types.Resource; | ||||
| import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
| import org.apache.tools.tar.TarConstants; | |||||
| import org.apache.tools.tar.TarEntry; | import org.apache.tools.tar.TarEntry; | ||||
| import org.apache.tools.tar.TarInputStream; | import org.apache.tools.tar.TarInputStream; | ||||
| @@ -39,6 +40,8 @@ public class TarResource extends ArchiveResource { | |||||
| private String groupName = ""; | private String groupName = ""; | ||||
| private int uid; | private int uid; | ||||
| private int gid; | private int gid; | ||||
| private byte linkFlag = TarConstants.LF_NORMAL; | |||||
| private String linkName = ""; | |||||
| /** | /** | ||||
| * Default constructor. | * Default constructor. | ||||
| @@ -152,6 +155,22 @@ public class TarResource extends ArchiveResource { | |||||
| return gid; | 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. | * fetches information from the named entry inside the archive. | ||||
| */ | */ | ||||
| @@ -191,6 +210,8 @@ public class TarResource extends ArchiveResource { | |||||
| groupName = e.getGroupName(); | groupName = e.getGroupName(); | ||||
| uid = e.getUserId(); | uid = e.getUserId(); | ||||
| gid = e.getGroupId(); | gid = e.getGroupId(); | ||||
| linkName = e.getLinkName(); | |||||
| linkFlag = e.getLinkFlag(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -398,6 +398,26 @@ public class TarEntry implements TarConstants { | |||||
| this.mode = mode; | 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. | * Get this entry's link name. | ||||
| * | * | ||||
| @@ -20,16 +20,20 @@ package org.apache.tools.ant.taskdefs; | |||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.FileInputStream; | |||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.BuildFileRule; | import org.apache.tools.ant.BuildFileRule; | ||||
| import org.apache.tools.ant.FileUtilities; | 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.Before; | ||||
| import org.junit.Rule; | import org.junit.Rule; | ||||
| import org.junit.Test; | import org.junit.Test; | ||||
| import static org.junit.Assert.assertEquals; | import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.fail; | import static org.junit.Assert.fail; | ||||
| import static org.junit.Assert.assertNull; | |||||
| public class TarTest { | public class TarTest { | ||||
| @@ -206,5 +210,26 @@ public class TarTest { | |||||
| FileUtilities.getFileContents(new File(buildRule.getProject().getProperty("output"), "untar/asf-logo.gif.gz"))); | 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(); | |||||
| } | |||||
| } | |||||
| } | } | ||||