|
1 | 1 |
|
2 |
| -import std/terminal |
| 2 | +import ./n_shutil |
| 3 | +export n_shutil |
3 | 4 |
|
4 |
| -# Nim consider it's the same as os.terminal_size, |
5 |
| -# as they are both tuple of Nim |
6 |
| -type terminal_size = tuple[columns, lines: int] |
7 |
| -proc get_terminal_size*(fallback=(80, 24)): terminal_size = |
8 |
| - ## .. hint:: this does not simply refer to environment variable, |
9 |
| - ## call `os.get_terminal_size`. This is a wrapper around |
10 |
| - ## `terminalSize` of `std/terminal`, which is more steady, |
11 |
| - ## returning meaningful result even when stdout is not associatd with |
12 |
| - ## a terminal. |
13 |
| - result.columns = terminalWidth() |
14 |
| - if result.columns == 0: |
15 |
| - result.columns = fallback[0] |
16 |
| - result.lines = terminalHeight() |
17 |
| - if result.lines == 0: |
18 |
| - result.lines = fallback[1] |
19 |
| - |
20 |
| -import std/os |
21 |
| -when defined(posix): |
22 |
| - import std/posix |
23 |
| -import ./sys_impl/auditImpl as sys |
24 |
| -import ../pyerrors/oserr |
25 |
| -import ../io_abc |
26 |
| - |
27 |
| -const COPY_BUFSIZE = when defined(windows): 64 * 1024 else: 16 * 1024 |
28 |
| -# Python uses as followings, but it seems too large |
29 |
| -# when defined(windows): 1024 * 1024 else: 64 * 1024 |
30 |
| - |
31 |
| -proc copyfileobjImpl(s, d: File, length=COPY_BUFSIZE) = |
32 |
| - ## shutil.copyfileobj but for Nim's `File`, here length must be positive |
33 |
| - let bufferSize = length |
34 |
| - # The following is modified from Nim-2.1.1/Lib/std/private/osfiles.nim L241 |
35 |
| - # generic version of copyFile which works for any platform: |
36 |
| - |
37 |
| - # Hints for kernel-level aggressive sequential low-fragmentation read-aheads: |
38 |
| - # https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fadvise.html |
39 |
| - when defined(linux) or defined(osx): |
40 |
| - discard posix_fadvise(getFileHandle(d), 0.cint, 0.cint, POSIX_FADV_SEQUENTIAL) |
41 |
| - discard posix_fadvise(getFileHandle(s), 0.cint, 0.cint, POSIX_FADV_SEQUENTIAL) |
42 |
| - var buf = alloc(bufferSize) |
43 |
| - while true: |
44 |
| - var bytesread = readBuffer(s, buf, bufferSize) |
45 |
| - if bytesread > 0: |
46 |
| - var byteswritten = writeBuffer(d, buf, bytesread) |
47 |
| - if bytesread != byteswritten: |
48 |
| - dealloc(buf) |
49 |
| - raiseOSError(osLastError()) |
50 |
| - if bytesread != bufferSize: break |
51 |
| - dealloc(buf) |
52 |
| - flushFile(d) |
53 |
| - |
54 |
| -proc copyfileobj*(s, d: File, length=COPY_BUFSIZE) = |
55 |
| - ## shutil.copyfileobj but for Nim's `File` |
56 |
| - ## |
57 |
| - ## if `length` is negative, it means copying the data |
58 |
| - ## without looping over the source data in chunks |
59 |
| - if length < 0: |
60 |
| - d.write(s.readAll()) |
61 |
| - return |
62 |
| - copyfileobjImpl(s, d, length) |
63 |
| - |
64 |
| -type |
65 |
| - Error = object of PyOSError ## python's shutil.Error |
66 |
| - SameFileError* = object of Error |
67 |
| -template copyFileImpl(src, dst: string; options: CopyFlag) = |
68 |
| - ## called by copyfile |
69 |
| - bind copyFile, copyfileobjImpl |
70 |
| - when defined(windows): |
71 |
| - # std/os's `copyFile` under Windows calls copyFileW, |
72 |
| - # which will copy file attributes too. |
73 |
| - # so we use another implementation instead. |
74 |
| - let isSymlink = src.symlinkExists |
75 |
| - if isSymlink and cfSymlinkAsIs in options: |
76 |
| - createSymlink(expandSymlink(source), dest) |
77 |
| - return |
78 |
| - var |
79 |
| - fsrc = open(src) |
80 |
| - fdst = open(dst, fmWrite) |
81 |
| - defer: |
82 |
| - fsrc.close() |
83 |
| - fdst.close() |
84 |
| - copyfileobjImpl(fsrc, dst) |
85 |
| - else: |
86 |
| - copyFile(src, dst, options) |
87 |
| - |
88 |
| -template copyGen(pyname, impl) = |
89 |
| - proc pyname*[T](src, dst: PathLike[T], follow_symlinks=true) = |
90 |
| - sys.audit("shutil.copyfile", src, dst) |
91 |
| - let |
92 |
| - ssrc = $src |
93 |
| - sdst = $dst |
94 |
| - cpOptions = if follow_symlinks: {cfSymlinkFollow} else: {cfSymlinkAsIs} |
95 |
| - if sameFile(ssrc, sdst): |
96 |
| - raise newException(SameFileError, pth) |
97 |
| - tryOsOp(src, dst): impl(ssrc, sdst, options=cpOptions) |
98 |
| -
|
99 |
| -copyGen copyfile, copyFileImpl |
100 |
| -
|
101 |
| -proc copyWithPermissions(src, dst: string, |
102 |
| - options={cfSymlinkFollow}) = |
103 |
| - let dstFile = if dst.dirExists: dst / src.lastPathPart |
104 |
| - else: dst |
105 |
| - copyFileWithPermissions(src, dstFile, |
106 |
| - false, # we do not `ignorePermissionErrors` |
107 |
| - options) |
108 |
| -
|
109 |
| -copyGen copy, copyWithPermissions |
0 commit comments