diff options
author | Roman Inflianskas <rominf@users.noreply.github.com> | 2021-02-04 09:57:41 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-04 18:57:41 +0100 |
commit | e9b360c5dfac2331a57b1cc3310fc85fe65fe7af (patch) | |
tree | f9069b880b52ea6f81a15b2128e34c6227db9e0c /tests/stdlib | |
parent | bb85bc7ebc68e240f955015cd80f76ac424c16b5 (diff) | |
download | Nim-e9b360c5dfac2331a57b1cc3310fc85fe65fe7af.tar.gz |
stdlib/os: handle symlinks in copy/move functions (#16709)
* stdlib/os: handle symlinks in copy/move functions - Added optional `options` argument to `copyFile`, `copyFileToDir`, and `copyFileWithPermissions`. By default, symlinks are followed (copy files symlinks point to). - `copyDir` and `copyDirWithPermissions` copy symlinks as symlinks (instead of skipping them as it was before). - `moveFile` and `moveDir` move symlinks as symlinks (instead of skipping them sometimes as it was before). - Added optional `followSymlinks` argument to `setFilePermissions`. See also: https://github.com/nim-lang/RFCs/issues/319 Co-authored-by: Timothee Cour <timothee.cour2@gmail.com> * Address comments in #16709 Co-authored-by: Timothee Cour <timothee.cour2@gmail.com> * Address comments in #16709 (second iteration) Skip symlinks on Windows. Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>
Diffstat (limited to 'tests/stdlib')
-rw-r--r-- | tests/stdlib/tos.nim | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim index af3606a4a..b47412a62 100644 --- a/tests/stdlib/tos.nim +++ b/tests/stdlib/tos.nim @@ -26,6 +26,7 @@ Raises # test os path creation, iteration, and deletion import os, strutils, pathnorm +from stdtest/specialpaths import buildDir block fileOperations: let files = @["these.txt", "are.x", "testing.r", "files.q"] @@ -154,6 +155,112 @@ block fileOperations: doAssert fileExists("../dest/a/file.txt") removeDir("../dest") + # Symlink handling in `copyFile`, `copyFileWithPermissions`, `copyFileToDir`, + # `copyDir`, `copyDirWithPermissions`, `moveFile`, and `moveDir`. + block: + const symlinksAreHandled = not defined(windows) + const dname = buildDir/"D20210116T140629" + const subDir = dname/"sub" + const subDir2 = dname/"sub2" + const brokenSymlinkName = "D20210101T191320_BROKEN_SYMLINK" + const brokenSymlink = dname/brokenSymlinkName + const brokenSymlinkSrc = "D20210101T191320_nonexistant" + const brokenSymlinkCopy = brokenSymlink & "_COPY" + const brokenSymlinkInSubDir = subDir/brokenSymlinkName + const brokenSymlinkInSubDir2 = subDir2/brokenSymlinkName + + createDir(subDir) + createSymlink(brokenSymlinkSrc, brokenSymlink) + + # Test copyFile + when symlinksAreHandled: + doAssertRaises(OSError): + copyFile(brokenSymlink, brokenSymlinkCopy) + doAssertRaises(OSError): + copyFile(brokenSymlink, brokenSymlinkCopy, {cfSymlinkFollow}) + copyFile(brokenSymlink, brokenSymlinkCopy, {cfSymlinkIgnore}) + doAssert not fileExists(brokenSymlinkCopy) + copyFile(brokenSymlink, brokenSymlinkCopy, {cfSymlinkAsIs}) + when symlinksAreHandled: + doAssert expandSymlink(brokenSymlinkCopy) == brokenSymlinkSrc + removeFile(brokenSymlinkCopy) + else: + doAssert not fileExists(brokenSymlinkCopy) + doAssertRaises(AssertionDefect): + copyFile(brokenSymlink, brokenSymlinkCopy, + {cfSymlinkAsIs, cfSymlinkFollow}) + + # Test copyFileWithPermissions + when symlinksAreHandled: + doAssertRaises(OSError): + copyFileWithPermissions(brokenSymlink, brokenSymlinkCopy) + doAssertRaises(OSError): + copyFileWithPermissions(brokenSymlink, brokenSymlinkCopy, + options = {cfSymlinkFollow}) + copyFileWithPermissions(brokenSymlink, brokenSymlinkCopy, + options = {cfSymlinkIgnore}) + doAssert not fileExists(brokenSymlinkCopy) + copyFileWithPermissions(brokenSymlink, brokenSymlinkCopy, + options = {cfSymlinkAsIs}) + when symlinksAreHandled: + doAssert expandSymlink(brokenSymlinkCopy) == brokenSymlinkSrc + removeFile(brokenSymlinkCopy) + else: + doAssert not fileExists(brokenSymlinkCopy) + doAssertRaises(AssertionDefect): + copyFileWithPermissions(brokenSymlink, brokenSymlinkCopy, + options = {cfSymlinkAsIs, cfSymlinkFollow}) + + # Test copyFileToDir + when symlinksAreHandled: + doAssertRaises(OSError): + copyFileToDir(brokenSymlink, subDir) + doAssertRaises(OSError): + copyFileToDir(brokenSymlink, subDir, {cfSymlinkFollow}) + copyFileToDir(brokenSymlink, subDir, {cfSymlinkIgnore}) + doAssert not fileExists(brokenSymlinkInSubDir) + copyFileToDir(brokenSymlink, subDir, {cfSymlinkAsIs}) + when symlinksAreHandled: + doAssert expandSymlink(brokenSymlinkInSubDir) == brokenSymlinkSrc + removeFile(brokenSymlinkInSubDir) + else: + doAssert not fileExists(brokenSymlinkInSubDir) + + createSymlink(brokenSymlinkSrc, brokenSymlinkInSubDir) + + # Test copyDir + copyDir(subDir, subDir2) + when symlinksAreHandled: + doAssert expandSymlink(brokenSymlinkInSubDir2) == brokenSymlinkSrc + else: + doAssert not fileExists(brokenSymlinkInSubDir2) + removeDir(subDir2) + + # Test copyDirWithPermissions + copyDirWithPermissions(subDir, subDir2) + when symlinksAreHandled: + doAssert expandSymlink(brokenSymlinkInSubDir2) == brokenSymlinkSrc + else: + doAssert not fileExists(brokenSymlinkInSubDir2) + removeDir(subDir2) + + # Test moveFile + moveFile(brokenSymlink, brokenSymlinkCopy) + when not defined(windows): + doAssert expandSymlink(brokenSymlinkCopy) == brokenSymlinkSrc + else: + doAssert symlinkExists(brokenSymlinkCopy) + removeFile(brokenSymlinkCopy) + + # Test moveDir + moveDir(subDir, subDir2) + when not defined(windows): + doAssert expandSymlink(brokenSymlinkInSubDir2) == brokenSymlinkSrc + else: + doAssert symlinkExists(brokenSymlinkInSubDir2) + + removeDir(dname) + import times block modificationTime: # Test get/set modification times |