1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-26 22:52:34 +02:00

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.

Corresponding to flashrom svn r1727.

Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
This commit is contained in:
Stefan Tauner 2013-08-29 00:38:14 +00:00
parent 8e19b0414c
commit ec7a35f7ec
2 changed files with 205 additions and 153 deletions

View File

@ -333,14 +333,13 @@ LIB_OBJS = layout.o flashrom.o udelay.o programmer.o
CLI_OBJS = cli_classic.o cli_output.o print.o CLI_OBJS = cli_classic.o cli_output.o print.o
# Set the flashrom version string from the highest revision number # Set the flashrom version string from the highest revision number of the checked out flashrom files.
# of the checked out flashrom files.
# Note to packagers: Any tree exported with "make export" or "make tarball" # Note to packagers: Any tree exported with "make export" or "make tarball"
# will not require subversion. The downloadable snapshots are already exported. # will not require subversion. The downloadable snapshots are already exported.
SVNVERSION := $(shell ./util/getrevision.sh -u) SVNVERSION := $(shell ./util/getrevision.sh -u)
RELEASE := 0.9.7 RELEASE := 0.9.7
VERSION := $(RELEASE)-r$(SVNVERSION) VERSION := $(RELEASE)-$(SVNVERSION)
RELEASENAME ?= $(VERSION) RELEASENAME ?= $(VERSION)
SVNDEF := -D'FLASHROM_VERSION="$(VERSION)"' SVNDEF := -D'FLASHROM_VERSION="$(VERSION)"'

View File

@ -1,10 +1,11 @@
#!/bin/bash #!/bin/sh
# #
# This file is part of the flashrom project. # This file is part of the flashrom project.
# #
# Copyright (C) 2005 coresystems GmbH <stepan@coresystems.de> # Copyright (C) 2005 coresystems GmbH <stepan@coresystems.de>
# Copyright (C) 2009,2010 Carl-Daniel Hailfinger # Copyright (C) 2009,2010 Carl-Daniel Hailfinger
# Copyright (C) 2010 Chromium OS Authors # Copyright (C) 2010 Chromium OS Authors
# Copyright (C) 2013 Stefan Tauner
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -26,205 +27,257 @@ EXIT_FAILURE=1
# Make sure we don't get translated output # Make sure we don't get translated output
export LC_ALL=C export LC_ALL=C
# nor local times or dates
export TZ=UTC0
svn_revision() { # Helper functions
svnversion -cn . 2>/dev/null | \ # First argument is the path to inspect (usually optional; w/o it the whole repository will be considered)
sed -e "s/.*://" -e "s/\([0-9]*\).*/\1/" | \ svn_has_local_changes() {
grep "[0-9]" || svn status "$1" | egrep '^ *[ADMR] *' >/dev/null
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() { git_has_local_changes() {
echo $(svn info 2>/dev/null | git update-index -q --refresh >/dev/null
grep URL: | ! git diff-index --quiet HEAD -- "$1"
sed 's/.*URL:[[:blank:]]*//' |
grep ^.
)
} }
svn_timestamp() { git_last_commit() {
local date_format="+%Y-%m-%d %H:%M:%S" git log --pretty=format:"%h" -1 -- "$1"
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}"
} }
git_revision() { svn_is_file_tracked() {
echo $(git log --oneline | head -1 | awk '{print $1}') svn info "$1" >/dev/null 2>&1
} }
# Retrieve svn revision using git log data (for git mirrors) git_is_file_tracked() {
gitsvn_revision() { git ls-files --error-unmatch -- "$1" >/dev/null 2>&1
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)
echo "${r}"
} }
git_timestamp() { is_file_tracked() {
local date_format="+%b %d %Y %H:%M:%S" svn_is_file_tracked "$1" || git_is_file_tracked "$1"
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")
fi
echo "${timestamp}"
} }
# 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() { git_url() {
# Only the first line of `git remote' is considered. last_commit=$(git_last_commit "$1")
echo $(git remote show origin 2>/dev/null | # get all remote branches containing the last commit (excluding origin/HEAD and git-svn branches/tags)
grep 'Fetch URL:' | branches=$(git branch -r --contains $last_commit | sed '/\//!d;/.*->.*/d;s/[\t ]*//')
sed 's/.*URL:[[:blank:]]*//' | if [ -z "$branches" ] ; then
grep ^. echo "No remote branch contains a suitable commit">&2
) return
fi
# 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
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() { scm_url() {
local url local url=
if [ -d ".svn" ] ; then # for a primitive VCS like subversion finding the URL is easy: there is only one upstream host
url=$(svn_url) if svn_is_file_tracked "$1" ; then
elif [ -d ".git" ] ; then url="$(svn info "$1" 2>/dev/null |
url=$(git_url) grep URL: |
sed 's/.*URL:[[:blank:]]*//;s/:\/\/.*@/:\/\//' |
grep ^.)"
elif git_is_file_tracked "$1" ; then
url="$(git_url "$1")"
else
return ${EXIT_FAILURE}
fi fi
echo "${url}" echo "${url}"
} }
# Retrieve timestamp since last modification. If the sources are pristine, # 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. # date.
timestamp() { timestamp() {
local t local t
if [ -d ".svn" ] ; then if svn_is_file_tracked "$2" ; then
t=$(svn_timestamp) if svn_has_local_changes "$2"; then
elif [ -d ".git" ] ; then t=$(date -u "$1")
t=$(git_timestamp) 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 fi
echo ${t} echo "${t}"
} }
# Retrieve local SCM revision info. This is useful if we're working in # Retrieve local SCM revision info. This is useful if we're working in a different SCM than upstream and/or
# a even different SCM than upstream. # 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_revision() {
local r local r=
if [ -d ".git" ] ; then if svn_is_file_tracked "$1" ; then
r=$(git_revision) r=$(svn_has_local_changes "$1" && echo "dirty")
fi elif git_is_file_tracked "$1" ; then
r=$(git_last_commit "$1")
echo ${r} 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
# Get the upstream flashrom revision stored in SVN metadata. if git_has_local_changes "$1" ; then
# r="$r-dirty"
# If the local copy is svn, then use svnversion fi
# If the local copy is git, then scrape upstream revision from git logs else
upstream_revision() { return ${EXIT_FAILURE}
local r
if [ -d ".svn" ] ; then
r=$(svn_revision)
elif [ -d ".git" ] ; then
r=$(gitsvn_revision)
fi fi
echo "${r}" echo "${r}"
} }
# Get the upstream flashrom revision stored in SVN metadata.
upstream_revision() {
local r=
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() { show_help() {
echo "Usage: echo "Usage:
${0} <option> ${0} <command> [path]
Options Commands
-h or --help -h or --help
Display this message. this message
-u or --upstream
upstream flashrom revision
-l or --local -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 -t or --timestamp
timestamp of most recent modification timestamp of most recent modification
-U or --url "
url associated with local copy of flashrom
"
return return
} }
if [ ! -n "${1}" ] check_action() {
then if [ -n "$action" ]; then
show_help; echo "Error: Multiple actions given.">&2
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}"
exit ${EXIT_FAILURE} exit ${EXIT_FAILURE}
esac; fi
done }
exit ${EXIT_SUCCESS} 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"
}
main $@