diff --git a/update_version.nim b/update_version.nim
index 2f824a5..d49076b 100644
--- a/update_version.nim
+++ b/update_version.nim
@@ -11,6 +11,9 @@ const USAGE = """Usage:
Options:
+ -d, --dir
Use the given directory as the project root (defaults
+ to the current working directory).
+
-l, --lang Choose the language/ecosystem to consider. Valid
values are: 'nim' or 'node'. If not provided, this
is auto-detected by the presence of either a *.nimble
@@ -64,13 +67,14 @@ type
SemVerParts = enum major, minor, patch, prerelease, buildmetadata
type PackageVersion = object
- packageFile: Path
+ file: Path
version: string
name: string
case lang: LangType
of lNim:
- discard
+ lines: seq[string]
+ versionLine: int
of lNode:
nodePackage: JsonNode
@@ -85,27 +89,29 @@ let SemVerPattern =
re"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"
proc parseNimblePackage(dir: Path): PackageVersion =
+ result = PackageVersion(lang: lNim)
+
for fe in walkDir(dir):
if fe.kind == pcFile and
fe.path.splitFile.ext == ".nimble":
- let content = readFile($fe.path)
- for v in content.splitLines:
- if v.startsWith("version"):
- return PackageVersion(
- lang: lNim,
- packageFile: fe.path,
- version: v.split("=")[^1].strip(chars = {' ', '"'}),
- name: $fe.path.splitFile.name)
-
+ result.lines = readFile($fe.path).splitLines
+ for idx, l in result.lines:
+ if l.startsWith("version"):
+ result.versionLine = idx
+ result.version = l.split("=")[^1].strip(chars = {' ', '"'})
+ result.name = $fe.path.splitFile.name
+ result.file = fe.path
+ return result
raise newException(IOError, "No valid .nimble file found in $#" % [$dir])
proc parseNodePackage(dir: Path): PackageVersion =
- result.packageFile = dir / Path("package.json")
- result.lang = lNode
- result.nodePackage = parseFile($result.packageFile)
+ result = PackageVersion(
+ file: dir / Path("package.json"),
+ lang: lNode,
+ nodePackage: parseFile($result.file))
if not result.nodePackage.hasKey("name") or
not result.nodePackage.hasKey("version") or
@@ -118,6 +124,28 @@ proc parseNodePackage(dir: Path): PackageVersion =
result.version = result.nodePackage{"version"}.getStr
+proc detectAndParsePackage(dir: Path): PackageVersion =
+ try: result = parseNimblePackage(dir)
+ except:
+ let nimEx = getCurrentException()
+ try: result = parseNodePackage(dir)
+ except:
+ let nodeEx = getCurrentException()
+ stderr.writeLine(
+ "Unable to find a package definitions file. Errors:\n\t$#\n\t$#" %
+ [nimEx.msg, nodeEx.msg])
+
+
+proc writePackage(pkg: PackageVersion) =
+ if pkg.lang == lNim:
+ var lines = pkg.lines
+ lines[pkg.versionLine] = "version = \"$#\"" % pkg.version
+ writeFile($pkg.file, lines.join("\p"))
+ elif pkg.lang == lNode:
+ pkg.nodePackage["version"] = %pkg.version
+ writeFile($pkg.file, pkg.nodePackage.pretty)
+
+
proc incrementLastVersionPart(version: string): string =
let versionParts = toSeq(findIter(version, re"([^\d.]+)?\.?(\d+)"))
let lastVersionPartMatch = versionParts[^1]
@@ -178,15 +206,7 @@ proc incrementSemverPart(
when isMainModule:
let args = docopt(USAGE, version = UV_VERSION)
- if args["bump"]:
- discard
- elif args["set"]:
- discard
- elif args["get"]:
- discard
- elif args["interactive"]:
- discard
- elif args["test"]:
+ if args["test"]:
# incrementLastVersionPart
assert incrementLastVersionPart("1.0.0") == "1.0.1"
@@ -206,3 +226,55 @@ when isMainModule:
assert incrementSemverPart("1.5.10", buildmetadata) == "1.5.10+build.0"
echo "All tests passed."
+ quit(QuitSuccess)
+
+
+ let dir =
+ if args["--dir"]: Path($args["--dir"])
+ else: Path(".")
+
+ var pkg =
+ if args["--lang"] and $args["--lang"] == "nim":
+ parseNimblePackage(dir)
+ elif args["--lang"] and $args["--lang"] == "node":
+ parseNodePackage(dir)
+ else:
+ detectAndParsePackage(dir)
+
+ if args["bump"]:
+ if $args[""] == "last":
+ pkg.version = incrementLastVersionPart(pkg.version)
+ else:
+ let part = parseEnum[SemVerParts]($args[""])
+ pkg.version = incrementSemverPart(pkg.version, part)
+
+ writePackage(pkg)
+ echo pkg.version
+
+ elif args["set"]:
+ pkg.version = $args[""]
+ writePackage(pkg)
+ echo pkg.version
+
+ elif args["get"]: echo pkg.version
+
+ elif args["interactive"]:
+ var acceptNewVersion = false
+ var newVersion = pkg.version
+ while not acceptNewVersion:
+ stdout.writeLine "Current version is " & pkg.version
+ stdout.write "New version? "
+ newVersion = stdin.readLine
+
+ stdout.write "New version will be set to '" & pkg.version & "'. Is this correct (yes/no)? "
+ let isCorrect = stdin.readLine
+ let acceptNewVersion = "yes".startsWith(isCorrect.toLower)
+
+ pkg.version = newVersion
+ echo "Updating version definition in " & $pkg.file
+ writePackage(pkg)
+
+ # TODO:
+ # for f in filesToUpdate:
+ # echo "Updating version definition in " & $f
+ # updateVersionInFile(f)
diff --git a/update_version.nimble b/update_version.nimble
index 3796f44..132d34b 100644
--- a/update_version.nimble
+++ b/update_version.nimble
@@ -1,6 +1,6 @@
# Package
-version = "1.0.0"
+version = "1.0.1"
author = "Jonathan Bernard"
description = "Small util to update version consistently for nim and node packages."
license = "MIT"