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