diff options
-rw-r--r-- | lib/install.nim | 66 | ||||
-rw-r--r-- | src/feature/syncinstall.nim | 32 |
2 files changed, 76 insertions, 22 deletions
diff --git a/lib/install.nim b/lib/install.nim index 9539a62..03bebd5 100644 --- a/lib/install.nim +++ b/lib/install.nim @@ -1,4 +1,4 @@ -import future, os, posix, strutils +import future, os, posix, sequtils, strutils proc splitCommands(params: seq[string], index: int, res: seq[seq[string]]): seq[seq[string]] = if index < params.len: @@ -11,10 +11,15 @@ proc splitCommands(params: seq[string], index: int, res: seq[seq[string]]): seq[ proc perror*(s: cstring): void {.importc, header: "<stdio.h>".} template perror*: void = perror(paramStr(0)) -proc runCommand(params: seq[string]): int = +proc runCommand(params: seq[string], inputOutput: bool): int = if params.len > 0: let pid = fork() if pid == 0: + if not inputOutput: + discard close(0) + discard close(1) + discard open("/dev/null") + discard open("/dev/null") let cexec = allocCStringArray(params) let code = execvp(cexec[0], cexec) perror() @@ -31,31 +36,58 @@ proc runCommand(params: seq[string]): int = else: 0 -proc buildParams(commands: seq[seq[string]], index: int, asArg: string): seq[string] = - if commands[index].len > 0: commands[0] & asArg & "--" & commands[index] else: @[] +proc take(params: seq[string], start: int, count: int): (seq[string], int) = + let res = params[start .. start + count - 1] + (res, start + count) proc handleInstall*(params: seq[string]): int = - let destination = params[0] - let uid = params[1].parseInt - let gid = params[2].parseInt - let paramsStart = 3 + let (head, headIndex) = params.take(0, 3) + let destination = head[0] + let uid = head[1].parseInt + let gid = head[2].parseInt - let commands = splitCommands(params, paramsStart, @[]) - let targets = lc[x | (y <- commands[1 .. ^1], x <- y), string] + let (upgradeCommand, upgradeIndex) = params + .take(headIndex + 1, params[headIndex].parseInt) + let (databaseCommand, databaseIndex) = params + .take(upgradeIndex + 1, params[upgradeIndex].parseInt) + + let packages = params[databaseIndex .. ^1] + if packages.len /% 3 * 3 != packages.len: + raise newException(SystemError, "invalid arguments") + + let install: seq[tuple[name: string, file: string, mode: string]] = packages + .distribute(packages.len /% 3) + .map(l => (l[0], l[1], l[2])) if uid >= 0 and gid >= 0: - for file in targets: + for pkg in install: try: - let index = file.rfind("/") - let name = if index >= 0: file[index + 1 .. ^1] else: file + let index = pkg.file.rfind("/") + let name = if index >= 0: pkg.file[index + 1 .. ^1] else: pkg.file let dest = destination & "/" & name - copyFile(file, dest) + copyFile(pkg.file, dest) discard chown(dest, (Uid) uid, (Gid) gid) except: discard - let asdepsCode = runCommand(commands.buildParams(1, "--asdeps")) - if asdepsCode == 0: - runCommand(commands.buildParams(2, "--asexplicit")) + let asexplicit = install.filter(p => p.mode == "explicit").map(p => p.name) + let asdeps = install.filter(p => p.mode == "dependency").map(p => p.name) + + let installCode = runCommand(upgradeCommand & "--" & install.map(p => p.file), true) + + let asexplicitCode = if asexplicit.len > 0: + runCommand(databaseCommand & "--asexplicit" & "--" & asexplicit, false) + else: + 0 + + let asdepsCode = if asdeps.len > 0: + runCommand(databaseCommand & "--asdeps" & "--" & asdeps, false) + else: + 0 + + if installCode != 0: + installCode + elif asexplicitCode != 0: + asexplicitCode else: asdepsCode diff --git a/src/feature/syncinstall.nim b/src/feature/syncinstall.nim index 137d095..1fc2b6c 100644 --- a/src/feature/syncinstall.nim +++ b/src/feature/syncinstall.nim @@ -582,10 +582,24 @@ 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) + let installWithReason = withAlpmConfig(config, false, handle, dbs, errors): + let local = handle.local + install.map(proc (pkg: auto): tuple[name: string, file: string, mode: string] = + let explicit = pkg.name in explicits + let package = local[pkg.name] + let mode = if package != nil: (block: + let installedExplicitly = package.reason == AlpmReason.explicit + if explicit == installedExplicitly: + "auto" + elif explicit: + "explicit" + else: + "dependency") + elif explicit: + "auto" + else: + "dependency" + (pkg.name, pkg.file, mode)) let (cacheDir, cacheUser, cacheGroup) = if config.preserveBuilt == PreserveBuilt.internal: (config.cache, 0, 0) @@ -599,9 +613,17 @@ proc installGroupFromSources(config: Config, commonArgs: seq[Argument], # pass -1 values to disable caching ("", -1, -1) + let pacmanUpgradeParams = pacmanCmd & pacmanParams(config.color, + commonArgs & ("U", none(string), ArgumentType.short)) + + let pacmanDatabaseParams = pacmanCmd & pacmanParams(config.color, + commonArgs.keepOnlyOptions(commonOptions) & ("D", none(string), ArgumentType.short)) + let installParams = sudoPrefix & (pkgLibDir & "/install") & cacheDir & $cacheUser & $cacheGroup & - $pacmanParams.len & pacmanParams & $asdeps.len & asdeps & $asexplicit.len & asexplicit + $pacmanUpgradeParams.len & pacmanUpgradeParams & + $pacmanDatabaseParams.len & pacmanDatabaseParams & + lc[x | (i <- installWithReason, x <- [i.name, i.file, i.mode]), string] let code = forkWait(() => execResult(installParams)) if code != 0: |