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