summaryrefslogtreecommitdiffstats
path: root/debian/scripts/debian-cargo-vendor
blob: 6566b316d17bb4ee6aa0758142e2545d88abddcf (plain)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/bin/bash
# To run this, you need to first install cargo-lock.
#
# TODO: this script has a known bug in: if the Debian patches being applied,
# changes the set of dependencies, then "cargo vendor" is not re-run in order
# to pick up this new set of dependencies. This is manifested by an error
# message like: "perhaps a crate was updated and forgotten to be re-vendored?"
#
set -e

SCRIPTDIR="$(dirname "$(readlink -f "$0")")"

not_needed() {
	diff -ur packages-before packages-after | grep "^-- " | cut -d' ' -f2-3
}

ghetto_parse_cargo() {
	cat "$1" \
	 | tr '\n' '\t' \
	 | sed -e 's/\t\[/\n[/g' \
	 | perl -ne 'print if s/^\[(?:package|project)\].*\tname\s*=\s*"(.*?)".*\tversion\s*=\s*"(.*?)".*/\1 \2/g'
}

pruned_paths() {
	for i in vendor/*/Cargo.toml; do
		pkgnamever=
		pkgnamever=$(ghetto_parse_cargo "$i")
		if [ -z "$pkgnamever" ]; then
			echo >&2 "failed to parse: $i"
			exit 1
		fi
		echo "$pkgnamever $i"
	done | grep -F -f <(not_needed) | cut '-d ' -f3 | while read x; do
		echo " $(dirname $x)"
	done
}

crate_to_debcargo_conf() {
    echo "$1" | sed -e 's/_/-/g'
}

rm -rf vendor/
if [ -e "$CARGO_PRE_VENDOR" ]; then
	"$CARGO_PRE_VENDOR"
fi
cargo vendor --verbose vendor/
mkdir -p .cargo
cat >.cargo/config <<eof
[source.crates-io]
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "$PWD/vendor"
eof
cargo lock list > packages-before
cp Cargo.lock Cargo.lock.orig

if [ -d debcargo-conf ]; then ( cd debcargo-conf && git pull );
else git clone "${DEBCARGO_CONF:-https://salsa.debian.org/rust-team/debcargo-conf}"; fi

# keep applying patches, and drop to a subshell for manual fixing, until it succeeds
while ! ( cd vendor
x=true
for i in *; do
	debname=$(crate_to_debcargo_conf "$i")
	cd $i
	# if there is a d/rules then don't mess with it, it's too custom for this
	# script to deal with - just use the upstream version. example: backtrace-sys
	# TODO: deal with those better, especially backtrace-sys
	if [ -e ../../debcargo-conf/src/$debname/debian/rules ]; then
		echo >&2 "$0: the debcargo-conf for crate $i has a custom rules file, but applying patches anyway"
		echo >&2 "$0: you may want to examine this situation more closely"
	fi
	if [ -d ../../debcargo-conf/src/$debname/debian/patches ]; then
		echo >&2 "$0: patching $i"
		mkdir -p debian
		if [ ! -d debian/patches ]; then
			cp -a -n "../../debcargo-conf/src/$debname/debian/patches" debian/
		fi
		# first unapply any patches applied in the previous iteration
		QUILT_PATCHES=debian/patches quilt pop -af
		QUILT_PATCHES=debian/patches quilt push -a
		case $? in
		0|2) true;;
		*)  echo >&2 "$0: patching $i failed <<<<<<<<<<<<<<<<<<<<<<<<"
			QUILT_PATCHES=debian/patches quilt pop -af
			x=false;;
		esac
	fi
	if [ -f ../../debcargo-conf/src/$debname/debian/build.rs ]; then
		echo >&2 "$0: overwriting build.rs with our custom one"
		if [ ! -f build.rs.orig ]; then
			cp -f build.rs build.rs.orig
		fi
		cp -f ../../debcargo-conf/src/$i/debian/build.rs build.rs
	fi
	cd ..
done; $x ); do
	echo >&2 "================================================================================"
	echo >&2 "$0: You are now in a sub-shell!"
	echo >&2 "$0: Fix the failed patches in debcargo-conf/, then exit the sub-shell by pressing ctrl-D ONCE."
	echo >&2 "$0: If you need to abort this process, press ctrl-D then quickly ctrl-C."
	if [ -f "${SRCDIR:-$PWD}/debian/debcargo-conf.patch" ]; then
		echo >&2 "$0: Previous patch changes exist, to apply them run:"
		echo >&2 "  $ patch -d vendor -p2 < '${SRCDIR:-$PWD}/debian/debcargo-conf.patch'"
	fi
	echo >&2 "================================================================================"
	bash || true
	echo >&2 "$0: trying patches again..."
done
rm -rf vendor/*/.pc
find vendor/*/debian/patches -name '*~' -delete || true
cargo update
cargo lock list > packages-after
pruned_paths | while read x; do echo >&2 "$0: removing, because debcargo-conf patches makes it obsolete: $x"; rm -rf "$x"; done

# remove excluded files
( cd vendor
for i in *; do (
	debname=$(crate_to_debcargo_conf "$i")
	shopt -s globstar # needed for double-glob to work in excludes
	cd $i
	if [ -e ../../debcargo-conf/src/$debname/debian/rules ]; then
		echo >&2 "$0: the debcargo-conf for crate $i has a custom rules file, but applying excludes anyway"
		echo >&2 "$0: you may want to examine this situation more closely"
	fi
	if grep -q excludes ../../debcargo-conf/src/$debname/debian/debcargo.toml 2>/dev/null; then
		sed -nre 's/.*excludes\s*=\s*(\[[^]]*\]).*/\1/p' \
		  ../../debcargo-conf/src/$i/debian/debcargo.toml \
		  | python3 -c "import ast, sys; x=ast.literal_eval(sys.stdin.read()); print('\n'.join((i[:-3] if i.endswith('/**') else i) for i in x));" \
		  | while read x; do echo >&2 "$0: removing, since it's excluded by debcargo-conf: vendor/$i/$x"; rm -rf $x; done
	fi
); done; )

# TODO: rm special logic from debcargo and put into debcargo-conf instead
echo >&2 "$0: removing winapi archives"
rm -rf vendor/winapi-*-pc-windows-gnu/lib/*.a

echo >&2 "$0: pruning all checksums.."
for i in vendor/*; do ${SCRIPTDIR}/prune-checksums "$i"; done

( cd vendor
for i in *; do (
	cd $i
	debname=$(crate_to_debcargo_conf "$i")
	if [ -d debian/patches ]; then
		rm -rf "../../debcargo-conf/src/$debname/debian/patches"
		cp -a debian/patches "../../debcargo-conf/src/$debname/debian/"
	fi
); done; )
( cd debcargo-conf
git add .
if ! git diff --cached --quiet; then
	git commit -m "Manual changes from debian-cargo-vendor"
	git diff @~ > ../../debcargo-conf.patch || true
	(cd ../.. ; echo >&2 "$0: backed up patch changes to $PWD/debcargo-conf.patch")
	echo >&2 "$0: you should backport/merge them back into debcargo-conf.git"
fi
)

echo >&2 "$0: cleaning up..."
rm -rf .cargo Cargo.lock debcargo-conf packages-before packages-after

echo >&2 "$0: restoring original Cargo.lock"
mv Cargo.lock.orig Cargo.lock