xref: /aosp_15_r20/external/gsc-utils/util/getversion.sh (revision 4f2df630800bdcf1d4f0decf95d8a1cb87344f5f)
1#!/bin/bash
2#
3# Copyright 2012 The ChromiumOS Authors
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6#
7# Generate version information for the EC binary
8
9# Use this symbol as a separator to be able to reliably concatenate strings of
10# text.
11dc=$'\001'
12
13# Default marker to indicate 'dirty' repositories
14dirty_marker='+'
15
16# This function examines the state of the current directory and attempts to
17# extract its version information: the latest tag, if any, how many patches
18# are there since the latest tag, the top sha1, and if there are local
19# modifications.
20#
21# Local modifications are reported by concatenating the revision string and
22# the string '-dirty' using the $dc symbol as the separator.
23#
24# If there is no tags defined in this git repository, the base version is
25# considered to be 0.0.
26#
27# If current directory is not a git depository, this function prints out
28# "no_version"
29
30get_tree_version() {
31  local marker
32  local ghash
33  local numcommits
34  local tag
35  local vbase
36  local ver_branch
37  local ver_major
38
39  if ghash=`git rev-parse --short --verify HEAD 2>/dev/null`; then
40    if gdesc=`git describe --dirty --match='v*' 2>/dev/null`; then
41      IFS="-" fields=($gdesc)
42      tag="${fields[0]}"
43      IFS="." vernum=($tag)
44      numcommits=$((${vernum[2]}+${fields[1]:-0}))
45      ver_major="${vernum[0]}"
46      ver_branch="${vernum[1]}"
47    else
48      numcommits=`git rev-list HEAD | wc -l`
49      ver_major="v0"
50      ver_branch="0"
51    fi
52    # avoid putting the -dirty attribute if only the timestamp
53    # changed
54    git status > /dev/null 2>&1
55
56    if [ -n "$(git diff-index --name-only HEAD 2>/dev/null)" ]; then
57      marker="${dirty_marker}"
58    else
59      marker="-"
60    fi
61    vbase="${ver_major}.${ver_branch}.${numcommits}${marker}${ghash}"
62  else
63    # Fall back to the VCSID provided by the packaging system if available.
64    if ghash=${VCSID##*-}; then
65      vbase="1.1.9999-${ghash:0:7}"
66    else
67      # then ultimately fails to "no_version"
68      vbase="no_version"
69    fi
70  fi
71  if [[ "${marker}" == "${dirty_marker}" ]]; then
72      echo "${vbase}${dc}${marker}"
73  else
74      echo "${vbase}${dc}"
75  fi
76}
77
78
79main() {
80  local component
81  local dir_list
82  local gitdate
83  local most_recents
84  local most_recent_file
85  local root
86  local timestamp
87  local tool_ver
88  local values
89  local vbase
90  local ver
91
92  IFS="${dc}"
93  ver="${CR50_DEV:+DBG/}${CRYPTO_TEST:+CT/}${BOARD}_"
94  tool_ver=""
95  most_recents=()    # Non empty if any of the component repos is 'dirty'.
96  dir_list=( . )   # list of component directories, always includes the EC tree
97
98  if [[ -n ${BOARD} ]]; then
99    case "${BOARD}" in
100      (cr50)
101        dir_list+=( ../../third_party/tpm2 )
102        dir_list+=( ../pinweaver )
103        ;;
104      (*_fp)
105        dir_list+=( ./private )
106        ;;
107      (*)
108        # For private-crX boards add their git root and cryptoc.
109        for root in private-cr5*; do
110          if [[ -d "${root}/board/${BOARD}" ]]; then
111            dir_list+=( "${root}" ../../third_party/cryptoc )
112          fi
113        done
114        ;;
115    esac
116  fi
117  # Create a combined version string for all component directories.
118  for git_dir in ${dir_list[@]}; do
119    pushd "${git_dir}" > /dev/null
120    component="$(basename "${git_dir}")"
121    values=( $(get_tree_version) )
122    vbase="${values[0]}"             # Retrieved version information.
123    if [[ -n "${values[1]}" ]]; then
124      # From each modified repo get the most recently modified file.
125      most_recent_file="$(git status --porcelain | \
126                                       awk '$1 ~ /[M|A|?]/ {print $2}' |  \
127                                       xargs ls -t | head -1)"
128      most_recents+=("$(realpath "${most_recent_file}")")
129    fi
130    if [ "${component}" != "." ]; then
131      ver+=" ${component}:"
132    fi
133    ver+="${vbase}"
134    tool_ver+="${vbase}"
135    popd > /dev/null
136  done
137
138  # On some boards where the version number consists of multiple components we
139  # want to separate the first word of the version string as the version of the
140  # EC tree.
141  IFS=' ' first_word=(${ver})
142
143  echo "/* This file is generated by util/getversion.sh */"
144
145  echo "/* Version string, truncated to 31 chars (+ terminating null = 32) */"
146  echo "#define CROS_EC_VERSION32 \"${first_word:0:31}\""
147
148  echo "/* Version string for ectool. */"
149  echo "#define CROS_ECTOOL_VERSION \"${tool_ver}\""
150
151  echo "/* Version string for stm32mon. */"
152  echo "#define CROS_STM32MON_VERSION \"${tool_ver}\""
153
154  echo "/* Sub-fields for use in Makefile.rules and to form build info string"
155  echo " * in common/version.c. */"
156  echo "#define VERSION \"${ver}\""
157  if [ "$REPRODUCIBLE_BUILD" = 1 ]; then
158    echo '#define BUILDER "reproducible@build"'
159  else
160    echo "#define BUILDER \"${USER}@`hostname`\""
161  fi
162
163  if [[ ${#most_recents[@]} != 0 ]]; then
164    # There are modified files, use the timestamp of the most recent one as
165    # the build version timestamp.
166    most_recent_file="$(ls -t "${most_recents[@]}" | head -1)"
167    timestamp="$(stat -c '%y' "${most_recent_file}" | sed 's/\..*//')"
168    echo "/* Repo is dirty, using time of most recent file modification. */"
169    echo "#define DATE \"${timestamp}\""
170  else
171    echo "/* Repo is clean, use the commit date of the last commit. */"
172    # If called from an ebuild we won't have a git repo, so redirect stderr
173    # to avoid annoying 'Not a git repository' errors.
174    gitdate="$(
175      for git_dir in "${dir_list[@]}"; do
176        git -C "${git_dir}" log -1 --format='%ct %ci' HEAD 2>/dev/null
177      done | sort | tail -1 | cut -d ' ' -f '2 3')"
178    echo "#define DATE \"${gitdate}\""
179  fi
180}
181
182main
183