effort: More robust argument parsing

Why:

* The old way of handling arguments could make it
difficult to make non-breaking changes because
to be able to handle more arguments than the
'--above' argument, the logic would need to be heavily
refactored and demand restrictions on argument order.

This change addresses the need by:

* Parse arguments in a cleaner way
* Make the command more future proof with respect to arguments

Notable change is the synopsis. Please the see man page.
This commit is contained in:
Nicolai Skogheim 2015-08-29 15:14:26 +02:00
parent 0c7bf665f2
commit 86e1a7014c
4 changed files with 116 additions and 97 deletions

View file

@ -115,41 +115,32 @@ sort_effort() {
< $tmp sort -rn -k 2
}
above_index=0
has_above=false
next_is_above=false
num_paths=0
declare -a paths=()
while [ "${#}" -ge 1 ] ; do
# Some implementations of `seq` gives "1\n0" for seq 0
if [ $# -gt 0 ] ; then
for i in `seq ${#@}`
do
cur="${!i}"
case "$1" in
--above)
shift
above=$1
;;
--)
shift
args_to_git_log=$(printf " %q" "${@:1}")
break
;;
--*)
echo 1>&2 "error: unknown argument $1"
echo 1>&2 "error: if that argument was meant for git-log,"
echo 1>&2 "error: please put it after two dashes ( -- )."
exit 1
;;
*)
paths+=( "$1" )
;;
esac
if "$next_is_above" ; then
above="$cur"
next_is_above=false
continue
fi
case "$cur" in
--above)
if "$has_above" ; then
echo "error: --above can only be specified one time" 1>&2
exit 1
fi
next_is_above=true
has_above=true
above_index=$(( i - 1 ))
;;
--*)
;;
*)
num_paths=$(( num_paths + 1 ))
;;
esac
done
fi
shift
done
# Exit if above-value is not an int
if [ -z "${above##*[!0-9]*}" ] ; then
@ -157,26 +148,13 @@ if [ -z "${above##*[!0-9]*}" ] ; then
exit 1
fi
args_before_above=`printf " %q" "${@:1:$above_index}"`
num_args=$(( i - num_paths ))
if $has_above ; then offset=2 ; else offset=0 ; fi
from=$(( 1 + above_index + offset ))
len=$(( num_args - $(( above_index + offset)) ))
args_after_above=`printf " %q" "${@:$from:$len}"`
args_to_git_log="${args_before_above#\ \'\'}${args_after_above#\ \'\'}"
shift $num_args
# remove empty quotes that appear when there are no arguments
args_to_git_log="${args_to_git_log#\ \'\'}"
export args_to_git_log
# [path ...]
declare -a paths=()
if test $# -ge 1; then
paths=("$@")
else
if test "${#paths}" -eq 0; then
save_ifs=$IFS
IFS=`echo -en "\n\b"`
paths=(`git ls-files`)

View file

@ -1,13 +1,13 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-EFFORT" "1" "August 2015" "" "Git Extras"
.TH "GIT\-EFFORT" "1" "September 2015" "" "Git Extras"
.
.SH "NAME"
\fBgit\-effort\fR \- Show effort statistics on file(s)
.
.SH "SYNOPSIS"
\fBgit\-effort\fR [\-\-above <value>] [<options>] [[\-\-] <path>\.\.\.]
\fBgit\-effort\fR [\-\-above <value>] [<path>\.\.\.] [\-\- [<log options>\.\.\.]]
.
.SH "DESCRIPTION"
Shows effort statistics about files in the repository\.
@ -28,23 +28,20 @@ Display includes:
Ignore files with commits <= a value\.
.
.P
Run
.
.br
man \-P \'less +/Commit\e Limiting\' git\-log
.
.br
to read about options to limit which commits are counted\.
.
.P
Note: \fBgit\-effort\fR does not accept commit ranges\.
.
.P
[\-\-] <path>\.\.\.
<path>\.\.\.
.
.P
Only count commits that touches the given paths\.
.
.P
Note: \fBgit\-effort\fR does not accept revision ranges, but the underlying \fBgit log\fR does (See the examples)\.
.
.P
<log options>\.\.\.
.
.P
Options for \fBgit log\fR\. Note that you must use \fB\-\-\fR to separate options to \fBgit log\fR from options to \fBgit effort\fR\. This makes it possible to only count commits you are interested in\. Not all options are relevant in the context of \fBgit\-effort\fR, but those that are is listed under the "Commit Limiting" section on the \fBgit\-log\fR manpages\.
.
.SH "EXAMPLES"
Note: Output will first appear unsorted, then the screen is cleared and the sorted list is output\. The initial unsorted list is not shown in the examples for brevity\.
.
@ -70,7 +67,7 @@ $ git effort \-\-above 5
git\-repl 7 5
$ git effort \-\-after="one year ago" \-\-above 5 \-\-author="Leila Muhtasib"
$ git effort \-\-above 5 bin/* \-\- \-\-after="one year ago" \-\-author="Leila Muhtasib"
file commits active days
@ -86,18 +83,37 @@ $ git effort \-\-after="one year ago" \-\-above 5 \-\-author="Leila Muhtasib"
.IP "" 0
.
.P
Showing statistics on directories is also possible
Showing statistics on directories is also possible:
.
.IP "" 4
.
.nf
$ git effort bin man
$ git effort bin man \-\- \-\-after="one year ago"
file commits active days
bin\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. 406 232
man\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. 118 80
bin\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. 406 232
man\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. 118 80
.
.fi
.
.IP "" 0
.
.P
Only count commits in the specified revision range:
.
.P
$ git effort \-\- master\.\.feature
.
.IP "" 4
.
.nf
file commits active days
bin/git\-effort\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. 3 2
man/git\-effort\.md\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. 1 1
.
.fi
.

View file

@ -76,7 +76,7 @@
<h2 id="SYNOPSIS">SYNOPSIS</h2>
<p><code>git-effort</code> [--above &lt;value&gt;] [&lt;options&gt;] [[--] &lt;path&gt;...]</p>
<p><code>git-effort</code> [--above &lt;value&gt;] [&lt;path&gt;...] [-- [&lt;log options&gt;...]]</p>
<h2 id="DESCRIPTION">DESCRIPTION</h2>
@ -92,16 +92,19 @@
<p> Ignore files with commits &lt;= a value.</p>
<p> Run<br />
man -P 'less +/Commit\ Limiting' git-log<br />
to read about options to limit which commits are counted.</p>
<p> Note: <code>git-effort</code> does not accept commit ranges.</p>
<p> [--] &lt;path&gt;...</p>
<p> &lt;path&gt;...</p>
<p> Only count commits that touches the given paths.</p>
<p> Note: <code>git-effort</code> does not accept revision ranges, but the underlying <code>git log</code> does (See the examples).</p>
<p> &lt;log options&gt;...</p>
<p> Options for <code>git log</code>. Note that you must use <code>--</code> to separate options to <code>git log</code>
from options to <code>git effort</code>.
This makes it possible to only count commits you are interested in.
Not all options are relevant in the context of <code>git-effort</code>, but those that are is listed under the "Commit Limiting" section on the <code>git-log</code> manpages.</p>
<h2 id="EXAMPLES">EXAMPLES</h2>
<p> Note: Output will first appear unsorted, then the screen is cleared and the sorted
@ -124,7 +127,7 @@
git-repl 7 5
$ git effort --after="one year ago" --above 5 --author="Leila Muhtasib"
$ git effort --above 5 bin/* -- --after="one year ago" --author="Leila Muhtasib"
file commits active days
@ -136,19 +139,29 @@ $ git effort --after="one year ago" --above 5 --author="Leila Muhtasib"
git-graft 2 2
</code></pre>
<p> Showing statistics on directories is also possible</p>
<p> Showing statistics on directories is also possible:</p>
<pre><code>$ git effort bin man
<pre><code>$ git effort bin man -- --after="one year ago"
file commits active days
bin.......................................... 406 232
man.......................................... 118 80
bin.......................................... 406 232
man.......................................... 118 80
</code></pre>
<p> Only count commits in the specified revision range:</p>
<p> $ git effort -- master..feature</p>
<pre><code> file commits active days
bin/git-effort............................... 3 2
man/git-effort.md............................ 1 1
</code></pre>
<h2 id="AUTHOR">AUTHOR</h2>
<p>Written by Leila Muhtasib &lt;<a href="&#x6d;&#x61;&#x69;&#x6c;&#116;&#x6f;&#58;&#109;&#x75;&#104;&#x74;&#97;&#115;&#x69;&#x62;&#64;&#103;&#x6d;&#x61;&#x69;&#108;&#46;&#x63;&#111;&#x6d;" data-bare-link="true">&#x6d;&#117;&#x68;&#116;&#97;&#x73;&#x69;&#x62;&#64;&#x67;&#x6d;&#97;&#x69;&#108;&#x2e;&#x63;&#x6f;&#x6d;</a>&gt;</p>
<p>Written by Leila Muhtasib &lt;<a href="&#x6d;&#97;&#x69;&#x6c;&#116;&#x6f;&#x3a;&#109;&#117;&#x68;&#116;&#x61;&#x73;&#105;&#98;&#64;&#x67;&#109;&#x61;&#x69;&#x6c;&#46;&#x63;&#x6f;&#109;" data-bare-link="true">&#109;&#x75;&#104;&#116;&#x61;&#x73;&#x69;&#x62;&#64;&#x67;&#109;&#97;&#105;&#108;&#46;&#x63;&#111;&#109;</a>&gt;</p>
<h2 id="REPORTING-BUGS">REPORTING BUGS</h2>
@ -161,7 +174,7 @@ $ git effort --after="one year ago" --above 5 --author="Leila Muhtasib"
<ol class='man-decor man-foot man foot'>
<li class='tl'></li>
<li class='tc'>August 2015</li>
<li class='tc'>September 2015</li>
<li class='tr'>git-effort(1)</li>
</ol>

View file

@ -3,7 +3,7 @@ git-effort(1) -- Show effort statistics on file(s)
## SYNOPSIS
`git-effort` [--above &lt;value&gt;] [&lt;options&gt;] [[--] &lt;path&gt;...]
`git-effort` [--above &lt;value&gt;] [&lt;path&gt;...] [-- [&lt;log options&gt;...]]
## DESCRIPTION
@ -19,16 +19,19 @@ git-effort(1) -- Show effort statistics on file(s)
Ignore files with commits &lt;= a value.
Run
man -P 'less +/Commit\ Limiting' git-log
to read about options to limit which commits are counted.
Note: `git-effort` does not accept commit ranges.
[--] &lt;path&gt;...
&lt;path&gt;...
Only count commits that touches the given paths.
Note: `git-effort` does not accept revision ranges, but the underlying `git log` does (See the examples).
&lt;log options&gt;...
Options for `git log`. Note that you must use `--` to separate options to `git log`
from options to `git effort`.
This makes it possible to only count commits you are interested in.
Not all options are relevant in the context of `git-effort`, but those that are is listed under the "Commit Limiting" section on the `git-log` manpages.
## EXAMPLES
Note: Output will first appear unsorted, then the screen is cleared and the sorted
@ -51,7 +54,7 @@ git-effort(1) -- Show effort statistics on file(s)
git-repl 7 5
$ git effort --after="one year ago" --above 5 --author="Leila Muhtasib"
$ git effort --above 5 bin/* -- --after="one year ago" --author="Leila Muhtasib"
file commits active days
@ -62,14 +65,23 @@ git-effort(1) -- Show effort statistics on file(s)
git-changelog 3 2
git-graft 2 2
Showing statistics on directories is also possible
Showing statistics on directories is also possible:
$ git effort bin man
$ git effort bin man -- --after="one year ago"
file commits active days
bin.......................................... 406 232
man.......................................... 118 80
bin.......................................... 406 232
man.......................................... 118 80
Only count commits in the specified revision range:
$ git effort -- master..feature
file commits active days
bin/git-effort............................... 3 2
man/git-effort.md............................ 1 1
## AUTHOR