Author: stefanct
Date: Thu Aug 29 02:38:14 2013
New Revision: 1727
URL: http://flashrom.org/trac/flashrom/changeset/1727

Log:
Improve getrevision.sh.

 - remove bashism.
 - simplify some git-related code.
 - improved parameter and error handling.
 - additional -d/--date action which is similar to the timestamp action.
 - support for an optional path parameter.
 - there is only one sane time format.
 - and only one sane date format too.
 - use UTC dates and times only.
 - vastly improve git_url() to print the correct remote url and
   "nearest" branch.
 - remove username from repository URLs.
 - 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".
 - make retrieving the upstream revision work even in cloned git-svn
   repositories.
 - more abstractions and helper functions.
 - less fragmentation of actual functionality.

Signed-off-by: Stefan Tauner <[email protected]>
Acked-by: Stefan Tauner <[email protected]>

Modified:
   trunk/Makefile
   trunk/util/getrevision.sh

Modified: trunk/Makefile
==============================================================================
--- trunk/Makefile      Wed Aug 28 11:55:04 2013        (r1726)
+++ trunk/Makefile      Thu Aug 29 02:38:14 2013        (r1727)
@@ -333,14 +333,13 @@
 
 CLI_OBJS = cli_classic.o cli_output.o print.o
 
-# Set the flashrom version string from the highest revision number
-# of the checked out flashrom files.
+# Set the flashrom version string from the highest revision number of the 
checked out flashrom files.
 # Note to packagers: Any tree exported with "make export" or "make tarball"
 # will not require subversion. The downloadable snapshots are already exported.
 SVNVERSION := $(shell ./util/getrevision.sh -u)
 
 RELEASE := 0.9.7
-VERSION := $(RELEASE)-r$(SVNVERSION)
+VERSION := $(RELEASE)-$(SVNVERSION)
 RELEASENAME ?= $(VERSION)
 
 SVNDEF := -D'FLASHROM_VERSION="$(VERSION)"'

Modified: trunk/util/getrevision.sh
==============================================================================
--- trunk/util/getrevision.sh   Wed Aug 28 11:55:04 2013        (r1726)
+++ trunk/util/getrevision.sh   Thu Aug 29 02:38:14 2013        (r1727)
@@ -1,10 +1,11 @@
-#!/bin/bash
+#!/bin/sh
 #
 # This file is part of the flashrom project.
 #
 # Copyright (C) 2005 coresystems GmbH <[email protected]>
 # 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
@@ -26,205 +27,257 @@
 
 # Make sure we don't get translated output
 export LC_ALL=C
+# nor local times or dates
+export TZ=UTC0
 
-svn_revision() {
-       svnversion -cn . 2>/dev/null | \
-               sed -e "s/.*://" -e "s/\([0-9]*\).*/\1/" | \
-               grep "[0-9]" ||
-       svn info . 2>/dev/null | \
-               awk '/^Revision:/ {print $$2 }' | \
-               grep "[0-9]" ||
-       git svn info . 2>/dev/null | \
-               awk '/^Revision:/ {print $$2 }' | \
-               grep "[0-9]" ||
-       echo ''
-}
-
-svn_url() {
-       echo $(svn info 2>/dev/null |
-              grep URL: |
-                  sed 's/.*URL:[[:blank:]]*//' |
-                  grep ^.
-             )
-}
-
-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} +")
-       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")
-       fi
-
-       echo "${timestamp}"
+# Helper functions
+# First argument is the path to inspect (usually optional; w/o it the whole 
repository will be considered)
+svn_has_local_changes() {
+       svn status "$1" | egrep '^ *[ADMR] *' >/dev/null
 }
 
-git_revision() {
-       echo $(git log --oneline | head -1 | awk '{print $1}')
+git_has_local_changes() {
+       git update-index -q --refresh >/dev/null
+       ! git diff-index --quiet HEAD -- "$1"
 }
 
-# Retrieve svn revision using git log data (for git mirrors)
-gitsvn_revision() {
-       local r
+git_last_commit() {
+       git log --pretty=format:"%h" -1 -- "$1"
+}
 
-       git log|
-               grep git-svn-id|
-               sed 
's/.*git-svn-id:[[:blank:]]*\([^@]\+\)@[0-9]\+[[:blank:]]\+\([^[:blank:]]\+\)/\1
 \2/'|
-               sort|
-               uniq|
-               read url uuid
+svn_is_file_tracked() {
+       svn info "$1" >/dev/null 2>&1
+}
 
-       r=$(git log --grep="git-svn-id.*$uuid"| grep git-svn-id | \
-               sed 's/.*@//;s/[[:blank:]].*//'| \
-               sort -n | \
-               tail -1)
+git_is_file_tracked() {
+       git ls-files --error-unmatch -- "$1" >/dev/null 2>&1
+}
 
-       echo "${r}"
+is_file_tracked() {
+       svn_is_file_tracked "$1" || git_is_file_tracked "$1"
 }
 
-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} +")
-       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")
+# Tries to find a remote source for the changes committed locally.
+# This includes the URL of the remote repository including the last commit and 
a suitable branch name.
+# Takes one optional argument: the path to inspect
+git_url() {
+       last_commit=$(git_last_commit "$1")
+       # get all remote branches containing the last commit (excluding 
origin/HEAD and git-svn branches/tags)
+       branches=$(git branch -r --contains $last_commit | sed 
'/\//!d;/.*->.*/d;s/[\t ]*//')
+       if [ -z "$branches" ] ; then
+               echo "No remote branch contains a suitable commit">&2
+               return
        fi
 
-       echo "${timestamp}"
-}
+       # find "nearest" branch
+       local mindiff=9000
+       local target=
+       for branch in $branches ; do
+               curdiff=$(git rev-list --count $last_commit..$branch)
+               if [ $curdiff -ge $mindiff ] ; then
+                       continue
+               fi
+               mindiff=$curdiff
+               target=$branch
+       done
 
-git_url() {
-       # Only the first line of `git remote' is considered.
-       echo $(git remote show origin 2>/dev/null |
-              grep 'Fetch URL:' |
-              sed 's/.*URL:[[:blank:]]*//' |
-              grep ^.
-             )
+       echo "$(git ls-remote --exit-code --get-url ${target%/*}) ${target#*/}"
 }
 
+# Returns a string indicating where others can get the current source code 
(excluding uncommitted changes)
+# Takes one optional argument: the path to inspect
 scm_url() {
-       local url
+       local url=
 
-       if [ -d ".svn" ] ; then
-               url=$(svn_url)
-       elif [ -d ".git" ] ; then
-               url=$(git_url)
+       # for a primitive VCS like subversion finding the URL is easy: there is 
only one upstream host
+       if svn_is_file_tracked "$1" ; then
+               url="$(svn info "$1" 2>/dev/null |
+                      grep URL: |
+                      sed 's/.*URL:[[:blank:]]*//;s/:\/\/.*@/:\/\//' |
+                      grep ^.)"
+       elif git_is_file_tracked "$1" ; then
+               url="$(git_url "$1")"
+       else
+               return ${EXIT_FAILURE}
        fi
 
        echo "${url}"
 }
 
 # Retrieve timestamp since last modification. If the sources are pristine,
-# then the timestamp will match that of the SCM's more recent modification
+# then the timestamp will match that of the SCM's most recent modification
 # date.
 timestamp() {
        local t
 
-       if [ -d ".svn" ] ; then
-               t=$(svn_timestamp)
-       elif [ -d ".git" ] ; then
-               t=$(git_timestamp)
+       if svn_is_file_tracked "$2" ; then
+               if svn_has_local_changes "$2"; then
+                       t=$(date -u "$1")
+               else
+                       # No local changes, get date of the last log record.
+                       local last_commit_date="$(svn info "$2" | \
+                                                 grep '^Last Changed Date:' | \
+                                                 awk '{print $4" "$5" "$6}')"
+                       t=$(date -d "${last_commit_date}" -u "$1")
+               fi
+       elif git_is_file_tracked "$2" ; then
+               # are there local changes?
+               if git_has_local_changes "$2" ; then
+                       t=$(date -u "${1}")
+               else
+                       # No local changes, get date of the last commit
+                       t=$(date -d "$(git log --pretty=format:"%cD" -1 -- 
"$2")" -u "$1")
+               fi
+       else
+               t=$(date -u "$1")
        fi
 
-       echo ${t}
+       echo "${t}"
 }
 
-# Retrieve local SCM revision info. This is useful if we're working in
-# a even different SCM than upstream.
-#
-# If local copy is svn, then there is nothing to do here.
-# If local copy is git, then retrieve useful git revision info
+# Retrieve local SCM revision info. This is useful if we're working in a 
different SCM than upstream and/or
+# have local changes.
 local_revision() {
-       local r
+       local r=
 
-       if [ -d ".git" ] ; then
-               r=$(git_revision)
+       if svn_is_file_tracked "$1" ; then
+               r=$(svn_has_local_changes "$1" && echo "dirty")
+       elif git_is_file_tracked "$1" ; then
+               r=$(git_last_commit "$1")
+
+               local svn_base=$(git log --grep git-svn-id -1 --format='%h')
+               if [ "$svn_base" != "" ] ; then
+                       local diff_to_svn=$(git rev-list --count 
${svn_base}..${r})
+                       if [ "$diff_to_svn" -gt 0 ] ; then
+                               r="$r-$diff_to_svn"
+                       fi
+               fi
+
+               if git_has_local_changes "$1" ; then
+                       r="$r-dirty"
+               fi
+       else
+               return ${EXIT_FAILURE}
        fi
 
-       echo ${r}
+       echo "${r}"
 }
 
 # Get the upstream flashrom revision stored in SVN metadata.
-#
-# If the local copy is svn, then use svnversion
-# If the local copy is git, then scrape upstream revision from git logs
 upstream_revision() {
-       local r
+       local r=
 
-       if [ -d ".svn" ] ; then
-               r=$(svn_revision)
-       elif [ -d ".git" ] ; then
-               r=$(gitsvn_revision)
+       if svn_is_file_tracked "$1" ; then
+               r=$(svn info "$1" 2>/dev/null | \
+                   grep "Last Changed Rev:" | \
+                   sed -e "s/^Last Changed Rev: *//" -e "s/\([0-9]*\).*/r\1/" 
| \
+                   grep "r[0-9]")
+       elif git_is_file_tracked "$1" ; then
+               # If this is a "native" git-svn clone we could use git svn log:
+               # git svn log --oneline -1 | sed 's/^r//;s/[[:blank:]].*//' or 
even git svn find-rev
+               # but it is easier to just grep for the git-svn-id 
unconditionally
+               r=$(git log --grep git-svn-id -1 -- "$1" | \
+                   grep git-svn-id | \
+                   sed 's/.*@/r/;s/[[:blank:]].*//')
        fi
 
+       if [ -z "$r" ]; then
+               r="unknown" # default to unknown
+       fi
        echo "${r}"
 }
 
 show_help() {
        echo "Usage:
-       ${0} <option>
+       ${0} <command> [path]
 
-Options
+Commands
     -h or --help
-        Display this message.
-    -u or --upstream
-        upstream flashrom revision
+        this message
     -l or --local
-        local revision (if different from upstream)
+        local revision information including an indicator for uncommitted 
changes
+    -u or --upstream
+        upstream revision
+    -U or --url
+        URL associated with the latest commit
+    -d or --date
+        date of most recent modification
     -t or --timestamp
         timestamp of most recent modification
-    -U or --url
-        url associated with local copy of flashrom
-       "
+"
        return
 }
 
-if [ ! -n "${1}" ]
-then
-       show_help;
-       echo "No options specified";
-       exit ${EXIT_SUCCESS}
-fi
-
-# The is the main loop
-while [[ ${1} = -* ]];
-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)";
-               shift;;
-       -U|--url)
-               echo "$(scm_url)";
-               shift;;
-       *)
-               show_help;
-               echo "invalid option: ${1}"
+check_action() {
+       if [ -n "$action" ]; then
+               echo "Error: Multiple actions given.">&2
                exit ${EXIT_FAILURE}
-       esac;
-done
+       fi
+}
+
+main() {
+       local query_path=
+       local action=
+
+       # The is the main loop
+       while [ $# -gt 0 ];
+       do
+               case ${1} in
+               -h|--help)
+                       action=show_help;
+                       shift;;
+               -l|--local)
+                       check_action $1
+                       action=local_revision
+                       shift;;
+               -u|--upstream)
+                       check_action $1
+                       action=upstream_revision
+                       shift;;
+               -U|--url)
+                       check_action $1
+                       action=scm_url
+                       shift;;
+               -d|--date)
+                       check_action $1
+                       action="timestamp +%Y-%m-%d" # refrain from suffixing 
'Z' to indicate it's UTC
+                       shift;;
+               -t|--timestamp)
+                       check_action $1
+                       action="timestamp +%Y-%m-%dT%H:%M:%SZ" # There is only 
one valid time format! ISO 8601
+                       shift;;
+               -*)
+                       show_help;
+                       echo "Error: Invalid option: ${1}"
+                       exit ${EXIT_FAILURE};;
+               *)
+                       if [ -z "$query_path" ] ; then
+                               if [ ! -e "$1" ] ; then
+                                       echo "Error: Path \"${1}\" does not 
exist.">&2
+                                       exit ${EXIT_FAILURE}
+                               fi
+                               query_path=$1
+                       else
+                               echo "Warning: Ignoring over-abundant paramter: 
\"${1}\"">&2
+                       fi
+                       shift;;
+               esac;
+       done
+
+       # default to current directory (usually equals the whole repository)
+       if [ -z "$query_path" ] ; then
+               query_path=.
+       fi
+       if ! is_file_tracked "$query_path" ; then
+               echo "Warning: Path \"${query_path}\" is not under version 
control.">&2
+       fi
+       if [ -z "$action" ] ; then
+               show_help
+               echo "Error: No actions specified"
+               exit ${EXIT_FAILURE}
+       fi
+
+       $action "$query_path"
+}
 
-exit ${EXIT_SUCCESS}
+main $@

_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to