* Improve messaging for uninstall

* Uninstall if in right order

* Fix CI - cannot looks better

* Raise exception when nothing to remove

* Test case, minor test fix

* 0.19.6 fixes

* Fix Nim devel hash

* Feedback
This commit is contained in:
genotrance 2019-07-27 08:37:56 -05:00 • committed by Dominik Picheta
commit added89acc
5 changed files with 53 additions and 31 deletions

View file

@ -6,13 +6,13 @@ language: c
env: env:
- BRANCH=0.19.6 - BRANCH=0.19.6
- BRANCH=0.20.0 - BRANCH=0.20.2
- BRANCH=#ced0527ae334439a10e1719d1eccb727c19dc781 - BRANCH=#44aadd50cfa647a759610a15967960632bf597ce
cache: cache:
directories: directories:
- "$HOME/.choosenim/toolchains/nim-0.19.6" - "$HOME/.choosenim/toolchains/nim-0.19.6"
- "$HOME/.choosenim/toolchains/nim-0.20.0" - "$HOME/.choosenim/toolchains/nim-0.20.2"
install: install:
- export CHOOSENIM_CHOOSE_VERSION=$BRANCH - export CHOOSENIM_CHOOSE_VERSION=$BRANCH

View file

@ -840,7 +840,8 @@ proc uninstall(options: Options) =
raise newException(NimbleError, raise newException(NimbleError,
"Please specify the package(s) to uninstall.") "Please specify the package(s) to uninstall.")
var pkgsToDelete: seq[PackageInfo] = @[] var pkgsToDelete: HashSet[PackageInfo]
pkgsToDelete.init()
# Do some verification. # Do some verification.
for pkgTup in options.action.packages: for pkgTup in options.action.packages:
display("Looking", "for $1 ($2)" % [pkgTup.name, $pkgTup.ver], display("Looking", "for $1 ($2)" % [pkgTup.name, $pkgTup.ver],
@ -851,37 +852,33 @@ proc uninstall(options: Options) =
raise newException(NimbleError, "Package not found") raise newException(NimbleError, "Package not found")
display("Checking", "reverse dependencies", priority = HighPriority) display("Checking", "reverse dependencies", priority = HighPriority)
var errors: seq[string] = @[]
for pkg in pkgList: for pkg in pkgList:
# Check whether any packages depend on the ones the user is trying to # Check whether any packages depend on the ones the user is trying to
# uninstall. # uninstall.
if options.uninstallRevDeps: if options.uninstallRevDeps:
getAllRevDeps(options, pkg, pkgsToDelete) getAllRevDeps(options, pkg, pkgsToDelete)
else: else:
let revDeps = getRevDeps(options, pkg) let
revDeps = getRevDeps(options, pkg)
var reason = "" var reason = ""
if revDeps.len == 1: for revDep in revDeps:
reason = "$1 ($2) depends on it" % [revDeps[0].name, $revDeps[0].ver] if reason.len != 0: reason.add ", "
else: reason.add("$1 ($2)" % [revDep.name, revDep.version])
for i in 0 ..< revDeps.len: if reason.len != 0:
reason.add("$1 ($2)" % [revDeps[i].name, $revDeps[i].ver]) reason &= " depend" & (if revDeps.len == 1: "s" else: "") & " on it"
if i != revDeps.len-1:
reason.add ", "
reason.add " depend on it"
if revDeps.len > 0: if len(revDeps - pkgsToDelete) > 0:
errors.add("Cannot uninstall $1 ($2) because $3" % display("Cannot", "uninstall $1 ($2) because $3" %
[pkgTup.name, pkg.specialVersion, reason]) [pkgTup.name, pkg.specialVersion, reason], Warning, HighPriority)
else: else:
pkgsToDelete.add pkg pkgsToDelete.incl pkg
if pkgsToDelete.len == 0: if pkgsToDelete.len == 0:
raise newException(NimbleError, "\n " & errors.join("\n ")) raise newException(NimbleError, "Failed uninstall - no packages selected")
var pkgNames = "" var pkgNames = ""
for i in 0 ..< pkgsToDelete.len: for pkg in pkgsToDelete.items:
if i != 0: pkgNames.add ", " if pkgNames.len != 0: pkgNames.add ", "
let pkg = pkgsToDelete[i]
pkgNames.add("$1 ($2)" % [pkg.name, pkg.specialVersion]) pkgNames.add("$1 ($2)" % [pkg.name, pkg.specialVersion])
# Let's confirm that the user wants these packages removed. # Let's confirm that the user wants these packages removed.

View file

@ -3,7 +3,7 @@
# Stdlib imports # Stdlib imports
import system except TResult import system except TResult
import parsecfg, json, streams, strutils, parseutils, os, sets, tables import hashes, parsecfg, json, streams, strutils, parseutils, os, sets, tables
import httpclient import httpclient
# Local imports # Local imports
@ -542,6 +542,11 @@ proc `==`*(pkg1: PackageInfo, pkg2: PackageInfo): bool =
if pkg1.name == pkg2.name and pkg1.myPath == pkg2.myPath: if pkg1.name == pkg2.name and pkg1.myPath == pkg2.myPath:
return true return true
proc hash*(x: PackageInfo): Hash =
var h: Hash = 0
h = h !& hash(x.myPath)
result = !$h
when isMainModule: when isMainModule:
doAssert getNameVersion("/home/user/.nimble/libs/packagea-0.1") == doAssert getNameVersion("/home/user/.nimble/libs/packagea-0.1") ==
("packagea", "0.1") ("packagea", "0.1")

View file

@ -1,7 +1,7 @@
# Copyright (C) Dominik Picheta. All rights reserved. # Copyright (C) Dominik Picheta. All rights reserved.
# BSD License. Look at license.txt for more info. # BSD License. Look at license.txt for more info.
import os, json import os, json, sets
import options, common, version, download, packageinfo import options, common, version, download, packageinfo
@ -58,7 +58,7 @@ proc removeRevDep*(nimbleData: JsonNode, pkg: PackageInfo) =
newData[key] = newVal newData[key] = newVal
nimbleData["reverseDeps"] = newData nimbleData["reverseDeps"] = newData
proc getRevDeps*(options: Options, pkg: PackageInfo): seq[PkgTuple] = proc getRevDepTups*(options: Options, pkg: PackageInfo): seq[PkgTuple] =
## Returns a list of *currently installed* reverse dependencies for `pkg`. ## Returns a list of *currently installed* reverse dependencies for `pkg`.
result = @[] result = @[]
let thisPkgsDep = let thisPkgsDep =
@ -76,18 +76,25 @@ proc getRevDeps*(options: Options, pkg: PackageInfo): seq[PkgTuple] =
result.add(pkgTup) result.add(pkgTup)
proc getAllRevDeps*(options: Options, pkg: PackageInfo, result: var seq[PackageInfo]) = proc getRevDeps*(options: Options, pkg: PackageInfo): HashSet[PackageInfo] =
result.init()
let installedPkgs = getInstalledPkgsMin(options.getPkgsDir(), options)
for rdepTup in getRevDepTups(options, pkg):
for rdepInfo in findAllPkgs(installedPkgs, rdepTup):
result.incl rdepInfo
proc getAllRevDeps*(options: Options, pkg: PackageInfo, result: var HashSet[PackageInfo]) =
if pkg in result: if pkg in result:
return return
let installedPkgs = getInstalledPkgsMin(options.getPkgsDir(), options) let installedPkgs = getInstalledPkgsMin(options.getPkgsDir(), options)
for rdepTup in getRevDeps(options, pkg): for rdepTup in getRevDepTups(options, pkg):
for rdepInfo in findAllPkgs(installedPkgs, rdepTup): for rdepInfo in findAllPkgs(installedPkgs, rdepTup):
if rdepInfo in result: if rdepInfo in result:
continue continue
getAllRevDeps(options, rdepInfo, result) getAllRevDeps(options, rdepInfo, result)
result.add pkg result.incl pkg
when isMainModule: when isMainModule:
var nimbleData = %{"reverseDeps": newJObject()} var nimbleData = %{"reverseDeps": newJObject()}

View file

@ -465,8 +465,7 @@ test "can uninstall":
let ls = outp.strip.processOutput() let ls = outp.strip.processOutput()
check exitCode != QuitSuccess check exitCode != QuitSuccess
check "Cannot uninstall issue27b (0.1.0) because issue27a (0.1.0) depends" & check inLines(ls, "Cannot uninstall issue27b (0.1.0) because issue27a (0.1.0) depends")
" on it" in ls[ls.len-1]
check execNimble("uninstall", "-y", "issue27").exitCode == QuitSuccess check execNimble("uninstall", "-y", "issue27").exitCode == QuitSuccess
check execNimble("uninstall", "-y", "issue27a").exitCode == QuitSuccess check execNimble("uninstall", "-y", "issue27a").exitCode == QuitSuccess
@ -827,3 +826,17 @@ test "init does not overwrite existing files (#581)":
check execNimbleYes("init").exitCode == QuitSuccess check execNimbleYes("init").exitCode == QuitSuccess
check readFile("src/issue581.nim") == Src check readFile("src/issue581.nim") == Src
removeDir("issue581") removeDir("issue581")
test "remove skips packages with revDeps (#504)":
check execNimble("install", "nimboost@0.5.5", "nimfp@0.4.4", "-y").exitCode == QuitSuccess
var (output, exitCode) = execNimble("uninstall", "nimboost", "nimfp", "-n")
var lines = output.strip.processOutput()
check inLines(lines, "Cannot uninstall nimboost")
(output, exitCode) = execNimble("uninstall", "nimfp", "nimboost", "-y")
lines = output.strip.processOutput()
check (not inLines(lines, "Cannot uninstall nimboost"))
check execNimble("path", "nimboost").exitCode != QuitSuccess
check execNimble("path", "nimfp").exitCode != QuitSuccess