]> git.decadent.org.uk Git - dak.git/blob - config/debian/dinstall.functions
4440f512b4818bd6fa94abc36a97eb0e1284a1d0
[dak.git] / config / debian / dinstall.functions
1 # -*- mode:sh -*-
2 # Timestamp. Used for dinstall stat graphs
3 function ts() {
4         echo "Archive maintenance timestamp ($1): $(date +%H:%M:%S)"
5 }
6
7 # Remove daily lock
8 function remove_daily_lock() {
9     rm -f $LOCK_DAILY
10 }
11
12 # Remove changelog lock
13 function remove_changelog_lock() {
14     rm -f $LOCK_CHANGELOG
15 }
16
17 # Remove all locks
18 function remove_all_locks() {
19     rm -f $LOCK_DAILY $LOCK_ACCEPTED
20 }
21
22 function remove_locks {
23     remove_all_locks
24     trap - EXIT TERM HUP INT QUIT
25     ts "locked part finished"
26 }
27
28 function lockaccepted {
29     lockfile "$LOCK_ACCEPTED"
30     trap remove_all_locks EXIT TERM HUP INT QUIT
31 }
32
33 # If we error out this one is called, *FOLLOWED* by cleanup above
34 function onerror() {
35     ERRDATE=$(date "+%Y.%m.%d-%H:%M:%S")
36
37     subject="ATTENTION ATTENTION!"
38     if [ "${error}" = "false" ]; then
39         subject="${subject} (continued)"
40     else
41         subject="${subject} (interrupted)"
42     fi
43     subject="${subject} dinstall error at ${ERRDATE} in ${STAGEFILE} - (Be quiet, Brain, or I'll stab you with a Q-tip)"
44
45     if [ -r "${STAGEFILE}.log" ]; then
46         cat "${STAGEFILE}.log"
47     else
48         echo "file ${STAGEFILE}.log does not exist, sorry"
49     fi | mail -s "${subject}" -a "X-Debian: DAK" -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" cron@ftp-master.debian.org
50 }
51
52 ########################################################################
53 # the actual dinstall functions follow                                 #
54 ########################################################################
55
56 # pushing merkels QA user, part one
57 function qa1() {
58     log "Telling QA user that we start dinstall"
59     ssh -n -2 -i ~dak/.ssh/push_merkel_qa  -o BatchMode=yes -o SetupTimeOut=90 -o ConnectTimeout=90 qa@qa.debian.org sleep 1
60 }
61
62 # Updating various files
63 function updates() {
64     log "Updating Bugs docu, Mirror list and mailing-lists.txt"
65     cd $configdir
66     $scriptsdir/update-bugdoctxt
67     $scriptsdir/update-mirrorlists
68     $scriptsdir/update-mailingliststxt
69     $scriptsdir/update-pseudopackages.sh
70 }
71
72 # The first i18n one, syncing new descriptions
73 function i18n1() {
74     log "Synchronizing i18n package descriptions"
75     # First sync their newest data
76     cd ${scriptdir}/i18nsync
77     rsync -aq --delete --delete-after ddtp-sync:/does/not/matter . || true
78
79     # Now check if we still know about the packages for which they created the files
80     # is the timestamp signed by us?
81     if $(gpgv --keyring /srv/ftp-master.debian.org/s3kr1t/dot-gnupg/pubring.gpg timestamp.gpg timestamp); then
82         # now read it. As its signed by us we are sure the content is what we expect, no need
83         # to do more here. And we only test -d a directory on it anyway.
84         TSTAMP=$(cat timestamp)
85         # do we have the dir still?
86         if [ -d ${scriptdir}/i18n/${TSTAMP} ]; then
87             # Lets check!
88             if ${scriptsdir}/ddtp-i18n-check.sh . ${scriptdir}/i18n/${TSTAMP}; then
89                 # Yay, worked, lets copy around
90                 for dir in stretch sid; do
91                     if [ -d dists/${dir}/ ]; then
92                         cd dists/${dir}/main/i18n
93                         rsync -aq --delete --delete-after --exclude Translation-en.bz2 --exclude Translation-*.diff/ . ${ftpdir}/dists/${dir}/main/i18n/.
94                     fi
95                     cd ${scriptdir}/i18nsync
96                 done
97             else
98                 echo "ARRRR, bad guys, wrong files, ARRR"
99                 echo "Arf, Arf, Arf, bad guys, wrong files, arf, arf, arf" | mail -a "X-Debian: DAK" -s "Don't you kids take anything. I'm watching you. I've got eye implants in the back of my head." -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" debian-l10n-devel@lists.alioth.debian.org
100             fi
101         else
102             echo "ARRRR, missing the timestamp ${TSTAMP} directory, not updating i18n, ARRR"
103             echo "Arf, Arf, Arf, missing the timestamp ${TSTAMP} directory, not updating i18n, arf, arf, arf" | mail -a "X-Debian: DAK" -s "Lisa, if you don't like your job you don't strike. You just go in every day and do it really half-assed. That's the American way." -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" debian-l10n-devel@lists.alioth.debian.org
104         fi
105     else
106         echo "ARRRRRRR, could not verify our timestamp signature, ARRR. Don't mess with our files, i18n guys, ARRRRR."
107         echo "Arf, Arf, Arf, could not verify our timestamp signature, arf. Don't mess with our files, i18n guys, arf, arf, arf" | mail -a "X-Debian: DAK" -s "You can't keep blaming yourself. Just blame yourself once, and move on." -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" debian-l10n-devel@lists.alioth.debian.org
108     fi
109 }
110
111 # Syncing AppStream/DEP-11 data
112 function dep11() {
113     log "Synchronizing AppStream metadata"
114     # First sync their newest data
115     mkdir -p ${scriptdir}/dep11
116     cd ${scriptdir}/dep11
117     rsync -aq --delete --delete-after dep11-sync:/does/not/matter . || true
118
119     # Lets check!
120     if ${scriptsdir}/dep11-basic-validate.py . ${scriptdir}/dep11/; then
121         # Yay, worked, lets copy around
122         for dir in stretch sid; do
123             if [ -d ${dir}/ ]; then
124                 for comp in main contrib non-free; do
125                     mkdir -p ${ftpdir}/dists/${dir}/${comp}/dep11
126                     cd ${dir}/${comp}
127                     rsync -aq --delete --delete-after --exclude *.tmp . ${ftpdir}/dists/${dir}/${comp}/dep11/.
128                     cd ${scriptdir}/dep11
129                 done
130             fi
131         done
132     else
133         echo "ARRRR, bad guys, wrong files, ARRR"
134         echo "Arf, Arf, Arf, bad guys, wrong files, arf, arf, arf" | mail -a "X-Debian: DAK" -s "Don't you kids take anything. I'm watching you. I've got eye implants in the back of my head." -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" mak@debian.org
135     fi
136 }
137
138 function cruft() {
139     log "Checking for cruft in overrides"
140     dak check-overrides
141 }
142
143 function dominate() {
144     log "Removing obsolete source and binary associations"
145     dak dominate
146     dak manage-debug-suites unstable-debug experimental-debug
147 }
148
149 function autocruft() {
150     log "Check for obsolete binary packages"
151     dak auto-decruft -s unstable
152     dak auto-decruft -s experimental --if-newer-version-in unstable --if-newer-version-in-rm-msg "NVIU"
153 }
154
155 function fingerprints() {
156     log "Updating fingerprints"
157     dak import-keyring -L /srv/keyring.debian.org/keyrings/debian-keyring.gpg
158
159     OUTFILE=$(mktemp)
160     dak import-keyring --generate-users "%s" /srv/keyring.debian.org/keyrings/debian-maintainers.gpg >"${OUTFILE}"
161
162     if [ -s "${OUTFILE}" ]; then
163         /usr/sbin/sendmail -odq -oi -t -f envelope@ftp-master.debian.org <<EOF
164 From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>
165 To: <debian-project@lists.debian.org>
166 Subject: Debian Maintainers Keyring changes
167 Content-Type: text/plain; charset=utf-8
168 X-Debian: DAK
169 MIME-Version: 1.0
170
171 The following changes to the debian-maintainers keyring have just been activated:
172
173 $(cat $OUTFILE)
174
175 Debian distribution maintenance software,
176 on behalf of the Keyring maintainers
177
178 EOF
179     fi
180     rm -f "$OUTFILE"
181 }
182
183 function overrides() {
184     log "Writing overrides into text files"
185     cd $overridedir
186     dak make-overrides
187 }
188
189 function mpfm() {
190     local archiveroot
191
192     log "Generating package / file mapping"
193     for archive in "${public_archives[@]}"; do
194         archiveroot="$(get_archiveroot "${archive}")"
195         dak make-pkg-file-mapping "${archive}" | bzip2 -9 > "${archiveroot}/indices/package-file.map.bz2"
196     done
197 }
198
199 function packages() {
200     log "Generating Packages and Sources files"
201     for archive in "${public_archives[@]}"; do
202         log "  Generating Packages/Sources for ${archive}"
203         dak generate-packages-sources2 -a "${archive}"
204         log "  Generating Contents for ${archive}"
205         dak contents generate -a "${archive}"
206     done
207 }
208
209 function pdiff() {
210     log "Generating pdiff files"
211     dak generate-index-diffs
212 }
213
214 function release() {
215     log "Generating Release files"
216     for archive in "${public_archives[@]}"; do
217         dak generate-releases -a "${archive}"
218     done
219 }
220
221 function dakcleanup() {
222     log "Cleanup old packages/files"
223     dak clean-suites -m 10000
224     dak clean-queues -i "$unchecked"
225 }
226
227 function mklslar() {
228     local archiveroot
229     local FILENAME=ls-lR
230
231     for archive in "${public_archives[@]}"; do
232         archiveroot="$(get_archiveroot "${archive}")"
233         cd "${archiveroot}"
234
235         log "Removing any core files ..."
236         find -type f -name core -print -delete
237
238         log "Checking symlinks ..."
239         symlinks -rd .
240
241         log "Creating recursive directory listing ... "
242         rm -f ${FILENAME}.gz
243         TZ=UTC ls -lR | gzip -9c --rsyncable > ${FILENAME}.gz
244     done
245 }
246
247 function mkmaintainers() {
248     local archiveroot
249     local indices
250
251     log 'Creating Maintainers index ... '
252
253     for archive in "${public_archives[@]}"; do
254         archiveroot="$(get_archiveroot "${archive}")"
255         indices="${archiveroot}/indices"
256         if ! [ -d "${indices}" ]; then
257             mkdir "${indices}"
258         fi
259         cd "${indices}"
260
261         dak make-maintainers -a "${archive}" ${scriptdir}/masterfiles/pseudo-packages.maintainers
262         gzip -9v --rsyncable <Maintainers >Maintainers.gz
263         gzip -9v --rsyncable <Uploaders >Uploaders.gz
264     done
265 }
266
267 function copyoverrides() {
268     log 'Copying override files into public view ...'
269
270     (
271         shopt -s nullglob
272         for ofile in ${overridedir}/override.{squeeze,wheezy,jessie,stretch,sid}.{,extra.}{main,contrib,non-free}*; do
273             bname=${ofile##*/}
274             gzip -9cv --rsyncable ${ofile} > ${indices}/${bname}.gz
275             chmod g+w ${indices}/${bname}.gz
276         done
277     )
278 }
279
280 function mkfilesindices() {
281     set +o pipefail
282     umask 002
283     cd $base/ftp/indices/files/components
284
285     ARCHLIST=$(tempfile)
286
287     log "Querying postgres"
288     local query="
289       SELECT './pool/' || c.name || '/' || f.filename AS path, a.arch_string AS arch_string
290       FROM files f
291       JOIN files_archive_map af ON f.id = af.file_id
292       JOIN component c ON af.component_id = c.id
293       JOIN archive ON af.archive_id = archive.id
294       LEFT OUTER JOIN
295         (binaries b
296          JOIN architecture a ON b.architecture = a.id)
297         ON f.id = b.file
298       WHERE archive.name = 'ftp-master'
299       ORDER BY path, arch_string
300     "
301     psql -At -c "$query" >$ARCHLIST
302
303     includedirs () {
304         perl -ne 'print; while (m,/[^/]+$,) { $_=$`; print $_ . "\n" unless $d{$_}++; }'
305     }
306     poolfirst () {
307         perl -e '@nonpool=(); while (<>) { if (m,^\./pool/,) { print; } else { push @nonpool, $_; } } print for (@nonpool);'
308     }
309
310     log "Generating sources list"
311     (
312         sed -n 's/|$//p' $ARCHLIST
313         cd $base/ftp
314         find ./dists -maxdepth 1 \! -type d
315         find ./dists \! -type d | grep "/source/"
316     ) | sort -u | gzip -9 > source.list.gz
317
318     log "Generating arch lists"
319
320     ARCHES=$( (<$ARCHLIST sed -n 's/^.*|//p'; echo amd64) | grep . | grep -v all | sort -u)
321     for a in $ARCHES; do
322         (sed -n "s/|$a$//p" $ARCHLIST
323             sed -n 's/|all$//p' $ARCHLIST
324
325             cd $base/ftp
326             find ./dists -maxdepth 1 \! -type d
327             find ./dists \! -type d | grep -E "(proposed-updates.*_$a.changes$|/main/disks-$a/|/main/installer-$a/|/Contents-$a|/binary-$a/)"
328         ) | sort -u | gzip -9 > arch-$a.list.gz
329     done
330
331     log "Generating suite lists"
332
333     suite_list () {
334         local suite_id="$(printf %d $1)"
335         local query
336         query="
337           SELECT DISTINCT './pool/' || c.name || '/' || f.filename
338           FROM
339             (SELECT sa.source AS source
340                FROM src_associations sa
341               WHERE sa.suite = $suite_id
342              UNION
343              SELECT esr.src_id
344                FROM extra_src_references esr
345                JOIN bin_associations ba ON esr.bin_id = ba.bin
346                WHERE ba.suite = $suite_id
347              UNION
348              SELECT b.source AS source
349                FROM bin_associations ba
350                JOIN binaries b ON ba.bin = b.id WHERE ba.suite = $suite_id) s
351             JOIN dsc_files df ON s.source = df.source
352             JOIN files f ON df.file = f.id
353             JOIN files_archive_map af ON f.id = af.file_id
354             JOIN component c ON af.component_id = c.id
355             JOIN archive ON af.archive_id = archive.id
356             WHERE archive.name = 'ftp-master'
357         "
358         psql -F' ' -A -t -c "$query"
359
360         query="
361           SELECT './pool/' || c.name || '/' || f.filename
362           FROM bin_associations ba
363           JOIN binaries b ON ba.bin = b.id
364           JOIN files f ON b.file = f.id
365           JOIN files_archive_map af ON f.id = af.file_id
366           JOIN component c ON af.component_id = c.id
367           JOIN archive ON af.archive_id = archive.id
368           WHERE ba.suite = $suite_id AND archive.name = 'ftp-master'
369         "
370         psql -F' ' -A -t -c "$query"
371     }
372
373     psql -F' ' -At -c "SELECT id, suite_name FROM suite" |
374     while read id suite; do
375         [ -e $base/ftp/dists/$suite ] || continue
376         (
377             (cd $base/ftp
378                 distname=$(cd dists; readlink $suite || echo $suite)
379                 find ./dists/$distname \! -type d
380                 for distdir in ./dists/*; do
381                     [ "$(readlink $distdir)" != "$distname" ] || echo $distdir
382                 done
383             )
384             suite_list $id
385         ) | sort -u | gzip -9 > suite-${suite}.list.gz
386     done
387
388     log "Finding everything on the ftp site to generate sundries"
389     (cd $base/ftp; find . \! -type d \! -name 'Archive_Maintenance_In_Progress' | sort) >$ARCHLIST
390
391     rm -f sundries.list
392     zcat *.list.gz | cat - *.list | sort -u |
393     diff - $ARCHLIST | sed -n 's/^> //p' > sundries.list
394
395     log "Generating files list"
396
397     for a in $ARCHES; do
398         (echo ./project/trace; zcat arch-$a.list.gz source.list.gz) |
399         cat - sundries.list dists.list project.list docs.list indices.list |
400         sort -u | poolfirst > ../arch-$a.files
401     done
402
403     (cd $base/ftp/
404             for dist in sid jessie stretch; do
405                     find ./dists/$dist/main/i18n/ \! -type d | sort -u | gzip -9 > $base/ftp/indices/files/components/translation-$dist.list.gz
406             done
407     )
408
409     (cat ../arch-i386.files ../arch-amd64.files; zcat suite-proposed-updates.list.gz ; zcat translation-sid.list.gz ; zcat translation-jessie.list.gz ; zcat translation-stretch.list.gz) |
410     sort -u | poolfirst > ../typical.files
411
412     rm -f $ARCHLIST
413     log "Done!"
414     set -o pipefail
415 }
416
417 function mkchecksums() {
418     local archiveroot dsynclist md5list
419
420     for archive in "${public_archives[@]}"; do
421         archiveroot="$(get_archiveroot "${archive}")"
422         dsynclist=$dbdir/dsync.${archive}.list
423         md5list=${archiveroot}/indices/md5sums
424
425         log -n "Creating md5 / dsync index file for ${archive}... "
426
427         cd "$archiveroot"
428         ${bindir}/dsync-flist -q generate $dsynclist --exclude $dsynclist --md5
429         ${bindir}/dsync-flist -q md5sums $dsynclist | gzip -9n > ${md5list}.gz
430         ${bindir}/dsync-flist -q link-dups $dsynclist || true
431     done
432 }
433
434 function mirror() {
435     local archiveroot targetpath TRACEFILE
436
437     for archive in "${public_archives[@]}"; do
438         archiveroot="$(get_archiveroot "${archive}")"
439         targetpath="${mirrordir}/${archive}"
440         TRACEFILE="${archiveroot}/project/trace/ftp-master.debian.org"
441         mkdir -p "${archiveroot}/project/trace/"
442
443         log "Regenerating \"public\" mirror/${archive} hardlink fun"
444         DATE_SERIAL=$(date +"%Y%m%d01")
445         FILESOAPLUS1=$(awk '/serial/ { print $3+1 }' ${TRACEFILE} || echo ${DATE_SERIAL} )
446         if [ "$DATE_SERIAL" -gt "$FILESOAPLUS1" ]; then
447             SERIAL="$DATE_SERIAL"
448         else
449             SERIAL="$FILESOAPLUS1"
450         fi
451         date -u > ${TRACEFILE}
452         echo "Using dak v1" >> ${TRACEFILE}
453         echo "Running on host: $(hostname -f)" >> ${TRACEFILE}
454         echo "Archive serial: ${SERIAL}" >> ${TRACEFILE}
455
456         mkdir -p ${targetpath}
457         cd ${targetpath}
458         rsync -aH --link-dest ${archiveroot} --delete --delete-after --delete-excluded --exclude Packages.*.new --exclude Sources.*.new  --ignore-errors ${archiveroot}/. .
459     done
460 }
461
462 function expire() {
463     log "Expiring old database dumps..."
464     cd $base/backup
465     $scriptsdir/expire_dumps -d . -p -f "dump_*"
466 }
467
468 function transitionsclean() {
469     log "Removing out of date transitions..."
470     cd $base
471     dak transitions -c -a
472 }
473
474 function dm() {
475     log "Updating DM permissions page"
476     dak acl export-per-source dm >$exportdir/dm.txt
477 }
478
479 function bts() {
480     log "Categorizing uncategorized bugs filed against ftp.debian.org"
481     sudo -u dak-unpriv dak bts-categorize
482 }
483
484 function ddaccess() {
485     # Tell our dd accessible mirror to sync itself up. Including ftp dir.
486     log "Trigger dd accessible parts sync including ftp dir"
487     ${scriptsdir}/sync-dd dd-sync dd-sync1 dd-sync2 sync
488 }
489
490 function mirrorpush() {
491     log "Checking the public archive copies..."
492
493     local archiveroot targetpath
494
495     for archive in "${public_archives[@]}"; do
496         log "... archive: ${archive}"
497         archiveroot="$(get_archiveroot "${archive}")"
498         targetpath="${mirrordir}/${archive}"
499         cd ${archiveroot}/dists
500
501         broken=0
502         for release in $(find . -name "InRelease"); do
503             echo "Processing: ${release}"
504             subdir=${release%/InRelease}
505             while read SHASUM SIZE NAME; do
506                 if ! [ -f "${subdir}/${NAME}" ]; then
507                     bname=$(basename ${NAME})
508                     if [[ "${bname}" =~ ^(Packages|Sources|Contents-[a-zA-Z0-9-]+|Translation-[a-zA-Z_]+|Components-(amd64|i386)\.yml|icons-(128x128|64x64)\.tar)$ ]]; then
509
510                         # We don't keep unpacked files, don't check for their existance.
511                         # We might want to go and check their unpacked shasum, but right now
512                         # I don't care. I believe it should be enough if all the packed shasums
513                         # match.
514                         continue
515                     fi
516                     broken=$(( broken + 1 ))
517                     echo "File ${subdir}/${NAME} is missing"
518                     continue
519                 fi
520
521                 # We do have symlinks in the tree (see the contents files currently).
522                 # So we use "readlink -f" to check the size of the target, as thats basically
523                 # what gen-releases does
524                 fsize=$(stat -c %s $(readlink -f "${subdir}/${NAME}"))
525                 if [ ${fsize} -ne ${SIZE} ]; then
526                     broken=$(( broken + 1 ))
527                     echo "File ${subdir}/${NAME} has size ${fsize}, expected is ${SIZE}"
528                     continue
529                 fi
530
531                 fshasum=$(sha1sum $(readlink -f "${subdir}/${NAME}"))
532                 fshasum=${fshasum%% *}
533                 if [ "${fshasum}" != "${SHASUM}" ]; then
534                     broken=$(( broken + 1 ))
535                     echo "File ${subdir}/${NAME} has checksum ${fshasum}, expected is ${SHASUM}"
536                     continue
537                 fi
538             done < <(sed '1,/SHA1:/d' "${release}" | sed '/SHA256:/,$d')
539         done
540
541         if [ $broken -gt 0 ]; then
542             log_error "Trouble with the public mirror for ${archive}, found ${broken} errors"
543             continue
544         else
545             log "Starting the mirrorpush for ${archive}"
546             case ${archive} in
547                 ftp-master)
548                     fname="mirrorstart"
549                     pusharg=""
550                     ;;
551                 debian-debug)
552                     pusharg="-a debug"
553                     ;;&
554                 backports)
555                     pusharg="-a backports"
556                     ;;&
557                 *)
558                     fname="mirrorstart.${archive}"
559                     ;;
560             esac
561             date -u > /srv/ftp.debian.org/web/${fname}
562             echo "Using dak v1" >> /srv/ftp.debian.org/web/${fname}
563             echo "Running on host $(hostname -f)" >> /srv/ftp.debian.org/web/${fname}
564             sudo -H -u archvsync /home/archvsync/runmirrors ${pusharg} > ~dak/runmirrors-${archive}.log 2>&1 &
565         fi
566     done
567 }
568
569 function mirrorpush-backports() {
570     log "Syncing backports mirror"
571     sudo -u backports /home/backports/bin/update-archive
572 }
573
574 function i18n2() {
575     log "Exporting package data foo for i18n project"
576     STAMP=$(date "+%Y%m%d%H%M")
577     mkdir -p ${scriptdir}/i18n/${STAMP}
578     cd ${scriptdir}/i18n/${STAMP}
579     for suite in stable testing unstable; do
580         codename=$(dak admin s show ${suite}|grep '^Codename')
581         codename=${codename##* }
582         echo "Codename is ${codename}"
583         dak control-suite -l ${suite} >${codename}
584     done
585     echo "${STAMP}" > timestamp
586     gpg --secret-keyring /srv/ftp-master.debian.org/s3kr1t/dot-gnupg/secring.gpg --keyring /srv/ftp-master.debian.org/s3kr1t/dot-gnupg/pubring.gpg --no-options --batch --no-tty --armour --default-key 473041FA --detach-sign -o timestamp.gpg timestamp
587     rm -f md5sum
588     md5sum * > md5sum
589     cd ${webdir}/
590     ln -sfT ${scriptdir}/i18n/${STAMP} i18n
591
592     cd ${scriptdir}
593     find ./i18n -mindepth 1 -maxdepth 1 -mtime +2 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
594 }
595
596 function stats() {
597     log "Updating stats data"
598     cd $configdir
599     $scriptsdir/update-ftpstats $base/log/* > $base/misc/ftpstats.data
600     R --slave --vanilla < $base/misc/ftpstats.R
601     dak stats arch-space > $webdir/arch-space
602     dak stats pkg-nums > $webdir/pkg-nums
603 }
604
605 function cleantransactions() {
606     log "Cleanup transaction ids older than 3 months"
607     cd $base/backup/
608     find -maxdepth 1 -mindepth 1 -type f -name 'txid_*' -mtime +90 -delete
609 }
610
611 function logstats() {
612     $masterdir/tools/logs.py "$1"
613 }
614
615 # save timestamp when we start
616 function savetimestamp() {
617         NOW=`date "+%Y.%m.%d-%H:%M:%S"`
618         echo ${NOW} > "${dbdir}/dinstallstart"
619 }
620
621 function maillogfile() {
622     cat "$LOGFILE" | mail -a "X-Debian: DAK" -s "Log for dinstall run of ${NOW}" -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" cron@ftp-master.debian.org
623 }
624
625 function renamelogfile() {
626     if [ -f "${dbdir}/dinstallstart" ]; then
627         NOW=$(cat "${dbdir}/dinstallstart")
628 #        maillogfile
629         mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
630         logstats "$logdir/dinstall_${NOW}.log"
631         bzip2 -9 "$logdir/dinstall_${NOW}.log"
632     else
633         error "Problem, I don't know when dinstall started, unable to do log statistics."
634         NOW=`date "+%Y.%m.%d-%H:%M:%S"`
635 #        maillogfile
636         mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
637         bzip2 -9 "$logdir/dinstall_${NOW}.log"
638     fi
639 }
640
641 function testingsourcelist() {
642     dak ls -s testing -f heidi -r .| egrep 'source$' > ${webdir}/testing.list
643 }
644
645 # do a last run of process-unchecked before dinstall is on.
646 function process_unchecked() {
647     log "Processing the unchecked queue"
648     UNCHECKED_WITHOUT_LOCK="-p"
649     do_unchecked
650     sync_debbugs
651 }
652
653 # Function to update a "statefile" telling people what we are doing
654 # (more or less).
655 #
656 # This should be called with the argument(s)
657 #  - Status name we want to show.
658 #
659 function state() {
660     RIGHTNOW="$(date -u +"%a %b %d %T %Z %Y (%s)")"
661     cat >"${DINSTALLSTATE}" <<EOF
662 Dinstall start: ${DINSTALLBEGIN}
663 Current action: ${1}
664 Action start: ${RIGHTNOW}
665 EOF
666 }
667
668 # extract changelogs and stuff
669 function changelogs() {
670     if lockfile -r3 $LOCK_CHANGELOG; then
671         log "Extracting changelogs"
672         dak make-changelog -e -a ftp-master
673         [ -f ${exportdir}/changelogs/filelist.yaml ] && xz -f ${exportdir}/changelogs/filelist.yaml
674         mkdir -p ${exportpublic}/changelogs
675         cd ${exportpublic}/changelogs
676         rsync -aHW --delete --delete-after --ignore-errors ${exportdir}/changelogs/. .
677         sudo -H -u staticsync /usr/local/bin/static-update-component metadata.ftp-master.debian.org >/dev/null 2>&1 &
678
679         dak make-changelog -e -a backports
680         [ -f /srv/backports-master.debian.org/export/changelogs/filelist.yaml ] && xz -f /srv/backports-master.debian.org/export/changelogs/filelist.yaml
681         mkdir -p /srv/backports-master.debian.org/rsync/export/changelogs
682         cd /srv/backports-master.debian.org/rsync/export/changelogs
683         rsync -aHW --delete --delete-after --ignore-errors /srv/backports-master.debian.org/export/changelogs/. .
684         remove_changelog_lock
685         trap remove_changelog_lock EXIT TERM HUP INT QUIT
686     fi
687 }
688
689 function gitpdiff() {
690     # Might be that we want to change this to have more than one git repository.
691     # Advantage of one is that we do not need much space in terms of storage in git itself,
692     # git gc is pretty good on our input.
693     # But it might be faster. Well, lets test.
694     log "Adjusting the git tree for pdiffs"
695     cd ${dbdir}/git/git/
696
697     # The regex needs the architectures seperated with \|
698     garchs=$(dak admin a list|sed -e ':q;N;s/\n/\\|/g;t q')
699
700     # First, get all the files we want to work on. ../dists/ is a symlink to the real dists/ we
701     # want to work with.
702     # Also, we only want contents, packages and sources.
703     for file in $(find ../dists/ -regex ".*/\(Contents-\($archs\)\|\(Packages\|Sources\)\).gz"); do
704         log "${file}"
705         basen=${file%%.gz};
706         basen=${basen##../};
707         dir=${basen%/*};
708         mkdir -p $dir;
709         zcat $file > $basen;
710     done
711
712     # Second, add all there is into git
713     cd dists
714     git add .
715     # Maybe we want to make this the same for tag and commit? But well, shouldn't matter
716     COMD=$(date  -Is)
717     TAGD=$(date +%Y-%m-%d-%H-%M)
718     git commit -m "Commit of ${COMD}"
719     git tag "${TAGD}"
720  }