From 2243e3fbc2dd277ad81df5d795307bf8389b9240 Mon Sep 17 00:00:00 2001 From: Hitesh Jasani Date: Sat, 24 Aug 2019 05:15:29 -0400 Subject: [PATCH] Fix #567: Display package versions in sorted order (#688) * Fix #567: Display package versions in sorted order * Add docs * Fix docs to focus on git tags * Refactor to use version module * Streamline docs * Refactor to make things work in nim <= 0.19.6 * Improve code readability --- readme.markdown | 13 ++++++++++ src/nimblepkg/download.nim | 52 +++++++++++++++++++++++++------------- src/nimblepkg/version.nim | 14 +++++++--- tests/tester.nim | 4 +++ 4 files changed, 63 insertions(+), 20 deletions(-) diff --git a/readme.markdown b/readme.markdown index 5f3ef52..9470aa8 100644 --- a/readme.markdown +++ b/readme.markdown @@ -786,6 +786,19 @@ To summarise, the steps for release are: Once the new tag is in the remote repository, Nimble will be able to detect the new version. +##### Git Version Tagging + +Use dot separated numbers to represent the release version in the git +tag label. Nimble will parse these git tag labels to know which +versions of a package are published. + +``` text +v0.2.0 # 0.2.0 +v1 # 1 +v1.2.3-zuzu # 1.2.3 +foo-1.2.3.4 # 1.2.3.4 +``` + ## Publishing packages Publishing packages isn't a requirement. But doing so allows people to associate diff --git a/src/nimblepkg/download.nim b/src/nimblepkg/download.nim index b504b61..639354f 100644 --- a/src/nimblepkg/download.nim +++ b/src/nimblepkg/download.nim @@ -2,8 +2,9 @@ # BSD License. Look at license.txt for more info. import parseutils, os, osproc, strutils, tables, pegs, uri - import packageinfo, packageparser, version, tools, common, options, cli +from algorithm import SortOrder, sorted +from sequtils import toSeq, filterIt, map type DownloadMethod* {.pure.} = enum @@ -103,14 +104,21 @@ proc getTagsListRemote*(url: string, meth: DownloadMethod): seq[string] = # http://stackoverflow.com/questions/2039150/show-tags-for-remote-hg-repository raise newException(ValueError, "Hg doesn't support remote tag querying.") -proc getVersionList*(tags: seq[string]): Table[Version, string] = - # Returns: TTable of version -> git tag name - result = initTable[Version, string]() - for tag in tags: - if tag != "": - let i = skipUntil(tag, Digits) # skip any chars before the version - # TODO: Better checking, tags can have any names. Add warnings and such. - result[newVersion(tag[i .. tag.len-1])] = tag +proc getVersionList*(tags: seq[string]): OrderedTable[Version, string] = + ## Return an ordered table of Version -> git tag label. Ordering is + ## in descending order with the most recent version first. + let taggedVers: seq[tuple[ver: Version, tag: string]] = + tags + .filterIt(it != "") + .map(proc(s: string): tuple[ver: Version, tag: string] = + # skip any chars before the version + let i = skipUntil(s, Digits) + # TODO: Better checking, tags can have any + # names. Add warnings and such. + result = (newVersion(s[i .. s.len-1]), s)) + .sorted(proc(a, b: (Version, string)): int = cmp(a[0], b[0]), + SortOrder.Descending) + result = toOrderedTable[Version, string](taggedVers) proc getDownloadMethod*(meth: string): DownloadMethod = case meth @@ -268,14 +276,8 @@ proc echoPackageVersions*(pkg: Package) = try: let versions = getTagsListRemote(pkg.url, downMethod).getVersionList() if versions.len > 0: - var vstr = "" - var i = 0 - for v in values(versions): - if i != 0: - vstr.add(", ") - vstr.add(v) - i.inc - echo(" versions: " & vstr) + let sortedVersions = toSeq(values(versions)) + echo(" versions: " & join(sortedVersions, ", ")) else: echo(" versions: (No versions tagged in the remote repository)") except OSError: @@ -283,3 +285,19 @@ proc echoPackageVersions*(pkg: Package) = of DownloadMethod.hg: echo(" versions: (Remote tag retrieval not supported by " & pkg.downloadMethod & ")") + +when isMainModule: + # Test version sorting + block: + let data = @["v9.0.0-taeyeon", "v9.0.1-jessica", "v9.2.0-sunny", + "v9.4.0-tiffany", "v9.4.2-hyoyeon"] + let expected = toOrderedTable[Version, string]({ + newVersion("9.4.2-hyoyeon"): "v9.4.2-hyoyeon", + newVersion("9.4.0-tiffany"): "v9.4.0-tiffany", + newVersion("9.2.0-sunny"): "v9.2.0-sunny", + newVersion("9.0.1-jessica"): "v9.0.1-jessica", + newVersion("9.0.0-taeyeon"): "v9.0.0-taeyeon" + }) + doAssert expected == getVersionList(data) + + echo("Everything works!") diff --git a/src/nimblepkg/version.nim b/src/nimblepkg/version.nim index a3e7c4a..4834b6d 100644 --- a/src/nimblepkg/version.nim +++ b/src/nimblepkg/version.nim @@ -93,6 +93,11 @@ proc `==`*(ver: Version, ver2: Version): bool = else: return false +proc cmp*(a, b: Version): int = + if a < b: -1 + elif a > b: 1 + else: 0 + proc `<=`*(ver: Version, ver2: Version): bool = return (ver == ver2) or (ver < ver2) @@ -272,7 +277,7 @@ proc newVREq*(ver: string): VersionRange = result.ver = newVersion(ver) proc findLatest*(verRange: VersionRange, - versions: Table[Version, string]): tuple[ver: Version, tag: string] = + versions: OrderedTable[Version, string]): tuple[ver: Version, tag: string] = result = (newVersion(""), "") for ver, tag in versions: if not withinRange(ver, verRange): continue @@ -309,8 +314,11 @@ when isMainModule: doAssert(newVersion("") < newVersion("1.0.0")) doAssert(newVersion("") < newVersion("0.1.0")) - var versions = toTable[Version, string]({newVersion("0.1.1"): "v0.1.1", - newVersion("0.2.3"): "v0.2.3", newVersion("0.5"): "v0.5"}) + var versions = toOrderedTable[Version, string]({ + newVersion("0.1.1"): "v0.1.1", + newVersion("0.2.3"): "v0.2.3", + newVersion("0.5"): "v0.5" + }) doAssert findLatest(parseVersionRange(">= 0.1 & <= 0.4"), versions) == (newVersion("0.2.3"), "v0.2.3") diff --git a/tests/tester.nim b/tests/tester.nim index b08d0cf..09427e8 100644 --- a/tests/tester.nim +++ b/tests/tester.nim @@ -818,6 +818,10 @@ suite "Module tests": cd "..": check execCmdEx("nim c -r src/nimblepkg/cli").exitCode == QuitSuccess + test "download": + cd "..": + check execCmdEx("nim c -r src/nimblepkg/download").exitCode == QuitSuccess + test "init does not overwrite existing files (#581)": createDir("issue581/src") cd "issue581":