diff options
-rw-r--r-- | src/common.nim | 59 | ||||
-rw-r--r-- | src/feature/localquery.nim | 61 | ||||
-rw-r--r-- | src/feature/syncinstall.nim | 62 |
3 files changed, 113 insertions, 69 deletions
diff --git a/src/common.nim b/src/common.nim index b35d4f9..045f1f6 100644 --- a/src/common.nim +++ b/src/common.nim @@ -143,6 +143,65 @@ proc mapAurTargets*[T: RpcPackageInfo](targets: seq[SyncPackageTarget], FullPackageTarget[T](name: target.name, repo: target.repo, foundInfo: target.foundInfo, pkgInfo: none(T))) +proc queryUnrequired*(handle: ptr AlpmHandle, withOptional: bool, withoutOptional: bool, + assumeExplicit: seq[string]): (HashSet[string], HashSet[string], HashSet[string]) = + let (explicit, dependsTable, alternatives) = block: + var explicit = newSeq[string]() + var dependsTable = initTable[string, + HashSet[tuple[reference: PackageReference, optional: bool]]]() + var alternatives = initTable[string, HashSet[PackageReference]]() + + for pkg in handle.local.packages: + proc fixProvides(reference: PackageReference): PackageReference = + if reference.constraint.isNone: + (reference.name, reference.description, + some((ConstraintOperation.eq, $pkg.version))) + else: + reference + + let depends = toSeq(pkg.depends.items) + .map(d => d.toPackageReference).toSet + let optional = toSeq(pkg.optional.items) + .map(d => d.toPackageReference).toSet + let provides = toSeq(pkg.provides.items) + .map(d => d.toPackageReference).map(fixProvides).toSet + + if pkg.reason == AlpmReason.explicit: + explicit &= $pkg.name + dependsTable.add($pkg.name, + depends.map(x => (x, false)) + optional.map(x => (x, true))) + if provides.len > 0: + alternatives.add($pkg.name, provides) + + (explicit.toSet + assumeExplicit.toSet, dependsTable, alternatives) + + let providedBy = lc[(y, x.key) | (x <- alternatives.namedPairs, y <- x.value), + tuple[reference: PackageReference, name: string]] + + proc findRequired(withOptional: bool, results: HashSet[string], + check: HashSet[string]): HashSet[string] = + let full = results + check + + let direct = lc[x.reference | (y <- dependsTable.namedPairs, y.key in check, + x <- y.value, withOptional or not x.optional), PackageReference] + + let indirect = lc[x.name | (y <- direct, x <- providedBy, + y.isProvidedBy(x.reference)), string].toSet + + let checkNext = (direct.map(p => p.name).toSet + indirect) - full + if checkNext.len > 0: findRequired(withOptional, full, checkNext) else: full + + let installed = toSeq(dependsTable.keys).toSet + + proc findOrphans(withOptional: bool): HashSet[string] = + let required = findRequired(withOptional, initSet[string](), explicit) + installed - required + + let withOptionalSet = if withOptional: findOrphans(true) else: initSet[string]() + let withoutOptionalSet = if withoutOptional: findOrphans(false) else: initSet[string]() + + (installed, withOptionalSet, withoutOptionalSet) + proc formatArgument*(target: PackageTarget): string = target.repo.map(r => r & "/" & target.name).get(target.name) diff --git a/src/feature/localquery.nim b/src/feature/localquery.nim index 9dfaa05..d2beaa5 100644 --- a/src/feature/localquery.nim +++ b/src/feature/localquery.nim @@ -1,69 +1,18 @@ import algorithm, future, options, sequtils, sets, strutils, tables, - "../args", "../config", "../format", "../package", "../pacman", "../utils", + "../args", "../common", "../config", "../format", "../package", "../pacman", "../utils", "../wrapper/alpm" proc handleQueryOrphans*(args: seq[Argument], config: Config): int = - type Package = tuple[name: string, explicit: bool] - - let (installed, alternatives) = withAlpm(config.root, config.db, - newSeq[string](), config.arch, handle, dbs, errors): + let (installed, orphans, _) = withAlpm(config.root, config.db, newSeq[string](), + config.arch, handle, dbs, errors): for e in errors: printError(config.color, e) - - var installed = initTable[Package, HashSet[PackageReference]]() - var alternatives = initTable[string, HashSet[PackageReference]]() - - for pkg in handle.local.packages: - proc fixProvides(reference: PackageReference): PackageReference = - if reference.constraint.isNone: - (reference.name, reference.description, - some((ConstraintOperation.eq, $pkg.version))) - else: - reference - - let depends = toSeq(pkg.depends.items) - .map(d => d.toPackageReference).toSet - let optional = toSeq(pkg.optional.items) - .map(d => d.toPackageReference).toSet - let provides = toSeq(pkg.provides.items) - .map(d => d.toPackageReference).map(fixProvides).toSet - - installed.add(($pkg.name, pkg.reason == AlpmReason.explicit), - depends + optional) - if provides.len > 0: - alternatives.add($pkg.name, provides) - - (installed, alternatives) - - let providedBy = lc[(y, x.key) | (x <- alternatives.namedPairs, y <- x.value), - tuple[reference: PackageReference, name: string]] - - let installedSeq = lc[x | (x <- installed.pairs), - tuple[package: Package, dependencies: HashSet[PackageReference]]] - let explicit = installedSeq - .filter(t => t.package.explicit) - .map(t => t.package.name) - .toSet - - proc findRequired(results: HashSet[string], check: HashSet[string]): HashSet[string] = - let full = results + check - - let direct = lc[x | (y <- installedSeq, y.package.name in check, - x <- y.dependencies), PackageReference] - - let indirect = lc[x.name | (y <- direct, x <- providedBy, - y.isProvidedBy(x.reference)), string].toSet - - let checkNext = (direct.map(p => p.name).toSet + indirect) - full - if checkNext.len > 0: findRequired(full, checkNext) else: full - - let required = findRequired(initSet[string](), explicit) - let orphans = installedSeq.map(t => t.package.name).toSet - required + queryUnrequired(handle, true, false, @[]) let targets = args.targets.map(t => (if t[0 .. 5] == "local/": t[6 .. ^1] else: t)) # Provide similar output for not installed packages - let unknownTargets = targets.toSet - toSeq(installed.keys).map(p => p.name).toSet + let unknownTargets = targets.toSet - installed let results = if targets.len > 0: targets.filter(t => t in orphans or t in unknownTargets) else: diff --git a/src/feature/syncinstall.nim b/src/feature/syncinstall.nim index b393332..c7f9fbc 100644 --- a/src/feature/syncinstall.nim +++ b/src/feature/syncinstall.nim @@ -494,11 +494,13 @@ proc installGroupFromSources(config: Config, commonArgs: seq[Argument], proc handleInstall(args: seq[Argument], config: Config, upgradeCount: int, noconfirm: bool, explicits: HashSet[string], installed: seq[Installed], satisfied: Table[PackageReference, SatisfyResult], unsatisfied: seq[PackageReference], - directPacmanTargets: seq[string], additionalPacmanTargets: seq[string], - basePackages: seq[seq[seq[PackageInfo]]]): int = - let (directCode, directSome) = if directPacmanTargets.len > 0 or upgradeCount > 0: + targetNames: seq[string], build: bool, directPacmanTargets: seq[string], + additionalPacmanTargets: seq[string], basePackages: seq[seq[seq[PackageInfo]]]): int = + let workDirectPacmanTargets = if build: @[] else: directPacmanTargets + + let (directCode, directSome) = if workDirectPacmanTargets.len > 0 or upgradeCount > 0: (pacmanRun(true, config.color, args.filter(arg => not arg.isTarget) & - directPacmanTargets.map(t => (t, none(string), ArgumentType.target))), true) + workDirectPacmanTargets.map(t => (t, none(string), ArgumentType.target))), true) else: (0, false) @@ -652,6 +654,10 @@ proc handleInstall(args: seq[Argument], config: Config, upgradeCount: int, removeTmp() confirmAndCloneCode else: + let (_, initialUnrequired, initialUnrequiredWithoutOptional) = withAlpm(config.root, + config.db, newSeq[string](), config.arch, handle, dbs, errors): + queryUnrequired(handle, true, true, targetNames) + let (additionalCode, additionalSome) = if additionalPacmanTargets.len > 0: (block: printColon(config.color, tr"Installing build dependencies...") @@ -702,7 +708,40 @@ proc handleInstall(args: seq[Argument], config: Config, upgradeCount: int, if code != 0 and index < basePackages.len - 1: printWarning(config.color, tr"installation aborted") removeTmp() - code + + let (_, finalUnrequired, finalUnrequiredWithoutOptional) = withAlpm(config.root, + config.db, newSeq[string](), config.arch, handle, dbs, errors): + queryUnrequired(handle, true, true, targetNames) + + let unrequired = finalUnrequired - initialUnrequired + let unrequiredOptional = finalUnrequiredWithoutOptional - + initialUnrequiredWithoutOptional - unrequired + + let removeCode = if unrequired.len > 0 or unrequiredOptional.len > 0: (block: + let code = if unrequired.len > 0: (block: + printColon(config.color, tr"Removing build dependencies...") + pacmanRun(true, config.color, commonArgs & + ("R", none(string), ArgumentType.short) & + toSeq(unrequired.items).map(t => + (t, none(string), ArgumentType.target)))) + else: + 0 + + if code == 0 and unrequiredOptional.len > 0: + printColon(config.color, tr"Removing optional build dependencies...") + pacmanRun(true, config.color, commonArgs & + ("R", none(string), ArgumentType.short) & + toSeq(unrequiredOptional.items).map(t => + (t, none(string), ArgumentType.target))) + else: + code) + else: + 0 + + if removeCode != 0: + removeCode + else: + code elif not directSome and not additionalSome: echo(trp(" there is nothing to do\n")) 0 @@ -985,13 +1024,10 @@ proc handleSyncInstall*(args: seq[Argument], config: Config): int = satisfied, unsatisfied, directPacmanTargets, additionalPacmanTargets, orderedPkgInfos) else: - let explicits = if not args.check((none(string), "asdeps")): - targets.map(t => t.name) - else: - @[] - - let passDirectPacmanTargets = if build: @[] else: directPacmanTargets + let targetNames = targets.map(t => t.name) + let explicits = if not args.check((none(string), "asdeps")): targetNames else: @[] handleInstall(pacmanArgs, config, upgradeCount, noconfirm, - explicits.toSet, installed, satisfied, unsatisfied, passDirectPacmanTargets, - additionalPacmanTargets, orderedPkgInfos) + explicits.toSet, installed, satisfied, unsatisfied, + targetNames, build, directPacmanTargets, additionalPacmanTargets, + orderedPkgInfos) |