diff options
-rw-r--r-- | Makefile | 11 | ||||
-rw-r--r-- | lib/install.nim | 56 | ||||
-rw-r--r-- | src/config.nim | 8 | ||||
-rw-r--r-- | src/feature/syncinstall.nim | 32 | ||||
-rw-r--r-- | src/main.nim | 2 | ||||
-rw-r--r-- | src/pacman.nim | 40 | ||||
-rw-r--r-- | src/utils.nim | 11 |
7 files changed, 113 insertions, 47 deletions
@@ -10,6 +10,7 @@ TARGETS = \ completion/bash \ completion/zsh \ lib/bisect \ + lib/install \ src/pakku \ ${MAN_PAGES} @@ -117,6 +118,12 @@ lib/bisect: lib/bisect.nim --nimcache:"${NIM_CACHE_DIR}/bisect" \ -o:"$@" "$<" +lib/install: lib/install.nim + @echo "NIM: $@" + @nim c ${NIM_OPTIONS} \ + --nimcache:"${NIM_CACHE_DIR}/install" \ + -o:"$@" "$<" + src/pakku: src/main.nim $(shell find src -name \*.nim) @echo "NIM: $@" @nim c ${NIM_OPTIONS} \ @@ -147,6 +154,7 @@ install: $(call install,644,'doc/pakku.8','${MANDIR}/man8/pakku.8') $(call install,644,'doc/pakku.conf.5','${MANDIR}/man5/pakku.conf.5') $(call install,755,'lib/bisect','${PKGLIBDIR}/bisect') + $(call install,755,'lib/install','${PKGLIBDIR}/install') $(call install,755,'src/pakku','${BINDIR}/pakku') $(call install,644,'pakku.conf','${SYSCONFDIR}/pakku.conf') @@ -156,13 +164,14 @@ uninstall: $(call uninstall,'${MANDIR}/man8','pakku.8') $(call uninstall,'${MANDIR}/man5','pakku.conf.5') $(call uninstall,'${PKGLIBDIR}','bisect') + $(call uninstall,'${PKGLIBDIR}','install') $(call uninstall,'${BINDIR}','pakku') $(call uninstall,'${SYSCONFDIR}','pakku.conf') distcheck: @rm -rf 'pakku-${RVERSION}' @mkdir 'pakku-${RVERSION}' - @for f in ${DIST}; do cp --parents $$f 'pakku-${RVERSION}'; done + @for f in ${DIST}; do cp -d --parents $$f 'pakku-${RVERSION}'; done @sed -i 'pakku-${RVERSION}/Makefile' \ -e 's/^VERSION =.*/VERSION = ${RVERSION}/' \ diff --git a/lib/install.nim b/lib/install.nim new file mode 100644 index 0000000..cec9ca1 --- /dev/null +++ b/lib/install.nim @@ -0,0 +1,56 @@ +import future, os, posix, sequtils, strutils + +let params = commandLineParams() +let destination = params[0] +let paramsStart = 1 + +proc splitCommands(index: int, res: seq[seq[string]]): seq[seq[string]] = + if index < params.len: + let count = params[index].parseInt + let args = params[index + 1 .. index + count] + splitCommands(index + count + 1, res & args) + else: + res + +let commands = splitCommands(paramsStart, @[]) +let targets = lc[x | (y <- commands[1 .. ^1], x <- y), string] + +for file in targets: + try: + let index = file.rfind("/") + let name = if index >= 0: file[index + 1 .. ^1] else: file + copyFile(file, destination & "/" & name) + except: + discard + +proc perror*(s: cstring): void {.importc, header: "<stdio.h>".} +template perror*: void = perror(getAppFilename()) + +proc runCommand(params: seq[string]): int = + if params.len > 0: + let pid = fork() + if pid == 0: + let cexec = allocCStringArray(params) + let code = execvp(cexec[0], cexec) + perror() + deallocCStringArray(cexec) + quit(code) + else: + var status: cint = 1 + discard waitpid(pid, status, 0) + if WIFEXITED(status): + WEXITSTATUS(status) + else: + discard kill(getpid(), status) + 1 + else: + 0 + +proc buildParams(index: int, asArg: string): seq[string] = + if commands[index].len > 0: commands[0] & asArg & "--" & commands[index] else: @[] + +let asdepsCode = runCommand(buildParams(1, "--asdeps")) +if asdepsCode == 0: + programResult = runCommand(buildParams(2, "--asexplicit")) +else: + programResult = asdepsCode diff --git a/src/config.nim b/src/config.nim index ad57550..19dc0d6 100644 --- a/src/config.nim +++ b/src/config.nim @@ -21,12 +21,14 @@ type PacmanConfig* = object of CommonConfig rootOption*: Option[string] dbOption*: Option[string] + cacheOption*: Option[string] gpgOption*: Option[string] colorMode*: ColorMode Config* = object of CommonConfig root*: string db*: string + cache*: string tmpRootInitial*: string tmpRootCurrent*: string color*: bool @@ -105,12 +107,16 @@ proc db*(config: PacmanConfig): string = let workRoot = if root == "/": "" else: root workRoot & localStateDir & "/lib/pacman/" +proc cache*(config: PacmanConfig): string = + config.cacheOption.get(localStateDir & "/cache/pacman/pkg") + proc obtainConfig*(config: PacmanConfig): Config = let (configTable, _) = readConfigFile(sysConfDir & "/pakku.conf") let options = configTable.opt("options").map(t => t[]).get(initTable[string, string]()) let root = config.root let db = config.db + let cache = config.cache let color = config.colorMode.get proc obtainTmpDir(user: User): string = @@ -127,7 +133,7 @@ proc obtainConfig*(config: PacmanConfig): Config = let viewNoDefault = options.hasKey("ViewNoDefault") let preBuildCommand = options.opt("PreBuildCommand") - Config(root: root, db: db, + Config(root: root, db: db, cache: cache, tmpRootInitial: tmpRootInitial, tmpRootCurrent: tmpRootCurrent, color: color, dbs: config.dbs, arch: config.arch, debug: config.debug, progressBar: config.progressBar, verbosePkgList: config.verbosePkgList, pgpKeyserver: config.pgpKeyserver, diff --git a/src/feature/syncinstall.nim b/src/feature/syncinstall.nim index 2677570..1ee40c4 100644 --- a/src/feature/syncinstall.nim +++ b/src/feature/syncinstall.nim @@ -534,33 +534,23 @@ proc installGroupFromSources(config: Config, commonArgs: seq[Argument], handleTmpRoot(false) (newSeq[(string, string)](), 1) else: + let pacmanParams = pacmanCmd & pacmanParams(config.color, + commonArgs & ("U", none(string), ArgumentType.short)) let asdeps = install.filter(p => not (p.name in explicits)).map(p => p.file) let asexplicit = install.filter(p => p.name in explicits).map(p => p.file) - proc doInstall(files: seq[string], addArgs: seq[Argument]): int = - if files.len > 0: - pacmanRun(true, config.color, commonArgs & - ("U", none(string), ArgumentType.short) & addArgs & - files.map(f => (f, none(string), ArgumentType.target))) - else: - 0 + let installParams = sudoPrefix & (pkgLibDir & "/install") & config.cache & + $pacmanParams.len & pacmanParams & $asdeps.len & asdeps & $asexplicit.len & asexplicit - let asdepsCode = doInstall(asdeps, - @[("asdeps", none(string), ArgumentType.long)]) - if asdepsCode != 0: + let code = forkWait(() => execResult(installParams)) + if code != 0: handleTmpRoot(false) - (newSeq[(string, string)](), asdepsCode) + (newSeq[(string, string)](), code) else: - let asexplicitCode = doInstall(asexplicit, - @[("asexplicit", none(string), ArgumentType.long)]) - if asexplicitCode != 0: - handleTmpRoot(false) - (newSeq[(string, string)](), asexplicitCode) - else: - handleTmpRoot(true) - let installedAs = lc[(r.name.unsafeGet, r.pkgInfo.name) | (br <- buildResults, - r <- br.replacePkgInfos, r.name.isSome), (string, string)] - (installedAs, 0) + handleTmpRoot(true) + let installedAs = lc[(r.name.unsafeGet, r.pkgInfo.name) | (br <- buildResults, + r <- br.replacePkgInfos, r.name.isSome), (string, string)] + (installedAs, 0) proc deduplicatePkgInfos(pkgInfos: seq[PackageInfo], config: Config, printWarning: bool): seq[PackageInfo] = diff --git a/src/main.nim b/src/main.nim index 52f1cb8..10829b8 100644 --- a/src/main.nim +++ b/src/main.nim @@ -90,7 +90,7 @@ proc handleSync(args: seq[Argument], config: Config): int = let printMode = args.check(%%%"print") or args.check(%%%"print-format") if currentUser.uid != 0 and config.sudoExec and not printMode: - let collectedArgs = @[sudoCmd, getAppFilename()] & + let collectedArgs = sudoPrefix & getAppFilename() & lc[x | (y <- args, x <- y.collectArg), string] execResult(collectedArgs) else: diff --git a/src/pacman.nim b/src/pacman.nim index 8415de8..8b85590 100644 --- a/src/pacman.nim +++ b/src/pacman.nim @@ -277,29 +277,20 @@ proc checkConflicts*(args: seq[Argument], lc[(c.left, w) | (c <- conflicts, args.check(c.left.full), w <- c.right, args.check(w.full)), (string, string)].optFirst -proc checkExec(file: string): bool = - var statv: Stat - stat(file, statv) == 0 and (statv.st_mode and S_IXUSR) == S_IXUSR - -proc pacmanExec(root: bool, args: varargs[string]): int = - let exec = if root and checkExec(sudoCmd): - @[sudoCmd, pacmanCmd] & @args - elif root and checkExec(suCmd): - @[suCmd, "root", "-c", "exec \"$@\"", "--", "sh", pacmanCmd] & @args - else: - @[pacmanCmd] & @args +proc pacmanParams*(color: bool, args: varargs[Argument]): seq[string] = + let colorStr = if color: "always" else: "never" + let argsSeq = ("color", some(colorStr), ArgumentType.long) & + @args.filter(arg => not arg.matchOption(%%%"color")) + lc[x | (y <- argsSeq, x <- y.collectArg), string] +proc pacmanExecInternal(root: bool, params: varargs[string]): int = + let exec = if root: sudoPrefix & pacmanCmd & @params else: pacmanCmd & @params execResult(exec) proc pacmanExec*(root: bool, color: bool, args: varargs[Argument]): int = let useRoot = root and getuid() != 0 - let colorStr = if color: "always" else: "never" - - let argsSeq = ("color", some(colorStr), ArgumentType.long) & - @args.filter(arg => not arg.matchOption(%%%"color")) - let collectedArgs = lc[x | (y <- argsSeq, x <- y.collectArg), string] - - pacmanExec(useRoot, collectedArgs) + let params = pacmanParams(color, args) + pacmanExecInternal(useRoot, params) proc pacmanRun*(root: bool, color: bool, args: varargs[Argument]): int = let argsSeq = @args @@ -308,7 +299,7 @@ proc pacmanRun*(root: bool, color: bool, args: varargs[Argument]): int = proc pacmanValidateAndThrow(args: varargs[Argument]): void = let argsSeq = @args let collectedArgs = lc[x | (y <- argsSeq, x <- y.collectArg), string] - let code = forkWait(() => pacmanExec(false, "-T" & collectedArgs)) + let code = forkWait(() => pacmanExecInternal(false, "-T" & collectedArgs)) if code != 0: raise haltError(code) @@ -320,6 +311,7 @@ proc getMachineName: Option[string] = proc createConfigFromTable(table: Table[string, string], dbs: seq[string]): PacmanConfig = let root = table.opt("RootDir") let db = table.opt("DBPath") + let cache = table.opt("CacheDir") let gpg = table.opt("GPGDir") let color = if table.hasKey("Color"): ColorMode.colorAuto else: ColorMode.colorNever let verbosePkgList = table.hasKey("VerbosePkgLists") @@ -332,9 +324,10 @@ proc createConfigFromTable(table: Table[string, string], dbs: seq[string]): Pacm raise commandError(tr"can not get the architecture", colorNeeded = some(color.get)) - PacmanConfig(rootOption: root, dbOption: db, gpgOption: gpg, dbs: dbs, arch: archFinal, - colorMode: color, debug: false, progressBar: true, verbosePkgList: verbosePkgList, - pgpKeyserver: none(string), ignorePkgs: ignorePkgs, ignoreGroups: ignoreGroups) + PacmanConfig(rootOption: root, dbOption: db, cacheOption: cache, gpgOption: gpg, + dbs: dbs, arch: archFinal, colorMode: color, debug: false, progressBar: true, + verbosePkgList: verbosePkgList, pgpKeyserver: none(string), + ignorePkgs: ignorePkgs, ignoreGroups: ignoreGroups) proc obtainPacmanConfig*(args: seq[Argument]): PacmanConfig = proc getAll(pair: OptionPair): seq[string] = @@ -356,6 +349,7 @@ proc obtainPacmanConfig*(args: seq[Argument]): PacmanConfig = let root = getAll(%%%"root").optLast.orElse(defaultConfig.rootOption) let db = getAll(%%%"dbpath").optLast.orElse(defaultConfig.dbOption) + let cache = getAll(%%%"cachedir").optLast.orElse(defaultConfig.cacheOption) let gpg = getAll(%%%"gpgdir").optLast.orElse(defaultConfig.gpgOption) let arch = getAll(%%%"arch").optLast.get(defaultConfig.arch) let colorStr = getAll(%%%"color").optLast.get($defaultConfig.colorMode) @@ -398,7 +392,7 @@ proc obtainPacmanConfig*(args: seq[Argument]): PacmanConfig = file.close() pgpKeyserver) - let config = PacmanConfig(rootOption: root, dbOption: db, gpgOption: gpg, + let config = PacmanConfig(rootOption: root, dbOption: db, cacheOption: cache, gpgOption: gpg, dbs: defaultConfig.dbs, arch: arch, colorMode: color, debug: debug, progressBar: progressBar, verbosePkgList: defaultConfig.verbosePkgList, pgpKeyserver: pgpKeyserver, ignorePkgs: ignorePkgs + defaultConfig.ignorePkgs, diff --git a/src/utils.nim b/src/utils.nim index b480ce9..7dcf620 100644 --- a/src/utils.nim +++ b/src/utils.nim @@ -285,6 +285,17 @@ proc dropPrivileges*(): bool = else: return true +proc checkExec(file: string): bool = + var statv: Stat + stat(file, statv) == 0 and (statv.st_mode and S_IXUSR) == S_IXUSR + +let sudoPrefix*: seq[string] = if checkExec(sudoCmd): + @[sudoCmd] + elif checkExec(suCmd): + @[suCmd, "root", "-c", "exec \"$@\"", "--", "sh"] + else: + @[] + var intSigact: SigAction intSigact.sa_handler = SIG_DFL discard sigaction(SIGINT, intSigact) |