diff --git a/README.md b/README.md index 2d14606..f39f021 100644 --- a/README.md +++ b/README.md @@ -38,13 +38,15 @@ make install ## Usage ```bash -semver [-hqstw] +semver [-hqstw] [-i ] ``` Options: - `-h --help` Show the help screen. +- `-i --increment ` + Increment the specified component of the matched versions. Allowed values for component are 'major', 'minor', 'patch'. - `-q --quiet` Quiet - suppress normal output. - `-s --sort` @@ -54,7 +56,7 @@ Options: - `-w --word-match` Select words that match the semver pattern. (Equivalent to the *grep(1)* `--word-regexp` option.) -Most options can be combined. For example, `semver -stw` will word-match occurrences of semvers, sort them, and print them in tabulated form. +Options can be combined. For example, `semver -stw` will word-match occurrences of semvers, sort them, and print them in tabulated form. ## Manual @@ -73,14 +75,11 @@ semver < example.txt **Calculate** the next Git tag: ```bash -# ++major -git tag | semver -st | tail -n 1 | awk -F '\t' '{ print ++$1 "." 0 "." 0 }' +git tag | semver -s | tail -n 1 | semver -i major -# ++minor -git tag | semver -st | tail -n 1 | awk -F '\t' '{ print $1 "." ++$2 "." 0 }' +git tag | semver -s | tail -n 1 | semver -i minor -# ++patch -git tag | semver -st | tail -n 1 | awk -F '\t' '{ print $1 "." $2 "." ++$3 }' +git tag | semver -s | tail -n 1 | semver -i patch ``` **Cut** out the major, minor, and patch components of a version: @@ -94,7 +93,7 @@ semver -t <<< '1.2.3-alpha+1' | cut -f 1-3 ```bash v='0.0.1' while curl -fs "https://example.com/artifact/$v.tar.gz" > "$v.tar.gz"; do - v=$(semver -t <<< "$v" | awk -F '\t' '{ print $1 "." $2 "." ++$3 }') + v=$(semver -i patch <<< "$v") done ``` @@ -115,31 +114,3 @@ semver -tw < example.txt | tr '\t' ',' ```bash semver -q <<< '1.2.3' && echo 'ok' ``` - -## Functions - -These Bash helper functions can make complex versioning operations easier. - -```bash -#!/usr/bin/env bash - -function ++major { - semver -t <<< "$1" | awk -F '\t' '{ print ++$1 "." 0 "." 0 }' -} - -function ++minor { - semver -t <<< "$1" | awk -F '\t' '{ print $1 "." ++$2 "." 0 }' -} - -function ++patch { - semver -t <<< "$1" | awk -F '\t' '{ print $1 "." $2 "." ++$3 }' -} -``` - -Examples: - -```bash -++major '1.2.3' #=> 2.0.0 -++minor '1.2.3' #=> 1.3.0 -++patch '1.2.3' #=> 1.2.4 -``` diff --git a/semver b/semver index 35ac71e..f0d3219 100755 --- a/semver +++ b/semver @@ -2,7 +2,7 @@ use strict; use warnings; -use feature qw(say); +use feature qw(say switch); use Scalar::Util qw(looks_like_number); use List::Util qw(max); use Getopt::Long qw(GetOptionsFromArray :config bundling); @@ -25,14 +25,15 @@ sub semver::usage() { say STDERR "Semantic Versioning utility."; say STDERR ""; say STDERR "Usage:"; - say STDERR " $program [-hqstw]"; + say STDERR " $program [-hqstw] [-i ]"; say STDERR ""; say STDERR "Options:"; - say STDERR " -h --help Show the help screen."; - say STDERR " -q --quiet Quiet - suppress normal output."; - say STDERR " -s --sort Sort the matched versions in precedence order (low-to-high)."; - say STDERR " -t --tabulate Tabulate the matched versions (separator: '\\t')."; - say STDERR " -w --word-match Select words that match the semver pattern."; + say STDERR " -h --help Show the help screen."; + say STDERR " -i --increment Increment the specified component of the matched versions. Allowed values for component are 'major', 'minor', 'patch'."; + say STDERR " -q --quiet Quiet - suppress normal output."; + say STDERR " -s --sort Sort the matched versions in precedence order (low-to-high)."; + say STDERR " -t --tabulate Tabulate the matched versions (separator: '\\t')."; + say STDERR " -w --word-match Select words that match the semver pattern."; exit 1; } @@ -143,7 +144,7 @@ sub semver::compare { } sub semver::match { - my ($quiet, $sort, $tabulate, $word_match) = @_; + my ($increment, $quiet, $sort, $tabulate, $word_match) = @_; my $num_matches = 0; @@ -166,12 +167,18 @@ sub semver::match { exit 0; } + my @ver = ($1, $2, $3, $4, $5); + + if ($increment) { + @ver = inc($increment, $1, $2, $3); + } + if ($sort) { - push(@lines, plain($1, $2, $3, $4, $5)); + push(@lines, plain(@ver)); } elsif ($tabulate) { - say tabulate($1, $2, $3, $4, $5); + say tabulate(@ver); } else { - say plain($1, $2, $3, $4, $5); + say plain(@ver); } } } @@ -213,6 +220,18 @@ sub semver::tabulate { return $str; } +sub semver::inc { + my ($increment, $major, $minor, $patch) = @_; + + no warnings 'experimental'; + for ($increment) { + when ("major") { return (++$major, 0, 0) } + when ("minor") { return ($major, ++$minor, 0) } + when ("patch") { return ($major, $minor, ++$patch) } + default { say STDERR "Error: unrecognised value for -i|--increment option. Allowed values are 'major', 'minor', or 'patch'."; exit 1; } + } +} + sub semver::plain { my ($major, $minor, $patch, $pre, $build) = @_; @@ -239,22 +258,23 @@ sub semver::sort_pair { sub main { my @args = @_; - my ($help, $quiet, $sort, $tabulate, $word_match); + my ($help, $increment, $quiet, $sort, $tabulate, $word_match); main::GetOptionsFromArray( \@args, - "help|h" => \$help, - "quiet|q" => \$quiet, - "sort|s" => \$sort, - "tabulate|t" => \$tabulate, - "word-match|w" => \$word_match + "help|h" => \$help, + "quiet|q" => \$quiet, + "increment|i=s" => \$increment, + "sort|s" => \$sort, + "tabulate|t" => \$tabulate, + "word-match|w" => \$word_match ) or exit 1; if ($help || (scalar(@args) > 0)) { usage(); } - match($quiet, $sort, $tabulate, $word_match); + match($increment, $quiet, $sort, $tabulate, $word_match); } main(@ARGV); diff --git a/semver.1 b/semver.1 index e4b6f61..fb9de85 100644 --- a/semver.1 +++ b/semver.1 @@ -7,6 +7,7 @@ .Sh SYNOPSIS .Nm .Op Fl hqstw +.Op Fl i Ar .Sh DESCRIPTION The .Nm @@ -35,6 +36,20 @@ utility understands the following command-line options: .Bl -tag -width Ds indent .It Fl h, -help Display the usage screen. +.It Fl i, -increment Ar +Increment the specified +.Ar component +of the matched versions. Allowed values for +.Ar component +are 'major', 'minor', 'patch'. +.Pp +Example: +.Pp +.Bd -literal -offset indent +semver -i major <<< '1.2.3' # => 2.0.0 +semver -i minor <<< '1.2.3' # => 1.3.0 +semver -i patch <<< '1.2.3' # => 1.2.4 +.Ed .It Fl q, -quiet Quiet mode. Nothing shall be written to the standard output, regardless of matching Semantic Versions. The utility will exit immediately with zero status if a Semantic Version string is selected. .Pp @@ -109,14 +124,11 @@ semver < example.txt \fBCalculate\fR the next Git tag: .Pp .Bd -literal -offset indent -compact -# major++ -git tag | semver -st | tail -n 1 | awk -F '\\t' '{ print ++$1 "." 0 "." 0 }' +git tag | semver -s | tail -n 1 | semver -i major -# minor++ -git tag | semver -st | tail -n 1 | awk -F '\\t' '{ print $1 "." ++$2 "." 0 }' +git tag | semver -s | tail -n 1 | semver -i minor -# patch++ -git tag | semver -st | tail -n 1 | awk -F '\\t' '{ print $1 "." $2 "." ++$3 }' +git tag | semver -s | tail -n 1 | semver -i patch .Ed .Pp \fBCut\fR out the major, minor, and patch components of versions: @@ -130,7 +142,7 @@ semver -t <<< '1.2.3-alpha+1' | cut -f 1-3 .Bd -literal -offset indent -compact v='0.0.1' while curl -fs "https://example.com/artifact/$v.tar.gz" > "$v.tar.gz"; do - v=$(semver -t <<< "$v" | awk -F '\\t' '{ print $1 "." $2 "." ++$3 }') + v=$(semver -i patch <<< "$v") done .Ed .Pp diff --git a/test/options/increment.bats b/test/options/increment.bats new file mode 100644 index 0000000..ab7769f --- /dev/null +++ b/test/options/increment.bats @@ -0,0 +1,48 @@ +#!/usr/bin/env bats + +semver() { + ./semver "$@" +} + +@test 'semver -i major: should increment the major version' { + [[ $(semver -i major <<< '1.2.3') = '2.0.0' ]] +} + +@test 'semver -i minor: should increment the minor version' { + [[ $(semver -i minor <<< '1.2.3') = '1.3.0' ]] +} + +@test 'semver -i patch: should increment the patch version' { + [[ $(semver -i patch <<< '1.2.3') = '1.2.4' ]] +} + +@test 'semver -i patch: should increment a build modifier correctly' { + # TODO: is this the correct behaviour? + [[ $(semver -i patch <<< '1.2.3-alpha.1') = '1.2.3' ]] +} + +@test 'semver -i: should reject unknown version component arguments' { + run semver -i foobar <<< '1.2.3' + + [[ "$status" -eq 1 ]] && [[ "${lines[0]}" = "Error: unrecognised value for -i|--increment option. Allowed values are 'major', 'minor', or 'patch'." ]] +} + +@test 'semver -i: should increment all matched versions' { + input=$(cat <