Overall this is great! I definitely think it's easier to read, test, and maintain than the Makefile approach. But I suppose we'll find out how others feel...

On Tue, Aug 6, 2013 at 6:51 PM, Stefan Tauner <stefan.tauner@student.tuwien.ac.at> wrote:
 - remove bashism
 - simplify some git-related code
 - there is only one sane time format.
 - vastly improve git_url() to print the correct remote url and
   "nearest" branch
 - add "-dirty" to local revisions if there are uncommitted changes
 - indicate in local revisions how many git-only commits were done
   since branching from upstream svn
 - fix svn_revision() fallback to svn info and remove git-svn
 - print leading r in script instead of hardcode it in the makefile;
   no more "0.9.7-runknown"

Signed-off-by: Stefan Tauner <stefan.tauner@student.tuwien.ac.at>
---
 Makefile            |   2 +-
 util/getrevision.sh | 156 +++++++++++++++++++++++++++++-----------------------
 2 files changed, 89 insertions(+), 69 deletions(-)

diff --git a/Makefile b/Makefile
index da0d0da..e1a4474 100644
--- a/Makefile
+++ b/Makefile
@@ -329,7 +329,7 @@ CLI_OBJS = cli_classic.o cli_output.o print.o
 SVNVERSION := $(shell ./util/getrevision.sh -u)

 RELEASE := 0.9.6.1
-VERSION := $(RELEASE)-r$(SVNVERSION)
+VERSION := $(RELEASE)-$(SVNVERSION)
 RELEASENAME ?= $(VERSION)

 SVNDEF := -D'FLASHROM_VERSION="$(VERSION)"'
diff --git a/util/getrevision.sh b/util/getrevision.sh
index 678d66b..95a57fe 100755
--- a/util/getrevision.sh
+++ b/util/getrevision.sh
@@ -5,6 +5,7 @@
 # Copyright (C) 2005 coresystems GmbH <stepan@coresystems.de>
 # Copyright (C) 2009,2010 Carl-Daniel Hailfinger
 # Copyright (C) 2010 Chromium OS Authors
+# Copyright (C) 2013 Stefan Tauner
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -23,18 +24,17 @@

 EXIT_SUCCESS=0
 EXIT_FAILURE=1
+date_format="+%Y-%m-%dT%H:%M:%S%z" # There is only one valid timeformat FFS! ISO 8601

 svn_revision() {
        LC_ALL=C svnversion -cn . 2>/dev/null | \
-               sed -e "s/.*://" -e "s/\([0-9]*\).*/\1/" | \
-               grep "[0-9]" ||
+               sed -e "s/.*://" -e "s/\([0-9]*\).*/r\1/" | \
+               grep "r[0-9]" ||
        LC_ALL=C svn info . 2>/dev/null | \
-               awk '/^Revision:/ {print $$2 }' | \
-               grep "[0-9]" ||
-       LC_ALL=C git svn info . 2>/dev/null | \
-               awk '/^Revision:/ {print $$2 }' | \
-               grep "[0-9]" ||
-       echo ''
+               grep "Last Changed Rev:" | \
+               sed -e "s/^Last Changed Rev: *//" -e "s/\([0-9]*\).*/r\1/" | \
+               grep "r[0-9]" ||
+       echo "unknown"
 }

 svn_url() {
@@ -45,74 +45,81 @@ svn_url() {
              )
 }

+svn_has_local_changes() {
+       svn status | egrep '^ *[ADMR] *' > /dev/null
+}
+
 svn_timestamp() {
-       local date_format="+%Y-%m-%d %H:%M:%S"
        local timestamp

-       # are there local changes in the client?
-       if svn status | egrep '^ *[ADMR] *' > /dev/null ; then
-               timestamp=$(date "${date_format} +")
+       if svn_has_local_changes ; then
+               timestamp=$(date "${date_format}")
        else
                # No local changes, get date of the last log record.
                local last_commit_date=$(svn info | grep '^Last Changed Date:' | \
                                         awk '{print $4" "$5" "$6}')
-               timestamp=$(date --utc --date "${last_commit_date}" \
-                               "${date_format} UTC")
+               timestamp=$(date -d "${last_commit_date}" "${date_format}")
        fi

        echo "${timestamp}"
 }

-git_revision() {
-       echo $(git log --oneline | head -1 | awk '{print $1}')
-}
-
-# Retrieve svn revision using git log data (for git mirrors)
+# Retrieve svn revision using git log data (for git-svn mirrors)
 gitsvn_revision() {
        local r

-       git log|
-               grep git-svn-id|
-               sed 's/.*git-svn-id:[[:blank:]]*\([^@]\+\)@[0-9]\+[[:blank:]]\+\([^[:blank:]]\+\)/\1 \2/'|
-               sort|
-               uniq|
-               read url uuid
-
-       r=$(git log --grep="git-svn-id.*$uuid"| grep git-svn-id | \
-               sed 's/.*@//;s/[[:blank:]].*//'| \
-               sort -n | \
-               tail -1)
+       # If this is a "native" git-svn clone we could use git svn log like so
+       # if [ -e .git/svn/.metadata ]; then
+       #       r=$(git svn log --oneline -1 | sed 's/^r//;s/[[:blank:]].*//')
+       # else
+               r=$(git log --grep git-svn-id -1 | \
+                       grep git-svn-id | \
+                       sed 's/.*@/r/;s/[[:blank:]].*//')
+       # fi

        echo "${r}"
 }

+git_has_local_changes() {
+       git update-index -q --refresh
+       ! git diff-index --quiet HEAD --
+}
+
 git_timestamp() {
-       local date_format="+%b %d %Y %H:%M:%S"
        local timestamp

-       # are there local changes in the client?
-       if git status | \
-          egrep '^# Change(s to be committed|d but not updated):$' > /dev/null
-       then
-               timestamp=$(date "${date_format} +")
+       # are there local changes?
+       if git_has_local_changes ; then
+               timestamp=$(date "${date_format}")
        else
-               # No local changes, get date of the last log record.
-               local last_commit_date=$(git log | head -3 | grep '^Date:' | \
-                                        awk '{print $3" "$4" "$6" "$5" "$7}')
-               timestamp=$(date --utc --date "${last_commit_date}" \
-                           "${date_format} UTC")
+               # No local changes, get date of the last commit
+               timestamp=$(date -d "$(git log --pretty=format:"%cD" -1)" "${date_format}")
        fi

        echo "${timestamp}"
 }

 git_url() {
-       # Only the first line of `git remote' is considered.
-       echo $(LC_ALL=C git remote show origin 2>/dev/null |
-              grep 'Fetch URL:' |
-              sed 's/.*URL:[[:blank:]]*//' |
-              grep ^.
-             )
+       # get all remote branches containing the last commit
+       branches=$(git branch -r --contains HEAD | cut -c 3-)
+       if [ -z "$branches" ] ; then
+               echo "No remote branch contains current HEAD">&2
+               return
+       fi
+
+       # find "nearest" branch
+       local diff=9000
+       local target=
+       for branch in $branches ; do
+               curdiff=$(git rev-list --count HEAD..$branch)
+               if [ $curdiff -ge $diff ] ; then
+                       continue
+               fi
+               diff=$curdiff
+               target=$branch
+       done
+
+       echo "$(git ls-remote --exit-code --get-url ${target%/*}) ${target#*/}"
 }

I am seeing a lot of errors when trying this. The version in the previous patch worked, though it kept the http:// prefix which is kind of superfluous.

Try cloning http://git.chromium.org/chromiumos/third_party/flashrom.git

$ sh getrevision.sh -U
fatal: ambiguous argument 'HEAD..->': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
getrevision.sh: line 115: [: -ge: unary operator expected
getrevision.sh: line 115: [: 0: unary operator expected
http://git.chromium.org/chromiumos/third_party/flashrom.git master

What about something like:
git ls-remote --exit-code --get-url | sed 's/.*\/\///'

That looks simpler and works better, at least in my testing...

 

 scm_url() {
@@ -142,16 +149,26 @@ timestamp() {
        echo ${t}
 }

-# Retrieve local SCM revision info. This is useful if we're working in
-# a even different SCM than upstream.
+
+# Retrieve local SCM revision info. This is useful if we're working in a different SCM than upstream and/or
+# have local changes.
 #
-# If local copy is svn, then there is nothing to do here.
-# If local copy is git, then retrieve useful git revision info
 local_revision() {
        local r

-       if [ -d ".git" ] ; then
-               r=$(git_revision)
+       if [ -d ".svn" ] ; then
+               r=$(svn_has_local_changes && echo "-dirty")
+       elif [ -d ".git" ] ; then
+               r=$(git rev-parse --short HEAD)
+
+               local svn_base=$(git log --grep git-svn-id -1 --format='%h')
+               if [ "$svn_base" != "" ] ; then
+                       r="$r-$(git rev-list --count $svn_base..HEAD)"
+               fi
+
+               if git_has_local_changes ; then
+                       r="$r-dirty"
+               fi
        fi

        echo ${r}
@@ -168,6 +185,8 @@ upstream_revision() {
                r=$(svn_revision)
        elif [ -d ".git" ] ; then
                r=$(gitsvn_revision)
+       else
+               r="unknown"
        fi

        echo "${r}"
@@ -180,48 +199,49 @@ show_help() {
 Options
     -h or --help
         Display this message.
+    -l or --local
+        local revision (if different from upstream) and an indicator for uncommitted changes
     -u or --upstream
         upstream flashrom revision
-    -l or --local
-        local revision (if different from upstream)
-    -t or --timestamp
-        timestamp of most recent modification
     -U or --url
         url associated with local copy of flashrom
+    -t or --timestamp
+        timestamp of most recent modification
        "
        return
 }

-if [ ! -n "${1}" ]
-then
+if [ -z "${1}" ] ; then
        show_help;
        echo "No options specified";
-       exit ${EXIT_SUCCESS}
+       exit ${EXIT_FAILURE}
 fi

 # The is the main loop
-while [[ ${1} = -* ]];
+while [ $# -gt 0 ];
 do
        case ${1} in
        -h|--help)
                show_help;
                shift;;
-       -u|--upstream)
-               echo "$(upstream_revision)";
-               shift;;
        -l|--local)
                echo "$(local_revision)";
                shift;;
-       -t|--timestamp)
-               echo "$(timestamp)";
+       -u|--upstream)
+               echo "$(upstream_revision)";
                shift;;
        -U|--url)
                echo "$(scm_url)";
                shift;;
-       *)
+       -t|--timestamp)
+               echo "$(timestamp)";
+               shift;;
+       -*)
                show_help;
                echo "invalid option: ${1}"
-               exit ${EXIT_FAILURE}
+               exit ${EXIT_FAILURE};;
+       *)
+               shift;; # ignore arguments not starting with -
        esac;
 done

--
Kind regards, Stefan Tauner


_______________________________________________
flashrom mailing list
flashrom@flashrom.org
http://www.flashrom.org/mailman/listinfo/flashrom



--
David Hendricks (dhendrix)
Systems Software Engineer, Google Inc.