blob: 9b3497c718f192075e7ccc6c054e93c507b84631 [file] [log] [blame]
#!/bin/bash
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# The "get_hash_for_release" command can be used in one of two forms:
# - It can be used to return the hash associated with the project in
# the current directory:
#
# ~/chromiumos/chromite$ get_hash_for_release 6822.0.0
# 0b325183cf2eee7f93d7d631a8639c089f4a2d4f
# # This is the hash of the "chromite" package for release 6822.0.0
#
# - It can indicate what is the earliest release where a given hash
# appeared:
#
# ~/chromiumos/chromite$ get_hash_for_release R41 \
# 8eba257003357ca945528fb93dadd2c4d16b7d11
# Oldest release with 8eba257003357ca945528fb93dadd2c4d16b7d11 is 6674.0.0
fetch_manifests() {
temp_dir=/tmp/chrome_manifest_temp
if [[ ! -d "${temp_dir}" ]] ; then
mkdir -p "${temp_dir}"
local git_server="https://chrome-internal.googlesource.com"
git clone -q --depth 1 --single-branch \
"${git_server}/chromeos/manifest-versions" "${temp_dir}"
else
(cd "${temp_dir}" && git pull -q)
fi
}
cleanup_manifests() {
if [[ -d "${temp_dir}" ]] ; then
rm -rf "${temp_dir}"
fi
}
is_child_release() {
# Release numbers are stated in a set of dotted integers.
# 2.0.0.0 is a child of 1.0.0.0 (later release)
# 2.1.0.0 is a child of 2.0.0.0 (new branch)
# 3.0.0.0 is a child of 2.0.0.0 but not 2.1.0.0 since 2.1 branched from 2.0.
# 3.0.1.0 isn't really valid (branches are left aligned) but we ignore this.
local child
local parent
IFS='.' read -a child <<< "$1"
IFS='.' read -a parent <<< "$2"
if [[ ${#child[@]} -ne ${#parent[@]} ]] ; then
return 1
fi
local must_be_root
for idx in $(seq 0 $((${#child[@]} - 1))); do
local parent_num="${parent[idx]}"
[[ -n "${must_be_root}" && "$parent_num" != "0" ]] && return 1
local child_num="${child[idx]}"
[[ "${parent_num}" > "${child_num}" ]] && return 1
[[ "${parent_num}" < "${child_num}" ]] && must_be_root=1
done
return 0
}
get_project_info() {
repo info . 2>/dev/null | egrep '^(Project|Current revision):' | cut -f2 -d:
}
get_revision() {
local release="$1"
local revision="$2"
grep "${project}.*upstream=.*${branch}" \
${temp_dir}/buildspecs/$release/${revision}.xml |
sed -e 's/ *<project.*revision="\([^"]*\)".*/\1/' \
-e 's/^.*\/\([0-9.]*\)\.xml:/\1 : /'
}
get_hash_for_release() {
get_revision '*' "${revision}"
}
get_release_for_hash() {
local release="${revision:1}"
local -a all_revs=($(ls "${temp_dir}/buildspecs/${release}" |
sort -Vr | sed -e 's/\.xml$//'))
latest_rev=$(basename $(cd "${temp_dir}/buildspecs/${release}" &&
git log -n1 --name-only --oneline --grep release . |
grep -v ' ' | sort -V | tail -1 |
sed -e 's/\.xml$//'))
revs=()
for rev in "${all_revs[@]}"; do
is_child_release "${latest_rev}" "${rev}" && revs+=("${rev}")
done
last_released_hash=$(get_revision "${release}" "${latest_rev}" |
awk '{print $1}')
if [[ -z "${last_released_hash}" ]] ; then
echo "Huh? Can't find hash for ${latest_rev}"
return
fi
local -a hashes
found=''
for search_size in 10 100 1000 10000; do
hashes=($(git log --pretty=format:%H -n "${search_size}" \
"${last_released_hash}"))
if echo "${hashes[*]}" | grep -q $hash; then
found=1
break
fi
done
if [[ -z "${found}" ]] ; then
echo "Perhaps ${hash} was never in release ${release}?"
return
fi
# Pop all hashes after the one we care about.
while [[ "${hashes[-1]}" != "${hash}" ]] ; do
unset hashes[${#hashes[@]}-1]
done
oldest_release="${latest_rev}"
idx=1
while [[ $idx -lt ${#revs[@]} ]]; do
rev="${revs[idx]}"
hash_for_rev=$(get_revision "${release}" "${rev}" |
awk '{print $1}')
if ! echo "${hashes[*]}" | grep -q $hash_for_rev; then
break
fi
oldest_release="${rev}"
idx=$(( idx + 1 ))
done
echo "Oldest release with ${hash} is ${oldest_release}"
}
main() {
revision="${1}"
if [[ -z "${revision}" ]] ; then
echo "Usage: $0 <revision> [hash]"
exit 0
fi
if expr "${revision}" : '[MR]' > /dev/null; then
hash="${2}"
shift
fi
project_info=($(get_project_info))
if [[ "${#project_info[@]}" < 2 ]] ; then
echo "Couldn't get project info (are you in a repo directory?)"
exit 0
fi
project="${project_info[0]}"
branch="$(echo ${project_info[1]} | cut -d/ -f3)"
if [[ "${branch}" == "master" ]] ; then
branch=""
elif [[ "${branch}" == "chromeos-3.4" ]] ; then
# Hack for old releases of chromeos-kernel.
branch='\.[4B]"'
fi
fetch_manifests
if [[ -z "${hash}" ]] ; then
get_hash_for_release
else
get_release_for_hash
fi
#cleanup_manifests
}
main "$@"