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