2022-12-14 11:28:25 +03:00
#!/bin/bash
set -Eeuo pipefail
2022-06-07 15:17:45 +03:00
# init colors
2022-12-27 21:18:46 +03:00
color_grey = $( echo -ne "\033[0;30m" )
2022-06-07 15:17:45 +03:00
color_red = $( echo -ne "\033[1;31m" )
color_green = $( echo -ne "\033[1;32m" )
color_yellow = $( echo -ne "\033[1;33m" )
color_blue = $( echo -ne "\033[1;34m" )
color_reset = $( echo -ne "\033[0m" )
# functions
check_args( ) {
# init args
run_mode = " $1 "
# check args
if [ -n " ${ run_mode } " ] && [ " ${ run_mode } " != "--check" ] ; then
echo " ${ color_yellow } "
echo "Usage:"
echo " $( basename " $0 " ) # update all crates to latest version into Cargo.toml and Cargo.lock files in actual dir/subdir "
echo " $( basename " $0 " ) --check # display upgradable crates from Cargo.toml and Cargo.lock files in actual dir/subdir "
echo " ${ color_reset } "
return 1
fi
}
convert_toml_crates_to_key_value( ) {
# init args
toml_file = " $1 "
# convert toml crates to key value
sed -n " /dependencies\]/,/^ $/p " " ${ toml_file } " |
grep --extended-regexp --invert-match " ^\[|path|^ $" |
2022-12-27 21:18:46 +03:00
cut --delimiter ',' --field 1 |
sed "s/version//g" |
tr -d '"{=' |
tr -d "'" |
tr -s ' ' |
sort
2022-06-07 15:17:45 +03:00
}
get_crate_latest_version( ) {
# init args
crate_url = " $1 "
# get crate latest version
crate_object = $( curl -kLs " ${ crate_url } " || true )
2022-12-27 21:18:46 +03:00
crate_max_stable_version = $( echo " ${ crate_object } " | ( jq -r .crate.max_stable_version 2>/dev/null || true ) )
2022-06-07 15:17:45 +03:00
last_version = $( echo " ${ crate_max_stable_version } " | ( grep --extended-regexp " ^[0-9].*.[0-9].*.[0-9] $" || true ) )
echo " ${ last_version } "
}
2022-12-27 21:18:46 +03:00
get_crate_github_release_body( ) {
# init args
crate_url = " $1 "
crate_release = " $2 "
# get crate github repository
crate_object = $( curl -kLs " ${ crate_url } " || true )
crate_repository = $( echo " ${ crate_object } " | ( jq -r .crate.repository 2>/dev/null || true ) )
github_repository = $( echo " ${ crate_repository } " | ( grep --extended-regexp "^https://github.com" || true ) )
# get github release body
if [ -n " ${ github_repository } " ] ; then
owner_repo = $( echo " ${ github_repository } " | cut --delimiter "/" --field 4-)
tag_name = $( curl -kLs --header "Accept: application/vnd.github+json" https://api.github.com/repos/" ${ owner_repo } " /git/refs/tags | ( jq -r .[ ] .ref 2>/dev/null || true ) | ( grep " ${ crate_release } $" || true ) | cut --delimiter "/" --field 3)
release_body = $( ( curl -kLs --header "Accept: application/vnd.github+json" https://api.github.com/repos/" ${ owner_repo } " /releases/tags/" ${ tag_name } " || true ) | ( jq -r .body 2>/dev/null ||
true ) )
else
release_body = "null"
fi
# display release infos
echo -e " \n ${ color_grey } ${ crate_repository } ${ color_reset } \n "
if [ -n " ${ release_body } " ] && [ " ${ release_body } " != "null" ] ; then
echo -n " ${ color_grey } "
echo " ${ release_body } " | tr -s ' ' | sed 's/```//g' | sed "s/^-//g" | sed "s/^/ /g"
echo -e " ${ color_reset } \n "
fi
}
2022-06-07 15:17:45 +03:00
update_crate_version_in_toml( ) {
# init args
crate = " $1 "
actual_version = " $2 "
last_version = " $3 "
toml_file = " $4 "
# update crate version in toml
2022-07-13 15:15:49 +03:00
sed -i -- " s/ ${ crate } = { version = \" ${ actual_version } \"/ ${ crate } = { version = \" ${ last_version } \"/g " " ${ toml_file } "
sed -i -- " s/ ${ crate } = \" ${ actual_version } \"/ ${ crate } = \" ${ last_version } \"/g " " ${ toml_file } "
2022-06-07 15:17:45 +03:00
if grep --extended-regexp --silent " ${ crate } .*=.* ${ last_version } " " ${ toml_file } " ; then
echo " ${ color_blue } updated to ${ last_version } ${ color_reset } "
else
echo " ${ color_red } error, update to ${ last_version } fails, please check ${ toml_file } format and syntax, then re-run this script ${ color_reset } "
return 1
fi
}
which_is_the_newest_version( ) {
# init vars
first_version = " $1 "
second_version = " $2 "
# which is the newest version
echo -e " ${ first_version } \n ${ second_version } " |
sort --version-sort |
tail -1
}
main( ) {
# init vars
crates_api_root_url = "https://crates.io/api/v1/crates"
2022-12-19 19:23:29 +03:00
arg = " ${ 1 :- } "
2022-06-07 15:17:45 +03:00
check_args " ${ arg } "
updated_count = 0
# update toml
for package in packages/*; do
toml_file = " ${ package } /Cargo.toml "
2022-12-27 21:18:46 +03:00
echo -e "\n--------------------------------------------------------"
echo -e " ### Crates updates for * ${ toml_file } *\n "
2022-06-07 15:17:45 +03:00
while read -r crate actual_version; do
crate_url = " ${ crates_api_root_url } / ${ crate } "
last_version = $( get_crate_latest_version " ${ crate_url } " )
if [ -z " ${ last_version } " ] ; then
echo " ${ color_red } runtime error ${ color_reset } , i could not get last version from ${ crate_url } "
return 1
fi
2022-12-27 21:18:46 +03:00
echo -n " - ${ crate } ${ actual_version } "
2022-06-07 15:17:45 +03:00
newest_version = $( which_is_the_newest_version " ${ last_version } " " ${ actual_version } " )
if [ " ${ newest_version } " = = " ${ actual_version } " ] ; then
echo " ${ color_green } newest ${ color_reset } "
else
if [ " ${ arg } " = "--check" ] ; then
echo " ${ color_red } old, please update to latest ${ last_version } ${ color_reset } "
updated_count = $(( updated_count + 1 ))
else
update_crate_version_in_toml " ${ crate } " " ${ actual_version } " " ${ last_version } " " ${ toml_file } "
2022-12-27 21:18:46 +03:00
get_crate_github_release_body " ${ crate_url } " " ${ last_version } "
2022-06-07 15:17:45 +03:00
fi
fi
done < <( convert_toml_crates_to_key_value " ${ toml_file } " )
done
# update lock
if [ " ${ arg } " != "--check" ] ; then
2022-12-27 21:18:46 +03:00
updated_lock_file = "/tmp/updated_locks.list"
echo -e "\n--------------------------------------------------------"
echo -e "### Crates updates for *Cargo.lock*\n"
cargo update --color always -vv 2>& 1 |
2023-01-10 15:56:39 +03:00
( grep -Ev "crates.io index|Removing" || true ) |
2022-12-27 21:18:46 +03:00
tr -s ' ' |
sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g" |
sed "s/ Updating //g" |
sed "s/->//g" > " ${ updated_lock_file } "
while read -r crate actual_version last_version ; do
2023-01-10 15:56:39 +03:00
formated_actual_version = $( echo " ${ actual_version } " | ( grep --only-matching --extended-regexp "[0-9].*.[0-9].*.[0-9]" || true ) )
formated_last_version = $( echo " ${ last_version } " | ( grep --only-matching --extended-regexp "[0-9].*.[0-9].*.[0-9]" || true ) )
2022-12-27 21:18:46 +03:00
crate_url = " ${ crates_api_root_url } / ${ crate } "
echo " - ${ crate } ${ formated_actual_version } ${ color_blue } updated to ${ formated_last_version } ${ color_reset } "
get_crate_github_release_body " ${ crate_url } " " ${ last_version } "
done < " ${ updated_lock_file } "
2022-06-07 15:17:45 +03:00
echo -e "\n"
fi
# display help if update is needed with --check run_mode
if [ " ${ updated_count } " -gt 0 ] ; then
echo -e " \n ${ color_yellow } ...Consider re-executing $( basename " $0 " ) without --check option to automatically update ${ updated_count } old crates ${ color_reset } \n "
return " ${ updated_count } "
fi
}
# run
main " $@ "
2022-12-14 11:28:25 +03:00