diff options
author | kitsunyan | 2018-04-20 00:08:22 +0000 |
---|---|---|
committer | kitsunyan | 2018-04-20 00:08:22 +0000 |
commit | 15a78acfc45556cf73264e1a20af1e0894d5aaf1 (patch) | |
tree | 62298e9123a2a25a226185387f936b0ec3897c43 | |
parent | edd51c66aa5667135bdb9b82b9ab9f4a6fe5ba6a (diff) |
Catch SIGINT and ask to remove build dependencies
-rw-r--r-- | src/feature/syncinstall.nim | 49 | ||||
-rw-r--r-- | src/main.nim | 4 | ||||
-rw-r--r-- | src/utils.nim | 21 |
3 files changed, 48 insertions, 26 deletions
diff --git a/src/feature/syncinstall.nim b/src/feature/syncinstall.nim index 03d1342..9d22574 100644 --- a/src/feature/syncinstall.nim +++ b/src/feature/syncinstall.nim @@ -299,7 +299,7 @@ proc editLoop(config: Config, base: string, repoPath: string, gitPath: Option[st editFileLoopAll(0) proc buildLoop(config: Config, pkgInfos: seq[PackageInfo], noconfirm: bool, - noextract: bool): (Option[BuildResult], int) = + noextract: bool): (Option[BuildResult], int, bool) = let base = pkgInfos[0].base let repoPath = repoPath(config.tmpRoot, base) let gitPath = pkgInfos[0].gitPath @@ -333,7 +333,7 @@ proc buildLoop(config: Config, pkgInfos: seq[PackageInfo], noconfirm: bool, if not workConfFileCopySuccess: printError(config.color, tr"failed to copy config file '$#'" % [confFile]) - (none(BuildResult), 1) + (none(BuildResult), 1, false) else: let envExt = getEnv("PKGEXT") let confExt = if envExt.len == 0: @@ -346,29 +346,32 @@ proc buildLoop(config: Config, pkgInfos: seq[PackageInfo], noconfirm: bool, else: envExt - let buildCode = forkWait(proc: int = - if chdir(buildPath) == 0: - discard cunsetenv("MAKEPKG_CONF") - dropPrivileges() + let (buildCode, interrupted) = catchInterrupt(): + forkWait(proc: int = + if chdir(buildPath) == 0: + discard cunsetenv("MAKEPKG_CONF") + dropPrivileges() - if not noextract: - removeDirQuiet(buildPath & "src") + if not noextract: + removeDirQuiet(buildPath & "src") - let optional: seq[tuple[arg: string, cond: bool]] = @[ - ("-e", noextract), - ("-m", not config.color) - ] + let optional: seq[tuple[arg: string, cond: bool]] = @[ + ("-e", noextract), + ("-m", not config.color) + ] - execResult(@[makepkgCmd, "--config", workConfFile, "-f"] & - optional.filter(o => o.cond).map(o => o.arg)) - else: - quit(1)) + execResult(@[makepkgCmd, "--config", workConfFile, "-f"] & + optional.filter(o => o.cond).map(o => o.arg)) + else: + quit(1)) discard unlink(workConfFile) - if buildCode != 0: + if interrupted: + (none(BuildResult), buildCode, interrupted) + elif buildCode != 0: printError(config.color, tr"failed to build '$#'" % [base]) - (none(BuildResult), buildCode) + (none(BuildResult), buildCode, false) else: let resultPkgInfos = reloadPkgInfos(config, buildPath, pkgInfos) @@ -392,7 +395,7 @@ proc buildLoop(config: Config, pkgInfos: seq[PackageInfo], noconfirm: bool, if failedNames.len > 0: for name in failedNames: printError(config.color, tr"$#: failed to extract package info" % [name]) - (none(BuildResult), 1) + (none(BuildResult), 1, false) else: let targetPkgInfos: seq[ReplacePkgInfo] = resultByIndices .map(i => (some(i.name), i.pkgInfo.get)) @@ -400,7 +403,7 @@ proc buildLoop(config: Config, pkgInfos: seq[PackageInfo], noconfirm: bool, let additionalPkgInfos: seq[ReplacePkgInfo] = resultPkgInfos .filter(i => not (i.name in filterNames)) .map(i => (none(string), i)) - (some(($confExt, targetPkgInfos & additionalPkgInfos)), 0) + (some(($confExt, targetPkgInfos & additionalPkgInfos)), 0, false) proc buildFromSources(config: Config, commonArgs: seq[Argument], pkgInfos: seq[PackageInfo], noconfirm: bool): (Option[BuildResult], int) = @@ -423,10 +426,12 @@ proc buildFromSources(config: Config, commonArgs: seq[Argument], if res == 'a': (none(BuildResult), 1) else: - let (buildResult, code) = buildLoop(config, pkgInfos, + let (buildResult, code, interrupted) = buildLoop(config, pkgInfos, noconfirm, noextract) - if code != 0: + if interrupted: + (buildResult, 1) + elif code != 0: proc ask(): char = let res = printColonUserChoice(config.color, tr"Build failed, retry?", ['y', 'e', 'n', '?'], 'n', '?', diff --git a/src/main.nim b/src/main.nim index 685b9d3..045b44e 100644 --- a/src/main.nim +++ b/src/main.nim @@ -193,11 +193,7 @@ proc handleVersion(): int = echo(' '.repeat(23), "Copyright (C) ", copyright) pacmanExec(false, false, ("V", none(string), ArgumentType.short)) -proc signal(sign: cint, handler: pointer): pointer - {.importc, header: "<signal.h>".} - discard setlocale(LC_ALL, "") -discard signal(SIGINT, cast[pointer](SIG_DFL)) template withErrorHandler(propColor: Option[bool], T: typedesc, body: untyped): tuple[success: Option[T], code: int] = diff --git a/src/utils.nim b/src/utils.nim index e67274f..7cbf184 100644 --- a/src/utils.nim +++ b/src/utils.nim @@ -277,6 +277,27 @@ proc dropPrivileges*() = discard cunsetenv("SUDO_GID") discard cunsetenv("PKEXEC_UID") +var intSigact: SigAction +intSigact.sa_handler = SIG_DFL +discard sigaction(SIGINT, intSigact) + +var wasInterrupted = false + +proc interruptHandler(signal: cint): void {.noconv.} = + wasInterrupted = true + +template catchInterrupt*(body: untyped): untyped = + block: + var intSigact: SigAction + var oldIntSigact: SigAction + intSigact.sa_handler = interruptHandler + discard sigaction(SIGINT, intSigact, oldIntSigact) + let data = body + let interrupted = wasInterrupted + wasInterrupted = false + discard sigaction(SIGINT, oldIntSigact) + (data, interrupted) + proc toString*[T](arr: array[T, char], length: Option[int]): string = var workLength = length.get(T.high + 1) var str = newStringOfCap(workLength) |