From 1817df53a2b935f23b0efa470377c44b8d0ab72d Mon Sep 17 00:00:00 2001 From: "deepin-community-bot[bot]" <156989552+deepin-community-bot[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 03:24:39 +0000 Subject: [PATCH] feat: update devscripts to 2.25.18 --- .gitignore | 143 + .mailmap | 5 + Makefile.common | 3 +- README.md | 6 +- conf.default.in | 5 - debian/NEWS | 14 + debian/changelog | 120 + debian/control | 15 +- debian/copyright | 4 - debian/manpages | 1 + debian/tests/control | 20 + debian/tests/metacpan | 4 + lib/Devscripts/MkOrigtargz.pm | 38 +- lib/Devscripts/Salsa.pm | 33 + lib/Devscripts/Salsa/Config.pm | 7 +- lib/Devscripts/Salsa/check_repo.pm | 7 +- lib/Devscripts/Salsa/del_repo.pm | 1 + lib/Devscripts/Salsa/forks.pm | 1 + lib/Devscripts/Salsa/last_ci_status.pm | 7 +- lib/Devscripts/Salsa/merge_requests.pm | 1 + lib/Devscripts/Salsa/path.pm | 17 + lib/Devscripts/Salsa/update_watch5.pm | 101 + lib/Devscripts/Uscan.pm | 165 + lib/Devscripts/Uscan/Config.pm | 27 +- lib/Devscripts/Uscan/Downloader.pm | 55 +- lib/Devscripts/Uscan/Output.pm | 10 +- lib/Devscripts/Uscan/Templates.pod | 98 + lib/Devscripts/Uscan/Templates/Github.pm | 26 + lib/Devscripts/Uscan/Templates/Metacpan.pm | 19 + lib/Devscripts/Uscan/Utils.pm | 21 +- lib/Devscripts/Uscan/Version4.pm | 300 + lib/Devscripts/Uscan/WatchFile.pm | 249 +- .../Uscan/{WatchLine.pm => WatchSource.pm} | 759 +- lib/Devscripts/Uscan/WatchSource/Parser.pm | 66 + lib/Devscripts/Uscan/WatchSource/Transform.pm | 135 + lib/Devscripts/Uscan/_vcs.pm | 53 +- lib/Devscripts/Uscan/_xtp.pm | 14 +- lib/Devscripts/Uscan/ftp.pm | 52 +- lib/Devscripts/Uscan/git.pm | 125 +- lib/Devscripts/Uscan/http.pm | 59 +- lib/Devscripts/Uscan/metacpan.pm | 89 + lib/Devscripts/Uscan/svn.pm | 15 +- po4a/Makefile | 13 +- po4a/devscripts-po4a.conf | 6 +- po4a/po/de.po | 30144 +++++++++------- po4a/po/devscripts.pot | 19490 +++++----- po4a/po/fr.po | 24665 +++++++------ po4a/po/pt.po | 29911 ++++++++------- scripts/Makefile | 10 +- scripts/debchange.bash_completion | 6 +- scripts/debchange.pl | 15 +- scripts/debian-watch-4.pod | 1421 + scripts/debian-watch.pod | 1551 + scripts/dep-14-convert-git-branch-names.sh | 18 + scripts/git-deborig.pl | 284 - scripts/mk-origtargz.pl | 13 +- scripts/salsa.bash_completion | 4 +- scripts/salsa.pl | 21 + scripts/uscan-templates.pod | 80 + scripts/uscan.bash_completion | 2 +- scripts/uscan.pl | 1485 +- scripts/what-patch.sh | 21 - test/Makefile | 1 + test/lib_test_uscan | 5 + test/t/uscan.t | 217 + test/t/uscan/README.md | 42 + test/t/uscan/any_version/_.html | 8 + test/t/uscan/any_version/debian/changelog | 5 + test/t/uscan/any_version/debian/copyright | 17 + test/t/uscan/any_version/debian/rules | 4 + test/t/uscan/any_version/debian/source/format | 1 + test/t/uscan/any_version/debian/watch | 5 + test/t/uscan/any_version/wanted_files | 2 + test/t/uscan/automangle/_.html | 8 + test/t/uscan/automangle/debian/watch | 13 + test/t/uscan/automangle/wanted_files | 4 + test/t/uscan/components/_.html | 10 + test/t/uscan/components/debian/changelog | 5 + test/t/uscan/components/debian/copyright | 17 + test/t/uscan/components/debian/rules | 4 + test/t/uscan/components/debian/source/format | 1 + test/t/uscan/components/debian/watch | 11 + test/t/uscan/components/wanted_files | 4 + ...e-oidc-client_git_matching-refs_tags_.html | 22 + test/t/uscan/github/debian/changelog | 5 + test/t/uscan/github/debian/copyright | 17 + test/t/uscan/github/debian/rules | 4 + test/t/uscan/github/debian/source/format | 1 + test/t/uscan/github/debian/watch | 6 + test/t/uscan/github/wanted_files | 2 + test/t/uscan/metacpan/debian/changelog | 5 + test/t/uscan/metacpan/debian/copyright | 28 + test/t/uscan/metacpan/debian/rules | 4 + test/t/uscan/metacpan/debian/source/format | 1 + test/t/uscan/metacpan/debian/watch | 5 + test/t/uscan/metacpan/internet | 0 test/t/uscan/metacpan/wanted_files | 2 + test/t/uscan/semantic_version/_.html | 8 + test/t/uscan/semantic_version/debian/watch | 6 + test/t/uscan/semantic_version/wanted_files | 2 + test/t/uscan/simple_test/_.html | 5 + test/t/uscan/simple_test/debian/changelog | 5 + test/t/uscan/simple_test/debian/copyright | 17 + test/t/uscan/simple_test/debian/rules | 4 + test/t/uscan/simple_test/debian/source/format | 1 + test/t/uscan/simple_test/debian/watch | 5 + test/t/uscan/simple_test/wanted_files | 2 + test/t/uscan/stable_version/_.html | 8 + test/t/uscan/stable_version/debian/changelog | 5 + test/t/uscan/stable_version/debian/copyright | 17 + test/t/uscan/stable_version/debian/rules | 4 + .../uscan/stable_version/debian/source/format | 1 + test/t/uscan/stable_version/debian/watch | 5 + test/t/uscan/stable_version/wanted_files | 2 + test/test_debchange | 11 +- test/test_mk-origtargz | 40 +- test/test_uscan | 12 +- test/test_uscan_ftp | 5 - test/test_uscan_git | 190 +- test/test_uscan_group | 75 +- test/test_uscan_mangle | 9 +- test/test_uscan_svn | 15 +- test/test_uscan_update | 116 + 123 files changed, 63011 insertions(+), 50095 deletions(-) create mode 100644 .gitignore create mode 100644 .mailmap create mode 100644 debian/tests/metacpan create mode 100644 lib/Devscripts/Salsa/path.pm create mode 100644 lib/Devscripts/Salsa/update_watch5.pm create mode 100644 lib/Devscripts/Uscan.pm create mode 100644 lib/Devscripts/Uscan/Templates.pod create mode 100644 lib/Devscripts/Uscan/Templates/Github.pm create mode 100644 lib/Devscripts/Uscan/Templates/Metacpan.pm create mode 100644 lib/Devscripts/Uscan/Version4.pm rename lib/Devscripts/Uscan/{WatchLine.pm => WatchSource.pm} (72%) create mode 100644 lib/Devscripts/Uscan/WatchSource/Parser.pm create mode 100644 lib/Devscripts/Uscan/WatchSource/Transform.pm create mode 100644 lib/Devscripts/Uscan/metacpan.pm create mode 100644 scripts/debian-watch-4.pod create mode 100644 scripts/debian-watch.pod delete mode 100755 scripts/git-deborig.pl create mode 100644 scripts/uscan-templates.pod create mode 100644 test/t/uscan.t create mode 100644 test/t/uscan/README.md create mode 100644 test/t/uscan/any_version/_.html create mode 100644 test/t/uscan/any_version/debian/changelog create mode 100644 test/t/uscan/any_version/debian/copyright create mode 100644 test/t/uscan/any_version/debian/rules create mode 100644 test/t/uscan/any_version/debian/source/format create mode 100644 test/t/uscan/any_version/debian/watch create mode 100644 test/t/uscan/any_version/wanted_files create mode 100644 test/t/uscan/automangle/_.html create mode 100644 test/t/uscan/automangle/debian/watch create mode 100644 test/t/uscan/automangle/wanted_files create mode 100644 test/t/uscan/components/_.html create mode 100644 test/t/uscan/components/debian/changelog create mode 100644 test/t/uscan/components/debian/copyright create mode 100644 test/t/uscan/components/debian/rules create mode 100644 test/t/uscan/components/debian/source/format create mode 100644 test/t/uscan/components/debian/watch create mode 100644 test/t/uscan/components/wanted_files create mode 100644 test/t/uscan/github/_repos_linagora_simple-oidc-client_git_matching-refs_tags_.html create mode 100644 test/t/uscan/github/debian/changelog create mode 100644 test/t/uscan/github/debian/copyright create mode 100644 test/t/uscan/github/debian/rules create mode 100644 test/t/uscan/github/debian/source/format create mode 100644 test/t/uscan/github/debian/watch create mode 100644 test/t/uscan/github/wanted_files create mode 100644 test/t/uscan/metacpan/debian/changelog create mode 100644 test/t/uscan/metacpan/debian/copyright create mode 100644 test/t/uscan/metacpan/debian/rules create mode 100644 test/t/uscan/metacpan/debian/source/format create mode 100644 test/t/uscan/metacpan/debian/watch create mode 100644 test/t/uscan/metacpan/internet create mode 100644 test/t/uscan/metacpan/wanted_files create mode 100644 test/t/uscan/semantic_version/_.html create mode 100644 test/t/uscan/semantic_version/debian/watch create mode 100644 test/t/uscan/semantic_version/wanted_files create mode 100644 test/t/uscan/simple_test/_.html create mode 100644 test/t/uscan/simple_test/debian/changelog create mode 100644 test/t/uscan/simple_test/debian/copyright create mode 100755 test/t/uscan/simple_test/debian/rules create mode 100644 test/t/uscan/simple_test/debian/source/format create mode 100644 test/t/uscan/simple_test/debian/watch create mode 100644 test/t/uscan/simple_test/wanted_files create mode 100644 test/t/uscan/stable_version/_.html create mode 100644 test/t/uscan/stable_version/debian/changelog create mode 100644 test/t/uscan/stable_version/debian/copyright create mode 100644 test/t/uscan/stable_version/debian/rules create mode 100644 test/t/uscan/stable_version/debian/source/format create mode 100644 test/t/uscan/stable_version/debian/watch create mode 100644 test/t/uscan/stable_version/wanted_files create mode 100755 test/test_uscan_update diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6bbb04d --- /dev/null +++ b/.gitignore @@ -0,0 +1,143 @@ +*.pyc +build-stamp-arch +build-stamp-indep +conf.default +debian/*.debhelper +debian/debhelper-build-stamp +debian/devscripts.debhelper.log +debian/devscripts.substvars +debian/devscripts/ +debian/files +doc/devscripts.7 +make_scripts +po4a/fr/*.1 +po4a/fr/*.5 +po4a/fr/*.dbk +po4a/fr/*.pl +po4a/fr/*.pod +po4a/de/*.1 +po4a/de/*.5 +po4a/de/*.dbk +po4a/de/*.pl +po4a/de/*.pod +po4a/pt/*.1 +po4a/pt/*.5 +po4a/pt/*.dbk +po4a/pt/*.pl +po4a/pt/*.pod +po4a/translate +scripts/bash_completion/* +scripts/annotate-output +scripts/archpath +scripts/bts +scripts/bts.1 +scripts/build +scripts/build-rdeps +scripts/build-rdeps.1 +scripts/chdist +scripts/chdist.1 +scripts/checkbashisms +scripts/cowpoke +scripts/dcmd +scripts/dd-list +scripts/deb-reversion +scripts/deb-reversion.1 +scripts/deb-why-removed +scripts/deb-why-removed.1 +scripts/deb2apptainer +scripts/deb2docker +scripts/debbisect.1 +scripts/debc +scripts/debchange +scripts/debcheckout +scripts/debcheckout.1 +scripts/debclean +scripts/debcommit +scripts/debcommit.1 +scripts/debdiff +scripts/debftbfs.1 +scripts/debi +scripts/debian-watch-4.5 +scripts/debian-watch.5 +scripts/debootsnap.1 +scripts/debpkg +scripts/debpkg-wrapper +scripts/debrebuild +scripts/debrebuild.1 +scripts/debrelease +scripts/debrepro +scripts/debrepro.1 +scripts/debrsign +scripts/debsign +scripts/debsnap +scripts/debuild +scripts/dep-14-convert-git-branch-names +scripts/dep3changelog +scripts/devscripts.chdist +scripts/devscripts.debchange +scripts/devscripts.debsign +scripts/devscripts.egg-info +scripts/devscripts.pkgnames +scripts/devscripts.uupdate +scripts/devscripts/__init__.py +scripts/dget +scripts/dget.1 +scripts/diff2patches +scripts/dpkg-depcheck +scripts/dpkg-genbuilddeps +scripts/dscextract +scripts/dscverify +scripts/edit-patch +scripts/getbuildlog +scripts/grep-excuses +scripts/hardening-check +scripts/hardening-check.1 +scripts/libvfork.o +scripts/libvfork.so.0 +scripts/list-unreleased +scripts/ltnu +scripts/ltnu.1 +scripts/manpage-alert +scripts/mass-bug +scripts/mass-bug.1 +scripts/mergechanges +scripts/mk-origtargz +scripts/mk-origtargz.1 +scripts/mk-build-deps +scripts/mk-build-deps.1 +scripts/namecheck +scripts/namecheck.1 +scripts/nmudiff +scripts/origtargz +scripts/origtargz.1 +scripts/plotchangelog +scripts/pts-subscribe +scripts/rc-alert +scripts/reproducible-check.1 +scripts/rmadison +scripts/rmadison.1 +scripts/run_bisect +scripts/run_bisect_qemu +scripts/sadt.1 +scripts/salsa +scripts/salsa.1 +scripts/svnpath +scripts/svnpath.1 +scripts/tagpending +scripts/tagpending.1 +scripts/transition-check +scripts/transition-check.1 +scripts/uscan +scripts/uscan.1 +scripts/uscan-templates.5 +scripts/uupdate +scripts/what-patch +scripts/who-permits-upload +scripts/who-permits-upload.1 +scripts/who-uploads +scripts/whodepends +scripts/wnpp-alert +scripts/wnpp-check +test-stamp +translated_manpages +version diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000..c03ed4f --- /dev/null +++ b/.mailmap @@ -0,0 +1,5 @@ +James McCoy +James McCoy +Johannes Schauer Marin Rodrigues +Johannes Schauer Marin Rodrigues +Johannes Schauer Marin Rodrigues diff --git a/Makefile.common b/Makefile.common index f45f44c..3d225f0 100644 --- a/Makefile.common +++ b/Makefile.common @@ -3,7 +3,8 @@ GEN_MAN1S := bts.1 build-rdeps.1 chdist.1 debcheckout.1 debcommit.1 \ mk-build-deps.1 mk-origtargz.1 namecheck.1 rmadison.1 sadt.1 svnpath.1 \ uscan.1 salsa.1 \ tagpending.1 origtargz.1 transition-check.1 who-permits-upload.1 \ - git-deborig.1 hardening-check.1 + hardening-check.1 +GEN_MAN5S := PREFIX = /usr BINDIR = $(PREFIX)/bin diff --git a/README.md b/README.md index efeaf98..ca7be17 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ And now, in alphabetical order, the scripts: can be performed by sbuild or other builders in a chroot environment created by debootsnap. The generated artifacts will be verified against the hashes from the buildinfo file. - [sbuild | mmdebstrap, python3-pycurl, libdpkg-perl] + [sbuild | mmdebstrap, python3-pycurl, libdpkg-perl, libstring-shellquote-perl] - debrepro: A script that tests reproducibility of Debian packages. It will build a given source directory twice, with a set of variation between the @@ -191,10 +191,6 @@ And now, in alphabetical order, the scripts: - getbuildlog: download package build logs from Debian auto-builders. [wget] -- git-deborig: try to produce Debian orig.tar using git-archive(1). - [libdpkg-perl, libgit-wrapper-perl, liblist-compare-perl, - libstring-shellquote-perl, libtry-tiny-perl] - - grep-excuses: grep britney's excuses to find out what is happening to your packages. [libdbd-pg-perl, libterm-size-perl, libyaml-libyaml-perl, wget, w3m] diff --git a/conf.default.in b/conf.default.in index 63bebee..0547b1f 100644 --- a/conf.default.in +++ b/conf.default.in @@ -555,11 +555,6 @@ # Should we download newer upstream files we come across? # USCAN_DOWNLOAD=yes # -# Should we use FTP PASV mode for ftp:// links? 'default' means let -# Net::FTP(3) make the choice (primarily based on the FTP_PASSIVE -# environment variable); 'yes' and 'no' override the default -# USCAN_PASV=default -# # Should we create a symlink from the downloaded tar.gz file to # pkg_version.orig.tar.gz, rename it like this or do nothing? # Options are 'symlink'/'yes', 'rename' or 'no' diff --git a/debian/NEWS b/debian/NEWS index 0e31490..c5a6353 100644 --- a/debian/NEWS +++ b/debian/NEWS @@ -1,3 +1,17 @@ +devscripts (2.25.18) unstable; urgency=medium + + A fix (see #1100020) for archive naming issues in uscan required breaking + changes affecting a few debian/watch files: + + - in default (LWP) mode, dirversionmangle rules that duplicate (implicit or + explicit) uversionmangle rules must now be removed + + - in vcs (git and svn) HEAD modes, filenamemangle must now be used instead + of uversionmangle (as was previously suggested by the documentation) to + set a version number. + + -- Julien Plissonneau Duquène Wed, 13 Aug 2025 09:49:22 +0000 + devscripts (2.16.10) unstable; urgency=medium debuild's target mode (i.e. where it runs the specified debian/rules diff --git a/debian/changelog b/debian/changelog index 5560b15..d4dc435 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,123 @@ +devscripts (2.25.18) unstable; urgency=medium + + [ Yadd ] + * uscan: + - When --update-watchfile, try to use templates + - Add libmetacpan-client-perl into suggested packages + * Update French translation + + [ Sean Whitton ] + * Delete git-deborig. + Script is moving to the git-debpush package. See #1105759. + - Drop deps and recs on libgit-wrapper-perl, liblist-compare-perl, + libtry-tiny-perl. + * Add Recommends on git-debpush. + * README.md: debrebuild requires libstring-shellquote-perl. + + [ Bas Couwenberg ] + * debchange: trixie is now stable, forky is testing. + + [ Julien Plissonneau Duquène ] + * uscan: + - Add a test case for using --download-version with version mangling in + git mode. + - Match unmangled versions against --download-version (Closes: #1100020) + - Add NEWS entry about d/watch breaking changes + + -- Sean Whitton Fri, 15 Aug 2025 22:48:48 +0100 + +devscripts (2.25.17) experimental; urgency=medium + + [ наб ] + * uscan: add sample Forgejo (Codeberg) stanzas + + [ James Cowgill ] + * mk-origtargz: + - Exclude empty directories when using Files-Included + (Closes: #1021287) + - Add a test for Files-Included- + - Document --include-file option + * uscan: + - Fix indentation in copyright file examples + - Add an example using the Files-Included stanza (Closes: #977795) + + [ Dorle Osterode ] + * (de) po4a/po/de.po: Update translation + + [ Hugh McMaster ] + * .gitignore: Add scripts/dep-14-convert-git-branch-names + * test/test_uscan_git: + - Update watch file for version 5 syntax + - Use global variable 'MODULE1' for 'subrepo' + - Update some error messages + + [ Yadd ] + * Replace gpg by gnupg and sopv by gpgv into test dependencies because + devscripts tests do not work with sequoia gpg (Closes: #1109607) + * uscan: + - Add "auto" values for Uversion-Mangle and Filename-Mangle + - Add macros @COMPONENT@, @SEMANTIC_VERSION@, @STABLE_VERSION@ + - Fix some debug messages broken by v5 + - Apply pagemangle also when searchmode=plain (Closes: #1057773) + - support overriding +~ delimiter for groups (Closes: #976829) + - add aliases: Version-Regex and Version-Pattern are aliases of + Matching-Pattern + - Fix doc for boolean option (Closes: #1109879) + - Fix Git-Modules option (Closes: #1109883) + - Drop pasv option: no effect for a while (Closes: #1109878) + - Add template engine + * Add GitHub template + * Add Metacpan template + * Update French translations + + [ Niels Thykier ] + * uscan templates: + - Template/Github.pm: + * Set `pgpmode` to `none` by default + * Do not override `Search-Mode` if provided in the file + - Template/Metacpan.pm: + * Set `pgpmode` to `none` by default + * Do not override `source` if provided + * Allow `::` in metacpan dists + - Fix some undef warnings + + -- Yadd Mon, 28 Jul 2025 22:34:14 +0200 + +devscripts (2.25.16) experimental; urgency=medium + + [ Mechtilde ] + * Improved the German translation of the manpage for the tool bts + + [ Nick Brown ] + * uscan: correct setting of request headers + + [ Hugh McMaster ] + * uscan: + - uscan/Downloader.pm: Clone main git repository and submodules separately + - uscan/git.pm: Refactor code to clone versionless repositories with or + without submodules and refactor '$newversion' generation + - test/test_uscan_git: Update submodule test names + - test/test_uscan_git: Add tests to clone from HEAD with submodules + + [ Yadd ] + * salsa: + - Use current repository if project is missing (check_repo, del_repo, + forks, last_ci_status, and merge_requests) and add "path" subcommand + - Add update_watch5 command to update debian/watch to version 5 + * uscan + - Add more git debug + - Add recommended dependency to libio-string-perl (used by uscan/http) + - Better uscan test framework based on LWP::Protocol::PSGI + - Add new debian/watch format: version 5 + * uscan: force Version-Schema to "group" for main watchsource when + Version-Schema is "checksum" + * Split uscan manpage and create debian-watch(5) [version 5] and + debian-watch-4(5) for previous formats + - Add liblwp-protocol-psgi-perl in autopkgtest dependencies + * Update French translation + + -- Yadd Sun, 20 Jul 2025 10:32:11 +0200 + devscripts (2.25.15) unstable; urgency=medium [ Yadd ] diff --git a/debian/control b/debian/control index 510537c..2874ad7 100644 --- a/debian/control +++ b/debian/control @@ -18,8 +18,9 @@ Build-Depends: faketime , file , git (>= 1:2.7.0) , - gpg , + gnupg , gpg-agent , + gpgv , help2man, isort , libdistro-info-perl , @@ -27,15 +28,14 @@ Build-Depends: libfile-dirlist-perl , libfile-homedir-perl , libfile-touch-perl , - libgit-wrapper-perl , libgitlab-api-v4-perl (>= 0.13) , + libio-string-perl , libjson-perl , - liblist-compare-perl , + liblwp-protocol-psgi-perl , libmoo-perl , libstring-shellquote-perl , libtest-output-perl , libtimedate-perl , - libtry-tiny-perl , liburi-perl , libwww-perl , lsb-release , @@ -58,7 +58,6 @@ Build-Depends: python3-unidiff , python3-xdg , shunit2 , - sopv | gpgv , subversion [!i386] , unzip , wdiff , @@ -97,13 +96,12 @@ Recommends: apt (>= 1.3~pre3), dctrl-tools, dput | dupload, + git-debpush (>= 13.12), libdistro-info-perl, libencode-locale-perl, - libgit-wrapper-perl, + libio-string-perl, libjson-perl, - liblist-compare-perl, libstring-shellquote-perl, - libtry-tiny-perl, liburi-perl, licensecheck, lintian, @@ -141,6 +139,7 @@ Suggests: how-can-i-help, libauthen-sasl-perl, libdbd-pg-perl, + libmetacpan-client-perl, libterm-size-perl, libtimedate-perl, libyaml-libyaml-perl, diff --git a/debian/copyright b/debian/copyright index 3033b03..8d1cd43 100644 --- a/debian/copyright +++ b/debian/copyright @@ -239,10 +239,6 @@ Files: scripts/getbuildlog.* Copyright: 2008, Frank S. Thomas License: GPL-2+ -Files: scripts/git-deborig* -Copyright: 2016-2018, Sean Whitton -License: GPL-3+ - Files: scripts/grep-excuses.* Copyright: 2002, Joey Hess License: GPL-2+ diff --git a/debian/manpages b/debian/manpages index 40ace08..fe88aa4 100644 --- a/debian/manpages +++ b/debian/manpages @@ -3,3 +3,4 @@ po4a/de/*.5 po4a/fr/*.1 po4a/fr/*.5 scripts/*.1 +scripts/*.5 diff --git a/debian/tests/control b/debian/tests/control index 3bca5ef..040dae0 100644 --- a/debian/tests/control +++ b/debian/tests/control @@ -1,4 +1,5 @@ Tests: + metacpan, shunit2, Depends: debhelper, @@ -7,9 +8,12 @@ Depends: faketime, git, gnupg, + gpgv, libdistro-info-perl, libgitlab-api-v4-perl, + libio-string-perl, libjson-perl, + liblwp-protocol-psgi-perl, libtest-output-perl, libwww-perl, lzip, @@ -36,3 +40,19 @@ Restrictions: allow-stderr, breaks-testbed, needs-root, + +Tests: + metacpan, +Depends: + debhelper, + libfile-dirlist-perl, + libfile-homedir-perl, + libfile-touch-perl, + libio-string-perl, + libjson-perl, + liblwp-protocol-psgi-perl, + libmetacpan-client-perl, + libwww-perl, +Restrictions: + needs-internet, + allow-stderr, diff --git a/debian/tests/metacpan b/debian/tests/metacpan new file mode 100644 index 0000000..1f67fa5 --- /dev/null +++ b/debian/tests/metacpan @@ -0,0 +1,4 @@ +#!/bin/sh +set -e +cd test +TEST_INTERNET=1 prove -v -I../lib t/uscan.t diff --git a/lib/Devscripts/MkOrigtargz.pm b/lib/Devscripts/MkOrigtargz.pm index b1a691d..aee4183 100644 --- a/lib/Devscripts/MkOrigtargz.pm +++ b/lib/Devscripts/MkOrigtargz.pm @@ -193,6 +193,15 @@ sub make_orig_targz { ds_die($@); return $self->status(1); } + my @include_regexes; + eval { + @include_regexes + = map { glob_to_regex($_) } @{ $self->include_globs }; + }; + if ($@) { + ds_die($@); + return $self->status(1); + } for my $filename (sort @files) { my $last_match; for my $info (@exclude_info) { @@ -204,25 +213,28 @@ sub make_orig_targz { @x ) { if (!$last_match) { - # if the current entry is a directory, check if it - # matches any exclude-ignored glob my $ignore_this_exclude = 0; - for my $ignore_exclude (@{ $self->include_globs }) { - my $ignore_exclude_regex - = glob_to_regex($ignore_exclude); - - if ($filename =~ $ignore_exclude_regex) { + for my $include_regex (@include_regexes) { + if ($filename + =~ m@^(?:[^/]*/)?(?:$include_regex)(?:/.*)?$@x) + { $ignore_this_exclude = 1; last; } - if ( $filename =~ m,/$, - && $ignore_exclude =~ $info->{regex}) { - $ignore_this_exclude = 1; - last; + } + + # if this exclude is ignored, also resurrect + # all parent directories of this file + if ($ignore_this_exclude) { + my @parts = File::Spec->splitdir($filename); + while (pop(@parts)) { + delete( + $delete{ File::Spec->catdir(@parts) . "/" + }); } + } else { + $delete{$filename} = 1; } - next if $ignore_this_exclude; - $delete{$filename} = 1; } $last_match = $info; } diff --git a/lib/Devscripts/Salsa.pm b/lib/Devscripts/Salsa.pm index d1dd92d..a1a3636 100755 --- a/lib/Devscripts/Salsa.pm +++ b/lib/Devscripts/Salsa.pm @@ -31,6 +31,7 @@ BEGIN { use Moo; use File::Basename; use File::Path qw(make_path); +use Dpkg::IPC; # Command aliases use constant cmd_aliases => { @@ -307,6 +308,38 @@ sub id2username { return $res; } +sub localPath2projectPath { + my ($self, $path) = @_; + if (defined $path and !-d $path) { + ds_die "$path isn't a directory"; + return; + } + $path ||= '.'; + unless (-e "$path/.git") { + ds_verbose 'Not a git repository'; + return; + } + my $out; + spawn( + exec => [qw(git remote -v)], + chdir => $path, + to_string => \$out, + wait_child => 1, + nocheck => 0, + ); + if ($@) { + ds_verbose "git error: $@"; + return; + } + my $base = $self->config->git_server_url; + + if ($out =~ /\Q$base\E(.*?)\.git/) { + return $1; + } + ds_verbose "$base not found in git remote"; + return; +} + =item B: convert group name to id =cut diff --git a/lib/Devscripts/Salsa/Config.pm b/lib/Devscripts/Salsa/Config.pm index ece1f18..8fcf5fe 100755 --- a/lib/Devscripts/Salsa/Config.pm +++ b/lib/Devscripts/Salsa/Config.pm @@ -27,7 +27,7 @@ foreach (qw( irker disable_irker irker_host irker_port kgb disable_kgb kgb_options tagpending disable_tagpending - rename_head source_branch dest_branch + rename_head source_branch dest_branch debian_branch enable_remove_branch disable_remove_branch build_timeout ci_config_path schedule_desc schedule_ref schedule_cron schedule_tz schedule_enable @@ -315,7 +315,8 @@ use constant keys => [ # Branch ['rename-head!', 'SALSA_RENAME_HEAD', 'bool'], ['source-branch=s', 'SALSA_SOURCE_BRANCH', undef, 'master'], - ['dest-branch=s', 'SALSA_DEST_BRANCH', undef, 'debian/latest'], + ['debian-branch=s', 'SALSA_DEBIAN_BRANCH'], + ['dest-branch=s', 'SALSA_DEST_BRANCH', undef, 'debian/latest'], [ 'enable-remove-source-branch!', undef, @@ -405,7 +406,7 @@ use constant rules => [ return (0, "No command given, aborting") unless (@ARGV); $_[0]->command(shift @ARGV); return (0, "Malformed command: " . $_[0]->command) - unless ($_[0]->command =~ /^[a-z_]+$/); + unless ($_[0]->command =~ /^[a-z_][a-z0-9_]+$/); return 1; }, sub { diff --git a/lib/Devscripts/Salsa/check_repo.pm b/lib/Devscripts/Salsa/check_repo.pm index c9de322..5265fd3 100755 --- a/lib/Devscripts/Salsa/check_repo.pm +++ b/lib/Devscripts/Salsa/check_repo.pm @@ -31,8 +31,11 @@ sub _check_repo { my $res = 0; my @fail; unless (@reponames or $self->config->all or $self->config->all_archived) { - ds_warn "Usage $0 check_repo <--all|--all-archived|names>"; - return 1; + @reponames = ($self->localPath2projectPath); + unless (@reponames) { + ds_warn "Usage $0 check_repo <--all|--all-archived|names>"; + return 1; + } } if (@reponames and $self->config->all) { ds_warn "--all with a reponame makes no sense"; diff --git a/lib/Devscripts/Salsa/del_repo.pm b/lib/Devscripts/Salsa/del_repo.pm index 2573b64..fddf610 100644 --- a/lib/Devscripts/Salsa/del_repo.pm +++ b/lib/Devscripts/Salsa/del_repo.pm @@ -8,6 +8,7 @@ use Moo::Role; sub del_repo { my ($self, $reponame) = @_; + $reponame ||= $self->localPath2projectPath; unless ($reponame) { ds_warn "Project name or path is missing"; return 1; diff --git a/lib/Devscripts/Salsa/forks.pm b/lib/Devscripts/Salsa/forks.pm index 0d7f710..304b9f5 100644 --- a/lib/Devscripts/Salsa/forks.pm +++ b/lib/Devscripts/Salsa/forks.pm @@ -8,6 +8,7 @@ use Moo::Role; sub forks { my ($self, @reponames) = @_; my $res = 0; + @reponames = ($self->localPath2projectPath) unless @reponames; unless (@reponames) { ds_warn "Project name is missing"; return 1; diff --git a/lib/Devscripts/Salsa/last_ci_status.pm b/lib/Devscripts/Salsa/last_ci_status.pm index 2292c30..c0df28d 100644 --- a/lib/Devscripts/Salsa/last_ci_status.pm +++ b/lib/Devscripts/Salsa/last_ci_status.pm @@ -13,8 +13,11 @@ use constant FAILED => 'failed'; sub last_ci_status { my ($self, @repos) = @_; unless (@repos or $self->config->all or $self->config->all_archived) { - ds_warn "Usage $0 ci_status <--all|--all-archived|names>"; - return 1; + @repos = ($self->localPath2projectPath); + unless (@repos) { + ds_warn "Usage $0 ci_status <--all|--all-archived|names>"; + return 1; + } } if (@repos and $self->config->all) { ds_warn "--all with a project name makes no sense"; diff --git a/lib/Devscripts/Salsa/merge_requests.pm b/lib/Devscripts/Salsa/merge_requests.pm index f647689..11c22a1 100644 --- a/lib/Devscripts/Salsa/merge_requests.pm +++ b/lib/Devscripts/Salsa/merge_requests.pm @@ -8,6 +8,7 @@ use Moo::Role; sub merge_requests { my ($self, @reponames) = @_; my $res = 1; + @reponames = ($self->localPath2projectPath) unless @reponames; unless (@reponames) { ds_warn "project name is missing"; return 1; diff --git a/lib/Devscripts/Salsa/path.pm b/lib/Devscripts/Salsa/path.pm new file mode 100644 index 0000000..6ff10ca --- /dev/null +++ b/lib/Devscripts/Salsa/path.pm @@ -0,0 +1,17 @@ +package Devscripts::Salsa::path; + +use strict; +use Devscripts::Output; +use Dpkg::IPC; +use Moo::Role; + +sub path { + my ($self, $path) = @_; + if (my $remote = $self->localPath2projectPath($path)) { + print "$remote\n"; + return 0; + } + return ds_die "Not found"; +} + +1; diff --git a/lib/Devscripts/Salsa/update_watch5.pm b/lib/Devscripts/Salsa/update_watch5.pm new file mode 100644 index 0000000..d386de5 --- /dev/null +++ b/lib/Devscripts/Salsa/update_watch5.pm @@ -0,0 +1,101 @@ +package Devscripts::Salsa::update_watch5; + +use strict; +use Devscripts::Output; +use Devscripts::Uscan::Version4; +use Dpkg::IPC; +use MIME::Base64; +use Moo::Role; +use File::Temp 'tempdir'; + +with "Devscripts::Salsa::Repo"; + +sub update_watch5 { + my ($self, @reponames) = @_; + my $ret = 0; + my @fail; + unless (@reponames or $self->config->all or $self->config->all_archived) { + ds_warn "Usage $0 check_repo <--all|--all-archived|names>"; + return 1; + } + if (@reponames and $self->config->all) { + ds_warn "--all with a reponame makes no sense"; + return 1; + } + if (@reponames and $self->config->all_archived) { + ds_warn "--all-archived with a reponame makes no sense"; + return 1; + } + my @repos = $self->get_repo(0, @reponames); + return @repos unless (ref $repos[0]); + my $wdir = tempdir(CLEANUP => 1); + my $i = 0; + foreach my $repo (@repos) { + if ($ret and !$self->config->no_fail) { + return $ret; + } + my ($id, $name) = @$repo; + unless ($id) { + ds_debug $@; + ds_warn "Project $name not found"; + $ret++; + next; + } + my $project = eval { $self->api->project($id) }; + unless ($project) { + ds_debug $@; + ds_warn "Project $name not found"; + $ret++; + next; + } + ds_debug "Get debian/watch from $name ($id)"; + my $wbranch + = $self->config->debian_branch || $project->{default_branch}; + my $res = $self->api->file($id, 'debian/watch', { ref => $wbranch }); + + unless ($res) { + ds_warn + "Project $name has no debian/watch file in branch $wbranch"; + $ret++; + next; + } + my $content = decode_base64($res->{content}); + unless ($content) { + ds_warn "Empty debian/watch file in branch $wbranch"; + $ret++; + next; + } + if ($content =~ /Version:\s+5/s) { + ds_warn "Project $name already updated"; + next; + } + $i++; + open my $fh, '>', "$wdir/$i" or die $!; + print $fh $content; + $fh->close; + my $watch5 = Devscripts::Uscan::Version4->new("$wdir/$i"); + unless ($watch5) { + ds_warn "Unable to transform debian/watch from $name ($id)"; + $ret++; + next; + } else { + local $/ = undef; + $content = <$watch5>; + } + $watch5->close; + $content =~ s/(\r?\n){2}$/$1/s; + + $res = $self->api->edit_file( + $id, + 'debian/watch', + { + branch => $wbranch, + commit_message => + 'Update debian/watch to version 5 using salsa update_watch5', + content => $content, + }); + } + return $ret; +} + +1; diff --git a/lib/Devscripts/Uscan.pm b/lib/Devscripts/Uscan.pm new file mode 100644 index 0000000..57c51fa --- /dev/null +++ b/lib/Devscripts/Uscan.pm @@ -0,0 +1,165 @@ +package Devscripts::Uscan; + +use strict; +use warnings; +use Cwd qw/cwd/; +use Exporter 'import'; +use Devscripts::Uscan::Config; +use Devscripts::Uscan::FindFiles; +use Devscripts::Uscan::Output; +use Devscripts::Uscan::WatchFile; + +our @EXPORT = (qw(uscan process_watchfile)); + +sub uscan { + # Reset global variables + %Devscripts::Uscan::WatchLine::already_downloaded = (); + Devscripts::Uscan::Output::reset(); + + # Initialize configuration + my $config = Devscripts::Uscan::Config->new->parse; + if ($dehs) { + uscan_verbose "The --dehs option enabled.\n" + . " STDOUT = XML output for use by other programs\n" + . " STDERR = plain text output for human\n" + . " Use the redirection of STDOUT to a file to get the clean XML data"; + } + + my $res = 0; + + # Search for watchfiles + my @wf = find_watch_files($config); + foreach (@wf) { + + # Read watchfiles + my ($tmp) = process_watchfile($config, @$_); + $res ||= $tmp; + + # Are there any warnings to give if we're using dehs? + dehs_output if ($dehs); + } + + uscan_verbose "Scan finished"; + return ($res, $found); +} + +sub process_watchfile { + my ($config, $pkg_dir, $package, $version, $watchfile) = @_; + my $opwd = cwd(); + chdir $pkg_dir; + + my $wf = Devscripts::Uscan::WatchFile->new({ + config => $config, + package => $package, + pkg_dir => $pkg_dir, + pkg_version => $version, + watchfile => $watchfile, + }); + return ($wf->status, $found) if ($wf->status); + + my $res = $wf->process_lines; + chdir $opwd; + return ($res, $found); +} + +1; +__END__ + +=head1 NAME + +Devscripts::Uscan - Main L library + +=head1 SYNOPSIS + + use Devscripts::Uscan; + my ($res, $found) = uscan(); + exit($res ? $res : $found ? 0 : 1); + +=head1 DESCRIPTION + +Devscripts::Uscan is the main library called by L + +=head2 EXPORT + +This functions are automatically imported: + +=head3 B + +Parse watch files and return two values: + +=over + +=item * B<$res>: the exit code. 0 if nothing wrong happened. + +=item * B<$found>: return the number of new upstream found. + +=back + +=head3 B + +Read given watch file and does L job. + +=head4 Arguments + +=over + +=item * B<$config>: a L object + +=item * B<$pkg_dir>: root of the Debian source directory + +=item * B<$package>: name of the package + +=item * B<$version>: current Debian version of the package + +=item * B<$watchfile>: path to the watch file + +=back + +=head4 Returned values + +B returns 2 values: + +=over + +=item * B<$res>: the exit status. 0 if nothing wrong happened. + +=item * B<$found>: number of upstream updates found. + +B: this value is a cumulative one. If you want to call +B more than one time and want to check this value for +the current watch file, you have to reset it using the global B<$found> +variable provided by L: + + use Devscripts::Uscan::Output; + # Loop + my $res; + while (XX) { + # ... + $found = 0; + $res = process_watchfile(@arguments); + if($found) { + #... + } + } + + +=back + +=head1 SEE ALSO + +L, L + +=head1 AUTHOR + +Xavier Guimard + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2021 by Xavier Guimard + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.32.1 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/lib/Devscripts/Uscan/Config.pm b/lib/Devscripts/Uscan/Config.pm index 6ba22d3..369eafb 100644 --- a/lib/Devscripts/Uscan/Config.pm +++ b/lib/Devscripts/Uscan/Config.pm @@ -25,7 +25,7 @@ use Moo; extends 'Devscripts::Config'; -our $CURRENT_WATCHFILE_VERSION = 4; +our $CURRENT_WATCHFILE_VERSION = 5; use constant default_user_agent => "Debian uscan" . ($main::uscan_version ? " $main::uscan_version" : ''); @@ -47,10 +47,10 @@ has download_current_version => (is => 'rw'); has download_debversion => (is => 'rw'); has download_version => (is => 'rw'); has exclusion => (is => 'rw'); +has version_separator => (is => 'rw'); has log => (is => 'rw'); has orig => (is => 'rw'); has package => (is => 'rw'); -has pasv => (is => 'rw'); has http_header => (is => 'rw', default => sub { {} }); # repack to .tar.$zsuffix if 1 @@ -113,6 +113,7 @@ use constant keys => [ ['uversion|upstream-version=s'], ['vcs-export-uncompressed', 'USCAN_VCS_EXPORT_UNCOMPRESSED', 'bool'], ['watchfile=s'], + ['update-watchfile', undef, 'bool', 0], # 2.3 - More complex options # http headers (#955268) ['http-header=s', 'USCAN_HTTP_HEADER', undef, sub { {} }], @@ -151,22 +152,16 @@ use constant keys => [ ['no-download', undef, sub { $_[0]->download(0); return 1; }], ['overwrite-download', undef, sub { $_[0]->download(3) }], - # "pasv" + # Deprecated "pasv" [ 'pasv|passive', - 'USCAN_PASV', + undef, sub { - return $_[0]->pasv('default') - unless ($_[1] =~ /^(yes|0|1|no)$/); - $_[0]->pasv({ - yes => 1, - 1 => 1, - no => 0, - 0 => 0, - }->{$1}); + warn 'Useless option: only passive mode is available' + if defined $_[1]; return 1; }, - 0 + undef, ], # "safe" and "symlink" and their aliases @@ -216,7 +211,9 @@ use constant keys => [ sub { if ($_[1]) { $_[0]->version; exit 0 } } - ]]; + ], + ['version-separator', 'USCAN_VERSION_SEPARATOR', undef, '+~'], +]; use constant rules => [ sub { @@ -327,8 +324,6 @@ Options: redirections and page content alterations. --no-exclusion Disable automatic exclusion of files mentioned in debian/copyright field Files-Excluded and Files-Excluded-* - --pasv Use PASV mode for FTP connections - --no-pasv Don\'t use PASV mode for FTP connections (default) --no-symlink Don\'t rename nor repack upstream tarball --timeout N Specifies how much time, in seconds, we give remote servers to respond (default 20 seconds) diff --git a/lib/Devscripts/Uscan/Downloader.pm b/lib/Devscripts/Uscan/Downloader.pm index 2d3699a..bedc8d5 100644 --- a/lib/Devscripts/Uscan/Downloader.pm +++ b/lib/Devscripts/Uscan/Downloader.pm @@ -36,19 +36,6 @@ BEGIN { has agent => (is => 'rw', default => sub { "Debian uscan $main::uscan_version" }); has timeout => (is => 'rw'); -has pasv => ( - is => 'rw', - default => 'default', - trigger => sub { - my ($self, $nv) = @_; - if ($nv) { - uscan_verbose "Set passive mode: $self->{pasv}"; - $ENV{'FTP_PASSIVE'} = $self->pasv; - } elsif ($ENV{'FTP_PASSIVE'}) { - uscan_verbose "Unset passive mode"; - delete $ENV{'FTP_PASSIVE'}; - } - }); has destdir => (is => 'rw'); # 0: no repo, 1: shallow clone, 2: full clone @@ -129,7 +116,7 @@ sub download ($$$$$$$$) { . $response->status_line); return 0; } - } elsif ($mode eq 'ftp') { + } elsif ($mode eq 'ftp' or $mode eq 'metacpan') { uscan_verbose "Requesting URL:\n $url"; $request = HTTP::Request->new('GET', "$url"); $response = $self->user_agent->request($request, $fname); @@ -188,17 +175,20 @@ sub download ($$$$$$$$) { my ($infodir, $attr_file, $attr_bkp); if ($self->git_export_all) { # override any export-subst and export-ignore attributes + uscan_debug 'git rev-parse --git-path info/'; spawn( exec => [qw|git rev-parse --git-path info/|], to_string => \$infodir, ); chomp $infodir; mkdir $infodir unless -e $infodir; + uscan_debug 'git rev-parse --git-path info/attributes'; spawn( exec => [qw|git rev-parse --git-path info/attributes|], to_string => \$attr_file, ); chomp $attr_file; + uscan_debug 'git rev-parse --git-path info/attributes-uscan'; spawn( exec => [qw|git rev-parse --git-path info/attributes-uscan|], @@ -230,29 +220,36 @@ sub download ($$$$$$$$) { } } } else { + # clone main repository if ($self->gitrepo_state == 0) { my @opts = (); - if ($optref->git->{modules}) { - foreach my $m (@{ $optref->git->{modules} }) { - push(@opts, "--recurse-submodules=$m"); - } - } else { - push(@opts, '--bare'); - } - $self->gitrepo_state(2); + push(@opts, '--quiet') if not $verbose; + push(@opts, '--bare') if not $optref->git->{modules}; + if ($optref->git->{mode} eq 'shallow') { my $tag = $gitref; $tag =~ s#^refs/(?:tags|heads)/##; - - if ($optref->git->{modules}) { - push(@opts, '--shallow-submodules'); - } push(@opts, '--depth=1', '-b', $tag); $self->gitrepo_state(1); + } else { + $self->gitrepo_state(2); } uscan_exec('git', 'clone', @opts, $base, "$destdir/$gitrepo_dir"); } + # clone submodules + if ($optref->git->{modules}) { + my @opts = (); + push(@opts, '--quiet') if not $verbose; + push(@opts, qw/update --init --recursive/); + push(@opts, '--depth=1') if $self->gitrepo_state == 1; + push(@opts, '--'); + foreach my $m (@{ $optref->git->{modules} }) { + push(@opts, "$m"); + } + chdir "$destdir/$gitrepo_dir"; + uscan_exec('git', 'submodule', @opts); + } chdir "$destdir/$gitrepo_dir" or @@ -266,6 +263,7 @@ sub download ($$$$$$$$) { for (my $tmp, my $i = 0 ; $i < @gitpaths ; $i++) { my @cmd = ("git", "rev-parse", "--git-path", ${ gitpaths [$i] }); + uscan_debug join ' ', @cmd; spawn( exec => [@cmd], to_string => \$tmp, @@ -274,6 +272,8 @@ sub download ($$$$$$$$) { push(@{ $arr_refs[$i] }, split(/\n/, $tmp)); if ($optref->git->{modules}) { + uscan_debug 'git submodule --quiet foreach ' + . join(' ', @cmd); spawn( exec => ['git', 'submodule', '--quiet', 'foreach', @cmd], @@ -310,8 +310,7 @@ sub download ($$$$$$$$) { "--output=$abs_dst/\$sha1.tar HEAD", "&& tar -Af $abs_dst/$pkg-$ver.tar $abs_dst/\$sha1.tar", "&& rm $abs_dst/\$sha1.tar"; - uscan_exec_no_fail('git', 'submodule', '--quiet', 'foreach', - $cmd) == 0 + uscan_exec_no_fail('git', 'submodule', 'foreach', $cmd) == 0 or $clean_and_die->("git archive (submodules) failed"); } diff --git a/lib/Devscripts/Uscan/Output.pm b/lib/Devscripts/Uscan/Output.pm index 77126cf..5c53aec 100644 --- a/lib/Devscripts/Uscan/Output.pm +++ b/lib/Devscripts/Uscan/Output.pm @@ -13,11 +13,17 @@ our @EXPORT = ( )); # ACCESSORS -our ($dehs, $dehs_tags, $dehs_start_output, $dehs_end_output, $found) - = (0, {}, 0, 0); +our ($dehs, $dehs_tags, $dehs_start_output, $dehs_end_output, $found); +reset(); our $progname = basename($0); +sub reset { + ($dehs, $dehs_tags, $dehs_start_output, $dehs_end_output, $found,) + = (0, {}, 0, 0,); + %Devscripts::Uscan::WatchSource::already_downloaded = (); +} + sub printwarn_raw { my ($msg, $w) = @_; if ($w or $dehs) { diff --git a/lib/Devscripts/Uscan/Templates.pod b/lib/Devscripts/Uscan/Templates.pod new file mode 100644 index 0000000..b10bc4c --- /dev/null +++ b/lib/Devscripts/Uscan/Templates.pod @@ -0,0 +1,98 @@ +=pod + +=head1 NAME + +Templates for uscan. + +=head1 DESCRIPTION + +This document explain how to build a template for L. + +=head1 FORMAT OF THE TEMPLATE + +A L template is a Perl class with the following rules: + +=over + +=item * It must be in B namespace + +=item * Its name must start by an uppercase character and others must +be in lowercase + +=item * It must implement a function named B + +=back + +Example: C + +=head1 THE C FUNCTION + +=over + +=item * It receives a single argument I<(C<$watchSource>)> + +=item * It must return the same type of object modified + +=item * It should clean its specific keys + +=item * It should not override parameters explicitly defined in B + +=back + +=head2 Example + +Object received by B: + + { + template => 'GitHub' + project => 'simple-oidc-client', + author => 'linagora', + + version => 5, + _raw => 'Template: GitHub + Owner: linagora + Project: simple-oidc-client + Version-Mangle: auto + ', + } + +Object returned by B: + + { + source => 'https://api.github.com/repos/linagora/simple-oidc-client/git/matching-refs/tags/', + matchingpattern => 'https://api.github.com/repos/[^/]+/[^/]+/git/refs/tags/(?:[^/]+\\-)?@ANY_VERSION@', + searchmode => 'plain', + downloadurlmangle => 's%(api.github.com/repos/[^/]+/[^/]+)/git/refs/%$1/tarball/refs/%g', + filenamemangle => 's%.*/(?:[^/]+\\-)?@ANY_VERSION@%@PACKAGE@-$1.tar.gz%', + gpgmode => 'none', + versionmangle => 'auto', + + version => 5, + _raw => 'Template: GitHub + Owner: linagora + Project: simple-oidc-client + Version-Mangle: auto + ' + } + +=head1 USE TEMPLATE WHEN UPDATING WATCHFILE + +When B is used, it can detect if a template can be used. +To insert a template into this behavior, you must add an entry into the +C<@templates> variable inside B. + +Each entry is a reference to an array with 2 entries: + +=over + +=item * a regular expression compiled with C + +=item * a reference to a function + +This function receives a hash reference that contains the field of a +B I<(a line in version 4)> and must return this reference +modified or not. See B and B examples in this file. + +=back + +=cut diff --git a/lib/Devscripts/Uscan/Templates/Github.pm b/lib/Devscripts/Uscan/Templates/Github.pm new file mode 100644 index 0000000..6667dbd --- /dev/null +++ b/lib/Devscripts/Uscan/Templates/Github.pm @@ -0,0 +1,26 @@ +package Devscripts::Uscan::Templates::Github; + +use strict; + +sub transform { + my $watchSource = shift; + delete $watchSource->{template}; + my $owner = delete $watchSource->{owner}; + my $project = delete $watchSource->{project}; + die 'Missing owner' unless $owner; + die 'Missing project' unless $project; + + $watchSource->{source} + ||= "https://api.github.com/repos/$owner/$project/git/matching-refs/tags/"; + $watchSource->{matchingpattern} + ||= 'https://api.github.com/repos/[^/]+/[^/]+/git/refs/tags/(?:[^/]+\-)?@ANY_VERSION@'; + $watchSource->{downloadurlmangle} + ||= 's%(api.github.com/repos/[^/]+/[^/]+)/git/refs/%$1/tarball/refs/%g'; + $watchSource->{filenamemangle} + ||= 's%.*/(?:[^/]+\-)?@ANY_VERSION@%@PACKAGE@-$1.tar.gz%'; + $watchSource->{searchmode} ||= 'plain'; + $watchSource->{pgpmode} ||= 'none'; + return $watchSource; +} + +1; diff --git a/lib/Devscripts/Uscan/Templates/Metacpan.pm b/lib/Devscripts/Uscan/Templates/Metacpan.pm new file mode 100644 index 0000000..bc53211 --- /dev/null +++ b/lib/Devscripts/Uscan/Templates/Metacpan.pm @@ -0,0 +1,19 @@ +package Devscripts::Uscan::Templates::Metacpan; + +use strict; + +sub transform { + my $watchSource = shift; + delete $watchSource->{template}; + $watchSource->{mode} = 'metacpan'; + my $dist = delete $watchSource->{dist} // ''; + $dist =~ s/::/-/g; + $watchSource->{source} ||= $dist; + die 'Missing Dist' unless $watchSource->{source}; + $watchSource->{matchingpattern} + ||= "https://cpan.metacpan.org/.*$watchSource->{source}-\@ANY_VERSION@"; + $watchSource->{pgpmode} ||= 'none'; + return $watchSource; +} + +1; diff --git a/lib/Devscripts/Uscan/Utils.pm b/lib/Devscripts/Uscan/Utils.pm index e93f240..d98c470 100644 --- a/lib/Devscripts/Uscan/Utils.pm +++ b/lib/Devscripts/Uscan/Utils.pm @@ -28,12 +28,10 @@ sub fix_href ($) { return $href; } -sub recursive_regex_dir ($$$$$$) { +sub recursive_regex_dir ($$$$$) { # If return '', parent code to cause return 1 - my ($line, $base, $dirversionmangle, $watchfile, $lineptr, - $download_version) - = @_; + my ($line, $base, $dirversionmangle, $watchfile, $download_version) = @_; $base =~ m%^(\w+://[^/]+)/(.*)$%; my $site = $1; @@ -47,7 +45,7 @@ sub recursive_regex_dir ($$$$$$) { if ($dirpattern =~ /\(.*\)/) { uscan_verbose "dir=>$dir dirpattern=>$dirpattern"; my $newest_dir = newest_dir($line, $site, $dir, $dirpattern, - $dirversionmangle, $watchfile, $lineptr, $download_version); + $dirversionmangle, $watchfile, $download_version); uscan_verbose "newest_dir => '$newest_dir'"; if ($newest_dir ne '') { $dir .= "$newest_dir"; @@ -63,12 +61,12 @@ sub recursive_regex_dir ($$$$$$) { } # very similar to code above -sub newest_dir ($$$$$$$$) { +sub newest_dir ($$$$$$$) { # return string $newdir as success # return string '' if error, to cause grand parent code to return 1 my ($line, $site, $dir, $pattern, $dirversionmangle, $watchfile, - $lineptr, $download_version) + $download_version) = @_; my ($newdir); uscan_verbose "Requesting URL:\n $site$dir"; @@ -444,19 +442,18 @@ sub safe_replace($$) { } # call this as -# if mangle($watchfile, \$line, 'uversionmangle:', +# if mangle($watchfile, 'uversionmangle:', # \@{$options{'uversionmangle'}}, \$version) { # return 1; # } -sub mangle($$$$$) { - my ($watchfile, $lineptr, $name, $rulesptr, $verptr) = @_; +sub mangle($$$$) { + my ($watchfile, $name, $rulesptr, $verptr) = @_; foreach my $pat (@{$rulesptr}) { if (!safe_replace($verptr, $pat)) { uscan_warn "In $watchfile, potentially" . " unsafe or malformed $name" . " pattern:\n '$pat'" - . " found. Skipping watchline\n" - . " $$lineptr"; + . " found. Skipping watchSource\n"; return 1; } uscan_debug "After $name $$verptr"; diff --git a/lib/Devscripts/Uscan/Version4.pm b/lib/Devscripts/Uscan/Version4.pm new file mode 100644 index 0000000..654b877 --- /dev/null +++ b/lib/Devscripts/Uscan/Version4.pm @@ -0,0 +1,300 @@ +package Devscripts::Uscan::Version4; + +use strict; +use Devscripts::Uscan::Config; +use Devscripts::Uscan::Output; +use Devscripts::Uscan::Config; +use IO::String; + +my %order = ( + Component => 1, + Template => 2, + Source => 3, + 'Matching-Pattern' => 4, +); + +# Prepare attributs name changes between version 4 and version 5 +our %RENAMED = (); + +# Template transformers +my @templates = ( + # Metacpan + # + # The following URLs are grouped here with regexp-asseble(1): + # https://metacpan.org/release/(\w[\w\-\:]*\w) + # https://metacpan.org/dist/(\w[\w\-\:]*\w) + # https://fastapi.metacpan.org/v1/release/(\w[\w\-\:]*\w) + [ +qr#https:\/\/(?:fastapi.metacpan.org\/v1\/release|metacpan.org\/(?:release|dist))\/(\w[\w\-\:]*\w)# + => sub { + my ($res) = @_; + $res->{Dist} = $1; + $res->{Template} = 'Metacpan'; + delete $res->{$_} foreach (qw(Source Matching-Pattern)); + return $res; + } + ], + # Github + [ + qr#https://github.com/([^/]+)/([^/]+)/(releases|tags)# => sub { + my ($res) = @_; + $res->{Template} = 'Github'; + $res->{Owner} = $1; + $res->{Project} = $2; + delete $res->{$_} + foreach ( + qw(Source Matching-Pattern Downloadurlmangle Filenamemangle)); + return $res; + } + ], +); + +sub new { + my ($class, $file, $config) = @_; + local $/ = "\n"; + my ($WATCH); + unless (open $WATCH, '<', $file) { + uscan_die "could not open $file: $!"; + } + my ($newContent, $watch_version); + my $comments = ''; + + # Taken from uscan 2.21.6 + while (<$WATCH>) { + my $res = {}; + if (s/^\s*\#/#/) { + $comments .= $_; + next; + } + next if /^\s*$/; + s/^\s*//; + my ($base, $filepattern, $lastversion, $action); + + CHOMP: + + # Reassemble lines split using \ + chomp; + if (s/(? 3) { + + # drop leading \s only if version 4 + my $nextline = <$WATCH>; + $nextline =~ s/^\s*//; + $_ .= $nextline; + } else { + $_ .= <$WATCH>; + } + goto CHOMP; + } + + # "version" must be the first field + if (!$watch_version) { + + # Looking for "version" field. + if (/^version\s*=\s*(\d+)(\s|$)/) { # Found + $watch_version = $1; + + # Note that version=1 watchfiles have no "version" field so + # authorizated values are >= 2 and <= CURRENT_WATCHFILE_VERSION + if ($watch_version < 2 or $watch_version > 4) { + # "version" field found but has no authorizated value + uscan_warn "$file version number is unrecognised"; + } + + # Next line + next; + } elsif (/^Version: \d+$/) { + die "$file seems to be already updated, aborting"; + } + + # version=1 is deprecated + else { + $watch_version = 1; + } + } + # "version" is fixed, parsing lines now + + # VERSION 1 + if ($watch_version == 1) { + # Handle shell \\ -> \ + s/\\\\/\\/g if $watch_version == 1; + my ($site, $dir); + ($site, $dir, $filepattern, $lastversion, $action) = split ' ', + $_, 4; + if ( !$lastversion + or $site =~ /\(.*\)/ + or $dir =~ /\(.*\)/) { + uscan_warn <{'User-Agent'} = $1; + } + my @opts = sort split /,/, $opts; + foreach my $opt (@opts) { + next unless $opt =~ /\S/; + next + if $opt =~ /^(?:nopas(?:sive|v)|pas(?:sive|v)|active)$/; + uscan_debug "Parsing $opt"; + unless ($opt =~ /^\s*([\w\-]+)(?:\s*=\s*(.*?))?\s*$/) { + uscan_warn "Unable to parse '$opt', skipping"; + next; + } + my ($k, $v) = ($1, $2); + $k = ucfirst $k; + $k =~ s/-(.)/'-'.uc($1)/ge; + $res->{$k} = defined $v ? $v : 'yes'; + } + } + ($base, $filepattern, $lastversion, $action) = split /\s+/, $_, 4; + if ($base =~ s%/([^/]*(?:\@.*\@|\([^/]*\))[^/]*)$%/%) { + + # Last component of $base has a pair of parentheses, so no + # separate filepattern field; we remove the filepattern from the + # end of $base and rescan the rest of the line + $filepattern = $1; + (undef, $lastversion, $action) = split /\s+/, $_, 3; + } + } + # End: Taken form uscan 2.21.6 + + if ($lastversion) { + if ($lastversion =~ m/^(?:group|checksum|ignore)$/) { + $res->{'Version-Schema'} = $lastversion; + } elsif ($lastversion eq 'debian') { + } elsif ($lastversion eq 'prev') { + $res->{'Version-Schema'} = 'previous'; + } else { + $res->{'Version-Constraint'} = $lastversion; + } + } + $res->{Source} = $base; + $res->{'Matching-Pattern'} = $filepattern + if defined $filepattern and $filepattern ne 'debian'; + $res->{'Update-Script'} = $action if defined $action; + + # Use template if --update-watchfile and if possible + if ($config and $config->{update_watchfile}) { + foreach my $tmpl (@templates) { + $res = $tmpl->[1]->($res) if $res->{Source} =~ $tmpl->[0]; + } + } + + # Line was split, storing it now + $newContent .= $comments . join( + "\n", + map { ($RENAMED{ lc $_ } || $_) . ": $res->{$_}" } sort { + $order{$a} ? ($order{$b} ? ($order{$a} <=> $order{$b}) : -1) + : $order{$b} ? 1 + : $a cmp $b + } keys %$res + ) . "\n\n"; + $comments = ''; + } + + close $WATCH or uscan_warn "problems reading $file: $!"; + + $newContent =~ s/\n\n$/\n/s; + $newContent + = "Version: " + . $Devscripts::Uscan::Config::CURRENT_WATCHFILE_VERSION + . "\n\n$newContent"; + my $self = IO::String->new($newContent); + uscan_verbose "File $file converted into << ==EOF==\n$newContent\n==EOF=="; + return $self; +} + +1; +__END__ + +=pod + +=head1 NAME + +Devscripts::Uscan::Version4 - convert on-the-fly old formatted debian/watch to format 5 + +=head1 SYNOPSIS + + use Devscripts::Uscan::Version4; + my $filehandle = Devscripts::Uscan::Version4->new("debian/watch"); + print while (<$filehandle>); + +=head1 DESCRIPTION + +Uscan class to convert on the fly a old formatted debian/watch. + +=head2 Functioning + +Devscripts::Uscan::Version4::new() reads the given watchfile, transform it and +returns a L object. + +=head1 SEE ALSO + +L, L + +=head1 AUTHOR + +Xavier Guimard Eyadd@debian.orgE. + +=head1 COPYRIGHT AND LICENSE + +Xavier Guimard + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +=cut diff --git a/lib/Devscripts/Uscan/WatchFile.pm b/lib/Devscripts/Uscan/WatchFile.pm index 71be449..5bb0830 100644 --- a/lib/Devscripts/Uscan/WatchFile.pm +++ b/lib/Devscripts/Uscan/WatchFile.pm @@ -1,7 +1,7 @@ =head1 NAME -Devscripts::Uscan::WatchFile - watchfile object for L +Devscripts::Uscan::WatchFile - watchsources object for L =head1 SYNOPSIS @@ -35,7 +35,7 @@ Uscan class to parse watchfiles. =head2 new() I<(Constructor)> -Parse watch file and creates L objects for +Parse watch file and creates L objects for each line. =head3 Required parameters @@ -56,7 +56,7 @@ each line. =over -=item watchlines: ref to the array that contains watchlines objects +=item watchSources ref to the array that contains watchSources objects =item watch_version: format version of the watchfile @@ -64,11 +64,11 @@ each line. =head2 process_lines() -Method that launches Devscripts::Uscan::WatchLine::process() on each watchline. +Method that launches Devscripts::Uscan::WatchSource::process() on each watchSource. =head1 SEE ALSO -L, L, L, +L, L, L, L =head1 AUTHOR @@ -97,19 +97,14 @@ package Devscripts::Uscan::WatchFile; use strict; use Devscripts::Uscan::Downloader; use Devscripts::Uscan::Output; -use Devscripts::Uscan::WatchLine; +use Devscripts::Uscan::WatchSource; use Dpkg::Version; use File::Copy qw/copy move/; use List::Util qw/first/; use Moo; -use constant { - ANY_VERSION => '(?:[-_]?[Vv]?(\d[\-+\.:\~\da-zA-Z]*))', - ARCHIVE_EXT => - '(?i)(?:\.(?:tar\.xz|tar\.bz2|tar\.gz|tar\.zstd?|zip|tgz|tbz|txz))', - DEB_EXT => '(?:[\+~](debian|dfsg|ds|deb)(\.)?(\d+)?$)', -}; -use constant SIGNATURE_EXT => ARCHIVE_EXT . '(?:\.(?:asc|pgp|gpg|sig|sign))'; +with 'Devscripts::Uscan::WatchSource::Parser', + 'Devscripts::Uscan::WatchSource::Transform'; # Required new() parameters has config => (is => 'rw', required => 1); @@ -131,7 +126,6 @@ has downloader => ( Devscripts::Uscan::Downloader->new({ timeout => $_[0]->config->timeout, agent => $_[0]->config->user_agent, - pasv => $_[0]->config->pasv, destdir => $_[0]->config->destdir, headers => $_[0]->config->http_header, }); @@ -150,7 +144,9 @@ has origcount => (is => 'rw'); has origtars => (is => 'rw', default => sub { [] }); has status => (is => 'rw', default => sub { 0 }); has watch_version => (is => 'rw'); -has watchlines => (is => 'rw', default => sub { [] }); +has commonOpts => (is => 'rw', default => sub { {} }); +has watchSources => (is => 'rw', default => sub { [] }); +has watchOptions => (is => 'rw', default => sub { [] }); # Values shared between lines has shared => ( @@ -186,6 +182,36 @@ sub BUILD { my $watch_version = 0; my $nextline; $dehs_tags = {}; + my $watchFileHandle; + + if ($self->config->{update_watchfile}) { + require Devscripts::Uscan::Version4; + eval { + $watchFileHandle + = Devscripts::Uscan::Version4->new($args->{watchfile}, + $self->config); + }; + if ($@) { + uscan_die + "Unable to load $args->{watchfile} with Version4.pm:\n$@"; + } else { + local $/ = undef; + my $content = <$watchFileHandle>; + $watchFileHandle->close; + $watchFileHandle = undef; + if (open $watchFileHandle, '>', $args->{watchfile}) { + print $watchFileHandle $content; + $watchFileHandle->close; + uscan_warn "$args->{watchfile} is now converted to version 5."; + uscan_warn + 'BE CAREFUL, some default values changed in version 5, ' + . "you shouldn't commit this without test."; + } else { + uscan_warn "Unable to write $args->{watchfile}: $!"; + } + } + return; + } uscan_verbose "Process watch file at: $args->{watchfile}\n" . " package = $args->{package}\n" @@ -193,90 +219,48 @@ sub BUILD { . " pkg_dir = $args->{pkg_dir}"; $self->origcount(0); # reset to 0 for each watch file - unless (open WATCH, $args->{watchfile}) { + unless (open $watchFileHandle, $args->{watchfile}) { uscan_warn "could not open $args->{watchfile}: $!"; return 1; } - my $lineNumber = 0; - while () { - next if /^\s*\#/; - next if /^\s*$/; - s/^\s*//; - - CHOMP: - - # Reassemble lines split using \ - chomp; - if (s/(?{watchfile} ended with \\; skipping last line"; - $self->status(1); - last; - } - if ($watch_version > 3) { - - # drop leading \s only if version 4 - $nextline = ; - $nextline =~ s/^\s*//; - $_ .= $nextline; - } else { - $_ .= ; - } - goto CHOMP; - } - - # "version" must be the first field - if (!$watch_version) { - - # Looking for "version" field. - if (/^version\s*=\s*(\d+)(\s|$)/) { # Found - $watch_version = $1; - - # Note that version=1 watchfiles have no "version" field so - # authorizated values are >= 2 and <= CURRENT_WATCHFILE_VERSION - if ( $watch_version < 2 - or $watch_version - > $Devscripts::Uscan::Config::CURRENT_WATCHFILE_VERSION) { - # "version" field found but has no authorizated value - uscan_warn -"$args->{watchfile} version number is unrecognised; skipping watch file"; - last; - } - - # Next line - next; - } - - # version=1 is deprecated - else { - $watch_version = 1; - } - } - if ($watch_version < 3) { - uscan_warn -"$args->{watchfile} is an obsolete version $watch_version watch file;\n" - . " please upgrade to a higher version\n" - . " (see uscan(1) for details)."; + eval { $self->parseWatchFile($watchFileHandle, $args) }; + my $error; + if ($@) { + uscan_debug "Version 5 parser returned: $@"; + # TODO: later, increase log level to uscan_warn + uscan_verbose + "$args->{watchfile} isn't formatted in version 5, trying version 4"; + $error = $@; + $watchFileHandle->close; + require Devscripts::Uscan::Version4; + eval { + $watchFileHandle + = Devscripts::Uscan::Version4->new($args->{watchfile}); + }; + if ($@) { + uscan_warn "Unable to read $args->{watchfile}:\n" + . " - version 5: $error\n" + . " - version <5: $@\n"; + return; } + $self->parseWatchFile($watchFileHandle, $args); + uscan_verbose 'Reset watch_version to 4 because ' + . 'default value may change in version 5'; + $self->watch_version(4); + } + close $watchFileHandle + or $self->status(1), + uscan_warn "problems reading $$args->{watchfile}: $!"; - # "version" is fixed, parsing lines now - - # Are there any warnings from this part to give if we're using dehs? - dehs_output if ($dehs); - - # Handle shell \\ -> \ - s/\\\\/\\/g if $watch_version == 1; - - # Handle @PACKAGE@ @ANY_VERSION@ @ARCHIVE_EXT@ substitutions - s/\@PACKAGE\@/$args->{package}/g; - s/\@ANY_VERSION\@/ANY_VERSION/ge; - s/\@ARCHIVE_EXT\@/ARCHIVE_EXT/ge; - s/\@SIGNATURE_EXT\@/SIGNATURE_EXT/ge; - s/\@DEB_EXT\@/DEB_EXT/ge; + unless ($self->transformWatchSource($args)) { + uscan_die "Unable to read watchSource"; + return; + } - my $line = Devscripts::Uscan::WatchLine->new({ + my $lineNumber = 0; + foreach my $watchSource (@{ $self->watchOptions }) { + my $line = Devscripts::Uscan::WatchSource->new({ # Shared between lines config => $self->config, downloader => $self->downloader, @@ -284,29 +268,24 @@ sub BUILD { keyring => $self->keyring, # Other parameters - line => $_, + watchSource => $watchSource, pkg => $self->package, pkg_dir => $self->pkg_dir, pkg_version => $self->pkg_version, - watch_version => $watch_version, + watch_version => $self->watch_version, watchfile => $self->watchfile, }); push @{ $self->group }, $lineNumber if ($line->type and $line->type =~ /^(?:group|checksum)$/); - push @{ $self->watchlines }, $line; + push @{ $self->watchSources }, $line; $lineNumber++; } - - close WATCH - or $self->status(1), - uscan_warn "problems reading $$args->{watchfile}: $!"; - $self->watch_version($watch_version); } sub process_lines { my ($self) = shift; return $self->process_group if (@{ $self->group }); - foreach (@{ $self->watchlines }) { + foreach (@{ $self->watchSources }) { # search newfile and newversion my $res = $_->process; @@ -316,10 +295,13 @@ sub process_lines { } sub process_group { - my ($self) = @_; - my $saveDconfig = $self->config->download_version; + my ($self) = @_; + my $saveDconfig = $self->config->download_version; + my $versionSeparator = $self->commonOpts->{versionseparator} + || $self->{config}->{version_separator}; + my $rsep = qr/\Q$versionSeparator\E/; # Build version - my @cur_versions = split /\+~/, $self->pkg_version; + my @cur_versions = split $rsep, $self->pkg_version; my $checksum = 0; my $newChecksum = 0; if ( $cur_versions[$#cur_versions] @@ -334,11 +316,15 @@ sub process_group { my @ck_versions; # Isolate component and following lines if (my $v = $self->config->download_version) { - @dversion = map { s/\+.*$//; /^cs/ ? () : $_ } split /\+~/, $v; + @dversion = map { s/\+.*$//; /^cs/ ? () : $_ } + split $rsep, $v; } - foreach my $line (@{ $self->watchlines }) { - if ( $line->type and $line->type eq 'group' - or $line->type eq 'checksum') { + foreach my $line (@{ $self->watchSources }) { + if ( + $line->type + and ( $line->type eq 'group' + or $line->type eq 'checksum') + ) { $last_shared = $self->new_shared; $last_comp_version = shift @cur_versions if $line->type eq 'group'; } @@ -349,8 +335,10 @@ sub process_group { $line->pkg_version($last_comp_version || 0); } # Check if download is needed - foreach my $line (@{ $self->watchlines }) { - next unless ($line->type eq 'group' or $line->type eq 'checksum'); + foreach my $line (@{ $self->watchSources }) { + next + unless ($line->type + and ($line->type eq 'group' or $line->type eq 'checksum')); # Stop on error $self->config->download_version($line->{groupDversion}) if $line->{groupDversion}; @@ -368,17 +356,18 @@ sub process_group { if $line->shared->{download} > $download and ($line->type eq 'group' or $line->ctype); } - foreach my $line (@{ $self->watchlines }) { - next unless $line->type eq 'checksum'; + foreach my $line (@{ $self->watchSources }) { + next unless $line->type and $line->type eq 'checksum'; $newChecksum - = $self->sum($newChecksum, $line->search_result->{newversion}); - push @ck_versions, $line->search_result->{newversion}; + = $self->sum($newChecksum, + $line->search_result->{mangled_newversion}); + push @ck_versions, $line->search_result->{mangled_newversion}; } - foreach my $line (@{ $self->watchlines }) { - next unless ($line->type eq 'checksum'); + foreach my $line (@{ $self->watchSources }) { + next unless ($line->type and $line->type eq 'checksum'); $line->parse_result->{mangled_lastversion} = $checksum; - my $tmp = $line->search_result->{newversion}; - $line->search_result->{newversion} = $newChecksum; + my $tmp = $line->search_result->{mangled_newversion}; + $line->search_result->{mangled_newversion} = $newChecksum; unless ($line->ctype) { if ($line->cmp_versions) { $self->{status} += $line->status; @@ -387,17 +376,18 @@ sub process_group { $download = $line->shared->{download} if $line->shared->{download} > $download; } - $line->search_result->{newversion} = $tmp; + $line->search_result->{mangled_newversion} = $tmp; if ($line->component) { pop @{ $dehs_tags->{'component-upstream-version'} }; push @{ $dehs_tags->{'component-upstream-version'} }, $tmp; } } - foreach my $line (@{ $self->watchlines }) { + foreach my $line (@{ $self->watchSources }) { # Set same $download for all $line->shared->{download} = $download; # Non "group" lines where not initialized - unless ($line->type eq 'group' or $line->type eq 'checksum') { + unless ($line->type + and ($line->type eq 'group' or $line->type eq 'checksum')) { if ( $line->parse or $line->search or $line->get_upstream_url @@ -415,7 +405,7 @@ sub process_group { $self->{status} += $line->status; return $self->{status}; } - if ($line->type eq 'group') { + if ($line->type and $line->type eq 'group') { push @new_versions, $line->shared->{common_mangled_newversion} || $line->shared->{common_newversion} || (); @@ -424,18 +414,18 @@ sub process_group { $line->parse_result->{mangled_lastversion}; } } - my $new_version = join '+~', @new_versions; + my $new_version = join $versionSeparator, @new_versions; if ($newChecksum) { - $new_version .= "+~cs$newChecksum"; + $new_version .= "${versionSeparator}cs$newChecksum"; } if ($checksum) { push @last_versions, "cs$newChecksum"; push @last_debian_mangled_uversions, "cs$checksum"; } $dehs_tags->{'upstream-version'} = $new_version; - $dehs_tags->{'debian-uversion'} = join('+~', @last_versions) + $dehs_tags->{'debian-uversion'} = join($versionSeparator, @last_versions) if (grep { $_ } @last_versions); - $dehs_tags->{'debian-mangled-uversion'} = join '+~', + $dehs_tags->{'debian-mangled-uversion'} = join $versionSeparator, @last_debian_mangled_uversions if (grep { $_ } @last_debian_mangled_uversions); my $mangled_ver @@ -450,7 +440,7 @@ sub process_group { } else { $dehs_tags->{'status'} = "newer package available"; } - foreach my $line (@{ $self->watchlines }) { + foreach my $line (@{ $self->watchSources }) { my $path = $line->destfile or next; my $ver = $line->shared->{common_mangled_newversion}; $path =~ s/\Q$ver\E/$new_version/; @@ -480,11 +470,12 @@ sub process_group { } } if (@ck_versions) { - my $v = join '+~', @ck_versions; + my $v = join $versionSeparator, @ck_versions; if ($dehs) { $dehs_tags->{'decoded-checksum'} = $v; } else { - uscan_verbose 'Checksum ref: ' . join('+~', @ck_versions) . "\n"; + uscan_verbose 'Checksum ref: ' + . join($versionSeparator, @ck_versions) . "\n"; } } return 0; diff --git a/lib/Devscripts/Uscan/WatchLine.pm b/lib/Devscripts/Uscan/WatchSource.pm similarity index 72% rename from lib/Devscripts/Uscan/WatchLine.pm rename to lib/Devscripts/Uscan/WatchSource.pm index 55d6312..10db1ea 100644 --- a/lib/Devscripts/Uscan/WatchLine.pm +++ b/lib/Devscripts/Uscan/WatchSource.pm @@ -3,7 +3,7 @@ =head1 NAME -Devscripts::Uscan::WatchLine - watch line object for L +Devscripts::Uscan::WatchSource - watch source object for L =head1 DESCRIPTION @@ -13,7 +13,7 @@ Uscan class to parse watchfiles. =cut -package Devscripts::Uscan::WatchLine; +package Devscripts::Uscan::WatchSource; use strict; use Cwd qw/abs_path/; @@ -39,7 +39,7 @@ use Text::ParseWords; =over -=item B: ref to hash containing line options shared between lines. See +=item B: ref to hash containing watch source options shared between lines. See L code to see required keys. =item B: L object @@ -48,7 +48,9 @@ L code to see required keys. =item B: L object -=item B: search line (assembled in one line) +=item B: hash containing whatch sources options (built by +L using L +and L =item B: Debian package name @@ -71,7 +73,7 @@ foreach ( # Other 'downloader', # Devscripts::Uscan::Downloader object - 'line', # watch line string (concatenated line over the tailing \ ) + 'watchSource', # watch line string (concatenated line over the tailing \ ) 'pkg', # source package name found in debian/changelog 'pkg_dir', # usually . 'pkg_version', # last source package version @@ -158,7 +160,7 @@ foreach (qw(force_repack type upstream_url newfile_base)) { has $_ => (is => 'rw'); } -# 3.1 - Attributes initialized with default value, modified by line content +# 3.1 - Attributes initialized with default value, modified by watch source options has date => ( is => 'rw', default => sub { '%Y%m%d' }, @@ -231,7 +233,7 @@ If one method returns a non 0 value, it stops and return this error code. sub process { my ($self) = @_; - # - parse line + # - parse options $self->parse # - search newfile and newversion @@ -269,7 +271,7 @@ sub process { =head3 parse() -Parse the line and return 0 if nothing bad happen. It populates +Parse the watch source options and return 0 if nothing bad happen. It populates C<$self-Eparse_result> accessor with a hash that contains the following keys: @@ -333,22 +335,16 @@ following keys: sub BUILD { my ($self, $args) = @_; if ($self->watch_version > 3) { - my $line = $self->line; - if ($line =~ s/^opt(?:ion)?s\s*=\s*//) { - unless ($line =~ s/^".*?"(?:\s+|$)//) { - $line =~ s/^[^"\s]\S*(?:\s+|$)//; - } - } - my ($base, $filepattern, $lastversion, $action) = split /\s+/, $line, - 4; - $self->type($lastversion); + $self->type($self->watchSource->{versionschema}); } return $self; } sub parse { my ($self) = @_; - uscan_debug "parse line $self->{line}"; + uscan_debug "parse options: << ==EOF==\n" + . $self->{watchSource}->{_raw} + . "==EOF==\n"; # Need to clear remembered redirection URLs so we don't try to build URLs # from previous watch files or watch lines @@ -358,404 +354,305 @@ sub parse { my ($action, $base, $basedir, $filepattern, $lastversion, $pattern, $site); $dehs_tags->{package} = $self->pkg; - # Start parsing the watch line - if ($self->watch_version == 1) { - my ($dir); - ($site, $dir, $filepattern, $lastversion, $action) = split ' ', - $self->line, 5; - if ( !$lastversion - or $site =~ /\(.*\)/ - or $dir =~ /\(.*\)/) { - uscan_warn <{line} -EOF - return $self->status(1); - } - if ($site !~ m%\w+://%) { - $site = "ftp://$site"; - if ($filepattern !~ /\(.*\)/) { - - # watch_version=1 and old style watch file; - # pattern uses ? and * shell wildcards; everything from the - # first to last of these metachars is the pattern to match on - $filepattern =~ s/(\?|\*)/($1/; - $filepattern =~ s/(\?|\*)([^\?\*]*)$/$1)$2/; - $filepattern =~ s/\./\\./g; - $filepattern =~ s/\?/./g; - $filepattern =~ s/\*/.*/g; - $self->style('old'); - uscan_warn - "Using very old style of filename pattern in $watchfile\n" - . " (this might lead to incorrect results): $3"; - } - } - - # Merge site and dir - $base = "$site/$dir/"; - $base =~ s%(?{line}"; - return $self->status(1); + # Start parsing the watch source + # version 2/3/4 watch file + my $opts = $self->watchSource; + + if ($opts->{useragent}) { + my $user_agent_string = $opts->{useragent}; + $user_agent_string = $self->config->user_agent + if $self->config->user_agent ne + &Devscripts::Uscan::Config::default_user_agent; + $self->downloader->user_agent->agent($user_agent_string); + uscan_verbose "User-agent: $user_agent_string"; + delete $opts->{useragent}; + } + foreach my $optName (sort keys %$opts) { + next + if $optName + =~ /(?:source|version|versionschema|matchingpattern|_raw|updatescript)$/; + my $optVal = $opts->{$optName}; + uscan_verbose "Parsing $optName=$optVal"; + if ($optName =~ /^(?:nopas(?:sive|v)|pas(?:sive|v)|active)$/) { + uscan_warn + "Option $optName is deprecated, only passive mode is available"; } - } else { - # version 2/3/4 watch file - if ($self->{line} =~ s/^opt(?:ion)?s\s*=\s*//) { - my $opts; - if ($self->{line} =~ s/^"(.*?)"(?:\s+|$)//) { - $opts = $1; - } elsif ($self->{line} =~ s/^([^"\s]\S*)(?:\s+|$)//) { - $opts = $1; - } else { - uscan_warn -"malformed opts=... in watch file, skipping line:\n$self->{line}"; - return $self->status(1); - } - - # $opts string extracted from the argument of opts= - uscan_verbose "opts: $opts"; - - # $self->line watch line string without opts=... part - uscan_verbose "line: $self->{line}"; - - # user-agent strings has ,;: in it so special handling - if ( $opts =~ /^\s*user-agent\s*=\s*(.+?)\s*$/ - or $opts =~ /^\s*useragent\s*=\s*(.+?)\s*$/) { - my $user_agent_string = $1; - $user_agent_string = $self->config->user_agent - if $self->config->user_agent ne - &Devscripts::Uscan::Config::default_user_agent; - $self->downloader->user_agent->agent($user_agent_string); - uscan_verbose "User-agent: $user_agent_string"; - $opts = ''; - } - my @opts = split /,/, $opts; - foreach my $opt (@opts) { - next unless ($opt =~ /\S/); - uscan_verbose "Parsing $opt"; - if ($opt =~ /^\s*pasv\s*$/ or $opt =~ /^\s*passive\s*$/) { - $self->downloader->pasv(1); - } elsif ($opt =~ /^\s*active\s*$/ - or $opt =~ /^\s*nopasv\s*$/ - or $opt =~ /^\s*nopassive\s*$/) { - $self->downloader->pasv(0); - } - - # Line option "compression" is ignored if "--compression" - # was set in command-line - elsif ($opt =~ /^\s*compression\s*=\s*(.+?)\s*$/ - and not $self->compression) { - $self->compression(get_compression($1)); - } elsif ($opt =~ /^\s*bare\s*$/) { - - # persistent $bare - ${ $self->shared->{bare} } = 1; - } - - # Boolean line parameter - # - # $ regexp-assemble <git->{modules} = ['.']; - } elsif ($opt =~ /^\s*(decompress|repack)\s*$/) { - $self->$1(1); - } - - # Line parameter with a value - # - # $ regexp-assemble <$1($2); - } elsif ($opt =~ /^\s*git(export|mode)\s*=\s*(.+?)\s*$/) { - $self->git->{$1} = $2; - } elsif ($opt =~ /^\s*gitmodules\s*=\s*(.+?)\s*$/) { - $self->git->{modules} = [split /;/, $1]; - } elsif ($opt =~ /^\s*versionmangle\s*=\s*(.+?)\s*$/) { - $self->uversionmangle([split /;/, $1]); - $self->dversionmangle([split /;/, $1]); - } elsif ($opt =~ /^\s*pgpsigurlmangle\s*=\s*(.+?)\s*$/) { - $self->pgpsigurlmangle([split /;/, $1]); - $self->pgpmode('mangle'); - } elsif ($opt =~ /^\s*dversionmangle\s*=\s*(.+?)\s*$/) { - - $self->dversionmangle([ - map { - - # If dversionmangle is "auto", replace it by - # DEB_EXT removal - $_ eq 'auto' - ? ('s/' - . &Devscripts::Uscan::WatchFile::DEB_EXT - . '//') - : ($_) - } split /;/, - $1 - ]); - } - # Handle other *mangle: - # - # $ regexp-assemble <$1([split /;/, $2]); - } else { - uscan_warn "unrecognized option $opt"; - } - } + # Line option "compression" is ignored if "--compression" + # was set in command-line + elsif ($optName eq 'compression' and not $self->compression) { + $self->compression(get_compression($optVal)); + } elsif ($optName eq 'bare') { - # $self->line watch line string when no opts=... - uscan_verbose "line: $self->{line}"; + # persistent $bare + ${ $self->shared->{bare} } = _booleanVal($optVal, $optName); } - if ($self->line eq '') { - uscan_verbose "watch line only with opts=\"...\" and no URL"; - return $self->status(1); + # Boolean line parameter + # + # $ regexp-assemble <setBooleanValue($optName, $optVal); } - # 4 parameter watch line - ($base, $filepattern, $lastversion, $action) = split /\s+/, - $self->line, 4; - - # 3 parameter watch line (override) - if ($base =~ s%/([^/]*\([^/]*\)[^/]*)$%/%) { - - # Last component of $base has a pair of parentheses, so no - # separate filepattern field; we remove the filepattern from the - # end of $base and rescan the rest of the line - $filepattern = $1; - (undef, $lastversion, $action) = split /\s+/, $self->line, 3; - } - - # Always define "" if not defined - $lastversion //= ''; - $action //= ''; - if ($self->mode eq 'LWP') { - if ($base =~ m%^https?://%) { - $self->mode('http'); - } elsif ($base =~ m%^ftp://%) { - $self->mode('ftp'); + # Line parameter with a value + # + # $ regexp-assemble <$optName($optVal); + } elsif ($optName =~ /^git(export|mode)$/) { + $self->git->{$1} = $optVal; + } elsif ($optName eq 'gitmodules') { + if ($optVal eq 'all' or 'yes') { + $self->git->{modules} = ['.']; } else { - uscan_warn "unknown protocol for LWP: $base"; - return $self->status(1); - } - } - - # compression is persistent - $self->compression('default') unless ($self->compression); - - # Set $lastversion to the numeric last version - # Update $self->versionmode (its default "newer") - if (!length($lastversion) - or $lastversion =~ /^(group|checksum|debian)$/) { - if (!defined $self->pkg_version) { - uscan_warn "Unable to determine the current version\n" - . " in $watchfile, skipping:\n $self->{line}"; - return $self->status(1); + $self->git->{modules} = [split /;/, $optVal]; } - $lastversion = $self->pkg_version; - } elsif ($lastversion eq 'ignore') { - $self->versionmode('ignore'); - $lastversion = $minversion; - } elsif ($lastversion eq 'same') { - $self->versionmode('same'); - $lastversion = $minversion; - } elsif ($lastversion =~ m/^prev/) { - $self->versionmode('previous'); - - # set $lastversion = $previous_newversion later + } elsif ($optName eq 'versionmangle') { + $self->uversionmangle([split /;/, $optVal]); + $self->dversionmangle([split /;/, $optVal]); + } elsif ($optName eq 'pgpsigurlmangle') { + $self->pgpsigurlmangle([split /;/, $optVal]); + $self->pgpmode('mangle'); } - - # Check $filepattern has ( ...) - if ($filepattern !~ /\([^?].*\)/) { - if (($self->mode eq 'git' or $self->mode eq 'svn') - and $filepattern eq 'HEAD') { - $self->versionless(1); - } elsif ($self->mode eq 'git' - and $filepattern =~ m&^heads/&) { - $self->versionless(1); - } elsif ($self->mode eq 'http' - and @{ $self->filenamemangle }) { - $self->versionless(1); - } else { - uscan_warn - "Tag pattern missing version delimiters () in $watchfile" - . ", skipping:\n $self->{line}"; - return $self->status(1); - } + # Handle other *mangle: + # + # $ regexp-assemble <$optName([split /;/, $optVal]); + } elsif ($optName eq 'versionschema') { + $self->versionmode($optVal); + } else { + uscan_warn "unrecognized option $optName: $optVal"; } + } - # Check validity of options - if ($self->mode eq 'ftp' - and @{ $self->downloadurlmangle }) { - uscan_warn "downloadurlmangle option invalid for ftp sites,\n" - . " ignoring downloadurlmangle in $watchfile:\n" - . " $self->{line}"; + uscan_extra_debug "watchSource: << ==EOF==\n" + . $self->{watchSource}->{_raw} + . "==EOF==\n"; + + # 4 parameter watch line + ($base, $filepattern, $lastversion, $action) = ( + $opts->{source}, + $opts->{matchingpattern}, + $opts->{versionconstraint} // '', + $opts->{updatescript} // '' + ); + + if ($self->mode eq 'LWP') { + if ($base =~ m%^https?://%) { + $self->mode('http'); + } elsif ($base =~ m%^ftp://%) { + $self->mode('ftp'); + } else { + uscan_warn "unknown protocol for LWP: $base"; return $self->status(1); } - if ($self->mode ne 'git' and $self->git->{export} ne 'default') { - uscan_warn "gitexport option is valid only in git mode,\n" - . " ignoring gitexport in $watchfile:\n" - . " $self->{line}"; + } + + # compression is persistent + $self->compression('default') unless ($self->compression); + + # Set $lastversion to the numeric last version + # Update $self->versionmode (its default "newer") + if (!length($lastversion) + or $self->versionmode =~ /^(group|checksum)$/) { + if (!defined $self->pkg_version) { + uscan_warn "Unable to determine the current version\n" + . " in $watchfile, skipping:\n $self->{watchSource}->{source}"; return $self->status(1); } + $lastversion = $self->pkg_version; + } elsif ($self->versionmode eq 'ignore') { + $lastversion = $minversion; + } elsif ($lastversion eq 'same') { + $self->versionmode('same'); + $lastversion = $minversion; + } elsif ($self->versionmode eq 'previous') { + # set $lastversion = $previous_newversion later + } - # Limit use of opts="repacksuffix" to the single upstream package - if ($self->repacksuffix and @{ $self->shared->{components} }) { + # Check $filepattern has ( ...) + if ($filepattern !~ /\([^?].*\)/) { + if (($self->mode eq 'git' or $self->mode eq 'svn') + and $filepattern eq 'HEAD') { + $self->versionless(1); + } elsif ($self->mode eq 'git' + and $filepattern =~ m&^heads/&) { + $self->versionless(1); + } elsif ($self->mode eq 'http' + and @{ $self->filenamemangle }) { + $self->versionless(1); + } else { uscan_warn -"repacksuffix is not compatible with the multiple upstream tarballs;\n" - . " use oversionmangle"; + "Tag pattern missing version delimiters () in $watchfile" + . ", skipping:"; return $self->status(1); } + } - # Allow 2 char shorthands for opts="pgpmode=..." and check - if ($self->pgpmode =~ m/^au/) { - $self->pgpmode('auto'); - if (@{ $self->pgpsigurlmangle }) { - uscan_warn "Ignore pgpsigurlmangle because pgpmode=auto"; - $self->pgpsigurlmangle([]); - } - } elsif ($self->pgpmode =~ m/^ma/) { - $self->pgpmode('mangle'); - if (not @{ $self->pgpsigurlmangle }) { - uscan_warn "Missing pgpsigurlmangle. Setting pgpmode=default"; - $self->pgpmode('default'); - } - } elsif ($self->pgpmode =~ m/^no/) { - $self->pgpmode('none'); - } elsif ($self->pgpmode =~ m/^ne/) { - $self->pgpmode('next'); - } elsif ($self->pgpmode =~ m/^pr/) { - $self->pgpmode('previous'); - $self->versionmode('previous'); # no other value allowed - # set $lastversion = $previous_newversion later - } elsif ($self->pgpmode =~ m/^se/) { - $self->pgpmode('self'); - } elsif ($self->pgpmode =~ m/^git/) { - $self->pgpmode('gittag'); - } else { - $self->pgpmode('default'); - } + # Check validity of options + if ($self->mode eq 'ftp' + and @{ $self->downloadurlmangle }) { + uscan_warn "downloadurlmangle option invalid for ftp sites,\n" + . " ignoring downloadurlmangle in $watchfile:\n" + . " $self->{watchSource}->{source}"; + return $self->status(1); + } + if ($self->mode ne 'git' and $self->git->{export} ne 'default') { + uscan_warn "gitexport option is valid only in git mode,\n" + . " ignoring gitexport in $watchfile:\n" + . " $self->{watchSource}->{source}"; + return $self->status(1); + } - # For mode=svn, make pgpmode=none the default - if ($self->mode eq 'svn') { - if ($self->pgpmode eq 'default') { - $self->pgpmode('none'); - } elsif ($self->pgpmode ne 'none') { - uscan_die "Only pgpmode=none can be used with mode=svn.\n"; - } - } + # Limit use of opts="repacksuffix" to the single upstream package + if ($self->repacksuffix and @{ $self->shared->{components} }) { + uscan_warn +"repacksuffix is not compatible with the multiple upstream tarballs;\n" + . " use oversionmangle"; + return $self->status(1); + } - # If PGP used, check required programs and generate files + # Allow 2 char shorthands for opts="pgpmode=..." and check + if ($self->pgpmode =~ m/^au/) { + $self->pgpmode('auto'); if (@{ $self->pgpsigurlmangle }) { - my $pgpsigurlmanglestring = join(";", @{ $self->pgpsigurlmangle }); - uscan_debug "\$self->{'pgpmode'}=$self->{'pgpmode'}, " - . "\$self->{'pgpsigurlmangle'}=$pgpsigurlmanglestring"; - } else { - uscan_debug "\$self->{'pgpmode'}=$self->{'pgpmode'}, " - . "\$self->{'pgpsigurlmangle'}=undef"; + uscan_warn "Ignore pgpsigurlmangle because pgpmode=auto"; + $self->pgpsigurlmangle([]); + } + } elsif ($self->pgpmode =~ m/^ma/) { + $self->pgpmode('mangle'); + if (not @{ $self->pgpsigurlmangle }) { + uscan_warn "Missing pgpsigurlmangle. Setting pgpmode=default"; + $self->pgpmode('default'); } + } elsif ($self->pgpmode =~ m/^no/) { + $self->pgpmode('none'); + } elsif ($self->pgpmode =~ m/^ne/) { + $self->pgpmode('next'); + } elsif ($self->pgpmode =~ m/^pr/) { + $self->pgpmode('previous'); + $self->versionmode('previous'); # no other value allowed + # set $lastversion = $previous_newversion later + } elsif ($self->pgpmode =~ m/^se/) { + $self->pgpmode('self'); + } elsif ($self->pgpmode =~ m/^git/) { + $self->pgpmode('gittag'); + } else { + $self->pgpmode('default'); + } - # Check component for duplication and set $orig to the proper - # extension string - if ($self->pgpmode ne 'previous') { - if ($self->component) { - if (grep { $_ eq $self->component } - @{ $self->shared->{components} }) { - uscan_warn "duplicate component name: $self->{component}"; - return $self->status(1); - } - push @{ $self->shared->{components} }, $self->component; - } else { - $self->shared->{origcount}++; - if ($self->shared->{origcount} > 1) { - uscan_warn "more than one main upstream tarballs listed."; - - # reset variables - @{ $self->shared->{components} } = (); - $self->{shared}->{common_newversion} = undef; - $self->{shared}->{common_mangled_newversion} = undef; - $self->{shared}->{previous_newversion} = undef; - $self->{shared}->{previous_newfile_base} = undef; - $self->{shared}->{previous_sigfile_base} = undef; - $self->{shared}->{previous_download_available} = undef; - $self->{shared}->{uscanlog} = undef; - } - } + # For mode=svn, make pgpmode=none the default + if ($self->mode eq 'svn') { + if ($self->pgpmode eq 'default') { + $self->pgpmode('none'); + } elsif ($self->pgpmode ne 'none') { + uscan_die "Only pgpmode=none can be used with mode=svn.\n"; } + } - # Allow 2 char shorthands for opts="gitmode=..." and check - if ($self->git->{mode} =~ m/^sh/) { - $self->git->{mode} = 'shallow'; - } elsif ($self->git->{mode} =~ m/^fu/) { - $self->git->{mode} = 'full'; + # If PGP used, check required programs and generate files + if (@{ $self->pgpsigurlmangle }) { + my $pgpsigurlmanglestring = join(";", @{ $self->pgpsigurlmangle }); + uscan_debug "\$self->{'pgpmode'}=$self->{'pgpmode'}, " + . "\$self->{'pgpsigurlmangle'}=$pgpsigurlmanglestring"; + } else { + uscan_debug "\$self->{'pgpmode'}=$self->{'pgpmode'}, " + . "\$self->{'pgpsigurlmangle'}=undef"; + } + + # Check component for duplication and set $orig to the proper + # extension string + if ($self->pgpmode ne 'previous') { + if ($self->component) { + if (grep { $_ eq $self->component } + @{ $self->shared->{components} }) { + uscan_warn "duplicate component name: $self->{component}"; + return $self->status(1); + } + push @{ $self->shared->{components} }, $self->component; } else { - uscan_warn "Unknown gitmode, defaulting to 'shallow'"; - $self->git->{mode} = 'shallow'; + $self->shared->{origcount}++; + if ($self->shared->{origcount} > 1) { + uscan_warn "more than one main upstream tarballs listed."; + + # reset variables + @{ $self->shared->{components} } = (); + $self->{shared}->{common_newversion} = undef; + $self->{shared}->{common_mangled_newversion} = undef; + $self->{shared}->{previous_newversion} = undef; + $self->{shared}->{previous_newfile_base} = undef; + $self->{shared}->{previous_sigfile_base} = undef; + $self->{shared}->{previous_download_available} = undef; + $self->{shared}->{uscanlog} = undef; + } } + } - # Handle sf.net addresses specially - if (!$self->shared->{bare} and $base =~ m%^https?://sf\.net/%) { - uscan_verbose "sf.net redirection to qa.debian.org/watch/sf.php"; - $base =~ s%^https?://sf\.net/%https://qa.debian.org/watch/sf.php/%; - $filepattern .= '(?:\?.*)?'; - } + # Allow 2 char shorthands for opts="gitmode=..." and check + if ($self->git->{mode} =~ m/^sh/) { + $self->git->{mode} = 'shallow'; + } elsif ($self->git->{mode} =~ m/^fu/) { + $self->git->{mode} = 'full'; + } else { + uscan_warn "Unknown gitmode, defaulting to 'shallow'"; + $self->git->{mode} = 'shallow'; + } - # Handle pypi.python.org addresses specially - if ( !$self->shared->{bare} - and $base =~ m%^https?://pypi\.python\.org/packages/source/%) { - uscan_verbose "pypi.python.org redirection to pypi.debian.net"; - $base - =~ s%^https?://pypi\.python\.org/packages/source/./%https://pypi.debian.net/%; - } + # Handle sf.net addresses specially + if (!$self->shared->{bare} and $base =~ m%^https?://sf\.net/%) { + uscan_verbose "sf.net redirection to qa.debian.org/watch/sf.php"; + $base =~ s%^https?://sf\.net/%https://qa.debian.org/watch/sf.php/%; + $filepattern .= '(?:\?.*)?'; + } - # Handle pkg-ruby-extras gemwatch addresses specially - if ($base - =~ m%^https?://pkg-ruby-extras\.alioth\.debian\.org/cgi-bin/gemwatch% - ) { - uscan_warn -"redirecting DEPRECATED pkg-ruby-extras.alioth.debian.org/cgi-bin/gemwatch" - . " to gemwatch.debian.net"; - $base - =~ s%^https?://pkg-ruby-extras\.alioth\.debian\.org/cgi-bin/gemwatch%https://gemwatch.debian.net%; - } + # Handle pypi.python.org addresses specially + if ( !$self->shared->{bare} + and $base =~ m%^https?://pypi\.python\.org/packages/source/%) { + uscan_verbose "pypi.python.org redirection to pypi.debian.net"; + $base + =~ s%^https?://pypi\.python\.org/packages/source/./%https://pypi.debian.net/%; + } + # Handle pkg-ruby-extras gemwatch addresses specially + if ($base + =~ m%^https?://pkg-ruby-extras\.alioth\.debian\.org/cgi-bin/gemwatch%) + { + uscan_warn +"redirecting DEPRECATED pkg-ruby-extras.alioth.debian.org/cgi-bin/gemwatch" + . " to gemwatch.debian.net"; + $base + =~ s%^https?://pkg-ruby-extras\.alioth\.debian\.org/cgi-bin/gemwatch%https://gemwatch.debian.net%; } if ($self->ctype) { @@ -803,9 +700,8 @@ EOF my $mangled_lastversion = $lastversion; if ( mangle( - $watchfile, \$self->line, - 'dversionmangle:', \@{ $self->dversionmangle }, - \$mangled_lastversion + $watchfile, 'dversionmangle:', + \@{ $self->dversionmangle }, \$mangled_lastversion ) ) { return $self->status(1); @@ -815,22 +711,12 @@ EOF if ($self->versionmode eq 'ignore' and $self->config->download_version) { uscan_verbose 'Ignore --download_version for component with "ignore"'; } elsif ($self->config->download_version) { - my $mangled_downloadversion = $self->config->download_version; - if ( - mangle( - $watchfile, \$self->line, - 'uversionmangle:', \@{ $self->uversionmangle }, - \$mangled_downloadversion - ) - ) { - return $self->status(1); - } - $self->shared->{download_version} = $mangled_downloadversion; + $self->shared->{download_version} = $self->config->download_version; $self->shared->{download} = 2 if $self->shared->{download} == 1; # Change default 1 -> 2 $self->badversion(1); uscan_verbose "Download the --download-version specified version: " - . "(uversionmangled): $self->{shared}->{download_version}"; + . "$self->{shared}->{download_version}"; } elsif ($self->config->download_debversion) { $self->shared->{download_version} = $mangled_lastversion; $self->shared->{download} = 2 @@ -851,7 +737,7 @@ EOF uscan_warn "Unable to set versionmode=prev for the line without opts=pgpmode=prev\n" . " in $watchfile, skipping:\n" - . " $self->{line}"; + . " $self->{watchSource}->{source}"; return $self->status(1); } $self->shared->{download_version} = $self->shared->{common_newversion}; @@ -866,11 +752,11 @@ EOF if ($self->shared->{download}) { uscan_warn "Unable to set versionmode=prev for the line without opts=pgpmode=prev\n" - . " in $watchfile, skipping:\n $self->{line}"; + . " in $watchfile, skipping:\n $self->{watchSource}->{source}"; } else { uscan_verbose "Nothing was downloaded before, skipping pgp check"; - uscan_verbose " line " . $self->line; + uscan_verbose " line " . $self->{watchSource}->{source}; } return $self->status(1); } @@ -900,14 +786,14 @@ EOF } else { uscan_warn "Can't determine protocol and site in\n" . " $watchfile, skipping:\n" - . " $self->{line}"; + . " $self->{watchSource}->{source}"; return $self->status(1); } # Find the path with the greatest version number matching the regex $base = recursive_regex_dir($self, $base, - $self->dirversionmangle, $watchfile, \$self->line, + $self->dirversionmangle, $watchfile, $self->shared->{download_version}); if ($base eq '') { return $self->status(1); @@ -984,8 +870,9 @@ It populates B<$self-Esearch_result> hash ref with the following keys: =over -=item B: URL/tag pointing to the file to be downloaded -=item B: version number to be used for the downloaded file +=item B: mangled version number for comparisons +=item B: version number to be used for the downloaded file +=item B: URL/tag pointing to the file to be downloaded =back @@ -994,19 +881,22 @@ It populates B<$self-Esearch_result> hash ref with the following keys: sub search { my ($self) = @_; uscan_debug "line: search()"; - my ($newversion, $newfile) = $self->_do('search'); - unless ($newversion and $newfile) { + my ($mangled_newversion, $newversion, $newfile) = $self->_do('search'); + unless ($mangled_newversion and $newversion and $newfile) { return $self->status(1); } $self->status and return $self->status; - uscan_verbose "Looking at \$base = $self->{parse_result}->{base} with\n" - . " \$filepattern = $self->{parse_result}->{filepattern} found\n" - . " \$newfile = $newfile\n" - . " \$newversion = $newversion\n" - . " \$lastversion = $self->{parse_result}->{mangled_lastversion}"; + uscan_verbose + "Looking at \$base = $self->{parse_result}->{base} with\n" + . " \$filepattern = $self->{parse_result}->{filepattern} found\n" + . " \$newfile = $newfile\n" + . " \$mangled_newversion = $mangled_newversion\n" + . " \$newversion = $newversion\n" + . " \$lastversion = $self->{parse_result}->{mangled_lastversion}"; $self->search_result({ - newversion => $newversion, - newfile => $newfile, + mangled_newversion => $mangled_newversion, + newversion => $newversion, + newfile => $newfile, }); # The original version of the code didn't use (...) in the watch @@ -1017,13 +907,13 @@ sub search { if ($self->style eq 'old') { # Old-style heuristics - if ($newversion =~ /^\D*(\d+\.(?:\d+\.)*\d+)\D*$/) { - $self->search_result->{newversion} = $1; + if ($mangled_newversion =~ /^\D*(\d+\.(?:\d+\.)*\d+)\D*$/) { + $self->search_result->{mangled_newversion} = $1; } else { uscan_warn <<"EOF"; $progname warning: In $self->{watchfile}, couldn\'t determine a pure numeric version number from the file name for watch line - $self->{line} + $self->{watchSource}->{source} and file name $newfile Please use a new style watch file instead! EOF @@ -1136,7 +1026,7 @@ sub cmp_versions { my $mangled_ver = Dpkg::Version->new("1:${mangled_lastversion}-0", check => 0); my $upstream_ver - = Dpkg::Version->new("1:$self->{search_result}->{newversion}-0", + = Dpkg::Version->new("1:$self->{search_result}->{mangled_newversion}-0", check => 0); my $compver; if ($mangled_ver == $upstream_ver) { @@ -1156,11 +1046,11 @@ sub cmp_versions { . "$self->{search_result}->{newversion}, " . "specified download version is $self->{shared}->{download_version}"; $found++ unless ($self->versionmode =~ /(?:same|ignore)/); - } elsif ($self->versionmode eq 'newer') { + } elsif ($self->versionmode =~ /(?:newer|group|checksum$)/) { if ($compver eq 'newer') { uscan_msg "Newest version of $name on remote site is " . "$self->{search_result}->{newversion}, " - . "local version is $self->{parse_result}->{mangled_lastversion}\n" + . "local version is $self->{parse_result}->{lastversion}\n" . ( $mangled_lastversion eq $self->parse_result->{lastversion} ? "" @@ -1176,7 +1066,7 @@ sub cmp_versions { } elsif ($compver eq 'same') { uscan_verbose "Newest version of $name on remote site is " . $self->search_result->{newversion} - . ", local version is $self->{parse_result}->{mangled_lastversion}\n" + . ", local version is $self->{parse_result}->{lastversion}\n" . ( $mangled_lastversion eq $self->parse_result->{lastversion} ? "" @@ -1197,7 +1087,7 @@ sub cmp_versions { } else { # $compver eq 'old' uscan_verbose "Newest version of $name on remote site is " . $self->search_result->{newversion} - . ", local version is $self->{parse_result}->{mangled_lastversion}\n" + . ", local version is $self->{parse_result}->{lastversion}\n" . ( $mangled_lastversion eq $self->parse_result->{lastversion} ? "" @@ -1233,7 +1123,7 @@ Download file and, if available and needed, signature files. =cut -my %already_downloaded; +our %already_downloaded; sub download_file_and_sig { my ($self) = @_; @@ -1437,9 +1327,8 @@ sub download_file_and_sig { $pgpsig_url = $self->upstream_url; if ( mangle( - $self->watchfile, \$self->line, - 'pgpsigurlmangle:', \@{ $self->pgpsigurlmangle }, - \$pgpsig_url + $self->watchfile, 'pgpsigurlmangle:', + \@{ $self->pgpsigurlmangle }, \$pgpsig_url ) ) { return $self->status(1); @@ -1572,12 +1461,11 @@ sub download_file_and_sig { uscan_warn "strange ... unknown pgpmode = $self->{pgpmode}"; return $self->status(1); } - my $mangled_newversion = $self->search_result->{newversion}; + my $mangled_newversion = $self->search_result->{mangled_newversion}; if ( mangle( - $self->watchfile, \$self->line, - 'oversionmangle:', \@{ $self->oversionmangle }, - \$mangled_newversion + $self->watchfile, 'oversionmangle:', + \@{ $self->oversionmangle }, \$mangled_newversion ) ) { return $self->status(1); @@ -1848,6 +1736,19 @@ sub _do { return $self->$sub; } +sub setBooleanValue { + my ($self, $key, $value) = @_; + $self->$key(_booleanVal($value, $key)); +} + +sub _booleanVal { + uscan_warn 'Option ' + . ucfirst($_[1] // 'Unkwown') + . " should be yes or no, not '$_[0]'. Set it to 'no'" + if $_[0] !~ /^(?:1|0|yes|no)$/i; + return $_[0] =~ /^(?:1|yes)$/ ? 1 : 0; +} + 1; =head1 SEE ALSO diff --git a/lib/Devscripts/Uscan/WatchSource/Parser.pm b/lib/Devscripts/Uscan/WatchSource/Parser.pm new file mode 100644 index 0000000..01485df --- /dev/null +++ b/lib/Devscripts/Uscan/WatchSource/Parser.pm @@ -0,0 +1,66 @@ +package Devscripts::Uscan::WatchSource::Parser; + +use Moo::Role; +use Devscripts::Uscan::Output; + +sub parseWatchFile { + my ($self, $watchFileHandle, $args) = @_; + # Read in paragraph mode + local $/ = ""; + my $map = sub { + return map { + my @lines = split /\n/, $_; + my @res; + foreach my $line (@lines) { + # Skip comments and blank lines + next if $line =~ /^\s*(?:#.*)$/; + unless ($line =~ /^([\w\-]+)\s*:\s*(.*?)\s*$/) { + die "Unable to parse line '$line', skipping"; + } + my ($k, $v) = (lc($1), $2); + $k =~ s/-//g; + push @res, $k, $v; + } + push @res, _raw => $_; + return {@res}; + } @_; + }; + $self->commonOpts($map->($watchFileHandle->getline)); + unless (%{ $self->commonOpts }) { + die "Unable to parse $args->{watchfile} empty header"; + } + unless ($self->commonOpts->{version}) { + die 'Missing "Version" field in header, skipping ' + . $args->{watchfile}; + } + unless ($self->commonOpts->{version} >= 5) { + die +"Malformed file $args->{watchfile}, version $self->{commonOpts}->{version} is lower than 5"; + } + if ($self->commonOpts->{version} + > $Devscripts::Uscan::Config::CURRENT_WATCHFILE_VERSION) { + die +"$args->{watchfile} uses a newer version ($self->{commonOpts}->{version}) than supported (" + . $Devscripts::Uscan::Config::CURRENT_WATCHFILE_VERSION + . '), skipping this file'; + } + $self->watch_version($self->commonOpts->{version}); + my $line; + while (defined($line = $watchFileHandle->getline)) { + my $watchOptions = $map->($line); + unless ($watchOptions->{source} || $watchOptions->{template}) { + uscan_warn +"The following paragraph isn't well formatted, skipping it: << ==EOF==\n" + . $watchOptions->{_raw} + . "==EOF==\n"; + next; + } + foreach my $k (keys %{ $self->commonOpts }) { + $watchOptions->{$k} //= $self->commonOpts->{$k}; + } + + push @{ $self->watchOptions }, $watchOptions; + } +} + +1; diff --git a/lib/Devscripts/Uscan/WatchSource/Transform.pm b/lib/Devscripts/Uscan/WatchSource/Transform.pm new file mode 100644 index 0000000..6ffe73d --- /dev/null +++ b/lib/Devscripts/Uscan/WatchSource/Transform.pm @@ -0,0 +1,135 @@ +package Devscripts::Uscan::WatchSource::Transform; + +use Moo::Role; +use Devscripts::Uscan::Output; + +use constant { + ANY_VERSION => '(?:[-_]?[Vv]?(\d[\-+\.:\~\da-zA-Z]*))', + STABLE_VERSION => '(?:[-_]?[Vv]?((?:[1-9]\d*)(?:\.\d+){2}))', + # From semver.org + SEMANTIC_VERSION => +'(?:[-_]?[Vv]?((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?:[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?))', + ARCHIVE_EXT => + '(?i)(?:\.(?:tar\.xz|tar\.bz2|tar\.gz|tar\.zstd?|zip|tgz|tbz|txz))', + DEB_EXT => '(?:[\+~](debian|dfsg|ds|deb)(\.)?(\d+)?$)', + + ALIASES => { + versionregex => 'matchingpattern', + versionpattern => 'matchingpattern', + }, +}; +use constant SIGNATURE_EXT => ARCHIVE_EXT . '(?:\.(?:asc|pgp|gpg|sig|sign))'; + +sub transformWatchSource { + my ($self, $args) = @_; + + foreach my $watchSource (@{ $self->watchOptions }) { + + foreach my $alias (keys %{&ALIASES}) { + if (defined $watchSource->{$alias}) { + my $nk = ALIASES->{$alias}; + if (defined $watchSource->{$nk}) { + uscan_die "Key $nk is declared and its alias $nk too"; + return; + } + $watchSource->{$nk} = delete $watchSource->{$alias}; + } + } + + my $templates; + while ($watchSource->{template}) { + if ($watchSource->{template} !~ /^\w+$/) { + uscan_die qq'Malformed template "$watchSource->{template}"'; + return; + } + $watchSource->{template} = ucfirst(lc $watchSource->{template}); + my $pkg = "Devscripts::Uscan::Templates::$watchSource->{template}"; + $templates->{current} = $watchSource->{template}; + eval "require $pkg"; + if ($@) { + uscan_die qq'Unknown template "$watchSource->{template}": $@'; + } + my $transform = eval "$pkg->can('transform')"; + if (!$transform) { + uscan_die +qq'Template "$watchSource->{template}" has no transform function'; + return; + } + my $tmp = eval { $transform->($watchSource) }; + if ($@) { + uscan_die "$pkg failed: $@"; + return; + } + unless ($tmp) { + uscan_die "$pkg didn't return a watchsource"; + return; + } + $watchSource = $tmp; + if ( $watchSource->{template} + and $templates->{current} eq $watchSource->{template}) { + uscan_debug "$pkg missed to delete template field"; + delete $watchSource->{template}; + last; + } + if ($watchSource->{template}) { + $watchSource->{template} + = ucfirst(lc $watchSource->{template}); + if ($templates->{ $watchSource->{template} }) { + uscan_die +"Template look detected ($watchSource->{template} recalled)"; + return; + } + $templates->{ $watchSource->{template} }++; + } + } + + foreach my $k (keys %$watchSource) { + # Handle @FOO@ substitutions + $watchSource->{$k} =~ s/\@PACKAGE\@/$args->{package}/g; + $watchSource->{$k} =~ s/\@ANY_VERSION\@/ANY_VERSION/ge; + $watchSource->{$k} =~ s/\@STABLE_VERSION\@/STABLE_VERSION/ge; + $watchSource->{$k} =~ s/\@SEMANTIC_VERSION\@/SEMANTIC_VERSION/ge; + $watchSource->{$k} =~ s/\@ARCHIVE_EXT\@/ARCHIVE_EXT/ge; + $watchSource->{$k} =~ s/\@SIGNATURE_EXT\@/SIGNATURE_EXT/ge; + $watchSource->{$k} =~ s/\@DEB_EXT\@/DEB_EXT/ge; + $watchSource->{$k} =~ s/\@COMPONENT\@/$watchSource->{component}/g; + + if ($watchSource->{$k} eq 'auto') { + # dversionmangle=auto is replaced by s/@DEB_EXT@// + if ($k eq 'dversionmangle') { + $watchSource->{$k} = 's/' . DEB_EXT . '//'; + } + # filenamemangle=auto is replaced by + # s/.*?(@ANY_VERSION@@ARCHIVE_EXT@)/@PACKAGE@-$1/ + # But @PACKAGE@ is replaced by @PACKAGE@-@COMPONENT@ when + # watch source is a component + elsif ($k eq 'filenamemangle') { + $watchSource->{$k} + = 's/.*?[-_]*(' + . ANY_VERSION + . ARCHIVE_EXT . ')/' + . $args->{package} + . ( + $watchSource->{component} + ? '-' . $watchSource->{component} + : '' + ) . '-$1/'; + } elsif ($k eq 'uversionmangle') { + $watchSource->{$k} + = 's/(\d)[_\.\-\+]?((?:RC|rc|pre|dev|beta|alpha)\d*)$/$1~$2/'; + } + } + } + + # When global "Version-Schema" is "checksum", the main watch source has + # to be "group" + if ( $watchSource->{versionschema} + and $watchSource->{versionschema} eq 'checksum' + and !$watchSource->{component}) { + $watchSource->{versionschema} = 'group'; + } + } + return 1; +} + +1; diff --git a/lib/Devscripts/Uscan/_vcs.pm b/lib/Devscripts/Uscan/_vcs.pm index 88ed166..1b33e86 100644 --- a/lib/Devscripts/Uscan/_vcs.pm +++ b/lib/Devscripts/Uscan/_vcs.pm @@ -18,13 +18,44 @@ sub _vcs_newfile_base { if (!$self->config->{vcs_export_uncompressed}) { $newfile_base .= '.' . get_suffix($self->compression); } + if (@{ $self->filenamemangle }) { + my $cmp = $newfile_base; + uscan_verbose "Matching target for filenamemangle: $newfile_base"; + if ( + mangle( + $self->watchfile, 'filenamemangle:', + \@{ $self->filenamemangle }, \$newfile_base + ) + ) { + $self->status(1); + return undef; + } + if ($cmp eq $newfile_base) { + uscan_die "filenamemangle failed for $cmp"; + } + if ($self->versionless) { + # set version from filenamemangling result + $newfile_base + =~ m/^.+?[-_]?(\d[\-+\.:\~\da-zA-Z]*)(?:\.tar(\..*)?)$/i; + $self->search_result->{newversion} + = $self->search_result->{mangled_newversion} = $1; + unless ($self->search_result->{mangled_newversion}) { + uscan_warn +"Fix filenamemangle to produce a filename with the correct version"; + $self->status(1); + return undef; + } + uscan_verbose +"Newest upstream tarball version from the filenamemangled filename: $self->{search_result}->{newversion}"; + } + } return $newfile_base; } sub get_refs { my ($self, $command, $ref_pattern, $package) = @_; my @command = @$command; - my ($newfile, $newversion); + my ($newfile, $newversion, $mangled_newversion); { local $, = ' '; uscan_verbose "Execute: @command"; @@ -34,24 +65,24 @@ sub get_refs { my @refs; my $ref; my $version; + my $mangled_version; while () { chomp; uscan_debug "$_"; if ($_ =~ $ref_pattern) { $ref = $1; foreach my $_pattern (@{ $self->patterns }) { - $version = join(".", + $mangled_version = $version = join(".", map { $_ if defined($_) } $ref =~ m&^$_pattern$&); if ( mangle( - $self->watchfile, \$self->line, - 'uversionmangle:', \@{ $self->uversionmangle }, - \$version + $self->watchfile, 'uversionmangle:', + \@{ $self->uversionmangle }, \$mangled_version ) ) { return undef; } - push @refs, [$version, $ref]; + push @refs, [$mangled_version, $version, $ref]; } } } @@ -59,7 +90,7 @@ sub get_refs { @refs = Devscripts::Versort::upstream_versort(@refs); my $msg = "Found the following matching refs:\n"; foreach my $ref (@refs) { - $msg .= " $$ref[1] ($$ref[0])\n"; + $msg .= " $$ref[2] ($$ref[0])\n"; } uscan_verbose "$msg"; if ($self->shared->{download_version} @@ -67,9 +98,9 @@ sub get_refs { # extract ones which has $version in the above loop matched with $download_version my @vrefs - = grep { $$_[0] eq $self->shared->{download_version} } @refs; + = grep { $$_[1] eq $self->shared->{download_version} } @refs; if (@vrefs) { - ($newversion, $newfile) = @{ $vrefs[0] }; + ($mangled_newversion, $newversion, $newfile) = @{ $vrefs[0] }; } else { uscan_warn "$progname warning: In $self->{watchfile} no matching" @@ -81,7 +112,7 @@ sub get_refs { } } else { - ($newversion, $newfile) = @{ $refs[0] }; + ($mangled_newversion, $newversion, $newfile) = @{ $refs[0] }; } } else { uscan_warn "$progname warning: In $self->{watchfile},\n" @@ -89,7 +120,7 @@ sub get_refs { . " $self->{line}"; return undef; } - return ($newversion, $newfile); + return ($mangled_newversion, $newversion, $newfile); } 1; diff --git a/lib/Devscripts/Uscan/_xtp.pm b/lib/Devscripts/Uscan/_xtp.pm index 092cb52..1849302 100644 --- a/lib/Devscripts/Uscan/_xtp.pm +++ b/lib/Devscripts/Uscan/_xtp.pm @@ -24,9 +24,8 @@ sub _xtp_newfile_base { uscan_verbose "Matching target for filenamemangle: $newfile_base"; if ( mangle( - $self->watchfile, \$self->line, - 'filenamemangle:', \@{ $self->filenamemangle }, - \$newfile_base + $self->watchfile, 'filenamemangle:', + \@{ $self->filenamemangle }, \$newfile_base ) ) { $self->status(1); @@ -38,13 +37,14 @@ sub _xtp_newfile_base { if ($cmp eq $newfile_base) { uscan_die "filenamemangle failed for $cmp"; } - unless ($self->search_result->{newversion}) { + unless ($self->search_result->{mangled_newversion}) { - # uversionmanglesd version is '', make best effort to set it + # uversionmangled version is '', make best effort to set it $newfile_base =~ m/^.+?[-_]?(\d[\-+\.:\~\da-zA-Z]*)(?:\.tar\.(gz|bz2|xz|zstd?)|\.zip)$/i; - $self->search_result->{newversion} = $1; - unless ($self->search_result->{newversion}) { + $self->search_result->{newversion} + = $self->search_result->{mangled_newversion} = $1; + unless ($self->search_result->{mangled_newversion}) { uscan_warn "Fix filenamemangle to produce a filename with the correct version"; $self->status(1); diff --git a/lib/Devscripts/Uscan/ftp.pm b/lib/Devscripts/Uscan/ftp.pm index 5a24d8a..48da935 100644 --- a/lib/Devscripts/Uscan/ftp.pm +++ b/lib/Devscripts/Uscan/ftp.pm @@ -43,13 +43,13 @@ sub ftp_search { =~ m/(?:<\s*a\s+[^>]*href\s*=\s*\")((?-i)$self->{parse_result}->{pattern})\"/gi ) { my $file = fix_href($1); - my $mangled_version + my $version = join(".", $file =~ m/^$self->{parse_result}->{pattern}$/); + my $mangled_version = $version; if ( mangle( - $self->watchfile, \$self->line, - 'uversionmangle:', \@{ $self->uversionmangle }, - \$mangled_version + $self->watchfile, 'uversionmangle:', + \@{ $self->uversionmangle }, \$mangled_version ) ) { return undef; @@ -57,12 +57,13 @@ sub ftp_search { my $match = ''; if (defined $self->shared->{download_version} and not $self->versionmode eq 'ignore') { - if ($mangled_version eq $self->shared->{download_version}) { + if ($version eq $self->shared->{download_version}) { $match = "matched with the download version"; } } my $priority = $mangled_version . '-' . get_priority($file); - push @files, [$priority, $mangled_version, $file, $match]; + push @files, + [$priority, $mangled_version, $file, $match, $version]; } } else { uscan_verbose "Standard FTP listing."; @@ -77,24 +78,24 @@ sub ftp_search { my $file = $1; my $mangled_version = join(".", $file =~ m/^$self->{parse_result}->{filepattern}$/); + my $version = $mangled_version; if ( mangle( - $self->watchfile, \$self->line, - 'uversionmangle:', \@{ $self->uversionmangle }, - \$mangled_version + $self->watchfile, 'uversionmangle:', + \@{ $self->uversionmangle }, \$mangled_version ) ) { return undef; } my $match = ''; if (defined $self->shared->{download_version}) { - if ($mangled_version eq $self->shared->{download_version}) - { + if ($version eq $self->shared->{download_version}) { $match = "matched with the download version"; } } my $priority = $mangled_version . '-' . get_priority($file); - push @files, [$priority, $mangled_version, $file, $match]; + push @files, + [$priority, $mangled_version, $file, $match, $version]; } } } @@ -107,29 +108,32 @@ sub ftp_search { } uscan_verbose $msg; } - my ($newversion, $newfile); + my ($mangled_newversion, $newversion, $newfile); if (defined $self->shared->{download_version}) { # extract ones which has $match in the above loop defined my @vfiles = grep { $$_[3] } @files; if (@vfiles) { - (undef, $newversion, $newfile, undef) = @{ $vfiles[0] }; + (undef, $mangled_newversion, $newfile, undef, $newversion) + = @{ $vfiles[0] }; } else { uscan_warn "In $self->{watchfile} no matching files for version $self->{shared}->{download_version}" - . " in watch line\n $self->{line}"; + . " in watch line"; return undef; } } else { if (@files) { - (undef, $newversion, $newfile, undef) = @{ $files[0] }; + (undef, $mangled_newversion, $newfile, undef, $newversion) + = @{ $files[0] }; } else { uscan_warn -"In $self->{watchfile} no matching files for watch line\n $self->{line}"; + "In $self->{watchfile} no matching files for watch source\n " + . $self->{watchSource}->{source}; return undef; } } - return ($newversion, $newfile); + return ($mangled_newversion, $newversion, $newfile); } sub ftp_upstream_url { @@ -141,7 +145,7 @@ sub ftp_upstream_url { sub ftp_newdir { my ($line, $site, $dir, $pattern, $dirversionmangle, $watchfile, - $lineptr, $download_version) + $download_version) = @_; my $downloader = $line->downloader; @@ -182,9 +186,8 @@ sub ftp_newdir { my $mangled_version = join(".", $dir =~ m/^$pattern$/); if ( mangle( - $watchfile, $lineptr, - 'dirversionmangle:', \@{$dirversionmangle}, - \$mangled_version + $watchfile, 'dirversionmangle:', + \@{$dirversionmangle}, \$mangled_version ) ) { return 1; @@ -222,9 +225,8 @@ sub ftp_newdir { my $mangled_version = join(".", $dir =~ m/^$pattern$/); if ( mangle( - $watchfile, $lineptr, - 'dirversionmangle:', \@{$dirversionmangle}, - \$mangled_version + $watchfile, 'dirversionmangle:', + \@{$dirversionmangle}, \$mangled_version ) ) { return 1; diff --git a/lib/Devscripts/Uscan/git.pm b/lib/Devscripts/Uscan/git.pm index 9d55ad0..d5d47e9 100644 --- a/lib/Devscripts/Uscan/git.pm +++ b/lib/Devscripts/Uscan/git.pm @@ -1,7 +1,7 @@ package Devscripts::Uscan::git; use strict; -use Cwd qw/abs_path/; +use Cwd qw/abs_path cwd/; use Devscripts::Uscan::Output; use Devscripts::Uscan::Utils; use Devscripts::Uscan::_vcs; @@ -14,68 +14,55 @@ use Moo::Role; ###################################################### sub git_search { my ($self) = @_; - my ($newfile, $newversion); + my ($newfile, $newversion, $mangled_newversion); if ($self->versionless) { $newfile = $self->parse_result->{filepattern}; # HEAD or heads/ + my @args = (); + my $curdir = cwd(); + + push(@args, '--quiet') if not $verbose; + push(@args, '--bare') if not $self->git->{modules}; + if ($self->pretty eq 'describe') { $self->git->{mode} = 'full'; } - if ( $self->git->{mode} eq 'shallow' - and $self->parse_result->{filepattern} eq 'HEAD') { - uscan_exec( - 'git', - 'clone', - '--quiet', - '--bare', - '--depth=1', - $self->parse_result->{base}, - "$self->{downloader}->{destdir}/" . $self->gitrepo_dir - ); - $self->downloader->gitrepo_state(1); - } elsif ($self->git->{mode} eq 'shallow' - and $self->parse_result->{filepattern} ne 'HEAD') - { # heads/ - $newfile =~ s&^heads/&&; # Set to - uscan_exec( - 'git', - 'clone', - '--quiet', - '--bare', - '--depth=1', - '-b', - "$newfile", - $self->parse_result->{base}, - "$self->{downloader}->{destdir}/" . $self->gitrepo_dir - ); + + if ($self->git->{mode} eq 'shallow') { + push(@args, '--depth=1'); $self->downloader->gitrepo_state(1); } else { - uscan_exec( - 'git', 'clone', '--quiet', '--bare', - $self->parse_result->{base}, - "$self->{downloader}->{destdir}/" . $self->gitrepo_dir - ); $self->downloader->gitrepo_state(2); } - if ($self->pretty eq 'describe') { + if ($newfile ne 'HEAD') { + $newfile = s&^heads/&&; # Set to + push(@args, '-b', "$newfile"); + } + + # clone main repository + uscan_exec( + 'git', 'clone', @args, + $self->parse_result->{base}, + "$self->{downloader}->{destdir}/" . $self->gitrepo_dir + ); + + chdir "$self->{downloader}->{destdir}/$self->{gitrepo_dir}"; + + if ($self->pretty eq 'describe') { # use unannotated tags to be on safe side + uscan_debug "git describe --tags"; spawn( - exec => [ - 'git', -"--git-dir=$self->{downloader}->{destdir}/$self->{gitrepo_dir}", - 'describe', - '--tags' - ], + exec => ['git', 'describe', '--tags'], wait_child => 1, to_string => \$newversion ); $newversion =~ s/-/./g; chomp($newversion); + $mangled_newversion = $newversion; if ( mangle( - $self->watchfile, \$self->line, - 'uversionmangle:', \@{ $self->uversionmangle }, - \$newversion + $self->watchfile, 'uversionmangle:', + \@{ $self->uversionmangle }, \$mangled_newversion ) ) { return undef; @@ -83,41 +70,23 @@ sub git_search { } else { my $tmp = $ENV{TZ}; $ENV{TZ} = 'UTC'; - $newfile - = $self->parse_result->{filepattern}; # HEAD or heads/ - if ($self->parse_result->{filepattern} eq 'HEAD') { - spawn( - exec => [ - 'git', -"--git-dir=$self->{downloader}->{destdir}/$self->{gitrepo_dir}", - 'log', - '-1', - "--date=format-local:$self->{date}", - "--pretty=$self->{pretty}" - ], - wait_child => 1, - to_string => \$newversion - ); - } else { - $newfile =~ s&^heads/&&; # Set to - spawn( - exec => [ - 'git', -"--git-dir=$self->{downloader}->{destdir}/$self->{gitrepo_dir}", - 'log', - '-1', - '-b', - "$newfile", - "--date=format-local:$self->{date}", - "--pretty=$self->{pretty}" - ], - wait_child => 1, - to_string => \$newversion - ); - } + @args = ('-1'); + push(@args, '-b', $newfile) if ($newfile ne 'HEAD'); + push(@args, "--date=format-local:$self->{date}"); + push(@args, "--pretty=$self->{pretty}"); + + uscan_debug "git log " . join(' ', @args); + + spawn( + exec => ['git', 'log', @args], + wait_child => 1, + to_string => \$newversion + ); $ENV{TZ} = $tmp; chomp($newversion); + $mangled_newversion = $newversion; } + chdir "$curdir"; } ################################################ # search $newfile $newversion (git mode w/tag) @@ -149,11 +118,11 @@ sub git_search { @args = ('show-ref'); } } - ($newversion, $newfile) + ($mangled_newversion, $newversion, $newfile) = get_refs($self, ['git', @args], qr/^\S+\s+([^\^\{\}]+)$/, 'git'); return undef if !defined $newversion; } - return ($newversion, $newfile); + return ($mangled_newversion, $newversion, $newfile); } sub git_upstream_url { diff --git a/lib/Devscripts/Uscan/http.pm b/lib/Devscripts/Uscan/http.pm index 0da9798..95f8a05 100644 --- a/lib/Devscripts/Uscan/http.pm +++ b/lib/Devscripts/Uscan/http.pm @@ -64,7 +64,7 @@ sub http_search { my $baseUrl = $1; my $hdr = $2; if ($self->parse_result->{base} =~ m#^\Q$baseUrl\E(?:/.*)?$#) { - $request->header($hdr => $self->headers->{$k}); + $request->header($hdr => $self->downloader->headers->{$k}); uscan_verbose "Set per-host custom header $hdr for " . $self->parse_result->{base}; } else { @@ -95,6 +95,16 @@ sub http_search { uscan_extra_debug "received content:\n$content\n[End of received content] by HTTP"; + # pagenmangle: should not abuse this slow operation + if ( + mangle( + $self->watchfile, 'pagemangle:\n', + [@{ $self->pagemangle }], \$content + ) + ) { + return undef; + } + my @hrefs; if (!$self->searchmode or $self->searchmode eq 'html') { @hrefs = $self->html_search($content, $self->patterns); @@ -114,30 +124,33 @@ sub http_search { } uscan_verbose $msg; } - my ($newversion, $newfile); + my ($mangled_newversion, $newversion, $newfile); if (defined $self->shared->{download_version} and not $self->versionmode eq 'ignore') { # extract ones which has $match in the above loop defined my @vhrefs = grep { $$_[3] } @hrefs; if (@vhrefs) { - (undef, $newversion, $newfile, undef) = @{ $vhrefs[0] }; + (undef, $mangled_newversion, $newfile, undef, $newversion) + = @{ $vhrefs[0] }; } else { uscan_warn "In $self->{watchfile} no matching hrefs for version $self->{shared}->{download_version}" - . " in watch line\n $self->{line}"; + . " in watch source\n $self->{watchSource}->{source}"; return undef; } } else { if (@hrefs) { - (undef, $newversion, $newfile, undef) = @{ $hrefs[0] }; + (undef, $mangled_newversion, $newfile, undef, $newversion) + = @{ $hrefs[0] }; } else { uscan_warn -"In $self->{watchfile} no matching files for watch line\n $self->{line}"; + "In $self->{watchfile} no matching files for watch source\n " + . $self->{watchSource}->{source}; return undef; } } - return ($newversion, $newfile); + return ($mangled_newversion, $newversion, $newfile); } ####################################################################### @@ -211,9 +224,8 @@ sub http_upstream_url { if (@{ $self->downloadurlmangle }) { if ( mangle( - $self->watchfile, \$self->line, - 'downloadurlmangle:', \@{ $self->downloadurlmangle }, - \$upstream_url + $self->watchfile, 'downloadurlmangle:', + \@{ $self->downloadurlmangle }, \$upstream_url ) ) { $self->status(1); @@ -225,7 +237,7 @@ sub http_upstream_url { sub http_newdir { my ($https, $line, $site, $dir, $pattern, $dirversionmangle, - $watchfile, $lineptr, $download_version) + $watchfile, $download_version) = @_; my $downloader = $line->downloader; @@ -373,17 +385,6 @@ sub url_canonicalize_dots { sub html_search { my ($self, $content, $patterns, $mangle) = @_; - - # pagenmangle: should not abuse this slow operation - if ( - mangle( - $self->watchfile, \$self->line, - 'pagemangle:\n', [@{ $self->pagemangle }], - \$content - ) - ) { - return undef; - } if ( !$self->shared->{bare} and $content =~ m%^<[?]xml%i and $content =~ m%xmlns="http://s3.amazonaws.com/doc/2006-03-01/"% @@ -464,13 +465,13 @@ sub parse_href { my ($self, $href, $_pattern, $match, $mangle) = @_; $mangle //= 'uversionmangle'; - my $mangled_version; + my ($mangled_version, $version); if ($self->watch_version == 2) { # watch_version 2 only recognised one group; the code # below will break version 2 watch files with a construction # such as file-([\d\.]+(-\d+)?) (bug #327258) - $mangled_version + $version = $mangled_version = ref $match eq 'ARRAY' ? $match->[0] : $match; @@ -486,12 +487,12 @@ sub parse_href { map { $_ if defined($_) } ref $match eq 'ARRAY' ? @$match : $href =~ m&^$_pattern$&); } + $version = $mangled_version; if ( mangle( - $self->watchfile, \$self->line, - "$mangle:", \@{ $self->$mangle }, - \$mangled_version + $self->watchfile, "$mangle:", + \@{ $self->$mangle }, \$mangled_version ) ) { return (); @@ -499,12 +500,12 @@ sub parse_href { } $match = ''; if (defined $self->shared->{download_version}) { - if ($mangled_version eq $self->shared->{download_version}) { + if ($version eq $self->shared->{download_version}) { $match = "matched with the download version"; } } my $priority = $mangled_version . '-' . get_priority($href); - return [$priority, $mangled_version, $href, $match]; + return [$priority, $mangled_version, $href, $match, $version]; } 1; diff --git a/lib/Devscripts/Uscan/metacpan.pm b/lib/Devscripts/Uscan/metacpan.pm new file mode 100644 index 0000000..4b8e085 --- /dev/null +++ b/lib/Devscripts/Uscan/metacpan.pm @@ -0,0 +1,89 @@ +package Devscripts::Uscan::metacpan; + +use strict; +use Devscripts::Uscan::Output; +use Devscripts::Uscan::Utils; +use Devscripts::Uscan::_xtp; +use Moo::Role; +use MetaCPAN::Client; + +sub metacpan_search { + my ($self) = @_; + uscan_verbose "Searching versions of $self->{parse_result}->{base}"; + my $mcpan = MetaCPAN::Client->new; + my $releases = $mcpan->release({ + all => [{ + distribution => $self->{parse_result}->{base} } + ], + fields => [qw(version download_url)] }); + + my (@files); + while (my $release = $releases->next) { + my $mangled_version = $release->version; + my $file = $release->download_url; + if ( + mangle( + $self->watchfile, 'uversionmangle:', + \@{ $self->uversionmangle }, \$mangled_version + ) + ) { + return undef; + } + my $match = ''; + if (defined $self->shared->{download_version} + and not $self->versionmode eq 'ignore') { + if ($mangled_version eq $self->shared->{download_version}) { + $match = "matched with the download version"; + } + } + my $priority = $mangled_version . '-' . get_priority($file); + push @files, + [$priority, $mangled_version, $file, $match, $release->version]; + } + if (@files) { + @files = Devscripts::Versort::versort(@files); + my $msg + = "Found the following matching files on the web page (newest first):\n"; + foreach my $file (@files) { + $msg .= " $$file[2] ($$file[1]) index=$$file[0] $$file[3]\n"; + } + uscan_verbose $msg; + } + my ($mangled_newversion, $newversion, $newfile); + if (defined $self->shared->{download_version}) { + + # extract ones which has $match in the above loop defined + my @vfiles = grep { $$_[3] } @files; + if (@vfiles) { + (undef, $mangled_newversion, $newfile, undef, $newversion) + = @{ $vfiles[0] }; + } else { + uscan_warn +"In $self->{watchfile} no matching files for version $self->{shared}->{download_version}" + . " in watch line"; + return undef; + } + } else { + if (@files) { + (undef, $mangled_newversion, $newfile, undef, $newversion) + = @{ $files[0] }; + } else { + uscan_warn + "In $self->{watchfile} no matching files for watch source\n " + . $self->{watchSource}->{source}; + return undef; + } + } + return ($mangled_newversion, $newversion, $newfile); +} + +sub metacpan_upstream_url { + my ($self) = @_; + return $self->search_result->{newfile}; +} + +*metacpan_newfile_base = \&Devscripts::Uscan::_xtp::_xtp_newfile_base; + +sub metacpan_clean { 0 } + +1; diff --git a/lib/Devscripts/Uscan/svn.pm b/lib/Devscripts/Uscan/svn.pm index 65dacae..05db100 100644 --- a/lib/Devscripts/Uscan/svn.pm +++ b/lib/Devscripts/Uscan/svn.pm @@ -14,7 +14,7 @@ use Moo::Role; ###################################################### sub svn_search { my ($self) = @_; - my ($newfile, $newversion); + my ($newfile, $newversion, $mangled_newversion); if ($self->versionless) { $newfile = $self->parse_result->{base}; spawn( @@ -27,12 +27,11 @@ sub svn_search { to_string => \$newversion ); chomp($newversion); - $newversion = sprintf '0.0~svn%d', $newversion; + $mangled_newversion = $newversion = sprintf '0.0~svn%d', $newversion; if ( mangle( - $self->watchfile, \$self->line, - 'uversionmangle:', \@{ $self->uversionmangle }, - \$newversion + $self->watchfile, 'uversionmangle:', + \@{ $self->uversionmangle }, \$mangled_newversion ) ) { return undef; @@ -44,11 +43,11 @@ sub svn_search { ################################################ elsif ($self->mode eq 'svn') { my @args = ('list', $self->parse_result->{base}); - ($newversion, $newfile) + ($mangled_newversion, $newversion, $newfile) = get_refs($self, ['svn', @args], qr/(.+)/, 'subversion'); - return undef if !defined $newversion; + return undef if !defined $mangled_newversion; } - return ($newversion, $newfile); + return ($mangled_newversion, $newversion, $newfile); } sub svn_upstream_url { diff --git a/po4a/Makefile b/po4a/Makefile index 522dbb2..7d520c8 100644 --- a/po4a/Makefile +++ b/po4a/Makefile @@ -7,11 +7,12 @@ DESC_fr/ = Utilitaires Debian DESC_pt/ = Utilitários Debian GEN_TR_MAN1S := $(sort $(foreach lang,$(LANGS),$(patsubst %.1,$(lang)/%.$(lang).1,$(GEN_MAN1S)))) +GEN_TR_MAN5S := $(sort $(foreach lang,$(LANGS),$(patsubst %.5,$(lang)/%.$(lang).5,$(GEN_MAN5S)))) all: translate # GEN_TR_MAN1S needs translate finished, serialize the calls @$(MAKE) transform -transform: $(GEN_TR_MAN1S) +transform: $(GEN_TR_MAN1S) $(GEN_TR_MAN5S) translate: ../doc/devscripts.7 po4a --previous --no-backups --keep=0 devscripts-po4a.conf @@ -36,3 +37,13 @@ clean: ../doc/devscripts.7 mkdir -p $(LANGS) xsltproc --nonet -o $@ \ /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl $< +%.5:: %.pl translate + -podchecker $< + pod2man --utf8 --center=" " --release="$(DESC_$(dir $@))" $< > $@ +%.5:: %.pod translate + -podchecker $< + pod2man --utf8 --center=" " --release="$(DESC_$(dir $@))" $< > $@ +%.5:: %.dbk translate + mkdir -p $(LANGS) + xsltproc --nonet -o $@ \ + /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl $< diff --git a/po4a/devscripts-po4a.conf b/po4a/devscripts-po4a.conf index 97b8434..9dd6e90 100644 --- a/po4a/devscripts-po4a.conf +++ b/po4a/devscripts-po4a.conf @@ -40,6 +40,10 @@ $lang:$lang/debdiff-apply.$lang.1 add_$lang:?add_$lang/translator_man.add [type:man] ../scripts/debi.1 \ $lang:$lang/debi.$lang.1 add_$lang:?add_$lang/translator_man.add +[type:pod] ../scripts/debian-watch.pod \ + $lang:$lang/debian-watch.$lang.pod add_$lang:?add_$lang/translator_pod.add +[type:pod] ../scripts/debian-watch-4.pod \ + $lang:$lang/debian-watch-4.$lang.pod add_$lang:?add_$lang/translator_pod.add [type:pod] ../scripts/debrepro.pod \ $lang:$lang/debrepro.$lang.pod add_$lang:?add_$lang/translator_pod.add [type:man] ../scripts/debrelease.1 \ @@ -78,8 +82,6 @@ $lang:$lang/dscverify.$lang.1 add_$lang:?add_$lang/translator_man.add [type:man] ../scripts/getbuildlog.1 \ $lang:$lang/getbuildlog.$lang.1 add_$lang:?add_$lang/translator_man.add -[type:pod] ../scripts/git-deborig.pl \ - $lang:$lang/git-deborig.$lang.pl add_$lang:?add_$lang/translator_pod.add [type:man] ../scripts/grep-excuses.1 \ $lang:$lang/grep-excuses.$lang.1 add_$lang:?add_$lang/translator_man.add [type:pod] ../scripts/hardening-check.pl \ diff --git a/po4a/po/de.po b/po4a/po/de.po index ea56d2f..55b0511 100644 --- a/po4a/po/de.po +++ b/po4a/po/de.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: devscripts 2.18.9\n" "Report-Msgid-Bugs-To: devscripts@packages.debian.org\n" -"POT-Creation-Date: 2025-05-19 07:42+0000\n" -"PO-Revision-Date: 2025-05-05 15:21+0200\n" +"POT-Creation-Date: 2025-08-13 20:39+0200\n" +"PO-Revision-Date: 2025-07-25 15:40+0200\n" "Last-Translator: Dorle Osterode \n" "Language-Team: de \n" "Language: de\n" @@ -73,18 +73,18 @@ msgstr "DEBIAN" #: ../scripts/deb2docker.1:3 ../scripts/debc.1:2 ../scripts/debchange.1:2 #: ../scripts/debcheckout.pl:24 ../scripts/debclean.1:2 #: ../scripts/debcommit.pl:3 ../scripts/debdiff.1:2 -#: ../scripts/debdiff-apply.1:17 ../scripts/debi.1:2 ../scripts/debrepro.pod:1 -#: ../scripts/debrelease.1:2 ../scripts/deb-why-removed.pl:196 -#: ../scripts/debrsign.1:2 ../scripts/debsign.1:2 ../scripts/debsnap.1:3 -#: ../scripts/debuild.1:2 ../scripts/dep3changelog.1:2 -#: ../scripts/dep-14-convert-git-branch-names.1:2 ../doc/devscripts.7:2 -#: ../scripts/dget.pl:572 ../scripts/diff2patches.1:2 +#: ../scripts/debdiff-apply.1:17 ../scripts/debi.1:2 +#: ../scripts/debian-watch.pod:3 ../scripts/debian-watch-4.pod:3 +#: ../scripts/debrepro.pod:1 ../scripts/debrelease.1:2 +#: ../scripts/deb-why-removed.pl:196 ../scripts/debrsign.1:2 +#: ../scripts/debsign.1:2 ../scripts/debsnap.1:3 ../scripts/debuild.1:2 +#: ../scripts/dep3changelog.1:2 ../scripts/dep-14-convert-git-branch-names.1:2 +#: ../doc/devscripts.7:2 ../scripts/dget.pl:572 ../scripts/diff2patches.1:2 #: ../scripts/dpkg-depcheck.1:2 ../scripts/dpkg-genbuilddeps.1:2 #: ../doc/edit-patch.1:2 ../scripts/dscextract.1:2 ../scripts/dscverify.1:2 -#: ../scripts/getbuildlog.1:2 ../scripts/git-deborig.pl:20 -#: ../scripts/grep-excuses.1:2 ../scripts/hardening-check.pl:532 -#: ../scripts/list-unreleased.1:2 ../scripts/ltnu.pod:1 -#: ../scripts/manpage-alert.1:2 ../scripts/mass-bug.pl:21 +#: ../scripts/getbuildlog.1:2 ../scripts/grep-excuses.1:2 +#: ../scripts/hardening-check.pl:532 ../scripts/list-unreleased.1:2 +#: ../scripts/ltnu.pod:1 ../scripts/manpage-alert.1:2 ../scripts/mass-bug.pl:21 #: ../scripts/mergechanges.1:2 ../scripts/mk-build-deps.pl:24 #: ../scripts/mk-origtargz.pl:25 ../scripts/namecheck.pl:3 #: ../scripts/nmudiff.1:2 ../scripts/origtargz.pl:20 @@ -121,10 +121,9 @@ msgstr "annotate-output - versieht Programmausgaben mit Zeit und Datenstrom" #: ../scripts/dep-14-convert-git-branch-names.1:30 ../scripts/dget.pl:576 #: ../scripts/dpkg-depcheck.1:4 ../scripts/dpkg-genbuilddeps.1:4 #: ../doc/edit-patch.1:6 ../scripts/dscextract.1:4 ../scripts/dscverify.1:4 -#: ../scripts/getbuildlog.1:4 ../scripts/git-deborig.pl:24 -#: ../scripts/grep-excuses.1:4 ../scripts/hardening-check.pl:536 -#: ../scripts/list-unreleased.1:4 ../scripts/ltnu.pod:5 -#: ../scripts/manpage-alert.1:4 ../scripts/mass-bug.pl:25 +#: ../scripts/getbuildlog.1:4 ../scripts/grep-excuses.1:4 +#: ../scripts/hardening-check.pl:536 ../scripts/list-unreleased.1:4 +#: ../scripts/ltnu.pod:5 ../scripts/manpage-alert.1:4 ../scripts/mass-bug.pl:25 #: ../scripts/mergechanges.1:4 ../scripts/mk-build-deps.pl:28 #: ../scripts/mk-origtargz.pl:29 ../scripts/nmudiff.1:4 #: ../scripts/origtargz.pl:24 ../scripts/plotchangelog.1:4 @@ -153,30 +152,31 @@ msgstr "B [I …] I [I …]" #: ../scripts/deb2docker.1:10 ../scripts/debc.1:6 ../scripts/debchange.1:8 #: ../scripts/debcheckout.pl:40 ../scripts/debclean.1:6 #: ../scripts/debcommit.pl:11 ../scripts/debdiff.1:15 -#: ../scripts/debdiff-apply.1:27 ../scripts/debi.1:6 ../scripts/debrepro.pod:9 -#: ../scripts/debrelease.1:6 ../scripts/deb-reversion.dbk:82 -#: ../scripts/deb-why-removed.pl:204 ../scripts/debrsign.1:7 -#: ../scripts/debsign.1:6 ../scripts/debsnap.1:14 ../scripts/debuild.1:10 -#: ../scripts/dep3changelog.1:6 ../scripts/dep-14-convert-git-branch-names.1:4 -#: ../doc/devscripts.7:4 ../scripts/dget.pl:586 ../scripts/diff2patches.1:10 +#: ../scripts/debdiff-apply.1:27 ../scripts/debi.1:6 +#: ../scripts/debian-watch.pod:7 ../scripts/debian-watch-4.pod:7 +#: ../scripts/debrepro.pod:9 ../scripts/debrelease.1:6 +#: ../scripts/deb-reversion.dbk:82 ../scripts/deb-why-removed.pl:204 +#: ../scripts/debrsign.1:7 ../scripts/debsign.1:6 ../scripts/debsnap.1:14 +#: ../scripts/debuild.1:10 ../scripts/dep3changelog.1:6 +#: ../scripts/dep-14-convert-git-branch-names.1:4 ../doc/devscripts.7:4 +#: ../scripts/dget.pl:586 ../scripts/diff2patches.1:10 #: ../scripts/dpkg-depcheck.1:6 ../scripts/dpkg-genbuilddeps.1:6 #: ../doc/edit-patch.1:11 ../scripts/dscextract.1:6 ../scripts/dscverify.1:6 -#: ../scripts/getbuildlog.1:8 ../scripts/git-deborig.pl:28 -#: ../scripts/grep-excuses.1:6 ../scripts/hardening-check.pl:543 -#: ../scripts/list-unreleased.1:6 ../scripts/ltnu.pod:13 -#: ../scripts/manpage-alert.1:6 ../scripts/mass-bug.pl:29 -#: ../scripts/mergechanges.1:6 ../scripts/mk-build-deps.pl:34 -#: ../scripts/mk-origtargz.pl:39 ../scripts/nmudiff.1:6 -#: ../scripts/origtargz.pl:34 ../scripts/plotchangelog.1:7 -#: ../scripts/pts-subscribe.1:8 ../scripts/rc-alert.1:8 -#: ../scripts/rmadison.pl:273 ../scripts/sadt.pod:25 ../scripts/salsa.pl:28 -#: ../doc/suspicious-source.1:24 ../scripts/svnpath.pl:17 -#: ../scripts/tagpending.pl:88 ../scripts/transition-check.pl:33 -#: ../scripts/uscan.pl:42 ../scripts/uupdate.1:10 ../doc/what-patch.1:8 -#: ../scripts/whodepends.1:6 ../scripts/who-uploads.1:6 -#: ../scripts/who-permits-upload.pl:56 ../scripts/wnpp-alert.1:8 -#: ../scripts/wnpp-check.1:8 ../doc/wrap-and-sort.1:22 -#: ../doc/devscripts.conf.5:4 +#: ../scripts/getbuildlog.1:8 ../scripts/grep-excuses.1:6 +#: ../scripts/hardening-check.pl:543 ../scripts/list-unreleased.1:6 +#: ../scripts/ltnu.pod:13 ../scripts/manpage-alert.1:6 +#: ../scripts/mass-bug.pl:29 ../scripts/mergechanges.1:6 +#: ../scripts/mk-build-deps.pl:34 ../scripts/mk-origtargz.pl:39 +#: ../scripts/nmudiff.1:6 ../scripts/origtargz.pl:34 +#: ../scripts/plotchangelog.1:7 ../scripts/pts-subscribe.1:8 +#: ../scripts/rc-alert.1:8 ../scripts/rmadison.pl:273 ../scripts/sadt.pod:25 +#: ../scripts/salsa.pl:31 ../doc/suspicious-source.1:24 +#: ../scripts/svnpath.pl:17 ../scripts/tagpending.pl:88 +#: ../scripts/transition-check.pl:33 ../scripts/uscan.pl:42 +#: ../scripts/uupdate.1:10 ../doc/what-patch.1:8 ../scripts/whodepends.1:6 +#: ../scripts/who-uploads.1:6 ../scripts/who-permits-upload.pl:56 +#: ../scripts/wnpp-alert.1:8 ../scripts/wnpp-check.1:8 +#: ../doc/wrap-and-sort.1:22 ../doc/devscripts.conf.5:4 #, no-wrap msgid "DESCRIPTION" msgstr "BESCHREIBUNG" @@ -219,17 +219,16 @@ msgstr "" #: ../scripts/dget.pl:630 ../scripts/diff2patches.1:16 #: ../scripts/dpkg-depcheck.1:15 ../scripts/dscextract.1:14 #: ../scripts/dscverify.1:18 ../scripts/getbuildlog.1:24 -#: ../scripts/git-deborig.pl:47 ../scripts/grep-excuses.1:14 -#: ../scripts/hardening-check.pl:613 ../scripts/list-unreleased.1:12 -#: ../scripts/ltnu.pod:27 ../scripts/manpage-alert.1:12 -#: ../scripts/mass-bug.pl:63 ../scripts/mk-build-deps.pl:44 -#: ../scripts/mk-origtargz.pl:63 ../scripts/nmudiff.1:24 -#: ../scripts/origtargz.pl:100 ../scripts/plotchangelog.1:43 -#: ../scripts/pts-subscribe.1:18 ../scripts/rc-alert.1:17 -#: ../scripts/rmadison.pl:282 ../scripts/sadt.pod:42 ../scripts/salsa.pl:437 -#: ../doc/suspicious-source.1:34 ../scripts/tagpending.pl:94 -#: ../scripts/transition-check.pl:42 ../scripts/uupdate.1:54 -#: ../doc/what-patch.1:15 ../scripts/whodepends.1:10 +#: ../scripts/grep-excuses.1:14 ../scripts/hardening-check.pl:613 +#: ../scripts/list-unreleased.1:12 ../scripts/ltnu.pod:27 +#: ../scripts/manpage-alert.1:12 ../scripts/mass-bug.pl:63 +#: ../scripts/mk-build-deps.pl:44 ../scripts/mk-origtargz.pl:63 +#: ../scripts/nmudiff.1:24 ../scripts/origtargz.pl:100 +#: ../scripts/plotchangelog.1:43 ../scripts/pts-subscribe.1:18 +#: ../scripts/rc-alert.1:17 ../scripts/rmadison.pl:282 ../scripts/sadt.pod:42 +#: ../scripts/salsa.pl:453 ../doc/suspicious-source.1:34 +#: ../scripts/tagpending.pl:94 ../scripts/transition-check.pl:42 +#: ../scripts/uupdate.1:54 ../doc/what-patch.1:15 ../scripts/whodepends.1:10 #: ../scripts/who-uploads.1:15 ../scripts/who-permits-upload.pl:62 #: ../scripts/wnpp-alert.1:17 ../scripts/wnpp-check.1:16 #: ../doc/wrap-and-sort.1:35 @@ -316,7 +315,7 @@ msgstr "Zeigt eine Hilfenachricht." #. type: SH #: ../scripts/annotate-output.1:39 ../scripts/debrepro.pod:144 #: ../scripts/debsnap.1:102 ../scripts/dscextract.1:20 -#: ../scripts/transition-check.pl:54 ../scripts/uscan.pl:2024 +#: ../scripts/transition-check.pl:54 ../scripts/uscan.pl:646 #: ../scripts/wnpp-check.1:28 #, no-wrap msgid "EXIT STATUS" @@ -523,6 +522,7 @@ msgstr "" #: ../scripts/debcheckout.pl:231 ../scripts/debclean.1:110 #: ../scripts/debcommit.pl:972 ../scripts/debdiff.1:251 #: ../scripts/debdiff-apply.1:111 ../scripts/debi.1:131 +#: ../scripts/debian-watch.pod:1538 ../scripts/debian-watch-4.pod:1409 #: ../scripts/debrepro.pod:171 ../scripts/debrelease.1:132 #: ../scripts/deb-reversion.dbk:247 ../scripts/deb-why-removed.pl:247 #: ../scripts/debrsign.1:66 ../scripts/debsign.1:132 ../scripts/debsnap.1:138 @@ -530,14 +530,14 @@ msgstr "" #: ../scripts/dep-14-convert-git-branch-names.1:48 ../scripts/dget.pl:763 #: ../scripts/diff2patches.1:45 ../scripts/dpkg-depcheck.1:118 #: ../scripts/dpkg-genbuilddeps.1:30 ../scripts/dscverify.1:81 -#: ../scripts/git-deborig.pl:79 ../scripts/grep-excuses.1:61 -#: ../scripts/hardening-check.pl:704 ../scripts/list-unreleased.1:19 -#: ../scripts/ltnu.pod:105 ../scripts/mk-origtargz.pl:209 -#: ../scripts/nmudiff.1:127 ../scripts/origtargz.pl:162 -#: ../scripts/plotchangelog.1:124 ../scripts/pts-subscribe.1:51 -#: ../scripts/rc-alert.1:121 ../scripts/rmadison.pl:406 ../scripts/sadt.pod:74 -#: ../scripts/salsa.pl:1094 ../scripts/tagpending.pl:149 -#: ../scripts/uscan.pl:2201 ../scripts/uupdate.1:189 ../doc/what-patch.1:35 +#: ../scripts/grep-excuses.1:61 ../scripts/hardening-check.pl:704 +#: ../scripts/list-unreleased.1:19 ../scripts/ltnu.pod:105 +#: ../scripts/mk-origtargz.pl:214 ../scripts/nmudiff.1:127 +#: ../scripts/origtargz.pl:162 ../scripts/plotchangelog.1:124 +#: ../scripts/pts-subscribe.1:51 ../scripts/rc-alert.1:121 +#: ../scripts/rmadison.pl:406 ../scripts/sadt.pod:74 ../scripts/salsa.pl:1115 +#: ../scripts/tagpending.pl:149 ../scripts/uscan.pl:823 +#: ../scripts/uupdate.1:189 ../doc/what-patch.1:35 #: ../scripts/who-permits-upload.pl:167 ../scripts/wnpp-alert.1:29 #: ../scripts/wnpp-check.1:26 ../doc/devscripts.conf.5:54 #, no-wrap @@ -573,22 +573,23 @@ msgstr "" #: ../scripts/debc.1:129 ../scripts/debchange.1:493 #: ../scripts/debcheckout.pl:236 ../scripts/debclean.1:113 #: ../scripts/debcommit.pl:968 ../scripts/debdiff.1:259 ../scripts/debi.1:133 +#: ../scripts/debian-watch.pod:1543 ../scripts/debian-watch-4.pod:1413 #: ../scripts/debrepro.pod:175 ../scripts/debrelease.1:136 #: ../scripts/deb-reversion.dbk:292 ../scripts/debrsign.1:70 #: ../scripts/debsign.1:143 ../scripts/debuild.1:459 #: ../scripts/dep3changelog.1:26 ../scripts/dget.pl:755 #: ../scripts/diff2patches.1:48 ../scripts/dpkg-genbuilddeps.1:36 #: ../scripts/dscextract.1:32 ../scripts/dscverify.1:85 -#: ../scripts/getbuildlog.1:41 ../scripts/git-deborig.pl:83 -#: ../scripts/grep-excuses.1:63 ../scripts/hardening-check.pl:692 -#: ../scripts/list-unreleased.1:21 ../scripts/manpage-alert.1:28 -#: ../scripts/mass-bug.pl:596 ../scripts/mergechanges.1:28 -#: ../scripts/mk-build-deps.pl:141 ../scripts/mk-origtargz.pl:213 -#: ../scripts/namecheck.pl:24 ../scripts/nmudiff.1:131 -#: ../scripts/origtargz.pl:166 ../scripts/plotchangelog.1:126 -#: ../scripts/pts-subscribe.1:56 ../scripts/rc-alert.1:125 -#: ../scripts/rmadison.pl:410 ../scripts/salsa.pl:1098 ../scripts/svnpath.pl:96 -#: ../scripts/transition-check.pl:81 ../scripts/uscan.pl:2205 +#: ../scripts/getbuildlog.1:41 ../scripts/grep-excuses.1:63 +#: ../scripts/hardening-check.pl:692 ../scripts/list-unreleased.1:21 +#: ../scripts/manpage-alert.1:28 ../scripts/mass-bug.pl:596 +#: ../scripts/mergechanges.1:28 ../scripts/mk-build-deps.pl:141 +#: ../scripts/mk-origtargz.pl:218 ../scripts/namecheck.pl:24 +#: ../scripts/nmudiff.1:131 ../scripts/origtargz.pl:166 +#: ../scripts/plotchangelog.1:126 ../scripts/pts-subscribe.1:56 +#: ../scripts/rc-alert.1:125 ../scripts/rmadison.pl:410 +#: ../scripts/salsa.pl:1119 ../scripts/svnpath.pl:96 +#: ../scripts/transition-check.pl:81 ../scripts/uscan.pl:827 #: ../scripts/uupdate.1:196 ../scripts/whodepends.1:19 #: ../scripts/who-uploads.1:73 ../scripts/who-permits-upload.pl:162 #: ../scripts/wnpp-alert.1:31 ../scripts/wnpp-check.1:36 @@ -805,10 +806,10 @@ msgid "" "character though, so you may need to quote it!)" msgstr "" "Für Ihren Komfort wurden ein paar zusätzliche Befehle hinzugefügt und dieses " -"Programm ist ist weniger strikt in dem, was eine gültige Fehlernummer " -"darstellt. Beispielsweise wird »severity Bug#85942 normal« wie auch " -"»severity #85942 normal« verstanden. (Allerdings könnte Ihre Shell »#« als " -"Kommentarzeichen ansehen, weswegen Sie es maskieren müssen!)" +"Programm ist weniger strikt in dem, was eine gültige Fehlernummer darstellt. " +"Beispielsweise wird »severity Bug#85942 normal« wie auch »severity #85942 " +"normal« verstanden. (Allerdings könnte Ihre Shell »#« als Kommentarzeichen " +"ansehen, weswegen Sie es maskieren müssen!)" #. type: textblock #: ../scripts/bts.pl:220 @@ -818,8 +819,8 @@ msgid "" "commands). So it understands things like \"bts cl 85942\"." msgstr "" "Außerdem ermöglicht Ihnen dieses Programm zu Ihrer Annehmlichkeit Befehle " -"auf die kleinste eindeutige Teilzeichenkette abzukürzen (ähnlich wie Sie CVS " -"Befehle abkürzen lässt). So versteht es Dinge wie »bts cl 85942«." +"auf die kleinste eindeutige Teilzeichenkette abzukürzen (ähnlich wie sich " +"CVS Befehle abkürzen lassen). So versteht es Dinge wie »bts cl 85942«." #. type: textblock #: ../scripts/bts.pl:224 @@ -833,12 +834,13 @@ msgid "" "normal\" will not be treated as a comment!)" msgstr "" "Es ist ebenfalls möglich, der E-Mail an das BTS einen Kommentar beizufügen. " -"Falls Ihre Shell nicht den Kommentar in einem Befehl wie »bts severity 30321 " -"normal #inflated severity« streicht, dann ist dieses Programm schlau genug " -"herauszufinden, wo der Kommentar ist und ihn in die E-Mail einzufügen. " -"Beachten Sie, dass die meisten Shells solche Kommentare streichen, bevor sie " -"beim Programm ankommen, es sei denn, der Kommentar ist maskiert. (Etwas wie " -"»bts severity #85942 normal« wird nicht als Kommentar angesehen!)" +"Falls Ihre Shell den Kommentar in einem Befehl wie »bts severity 30321 " +"normal #inflated severity« nicht beachtet, dann ist dieses Programm klug " +"genug herauszufinden, wo der Kommentar ist, und ihn in die E-Mail " +"einzufügen. Beachten Sie, dass die meisten Shells solche Kommentare " +"streichen, bevor sie beim Programm ankommen, es sei denn, der Kommentar ist " +"maskiert. (Etwas wie »bts severity #85942 normal« wird nicht als Kommentar " +"angesehen!)" #. type: textblock #: ../scripts/bts.pl:232 @@ -851,9 +853,9 @@ msgid "" msgstr "" "Sie können mehrere Befehle angeben, indem Sie sie durch einen einzelnen " "Punkt trennen, ungefähr wie B; ein einzelnes Komma könnte auch " -"benutzt werden; alle die Befehle werden in einer einzigen E-Mail gesandt. Es " -"ist wichtig, dass der Punkt/das Komma von Leerzeichen umgeben ist, damit es " -"nicht als Teil des Befehls missverstanden wird. Zum Beispiel (wo nötig " +"benutzt werden; all diese Befehle werden in einer einzigen E-Mail gesandt. " +"Es ist wichtig, dass der Punkt/das Komma von Leerzeichen umgeben ist, damit " +"es nicht als Teil des Befehls missverstanden wird. Zum Beispiel (wo nötig " "maskieren, so dass B den Kommentar sieht):" #. type: verbatim @@ -902,7 +904,7 @@ msgid "" msgstr "" "B durchsucht die B-Konfigurationsdateien wie oben " "beschrieben. Befehlszeilenoptionen setzen jedoch die Einstellungen der " -"Konfigurationsdatei außer Kr." +"Konfigurationsdatei außer Kraft." #. type: =item #: ../scripts/bts.pl:256 @@ -1440,7 +1442,7 @@ msgstr "" #: ../scripts/debrelease.1:95 ../scripts/debsign.1:95 ../scripts/debuild.1:258 #: ../scripts/dpkg-depcheck.1:92 ../scripts/dscverify.1:25 #: ../scripts/grep-excuses.1:15 ../scripts/mass-bug.pl:125 -#: ../scripts/nmudiff.1:78 ../scripts/rmadison.pl:348 ../scripts/uscan.pl:1651 +#: ../scripts/nmudiff.1:78 ../scripts/rmadison.pl:348 ../scripts/uscan.pl:287 #: ../scripts/uupdate.1:56 ../scripts/who-uploads.1:41 #, no-wrap msgid "B<--no-conf>, B<--noconf>" @@ -1461,7 +1463,7 @@ msgstr "" "Befehlszeile angegebene Option benutzt werden." #. type: =head1 -#: ../scripts/bts.pl:814 ../scripts/chdist.pl:62 ../scripts/salsa.pl:57 +#: ../scripts/bts.pl:814 ../scripts/chdist.pl:62 ../scripts/salsa.pl:60 msgid "COMMANDS" msgstr "BEFEHLE" @@ -3655,7 +3657,7 @@ msgstr "führt den Fehlersuchmodus aus." #: ../scripts/debclean.1:87 ../scripts/diff2patches.1:22 #: ../scripts/grep-excuses.1:23 ../scripts/mass-bug.pl:135 #: ../scripts/nmudiff.1:92 ../scripts/plotchangelog.1:92 -#: ../scripts/salsa.pl:545 ../scripts/uscan.pl:1871 +#: ../scripts/salsa.pl:561 ../scripts/uscan.pl:499 #, no-wrap msgid "B<--help>" msgstr "B<--help>" @@ -3675,7 +3677,7 @@ msgstr "zeigt die Aufrufinformationen." #: ../scripts/dscverify.1:41 ../scripts/grep-excuses.1:26 #: ../scripts/mass-bug.pl:139 ../scripts/nmudiff.1:95 #: ../scripts/plotchangelog.1:95 ../scripts/pts-subscribe.1:31 -#: ../scripts/rmadison.pl:344 ../scripts/uscan.pl:1875 ../scripts/uupdate.1:104 +#: ../scripts/rmadison.pl:344 ../scripts/uscan.pl:503 ../scripts/uupdate.1:104 #: ../scripts/who-uploads.1:48 #, no-wrap msgid "B<--version>" @@ -3761,14 +3763,12 @@ msgstr "chdist - Skript, um einfach mit mehreren Distributionen zu spielen" #. type: textblock #: ../scripts/chdist.pl:24 msgid "B [I] [I] [I]" -msgstr "B [I] [I] [I]" +msgstr "B [I] [I] [I]" #. type: textblock #: ../scripts/chdist.pl:26 -#, fuzzy -#| msgid "B [I] [I] [I]" msgid "B [I] I I [I]" -msgstr "B [I] [I] [I]" +msgstr "B [I] I I [I]" #. type: textblock #: ../scripts/chdist.pl:28 @@ -3778,6 +3778,11 @@ msgid "" "may be any program available on the system and anything based on apt will be " "using the I apt data." msgstr "" +"Die zweite Form wird akzeptiert, wenn I nicht in der unten " +"aufgeführten Liste von Befehlen enthalten ist (siehe L). In dem " +"Fall kann I jedes auf dem System verfügbare Programm sein und alle " +"auf apt basierenden Programme werden die apt-Daten aus I " +"verwenden." #. type: textblock #: ../scripts/chdist.pl:35 @@ -3801,7 +3806,7 @@ msgstr "stellt einen Aufruftext bereit." #. type: =item #: ../scripts/chdist.pl:48 msgid "B<-d>, B<--data-dir> I" -msgstr "B<-d>, B<--data-dir> I" +msgstr "B<-d>, B<--data-dir> I" #. type: textblock #: ../scripts/chdist.pl:50 @@ -3820,7 +3825,7 @@ msgstr "wählt die Architektur aus (Vorgabe: »B«)." #. type: textblock #: ../scripts/chdist.pl:58 ../scripts/deb-reversion.dbk:239 -#: ../scripts/mass-bug.pl:141 ../scripts/uscan.pl:1877 +#: ../scripts/mass-bug.pl:141 ../scripts/uscan.pl:505 msgid "Display version information." msgstr "zeigt Versionsinformationen." @@ -3842,7 +3847,7 @@ msgstr "B I |B|B|B|…>" #. type: textblock #: ../scripts/chdist.pl:72 msgid "Run B inside I" -msgstr "führt B innerhalb I aus." +msgstr "führt B innerhalb von I aus." #. type: =item #: ../scripts/chdist.pl:74 @@ -3852,7 +3857,7 @@ msgstr "B I |B|…>" #. type: textblock #: ../scripts/chdist.pl:76 msgid "Run B inside I" -msgstr "führt B innerhalb I aus." +msgstr "führt B innerhalb von I aus." #. type: =item #: ../scripts/chdist.pl:78 @@ -3862,17 +3867,17 @@ msgstr "B I |B|…>" #. type: textblock #: ../scripts/chdist.pl:80 msgid "Run B inside I" -msgstr "führt B innerhalb I aus." +msgstr "führt B innerhalb von I aus." #. type: =item #: ../scripts/chdist.pl:82 msgid "B I |B|...>" -msgstr "B I |B|…>" +msgstr "B I |B|…>" #. type: textblock #: ../scripts/chdist.pl:84 msgid "Run B inside I" -msgstr "führt B innerhalb I aus." +msgstr "führt B innerhalb von I aus." #. type: =item #: ../scripts/chdist.pl:86 @@ -3882,14 +3887,12 @@ msgstr "B I […]" #. type: textblock #: ../scripts/chdist.pl:88 msgid "Run B inside I" -msgstr "führt B innerhalb I aus." +msgstr "führt B innerhalb von I aus." #. type: =item #: ../scripts/chdist.pl:90 -#, fuzzy -#| msgid "B I [...]" msgid "B I [...]" -msgstr "B I […]" +msgstr "B I […]" #. type: textblock #: ../scripts/chdist.pl:92 @@ -3898,6 +3901,10 @@ msgid "" "codename differ from the system origin and suite/codename then they need to " "be set using B options." msgstr "" +"führt B innerhalb von I aus. Wenn Ursprung und " +"Suite/Codename von I sich von Ursprung und Suite/Codename des " +"Systems unterscheiden, müssen sie per Optionen an B übergeben " +"werden." #. type: =item #: ../scripts/chdist.pl:97 @@ -3907,7 +3914,7 @@ msgstr "B I […]" #. type: textblock #: ../scripts/chdist.pl:99 msgid "Run B inside I" -msgstr "führt B innerhalb I aus." +msgstr "führt B innerhalb von I aus." #. type: =item #: ../scripts/chdist.pl:101 @@ -3964,7 +3971,7 @@ msgid "" msgstr "" "dasselbe wie B/B, führt aber " "zusätzlich B aus und zeigt an, wo das Paket neuer " -"ist" +"ist." #. type: =item #: ../scripts/chdist.pl:122 @@ -3974,7 +3981,7 @@ msgstr "B I" #. type: textblock #: ../scripts/chdist.pl:124 msgid "Compare sources and binaries for I" -msgstr "vergleicht die Quell- und Binärdateien für I" +msgstr "vergleicht die Quell- und Binärdateien für I." #. type: =item #: ../scripts/chdist.pl:126 @@ -3988,7 +3995,7 @@ msgid "" "and display where the package is newer" msgstr "" "dasselbe wie B, führt aber zusätzlich B aus und zeigt an, wo das Paket neuer ist" +"compare-versions> aus und zeigt an, wo das Paket neuer ist." #. type: =item #: ../scripts/chdist.pl:131 @@ -4790,16 +4797,6 @@ msgstr "B" #. type: Plain text #: ../scripts/cowpoke.1:194 -#, fuzzy -#| msgid "" -#| "If this option is set, it is expected to contain the gpg key ID to pass " -#| "to B(1) if the packages are to be remotely signed. You will be " -#| "prompted to confirm whether you wish to sign the packages after all " -#| "builds are complete. If this option is unset or an empty string, no " -#| "attempt to sign packages will be made. It may be overridden on an " -#| "I and I specific basis using the " -#| "IB<_>IB<_SIGN_KEYID> option described below, or per-" -#| "invocation with the B<--sign> command line option." msgid "" "If this option is set, it is expected to contain the OpenPGP key ID to pass " "to B(1) if the packages are to be remotely signed. You will be " @@ -4809,7 +4806,7 @@ msgid "" "specific basis using the IB<_>IB<_SIGN_KEYID> option described " "below, or per-invocation with the B<--sign> command line option." msgstr "" -"Falls diese Option gesetzt ist, wird erwartet, dass sie die GPG-" +"Falls diese Option gesetzt ist, wird erwartet, dass sie die OpenPGP-" "Schlüsselkennung zur Übergabe an B(1) enthält, falls die Pakete aus " "der Ferne signiert werden sollen. Sie werden um Bestätigung gebeten, ob Sie " "die Pakete signieren möchten, nachdem das Bauen aller Pakete abgeschlossen " @@ -6546,7 +6543,7 @@ msgstr "" #. type: =head2 #: ../scripts/debc.1:28 ../scripts/debchange.1:109 ../scripts/debclean.1:27 #: ../scripts/debi.1:28 ../scripts/debrelease.1:20 ../scripts/debuild.1:51 -#: ../scripts/uscan.pl:2086 +#: ../scripts/uscan.pl:708 #, no-wrap msgid "Directory name checking" msgstr "Prüfung von Verzeichnisnamen" @@ -6578,14 +6575,14 @@ msgstr "" #. type: textblock #: ../scripts/debc.1:41 ../scripts/debchange.1:122 ../scripts/debclean.1:40 #: ../scripts/debi.1:41 ../scripts/debrelease.1:33 ../scripts/debuild.1:65 -#: ../scripts/uscan.pl:2101 +#: ../scripts/uscan.pl:723 msgid "B can take the following values:" msgstr "B kann die folgenden Werte annehmen:" #. type: =item #: ../scripts/debc.1:41 ../scripts/debchange.1:122 ../scripts/debclean.1:40 #: ../scripts/debi.1:41 ../scripts/debrelease.1:33 ../scripts/debuild.1:65 -#: ../scripts/uscan.pl:2032 ../scripts/uscan.pl:2105 +#: ../scripts/uscan.pl:654 ../scripts/uscan.pl:727 #, no-wrap msgid "B<0>" msgstr "B<0>" @@ -6593,14 +6590,14 @@ msgstr "B<0>" #. type: textblock #: ../scripts/debc.1:44 ../scripts/debchange.1:125 ../scripts/debclean.1:43 #: ../scripts/debi.1:44 ../scripts/debrelease.1:36 ../scripts/debuild.1:68 -#: ../scripts/uscan.pl:2107 +#: ../scripts/uscan.pl:729 msgid "Never check the directory name." msgstr "prüft den Verzeichnisnamen nie." #. type: =item #: ../scripts/debc.1:44 ../scripts/debchange.1:125 ../scripts/debclean.1:43 #: ../scripts/debi.1:44 ../scripts/debrelease.1:36 ../scripts/debuild.1:68 -#: ../scripts/uscan.pl:2037 ../scripts/uscan.pl:2109 +#: ../scripts/uscan.pl:659 ../scripts/uscan.pl:731 #, no-wrap msgid "B<1>" msgstr "B<1>" @@ -6618,7 +6615,7 @@ msgstr "" #. type: =item #: ../scripts/debc.1:48 ../scripts/debchange.1:129 ../scripts/debclean.1:47 #: ../scripts/debi.1:48 ../scripts/debrelease.1:40 ../scripts/debuild.1:72 -#: ../scripts/uscan.pl:2116 +#: ../scripts/uscan.pl:738 #, no-wrap msgid "B<2>" msgstr "B<2>" @@ -6626,7 +6623,7 @@ msgstr "B<2>" #. type: textblock #: ../scripts/debc.1:51 ../scripts/debchange.1:132 ../scripts/debclean.1:50 #: ../scripts/debi.1:51 ../scripts/debrelease.1:43 ../scripts/debuild.1:75 -#: ../scripts/uscan.pl:2118 +#: ../scripts/uscan.pl:740 msgid "Always check the directory name." msgstr "prüft den Verzeichnisnamen immer." @@ -6703,7 +6700,7 @@ msgstr "" #. type: =item #: ../scripts/debc.1:77 ../scripts/debchange.1:382 ../scripts/debclean.1:72 #: ../scripts/debi.1:86 ../scripts/debrelease.1:87 ../scripts/debuild.1:313 -#: ../scripts/uscan.pl:1745 +#: ../scripts/uscan.pl:381 #, no-wrap msgid "B<--check-dirname-level> I" msgstr "B<--check-dirname-level> I" @@ -6723,7 +6720,7 @@ msgstr "" #. type: =item #: ../scripts/debc.1:81 ../scripts/debchange.1:386 ../scripts/debclean.1:76 #: ../scripts/debi.1:90 ../scripts/debrelease.1:91 ../scripts/debuild.1:317 -#: ../scripts/uscan.pl:1749 +#: ../scripts/uscan.pl:385 #, no-wrap msgid "B<--check-dirname-regex> I" msgstr "B<--check-dirname-regex> I" @@ -7368,7 +7365,7 @@ msgstr "" #. type: =item #: ../scripts/debchange.1:218 ../scripts/mk-origtargz.pl:71 -#: ../scripts/uscan.pl:1776 +#: ../scripts/uscan.pl:412 #, no-wrap msgid "B<--package> I" msgstr "B<--package> I" @@ -9327,7 +9324,8 @@ msgstr "" "Commit-Nachricht automatisch aus dem Changelog bestimmt wurde." #. type: =item -#: ../scripts/debcommit.pl:167 ../scripts/uscan.pl:399 +#: ../scripts/debcommit.pl:167 ../scripts/debian-watch.pod:299 +#: ../scripts/debian-watch-4.pod:277 msgid "B" msgstr "B" @@ -10643,17894 +10641,20552 @@ msgstr "" "Gilbey Ejdg@debian.orgE verändert." #. type: textblock -#: ../scripts/debrepro.pod:3 -msgid "debrepro - reproducibility tester for Debian packages" -msgstr "debrepro - Reproduzierbarkeitstester für Debian-Pakete" - -#. type: textblock -#: ../scripts/debrepro.pod:7 -msgid "B [I] [I]" -msgstr "B [I] [I]" - -#. type: textblock -#: ../scripts/debrepro.pod:11 -msgid "" -"B will build a given source directory twice, with a set of " -"variations between the first and the second build, and compare the produced " -"binary packages. If B is installed, it is used to compare non-" -"matching binaries. If B is installed, it is used during the " -"build to inject non-determinism in filesystem listing operations." +#: ../scripts/debian-watch.pod:5 +msgid "debian/watch version 5 - Format specification for debian/watch." msgstr "" -"B wird ein angegebenes Quellverzeichnis zweimal bauen, mit einem " -"Satz von Veränderungen zwischen erstem und zweiten Bauen und dann die " -"erzeugten Binärpakete vergleichen. Falls B installiert ist, wird " -"es zum Vergleich unpassender Programme verwendet. Falls B " -"installiert ist, wird es während des Bauens benutzt, um nicht vorbestimmtes " -"in Dateisystemauflistungsaktionen einzuspeisen." #. type: textblock -#: ../scripts/debrepro.pod:18 +#: ../scripts/debian-watch.pod:9 +#, fuzzy +#| msgid "" +#| "The current version 4 format of F can be summarized as " +#| "follows:" msgid "" -"I must be a directory containing an unpacked Debian source " -"package. If I is omitted, the current directory is assumed." +"This document describe current version format of F I<(version " +"5)>." msgstr "" -"I muss ein Verzeichnis sein, das ein entpacktes Debian-Quellpaket " -"enthält. Falls I weggelassen wird, wird das aktuelle Verzeichnis " -"angenommen." +"Das derzeitig Format der Version 4 von F kann wie folgt " +"zusammengefasst werden" #. type: =head1 -#: ../scripts/debrepro.pod:21 -msgid "OUTPUT DIRECTORY" -msgstr "AUSGABEVERZEICHNIS" +#: ../scripts/debian-watch.pod:11 +#, fuzzy +#| msgid "FORMAT OF THE WATCH FILE" +msgid "FORMAT OF THE WATCH FILE, VERSION 5" +msgstr "FORMAT DER WATCH-DATEI" #. type: textblock -#: ../scripts/debrepro.pod:23 -msgid "" -"At the very end of a build, B will inform the location of the " -"output directory where the build artifacts can be found. In that directory, " -"you will find:" +#: ../scripts/debian-watch.pod:13 +#, fuzzy +#| msgid "" +#| "The current version 4 format of F can be summarized as " +#| "follows:" +msgid "The version 5 format of F can be summarized as follows:" msgstr "" -"Ganz am Ende des Bauens wird B den Speicherort des " -"Ausgabeverzeichnisses mitteilen, wo die Bauartefakte zu finden sind. In " -"diesem Verzeichnis werden Sie folgendes finden:" +"Das derzeitig Format der Version 4 von F kann wie folgt " +"zusammengefasst werden" #. type: =item -#: ../scripts/debrepro.pod:29 -msgid "I<$OUTPUTDIR/first>" -msgstr "I<$AUSGABEVERZ/first>" - -#. type: textblock -#: ../scripts/debrepro.pod:31 -msgid "" -"Contains the results of the first build, including a copy of the source " -"tree, and the resulting binary packages." +#: ../scripts/debian-watch.pod:17 +msgid "* File is written using rfc822-style, like other debian files." msgstr "" -"enthält die Ergebnisse des ersten Bauens, einschließlich einer Kopie des " -"Quellverzeichnisbaums und den daraus resultierenden Binärpaketen." #. type: =item -#: ../scripts/debrepro.pod:34 -msgid "I<$OUTPUTDIR/first/build.sh>" -msgstr "I<$AUSGABEVERZ/first/build.sh>" - -#. type: textblock -#: ../scripts/debrepro.pod:36 -msgid "Contains the exact build script that was used in the first build." -msgstr "enthält das genaue Bauskript, das beim ersten Bauen benutzt wurde." +#: ../scripts/debian-watch.pod:19 +msgid "* Key names are case-insensitive" +msgstr "" #. type: =item -#: ../scripts/debrepro.pod:38 -msgid "I<$OUTPUTDIR/second>" -msgstr "I<$AUSGABEVERZ/second>" - -#. type: textblock -#: ../scripts/debrepro.pod:40 +#: ../scripts/debian-watch.pod:21 msgid "" -"Contains the results of the second build, including a copy of the source " -"tree, and the resulting binary packages." +"* Key names hyphens are ignored. Then B is equivalent to " +"B" msgstr "" -"enthält die Ergebnisse des zweiten Bauens, einschließlich einer Kopie des " -"Quellverzeichnisbaums und den daraus resultierenden Binärpaketen." +# http://www.zeichen.tv/ #. type: =item -#: ../scripts/debrepro.pod:43 -msgid "I<$OUTPUTDIR/second/build.sh>" -msgstr "I<$AUSGABEVERZ/second/build.sh>" - -#. type: textblock -#: ../scripts/debrepro.pod:45 -msgid "Contains the exact build script that was used in the second build." -msgstr "enthält das genaue Bauskript, das beim zweiten Bauen benutzt wurde." +#: ../scripts/debian-watch.pod:24 ../scripts/debian-watch-4.pod:21 +msgid "* A line started by B<#> (hash) is a comment line and dropped." +msgstr "" +"* Eine Zeile, die mit B<#> (Doppelkreuz) beginnt, ist eine Kommentarzeile " +"und wird weggelassen." -#. type: textblock -#: ../scripts/debrepro.pod:49 -msgid "" -"Taking a B between I<$OUTPUTDIR/first/build.sh> and I<$OUTPUTDIR/" -"second/build.sh> is an excellent way of figuring out exactly what changed " -"between the two builds." +#. type: =item +#: ../scripts/debian-watch.pod:26 +msgid "* First paragraph" msgstr "" -"Um herauszufinden, was genau sich zwischen den beiden Bauvorgängen geändert " -"hat, ist B zwischen I<$AUSGABEVERZ/first/build.sh> und " -"I<$AUSGABEVERZ/second/build.sh> eine hervorragende Methode." -#. type: =head1 -#: ../scripts/debrepro.pod:53 -msgid "SUPPORTED VARIATIONS" -msgstr "UNTERSTÜTZTE VARIATIONEN" +#. type: =item +#: ../scripts/debian-watch.pod:30 +#, fuzzy +#| msgid "* The first non-comment line is:" +msgid "* The first non-comment line of the first paragraph is:" +msgstr "* Die erste Nichtkommentarzeile ist:" #. type: =item -#: ../scripts/debrepro.pod:57 -msgid "B" -msgstr "B" +#: ../scripts/debian-watch.pod:34 +#, fuzzy +#| msgid "B" +msgid "B" +msgstr "B" #. type: textblock -#: ../scripts/debrepro.pod:59 +#: ../scripts/debian-watch.pod:38 ../scripts/debian-watch-4.pod:36 +msgid "This is a required line and the recommended version number." +msgstr "Dies ist eine benötigte Zeile und die empfohlene Versionsnummer." + +#. type: =item +#: ../scripts/debian-watch.pod:40 msgid "" -"The I<$USER> environment variable will contain different values between the " -"first and second builds." +"* All other options inserted into first paragraph are used as default values " +"for next paragraphs" msgstr "" -"Die Umgebungsvariable I<$USER> wird bei erstem und zweitem Bauen " -"unterschiedliche Werte enthalten." #. type: =item -#: ../scripts/debrepro.pod:62 -msgid "B" -msgstr "B" - -#. type: textblock -#: ../scripts/debrepro.pod:64 +#: ../scripts/debian-watch.pod:45 +#, fuzzy +#| msgid "" +#| "* The following non-comment lines (watch lines) specify the rules for the " +#| "selection of the candidate upstream tarball URLs and are in one of the " +#| "following three formats:" msgid "" -"During the second build, a fake, non-existing directory will be appended to " -"the I<$PATH> environment variable." +"* The following paragraphs (watch sources) specify the rules for the " +"selection of the candidate upstream tarball URLs:" msgstr "" -"Während des zweiten Bauens wird ein gefälschtes, nicht existierendes " -"Verzeichnis an die Umgebungsvariable I<$PATH> angehängt." +"* Die folgenden Nichtkommentarzeilen (Watch-Zeilen) geben die Regeln für die " +"Auswahl der Kandidaten für Tarball-URLs der Ursprungsautoren in einem der " +"folgenden drei Formate an:" #. type: =item -#: ../scripts/debrepro.pod:67 -msgid "B" -msgstr "B" - -#. type: textblock -#: ../scripts/debrepro.pod:69 -msgid "The builds will use different umask settings." -msgstr "Beim Bauen werden unterschiedliche Umask-Einstellungen verwendet." +#: ../scripts/debian-watch.pod:50 +msgid "" +"* The B field is required. It gives the URL where B will " +"look at candidate upstream tarballs." +msgstr "" #. type: =item -#: ../scripts/debrepro.pod:71 -msgid "B" -msgstr "B" +#: ../scripts/debian-watch.pod:53 +msgid "" +"* The B field is recommended. It specifies the full string " +"matching pattern for hrefs in the web page. B provides also templates " +"that fill this field automatically I<(see below)>. Default value: " +"C<(?:@PACKAGE@)?@ANY_VERSION@@ARCHIVE_EXT@>." +msgstr "" #. type: textblock -#: ../scripts/debrepro.pod:73 -msgid "Both I<$LC_ALL> and I<$LANG> will be different across the two builds." +#: ../scripts/debian-watch.pod:60 +msgid "Other available fields are described in B." msgstr "" -"Sowohl I<$LC_ALL> als auch I<$LANG> werden sich bei den beiden Bauvorgängen " -"unterscheiden." -#. type: =item -#: ../scripts/debrepro.pod:75 -msgid "B" -msgstr "B" - -#. type: textblock -#: ../scripts/debrepro.pod:77 -msgid "I<$TZ> will be different across builds." -msgstr "I<$TZ> wird sich bei den beiden Bauvorgängen unterscheiden." +#. type: =head1 +#: ../scripts/debian-watch.pod:64 ../scripts/debian-watch-4.pod:192 +msgid "WATCH FILE OPTIONS" +msgstr "»WATCH«-DATEIOPTIONEN" -#. type: =item -#: ../scripts/debrepro.pod:79 -msgid "B" -msgstr "B" +#. type: =head2 +#: ../scripts/debian-watch.pod:66 +msgid "Substitutions" +msgstr "" #. type: textblock -#: ../scripts/debrepro.pod:81 +#: ../scripts/debian-watch.pod:68 ../scripts/debian-watch-4.pod:153 msgid "" -"If B is installed, both builds will be done under a disorderfs " -"overlay directory. This will cause filesystem listing operations to be " -"return items in a non-deterministic order." +"There are a few special strings which are substituted by B to make it " +"easy to write the watch file." msgstr "" -"Falls B installiert ist, werden beide Bauvorgänge unter einem " -"überlagernden Disorderfs-Verzeichnis erledigt. Dies führt dazu, dass " -"Dateisystemauflistungstransaktionen Elemente in einer nicht festgelegten " -"Reihenfolge zurückgeben." +"Es gibt ein paar spezielle Zeichenketten, die durch B ersetzt werden, " +"um das Schreiben der Watch-Datei zu erleichtern." #. type: =item -#: ../scripts/debrepro.pod:85 -msgid "B