diff options
author | Gruruya <gruruya.chi4c@slmails.com> | 2023-05-27 14:49:19 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-27 20:49:19 +0200 |
commit | d5ba14db619eb52cb97f66f37cd04a240d84223d (patch) | |
tree | 024162ac28beddaaee7211cf4fa42ac6f04f8a69 | |
parent | 2dcc7195daab5964a68d7eb6edf897edc0cf2052 (diff) | |
download | Nim-d5ba14db619eb52cb97f66f37cd04a240d84223d.tar.gz |
Atlas: add `atlas tag` command (#21936)
* Initial structure, `GitTags` → `GitRefsTags` * Determine if we should use v prefix * get tag from latest tag, patch nimble file * Just do tags for now * atlas tag now tags and pushes * Improve UX of `atlas tag` * better description for `tag` * Small fixup * Consistent naming * strip after checking status * Take major/minor/patch as arg for `atlas tag` * undo testing comment * Fix for `v` prefixed versions * Avoid useless assignment * Remove uselss enum assignment * Consistent parameter seperation * Add error handling for non-semver tags * Use `assert` to quit on error * Update tools/atlas/atlas.nim Co-authored-by: Andreas Rumpf <rumpf_a@web.de> * Don't push tags if errors occurred * Allow `atlas tag [tag]` again * Add atlas tag `a..z` for fields > 3 * Document the three input options * Take up less lines in help * Less or in help * One last doc pass * Check args length * clarify last tag * consistency/order --------- Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
-rw-r--r-- | tools/atlas/atlas.nim | 88 |
1 files changed, 84 insertions, 4 deletions
diff --git a/tools/atlas/atlas.nim b/tools/atlas/atlas.nim index 13a2bb785..9361cf043 100644 --- a/tools/atlas/atlas.nim +++ b/tools/atlas/atlas.nim @@ -43,6 +43,10 @@ Command: updateDeps [filter] update every dependency that has a remote URL that matches `filter` if a filter is given + tag [major|minor|patch] + add and push a new tag, input must be one of: + ['major'|'minor'|'patch'] or a SemVer tag like ['1.0.3'] + or a letter ['a'..'z']: a.b.c.d.e.f.g build|test|doc|tasks currently delegates to `nimble build|test|doc` task <taskname> currently delegates to `nimble <taskname>` @@ -83,6 +87,9 @@ type DepRelation = enum normal, strictlyLess, strictlyGreater + SemVerField = enum + major, minor, patch + Dependency = object name: PackageName url, commit: string @@ -116,9 +123,12 @@ const type Command = enum GitDiff = "git diff", + GitTag = "git tag", GitTags = "git show-ref --tags", + GitLastTaggedRef = "git rev-list --tags --max-count=1", GitRevParse = "git rev-parse", GitCheckout = "git checkout", + GitPush = "git push origin", GitPull = "git pull", GitCurrentCommit = "git log -n 1 --format=%H" GitMergeBase = "git merge-base" @@ -143,7 +153,7 @@ proc exec(c: var AtlasContext; cmd: Command; args: openArray[string]): (string, when MockupRun: assert TestLog[c.step].cmd == cmd, $(TestLog[c.step].cmd, cmd) case cmd - of GitDiff, GitTags, GitRevParse, GitPull, GitCurrentCommit: + of GitDiff, GitTag, GitTags, GitLastTaggedRef, GitRevParse, GitPush, GitPull, GitCurrentCommit: result = (TestLog[c.step].output, TestLog[c.step].exitCode) of GitCheckout: assert args[0] == TestLog[c.step].output @@ -209,6 +219,9 @@ proc message(c: var AtlasContext; category: string; p: PackageName; args: vararg msg.add a stdout.writeLine msg +proc info(c: var AtlasContext; p: PackageName; args: varargs[string]) = + message(c, "[Info] ", p, args) + proc warn(c: var AtlasContext; p: PackageName; args: varargs[string]) = message(c, "[Warning] ", p, args) inc c.errors @@ -217,9 +230,6 @@ proc error(c: var AtlasContext; p: PackageName; args: varargs[string]) = message(c, "[Error] ", p, args) inc c.errors -proc info(c: var AtlasContext; p: PackageName; args: varargs[string]) = - message(c, "[Info] ", p, args) - proc sameVersionAs(tag, ver: string): bool = const VersionChars = {'0'..'9', '.'} @@ -270,6 +280,62 @@ proc gitPull(c: var AtlasContext; p: PackageName) = if status != 0: error(c, p, "could not 'git pull'") +proc gitTag(c: var AtlasContext; tag: string) = + let (_, status) = exec(c, GitTag, [tag]) + if status != 0: + error(c, c.projectDir.PackageName, "could not 'git tag " & tag & "'") + +proc pushTag(c: var AtlasContext; tag: string) = + let (outp, status) = exec(c, GitPush, [tag]) + if status != 0: + error(c, c.projectDir.PackageName, "could not 'git push " & tag & "'") + elif outp.strip() == "Everything up-to-date": + info(c, c.projectDir.PackageName, "is up-to-date") + else: + info(c, c.projectDir.PackageName, "successfully pushed tag: " & tag) + +proc incrementTag(lastTag: string; field: Natural): string = + var startPos = + if lastTag[0] in {'0'..'9'}: 0 + else: 1 + var endPos = lastTag.find('.', startPos) + if field >= 1: + for i in 1 .. field: + assert endPos != -1, "the last tag '" & lastTag & "' is missing . periods" + startPos = endPos + 1 + endPos = lastTag.find('.', startPos) + if endPos == -1: + endPos = len(lastTag) + let patchNumber = parseInt(lastTag[startPos..<endPos]) + lastTag[0..<startPos] & $(patchNumber + 1) & lastTag[endPos..^1] + +proc incrementLastTag(c: var AtlasContext; field: Natural): string = + let (ltr, status) = exec(c, GitLastTaggedRef, []) + if status == 0: + let + lastTaggedRef = ltr.strip() + (lt, _) = osproc.execCmdEx("git describe --tags " & lastTaggedRef) + lastTag = lt.strip() + (cc, _) = exec(c, GitCurrentCommit, []) + currentCommit = cc.strip() + + if lastTaggedRef == currentCommit: + info c, c.projectDir.PackageName, "the current commit '" & currentCommit & "' is already tagged '" & lastTag & "'" + lastTag + else: + incrementTag(lastTag, field) + else: "v0.0.1" # assuming no tags have been made yet + +proc tag(c: var AtlasContext; tag: string) = + gitTag(c, tag) + pushTag(c, tag) + +proc tag(c: var AtlasContext; field: Natural) = + let oldErrors = c.errors + let newTag = incrementLastTag(c, field) + if c.errors == oldErrors: + tag(c, newTag) + proc updatePackages(c: var AtlasContext) = if dirExists(c.workspace / PackagesDir): withDir(c, c.workspace / PackagesDir): @@ -839,6 +905,20 @@ proc main = echo toJson(extractRequiresInfo(args[0])) else: error "File does not exist: " & args[0] + of "tag": + projectCmd() + if args.len == 0: + tag(c, ord(patch)) + elif args[0].len == 1 and args[0][0] in {'a'..'z'}: + let field = ord(args[0][0]) - ord('a') + tag(c, field) + elif '.' in args[0]: + tag(c, args[0]) + else: + var field: SemVerField + try: field = parseEnum[SemVerField](args[0]) + except: error "tag command takes one of 'patch' 'minor' 'major', a SemVer tag, or a letter from 'a' to 'z'" + tag(c, ord(field)) of "build", "test", "doc", "tasks": projectCmd() nimbleExec(action, args) |