diff --git a/WHATSNEW b/WHATSNEW index ce969f403..52387d175 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -17,15 +17,20 @@ Fixed bugs: * bootstrapping Ant on Windows failed Bugzilla Report 61027 - * Bugzilla Reports 59648 and 43271 - Fixed the issue where the - SCP based tasks would try to change the permissions on the - parent directory of a transferred file, instead of changing it - on the transferred file itself. - - * Bugzilla Report 60644 - Fixed the issue where the source file - being copied could end up being corrupted if the target of the - copy happened to be the same source file (symlinked back - to itself). + * Fixed the issue where the SCP based tasks would try to change + the permissions on the parent directory of a transferred file, + instead of changing it on the transferred file itself. + Bugzilla Reports 59648 and 43271 + + * Fixed the issue where the source file being copied could end + up being corrupted if the target of the copy happened to be + the same source file (symlinked back to itself). + Bugzilla Report 60644 + + * Fixed the issue where symlink creation with "overwrite=false", + on existing symlink whose target was a directory, would end + up creating a new symlink under the target directory. + Bugzilla Report 58683 Other changes: -------------- diff --git a/manual/Tasks/symlink.html b/manual/Tasks/symlink.html index df42abd6a..331bd79f6 100644 --- a/manual/Tasks/symlink.html +++ b/manual/Tasks/symlink.html @@ -26,10 +26,10 @@
Manages symbolic links on Unix based platforms. Can be used to -make an individual link, delete a link, create multiple links from properties files, -or create properties files describing links in the specified directories. -Existing links are not overwritten by default. +
Manages symbolic links on platforms where Java supports symbolic links. +Can be used to make an individual link, delete a link, create multiple links +from properties files, or create properties files describing links in the +specified directories. Existing links are not overwritten by default.
FileSets are used to select a set of links to record, or a set of property files to create links from.
@@ -127,18 +127,8 @@ set of links to record, or a set of property files to create links from. variable to an absolute path, which will remove the /some/working/directory portion of the above path and allow ant to find the correct commandline execution script. -LIMITATIONS: Because Java has no direct support for
- handling symlinks this task divines them by comparing canonical and
- absolute paths. On non-unix systems this may cause false positives.
- Furthermore, any operating system on which the command
- ln -s <linkname> <resourcename>
is not a valid
- command on the command line will not be able to use action="single" or
- action="recreate". Action="record" and action=delete should still work. Finally,
- the lack of support for symlinks in Java means that all links are recorded as
- links to the canonical resource name. Therefore the link:
- link --> subdir/dir/../foo.bar
will be recorded as
- link=subdir/foo.bar
and restored as
- link --> subdir/foo.bar
NOTE: Starting Ant version 1.10.2, this task relies on the symbolic + link support introduced in Java 7 through the java.nio.file.Files APIs
diff --git a/src/etc/testcases/taskdefs/optional/unix/symlink.xml b/src/etc/testcases/taskdefs/optional/unix/symlink.xml index f039a622f..134f29f18 100644 --- a/src/etc/testcases/taskdefs/optional/unix/symlink.xml +++ b/src/etc/testcases/taskdefs/optional/unix/symlink.xml @@ -302,7 +302,7 @@LIMITATIONS: Because Java has no direct support for
- * handling symlinks this task divines them by comparing canonical and
- * absolute paths. On non-unix systems this may cause false positives.
- * Furthermore, any operating system on which the command
- * ln -s link resource
is not a valid command on the command line
- * will not be able to use action="delete", action="single"
- * or action="recreate", but action="record" should still
- * work. Finally, the lack of support for symlinks in Java means that all links
- * are recorded as links to the canonical resource name.
- * Therefore the link: link --> subdir/dir/../foo.bar
will be
- * recorded as link=subdir/foo.bar
and restored as
- * link --> subdir/foo.bar
.
Note: Starting Ant version 1.10.2, this task relies on the symbolic link support + * introduced in Java 7 through the {@link Files} APIs. */ public class Symlink extends DispatchTask { - private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); - private static final SymbolicLinkUtils SYMLINK_UTILS = - SymbolicLinkUtils.getSymbolicLinkUtils(); private String resource; private String link; @@ -187,12 +172,18 @@ public class Symlink extends DispatchTask { handleError("Must define the link name for symlink!"); return; } + final Path linkPath = Paths.get(link); + if (!Files.isSymbolicLink(linkPath)) { + log("Skipping deletion of " + linkPath + " since it's not a symlink", Project.MSG_VERBOSE); + // just ignore and silently return (this is consistent + // with the current, 1.9.x versions, of Ant) + return; + + } log("Removing symlink: " + link); - SYMLINK_UTILS.deleteSymbolicLink(FILE_UTILS - .resolveFile(new File("."), link), - this); + deleteSymLink(linkPath); } catch (IOException ioe) { - handleError(ioe.toString()); + handleError(ioe.getMessage()); } finally { setDefaults(); } @@ -207,26 +198,31 @@ public class Symlink extends DispatchTask { try { if (fileSets.isEmpty()) { handleError( - "File set identifying link file(s) required for action recreate"); + "File set identifying link file(s) required for action recreate"); return; } - Properties links = loadLinks(fileSets); - - for (String lnk : links.stringPropertyNames()) { - String res = links.getProperty(lnk); - // handle the case where lnk points to a directory (bug 25181) + final Properties links = loadLinks(fileSets); + for (final String lnk : links.stringPropertyNames()) { + final String res = links.getProperty(lnk); try { - File test = new File(lnk); - if (!SYMLINK_UTILS.isSymbolicLink(lnk)) { - doLink(res, lnk); - } else if (!test.getCanonicalPath().equals( - new File(res).getCanonicalPath())) { - SYMLINK_UTILS.deleteSymbolicLink(test, this); - doLink(res, lnk); - } // else lnk exists, do nothing - } catch (IOException ioe) { - handleError("IO exception while creating link"); + if (Files.isSymbolicLink(Paths.get(lnk)) && + new File(lnk).getCanonicalPath().equals(new File(res).getCanonicalPath())) { + // it's already a symlink and the symlink target is the same + // as the target noted in the properties file. So there's no + // need to recreate it + continue; + } + } catch (IOException e) { + final String errMessage = "Failed to check if path " + lnk + " is a symbolic link, linking to " + res; + if (failonerror) { + throw new BuildException(errMessage, e); + } + // log and continue + log(errMessage, Project.MSG_INFO); + continue; } + // create the link + this.doLink(res, lnk); } } finally { setDefaults(); @@ -361,56 +357,45 @@ public class Symlink extends DispatchTask { /** * Delete a symlink (without deleting the associated resource). + *
+ *
This is a convenience method that simply invokes {@link #deleteSymlink(File)} * - *
This is a convenience method that simply invokes
- * deleteSymlink(java.io.File)
.
- *
- * @param path A string containing the path of the symlink to delete.
+ * @param path A string containing the path of the symlink to delete.
+ * @throws IOException If the deletion attempt fails
*
- * @throws IOException If calls to File.rename
- * or File.delete
fail.
- * @deprecated use
- * org.apache.tools.ant.util.SymbolicLinkUtils#deleteSymbolicLink
- * instead
+ * @deprecated use {@link Files#delete(Path)} instead
*/
@Deprecated
- public static void deleteSymlink(String path)
- throws IOException {
- SYMLINK_UTILS.deleteSymbolicLink(new File(path), null);
+ public static void deleteSymlink(final String path)
+ throws IOException {
+ deleteSymlink(Paths.get(path).toFile());
}
/**
* Delete a symlink (without deleting the associated resource).
- *
- *
This is a utility method that removes a unix symlink without removing + *
+ *
This is a utility method that removes a symlink without removing * the resource that the symlink points to. If it is accidentally invoked - * on a real file, the real file will not be harmed.
- * - *This method works by - * getting the canonical path of the link, using the canonical path to - * rename the resource (breaking the link) and then deleting the link. - * The resource is then returned to its original name inside a finally - * block to ensure that the resource is unharmed even in the event of - * an exception.
+ * on a real file, the real file will not be harmed and instead this method + * returns silently. + ** - *
Since Ant 1.8.0 this method will try to delete the File object if - * it reports it wouldn't exist (as symlinks pointing nowhere usually do). - * Prior version would throw a FileNotFoundException in that case.
+ *Since Ant 1.10.2 this method relies on the {@link Files#isSymbolicLink(Path)} + * and {@link Files#delete(Path)} to check and delete the symlink + *
* - * @param linkfil AFile
object of the symlink to delete.
+ * @param linkfil A File
object of the symlink to delete. Cannot be null.
+ * @throws IOException If the attempt to delete runs into exception
*
- * @throws IOException If calls to File.rename
,
- * File.delete
or
- * File.getCanonicalPath
- * fail.
- * @deprecated use
- * org.apache.tools.ant.util.SymbolicLinkUtils#deleteSymbolicLink
- * instead
+ * @deprecated use {@link Files#delete(Path)} instead
*/
@Deprecated
- public static void deleteSymlink(File linkfil)
- throws IOException {
- SYMLINK_UTILS.deleteSymbolicLink(linkfil, null);
+ public static void deleteSymlink(final File linkfil)
+ throws IOException {
+ if (!Files.isSymbolicLink(linkfil.toPath())) {
+ return;
+ }
+ deleteSymLink(linkfil.toPath());
}
/**
@@ -448,36 +433,59 @@ public class Symlink extends DispatchTask {
/**
* Conduct the actual construction of a link.
*
- * The link is constructed by calling Execute.runCommand
.
File
objects containing the
- * links (with canonical parent directories).
+ * @param fileSets The filesets specified by the user.
+ * @return A Set of File
objects containing the
+ * links (with canonical parent directories).
*/
private Set