summary refs log tree commit diff
path: root/bin/semver
diff options
context:
space:
mode:
Diffstat (limited to 'bin/semver')
-rwxr-xr-xbin/semver107
1 files changed, 67 insertions, 40 deletions
diff --git a/bin/semver b/bin/semver
index 4072662..8205678 100755
--- a/bin/semver
+++ b/bin/semver
@@ -8,18 +8,33 @@
 # patch(robertgzr)
 # allow tagging a new non-annotated release
 
+import getopt
+import io
 import os
 import subprocess
 import sys
 import tempfile
-import getopt
+import time
 
+dry_run = False
 simple_tag = True
 force = False
 changelog = False
+push = False
+
+
+def exec(args, dry_run=False, strict=True):
+    print(f"+ {args}")
+    if not dry_run:
+        p = subprocess.run(args, stdout=subprocess.PIPE)
+        if strict and p.returncode != 0:
+            print(f"ERROR: {' '.join(args)} returned nonzero exit code")
+            sys.exit(1)
+        return p.stdout.decode().strip()
+
 
 def usage():
-    print(f"usage: {sys.argv[0]} OPTIONS COMMANDS")
+    print(f"usage: {os.path.basename(sys.argv[0])} OPTIONS COMMANDS")
     print("""
 bump the previous tag and create a new one
 
@@ -28,6 +43,8 @@ OPTIONS:
 \t-a\tannotate tag
 \t-f\toverwrite existing tag
 \t-c\twrite CHANGELOG
+\t-p\tpush changes
+\t-n\tdry run
 
 COMMANDS:
 \tpatch
@@ -38,7 +55,7 @@ COMMANDS:
 
 
 try:
-    opts, argv = getopt.getopt(sys.argv[1:], 'afch')
+    opts, argv = getopt.getopt(sys.argv[1:], 'afcpnh')
 except getopt.GetoptError as err:
     print(err)
     usage()
@@ -50,6 +67,10 @@ for o, val in opts:
         force = not force
     elif o == "-c":
         changelog = not changelog
+    elif o == "-p":
+        push = not push
+    elif o == "-n":
+        dry_run = not dry_run
     elif o == "-h":
         usage()
     else:
@@ -58,14 +79,15 @@ for o, val in opts:
 if any(item in ["-h", "--help", "help"] for item in argv):
     usage()
 
-if subprocess.run(["git", "branch", "--show-current"],
-                  stdout=subprocess.PIPE).stdout.decode().strip() != "master":
+if len(argv) < 1 or len(argv) > 1:
+    usage()
+
+if exec(["git", "branch", "--show-current"]) != "master":
     print("WARNING: not on master branch.")
 
-subprocess.run(["git", "pull", "--rebase"])
+exec(["git", "pull", "--dry-run", "--rebase"])
 
-describe = subprocess.run(["git", "describe", "--abbrev=0", "--tags"],
-                   stdout=subprocess.PIPE).stdout.decode().strip()
+describe = exec(["git", "describe", "--abbrev=0", "--tags"], strict=False)
 # TODO also ask to re-append the trailing portion.... e.g. -rev1
 
 prepend = None
@@ -90,19 +112,23 @@ if describe:
         )
         sys.exit(1)
 
-    old_version_revision = subprocess.run(["git", "log", "--pretty=%H", "-1", describe],
-                                        stdout=subprocess.PIPE).stdout.decode().strip()
-    head_revision = subprocess.run(["git", "log", "--pretty=%H", "-1", "HEAD"],
-                                        stdout=subprocess.PIPE).stdout.decode().strip()
+    old_version_revision = exec(["git", "log", "--pretty=%H", "-1", describe])
+    head_revision = exec(["git", "log", "--pretty=%H", "-1", "HEAD"])
     if old_version_revision == head_revision:
         print(f"WARNING: HEAD already tagged as {describe}")
         if not force:
             sys.exit(0)
 
-if not simple_tag or changelog:
-    shortlog = subprocess.run(
-        ["git", "shortlog", "--no-merges", f"{prepend}{describe}..HEAD"],
-        stdout=subprocess.PIPE).stdout.decode()
+if (not simple_tag) or changelog:
+    previous = describe and describe + ".."
+    if prepend:
+        previous = prepend + previous
+    shortlog = exec(["git", "shortlog", "--no-merges", f"{previous}HEAD"])
+    if not shortlog:
+        print(f"WARNING: no shortlog")
+        sys.exit(1)
+    else:
+        print(f"{shortlog}")
 
 new_version = None
 
@@ -127,37 +153,38 @@ if prepend and (new_version[0] != 'v'):
     new_version = prepend + new_version
 
 if os.path.exists("contrib/_incr_version"):
-    p = subprocess.run(["contrib/_incr_version", describe, new_version])
-    if p.returncode != 0:
-        print("Error: _incr_version returned nonzero exit code")
-        sys.exit(1)
+    exec(["contrib/_incr_version", describe, new_version])
 
 args = ["git", "tag"]
 if force:
     args.extend(["-f"])
 
-if not simple_tag:
+if simple_tag:
+    args.extend(["-m", new_version, new_version])
+    exec(args, dry_run)
+else:
     with tempfile.NamedTemporaryFile() as f:
-        basename = os.path.basename(os.getcwd())
-        f.write(f"{basename} {new_version}\n\n".encode())
+        f.write(new_version.encode())
+        f.write(f"\n\n".encode())
         f.write(shortlog.encode())
         f.flush()
-        args.extend(["-e", "-F", f.name, "-a", new_version])
-        subprocess.run(args)
-else:
-    args.extend(["-m", new_version, new_version])
-    subprocess.run(args)
-
-print(f"Tagged {new_version}")
+        args.extend(["-F", f.name, "-a", new_version])
+        exec(args, dry_run)
 
 if changelog:
-    import time
-    now = time.strftime("%Y-%m-%d", time.localtime())
-    with open("CHANGELOG", "r+") as f:
-        data = f.read()
-        f.seek(0)
-        f.write(f"\n{new_version} ({now})\n\n")
-        f.write(shortlog)
-        f.write(data)
-        f.flush()
-    print("Generated CHANGELOG")
+    changelog = io.StringIO()
+    changelog.write(
+        f"\n{new_version} ({time.strftime('%Y-%m-%d', time.localtime())})\n\n")
+    changelog.write(shortlog)
+    if dry_run:
+        print("+ [writing changelog]")
+        print(changelog.getvalue())
+    else:
+        with open("CHANGELOG", "w+") as f:
+            changelog.write(f.read())
+            f.seek(0)
+            f.write(changelog)
+            f.flush()
+
+if push:
+    exec(["git", "push", "origin", "HEAD", new_version], dry_run)