# This file should not have its executable bit set. # This script should not be run directly. Instead, create an executable file # "UpdateFromUpstream.sh", which defines the following shell variables: # # - thirdparty_module_name : # The name of the ThirdParty module to be updated. This must match the # name of the ITK ThirdParty module's base directory (which contains # "itk-module.cmake"). # i.e. "Modules/ThirdParty//itk-module.cmake" # - upstream_git_url : # The full URL (including the scheme) of the upstream Git repository # that the ThirdParty module tracks. # - upstream_git_branch : # The upstream Git branch name that the ThirdParty module tracks. # - snapshot_author_name : # The author name to which the upstream files should be attributed, # in ITK's Git repository. # - snapshot_author_email : # The author email to which the upstream files should be attributed. # in ITK's Git repository. # - snapshot_redact_cmd : # A string, containing a command to be eval'd within the CWD of the fresh # upstream snapshot, in order to prepare it for being committed to ITK's # repository. The string may be empty or contain multiple commands chained # with "&&", etc. The command typically removes extraneous files # or directories that shouldn't be committed to ITK for size, simplicity, # or licensing reasons. # - snapshot_relative_path : # The path, relative to the ThirdParty module's base directory, that # the upstream snapshot's file should be merged into. # e.g. "src/mylib/" # - snapshot_paths : # An optional list of file patterns to be included in the snapshot. E.g. # snapshot_paths=' # dir1 # dir2/*.c # file1.txt # ' # - github_compare : # This option is only relevant for third party projects which have their # repositories on Github. It is an optional boolean (true/false) that # selects how to present the git log, since last update, in the commit # message. If set to false, the log generated with the `shortlog` git # subcommand will be integrated in the commit message. If set to true, # a URL will be added to the commit message. This URL points to a # github page showing the differences between the last update of the # project in ITK and the current commit used in the update. # # The script, "UpdateFromUpstream.sh", must be located in the associated # ThirdParty module's base directory. # die() { echo "Error: $@" 1>&2 exit 1 } update_from_upstream() { ## Set up paths ## local module_path=$( cd "$( dirname "$0" )" && pwd ) module_path=$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$module_path") local toplevel_path=$(cd "$module_path" && git rev-parse --show-toplevel) if [[ $? -ne 0 ]]; then die "Could not find the top-level of a Git repository in \"$module_path\"" fi cd "$toplevel_path" ## Validate ## local required_commands=( git grep sed egrep tar dirname basename tr ) for required_command in ${required_commands[@]}; do type -p $required_command >/dev/null 2>&1 if [[ $? -ne 0 ]]; then die "Command \"$required_command\" not found" fi done local input_variables=( thirdparty_module_name snapshot_relative_path \ upstream_git_url upstream_git_branch \ snapshot_author_name snapshot_author_email ) for input_variable in ${input_variables[@]}; do if [[ -z $(eval echo "\$$input_variable") ]]; then die "\$$input_variable must be set" fi done local module_path_basename=$(basename "$module_path") if [[ "$thirdparty_module_name" != "$module_path_basename" ]]; then die "The script \"$0\" must be in the base directory for the \"$thirdparty_module_name\" module" fi ## Old snapshot commit ## local regex_date='20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]' local snapshot_old_regex="$thirdparty_module_name $regex_date ([0-9a-f]*)" local snapshot_old_sha=$(git rev-list --author="$snapshot_author_email" --grep="$snapshot_old_regex" -n 1 HEAD) if [[ -z "$snapshot_old_sha" ]]; then read -ep "Create a new snapshot branch? [N/y]: " create_new if [[ "$create_new" != "y" && "$create_new" != "Y" ]]; then die "Could not find previous snapshot." fi fi ## New upstream commit ## git fetch --quiet "$upstream_git_url" "$upstream_git_branch" 2> >(sed '/warning: no common commits/d' >&2) if [[ $? -ne 0 ]]; then die "Could not \"git fetch\" from $upstream_git_url:$upstream_git_branch" fi local upstream_new_sha=$(git rev-parse FETCH_HEAD) local upstream_new_sha_short=$(git rev-parse --short=8 $upstream_new_sha) local upstream_new_datetime=$(git rev-list $upstream_new_sha --format='%ci' -n 1 | grep "^$regex_date") local upstream_new_date=$(echo "$upstream_new_datetime" | grep -o "$regex_date") ## Old upstream commit ## if [[ -n "$snapshot_old_sha" ]]; then local upstream_old_sha_short=$( git cat-file commit $snapshot_old_sha | sed -n '/'"$snapshot_old_regex"'/ {s/.*(//;s/)//;p;}' | egrep '^[0-9a-f]+$' ) local upstream_old_sha=$(git rev-parse --verify -q "$upstream_old_sha_short") fi if [[ "$upstream_old_sha" == "$upstream_new_sha" ]]; then echo 'Upstream has no updates' exit 0 fi ## New snapshot tree ## local snapshot_branch_name=`echo "upstream-${thirdparty_module_name}" | tr '[:upper:]' '[:lower:]'` # make string lowercase local snapshot_temp_dir="$snapshot_branch_name" local snapshot_temp_path="$toplevel_path/$snapshot_temp_dir/" local snapshot_temp_index="$toplevel_path/$snapshot_branch_name.index" rm -rf "$snapshot_temp_path" "$snapshot_temp_index" cd "$toplevel_path" && git archive --prefix="$snapshot_temp_dir/" $upstream_new_sha -- $snapshot_paths | tar x ( cd "$snapshot_temp_path" && eval "$snapshot_redact_cmd" ) if [[ $? -ne 0 ]]; then rm -rf "$snapshot_temp_path" "$snapshot_temp_index" die 'Could not eval $snapshot_redact_cmd in upstream snapshot' fi local snapshot_new_tree=$( GIT_WORK_TREE="$snapshot_temp_path" && GIT_INDEX_FILE="$snapshot_temp_index" && export GIT_WORK_TREE GIT_INDEX_FILE && git add --all && git write-tree ) rm -rf "$snapshot_temp_path" "$snapshot_temp_index" ## New snapshot commit ## if [[ -z "$snapshot_old_sha" ]]; then local snapshot_new_shortlog="Initial import of $upstream_new_sha" local snapshot_new_change_id=$(git commit-tree $snapshot_new_tree