[backport] run nimpretty on os-related stuff
This commit is contained in:
parent
dcf3181bd1
commit
34d0be2ec1
10 changed files with 191 additions and 182 deletions
|
|
@ -32,22 +32,22 @@ when defined(linux):
|
|||
|
||||
type
|
||||
ProcessOption* = enum ## Options that can be passed to `startProcess proc
|
||||
## <#startProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_.
|
||||
poEchoCmd, ## Echo the command before execution.
|
||||
poUsePath, ## Asks system to search for executable using PATH environment
|
||||
## variable.
|
||||
## On Windows, this is the default.
|
||||
poEvalCommand, ## Pass `command` directly to the shell, without quoting.
|
||||
## Use it only if `command` comes from trusted source.
|
||||
poStdErrToStdOut, ## Merge stdout and stderr to the stdout stream.
|
||||
poParentStreams, ## Use the parent's streams.
|
||||
poInteractive, ## Optimize the buffer handling for responsiveness for
|
||||
## UI applications. Currently this only affects
|
||||
## Windows: Named pipes are used so that you can peek
|
||||
## at the process' output streams.
|
||||
poDaemon ## Windows: The program creates no Window.
|
||||
## Unix: Start the program as a daemon. This is still
|
||||
## work in progress!
|
||||
## <#startProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_.
|
||||
poEchoCmd, ## Echo the command before execution.
|
||||
poUsePath, ## Asks system to search for executable using PATH environment
|
||||
## variable.
|
||||
## On Windows, this is the default.
|
||||
poEvalCommand, ## Pass `command` directly to the shell, without quoting.
|
||||
## Use it only if `command` comes from trusted source.
|
||||
poStdErrToStdOut, ## Merge stdout and stderr to the stdout stream.
|
||||
poParentStreams, ## Use the parent's streams.
|
||||
poInteractive, ## Optimize the buffer handling for responsiveness for
|
||||
## UI applications. Currently this only affects
|
||||
## Windows: Named pipes are used so that you can peek
|
||||
## at the process' output streams.
|
||||
poDaemon ## Windows: The program creates no Window.
|
||||
## Unix: Start the program as a daemon. This is still
|
||||
## work in progress!
|
||||
|
||||
ProcessObj = object of RootObj
|
||||
when defined(windows):
|
||||
|
|
@ -66,21 +66,16 @@ type
|
|||
Process* = ref ProcessObj ## Represents an operating system process.
|
||||
|
||||
const poDemon* {.deprecated.} = poDaemon ## Nim versions before 0.20
|
||||
## used the wrong spelling ("demon").
|
||||
## Now `ProcessOption` uses the correct spelling ("daemon"),
|
||||
## and this is needed just for backward compatibility.
|
||||
## used the wrong spelling ("demon").
|
||||
## Now `ProcessOption` uses the correct spelling ("daemon"),
|
||||
## and this is needed just for backward compatibility.
|
||||
|
||||
|
||||
proc execProcess*(command: string,
|
||||
workingDir: string = "",
|
||||
args: openArray[string] = [],
|
||||
env: StringTableRef = nil,
|
||||
options: set[ProcessOption] = {poStdErrToStdOut,
|
||||
poUsePath,
|
||||
poEvalCommand}): TaintedString {.
|
||||
rtl, extern: "nosp$1",
|
||||
tags: [ExecIOEffect, ReadIOEffect,
|
||||
RootEffect].}
|
||||
proc execProcess*(command: string, workingDir: string = "",
|
||||
args: openArray[string] = [], env: StringTableRef = nil,
|
||||
options: set[ProcessOption] = {poStdErrToStdOut, poUsePath, poEvalCommand}):
|
||||
TaintedString {.rtl, extern: "nosp$1",
|
||||
tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
|
||||
## A convenience procedure that executes ``command`` with ``startProcess``
|
||||
## and returns its output as a string.
|
||||
##
|
||||
|
|
@ -102,8 +97,8 @@ proc execProcess*(command: string,
|
|||
## # Note: outp may have an interleave of text from the nim compile
|
||||
## # and any output from mytestfile when it runs
|
||||
|
||||
proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [ExecIOEffect,
|
||||
ReadIOEffect, RootEffect].}
|
||||
proc execCmd*(command: string): int {.rtl, extern: "nosp$1",
|
||||
tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
|
||||
## Executes ``command`` and returns its error code.
|
||||
##
|
||||
## Standard input, output, error streams are inherited from the calling process.
|
||||
|
|
@ -121,13 +116,11 @@ proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [ExecIOEffect
|
|||
## .. code-block:: Nim
|
||||
## let errC = execCmd("nim c -r mytestfile.nim")
|
||||
|
||||
proc startProcess*(command: string,
|
||||
workingDir: string = "",
|
||||
args: openArray[string] = [],
|
||||
env: StringTableRef = nil,
|
||||
options: set[ProcessOption] = {poStdErrToStdOut}):
|
||||
owned(Process) {.rtl, extern: "nosp$1", tags: [ExecIOEffect, ReadEnvEffect,
|
||||
RootEffect].}
|
||||
proc startProcess*(command: string, workingDir: string = "",
|
||||
args: openArray[string] = [], env: StringTableRef = nil,
|
||||
options: set[ProcessOption] = {poStdErrToStdOut}):
|
||||
owned(Process) {.rtl, extern: "nosp$1",
|
||||
tags: [ExecIOEffect, ReadEnvEffect, RootEffect].}
|
||||
## Starts a process. `Command` is the executable file, `workingDir` is the
|
||||
## process's working directory. If ``workingDir == ""`` the current directory
|
||||
## is used (default). `args` are the command line arguments that are passed to the
|
||||
|
|
@ -216,7 +209,7 @@ proc processID*(p: Process): int {.rtl, extern: "nosp$1".} =
|
|||
return p.id
|
||||
|
||||
proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
|
||||
extern: "nosp$1", tags: [].}
|
||||
extern: "nosp$1", tags: [].}
|
||||
## Waits for the process to finish and returns `p`'s error code.
|
||||
##
|
||||
## **WARNING**: Be careful when using `waitForExit` for processes created without
|
||||
|
|
@ -274,7 +267,7 @@ proc inputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
|
|||
result = p.inHandle
|
||||
|
||||
proc outputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
|
||||
tags: [].} =
|
||||
tags: [].} =
|
||||
## Returns ``p``'s output file handle for reading from.
|
||||
##
|
||||
## **WARNING**: The returned `FileHandle` should not be closed manually as
|
||||
|
|
@ -286,7 +279,7 @@ proc outputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
|
|||
result = p.outHandle
|
||||
|
||||
proc errorHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
|
||||
tags: [].} =
|
||||
tags: [].} =
|
||||
## Returns ``p``'s error file handle for reading from.
|
||||
##
|
||||
## **WARNING**: The returned `FileHandle` should not be closed manually as
|
||||
|
|
@ -303,12 +296,11 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
|
|||
result = cpuinfo.countProcessors()
|
||||
|
||||
proc execProcesses*(cmds: openArray[string],
|
||||
options = {poStdErrToStdOut, poParentStreams},
|
||||
n = countProcessors(),
|
||||
beforeRunEvent: proc(idx: int) = nil,
|
||||
afterRunEvent: proc(idx: int, p: Process) = nil): int
|
||||
{.rtl, extern: "nosp$1",
|
||||
tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect].} =
|
||||
options = {poStdErrToStdOut, poParentStreams}, n = countProcessors(),
|
||||
beforeRunEvent: proc(idx: int) = nil,
|
||||
afterRunEvent: proc(idx: int, p: Process) = nil):
|
||||
int {.rtl, extern: "nosp$1",
|
||||
tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect].} =
|
||||
## Executes the commands `cmds` in parallel.
|
||||
## Creates `n` processes that execute in parallel.
|
||||
##
|
||||
|
|
@ -413,20 +405,20 @@ proc execProcesses*(cmds: openArray[string],
|
|||
for i in 0..high(cmds):
|
||||
if beforeRunEvent != nil:
|
||||
beforeRunEvent(i)
|
||||
var p = startProcess(cmds[i], options=options + {poEvalCommand})
|
||||
var p = startProcess(cmds[i], options = options + {poEvalCommand})
|
||||
result = max(abs(waitForExit(p)), result)
|
||||
if afterRunEvent != nil: afterRunEvent(i, p)
|
||||
close(p)
|
||||
|
||||
when not defined(useNimRtl):
|
||||
proc execProcess(command: string,
|
||||
workingDir: string = "",
|
||||
args: openArray[string] = [],
|
||||
env: StringTableRef = nil,
|
||||
options: set[ProcessOption] = {poStdErrToStdOut,
|
||||
poUsePath,
|
||||
poEvalCommand}): TaintedString =
|
||||
var p = startProcess(command, workingDir=workingDir, args=args, env=env, options=options)
|
||||
proc execProcess(command: string, workingDir: string = "",
|
||||
args: openArray[string] = [], env: StringTableRef = nil,
|
||||
options: set[ProcessOption] = {poStdErrToStdOut, poUsePath,
|
||||
poEvalCommand}):
|
||||
TaintedString =
|
||||
|
||||
var p = startProcess(command, workingDir = workingDir, args = args,
|
||||
env = env, options = options)
|
||||
var outp = outputStream(p)
|
||||
result = TaintedString""
|
||||
var line = newStringOfCap(120).TaintedString
|
||||
|
|
@ -501,16 +493,14 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
#var
|
||||
# O_WRONLY {.importc: "_O_WRONLY", header: "<fcntl.h>".}: int
|
||||
# O_RDONLY {.importc: "_O_RDONLY", header: "<fcntl.h>".}: int
|
||||
proc myDup(h: Handle; inherit: WINBOOL=1): Handle =
|
||||
proc myDup(h: Handle; inherit: WINBOOL = 1): Handle =
|
||||
let thisProc = getCurrentProcess()
|
||||
if duplicateHandle(thisProc, h,
|
||||
thisProc, addr result,0,inherit,
|
||||
if duplicateHandle(thisProc, h, thisProc, addr result, 0, inherit,
|
||||
DUPLICATE_SAME_ACCESS) == 0:
|
||||
raiseOSError(osLastError())
|
||||
|
||||
proc createAllPipeHandles(si: var STARTUPINFO;
|
||||
stdin, stdout, stderr: var Handle;
|
||||
hash: int) =
|
||||
stdin, stdout, stderr: var Handle; hash: int) =
|
||||
var sa: SECURITY_ATTRIBUTES
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES).cint
|
||||
sa.lpSecurityDescriptor = nil
|
||||
|
|
@ -518,37 +508,37 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
let pipeOutName = newWideCString(r"\\.\pipe\stdout" & $hash)
|
||||
let pipeInName = newWideCString(r"\\.\pipe\stdin" & $hash)
|
||||
let pipeOut = createNamedPipe(pipeOutName,
|
||||
dwOpenMode=PIPE_ACCESS_INBOUND or FILE_FLAG_WRITE_THROUGH,
|
||||
dwPipeMode=PIPE_NOWAIT,
|
||||
nMaxInstances=1,
|
||||
nOutBufferSize=1024, nInBufferSize=1024,
|
||||
nDefaultTimeOut=0,addr sa)
|
||||
dwOpenMode = PIPE_ACCESS_INBOUND or FILE_FLAG_WRITE_THROUGH,
|
||||
dwPipeMode = PIPE_NOWAIT,
|
||||
nMaxInstances = 1,
|
||||
nOutBufferSize = 1024, nInBufferSize = 1024,
|
||||
nDefaultTimeOut = 0, addr sa)
|
||||
if pipeOut == INVALID_HANDLE_VALUE:
|
||||
raiseOSError(osLastError())
|
||||
let pipeIn = createNamedPipe(pipeInName,
|
||||
dwOpenMode=PIPE_ACCESS_OUTBOUND or FILE_FLAG_WRITE_THROUGH,
|
||||
dwPipeMode=PIPE_NOWAIT,
|
||||
nMaxInstances=1,
|
||||
nOutBufferSize=1024, nInBufferSize=1024,
|
||||
nDefaultTimeOut=0,addr sa)
|
||||
dwOpenMode = PIPE_ACCESS_OUTBOUND or FILE_FLAG_WRITE_THROUGH,
|
||||
dwPipeMode = PIPE_NOWAIT,
|
||||
nMaxInstances = 1,
|
||||
nOutBufferSize = 1024, nInBufferSize = 1024,
|
||||
nDefaultTimeOut = 0, addr sa)
|
||||
if pipeIn == INVALID_HANDLE_VALUE:
|
||||
raiseOSError(osLastError())
|
||||
|
||||
si.hStdOutput = createFileW(pipeOutName,
|
||||
FILE_WRITE_DATA or SYNCHRONIZE, 0, addr sa,
|
||||
OPEN_EXISTING, # very important flag!
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0 # no template file for OPEN_EXISTING
|
||||
)
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0 # no template file for OPEN_EXISTING
|
||||
)
|
||||
if si.hStdOutput == INVALID_HANDLE_VALUE:
|
||||
raiseOSError(osLastError())
|
||||
si.hStdError = myDup(si.hStdOutput)
|
||||
si.hStdInput = createFileW(pipeInName,
|
||||
FILE_READ_DATA or SYNCHRONIZE, 0, addr sa,
|
||||
OPEN_EXISTING, # very important flag!
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0 # no template file for OPEN_EXISTING
|
||||
)
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0 # no template file for OPEN_EXISTING
|
||||
)
|
||||
if si.hStdOutput == INVALID_HANDLE_VALUE:
|
||||
raiseOSError(osLastError())
|
||||
|
||||
|
|
@ -569,11 +559,10 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
proc fileClose(h: Handle) {.inline.} =
|
||||
if h > 4: discard closeHandle(h)
|
||||
|
||||
proc startProcess(command: string,
|
||||
workingDir: string = "",
|
||||
args: openArray[string] = [],
|
||||
env: StringTableRef = nil,
|
||||
options: set[ProcessOption] = {poStdErrToStdOut}): owned Process =
|
||||
proc startProcess(command: string, workingDir: string = "",
|
||||
args: openArray[string] = [], env: StringTableRef = nil,
|
||||
options: set[ProcessOption] = {poStdErrToStdOut}):
|
||||
owned Process =
|
||||
var
|
||||
si: STARTUPINFO
|
||||
procInfo: PROCESS_INFORMATION
|
||||
|
|
@ -789,7 +778,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
|
||||
proc hasData*(p: Process): bool =
|
||||
var x: int32
|
||||
if peekNamedPipe(p.outHandle, lpTotalBytesAvail=addr x):
|
||||
if peekNamedPipe(p.outHandle, lpTotalBytesAvail = addr x):
|
||||
result = x > 0
|
||||
|
||||
elif not defined(useNimRtl):
|
||||
|
|
@ -842,11 +831,10 @@ elif not defined(useNimRtl):
|
|||
tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], cdecl, gcsafe.}
|
||||
{.pop.}
|
||||
|
||||
proc startProcess(command: string,
|
||||
workingDir: string = "",
|
||||
args: openArray[string] = [],
|
||||
env: StringTableRef = nil,
|
||||
options: set[ProcessOption] = {poStdErrToStdOut}): owned Process =
|
||||
proc startProcess(command: string, workingDir: string = "",
|
||||
args: openArray[string] = [], env: StringTableRef = nil,
|
||||
options: set[ProcessOption] = {poStdErrToStdOut}):
|
||||
owned Process =
|
||||
var
|
||||
pStdin, pStdout, pStderr: array[0..1, cint]
|
||||
new(result)
|
||||
|
|
@ -1013,7 +1001,7 @@ elif not defined(useNimRtl):
|
|||
if sizeRead == sizeof(error):
|
||||
raiseOSError(osLastError(),
|
||||
"Could not find command: '$1'. OS error: $2" %
|
||||
[$data.sysCommand, $strerror(error)])
|
||||
[$data.sysCommand, $strerror(error)])
|
||||
|
||||
return pid
|
||||
|
||||
|
|
@ -1066,7 +1054,7 @@ elif not defined(useNimRtl):
|
|||
discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
|
||||
|
||||
startProcessFail(data)
|
||||
{.pop}
|
||||
{.pop.}
|
||||
|
||||
proc close(p: Process) =
|
||||
if poParentStreams notin p.options:
|
||||
|
|
@ -1401,7 +1389,7 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
|
|||
## .. code-block:: Nim
|
||||
## let (outp, errC) = execCmdEx("nim c -r mytestfile.nim")
|
||||
|
||||
var p = startProcess(command, options=options + {poEvalCommand})
|
||||
var p = startProcess(command, options = options + {poEvalCommand})
|
||||
var outp = outputStream(p)
|
||||
|
||||
# There is no way to provide input for the child process
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue