aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkitsunyan2018-04-22 22:47:55 +0000
committerkitsunyan2018-04-22 22:47:55 +0000
commita1a5e345daaeae0fae1da58e3683041d48e2583a (patch)
tree67349123a37b8459a405954cc6ca0548662d8467
parent276d8b9b1dd15f3c6fdf6c44f2bab35713a98b74 (diff)
Add support for version constraints for targets
-rw-r--r--src/common.nim68
-rw-r--r--src/feature/syncinfo.nim6
-rw-r--r--src/feature/syncinstall.nim81
-rw-r--r--src/package.nim44
4 files changed, 105 insertions, 94 deletions
diff --git a/src/common.nim b/src/common.nim
index d1c4daa..9288d64 100644
--- a/src/common.nim
+++ b/src/common.nim
@@ -16,7 +16,7 @@ type
]
PackageTarget* = object of RootObj
- name*: string
+ reference*: PackageReference
repo*: Option[string]
SyncPackageTarget* = object of PackageTarget
@@ -52,12 +52,14 @@ proc checkAndRefresh*(color: bool, args: seq[Argument]): tuple[code: int, args:
(0, args)
proc packageTargets*(args: seq[Argument]): seq[PackageTarget] =
- args.targets.map(proc (target: string): PackageTarget =
+ args.targets.map(target => (block:
let splitTarget = target.split('/', 2)
- if splitTarget.len == 2:
- PackageTarget(name: splitTarget[1], repo: some(splitTarget[0]))
- else:
- PackageTarget(name: target, repo: none(string)))
+ let (repo, nameConstraint) = if splitTarget.len == 2:
+ (some(splitTarget[0]), splitTarget[1])
+ else:
+ (none(string), target)
+ let reference = parsePackageReference(nameConstraint, false)
+ PackageTarget(reference: reference, repo: repo)))
proc isAurTargetSync*(target: SyncPackageTarget): bool =
target.foundInfo.isNone and (target.repo.isNone or target.repo == some("aur"))
@@ -70,10 +72,10 @@ proc findSyncTargets*(handle: ptr AlpmHandle, dbs: seq[ptr AlpmDatabase],
(seq[SyncPackageTarget], seq[string]) =
let dbTable = dbs.map(d => ($d.name, d)).toTable
- proc checkProvided(name: string, db: ptr AlpmDatabase): bool =
+ proc checkProvided(reference: PackageReference, db: ptr AlpmDatabase): bool =
for pkg in db.packages:
for provides in pkg.provides:
- if $provides.name == name:
+ if reference.isProvidedBy(provides.toPackageReference):
return true
return false
@@ -83,12 +85,12 @@ proc findSyncTargets*(handle: ptr AlpmHandle, dbs: seq[ptr AlpmDatabase],
if dbTable.hasKey(repo):
let db = dbTable[repo]
- let pkg = db[target.name]
+ let pkg = db[target.reference.name]
- if pkg != nil:
- let base = if pkg.base == nil: target.name else: $pkg.base
+ if pkg != nil and target.reference.isProvidedBy(pkg.toPackageReference):
+ let base = if pkg.base == nil: target.reference.name else: $pkg.base
return some((repo, some((base, $pkg.version, some($pkg.arch)))))
- elif checkProvides and target.name.checkProvided(db):
+ elif checkProvides and target.reference.checkProvided(db):
return some((repo, none(SyncFoundPackageInfo)))
else:
return none(SyncFoundInfo)
@@ -97,9 +99,9 @@ proc findSyncTargets*(handle: ptr AlpmHandle, dbs: seq[ptr AlpmDatabase],
else:
let directResult = dbs
.map(db => (block:
- let pkg = db[target.name]
- if pkg != nil:
- let base = if pkg.base == nil: target.name else: $pkg.base
+ let pkg = db[target.reference.name]
+ if pkg != nil and target.reference.isProvidedBy(pkg.toPackageReference):
+ let base = if pkg.base == nil: target.reference.name else: $pkg.base
some(($db.name, some((base, $pkg.version, some($pkg.arch)))))
else:
none(SyncFoundInfo)))
@@ -110,37 +112,45 @@ proc findSyncTargets*(handle: ptr AlpmHandle, dbs: seq[ptr AlpmDatabase],
if directResult.isSome:
return directResult
else:
- if allowGroups:
- let groupRepo = lc[d | (d <- dbs, g <- d.groups, $g.name == target.name),
- ptr AlpmDatabase].optFirst
+ if allowGroups and target.reference.constraint.isNone:
+ let groupRepo = lc[d | (d <- dbs, g <- d.groups,
+ $g.name == target.reference.name), ptr AlpmDatabase].optFirst
if groupRepo.isSome:
return groupRepo.map(d => ($d.name, none(SyncFoundPackageInfo)))
if checkProvides:
for db in dbs:
- if target.name.checkProvided(db):
+ if target.reference.checkProvided(db):
return some(($db.name, none(SyncFoundPackageInfo)))
return none(SyncFoundInfo)
else:
return none(SyncFoundInfo)
- let syncTargets = targets.map(t => SyncPackageTarget(name: t.name,
+ let syncTargets = targets.map(t => SyncPackageTarget(reference: t.reference,
repo: t.repo, foundInfo: findSync(t)))
- let checkAur = syncTargets.filter(isAurTargetSync).map(t => t.name)
- (syncTargets, checkAur)
+ let checkAurNames = syncTargets.filter(isAurTargetSync).map(t => t.reference.name)
+ (syncTargets, checkAurNames)
proc mapAurTargets*[T: RpcPackageInfo](targets: seq[SyncPackageTarget],
pkgInfos: seq[T]): seq[FullPackageTarget[T]] =
let aurTable = pkgInfos.map(i => (i.name, i)).toTable
targets.map(proc (target: SyncPackageTarget): FullPackageTarget[T] =
- if target.foundInfo.isNone and aurTable.hasKey(target.name):
- let pkgInfo = aurTable[target.name]
- let syncInfo = ("aur", some((pkgInfo.base, pkgInfo.version, none(string))))
- FullPackageTarget[T](name: target.name, repo: target.repo,
+ let res = if target.foundInfo.isNone and aurTable.hasKey(target.reference.name): (block:
+ let pkgInfo = aurTable[target.reference.name]
+ if target.reference.isProvidedBy(pkgInfo.toPackageReference):
+ some((("aur", some((pkgInfo.base, pkgInfo.version, none(string)))), pkgInfo))
+ else:
+ none((SyncFoundInfo, T)))
+ else:
+ none((SyncFoundInfo, T))
+
+ if res.isSome:
+ let (syncInfo, pkgInfo) = res.get
+ FullPackageTarget[T](reference: target.reference, repo: target.repo,
foundInfo: some(syncInfo), pkgInfo: some(pkgInfo))
else:
- FullPackageTarget[T](name: target.name, repo: target.repo,
+ FullPackageTarget[T](reference: target.reference, repo: target.repo,
foundInfo: target.foundInfo, pkgInfo: none(T)))
proc queryUnrequired*(handle: ptr AlpmHandle, withOptional: bool, withoutOptional: bool,
@@ -203,7 +213,7 @@ proc queryUnrequired*(handle: ptr AlpmHandle, withOptional: bool, withoutOptiona
(installed, withOptionalSet, withoutOptionalSet)
proc formatArgument*(target: PackageTarget): string =
- target.repo.map(r => r & "/" & target.name).get(target.name)
+ target.repo.map(r => r & "/" & $target.reference).get($target.reference)
proc ensureTmpOrError*(config: Config): Option[string] =
let tmpRootExists = try:
@@ -408,7 +418,7 @@ proc obtainBuildPkgInfos*[T: RpcPackageInfo](config: Config,
(pkg.base, pkg.version, pkg.arch.get, info.repo))
.deduplicate
- let pacmanTargetNames = pacmanTargets.map(t => t.name)
+ let pacmanTargetNames = pacmanTargets.map(t => t.reference.name)
obtainBuildPkgInfosInternal(config, bases, pacmanTargetNames)
proc cloneRepo*(config: Config, basePackages: seq[PackageInfo]): (int, Option[string]) =
diff --git a/src/feature/syncinfo.nim b/src/feature/syncinfo.nim
index 5ff6b38..d00dcc0 100644
--- a/src/feature/syncinfo.nim
+++ b/src/feature/syncinfo.nim
@@ -100,13 +100,13 @@ proc handleSyncInfo*(args: seq[Argument], config: Config): int =
let (_, callArgs) = checkAndRefresh(config.color, args)
let targets = args.packageTargets
- let (syncTargets, checkAur) = withAlpm(config.root, config.db,
+ let (syncTargets, checkAurNames) = withAlpm(config.root, config.db,
config.dbs, config.arch, handle, dbs, errors):
for e in errors: printError(config.color, e)
findSyncTargets(handle, dbs, targets, false, false)
- let (pkgInfos, aerrors) = getAurPackageInfo(checkAur, none(seq[RpcPackageInfo]),
- config.arch, proc (a: int, b: int) = discard)
+ let (pkgInfos, aerrors) = getAurPackageInfo(checkAurNames,
+ none(seq[RpcPackageInfo]), config.arch, proc (a: int, b: int) = discard)
for e in aerrors: printError(config.color, e)
let fullTargets = mapAurTargets[PackageInfo](syncTargets, pkgInfos)
diff --git a/src/feature/syncinstall.nim b/src/feature/syncinstall.nim
index ecb9f18..163bf34 100644
--- a/src/feature/syncinstall.nim
+++ b/src/feature/syncinstall.nim
@@ -206,26 +206,26 @@ proc findDependencies(config: Config, handle: ptr AlpmHandle,
let unsatisfied = lc[x | (i <- pkgInfos, x <- i.allDepends), PackageReference].deduplicate
findDependencies(config, handle, dbs, satisfied, unsatisfied, @[], printMode, noaur)
-proc filterNotFoundSyncTargets[T: RpcPackageInfo](syncTargets: seq[SyncPackageTarget],
- pkgInfos: seq[T], upToDateNeededNames: HashSet[string]):
- (Table[string, T], seq[SyncPackageTarget]) =
- let rpcInfoTable = pkgInfos.map(d => (d.name, d)).toTable
-
- proc notFoundOrFoundInAur(target: SyncPackageTarget): bool =
- not (target.name in upToDateNeededNames) and target.foundInfo.isNone and
- not (target.isAurTargetSync and rpcInfoTable.hasKey(target.name))
-
+proc filterNotFoundSyncTargetsInternal(syncTargets: seq[SyncPackageTarget],
+ pkgInfoReferencesTable: Table[string, PackageReference],
+ upToDateNeededTable: Table[string, PackageReference]): seq[SyncPackageTarget] =
# collect packages which were found neither in sync DB nor in AUR
- let notFoundTargets = syncTargets.filter(notFoundOrFoundInAur)
+ syncTargets.filter(t => not (upToDateNeededTable.opt(t.reference.name)
+ .map(r => t.reference.isProvidedBy(r)).get(false)) and t.foundInfo.isNone and
+ not (t.isAurTargetSync and pkgInfoReferencesTable.opt(t.reference.name)
+ .map(r => t.reference.isProvidedBy(r)).get(false)))
- (rpcInfoTable, notFoundTargets)
+proc filterNotFoundSyncTargets[T: RpcPackageInfo](syncTargets: seq[SyncPackageTarget],
+ pkgInfos: seq[T], upToDateNeededTable: Table[string, PackageReference]): seq[SyncPackageTarget] =
+ let pkgInfoReferencesTable = pkgInfos.map(i => (i.name, i.toPackageReference)).toTable
+ filterNotFoundSyncTargetsInternal(syncTargets, pkgInfoReferencesTable, upToDateNeededTable)
proc printSyncNotFound(config: Config, notFoundTargets: seq[SyncPackageTarget]) =
let dbs = config.dbs.toSet
for target in notFoundTargets:
if target.repo.isNone or target.repo == some("aur") or target.repo.unsafeGet in dbs:
- printError(config.color, trp("target not found: %s\n") % [target.name])
+ printError(config.color, trp("target not found: %s\n") % [$target.reference])
else:
printError(config.color, trp("database not found: %s\n") % [target.repo.unsafeGet])
@@ -854,14 +854,14 @@ proc handlePrint(args: seq[Argument], config: Config, printFormat: string, upgra
code
proc filterIgnoresAndConflicts(config: Config, pkgInfos: seq[PackageInfo],
- targetsSet: HashSet[string], installed: Table[string, Installed],
+ targetNamesSet: HashSet[string], installed: Table[string, Installed],
print: bool, noconfirm: bool): (seq[PackageInfo], seq[PackageInfo]) =
let acceptedPkgInfos = pkgInfos.filter(pkgInfo => (block:
let instGroups = lc[x | (i <- installed.opt(pkgInfo.name),
x <- i.groups), string]
if config.ignored(pkgInfo.name, (instGroups & pkgInfo.groups).deduplicate):
- if pkgInfo.name in targetsSet:
+ if pkgInfo.name in targetNamesSet:
if not print:
let input = printColonUserChoice(config.color,
trp"%s is in IgnorePkg/IgnoreGroup. Install anyway?" % [pkgInfo.name],
@@ -902,11 +902,11 @@ proc checkNeeded(installed: Table[string, Installed],
(true, 0)
proc obtainAurPackageInfos(config: Config, rpcInfos: seq[RpcPackageInfo],
- targets: seq[FullPackageTarget[RpcPackageInfo]],
+ rpcAurTargets: seq[FullPackageTarget[RpcPackageInfo]],
installed: Table[string, Installed], print: bool, needed: bool,
upgradeCount: int): (seq[PackageInfo], seq[Installed], seq[LocalIsNewer], seq[string]) =
let targetRpcInfoPairs: seq[tuple[rpcInfo: RpcPackageInfo, upgradeable: bool]] =
- targets.map(t => t.pkgInfo.get).map(i => (i, installed
+ rpcAurTargets.map(t => t.pkgInfo.get).map(i => (i, installed
.checkNeeded(i.name, i.version, true).needed))
let upToDateNeeded: seq[Installed] = if needed:
@@ -920,9 +920,9 @@ proc obtainAurPackageInfos(config: Config, rpcInfos: seq[RpcPackageInfo],
else:
@[]
- let targetsSet = targets.map(t => t.name).toSet
- let installedUpgradeRpcInfos = rpcInfos.filter(i => upgradeCount > 0 and
- not (i.name in targetsSet))
+ let installedUpgradeRpcInfos = rpcInfos.filter(i => upgradeCount > 0 and (block:
+ let reference = i.toPackageReference
+ rpcAurTargets.filter(t => t.reference.isProvidedBy(reference)).len == 0))
let upgradeStructs: seq[tuple[rpcInfo: RpcPackageInfo, needed: bool,
localIsNewer: Option[LocalIsNewer]]] = installedUpgradeRpcInfos
@@ -977,11 +977,11 @@ proc handleSyncInstall*(args: seq[Argument], config: Config): int =
let targets = args.packageTargets
- let (syncTargets, checkAur, installed, foreignUpgrade) = withAlpm(config.root, config.db,
+ let (syncTargets, checkAurNames, installed, foreignUpgrade) = withAlpm(config.root, config.db,
config.dbs, config.arch, handle, dbs, errors):
for e in errors: printError(config.color, e)
- let (syncTargets, checkAur) = findSyncTargets(handle, dbs, targets,
+ let (syncTargets, checkAurNames) = findSyncTargets(handle, dbs, targets,
not build, not build)
let installed = lc[($p.name, $p.version, p.groupsSeq, p.reason == AlpmReason.explicit) |
@@ -1006,32 +1006,33 @@ proc handleSyncInstall*(args: seq[Argument], config: Config): int =
else:
initSet[string]()
- (syncTargets, checkAur, installed, foreignUpgrade)
+ (syncTargets, checkAurNames, installed, foreignUpgrade)
- let checkAurFull = if noaur:
+ let checkAurNamesFull = if noaur:
@[]
elif upgradeCount > 0:
installed
.filter(i => i.name in foreignUpgrade and
(config.checkIgnored or not config.ignored(i.name, i.groups)))
- .map(i => i.name) & checkAur
+ .map(i => i.name) & checkAurNames
else:
- checkAur
+ checkAurNames
withAur():
- if checkAurFull.len > 0 and printFormat.isNone:
+ if checkAurNamesFull.len > 0 and printFormat.isNone:
printColon(config.color, tr"Checking AUR database...")
- let (rpcInfos, rerrors) = getRpcPackageInfo(checkAurFull)
+ let (rpcInfos, rerrors) = getRpcPackageInfo(checkAurNamesFull)
for e in rerrors: printError(config.color, e)
- let (rpcInfoTable, rpcNotFoundTargets) = filterNotFoundSyncTargets(syncTargets,
- rpcInfos, initSet[string]())
+ let rpcNotFoundTargets = filterNotFoundSyncTargets(syncTargets,
+ rpcInfos, initTable[string, PackageReference]())
if rpcNotFoundTargets.len > 0:
printSyncNotFound(config, rpcNotFoundTargets)
1
else:
if upgradeCount > 0 and not noaur and printFormat.isNone and config.printAurNotFound:
+ let rpcInfoTable = rpcInfos.map(i => (i.name, i)).toTable
for inst in installed:
if inst.name in foreignUpgrade and not config.ignored(inst.name, inst.groups) and
not rpcInfoTable.hasKey(inst.name):
@@ -1044,16 +1045,17 @@ proc handleSyncInstall*(args: seq[Argument], config: Config): int =
rpcInfos, rpcAurTargets, installedTable, printFormat.isSome, needed, upgradeCount)
for e in aperrors: printError(config.color, e)
- let upToDateNeededNames = upToDateNeeded.map(i => i.name).toSet
- let (_, notFoundTargets) = filterNotFoundSyncTargets(syncTargets,
- aurPkgInfos, upToDateNeededNames)
+ let upToDateNeededTable = upToDateNeeded.map(i => (i.name,
+ (i.name, none(string), some((ConstraintOperation.eq, i.version))))).toTable
+ let notFoundTargets = filterNotFoundSyncTargets(syncTargets,
+ aurPkgInfos, upToDateNeededTable)
if notFoundTargets.len > 0:
printSyncNotFound(config, notFoundTargets)
1
else:
- let fullTargets = mapAurTargets(syncTargets
- .filter(t => not (t.name in upToDateNeededNames)), aurPkgInfos)
+ let fullTargets = mapAurTargets(syncTargets.filter(t => not (upToDateNeededTable
+ .opt(t.reference.name).map(r => t.reference.isProvidedBy(r)).get(false))), aurPkgInfos)
let pacmanTargets = fullTargets.filter(t => not isAurTargetFull(t))
let aurTargets = fullTargets.filter(isAurTargetFull)
@@ -1070,11 +1072,11 @@ proc handleSyncInstall*(args: seq[Argument], config: Config): int =
let neededPacmanTargets = if printFormat.isNone and build and needed:
pacmanTargets.filter(target => (block:
let version = target.foundInfo.get.pkg.get.version
- if installedTable.checkNeeded(target.name, version, true).needed:
+ if installedTable.checkNeeded(target.reference.name, version, true).needed:
true
else:
printWarning(config.color, tra("%s-%s is up to date -- skipping\n") %
- [target.name, version])
+ [target.reference.name, version])
false))
else:
pacmanTargets
@@ -1094,9 +1096,9 @@ proc handleSyncInstall*(args: seq[Argument], config: Config): int =
1
else:
let pkgInfos = buildPkgInfos & aurPkgInfos
- let targetsSet = (pacmanTargets & aurTargets).map(t => t.name).toSet
+ let targetNamesSet = (pacmanTargets & aurTargets).map(t => t.reference.name).toSet
let (finalPkgInfos, acceptedPkgInfos) = filterIgnoresAndConflicts(config, pkgInfos,
- targetsSet, installedTable, printFormat.isSome, noconfirm)
+ targetNamesSet, installedTable, printFormat.isSome, noconfirm)
if finalPkgInfos.len > 0 and printFormat.isNone:
echo(trp("resolving dependencies...\n"))
@@ -1109,7 +1111,7 @@ proc handleSyncInstall*(args: seq[Argument], config: Config): int =
for pkgInfo in pkgInfos:
if not (pkgInfo.name in acceptedSet):
- if not (pkgInfo.name in targetsSet) and upgradeCount > 0 and
+ if not (pkgInfo.name in targetNamesSet) and upgradeCount > 0 and
installedTable.hasKey(pkgInfo.name):
let installedVersion = installedTable[pkgInfo.name].version
let newVersion = pkgInfo.version
@@ -1152,7 +1154,6 @@ proc handleSyncInstall*(args: seq[Argument], config: Config): int =
.filter(i => i.explicit).map(i => i.name).toSet
let foreignDepsNamesSet = foreignInstalled
.filter(i => not i.explicit).map(i => i.name).toSet
- let targetNamesSet = targets.map(t => t.name).toSet
let keepNames = foreignExplicitsNamesSet + foreignDepsNamesSet + targetNamesSet
let explicits = if args.check((none(string), "asexplicit")):
diff --git a/src/package.nim b/src/package.nim
index f0a4ee1..30ff2f8 100644
--- a/src/package.nim
+++ b/src/package.nim
@@ -177,9 +177,29 @@ proc toPackageReference*(dependency: ptr AlpmDependency): PackageReference =
template toPackageReference*(pkg: ptr AlpmPackage): PackageReference =
($pkg.name, none(string), some((ConstraintOperation.eq, $pkg.version)))
-template toPackageReference*(pkg: PackageInfo): PackageReference =
+template toPackageReference*(pkg: RpcPackageInfo): PackageReference =
(pkg.name, none(string), some((ConstraintOperation.eq, pkg.version)))
+proc parsePackageReference*(name: string, withDescription: bool): PackageReference =
+ var matches: array[3, string]
+
+ let descIndex = name.find(": ")
+ let (description, workName) = if withDescription and descIndex >= 0:
+ (some(name[descIndex + 2 .. ^1]), name[0 .. descIndex - 1])
+ else:
+ (none(string), name)
+
+ if workName.match(re"([^><=]*)\ *(=|>=|<=|>|<)\ *([^ ]*)", matches):
+ let constraints = toSeq(enumerate[ConstraintOperation]())
+ let index = constraints.map(s => $s).find(matches[1])
+
+ if index >= 0:
+ (matches[0], description, some((constraints[index], matches[2])))
+ else:
+ (matches[0], description, none(VersionConstraint))
+ else:
+ (workName, description, none(VersionConstraint))
+
proc parseSrcInfoKeys(srcInfo: string):
tuple[baseSeq: ref seq[SrcInfoPair], table: OrderedTable[string, ref seq[SrcInfoPair]]] =
var table = initOrderedTable[string, ref seq[SrcInfoPair]]()
@@ -224,29 +244,9 @@ proc parseSrcInfoName(repo: string, name: string, baseIndex: int, baseCount: int
else:
res
- proc splitConstraint(name: string): PackageReference =
- var matches: array[3, string]
-
- let descIndex = name.find(": ")
- let (description, workName) = if descIndex >= 0:
- (some(name[descIndex + 2 .. ^1]), name[0 .. descIndex - 1])
- else:
- (none(string), name)
-
- if workName.match(re"([^><=]*)\ *(=|>=|<=|>|<)\ *([^ ]*)", matches):
- let constraints = toSeq(enumerate[ConstraintOperation]())
- let index = constraints.map(s => $s).find(matches[1])
-
- if index >= 0:
- (matches[0], description, some((constraints[index], matches[2])))
- else:
- (matches[0], description, none(VersionConstraint))
- else:
- (workName, description, none(VersionConstraint))
-
proc collectArch(keyName: string): seq[PackageReference] =
(collect(keyName) & collect(keyName & "_" & arch))
- .map(splitConstraint)
+ .map(n => parsePackageReference(n, true))
.filter(c => c.name.len > 0)
proc filterReferences(references: seq[PackageReference],