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

Leo's avatar
Leo committed
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
# 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
}

55
find_dupe() {
56
	local pkgname="$1" repo="$2" r=
57 58 59 60 61 62 63 64 65

	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
}

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
upper_repo_depends() {
	[ "$SKIP_UPPER_REPO_DEPENDS" ] && return 0
	printf "%s\n" "$depends" | tr " " "\n" | sort -u | while read -r pkg; do
		for p in $(find_repo "$pkg" "$_repo"); do
			printf "$apkbuild:: depends '$pkg' is in upper repo '$p'\n"
		done
	done
}

duplicate_depends() {
	[ "$SKIP_DUPLICATE_DEPENDS" ] && return 0
	printf "%s\n" "$depends" | tr " " "\n" | sort | uniq -d | while read -r dup; do
		[ -z "$dup" ] && continue
		printf "$apkbuild:: duplicate '$dup' in depends\n"
	done
}

upper_repo_makedepends() {
	[ "$SKIP_UPPER_REPO_MAKEDEPENDS" ] && return 0
	printf "%s\n" "$makedepends" | tr " " "\n" | sort -u | while read -r pkg; do
		for p in $(find_repo "$pkg" "$_repo"); do
			printf "$apkbuild:: makedepends '$pkg' is in upper repo '$p'\n"
		done
	done
}

duplicate_makedepends() {
	[ "$SKIP_DUPLICATE_MAKEDEPENDS" ] && return 0
	printf "%s\n" "$makedepends" | tr " " "\n" | sort | uniq -d | while read -r dup; do
		[ -z "$dup" ] && continue
		printf "$apkbuild:: duplicate '$dup' in makedepends\n"
	done
}

upper_repo_checkdepends() {
	[ "$SKIP_UPPER_REPO_CHECKDEPENDS" ] && return 0
	printf "%s\n" "$checkdepends" | tr " " "\n" | sort -u | while read -r pkg; do
		for p in $(find_repo "$pkg" "$_repo"); do
			printf "$apkbuild:: checkdepends '$pkg' is in upper repo '$p'\n"
		done
	done
}

duplicate_checkdepends() {
	[ "$SKIP_DUPLICATE_CHECKDEPENDS" ] && return 0
	printf "%s\n" "$checkdepends" | tr " " "\n" | sort | uniq -d | while read -r dup; do
		[ -z "$dup" ] && continue
		printf "$apkbuild:: duplicate '$dup' in checkdepends\n"
	done
}

duplicate_package() {
Leo's avatar
Leo committed
118
	[ "$SKIP_DUPLICATE_PACKAGE" ] && return 0
119 120 121 122 123
	for _r in $(find_dupe "$pkgname" "$_repo"); do
		printf "$apkbuild:: package is already present in $_r\n"
	done
}

Leo's avatar
Leo committed
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
pkgname_dirname_mismatch() {
	[ "$SKIP_PKGNAME_DIRNAME_MISMATCH" ] && return 0
	local _dirname=
	case "${apkbuild%%/*}" in
		main|community|testing|unmaintained|non-free)
			_dirname="${apkbuild%/*}"
			_dirname="${_dirname##*/}"
			;;
		*) return 0 ;;
	esac
	if [ "$pkgname" != "$_dirname" ]; then
		printf "$apkbuild:: pkgname is '$pkgname' but is in directory '$_dirname'\n"
	fi
}

139 140 141
depends_makedepends_checkdepends_overlap() {
	[ "$SKIP_DEPENDS_MAKEDEPENDS_CHECKDEPENDS_OVERLAP" ] && return 0
	local _mkdeps _ckdeps d
Leo's avatar
Leo committed
142
	_mkdeps="$(echo $makedepends | tr " " "\\n" | sort -u)"
143 144
	_ckdeps="$(echo $checkdepends | tr " " "\\n" | sort -u)"
	[ -z "$_mkdeps" ] && [ -z "$_ckdeps" ] && return 0
Leo's avatar
Leo committed
145 146 147 148
	for d in $depends; do
		if printf "%s\\n" "$_mkdeps" | grep -q "^$d$"; then
			printf "%s:: dependency '%s' is in depends and makedepends\n" "$apkbuild" "$d"
		fi
149 150 151 152 153 154 155 156 157 158 159 160 161 162

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

	# Don't check against checkdepends if it is empty
	[ -z "$checkdepends" ] && return 0
	for d in $makedepends; do
		if printf "%s\\n" "$_ckdeps" | grep -q "^$d$"; then
			printf "%s:: dependency '%s' is in makedepends and checkdepends\n" "$apkbuild" "$d"
		fi
Leo's avatar
Leo committed
163 164 165
	done
}

Leo's avatar
Leo committed
166 167
for apkbuild; do
	if [ -f "$apkbuild" ]; then
Leo's avatar
Leo committed
168 169 170

	# Try to guess the repo, first see if our working directory is where
	# the repo is located
Leo's avatar
Leo committed
171
	_repo="${PWD%/*}"
Leo's avatar
Leo committed
172 173 174
	_repo="${_repo%/*}"
	_repo="${_repo##*/}"
	case "$_repo" in
Leo's avatar
Leo committed
175 176
		main|community|testing|unmaintained) ;;
		# Then have the path given to use be used
Leo's avatar
Leo committed
177 178
		*)
			_repo="${apkbuild%/*}"
Leo's avatar
Leo committed
179 180
			_repo="${_repo%/*}"
			_repo="${_repo##*/}"
Leo's avatar
Leo committed
181
			;;
Leo's avatar
Leo committed
182 183 184
	esac

	# Source apkbuild, we need some nice values
Leo's avatar
Leo committed
185
	srcdir="" . ./"$apkbuild" 2>/dev/null
Leo's avatar
Leo committed
186

Leo's avatar
Leo committed
187
	if [ ! -z "$depends" ]; then
Leo's avatar
Leo committed
188 189
		upper_repo_depends &
		duplicate_depends &
Leo's avatar
Leo committed
190 191 192
	fi

	if [ ! -z "$makedepends" ]; then
Leo's avatar
Leo committed
193 194
		upper_repo_makedepends &
		duplicate_makedepends &
195
		depends_makedepends_checkdepends_overlap &
Leo's avatar
Leo committed
196 197
	fi

Leo's avatar
Leo committed
198
	if [ ! -z "$checkdepends" ]; then
199
		if [ ! -z "${options##*!check*}" ]; then
Leo's avatar
Leo committed
200
			upper_repo_checkdepends &
201
		fi
Leo's avatar
Leo committed
202
		duplicate_checkdepends &
Leo's avatar
Leo committed
203 204
	fi

205
	if [ -z "$SKIP_DUPLICATE_PACKAGE" ]; then
Leo's avatar
Leo committed
206
		duplicate_package &
207
	fi
208

Leo's avatar
Leo committed
209 210
	pkgname_dirname_mismatch &

Leo's avatar
Leo committed
211
	wait
Leo's avatar
Leo committed
212

Leo's avatar
Leo committed
213 214 215 216 217
	else
	echo no such apkbuild "$apkbuild" 1>&2
	fi | sort -t: -n -k2 | grep . && ret=1
done
exit $ret