David Hendricks has uploaded this change for review. ( https://review.coreboot.org/20263
Change subject: util/getrevision.sh: Change version string ......................................................................
util/getrevision.sh: Change version string
Previously, we included the last stable version according to a hard- coded string in the Makefile and appended the subversion revision number.
With this patch the version string includes the last reachable git tag, number of commits since said tag in the upstream branches (if any), the name of said upstream branch, number of commits since that branch (if any), and the shortened git hash. In case there are uncommitted changes a "-dirty" indicator is also added. The case of unknown versions is explicitly handled in getrevision instead of simply appending "-unknown" to a hardcoded release number.
The version information is either taken from an existing git remote pointing to an upstream repository (or a known mirror), or if that is not available - with the user's consent - a shadow copy is fetched from the upstream repo that is updated on every build (usually takes less than a second).
In the following some examples of the version string changes are shown. Basically we print the distance to the last known upstream tag, which comprises any upstream commits since that tag as well as local commits on top of that. Additionally we handle upstream's stable and staging branches specially.
Old output: flashrom v0.9.7-r1716 on Linux 3.8.0-6-generic (x86_64)
New output variants:
Build of the 0.9.99 release without any changes: flashrom v0.9.99-e4f6643 on Linux 3.13.0-76-generic (x86_64)
5 commits since last tag in upstream's stable branch: flashrom v0.9.99-5-stable-e4f6643-dirty on Linux 3.13.0-76-generic (x86_64)
3 commits since last tag in upstream's staging branch and 4 local commits on top of that: flashrom v0.9.99-3-staging-4-e4f6643 on Linux 3.13.0-76-generic (x86_64)
3 commits since last tag in upstream's staging branch and 4 local commits on top of that, and some local uncommitted changes too: flashrom v0.9.99-3-staging-4-e4f6643-dirty on Linux 3.13.0-76-generic (x86_64)
3 commits since the last tag in an unrelated upstream branch (e.g., a stable release *branch* such as 0.9.99.x) or local branch: flashrom v0.9.99-3-e4f6643 on Linux 3.13.0-76-generic (x86_64)
No tags reachable from current commit (generic git fallback): flashrom d95935a version on Linux 3.13.0-76-generic (x86_64)
Not in a repository: flashrom unknown version on Linux 3.13.0-76-generic (x86_64)
Change-Id: Id6de60be4c751c070d4da648825a7e7b70e4a759 Signed-off-by: Stefan Tauner stefan.tauner@alumni.tuwien.ac.at Signed-off-by: David Hendricks dhendricks@fb.com --- M Makefile M util/getrevision.sh 2 files changed, 182 insertions(+), 44 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/63/20263/1
diff --git a/Makefile b/Makefile index cf3cfe8..c28fd73 100644 --- a/Makefile +++ b/Makefile @@ -534,7 +534,7 @@ VERSION ?= unknown MAN_DATE ?= unknown else -VERSION ?= $(shell ./util/getrevision.sh --local) +VERSION ?= $(shell ./util/getrevision.sh --revision) MAN_DATE ?= $(shell ./util/getrevision.sh -d $(PROGRAM).8.tmpl 2>/dev/null) # This is also a convenient time to install hooks. $(shell ./util/git-hooks/install.sh) diff --git a/util/getrevision.sh b/util/getrevision.sh index 8816879..d7960d8 100755 --- a/util/getrevision.sh +++ b/util/getrevision.sh @@ -30,6 +30,77 @@ # nor local times or dates export TZ=UTC0
+# List of important upstream branches... +upstream_branches="stable staging" +upstream_url="https://flashrom.org/git/flashrom.git" +upstream_patterns="github.com.flashrom/flashrom(.git)?|flashrom.org.git/flashrom(.git)?" + +# Generate upcache_refs +upcache_refs="" +upcache_prefix="refs/flashrom_org/" +for b in $upstream_branches ; do + upcache_refs="$upcache_refs ${upcache_prefix}$b" +done + +# We need to update our upstream information sometimes so that we can +# create detailed version information. To that end the code below +# fetches parts of the upstream repository via https. This takes about +# one second or less under normal circumstances. +# +# It can be called manually, but is usually called via the Makefile +# (implicitly via revision()) when there is no upstream information +# in any existing remote. +force_update_upcache() { + local rev_remote_refs + for ref in $upcache_refs ; do + rev_remote_refs="$rev_remote_refs +${ref##*/}:$ref" + done + git fetch -q "$upstream_url" --tags $rev_remote_refs && echo "Success." +} + +update_upcache() { + offline=$(git config flashrom.offline-builds 2>/dev/null) + if [ -z "$offline" ]; then + echo "\ +To produce useful version information the build process needs access +to the commit history from an upstream repository. If no git remote +is pointing to one we can store the necessary information out of +sight and update it on every build. + +To enable this functionality and fetch the upstream commits from + ${upstream_url} +please execute the following: + git config flashrom.offline-builds false + +Alternatively, add one of the upstream repositories as a git remote +to rely on that information. + +If you want to work completely offline and generate possibly +meaningless version strings then disable it using: + git config flashrom.offline-builds true + +You can force updating the local commit cache using: + $0 --force-update-upcache" >&2 + return 1 + elif [ "x$offline" = "xfalse" ]; then + echo "\ +Fetching commit history from upstream repository: + ${upstream_url} + +To disable any network activity execute: + git config flashrom.offline-builds true" >&2 + force_update_upcache >/dev/null + else + echo "\ +Fetching commit history from upstream is disabled - version +strings might be misleading. + +To ensure proper version strings and allow network access execute: + git config flashrom.offline-builds false" >&2 + fi + return 0 +} + # Helper functions # First argument is the path to inspect (usually optional; without # it the whole repository will be considered) @@ -129,48 +200,103 @@ echo "${t}" }
-# 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= +tag() { + local t=
if 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} + local sha=$(git_last_commit "$1") + t=$(git describe --abbrev=0 "$sha") fi - - echo "${r}" + if [ -z "$t" ]; then + t="unknown" # default to unknown + fi + echo "${t}" }
-# Get the upstream flashrom revision stored in SVN metadata. -upstream_revision() { - local r= +find_upremote() { + # Try to find upstream's remote name + for remote in $(git remote) ; do + local url=$(git ls-remote --get-url $remote) + if echo "$url" | grep -q -E "$upstream_patterns" ; then + echo "$remote" + return + fi + done +}
- if 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:]].*//') +revision() { + local sha=$(git_last_commit "$1" 2>/dev/null) + # No git no fun + if [ -z "$sha" ]; then + echo "unknown" + return fi
- if [ -z "$r" ]; then - r="unknown" # default to unknown + local r="$sha" + if git_has_local_changes "$1" ; then + r="$r-dirty" fi + + # sha + possibly dirty info is not exactly verbose, therefore + # the code below tries to use tags and branches from the upstream + # repos to derive a more precise version string. + # + # To that end we try to use the existing remotes first. If the + # upstream repos (and mirrors) are not available as remotes, use + # a shadow copy instead. + + local up_refs + local up_remote=$(find_upremote) + if [ -n "$up_remote" ]; then + for b in $upstream_branches ; do + up_refs="$up_refs ${up_remote}/${b}" + done + else + update_upcache || { echo "offline" ; return ; } + up_refs=$upcache_refs + fi + + # Find nearest commit contained in this branch that is also in any of the up_refs, i.e. the branch point + # of the current branch. This might be the latest commit if it's in any of the upstream branches. + local merge_point=$(git merge-base ${sha} ${up_refs}) + local upstream_branch + if [ -z "$merge_point" ]; then + echo "$sha" + return + fi + + # If the current commit is reachable from any remote branch, append the branch name and its + # distance to the nearest earlier tag to that tag name itself (tag-distance-branch). + # If multiple branches are reachable then we use the newest one (by commit date). + # If none is reachable we use the nearest tag and ? for distances and remote branch name. + + local cnt_upstream_branch2sha=$(git rev-list --count "${merge_point}..${sha}" 2>/dev/null) + + local lasttag=$(git describe --abbrev=0 "$merge_point" 2>/dev/null) + if [ -z "$lasttag" ]; then + echo "Could not find tag reachable from merge point!">&2 + echo "$sha" + return + fi + + local cnt_tag2upstream_branch=-1 + for ref in $up_refs ; do + if git merge-base --is-ancestor ${merge_point} ${ref}; then + upstream_branch=${ref##*/} # remove everything till last / + cnt_tag2upstream_branch=$(git rev-list --count "${lasttag}..${merge_point}" 2>/dev/null) + break + fi + done + + if [ "$cnt_upstream_branch2sha" -gt 0 ]; then + r="$cnt_upstream_branch2sha-$r" + fi + if [ "$cnt_tag2upstream_branch" -gt 0 ]; then + r="$upstream_branch-$r" + r="$cnt_tag2upstream_branch-$r" + fi + r="$lasttag-$r" + echo "${r}" }
@@ -187,16 +313,20 @@ this message -c or --check test if path is under version control at all - -l or --local - local revision information including an indicator for uncommitted changes - -u or --upstream - upstream revision - -U or --url + -T or --tag + returns the name of the last release/tag + -r or --revision + return unique revision information including the last tag and an indicator for uncommitted changes + -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 --update_upcache + update local shadow copy of upstream commits if need be and offline builds are not enforced + --force-update-upcache + force updating the local shadow copy of upstream commits " return } @@ -219,15 +349,15 @@ -h|--help) action=show_help; shift;; - -l|--local) + -T|--tag) check_action $1 - action=local_revision + action=tag shift;; - -u|--upstream) + -r|--revision) check_action $1 - action=upstream_revision + action=revision shift;; - -U|--url) + -u|--url) check_action $1 action=scm_url shift;; @@ -239,6 +369,14 @@ check_action $1 action="timestamp +%Y-%m-%dT%H:%M:%SZ" # There is only one valid time format! ISO 8601 shift;; + -U|--update_upcache) + check_action $1 + action=update_upcache + shift;; + --force-update-upcache) + check_action $1 + action=force_update_upcache + shift;; -c|--check) check_action $1 action=is_tracked