Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Araq 2018-10-15 12:20:52 +02:00
commit 0c04da6f26
2 changed files with 141 additions and 128 deletions

View file

@ -305,15 +305,6 @@ proc absolutePath*(path: string, root = getCurrentDir()): string =
raise newException(ValueError, "The specified root is not absolute: " & root) raise newException(ValueError, "The specified root is not absolute: " & root)
joinPath(root, path) joinPath(root, path)
when isMainModule:
doAssertRaises(ValueError): discard absolutePath("a", "b")
doAssert absolutePath("a") == getCurrentDir() / "a"
doAssert absolutePath("a", "/b") == "/b" / "a"
when defined(Posix):
doAssert absolutePath("a", "/b/") == "/b" / "a"
doAssert absolutePath("a", "/b/c") == "/b/c" / "a"
doAssert absolutePath("/a", "b/") == "/a"
proc expandFilename*(filename: string): string {.rtl, extern: "nos$1", proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
tags: [ReadDirEffect].} = tags: [ReadDirEffect].} =
## Returns the full (`absolute`:idx:) path of an existing file `filename`, ## Returns the full (`absolute`:idx:) path of an existing file `filename`,
@ -1724,13 +1715,22 @@ proc getFileInfo*(path: string, followSymlink = true): FileInfo =
rawToFormalFileInfo(rawInfo, path, result) rawToFormalFileInfo(rawInfo, path, result)
proc isHidden*(path: string): bool = proc isHidden*(path: string): bool =
## Determines whether a given path is hidden or not. Returns false if the ## Determines whether ``path`` is hidden or not, using this
## file doesn't exist. The given path must be accessible from the current ## reference https://en.wikipedia.org/wiki/Hidden_file_and_hidden_directory
## working directory of the program.
## ##
## On Windows, a file is hidden if the file's 'hidden' attribute is set. ## On Windows: returns true if it exists and its "hidden" attribute is set.
## On Unix-like systems, a file is hidden if it starts with a '.' (period) ##
## and is not *just* '.' or '..' ' ." ## On posix: returns true if ``lastPathPart(path)`` starts with ``.`` and is
## not ``.`` or ``..``. Note: paths are not normalized to determine `isHidden`.
runnableExamples:
when defined(posix):
doAssert ".foo".isHidden
doAssert: not ".foo/bar".isHidden
doAssert: not ".".isHidden
doAssert: not "..".isHidden
doAssert: not "".isHidden
doAssert ".foo/".isHidden
when defined(Windows): when defined(Windows):
when useWinUnicode: when useWinUnicode:
wrapUnary(attributes, getFileAttributesW, path) wrapUnary(attributes, getFileAttributesW, path)
@ -1739,14 +1739,8 @@ proc isHidden*(path: string): bool =
if attributes != -1'i32: if attributes != -1'i32:
result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32 result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32
else: else:
if fileExists(path): let fileName = lastPathPart(path)
let result = len(fileName) >= 2 and fileName[0] == '.' and fileName != ".."
fileName = extractFilename(path)
nameLen = len(fileName)
if nameLen == 2:
result = (fileName[0] == '.') and (fileName[1] != '.')
elif nameLen > 2:
result = (fileName[0] == '.') and (fileName[3] != '.')
{.pop.} {.pop.}

View file

@ -53,124 +53,125 @@ true
import os, strutils import os, strutils
let files = @["these.txt", "are.x", "testing.r", "files.q"] block fileOperations:
let dirs = @["some", "created", "test", "dirs"] let files = @["these.txt", "are.x", "testing.r", "files.q"]
let dirs = @["some", "created", "test", "dirs"]
let dname = "__really_obscure_dir_name" let dname = "__really_obscure_dir_name"
createDir(dname)
echo dirExists(dname)
# Test creating files and dirs
for dir in dirs:
createDir(dname/dir)
echo dirExists(dname/dir)
for file in files:
let fh = open(dname/file, fmReadWrite)
fh.close()
echo fileExists(dname/file)
echo "All:"
template norm(x): untyped =
(when defined(windows): x.replace('\\', '/') else: x)
for path in walkPattern(dname/"*"):
echo path.norm
echo "Files:"
for path in walkFiles(dname/"*"):
echo path.norm
echo "Dirs:"
for path in walkDirs(dname/"*"):
echo path.norm
# Test removal of files dirs
for dir in dirs:
removeDir(dname/dir)
echo dirExists(dname/dir)
for file in files:
removeFile(dname/file)
echo fileExists(dname/file)
removeDir(dname)
echo dirExists(dname)
# createDir should create recursive directories
createDir(dirs[0] / dirs[1])
echo dirExists(dirs[0] / dirs[1]) # true
removeDir(dirs[0])
# createDir should properly handle trailing separator
createDir(dname / "")
echo dirExists(dname) # true
removeDir(dname)
# createDir should raise IOError if the path exists
# and is not a directory
open(dname, fmWrite).close
try:
createDir(dname) createDir(dname)
except IOError: echo dirExists(dname)
echo "Raises"
removeFile(dname)
# removeFile should not remove directory # Test creating files and dirs
createDir(dname) for dir in dirs:
try: createDir(dname/dir)
echo dirExists(dname/dir)
for file in files:
let fh = open(dname/file, fmReadWrite)
fh.close()
echo fileExists(dname/file)
echo "All:"
template norm(x): untyped =
(when defined(windows): x.replace('\\', '/') else: x)
for path in walkPattern(dname/"*"):
echo path.norm
echo "Files:"
for path in walkFiles(dname/"*"):
echo path.norm
echo "Dirs:"
for path in walkDirs(dname/"*"):
echo path.norm
# Test removal of files dirs
for dir in dirs:
removeDir(dname/dir)
echo dirExists(dname/dir)
for file in files:
removeFile(dname/file)
echo fileExists(dname/file)
removeDir(dname)
echo dirExists(dname)
# createDir should create recursive directories
createDir(dirs[0] / dirs[1])
echo dirExists(dirs[0] / dirs[1]) # true
removeDir(dirs[0])
# createDir should properly handle trailing separator
createDir(dname / "")
echo dirExists(dname) # true
removeDir(dname)
# createDir should raise IOError if the path exists
# and is not a directory
open(dname, fmWrite).close
try:
createDir(dname)
except IOError:
echo "Raises"
removeFile(dname) removeFile(dname)
except OSError:
echo "Raises"
removeDir(dname)
# test copyDir: # removeFile should not remove directory
createDir("a/b") createDir(dname)
open("a/b/file.txt", fmWrite).close try:
createDir("a/b/c") removeFile(dname)
open("a/b/c/fileC.txt", fmWrite).close except OSError:
echo "Raises"
removeDir(dname)
copyDir("a", "../dest/a") # test copyDir:
removeDir("a") createDir("a/b")
open("a/b/file.txt", fmWrite).close
createDir("a/b/c")
open("a/b/c/fileC.txt", fmWrite).close
echo dirExists("../dest/a/b") copyDir("a", "../dest/a")
echo fileExists("../dest/a/b/file.txt") removeDir("a")
echo fileExists("../dest/a/b/c/fileC.txt") echo dirExists("../dest/a/b")
removeDir("../dest") echo fileExists("../dest/a/b/file.txt")
# test copyDir: echo fileExists("../dest/a/b/c/fileC.txt")
# if separator at the end of a path removeDir("../dest")
createDir("a/b")
open("a/file.txt", fmWrite).close
copyDir("a/", "../dest/a/") # test copyDir:
removeDir("a") # if separator at the end of a path
createDir("a/b")
open("a/file.txt", fmWrite).close
echo dirExists("../dest/a/b") copyDir("a/", "../dest/a/")
echo fileExists("../dest/a/file.txt") removeDir("a")
removeDir("../dest")
echo dirExists("../dest/a/b")
echo fileExists("../dest/a/file.txt")
removeDir("../dest")
# Test get/set modification times
# Should support at least microsecond resolution
import times import times
let tm = fromUnix(0) + 100.microseconds block modificationTime:
writeFile("a", "") # Test get/set modification times
setLastModificationTime("a", tm) # Should support at least microsecond resolution
let tm = fromUnix(0) + 100.microseconds
writeFile("a", "")
setLastModificationTime("a", tm)
when defined(macosx): when defined(macosx):
echo "true" echo "true"
else: else:
echo getLastModificationTime("a") == tm echo getLastModificationTime("a") == tm
removeFile("a") removeFile("a")
when defined(posix): block normalizedPath:
when defined(posix):
block normalizedPath:
block relative: block relative:
doAssert normalizedPath(".") == "." doAssert normalizedPath(".") == "."
doAssert normalizedPath("..") == ".." doAssert normalizedPath("..") == ".."
@ -198,9 +199,7 @@ when defined(posix):
doAssert normalizedPath("/a/b/c/..") == "/a/b" doAssert normalizedPath("/a/b/c/..") == "/a/b"
doAssert normalizedPath("/a/b/c/../") == "/a/b" doAssert normalizedPath("/a/b/c/../") == "/a/b"
else: else:
block normalizedPath:
block relative: block relative:
doAssert normalizedPath(".") == "." doAssert normalizedPath(".") == "."
doAssert normalizedPath("..") == ".." doAssert normalizedPath("..") == ".."
@ -227,3 +226,23 @@ else:
doAssert normalizedPath("\\a\\\\\\b") == "\\a\\b" doAssert normalizedPath("\\a\\\\\\b") == "\\a\\b"
doAssert normalizedPath("\\a\\b\\c\\..") == "\\a\\b" doAssert normalizedPath("\\a\\b\\c\\..") == "\\a\\b"
doAssert normalizedPath("\\a\\b\\c\\..\\") == "\\a\\b" doAssert normalizedPath("\\a\\b\\c\\..\\") == "\\a\\b"
block isHidden:
when defined(posix):
doAssert ".foo.txt".isHidden
doAssert "bar/.foo.ext".isHidden
doAssert: not "bar".isHidden
doAssert: not "foo/".isHidden
# Corner cases: paths are not normalized when determining `isHidden`
doAssert: not ".foo/.".isHidden
doAssert: not ".foo/..".isHidden
block absolutePath:
doAssertRaises(ValueError): discard absolutePath("a", "b")
doAssert absolutePath("a") == getCurrentDir() / "a"
doAssert absolutePath("a", "/b") == "/b" / "a"
when defined(Posix):
doAssert absolutePath("a", "/b/") == "/b" / "a"
doAssert absolutePath("a", "/b/c") == "/b/c" / "a"
doAssert absolutePath("/a", "b/") == "/a"