]> git.decadent.org.uk Git - dak.git/blob - config/debian/dinstall.functions
Also create Date: line in archives tracefiles
[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                     ;;
579                 debian-debug)
580                     pusharg="-a debug"
581                     ;;&
582                 backports)
583                     pusharg="-a backports"
584                     ;;&
585                 *)
586                     fname="mirrorstart.${archive}"
587                     ;;
588             esac
589             date -u > /srv/ftp.debian.org/web/${fname}
590             echo "Using dak v1" >> /srv/ftp.debian.org/web/${fname}
591             echo "Running on host $(hostname -f)" >> /srv/ftp.debian.org/web/${fname}
592             sudo -H -u archvsync /home/archvsync/runmirrors ${pusharg} > ~dak/runmirrors-${archive}.log 2>&1 &
593         fi
594     done
595 }
596
597 function mirrorpush-backports() {
598     log "Syncing backports mirror"
599     sudo -u backports /home/backports/bin/update-archive
600 }
601
602 function i18n2() {
603     log "Exporting package data foo for i18n project"
604     STAMP=$(date "+%Y%m%d%H%M")
605     mkdir -p ${scriptdir}/i18n/${STAMP}
606     cd ${scriptdir}/i18n/${STAMP}
607     for suite in stable testing unstable; do
608         codename=$(dak admin s show ${suite}|grep '^Codename')
609         codename=${codename##* }
610         echo "Codename is ${codename}"
611         dak control-suite -l ${suite} >${codename}
612     done
613     echo "${STAMP}" > timestamp
614     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
615     rm -f md5sum
616     md5sum * > md5sum
617     cd ${webdir}/
618     ln -sfT ${scriptdir}/i18n/${STAMP} i18n
619
620     cd ${scriptdir}
621     find ./i18n -mindepth 1 -maxdepth 1 -mtime +2 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
622 }
623
624 function stats() {
625     log "Updating stats data"
626     cd ${configdir}
627     ${scriptsdir}/update-ftpstats ${base}/log/* > ${base}/misc/ftpstats.data
628     R --slave --vanilla < ${base}/misc/ftpstats.R
629     dak stats arch-space > ${webdir}/arch-space
630     dak stats pkg-nums > ${webdir}/pkg-nums
631 }
632
633 function cleantransactions() {
634     log "Cleanup transaction ids older than 3 months"
635     cd ${base}/backup/
636     find -maxdepth 1 -mindepth 1 -type f -name 'txid_*' -mtime +90 -delete
637 }
638
639 function logstats() {
640     ${masterdir}/tools/logs.py "$1"
641 }
642
643 # save timestamp when we start
644 function savetimestamp() {
645     echo ${NOW} > "${dbdir}/dinstallstart"
646 }
647
648 function maillogfile() {
649     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
650 }
651
652 function testingsourcelist() {
653     dak ls -s testing -f heidi -r .| egrep 'source$' > ${webdir}/testing.list
654 }
655
656 # Function to update a "statefile" telling people what we are doing
657 # (more or less).
658 #
659 # This should be called with the argument(s)
660 #  - Status name we want to show.
661 #
662 function state() {
663     RIGHTNOW="$(date -u +"%a %b %d %T %Z %Y (%s)")"
664     cat >"${DINSTALLSTATE}" <<EOF
665 Dinstall start: ${DINSTALLBEGIN}
666 Current action: ${1}
667 Action start: ${RIGHTNOW}
668 EOF
669 }
670
671 # extract changelogs and stuff
672 function changelogs() {
673     if lockfile -r3 ${LOCK_CHANGELOG}; then
674         trap remove_changelog_lock EXIT TERM HUP INT QUIT
675         log "Extracting changelogs"
676         dak make-changelog -e -a ftp-master
677         [[ -f ${exportdir}/changelogs/filelist.yaml ]] && xz -f ${exportdir}/changelogs/filelist.yaml
678         mkdir -p ${exportpublic}/changelogs
679         cd ${exportpublic}/changelogs
680         rsync -aHW --delete --delete-after --ignore-errors ${exportdir}/changelogs/. .
681         sudo -H -u staticsync /usr/local/bin/static-update-component metadata.ftp-master.debian.org >/dev/null 2>&1 &
682
683         dak make-changelog -e -a backports
684         [[ -f /srv/backports-master.debian.org/export/changelogs/filelist.yaml  ]] && xz -f /srv/backports-master.debian.org/export/changelogs/filelist.yaml
685         mkdir -p /srv/backports-master.debian.org/rsync/export/changelogs
686         cd /srv/backports-master.debian.org/rsync/export/changelogs
687         rsync -aHW --delete --delete-after --ignore-errors /srv/backports-master.debian.org/export/changelogs/. .
688         remove_changelog_lock
689     fi
690 }
691
692 # Generate a list of extra mirror files, sha256sum em and sign that
693 function signotherfiles() {
694     log "Signing extra mirror files"
695
696     local archiveroot
697
698     for archive in "${public_archives[@]}"; do
699         log "... archive: ${archive}"
700         archiveroot="$(get_archiveroot "${archive}")"
701         local TMPLO=$( gettempfile )
702
703         cd ${archiveroot}
704         rm -f extrafiles
705         sha256sum $(find * -type f | egrep -v '(pool|i18n|dep11|source)/|Contents-.*\.(gz|diff)|installer|binary-|(In)?Release(.gpg)?|\.changes' | sort) > ${TMPLO}
706         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}
707         rm -f ${TMPLO}
708     done
709 }
710
711 function startup() {
712     touch "${DINSTALLSTART}"
713     ts "startup"
714     lockfile -l 3600 "${LOCK_DAILY}"
715     trap onerror ERR
716     touch "${LOCK_BRITNEY}"
717     TMPFILES="${TMPFILES} ${LOCK_DAILY} ${LOCK_BRITNEY}"
718 }
719
720 function postcronscript() {
721     logstats ${LOGFILE}
722     state "all done"
723     touch "${DINSTALLEND}"
724 }