-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtag-from-cargo-toml.sh
executable file
·106 lines (98 loc) · 2.77 KB
/
tag-from-cargo-toml.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/bin/bash
set -eu
dry=0
if [[ $# -gt 0 && $1 == "-n" ]]; then
dry=1
shift
fi
prefix="v"
if [[ $# -gt 0 ]]; then
if [[ $1 = -* || $# -gt 1 ]]; then
echo "Usage: $0 [-n] [prefix]"
exit 1
fi
prefix="$1"
shift
fi
function tag() {
local v=$1
local hash=$2
local tag="${prefix}${v}"
if git rev-parse "$tag" > /dev/null 2>&1; then
existing=$(git rev-parse "$tag^{}")
if [[ $hash == $existing ]]; then
echo "$hash $tag (already tagged)"
else
echo "$hash $tag (already tagged at $existing)"
fi
return
fi
if [[ $dry -eq 0 ]]; then
git tag -a -m "Release $tag" "$tag" "$hash"
fi
echo "$hash $tag"
}
# in case we're in a subdir:
cargo_toml="rust-bison-skeleton/Cargo.toml"
was=""
last_hash=""
last_name=""
function walk() {
local cargo_toml=$1
local start_hash=$2
for hash in $(git log --first-parent --format=oneline "$start_hash" -- "$cargo_toml" | awk '{print $1}'); do
n=$(git show "$hash:$cargo_toml" | grep -E '^name\s*=' | head -n1 | sed -e 's/[^"]*"//' -e 's/".*//')
v=$(git show "$hash:$cargo_toml" | grep -E '^version\s*=' | head -n1 | sed -e 's/[^"]*"//' -e 's/".*//')
if [[ -z "$last_name" ]]; then
last_name=$n
elif [[ -z "$n" ]]; then
# probably a workspace -- try a little harder to retrace versions
local cargo_toml="${cargo_toml%Cargo.toml}$last_name/Cargo.toml"
if ! git cat-file -e $hash:$cargo_toml 2>/dev/null; then
echo "!! crate disappeared -- stopping." > /dev/stderr
return
fi
n=$(git show "$hash:$cargo_toml" | grep -P '^name\s*=' | head -n1 | sed -e 's/[^"]*"//' -e 's/".*//')
if [[ -z "$n" ]]; then
echo "!! could not determine name of crate in workspace -- stopping." > /dev/stderr
return
elif [[ $last_name != $n ]]; then
echo "!! name changed from $n (in workspace) to $last_name -- stopping." > /dev/stderr
return
else
# restart within workspace
echo ".. following crate into workspace $last_name"
walk "$cargo_toml" "$hash"
return
fi
elif [[ $last_name != $n ]]; then
echo "!! name changed from $n to $last_name -- stopping." > /dev/stderr
break
fi
if [[ $was == $v ]]; then
# same version -- keep walking until we hit the previous
last_hash=$hash
continue
fi
if [[ $was = ${v}-* ]]; then
# pushed an alpha/beta/rc *after* main version?
# no, main version cannot have been released as non-alpha first
continue
fi
if [[ -z "$was" ]]; then
# start search
was="$v"
last_hash="$hash"
continue
fi
# this hash has a different hash than the previous one. so tag the last
# hash with the last version number, since that was the first hash at
# which that version number appeared.
tag "$was" "$last_hash"
last_hash="$hash"
was=$v
done
}
walk "$cargo_toml" "HEAD"
# tag the first commit that has this Cargo.toml
tag "$was" "$last_hash"