summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md1
-rw-r--r--lib/pure/os.nim8
-rw-r--r--tests/stdlib/tos.nim19
3 files changed, 27 insertions, 1 deletions
diff --git a/changelog.md b/changelog.md
index 6b4d4cf2b..07533c2d2 100644
--- a/changelog.md
+++ b/changelog.md
@@ -209,6 +209,7 @@
 - Added `progressInterval` argument to `asyncftpclient.newAsyncFtpClient` to control the interval
   at which progress callbacks are called.
 
+- Added `os.copyFileToDir`
 
 ## Language changes
 
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 5efbde268..2601f9d47 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1682,7 +1682,7 @@ proc setFilePermissions*(filename: string, permissions: set[FilePermission]) {.
 
 proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
   tags: [ReadIOEffect, WriteIOEffect], noWeirdTarget.} =
-  ## Copies a file from `source` to `dest`.
+  ## Copies a file from `source` to `dest`, where `dest.parentDir` must exist.
   ##
   ## If this fails, `OSError` is raised.
   ##
@@ -1738,6 +1738,12 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
     flushFile(d)
     close(d)
 
+proc copyFileToDir*(source, dir: string) {.noWeirdTarget, since: (1,3,7).} =
+  ## Copies a file `source` into directory `dir`, which must exist.
+  if dir.len == 0: # treating "" as "." is error prone
+    raise newException(ValueError, "dest is empty")
+  copyFile(source, dir / source.lastPathPart)
+
 when not declared(ENOENT) and not defined(Windows):
   when NoFakeVars:
     when not defined(haiku):
diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim
index 814ff103d..019303ebf 100644
--- a/tests/stdlib/tos.nim
+++ b/tests/stdlib/tos.nim
@@ -36,6 +36,25 @@ block fileOperations:
   createDir(dname)
   doAssert dirExists(dname)
 
+  block: # copyFile, copyFileToDir
+    doAssertRaises(OSError): copyFile(dname/"nonexistant.txt", dname/"nonexistant.txt")
+    let fname = "D20201009T112235"
+    let fname2 = "D20201009T112235.2"
+    writeFile(dname/fname, "foo")
+    let sub = "sub"
+    doAssertRaises(OSError): copyFile(dname/fname, dname/sub/fname2)
+    doAssertRaises(OSError): copyFileToDir(dname/fname, dname/sub)
+    doAssertRaises(ValueError): copyFileToDir(dname/fname, "")
+    copyFile(dname/fname, dname/fname2)
+    doAssert fileExists(dname/fname2)
+    createDir(dname/sub)
+    copyFileToDir(dname/fname, dname/sub)
+    doAssert fileExists(dname/sub/fname)
+    removeDir(dname/sub)
+    doAssert not dirExists(dname/sub)
+    removeFile(dname/fname)
+    removeFile(dname/fname2)
+
   # Test creating files and dirs
   for dir in dirs:
     createDir(dname/dir)