aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkitsunyan2018-06-10 03:46:10 +0000
committerkitsunyan2018-06-10 03:46:10 +0000
commit3faa7e763c9fbc93edca6aece732dfd2674fdc50 (patch)
tree00145bcb0c52ff904f8a3bd414b6c73b2742a07c
parent4e6a207ce3d764f73ce3294723c263e38d9b68d3 (diff)
Handle dependencies/explicits using "pacman -D" instead of two "pacman -S" calls
-rw-r--r--lib/install.nim66
-rw-r--r--src/feature/syncinstall.nim32
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: