@@ -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(); | |||||
} | |||||
} | |||||
} | } |