# 
# Copyright (c) 2010-2026 Samuel Thibault <samuel.thibault@ens-lyon.org>
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 
# THIS SOFTWARE IS PROVIDED BY Samuel Thibault ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
# EVENT SHALL Samuel Thibault BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
# OF SUCH DAMAGE.
#
# TODO: pour le mode "j'affiche toutes les dépendances qui font suer", n'afficher que celles pour les paquets qui du coup ne sont pas disponibles.

CFLAGS=-O2 -g #-Wall
LDLIBS=-lfl

SHELL=bash

include .arch

# gnupg (> 2) doesn't actually exist, don't use that dep, and let gnupg2 show up instead.
HACKDEPS = | sed -e 's/gnupg:$(ARCH) (> 2) | gnupg2/gnupg2/' -e 's/gnupg (> 2) | gnupg2/gnupg2/' -e 's/gnupg (>= 2) | gnupg2/gnupg2/'
BLACKLIST = net-tools

UPLOAD=people.debian.org:public_html/$(ARCH)/

#List of "failing" sets
#auto-not-for-us not-for-us last because it should never happen bd-uninstallable first because it produces uncertain colors
LISTS=bd-uninstallable dep-wait build-attempted failed building needs-build built uploaded auto-not-for-us not-for-us
FAIL_LISTS=dep-wait build-attempted failed auto-not-for-us not-for-us bd-uninstallable
SOME_BUILDD=srsbuildd

.PHONY: all
all: graph-uninstallable.fig graph-total-top.txt graph-top.txt graph-radial.fig graph-all-radial.fig graph-total-radial.fig graph-radial.ps graph-radial.pdf graph-radial.svg graph.xml summary.txt out_of_date.txt out_of_date2.txt installed.lst
# graph-uninstallable-all.fig 

upload: failed_packages.txt
	scp -4 -r archive $(UPLOAD)
	scp -4 graph.dot graph-radial.* graph-all-radial.* graph-uninstallable*.fig graph-total-top.txt graph-top.txt summary.txt out_of_date.txt out_of_date2.txt $(UPLOAD)
	scp -4 *.py *.l Makefile tail.dot Packages-hand $(UPLOAD)/scripts/

LIGHT = summary.txt failed.txt out_of_date.txt out_of_date2.txt
clean-light:
	rm -f $(LIGHT)
light: $(LIGHT)

upload-light:
	scp -4 $(LIGHT) $(UPLOAD)


WANNA_BUILD_NOARCH=/usr/local/bin/wanna-build -d sid --api=1
WANNA_BUILD=$(WANNA_BUILD_NOARCH) -A $(ARCH)

BUILDD=ssh -C -o ControlMaster=auto -o ControlPath=$$HOME/.ssh/master/%r@%h:%p -o ControlPersist=300 buildd.debian.org

.PHONY: failed_packages.txt
failed_packages.txt:
	( $(BUILDD) $(WANNA_BUILD) --list=failed ; $(BUILDD) $(WANNA_BUILD) --list=build-attempted ) > $@
	scp -4 $@ $(UPLOAD)

failed_diff.txt: failed.lst
	( for i in $$(cat $<) ; do \
		if grep -q "^$$i\$$" ../installed.lst ; then \
			echo $$i ; \
		fi ; \
	done ) > $@

pretend:
	-$(BUILDD) cd deps \; make

SHOW_DEPS=
# show all deps of dep-wait and building packages
# XXX clutters the figure...
SHOW_DEPS+=dep-wait-deps.dot
SHOW_DEPS+=failed-deps.dot
SHOW_DEPS+=build-attempted-deps.dot

FILTER_DEPS=tr , '\n' | grep -v '|' | grep -v 'debhelper-compat' | grep -v 'gettext' | grep -ve '! *$(ARCH)' | sed -e 's/<[^>]*>//g' | sed -e 's/([^)]*)//g' | sed -e '/\[[^]]*$(ARCH)[^]]*\]/s/\[[^]]*\]//g' | grep -v '\[[^!]*\]' | sed -e 's/\[[^]]*\]//g'
MANGLE_DEPS=sed -e 's/\(librust-.*\)+[^+]*-dev/\1-dev/' | sed -e  's/\(librust-.*\)\(-[0-9.]*\)-dev/\1-dev/'

#
# How to get data
#
dep-wait.txt auto-not-for-us.txt not-for-us.txt built.txt uploaded.txt failed.txt build-attempted.txt needs-build.txt building.txt all.txt installed.txt: %.txt:
	$(BUILDD) $(WANNA_BUILD) --list=$* | head -n -1 > $@
bd-uninstallable.txt:
	$(BUILDD) $(WANNA_BUILD) --list=bd-uninstallable $(HACKDEPS) | head -n -1 > $@

#
# Final dotty invocation
#
%-flat.fig: %.dot
	dot -Nshape=polygon -Tfig -o $@ $<
%-circo.fig: %.dot
	circo -Nshape=polygon -Tfig -o $@ $<
%-radial.ps: %.dot
	twopi -Nshape=polygon -Tps -o $@ $<
%-radial.pdf: %.dot
	twopi -Nshape=polygon -Tpdf -o $@ $<
%-radial.svg: %.dot
	twopi -Nshape=polygon -Tsvg -o $@ $<
%-radial.fig: %.dot
	twopi -Nshape=polygon -Tfig -o $@ $<
%-radial.dot: %.dot
	twopi -Nshape=polygon -Tdot -o $@ $<
%-patchwork.dot: %.dot
	patchwork -Nshape=polygon -Tdot -o $@ $<
%.gxl: %.dot
	dot2gxl -o $@ $<
%.xml: %-patchwork.dot Makefile
	tail -n +3 $< | ( \
		echo '<?xml version="1.0" ?>' ; \
		echo '<digraph>' ; \
		sed -n \
		       -e '/^[ 	]*fontcolor=.*/d' \
		       -e '/^[ 	]*height=.*/d' \
		       -e '/^[ 	]*width=.*/d' \
		       -e '/^[ 	]*pos=.*/d' \
		       -e '/^[ 	]*shape=.*/d' \
		       -e '/^[ 	]*style=.*/d' \
		       -e '/^[ 	]*fillcolor=.*/d' \
		       -e 's_^[ 	]*\([^"	 ]*\)[ 	]*\(\[.*\)$$_ 	"\1"	\2_' \
		       -e 's_^[ 	]*\([^"	 ]*\) -> \([^"	 ]*\)[ 	]*\(\[.*\)$$_	"\1" -> "\2" \3_' \
		       -e 's_^[ 	]*"\([^"	 ]*\)" -> \([^"	 ]*\)[ 	]*\(\[.*\)$$_	"\1" -> "\2" \3_' \
		       -e 's_^[ 	]*\([^"	 ]*\) -> "\([^"	 ]*\)"[ 	]*\(\[.*\)$$_	"\1" -> "\2" \3_' \
		       -e 's_^[ 	]*\("[^"]*"\)[ 	]*\[height=.*$$_	\1	[fillcolor=white,_' \
		       -e 's_^[ 	]*"\([^"]*\)"[ 	]*\[fillcolor=\([^], ]*\).*$$_<node id="\1"><attribute attr="\2"/></node>_p' \
		       -e 's_^[ 	]*"\([^"]*\)"[ 	]*\[color=green.*$$_<node id="\1"><attribute attr="red"/></node>_p' \
		       -e 's_^[ 	]*"\([^"]*\)" -> "\([^"]*\)"[ 	]*.*$$_<edge from="\1" label="" to="\2" wt="1"/>_p' \
		       ; \
		echo '</digraph>' ; \
	) > $@


%-top.txt: %.xml
	( ( LANG=C date ; \
	echo "child.	depth	package		biggest example of dep chain" ; \
	LANG=C.UTF-8 ./top.py $< | sort -n -r | $(BUILDD) while read child depth package rest \; \
	do \
		\[ \$$child -ge 10 \] \|\| continue \; \
		echo \"\$$child\	\$$depth\	\$$package\	\$$rest\" \; \
		$(WANNA_BUILD) -i \$$package \| sed -ne \'/^\ \ State\ /p\;/^\ \ Depends\ /p\;/^\ \ Failed\ /,/^\ \ Notes\ /p\;/^\ \ BD-Problem\ /,/^\ \ CalculatedPri\ /p\' \| grep -v \'^\ \ Notes\ \'  \| grep -v \'^\ \ CalculatedPri\ \' \| sed -e \'s/^/\	\	\	\	/\' \; \
	done ; \
	echo "less than 9 children: not represented here" ) > $@ ) 2>&1 | ( grep -v virtual-gnutls-dev ; true )

graph.dot: uninstallable-source.dot dep-wait-src.dot dep-wait-bogus.dot $(addsuffix .dot,$(LISTS)) dep-wait-all.dot tail.dot
	( \
		echo "strict digraph deps {" ; \
		echo "\""$$(LANG=C date)"\" -> \"Needs-Build\"" ; \
		cat $^ ; \
		echo "}" \
	) > $@

graph-all.dot: uninstallable-source.dot dep-wait-src.dot dep-wait-bogus.dot $(SHOW_DEPS) $(addsuffix .dot,$(LISTS)) dep-wait-all.dot tail.dot
	( \
		echo "strict digraph deps {" ; \
		echo "\""$$(LANG=C date)"\" -> \"Needs-Build\"" ; \
		cat $^ ; \
		echo "}" \
	) > $@

graph-total-radial.fig: graph-total.dot
	twopi -Nshape=polygon -Tfig -o $@ $<
graph-total-radial.dot: graph-total.dot
	twopi -Nshape=polygon -Tdot -o $@ $<
graph-total.dot: uninstallable-source.dot dep-wait-src.dot dep-wait-bogus.dot dep-wait-deps.dot build-attempted-deps.dot failed-deps.dot $(addsuffix .dot,$(LISTS)) dep-wait-all.dot tail.dot
	( \
		echo "strict digraph deps {" ; \
		cat $^ ; \
		echo "}" \
	) > $@

#
# Simple rules for setting colors
#
define txt2lst
$1.lst: $2 $1.txt
	./$$< < $1.txt 2> /dev/null > $$@
endef
define lst2dot
$1.dot: $1.lst
	( for i in $$$$(sort < $$<) ; \
	do \
		echo "\"$$$$i\" [fillcolor=$2,fontcolor=$3,style=filled,shape=ellipse]" ; \
	done ) > $$@
endef
define txt2dot
$(eval $(call txt2lst,$1,$2))
$(eval $(call lst2dot,$1,$3,$4))
endef
$(eval $(call txt2dot,dep-wait,wb,lightgrey,black))
$(eval $(call txt2dot,needs-build,wb,burlywood,black))
$(eval $(call txt2dot,building,wb,palegreen,black))
$(eval $(call txt2dot,uploaded,wb,green,black))
$(eval $(call txt2dot,built,wb,green,black))
$(eval $(call txt2dot,build-attempted,wb,OrangeRed,black))
$(eval $(call txt2dot,failed,wb,red,black))
$(eval $(call txt2dot,auto-not-for-us,wb,black,white))
$(eval $(call txt2dot,not-for-us,wb,black,white))
$(eval $(call txt2lst,all,wb))
$(eval $(call txt2lst,installed,wb))

bd-uninstallable.lst: bd-uninstallable.txt
	grep '^[^ ]' $< | cut -d / -f 2 | cut -d _ -f 1 | grep -v '^Total .*$$' > $@

bd-uninstallable-src.txt: bd-uninstallable.txt
	sed -n -e 's/    - \([^ ]*\).*/\1/p' $< | sed -e 's/$(ARCH)://' | sed -e 's/:$(ARCH)//' > $@

bd-uninstallable.dot: bd-uninstallable bd-uninstallable.txt
	./$< < $<.txt 2> /dev/null > $@
#bd-uninstallable.dot: bd-uninstallable.txt
#	sed -n \
#		-e 's/ *\([^ ]*\) .*build-depends on .*:$$/"\1" /h;s/^    - ([^ ])*$
#		
#		[fillcolor=orange,fontcolor=black,style=filled,shape=ellipse]\n\"\2\" -> \"\1\" [ style=solid ]/p' \
#		-e 's/ *\([^ ]*\) .*depends on \([^ ]*\) .*/\"\1\" [fillcolor=orange,fontcolor=black,style=filled]\n\"\2\" -> \"\1\" [ style=solid ]/p' \
#		$< > $@

bd-uninstallable-only.dot: bd-uninstallable.dot
	grep -v -- '->' $< > $@

#MIRROR=mirror.ftp-master.debian.org:/srv/mirrors/debian
MIRROR=mirror.ftp-master.debian.org:/srv/mirrors/debian-ports
MIRROR_SRC=mirror.ftp-master.debian.org:/srv/mirrors/debian
Packages-main:
	scp -qp $(MIRROR)/dists/unstable/main/binary-$(ARCH)/Packages.xz $@.xz
	xz -d < $@.xz | sed 's/:any//g' > $@
	rm -f $@.xz

Packages-main-unreleased:
	scp -qp $(MIRROR)/dists/unreleased/main/binary-$(ARCH)/Packages.xz $@.xz
	xz -d < $@.xz | sed 's/:any//g' > $@
	rm -f $@.xz

Packages-main-exp:
	scp -qp $(MIRROR)/dists/experimental/main/binary-$(ARCH)/Packages.xz $@.xz
	xz -d < $@.xz | sed 's/:any//g' > $@
	rm -f $@.xz

Sources-main:
	scp -qp $(MIRROR_SRC)/dists/unstable/main/source/Sources.xz $@.xz
	xz -d $@.xz

Sources-main-exp:
	scp -qp $(MIRROR_SRC)/dists/experimental/main/source/Sources.xz $@.xz
	xz -d $@.xz

# empty unless we really to put something in it by hand
Packages-hand:
	touch $@

#Packages-main:
#	wget -q -O - http://cdn.debian.net/debian/dists/unstable/main/binary-$(ARCH)/Packages.xz | xz -d | sed 's/:any//g' > $@
#
#Packages-main-exp:
#	wget -q -O - http://cdn.debian.net/debian/dists/experimental/main/binary-$(ARCH)/Packages.xz | xz -d | sed 's/:any//g' > $@
#
#Sources-main:
#	wget -q -O - http://cdn.debian.net/debian/dists/unstable/main/source/Sources.xz | xz -d > $@

myPackages: Packages-main Packages-main-unreleased
	grep-aptavail -sPackage,Source,Provides "" $^ > $@

mySources: Sources-main
	grep-aptavail -sPackage,Source,Binary,Build-Depends,Architecture "" $^ > $@

Packages-dp:
	wget -q http://ftp.debian-ports.org/debian/dists/unreleased/main/binary-$(ARCH)/Packages.bz2 -O - | bunzip2 > $@

	#ssh $(SOME_BUILDD) wget -q -O - http://incoming.debian.org/debian-buildd/dists/buildd-sid/main/binary-$(ARCH)/Packages.xz | xz -d | sed 's/:any//g' > $@
incomingPackages:
	wget -q -O - http://incoming.ports.debian.org/buildd/dists/sid/main/binary-$(ARCH)/Packages.xz | xz -d | sed 's/:any//g' > $@

Packages-incoming: incomingPackages
	grep-dctrl -FArchitecture $(ARCH) $< | sed 's/:any//g' > $@

#uninstallable.dot: Packages-main Packages-main-unreleased Packages-hand
#	cat $^ | dose-debcheck --failures --quiet 2> /dev/null | sed -e 's/\([^ ]*\).*/"\1" [fillcolor=orange,fontcolor=black,style=filled]/g' > $@

hurd-packages: Packages-main Packages-main-unreleased Packages-hand Packages-incoming
	grep-aptavail -X -n -FArchitecture -sPackage $(ARCH) $^ | grep -v ^$$ > $@
all-packages: Packages-main Packages-main-unreleased Packages-hand Packages-incoming
	grep-aptavail -X -n -FArchitecture -sPackage all $^ | grep -v ^$$ > $@
NMAX=5000
uninstallable.txt: hurd-packages Packages-main Packages-main-unreleased Packages-hand Packages-incoming
	-( \
		N=$$(wc -l < $<) ; \
		for i in $$(seq 0 $$(( N / ($(NMAX) - 1) ))) ; do \
			< $< tail -n +$$((i * $(NMAX) + 1)) | head -n $(NMAX) | tr '\n' , | sed -e s/,$$// > $<N ; \
			cat Packages* | dose-debcheck --failures --explain --checkonly "`cat $<N`" --quiet 2> /dev/null ; \
		done \
	) $(HACKDEPS) > $@
	rm -f $<N
uninstallable-all.txt: all-packages Packages-main Packages-main-unreleased Packages-hand Packages-incoming
	-( \
		N=$$(wc -l < $<) ; \
		for i in $$(seq 0 $$(( N / ( $(NMAX) - 1) ))) ; do \
			< $< tail -n +$$((i * $(NMAX) + 1)) | head -n $(NMAX) | tr '\n' , | sed -e s/,$$// > $<N ; \
			cat Packages* | dose-debcheck --failures --explain --checkonly "`cat $<N`" --quiet 2> /dev/null ; \
		done \
	) > $@
	rm -f $<N
#uninstallable-source%: uninstallable% myPackages
#	#test `grep '^[^ ]' $< | wc -l` -lt 1000
#	cat $< | \
#	while read line ; do \
#		if echo $$line | grep -q "depends on" ; then \
#			package=`echo $$line | cut -d ' ' -f 1` ; \
#			source_package=`grep-aptavail -X -FPackage -sSource:Package $$package myPackages | head -n 1 | cut -d ' ' -f 2` ; \
#			[ -z "$$source_package" ] && source_package=$$package; \
#			echo "$$line" | sed -e "s/$$package/$$package($$source_package)/g" ; \
#		else \
#			echo "$$line" ; \
#		fi; \
#	done > $@
#uninstallable-source.dot: uninstallable-source%dot: uninstallable uninstallable-source%txt
#	 ./$< < uninstallable-source$*txt > $@

uninstallable-source.dot: uninstallable-source%.dot: uninstallable%.txt uninstallable
	 ./uninstallable < $< > $@

graph-uninstallable%dot: uninstallable-source%dot bd-uninstallable-only.dot needs-build.dot building.dot built.dot uploaded.dot auto-not-for-us.dot not-for-us.dot dep-wait.dot build-attempted.dot failed.dot tail.dot
	( \
		echo "strict digraph deps {" ; \
		echo "\""$$(LANG=C date)"\" -> \"Needs-Build\"" ; \
		cat $^ ; \
		echo "}" \
	) > $@
	
graph-uninstallable%fig: graph-uninstallable%dot
	twopi -Nshape=polygon -T fig -o $@ $<

#
# deps of uploaded packages aren't suseful to show
#
uploaded-deps.dot:
	touch $@
built-deps.dot:
	touch $@

#
# Show all build-deps of failed and dep-wait packages, not only those expressed in the wanna-build db
#
build-attempted-deps.dot failed-deps.dot dep-wait-deps.dot: %-deps.dot: $(addsuffix .lst,$(FAIL_LISTS)) all.lst mySources
	# For each (potentially) failing package i, guess all problematic dependencies
	( for i in $$(grep -v '^glibc$$' < $*.lst | sort) ; \
	do \
		# look at build-deps of i \
		for j in $$(grep-aptavail -X -n -FPackage -sBuild-Depends $$i mySources | head -n 1 | $(FILTER_DEPS) ) ; \
		do \
			# for each of them (j), find the corresponding source package src \
			src=$$(grep-aptavail -r -n -FBinary -sPackage "\(^\| \)$$j\(,\|$$\)" mySources | head -n1 | grep -v $(BLACKLIST)) ; \
			provider=$$(echo $$j | $(MANGLE_DEPS)) ; \
			if [ -z "$$src" -a "$$j" != "$$provider" ]; \
			then \
				src=$$(grep-aptavail -r -n -FBinary -sPackage "\(^\| \)$$provider\(,\|$$\)" mySources | head -n1 | grep -v $(BLACKLIST)) ; \
				if [ -n "$$src" ]; \
				then \
					# found it, explicit all the path so that we know the name of the virtual package \
					if grep -q "^$$src$$" $(addsuffix .lst,$(FAIL_LISTS)) ; \
					then \
						# that source has troubles too, show the dependency \
						echo "\"$$src\" [ shape=ellipse ]" ; \
						echo "\"$$src\" -> \"$$provider\" [ style=dotted ]" ; \
						echo "\"$$provider\" -> \"$$j\" [ style=dashed ]" ; \
						echo "\"$$j\" -> \"$$i\" [ style=dashed ]" ; \
					else \
						if ! grep -q "^$$src$$" all.lst && [ "$$(grep-aptavail -r -n -sArchitecture -FPackage "^$$src$$" mySources | head -n 1)" != all ] ; \
						then \
							echo "\"$$src\" [ shape = ellipse, fillcolor=black,fontcolor=white ]" ; \
							echo "\"$$src\" -> \"$$provides\" [ style=dotted ]" ; \
							echo "\"$$provides\" -> \"$$i\" [ style=dashed ]" ; \
						fi \
					fi ; \
				fi ; \
			fi; \
			if [ -z "$$src" ]; \
			then \
				# if no source package seems available, look for a package that Provides it \
				provides=$$(grep-aptavail -r -n -FProvides -sPackage "\(^\| \)$$j\(,\|$$\)" myPackages 2> /dev/null | head -n 1) \
				src=$$(grep-aptavail -r -n -FBinary -sPackage "\(^\| \)$$provides\(,\|$$\)" mySources | head -n1) ; \
				if [ -n "$$src" ]; \
				then \
					# found it, explicit all the path so that we know the name of the virtual package \
					if grep -q "^$$src$$" $(addsuffix .lst,$(FAIL_LISTS)) ; \
					then \
						# that source has troubles too, show the dependency \
						echo "\"$$src\" [ shape=ellipse ]" ; \
						echo "\"$$src\" -> \"$$provides\" [ style=dotted ]" ; \
						echo "\"$$provides\" -> \"$$j\" [ style=dashed ]" ; \
						echo "\"$$j\" -> \"$$i\" [ style=dashed ]" ; \
					else \
						if ! grep -q "^$$src$$" all.lst && [ "$$(grep-aptavail -r -n -sArchitecture -FPackage "^$$src$$" mySources | head -n 1)" != all ] ; \
						then \
							echo "\"$$src\" [ shape = ellipse, fillcolor=black,fontcolor=white ]" ; \
							echo "\"$$src\" -> \"$$provides\" [ style=dotted ]" ; \
							echo "\"$$provides\" -> \"$$i\" [ style=dashed ]" ; \
						fi \
					fi ; \
				else \
					# else we don't know how to build the build-dep !! \
					echo "\"$$j\" [fillcolor=magenta,fontcolor=black,style=filled]" ; \
					echo "\"$$j\" -> \"$$i\" [ style=dashed ]" ; \
				fi ; \
			else \
				# found a source that provides the package \
				if grep -q "^$$src$$" $(addsuffix .lst,$(FAIL_LISTS)) && [ "$$i" != "$$src" ] ; \
				then \
					# that source has troubles too, show the dependency \
					# Pb: doesn't mean the binary package can't be installed... \
					echo "\"$$src\" [ shape = ellipse ]" ; \
					echo "\"$$src\" -> \"$$i\" [ style=dashed ]" ; \
				else \
					if ! grep -q "^$$src$$" all.lst && [ "$$(grep-aptavail -r -n -sArchitecture -FPackage "^$$src$$" mySources | head -n 1)" != all ] ; \
					then \
						# Unknown package \
						echo "\"$$src\" [ shape = ellipse ]" ; \
						echo "\"$$src\" [ fillcolor=black,fontcolor=white ]" ; \
						echo "\"$$src\" -> \"$$i\" [ style=dashed ]" ; \
					fi ; \
				fi; \
			fi ; \
		done ; \
	done ) > $@

#
# dep-wait are white, and show their source packages.
#
dep-wait-all.dot: dep-wait dep-wait.txt
	./$< < dep-wait.txt 2> /dev/null > $@

dep-wait-bogus.dot: dep-wait-all.dot mySources
	< $< grep -- '->' | cut -d ' ' -f 1,3 | tr -d '"' | ( \
		while read bin src ; \
		do \
			grep-aptavail -X -n -FPackage -sBuild-Depends $$src mySources | $(FILTER_DEPS) | grep -q $$bin || echo "\"$$bin\" -> \"$$src\" [ color=magenta ]" ; \
		done \
	) > $@

dep-wait-src.lst: dep-wait-src dep-wait.txt
	./$< < dep-wait.txt 2> /dev/null > $@

#
# Show the dependencies expressed in the wanna-build db
#
dep-wait-src.dot: dep-wait-src.lst bd-uninstallable-src.txt $(addsuffix .lst,$(LISTS)) mySources myPackages all.lst
	( \
		# for each needed package i, show the source \
		for i in $$(cat dep-wait-src.lst bd-uninstallable-src.txt | sort -u) ; \
		do \
			src=$$(grep-aptavail -r -n -FBinary -sPackage "\(^\| \)$$i\(,\|$$\)" mySources | head -n1 | grep -v $(BLACKLIST)) ; \
			provider=$$(echo $$i | $(MANGLE_DEPS)) ; \
			if [ -z "$$src" -a "$$i" != "$$provider" ]; \
			then \
				src=$$(grep-aptavail -r -n -FBinary -sPackage "\(^\| \)$$provider\(,\|$$\)" mySources | head -n1 | grep -v $(BLACKLIST)) ; \
				if [ -n "$$src" ]; \
				then \
					# found it, explicit all the path so that we know the name of the virtual package \
					if grep -q "^$$src$$" $(addsuffix .lst,$(FAIL_LISTS)) ; \
					then \
						# that source has troubles too, show the dependency \
						echo "\"$$src\" [ shape=ellipse ]" ; \
						echo "\"$$src\" -> \"$$provider\" [ style=dotted ]" ; \
						echo "\"$$provider\" -> \"$$i\" [ style=dashed ]" ; \
					else \
						if ! grep -q "^$$src$$" all.lst && [ "$$(grep-aptavail -r -n -sArchitecture -FPackage "^$$src$$" mySources | head -n 1)" != all ] ; \
						then \
							echo "\"$$src\" [ shape = ellipse, fillcolor=black,fontcolor=white ]" ; \
							echo "\"$$src\" -> \"$$provides\" [ style=dotted ]" ; \
							echo "\"$$provides\" -> \"$$i\" [ style=dashed ]" ; \
						fi \
					fi ; \
				fi ; \
			fi; \
			if [ -z "$$src" ]; \
			then \
				# no source, try to find a package that Provides it \
				provides=$$(grep-aptavail -r -n -FProvides -sPackage "\(^\| \)$$i\(,\|$$\)" myPackages 2> /dev/null | head -n 1) \
				src=$$(grep-aptavail -r -n -FBinary -sPackage "\(^\| \)$$provides\(,\|$$\)" mySources | head -n1) ; \
				if [ -n "$$provides" -a -n "$$src" ] ; \
				then \
					# got it, print the whole path \
					if grep -q "^$$src$$" $(addsuffix .lst,$(LISTS)) ; \
					then \
						echo "\"$$src\" [ shape = ellipse ]" ; \
						echo "\"$$src\" -> \"$$provides\" [ style=solid ]" ; \
						echo "\"$$provides\" -> \"$$i\" [ style=solid ]" ; \
					else \
						if ! grep -q "^$$src$$" all.lst && [ "$$(grep-aptavail -r -n -sArchitecture -FPackage "^$$src$$" mySources | head -n 1)" != all ] ; \
						then \
							echo "\"$$src\" [ shape = ellipse, fillcolor=black,fontcolor=white ]" ; \
							echo "\"$$src\" -> \"$$provides\" [ style=solid ]" ; \
							echo "\"$$provides\" -> \"$$i\" [ style=solid ]" ; \
						fi \
					fi \
				else \
					# else we don't know how to build the build-dep !! \
					echo "\"$$i\" [fillcolor=magenta,fontcolor=black,style=filled]" ; \
				fi \
			else \
				# show which package should be able to provide it \
				echo "\"$$src\" [ shape = ellipse ]" ; \
				if ! grep -q "^$$src$$" all.lst && [ "$$(grep-aptavail -r -n -sArchitecture -FPackage "^$$src$$" mySources | head -n 1)" != all ] ; \
				then \
					echo "\"$$src\" [ fillcolor=black,fontcolor=white ]" ; \
				fi ; \
				echo "\"$$src\" -> \"$$i\" [ style=solid ]" ; \
			fi \
		done \
	) > $@

# rm -f dep-wait dep-wait-src bd-uninstallable uninstallable wb
clean:
	rm -f dep-wait.o dep-wait.c dep-wait-all.dot dep-wait.lst \
	dep-wait-src.lst dep-wait-src.o \
	dep-wait-src.dot \
	dep-wait-only.dot dep-wait-deps.dot dep-wait.dot \
	auto-not-for-us* not-for-us* built* uploaded* building* build-attempted* failed* needs-build* \
	bd-uninstallable.dot bd-uninstallable-only.dot bd-uninstallable.lst \
	*.txt \
	uninstallable.c uninstallable-source.dot \
	incomingPackages Packages-main Packages-main-unreleased Packages-main-exp Packages-incoming Packages-dp \
	Sources-main* haskell-list haskell-deps.xml \
	all-packages*

%-radial.gdf: %-radial.dot
	( \
		convcolor() { \
			case $$1 in \
			''|white) echo 255,255,255,255 ;; \
			black) echo 0,0,0,255 ;; \
			red) echo 255,0,0,255 ;; \
			blue) echo 0,255,0,255 ;; \
			green) echo 0,0,255,255 ;; \
			magenta) echo 255,0,255,255 ;; \
			cyan) echo 0,255,255,255 ;; \
			yellow) echo 255,255,0,255 ;; \
			orange) echo 255,165,0,255 ;; \
			purple) echo 160,32,240,255 ;; \
			palegreen) echo 152,251,152,255 ;; \
			burlywood) echo 222,184,135,255 ;; \
			*) echo 1>&2 $$1 unknown ;; \
			esac \
		} ; \
		echo 'nodedef> name,label,x,y,color,shape VARCHAR(16)' ; \
		i=0; \
		< $< tail -n +4 | head -n -1 | grep -v -- '->' | \
		while read line ; \
		do \
			name=`echo $$line | cut -d ' ' -f 1 | tr -d '"'` ; \
			shape=`echo $$line | sed -n -e 's/.*shape=\([^], ]*\).*/\1/p'` ; \
			color=`echo $$line | sed -n -e 's/.*fillcolor=\([^], ]*\).*/\1/p'` ; \
			color=`convcolor $$color` ; \
			x=`echo $$line | sed -n -e 's/.*pos="\([^], ]*\).*/\1/p'` ; \
			y=`echo $$line | sed -n -e 's/.*pos="[0-9]*,\([^], "]*\).*/\1/p'` ; \
			echo v$$i,$$name,$$x,$$y,\"$$color\",$$shape ; \
			i=$$(($$i + 1)) ; \
		done ; \
		echo 'edgedef> node1,node2,color' ; \
		< $< grep -- '->' | \
		while read line ; \
		do \
			name1=`echo $$line | cut -d ' ' -f 1 | tr -d '"'` ; \
			name2=`echo $$line | cut -d ' ' -f 3 | tr -d '"'` ; \
			color=`echo $$line | sed -n -e 's/.*fillcolor=\([^, \]]\).*/\1/p'` ; \
			color=`convcolor $$color` ; \
		done ; \
	) > $@


out_of_date.txt:
	( $(BUILDD) \
	for package in \$$\( $(WANNA_BUILD) --order=W --list=all \| grep out-of-date \| grep -v Needs-Build \| grep -v Building \| grep -v Built \| grep -v Uploaded \| grep -v Installed \| cut -d _ -f 1 \| sed 's_.\*/__' \) \; \
	do \
	  if $(WANNA_BUILD_NOARCH) -A i386 -i \$$package \| grep \"^\ \ State\ \ \" \| grep -q \"Failed\\\|Build-Attempted\\\|BD-Uninstallable\" \|\| \
	     $(WANNA_BUILD_NOARCH) -A amd64 -i \$$package \| grep \"^\ \ State\ \ \" \| grep -q \"Failed\\\|Build-Attempted\\\|BD-Uninstallable\" \; then continue \; fi \; \
	  echo \$$package \; \
	  $(WANNA_BUILD) -i \$$package \| sed -ne \'/^\ \ State\ /p\;/^\ \ Depends\ /p\;/^\ \ Failed\ /,/^\ \ Notes\ /p\;/^\ \ BD-Problem\ /,/^\ \ CalculatedPri\ /p\;/^\ \ State-Days\ /p\' \| grep -v \'^\ \ Build-Arch-All\ \' \| grep -v \'^\ \ Notes\ \' \| grep -v \'^\ \ CalculatedPri\ \' \| sed -e \'s/^/\	\	\	\	/\' \; \
	done ) > $@

out_of_date_stats.txt: out_of_date.txt Makefile
	( \
	  echo -n "total: " ; grep -v "^	" $< | wc -l ; \
	  echo -n "bugreport: " ; grep "#[0-9][0-9][0-9][0-9][0-9][0-9]" $< | wc -l ; \
	  echo -n "iceweasel: " ; grep -- "- iceweasel-dev" $< | wc -l ; \
	  echo -n "samba: " ; grep -- "- libsmbclient-dev" $< | wc -l ; \
	  echo -n "tdb/ldb: " ; grep -e "- libxine2-bin\|libxine2-misc-plugins\|kde-runtime\|libtdb-dev" $< | wc -l ; \
	  echo -n "vlc: " ; grep -- "Depends.* : vlc" $< | wc -l ; \
	  echo -n "general FTBFS: " ; grep -i -- "general FTBFS" $< | wc -l ; \
	  true \
	) | tee $@

out_of_date2.txt:
	( $(BUILDD) \
	for package in \$$\( $(WANNA_BUILD) --order=S --list=all \| grep out-of-date \| grep -v Needs-Build \| grep -v Building \| grep -v Built \| grep -v Uploaded \| grep -v Installed \| cut -d _ -f 1 \| sed 's_.\*/__' \) \; \
	do \
	  if $(WANNA_BUILD_NOARCH) -A i386 -i \$$package \| grep \"^\ \ State\ \ \" \| grep -q \"Failed\\\|Build-Attempted\\\|BD-Uninstallable\" \|\| \
	     $(WANNA_BUILD_NOARCH) -A amd64 -i \$$package \| grep \"^\ \ State\ \ \" \| grep -q \"Failed\\\|Build-Attempted\\\|BD-Uninstallable\" \; then continue \; fi \; \
	  echo \$$package \; \
	  $(WANNA_BUILD) -i \$$package \| sed -ne \'/^\ \ State\ /p\;/^\ \ Depends\ /p\;/^\ \ Failed\ /,/^\ \ Notes\ /p\;/^\ \ BD-Problem\ /,/^\ \ CalculatedPri\ /p\;/^\ \ State-Days\ /p\' \| grep -v \'^\ \ Build-Arch-All\ \' \| grep -v \'^\ \ Notes\ \' \| grep -v \'^\ \ CalculatedPri\ \' \| sed -e \'s/^/\	\	\	\	/\' \; \
	done ) > $@

#out_of_date2.txt:
#	ssh mirror.ftp-master.debian.org psql service=projectb -f query_no_recent > $@

summary.txt:
	( \
	date ; \
	total=$$($(BUILDD) $(WANNA_BUILD) --list=all \| tail -n 1 | cut -f 2 -d ' ') ; \
	notforus=$$($(BUILDD) $(WANNA_BUILD) --list=not-for-us \| tail -n 1 | cut -f 2 -d ' ') ; \
	autonotforus=$$($(BUILDD) $(WANNA_BUILD) --list=auto-not-for-us \| tail -n 1 | cut -f 2 -d ' ') ; \
	autonotforus=$$(( $$autonotforus + $$($(BUILDD) $(WANNA_BUILD) --list=failed-removed \| tail -n 1 | cut -f 2 -d ' ') )) ; \
	installed=$$($(BUILDD) $(WANNA_BUILD) --list=installed \| tail -n 1 | cut -f 2 -d ' ') ; \
	need_build=$$($(BUILDD) $(WANNA_BUILD) --list=needs-build \| tail -n 1 | cut -f 2 -d ' ') ; \
	building=$$($(BUILDD) $(WANNA_BUILD) --list=building \| tail -n 1 | cut -f 2 -d ' ') ; \
	built=$$($(BUILDD) $(WANNA_BUILD) --list=built \| tail -n 1 | cut -f 2 -d ' ') ; \
	build_attempted=$$($(BUILDD) $(WANNA_BUILD) --list=build-attempted \| tail -n 1 | cut -f 2 -d ' ') ; \
	uploaded=$$($(BUILDD) $(WANNA_BUILD) --list=uploaded \| tail -n 1 | cut -f 2 -d ' ') ; \
	dep_wait=$$($(BUILDD) $(WANNA_BUILD) --list=dep-wait \| tail -n 1 | cut -f 2 -d ' ') ; \
	failed=$$($(BUILDD) $(WANNA_BUILD) --list=failed \| tail -n 1 | cut -f 2 -d ' ') ; \
	bd_uninstallable=$$($(BUILDD) $(WANNA_BUILD) --list=bd-uninstallable \| tail -n 1 | cut -f 2 -d ' ') ; \
	out_of_date=$$($(BUILDD) $(WANNA_BUILD) --list=all \| grep -v Installed \| grep -v Built \| grep -v Uploadad \| grep out-of-date \| wc -l) ; \
	echo Installed: $$installed ; \
	echo Needs-Build: $$need_build ; \
	echo Building: $$building ; \
	echo Built: $$built ; \
	echo Build-Attempted: $$build_attempted ; \
	echo Uploaded: $$uploaded ; \
	echo Dep-Wait: $$dep_wait ; \
	echo Failed: $$failed ; \
	echo BD-Uninstallable: $$bd_uninstallable ; \
	echo Not-For-Us: $$notforus ; \
	echo Auto-Not-For-Us: $$autonotforus ; \
	echo mytotal: $$(( $$installed + $$need_build + $$building + $$built + $$build_attempted + $$uploaded + $$dep_wait + $$failed + $$bd_uninstallable + $$notforus + $$autonotforus )) ; \
	echo total: $$total ; \
	total=$$(( $$total - $$notforus - $$autonotforus )) ; \
	echo 'total-*notforus/removed:' $$total ; \
	echo up-to-date: $$( python3 -c "print(round(($$installed + $$uploaded + $$built ) * 100 / $$total, 2))" )% ; \
	echo up-to-date2: $$( echo `$(BUILDD) tail -1 /srv/wanna-build/etc/graph2-data | awk '{print $$9 $$10}' | tr ',' ' ' | sed s/.$$/\*100.0/ | sed s#\ #/#` | bc -l | cut -c -5 )% ; \
	echo need-build: $$( python3 -c "print(round($$need_build * 100 / $$total,2))" )% ; \
	echo building: $$( python3 -c "print(round($$building * 100 / $$total ,2))" )% ; \
	echo failed: $$( python3 -c "print(round($$failed * 100 / $$total ,2))" )% ; \
	echo out of date: $$( python3 -c "print(round($$out_of_date * 100 / $$total ,2))" )% ; \
	echo dep: $$( python3 -c "print(round(( $$dep_wait + $$bd_uninstallable ) * 100 / $$total ,2))" )% ) > $@

summary: summary.txt
	cat $<

.PHONY: send
send:
	lftp -f send


MISSING ?= libghc-base-dev-4.11.1.0-12cf1
.PHONY: binnmu
binnmu: Packages-incoming Packages-main Makefile
	grep-aptavail -sPackage,Source -F Depends,Pre-Depends "$(MISSING)" Packages-incoming Packages-main | sed -n -e '/Package:/h' -e '/Source:/h' -e '/^$$/{x;p}' | cut -d ' ' -f 2 | uniq > $@
	@cat $@
	scp $@ buildd.debian.org:
	@echo "REASON=\"$(MISSING) not available any more\" binnmu$(SUFF) \$$(cat ~/binnmu)"



# Compute haskell package priorities through a roughly estimated number of descendants

# Keep only haskell packages
Sources-main-haskell: Sources-main
	grep-dctrl -s Package,Version,Binary,Build-Depends -F Binary -e 'libghc-|hadrian|pandoc' < $< > $@

# Keep only the latest version
Sources-main-uniq: Sources-main-haskell
	for i in $$(grep ^Package: $< | uniq | cut -d ' ' -f 2) ; do \
	  ver=$$(grep-dctrl -n -X -FPackage -sVersion $$i $< | tail -n 1) ; \
	  grep-dctrl -X -sPackage,Version,Binary,Build-Depends -FPackage $$i -a -FVersion $$ver $< ; \
	done > $@


# A version with only package version
Sources-main-ver: Sources-main-uniq
	grep-dctrl -s Package,Version -F Binary -e 'libghc-|hadrian|pandoc' < $< > $@
# A version with only source vs binaries
Sources-main-bin: Sources-main-uniq
	grep-dctrl -s Package,Binary -F Binary -e 'libghc-|hadrian|pandoc' < $< > $@
# A version with only build-depends
Sources-main-deps: Sources-main-uniq
	grep-dctrl -s Package,Build-Depends -F Build-Depends -e 'libghc-|hadrian|pandoc' < $< > $@

# An xml graph to check for loops
haskell-deps.xml: Sources-main-bin Sources-main-deps
	( \
	echo '<?xml version="1.0" ?>' ; \
	echo '<digraph>' ; \
	for i in $$(grep ^Package: Sources-main-deps | uniq | cut -d ' ' -f 2) ; do \
		echo "<node id=\"$$i\"></node>" ; \
		bin=$$(grep-dctrl -X -sBinary -FPackage "$$i" Sources-main-bin | tail -n 1 | sed -n -e 's/.*\(libghc-[^ ]*-dev\)\(,\| \|$$\).*/\1/p') ; \
		[ -n "$$bin" ] || continue ; \
		echo "<node id=\"$$bin\"></node>" ; \
		echo "<edge from=\"$$i\" to=\"$$bin\" wt=\"1\" />" ; \
		for j in $$( grep-dctrl -r -n -FBuild-Depends -sPackage "$$bin\( \|,\|\$$\)" Sources-main-deps | uniq ) ; do \
			echo "<edge from=\"$$bin\" to=\"$$j\" wt=\"1\" />" ; \
		done ; \
	done ; \
	echo '</digraph>' ; \
	) | grep -v 'from="libghc-quickcheck-instances-dev" to="haskell-text-short"' > $@
# Check for loops
cycle-haskell-deps: haskell-deps.xml
	./cycle.py $<

# Download list from wanna-build
haskell-list: Sources-main
	$(BUILDD) $(WANNA_BUILD) --list=all \| grep -E \\\(/haskell-\\\|haskell/\\\|/hdbc\\\|/missingh\\\|/pandoc\\\|highlighting-kate\\\|hslogger\\\) \| cut -d : -f 1 \| cut -d _ -f 1 \| cut -d / -f 2 > $@

# Compute package priority as the number of rbuilddeps + max priority(rbuilddeps)
# Start by echo -n > haskell-priorities
# Then make haskell-priorities as long as the diff tells it has not converged yet
# You should need at most three dozen iterations (see dep depth on https://release.debian.org/transitions/html/haskell.html)
.PHONY: haskell-priorities
haskell-priorities: haskell-list Sources-main-ver Sources-main-bin Sources-main-deps cycle-haskell-deps
	factor=5 ; \
	declare -A prio ; \
	while read w a a p h ; do \
		p=$${p#--build-priority=} ; \
		p=$${p#--permanent-build-priority=} ; \
		h=$${h%_*} ; \
		prio[$$h]=$$(($$p * $$factor)) ; \
	done < haskell-priorities; \
	( for i in $$(cat haskell-list) ; do \
	  ver=$$(grep-dctrl -n -X -FPackage -sVersion $$i Sources-main-ver | tail -n 1) ; \
	  bin=$$(grep-dctrl -X -sBinary -FPackage "$$i" Sources-main-bin | tail -n 1 | sed -n -e 's/.*\(libghc-[^ ]*-dev\|hadrian\|pandoc\).*/\1/p') ; \
	  [ -n "$$bin" ] || continue ; \
	  if [ "$$bin" = hadrian -o "$$bin" = pandoc ] ; then \
	    n=300 ; \
	  else \
	    max=0 ; \
	    n=0 ; \
	    for j in $$( grep-dctrl -n -FBuild-Depends -sPackage $$bin Sources-main-deps | uniq ) ; do \
	      n=$$(($$n + 1)) ; \
	      p=$${prio[$$j]} ; \
	      [ -n "$$p" ] || continue ; \
	      [ $$p -le $$max ] || max=$$p ; \
	    done ; \
	    n=$$(($$n + $$max)) ; \
	  fi ; \
	  echo wanna-build -A $(ARCH) --build-priority=0 $${i}_$$ver ; \
	  echo wanna-build -A $(ARCH) --permanent-build-priority=$$(( ( $$n + $$factor - 1 ) / $$factor)) $${i}_$$ver ; \
	done ) | tee $@.new
	@echo
	@echo
	diff $@ $@.new | wc -l
	@echo
	@echo
	mv -f $@.new $@
	# scp $@ buildd.debian.org:

Sources-main-exp-haskell: Sources-main-exp
	grep-dctrl -s Package,Version,Binary,Build-Depends -F Binary libghc- < $< > $@

Sources-main-exp-uniq: Sources-main--exp-haskell
	for i in $$(grep ^Package: $< | uniq | cut -d ' ' -f 2) ; do \
	  echo $$i 1>&2 ; \
	  ver=$$(grep-dctrl -n -X -FPackage -sVersion $$i $< | tail -n 1) ; \
	  grep-dctrl -X -sPackage,Version,Binary,Build-Depends -FPackage $$i -a -FVersion $$ver $< ; \
	done > $@

Sources-main-exp-bin: Sources-main-exp-uniq
	grep-dctrl -s Package,Version,Binary -F Binary libghc- < $< > $@
Sources-main-exp-deps: Sources-main-exp-uniq
	grep-dctrl -s Package,Build-Depends -F Build-Depends libghc- < $< > $@
.PHONY: haskell-exp-priorities
haskell-exp-priorities: Sources-main-exp-bin Sources-main-exp-deps
	scp $@ buildd.debian.org:

# Find out which Haskell packages are seen as missing and making another package
# bd-uninstallable, and thus the packages to be rebuilt
# (Note we use out_of_date.txt to avoid showing problems that also happen on amd64/i386 anyway)
.PHONY: haskell-missing
haskell-missing: out_of_date.txt
	for i in $$(grep -A 1 "on missing:" $< | grep -- "- " | sort -u | grep libghc | cut -d : -f 1 | cut -d - -f 2- | grep -v -- "-dev$$" ) ; do \
	  grep -q "^$$i$$" binnmu-done && echo "$$i already done" && continue ; \
	  echo ; echo ; echo MISSING=$$i make binnmu ; echo ; \
	  grep -B 1 $$i:$(ARCH) $< ; \
	done
