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

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
# 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

	check_in_repo() { test -d "$1"/"$2" && echo "$1" ; }

	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
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
# 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"
	# 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}"

	check_in_repo() { test -d "$1"/"$2" && echo "$1" ; }

	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
}
102
fi
Leo's avatar
Leo committed
103

104
find_dupe() {
105
	local pkgname="$1" repo="$2" r=
106 107 108 109 110 111 112 113 114

	check_in_repo() { test -d "$1"/"$2" && echo "$1" ; }

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

115 116
upper_repo_depends() {
	[ "$SKIP_UPPER_REPO_DEPENDS" ] && return 0
Leo's avatar
Leo committed
117
	[ "$SKIP_AL16" ] && return 0
118
	printf "%s\n" "$depends" | tr " " "\n" | tr -d "\t" | sort -u | while read -r pkg; do
119
		for p in $(find_repo "$pkg" "$_repo"); do
Leo's avatar
Leo committed
120
			printf "SC:[AL17]:$apkbuild::depends '$pkg' is in upper repo '$p'\n"
121 122 123 124 125 126
		done
	done
}

duplicate_depends() {
	[ "$SKIP_DUPLICATE_DEPENDS" ] && return 0
Leo's avatar
Leo committed
127
	[ "$SKIP_AL17" ] && return 0
128
	printf "%s\n" "$depends" | tr " " "\n" | tr -d "\t" | sort | uniq -d | while read -r dup; do
129
		[ -z "$dup" ] && continue
Leo's avatar
Leo committed
130
		printf "MC:[AL17]:$apkbuild::duplicate '$dup' in depends\n"
131 132 133 134 135
	done
}

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

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

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

duplicate_checkdepends() {
	[ "$SKIP_DUPLICATE_CHECKDEPENDS" ] && return 0
Leo's avatar
Leo committed
165
	[ "$SKIP_AL21" ] && return 0
166
	printf "%s\n" "$checkdepends" | tr " " "\n" | tr -d "\t" | sort | uniq -d | while read -r dup; do
167
		[ -z "$dup" ] && continue
Leo's avatar
Leo committed
168
		printf "MC:[AL21]:$apkbuild::duplicate '$dup' in checkdepends\n"
169 170 171 172
	done
}

duplicate_package() {
Leo's avatar
Leo committed
173
	[ "$SKIP_DUPLICATE_PACKAGE" ] && return 0
Leo's avatar
Leo committed
174
	[ "$SKIP_AL22" ] && return 0
175
	for _r in $(find_dupe "$pkgname" "$_repo"); do
Leo's avatar
Leo committed
176
		printf "SC:[AL22]:$apkbuild::package is already present in $_r\n"
177 178 179
	done
}

Leo's avatar
Leo committed
180 181
pkgname_dirname_mismatch() {
	[ "$SKIP_PKGNAME_DIRNAME_MISMATCH" ] && return 0
Leo's avatar
Leo committed
182
	[ "$SKIP_AL23" ] && return 0
Leo's avatar
Leo committed
183 184 185 186 187 188 189 190 191
	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
192
		printf "IC:[AL23]:$apkbuild::pkgname is '$pkgname' but is in directory '$_dirname'\n"
Leo's avatar
Leo committed
193 194 195
	fi
}

196 197
depends_makedepends_checkdepends_overlap() {
	[ "$SKIP_DEPENDS_MAKEDEPENDS_CHECKDEPENDS_OVERLAP" ] && return 0
Leo's avatar
Leo committed
198
	[ "$SKIP_AL24" ] && return 0
199
	local _mkdeps _ckdeps d
200 201
	_mkdeps="$(echo $makedepends | tr " " "\\n" | tr -d "\t" | sort -u)"
	_ckdeps="$(echo $checkdepends | tr " " "\\n" | tr -d "\t" | sort -u)"
202
	[ -z "$_mkdeps" ] && [ -z "$_ckdeps" ] && return 0
Leo's avatar
Leo committed
203 204
	for d in $depends; do
		if printf "%s\\n" "$_mkdeps" | grep -q "^$d$"; then
Leo's avatar
Leo committed
205
			printf "IC:[AL24]:%s::dependency '%s' is in depends and makedepends\n" "$apkbuild" "$d"
Leo's avatar
Leo committed
206
		fi
207 208 209 210

		# 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
211
			printf "IC:[AL24]:%s::dependency '%s' is in depends and checkdepends\n" "$apkbuild" "$d"
212 213 214
		fi
	done

Leo's avatar
Leo committed
215 216
	# 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.
217 218 219
	[ -z "$checkdepends" ] && return 0
	for d in $makedepends; do
		if printf "%s\\n" "$_ckdeps" | grep -q "^$d$"; then
Leo's avatar
Leo committed
220
			printf "IC:[AL24]:%s::dependency '%s' is in makedepends and checkdepends\n" "$apkbuild" "$d"
221
		fi
Leo's avatar
Leo committed
222 223 224
	done
}

Leo's avatar
Leo committed
225 226
for apkbuild; do
	if [ -f "$apkbuild" ]; then
Leo's avatar
Leo committed
227 228 229

	# Try to guess the repo, first see if our working directory is where
	# the repo is located
Leo's avatar
Leo committed
230
	_repo="${PWD%/*}"
Leo's avatar
Leo committed
231 232 233
	_repo="${_repo%/*}"
	_repo="${_repo##*/}"
	case "$_repo" in
Leo's avatar
Leo committed
234 235
		main|community|testing|unmaintained) ;;
		# Then have the path given to use be used
Leo's avatar
Leo committed
236 237
		*)
			_repo="${apkbuild%/*}"
Leo's avatar
Leo committed
238 239
			_repo="${_repo%/*}"
			_repo="${_repo##*/}"
Leo's avatar
Leo committed
240
			;;
Leo's avatar
Leo committed
241 242 243
	esac

	# Source apkbuild, we need some nice values
244 245 246 247
	srcdir="" . "$apkbuild" || {
		echo "Failed to source APKBUILD in '$apkbuild'" ;
		continue
	}
Leo's avatar
Leo committed
248

Leo's avatar
Leo committed
249
	if [ ! -z "$depends" ]; then
Leo's avatar
Leo committed
250 251
		upper_repo_depends &
		duplicate_depends &
Leo's avatar
Leo committed
252
	fi
Leo's avatar
Leo committed
253 254 255 256
	
	# 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
257 258

	if [ ! -z "$makedepends" ]; then
Leo's avatar
Leo committed
259 260
		upper_repo_makedepends &
		duplicate_makedepends &
Leo's avatar
Leo committed
261 262
	fi

Leo's avatar
Leo committed
263
	if [ ! -z "$checkdepends" ]; then
264
		if [ -z "$options" ] || [ ! -z "${options##*!check*}" ]; then
Leo's avatar
Leo committed
265
			upper_repo_checkdepends &
266
		fi
Leo's avatar
Leo committed
267
		duplicate_checkdepends &
Leo's avatar
Leo committed
268 269
	fi

270
	if [ -z "$SKIP_DUPLICATE_PACKAGE" ]; then
Leo's avatar
Leo committed
271
		duplicate_package &
272
	fi
273

Leo's avatar
Leo committed
274 275
	pkgname_dirname_mismatch &

Leo's avatar
Leo committed
276
	wait
Leo's avatar
Leo committed
277

Leo's avatar
Leo committed
278 279 280 281 282
	else
	echo no such apkbuild "$apkbuild" 1>&2
	fi | sort -t: -n -k2 | grep . && ret=1
done
exit $ret