aports-lint 9.67 KB
Newer Older
Leo's avatar
Leo committed
1 2 3
#!/bin/sh
export LC_ALL=C

4 5 6 7 8 9
# List of $repository/$packages that should not be used
deprecated_packages="
main/db
$(echo "$CUSTOM_DEPRECATED_PACKAGES" | tr ' ' '\n')
"

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
# Define find_repo using 'apk' which is slow and costly when the
# user wants it.
#
# Times go up from 0.02 for community/gcc6/APKBUILD to 3.26
if [ "$EXPENSIVE_FIND_REPO" ]; then

find_repo() {
	[ -z "$1" ] || [ -z "$2" ] && return 0

	local pkgname="$1" 
	# Repo the package we are linting currently is. We want it
	# for avoiding checks on repos we don't want
	local targetrepo="$2"

	# Unmaintained is the top of the ladder, it can depend on any
	# of the steps below
	if [ "$targetrepo" = "unmaintained" ]; then
		return 0
	fi

	# Search for the --origin of a package, matching the given name --exactly
	pkgname="$(apk search --origin --exact "$pkgname" \
			 | rev \
			 | cut -d -f3- 2>/dev/null \
			 | rev)"

	# If we found nothing just ignore it
	[ -z "$pkgname" ] && return 0

39
	check_in_repo() { test -f "$1"/"$2"/APKBUILD && echo "$1" ; }
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

	case "$targetrepo" in
		testing) 
			check_in_repo unmaintained "$pkgname"
			;;
		community)
			check_in_repo unmaintained "$pkgname"
			check_in_repo testing "$pkgname"
			;;
		main)
			check_in_repo unmaintained "$pkgname"
			check_in_repo testing "$pkgname"
			check_in_repo community "$pkgname"
			;;
	esac
}
else

Leo's avatar
Leo committed
58 59 60 61 62 63
# Finds from which repo a package comes from
# it can return multiple values if it finds multiple matches
find_repo() {
	[ -z "$1" ] || [ -z "$2" ] && return 0

	local pkgname="$1"
Leo's avatar
Leo committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77

	# ninja was deprecated and moved to unmaintained in favour of
	# samurai, which is in main/, but most package still call ninja
	# correctly because samurai provides it, but aports-lint is not
	# smart enough to deal with replaces= and provides=, we just check
	# directories.
	#
	# This leads to false positives where packages that depend on ninja
	# and rightfully get samurai are considered broken because ninja is in
	# unmaintained.
	if [ "$pkgname" = ninja ]; then
		return 0
	fi

Leo's avatar
Leo committed
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
	# Repo the package we are linting currently is. We want it
	# for avoiding checks on repos we don't want
	local targetrepo="$2"

	# Unmaintained is the top of the ladder, it can depend on any
	# of the steps below
	if [ "$targetrepo" = "unmaintained" ]; then
		return 0
	fi

	# Perform some transformations that can be done easily and cheaply
	# and are common.
	#
	# This is a hack until apk has something like xpkg -m or aports adopt
	# the xbps-src symlinks
	pkgname="${pkgname%-dev}"
	pkgname="${pkgname%-doc}"
	pkgname="${pkgname%-openrc}"
	pkgname="${pkgname%-bash-completion}"
	pkgname="${pkgname%-zsh-completion}"
	pkgname="${pkgname%-fish-completion}"
	# Disabled because it can cause conflicts with -dev packages, there is glade and libglade
	# which are separate packages but end up causing false-postiives
	# pkgname="${pkgname#lib}"
	pkgname="${pkgname%-static}"
	pkgname="${pkgname%-lang}"

105
	check_in_repo() { test -f "$1"/"$2"/APKBUILD && echo "$1" ; }
Leo's avatar
Leo committed
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

	case "$targetrepo" in
		testing) 
			check_in_repo unmaintained "$pkgname"
			;;
		community)
			check_in_repo unmaintained "$pkgname"
			check_in_repo testing "$pkgname"
			;;
		main)
			check_in_repo unmaintained "$pkgname"
			check_in_repo testing "$pkgname"
			check_in_repo community "$pkgname"
			;;
	esac
}
122
fi
Leo's avatar
Leo committed
123

124
find_dupe() {
125
	local pkgname="$1" repo="$2" r=
126

127
	check_in_repo() { test -f "$1"/"$2"/APKBUILD && echo "$1" ; }
128 129 130 131 132 133 134

	for r in unmaintained testing community main; do
		[ "$r" = "$repo" ] && continue
		check_in_repo "$r" "$pkgname"
	done
}

135 136
upper_repo_depends() {
	[ "$SKIP_UPPER_REPO_DEPENDS" ] && return 0
Leo's avatar
Leo committed
137
	[ "$SKIP_AL16" ] && return 0
Leo's avatar
Leo committed
138
	printf "%s\n" "$depends" | tr " " "\n" | tr -d "\t" | sort -u | while read -r pkg; do
139
		for p in $(find_repo "$pkg" "$_repo"); do
Leo's avatar
Leo committed
140
			printf "SC:[AL17]:$apkbuild::depends '$pkg' is in upper repo '$p'\n"
141 142 143 144 145 146
		done
	done
}

duplicate_depends() {
	[ "$SKIP_DUPLICATE_DEPENDS" ] && return 0
Leo's avatar
Leo committed
147
	[ "$SKIP_AL17" ] && return 0
Leo's avatar
Leo committed
148
	printf "%s\n" "$depends" | tr " " "\n" | tr -d "\t" | sort | uniq -d | while read -r dup; do
149
		[ -z "$dup" ] && continue
Leo's avatar
Leo committed
150
		printf "MC:[AL17]:$apkbuild::duplicate '$dup' in depends\n"
151 152 153 154 155
	done
}

upper_repo_makedepends() {
	[ "$SKIP_UPPER_REPO_MAKEDEPENDS" ] && return 0
Leo's avatar
Leo committed
156
	[ "$SKIP_AL18" ] && return 0
Leo's avatar
Leo committed
157
	printf "%s\n" "$makedepends" | tr " " "\n" | tr -d "\t" | sort -u | while read -r pkg; do
158
		for p in $(find_repo "$pkg" "$_repo"); do
Leo's avatar
Leo committed
159
			printf "SC:[AL18]:$apkbuild::makedepends '$pkg' is in upper repo '$p'\n"
160 161 162 163 164 165
		done
	done
}

duplicate_makedepends() {
	[ "$SKIP_DUPLICATE_MAKEDEPENDS" ] && return 0
Leo's avatar
Leo committed
166
	[ "$SKIP_AL19" ] && return 0
Leo's avatar
Leo committed
167
	printf "%s\n" "$makedepends" | tr " " "\n" | tr -d "\t" | sort | uniq -d | while read -r dup; do
168
		[ -z "$dup" ] && continue
Leo's avatar
Leo committed
169
		printf "MC:[AL19]:$apkbuild::duplicate '$dup' in makedepends\n"
170 171 172 173 174
	done
}

upper_repo_checkdepends() {
	[ "$SKIP_UPPER_REPO_CHECKDEPENDS" ] && return 0
Leo's avatar
Leo committed
175
	[ "$SKIP_AL20" ] && return 0
Leo's avatar
Leo committed
176
	printf "%s\n" "$checkdepends" | tr " " "\n" | tr -d "\t" | sort -u | while read -r pkg; do
177
		for p in $(find_repo "$pkg" "$_repo"); do
Leo's avatar
Leo committed
178
			printf "SC:[AL20]:$apkbuild::checkdepends '$pkg' is in upper repo '$p'\n"
179 180 181 182 183 184
		done
	done
}

duplicate_checkdepends() {
	[ "$SKIP_DUPLICATE_CHECKDEPENDS" ] && return 0
Leo's avatar
Leo committed
185
	[ "$SKIP_AL21" ] && return 0
Leo's avatar
Leo committed
186
	printf "%s\n" "$checkdepends" | tr " " "\n" | tr -d "\t" | sort | uniq -d | while read -r dup; do
187
		[ -z "$dup" ] && continue
Leo's avatar
Leo committed
188
		printf "MC:[AL21]:$apkbuild::duplicate '$dup' in checkdepends\n"
189 190 191 192
	done
}

duplicate_package() {
Leo's avatar
Leo committed
193
	[ "$SKIP_DUPLICATE_PACKAGE" ] && return 0
Leo's avatar
Leo committed
194
	[ "$SKIP_AL22" ] && return 0
195
	for _r in $(find_dupe "$pkgname" "$_repo"); do
Leo's avatar
Leo committed
196
		printf "SC:[AL22]:$apkbuild::package is already present in $_r\n"
197 198 199
	done
}

Leo's avatar
Leo committed
200 201
pkgname_dirname_mismatch() {
	[ "$SKIP_PKGNAME_DIRNAME_MISMATCH" ] && return 0
Leo's avatar
Leo committed
202
	[ "$SKIP_AL23" ] && return 0
Leo's avatar
Leo committed
203 204 205 206 207 208 209 210 211
	local _dirname=
	case "${apkbuild%%/*}" in
		main|community|testing|unmaintained|non-free)
			_dirname="${apkbuild%/*}"
			_dirname="${_dirname##*/}"
			;;
		*) return 0 ;;
	esac
	if [ "$pkgname" != "$_dirname" ]; then
Leo's avatar
Leo committed
212
		printf "IC:[AL23]:$apkbuild::pkgname is '$pkgname' but is in directory '$_dirname'\n"
Leo's avatar
Leo committed
213 214 215
	fi
}

216 217
depends_makedepends_checkdepends_overlap() {
	[ "$SKIP_DEPENDS_MAKEDEPENDS_CHECKDEPENDS_OVERLAP" ] && return 0
Leo's avatar
Leo committed
218
	[ "$SKIP_AL24" ] && return 0
219
	local _mkdeps _ckdeps d
Leo's avatar
Leo committed
220 221
	_mkdeps="$(echo $makedepends | tr " " "\\n" | tr -d "\t" | sort -u)"
	_ckdeps="$(echo $checkdepends | tr " " "\\n" | tr -d "\t" | sort -u)"
222
	[ -z "$_mkdeps" ] && [ -z "$_ckdeps" ] && return 0
Leo's avatar
Leo committed
223 224
	for d in $depends; do
		if printf "%s\\n" "$_mkdeps" | grep -q "^$d$"; then
Leo's avatar
Leo committed
225
			printf "IC:[AL24]:%s::dependency '%s' is in depends and makedepends\n" "$apkbuild" "$d"
Leo's avatar
Leo committed
226
		fi
227 228 229 230

		# Don't check against checkdepends if it is empty
		[ -z "$checkdepends" ] && continue
		if printf "%s\\n" "$_ckdeps" | grep -q "^$d$"; then
Leo's avatar
Leo committed
231
			printf "IC:[AL24]:%s::dependency '%s' is in depends and checkdepends\n" "$apkbuild" "$d"
232 233 234
		fi
	done

Leo's avatar
Leo committed
235 236
	# Don't check against checkdepends if it is empty, no need to check for
	# makedepends because the loop just won't run if it is empty.
237 238 239
	[ -z "$checkdepends" ] && return 0
	for d in $makedepends; do
		if printf "%s\\n" "$_ckdeps" | grep -q "^$d$"; then
Leo's avatar
Leo committed
240
			printf "IC:[AL24]:%s::dependency '%s' is in makedepends and checkdepends\n" "$apkbuild" "$d"
241
		fi
Leo's avatar
Leo committed
242 243 244
	done
}

245 246 247 248 249 250 251 252 253 254
deprecated_packages() {
	[ "$SKIP_DEPRECATED_PACKAGES" ] && return 0
	[ "$SKIP_AL58" ] && return 0
	local _depends _makedepends _checkdepends

	_depends="$(echo $depends | tr " " "\n" | sort -u)"
	_makedepends="$(echo $makedepends | tr " " "\n" | sort -u)"
	_checkdepends="$(echo $checkdepends | tr " " "\n" | sort -u)"
	
	for val in $deprecated_packages; do
255 256 257 258 259 260 261 262 263 264 265 266
		local _apkbuild
		if [ -f "$PWD"/$val/APKBUILD ]; then
			_apkbuild="$PWD"/$val/APKBUILD
		elif [ -f "$PWD"../$val/APKBUILD ]; then
			_apkbuild="$PWD"/$val/APKBUILD
		elif [ -f "$PWD"/../../$val/APKBUILD ]; then
			_apkbuild="$PWD"/../../$val/APKBUILD
		else
			echo "Failed to find APKBUILD for '$val'" ;
			continue
		fi
		. "$_apkbuild" || {
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
			echo "Failed to source APKBUILD in '$val'" ;
			continue
		}
		local invalids="$pkgname $subpackages"
		for invalid in $invalids; do
			if [ "$_depends" ]; then
				echo "$_depends" \
					| grep -q -x "$invalid" && \
					printf "SC:[AL58]:%s::Package '%s' in depends is deprecated\n" \
						"$apkbuild" "$invalid"
			fi
			if [ "$_makedepends" ]; then
				echo "$_makedepends" \
					| grep -q -x "$invalid" && \
					printf "SC:[AL58]:%s::Package '%s' in makedepends is deprecated\n" \
						"$apkbuild" "$invalid"
			fi
			if [ "$_checkdepends" ]; then
				echo "$_checkdepends" \
					| grep -q -x "$invalid" && \
					printf "SC:[AL58]:%s::Package '%s' in checkdepends is deprecated\n" \
						"$apkbuild" "$invalid"
			fi
		done
	done
}

Leo's avatar
Leo committed
294 295
for apkbuild; do
	if [ -f "$apkbuild" ]; then
Leo's avatar
Leo committed
296 297 298

	# Try to guess the repo, first see if our working directory is where
	# the repo is located
Leo's avatar
Leo committed
299
	_repo="${PWD%/*}"
Leo's avatar
Leo committed
300 301 302
	_repo="${_repo%/*}"
	_repo="${_repo##*/}"
	case "$_repo" in
Leo's avatar
Leo committed
303 304
		main|community|testing|unmaintained) ;;
		# Then have the path given to use be used
Leo's avatar
Leo committed
305 306
		*)
			_repo="${apkbuild%/*}"
Leo's avatar
Leo committed
307 308
			_repo="${_repo%/*}"
			_repo="${_repo##*/}"
Leo's avatar
Leo committed
309
			;;
Leo's avatar
Leo committed
310 311 312
	esac

	# Source apkbuild, we need some nice values
313 314 315 316
	srcdir="" . "$apkbuild" || {
		echo "Failed to source APKBUILD in '$apkbuild'" ;
		continue
	}
Leo's avatar
Leo committed
317

Leo's avatar
Leo committed
318
	if [ ! -z "$depends" ]; then
Leo's avatar
Leo committed
319 320
		upper_repo_depends &
		duplicate_depends &
Leo's avatar
Leo committed
321
	fi
Leo's avatar
Leo committed
322 323 324 325
	
	# This can be run if either 2 of the 3 are not empty
	# depends makedepends checkdepends
	depends_makedepends_checkdepends_overlap &
Leo's avatar
Leo committed
326 327

	if [ ! -z "$makedepends" ]; then
Leo's avatar
Leo committed
328 329
		upper_repo_makedepends &
		duplicate_makedepends &
Leo's avatar
Leo committed
330 331
	fi

Leo's avatar
Leo committed
332
	if [ ! -z "$checkdepends" ]; then
333
		if [ -z "$options" ] || [ ! -z "${options##*!check*}" ]; then
Leo's avatar
Leo committed
334
			upper_repo_checkdepends &
335
		fi
Leo's avatar
Leo committed
336
		duplicate_checkdepends &
Leo's avatar
Leo committed
337 338
	fi

339
	if [ -z "$SKIP_DUPLICATE_PACKAGE" ]; then
Leo's avatar
Leo committed
340
		duplicate_package &
341
	fi
342

Leo's avatar
Leo committed
343
	pkgname_dirname_mismatch &
344 345
	
	deprecated_packages &
Leo's avatar
Leo committed
346

Leo's avatar
Leo committed
347
	wait
Leo's avatar
Leo committed
348

Leo's avatar
Leo committed
349 350 351 352 353
	else
	echo no such apkbuild "$apkbuild" 1>&2
	fi | sort -t: -n -k2 | grep . && ret=1
done
exit $ret