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>
This commit is contained in:
Gruruya
2023-05-27 14:49:19 -04:00
committed by GitHub
parent 2dcc7195da
commit d5ba14db61

View File

@@ -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)