blob: 8e9ff06a39d7f429ffba7d027eb627310be6574c [file] [log] [blame] [edit]
#!/bin/bash
#
# Copyright 2020 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Generate version information for the hdctools python packages
# The output is a python file that contains a dictionary to construct version
# information. The utility sversion_util.py consumes that dictionary to generate
# version strings.
# Current, the dictionary contains the following fields:
# - the version base, a three digit string that contains
# v[major-number].[minor-number].[commits-since-major/minor]
# - the major/minor information is supplied through a git tag
# - in the abscence of a git repository e.g. by building through cros_workon
# the version base defaults to v0.9999.0 if VCSID is provided by the
# packaging system, otherwise to vno_version.0.0
# - git hash (first 7 elements) of the latest commit
# - a marker whether the directory is dirty
# - the builder hostname (and username if available)
# - the timestamp
# - with a git repository, it's either last commit time or build time
# (dirty repo)
# - without a git reposity, it defaults to the build time
# Use this symbol as a separator to be able to reliably concatenate strings of
# text.
dc=$'\001'
# Default marker to indicate 'dirty' repositories
dirty_marker='+'
# This function examines the state of the current directory and attempts to
# extract its version information: the latest tag, if any, how many patches
# are there since the latest tag, the top sha1, and if there are local
# modifications.
#
# If there is no tags defined in this git repository, the base version is
# considered to be 0.0.
#
# If current directory is not a git depository, this function prints out
# "no_version"
gen_version_py() {
local marker="-"
local ghash
local global_dirty
local numcommits
local tag
local vbase
local ver_branch
local ver_major
local branch_name
if ghash="$(git rev-parse --short --verify HEAD 2>/dev/null)"; then
if gdesc="$(git describe --dirty --match='v*' 2>/dev/null)"; then
IFS="-" read -r -a fields <<< "${gdesc}"
tag="${fields[0]}"
IFS="." read -r -a vernum <<< "${tag}"
numcommits=$((vernum[2]+${fields[1]:-0}))
ver_major="${vernum[0]}"
ver_branch="${vernum[1]}"
else
numcommits=$(git rev-list HEAD | wc -l)
ver_major="v0"
ver_branch="0"
fi
# avoid putting the -dirty attribute if only the timestamp
# changed
git status > /dev/null 2>&1
if [ -n "$(git diff-index --name-only HEAD 2>/dev/null)" ]; then
marker="${dirty_marker}"
fi
else
if ghash=${VCSID##*-}; then
ghash="${ghash:0:7}"
ver_major="v0"
ver_branch="9999"
else
# then ultimately fails to "no_version"
ghash=""
ver_major="vno_version"
ver_branch="0"
fi
numcommits="0"
fi
vbase="${ver_major}.${ver_branch}.${numcommits}"
ghash="${marker}${ghash}"
branch_name="$(git branch --show-current 2>/dev/null)"
# If dirty, then we also append a timestamp.
if [[ "$marker" == "$dirty_marker" ]]; then
most_recent_file="$(git status --porcelain | \
awk '$1 ~ /[M|A|?]/ {print $2}' | xargs ls -t | head -1)"
timestamp="$(stat -c '%y' "${most_recent_file}" | sed 's/\..*//')"
dirty="True"
else
# If called from an ebuild we won't have a git repo, so redirect stderr
# to avoid annoying 'Not a git repository' errors.
if raw_gitdate="$(git log -1 --format='%ci' HEAD 2>/dev/null)"; then
timestamp="$(echo ${raw_gitdate} | cut -d ' ' -f '1 2')"
else
timestamp=$(date +"%Y-%m-%d %T")
fi
dirty="False"
fi
# Only append username if there is one
[[ ! -z "${USER}" ]] && BLDR="${USER}@$(hostname)" || BLDR="$(hostname)"
cat <<-EOF
# This file is generated by getversion.sh
VER_DICT = {
'builder': '${BLDR}',
'vbase': '${vbase}',
'ghash': '${ghash}',
'date': '${timestamp}',
'dirty': '${dirty}',
'branch': '${branch_name}'
}
EOF
}
gen_version_py