Upgrade version to 2023.06.18 45/309245/1
authorwang biao <biao716.wang@samsung.com>
Mon, 8 Apr 2024 03:01:57 +0000 (11:01 +0800)
committerwang biao <biao716.wang@samsung.com>
Mon, 8 Apr 2024 03:01:57 +0000 (11:01 +0800)
Change-Id: If12e72333813bd95af632c8e5ba7ebb64706ca08
Signed-off-by: wang biao <biao716.wang@samsung.com>
packaging/build-compare.changes
packaging/build-compare.spec
packaging/functions.sh [changed mode: 0644->0755]
packaging/pkg-diff.sh [changed mode: 0644->0755]
packaging/same-build-result.sh
packaging/srpm-check.sh [changed mode: 0644->0755]

index 3d0dbde..e687537 100644 (file)
@@ -1,4 +1,402 @@
 -------------------------------------------------------------------
+Sat Jun 17 17:17:17 UTC 2023 - olaf@aepfle.de
+
+- Filter dune language version in dune-package files
+
+-------------------------------------------------------------------
+Wed May  3 17:32:18 UTC 2023 - Oleg Girko <ol@infoserver.lv>
+
+- Fix filtering compiled Python modules to handle Python >= 3.7
+
+-------------------------------------------------------------------
+Fri Apr 28 21:21:21 UTC 2023 - olaf@aepfle.de
+
+- remove timestamps from png files
+
+-------------------------------------------------------------------
+Sat Apr  8 23:58:34 UTC 2023 - Oleg Girko <ol@infoserver.lv>
+
+- Ignore more sections when comparing ELF executable files
+
+-------------------------------------------------------------------
+Fri Nov 25 23:51:35 UTC 2022 - Stefan Brüns <stefan.bruens@rwth-aachen.de>
+
+- Trim "PROVIDES" from source rpms (#59, bsc#1205998)
+
+-------------------------------------------------------------------
+Mon Sep 19 08:02:40 UTC 2022 - Dirk Müller <dmueller@suse.com>
+
+- move license to licensedir
+- spec file cleanups
+
+-------------------------------------------------------------------
+Fri Sep  2 07:15:18 UTC 2022 - Martin Kampas <martin.kampas@jolla.com>
+
+- fix compatibility with older sed (#55) 
+
+-------------------------------------------------------------------
+Tue Aug 23 06:53:29 UTC 2022 - Martin Kampas <martin.kampas@jolla.com>
+
+- handle more setuid/setgid ELF variants (#54)
+
+-------------------------------------------------------------------
+Mon Jun 20 12:34:56 UTC 2022 - olaf@aepfle.de
+
+- fix objdump parsing for non-executable sections (#53)
+
+-------------------------------------------------------------------
+Mon Jun 13 13:13:13 UTC 2022 - olaf@aepfle.de
+
+- fix objdump parsing (#52)
+
+-------------------------------------------------------------------
+Fri Mar  4 12:34:56 UTC 2022 - olaf@aepfle.de
+
+- handle -a also in same-build-result.sh
+- Find rpmlint.log in more places
+- fix logic error in appstream comparison
+- rework exit handling in same-build-result.sh
+- Fix result in case no rpmlint.log exist
+- remove count of checks and packages from rpmlint.log
+- remove Check time report from rpmlint.log
+- ELF diffing performance improvements
+- unpack packages in parallel
+- Add zstd handling
+
+-------------------------------------------------------------------
+Wed Feb 23 08:13:27 UTC 2022 - Stefan Seyfried <seife+obs@b1-systems.com>
+
+- Add extra handling for KMP versions
+
+-------------------------------------------------------------------
+Tue Sep 21 19:19:19 UTC 2021 - Stephan Kulow <coolo@suse.de>
+
+- Fix build-compare for shadow package
+
+-------------------------------------------------------------------
+Mon Sep 20 08:25:27 UTC 2021 - Andreas Schwab <schwab@suse.de>
+
+- Properly drop another duration from rpmlint.log
+
+-------------------------------------------------------------------
+Mon Sep  6 07:15:06 UTC 2021 - bwiedemann@suse.de
+
+- Drop another duration from rpmlint.log 
+
+-------------------------------------------------------------------
+Wed Aug 11 20:30:40 UTC 2021 - olaf@aepfle.de
+
+- Handle another Date: variant in DocBook generated man pages
+
+-------------------------------------------------------------------
+Mon Jul 27 06:06:06 UTC 2020 - bwiedemann@suse.de
+
+- Make output more diffable and readable
+- Fix regression in compare_archive
+- Fix unit tests
+
+-------------------------------------------------------------------
+Fri May 29 19:20:21 UTC 2020 - olaf@aepfle.de
+
+- Remove usage of readarray to remain compatible with bash3
+
+-------------------------------------------------------------------
+Fri May 29 07:30:51 UTC 2020 - olaf@aepfle.de
+
+- Colltect a list of known rpm tags and use it to build the
+  queryformat string for the tags listed below (bsc#1172232)
+  conflict obsolete oldsuggests provide recommend require suggest supplement
+
+-------------------------------------------------------------------
+Thu May 14 07:07:07 UTC 2020 - olaf@aepfle.de
+
+- Trim first line of man page to catch overly verbose tools (now Pandoc)
+
+-------------------------------------------------------------------
+Wed May 13 13:13:13 UTC 2020 - olaf@aepfle.de
+
+- compare also posttrans scripts, and pretrans + verifyscript
+
+-------------------------------------------------------------------
+Tue May  5 05:05:05 UTC 2020 - olaf@aepfle.de
+
+- handle oddly named ZIP archives
+- touch watchdog every 15 instead of 57 minutes
+
+-------------------------------------------------------------------
+Tue Mar 31 09:09:09 UTC 2020 - olaf@aepfle.de
+
+- gtk-doc: filter version info from html files
+
+-------------------------------------------------------------------
+Fri Jan 10 19:16:29 UTC 2020 - olaf@aepfle.de
+
+- compare archives in separate directory to preserve existing files
+- consider only files and symlinks in verify_before_processing
+
+-------------------------------------------------------------------
+Tue Jan  7 13:59:43 UTC 2020 - olaf@aepfle.de
+
+- this new decade must be handled in man pages created by docbook.xml 
+- use bash Process Substitution in diff_two_files
+- use bash Process Substitution when processing ELF files
+- move normalizing code from check_single_file into separate function
+- better input verification in check_single_file
+- split verification from diff_two_files into separate function
+- move check for ignored files out of check_single_file
+- separate helper functions from code in pkg-diff
+- touch host watchdog when producing output and in loops (issue#35)
+- add functions to touch host watchdog
+- always run cleanup in check_compressed_file
+- use EXIT handler in pkg-diff to remove tmpfiles
+
+-------------------------------------------------------------------
+Wed Aug 14 13:27:38 UTC 2019 - John Vandenberg <jayvdb@gmail.com>
+
+- pkg-diff.sh: Ignore R build timestamp & temp paths
+  https://github.com/openSUSE/build-compare/pull/34
+
+-------------------------------------------------------------------
+Tue Feb 19 09:30:20 UTC 2019 - olaf@aepfle.de
+
+- javadoc: filter dc.created
+- Support filenames with spaces
+- jar: always list files without date+size
+- Fix differing jars reported as identical
+
+-------------------------------------------------------------------
+Tue Aug 28 20:14:53 UTC 2018 - ol@infoserver.lv
+
+- Ignore value of Release header when comparing spec files
+
+-------------------------------------------------------------------
+Fri Jul  6 14:01:17 UTC 2018 - olaf@aepfle.de
+
+- pkg-diff: fix diff returning 0
+
+-------------------------------------------------------------------
+Wed Jul  4 05:58:13 UTC 2018 - olaf@aepfle.de
+
+- Match also ELF pie executable (bsc#1097339)
+
+-------------------------------------------------------------------
+Wed Jul  4 05:42:05 UTC 2018 - olaf@aepfle.de
+
+- Remove trailing space from two match patterns
+
+-------------------------------------------------------------------
+Tue Jun 26 06:45:38 UTC 2018 - olaf@aepfle.de
+
+- Recognize "setuid ELF nn-bit xSB shared object" ELF binaries
+
+-------------------------------------------------------------------
+Mon May 28 13:26:44 UTC 2018 - olaf@aepfle.de
+
+- Avoid large temporary files from hexdump output and avoid
+  diff(1) runing OOM by using a fifo (issue#24)
+
+-------------------------------------------------------------------
+Fri Apr 13 07:10:30 UTC 2018 - olaf@aepfle.de
+
+- check rpm capabilities for recommends/suggests
+
+-------------------------------------------------------------------
+Fri Dec  8 16:57:00 UTC 2017 - ol@infoserver.lv
+
+- Ignore /usr/lib/.build-id differences in package filelist
+
+-------------------------------------------------------------------
+Mon Dec  4 10:21:44 UTC 2017 - olaf@aepfle.de
+
+- Treat .egg files as zip
+
+-------------------------------------------------------------------
+Wed Nov  8 06:04:42 UTC 2017 - olaf@aepfle.de
+
+- srpm check requires cpio
+
+-------------------------------------------------------------------
+Mon Nov  6 15:15:04 UTC 2017 - olaf@aepfle.de
+
+- Fix usage of cmp_spec and unrpm in srpm-check.sh
+
+-------------------------------------------------------------------
+Fri Nov  3 14:03:04 UTC 2017 - olaf@aepfle.de
+
+- Catch empty rpm -qp --qf output for tags not understood by rpm
+
+-------------------------------------------------------------------
+Fri Oct 20 06:53:18 UTC 2017 - olaf@aepfle.de
+
+- Remove newly introduced files-duplicate check from rpmlint
+  In case files are hardlinked, the source and destination is
+  scrambled in rpm output: the pkg will be republished.
+  In case files are not hardlinked, the source and destination
+  is scrambled in rpmlint output: the pkg will be republished
+
+-------------------------------------------------------------------
+Thu Jul 27 12:05:25 UTC 2017 - olaf@aepfle.de
+
+- Compare also supplements and recomments (issue#18)
+
+-------------------------------------------------------------------
+Fri Mar 31 13:44:11 UTC 2017 - olaf@aepfle.de
+
+- Handle timestamp and checksum in xen.efi
+
+-------------------------------------------------------------------
+Wed Mar 22 19:05:36 UTC 2017 - olaf@aepfle.de
+
+- Handle _kf5_htmldir, it HAD to be different...
+
+-------------------------------------------------------------------
+Tue Mar 21 11:17:26 UTC 2017 - olaf@aepfle.de
+
+- Handle /usr/share/vdr/locale/
+
+-------------------------------------------------------------------
+Sun Feb 12 08:41:01 UTC 2017 - olaf@aepfle.de
+
+- Remove warning file-contains-date-and-time from rpmlint.log
+
+-------------------------------------------------------------------
+Thu Jan  5 11:01:53 UTC 2017 - olaf@aepfle.de
+
+- Fix name-version-release regex for release without dots
+
+-------------------------------------------------------------------
+Wed Dec 14 08:44:11 UTC 2016 - olaf@aepfle.de
+
+- Remove warning about python mtime mismatch, a republish will not help (bsc#915948)
+- Handle yet another variant of numbered anchor in html file
+
+-------------------------------------------------------------------
+Wed Nov  9 06:48:22 UTC 2016 - olaf@aepfle.de
+
+- Ignore /etc/ld.so.cache
+- Ignore /etc/machine-id
+
+-------------------------------------------------------------------
+Tue Nov  8 08:06:30 UTC 2016 - olaf@aepfle.de
+
+- Ignore /etc/hosts
+- Handle every path matching /share/man/ as man page
+
+-------------------------------------------------------------------
+Mon Nov  7 03:54:00 UTC 2016 - ol@infoserver.lv
+
+- Ignore .gnu_debugdata section when comparing ELF files.
+
+-------------------------------------------------------------------
+Wed Oct 12 16:40:24 CEST 2016 - ro@suse.de
+
+- pkg-diff.sh: use option --speed-large-files for diffing
+  disassembler output (bsc#1003528)
+
+-------------------------------------------------------------------
+Wed Sep 21 07:18:37 UTC 2016 - olaf@aepfle.de
+
+- Handle broken symlinks
+
+-------------------------------------------------------------------
+Thu Aug 25 14:27:34 UTC 2016 - olaf@aepfle.de
+
+- Update strip_numbered_anchors to catch more random identifiers
+
+-------------------------------------------------------------------
+Wed Aug 24 13:22:12 UTC 2016 - liezhi.yang@windriver.com
+
+- functions.sh: improve deb and ipk checking
+- Add support for deb and ipk packaging
+- pkg-diff.sh: check for fifo (named fifo)
+- pkg-diff.sh: remove space in the end for ftype
+- pkg-diff.sh: check_single_file(): return at once when same
+- functions.sh: run rpm once to make it faster
+
+-------------------------------------------------------------------
+Fri Aug  5 13:44:51 UTC 2016 - olaf@aepfle.de
+
+- Handle unknown ELF files as different.
+
+-------------------------------------------------------------------
+Wed Apr  6 07:06:58 UTC 2016 - olaf@aepfle.de
+
+- add used utilities to Requires
+
+-------------------------------------------------------------------
+Tue Mar  8 18:00:40 UTC 2016 - olaf@aepfle.de
+
+- Remove hacks from /var/adm/update-scripts|messages case
+
+-------------------------------------------------------------------
+Tue Mar  8 16:48:48 UTC 2016 - olaf@aepfle.de
+
+- Handle /var/adm/update-messages in scripts and filelist
+
+-------------------------------------------------------------------
+Mon Mar  7 11:56:28 UTC 2016 - olaf@aepfle.de
+
+- Whitespace in javadoc case
+- Whitespace changes in html case
+- Move case kde/gtk html up in the case list
+- Move case rdoc html up in the case list
+- Add option -a to same-build-result.sh and loop through all rpms
+- Rework sorting of rpm files in same-build-result.sh
+- Better diagnostic if number of subpackages changes
+- Create tmpfiles earlier in same-build-result.sh
+- Handle all javadoc html files
+
+-------------------------------------------------------------------
+Fri Mar  4 18:50:32 UTC 2016 - olaf@aepfle.de
+
+- Handle yet another variant of elc timestamps
+
+-------------------------------------------------------------------
+Thu Mar  3 12:44:04 UTC 2016 - olaf@aepfle.de
+
+- Handle timestamp in dvi files
+- Handle Last-modified HTML META tag
+- Handle yet another variant of javadoc timestamps
+
+-------------------------------------------------------------------
+Fri Jan  1 10:11:14 UTC 2016 - schwab@suse.de
+
+- Fix quoting in find expression
+
+-------------------------------------------------------------------
+Thu Oct 22 06:29:44 UTC 2015 - olaf@aepfle.de
+
+- Remove filename-too-long-for-joliet from rpmlint.log
+
+-------------------------------------------------------------------
+Mon Oct 12 13:59:31 UTC 2015 - olaf@aepfle.de
+
+- Filter out durations from rpmlint progress report 
+
+-------------------------------------------------------------------
+Fri Oct  2 09:00:52 UTC 2015 - olaf@aepfle.de
+
+- Handle texi2html 5.0 timestamps
+
+-------------------------------------------------------------------
+Fri Aug 21 12:57:57 UTC 2015 - seife+obs@b1-systems.com
+
+- avoid -kmp packages with "filename-too-long-for-joliet"
+  triggering constant republishing
+
+-------------------------------------------------------------------
+Wed Jul 15 09:50:58 UTC 2015 - olaf@aepfle.de
+
+- 2015.07.15
+- Handle more texi2html generated files and patterns
+
+-------------------------------------------------------------------
+Wed Jun 17 14:25:06 UTC 2015 - olaf@aepfle.de
+
+- 2015.06.17
+- Fix regex to handle /lib/(modules|firmware)/version-release-any properly
+
+-------------------------------------------------------------------
 Tue Apr 28 11:52:12 UTC 2015 - olaf@aepfle.de
 
 - 2015.04.28
index fa2ac3c..4b380f2 100644 (file)
@@ -21,7 +21,7 @@ Summary:        Build Result Compare Script
 License:        GPL-2.0+
 Group:          Development/Tools/Building
 Url:            https://github.com/openSUSE/build-compare
-Version:        2015.04.28
+Version:        2023.06.18
 Release:        0
 Source1:        COPYING
 Source2:        same-build-result.sh
old mode 100644 (file)
new mode 100755 (executable)
index 89057a5..e5af36b
 
 RPM="rpm -qp --nodigest --nosignature"
 
-check_header() 
-{
-   $RPM --qf "$QF" "$1"
+declare -a rpm_querytags
+collect_rpm_querytags() {
+  rpm_querytags=( $(rpm --querytags) )
+}
+# returns 0 if tag is known, returns 1 if unknown
+rpmtag_known() {
+  local needle="\<${1}\>"
+  local haystack="${rpm_querytags[@]}"
+  [[ "${haystack}" =~ ${needle} ]]
+  return $?
 }
 
-function is_prerelease_project() {
-  local proj_name=$1
-  if [[ $proj_name =~ "prerelease" ]] || [[ $proj_name =~ "trbs" ]]; then
-    return 1
-  fi
+set_rpm_meta_global_variables() {
+
+  local pkg=$1
+  local rpm_tags=
+  local out=`mktemp`
+  local t v qt
+  local -a type variant list
+
+# Name, Version, Release
+QF_NAME="%{NAME}"
+QF_VER_REL="%{VERSION}-%{RELEASE}"
+QF_NAME_VER_REL="%{NAME}-%{VERSION}-%{RELEASE}"
+
+QF_PROVIDES=
+type=(
+  CONFLICT
+  OBSOLETE
+  OLDSUGGESTS
+  PROVIDE
+  RECOMMEND
+  REQUIRE
+  SUGGEST
+  SUPPLEMENT
+)
+variant=(
+  NAME
+  FLAGS
+  VERSION
+)
+for t in "${type[@]}"
+do
+  unset list
+  list=()
+  for v in "${variant[@]}"
+  do
+    qt="${t}${v}"
+    rpmtag_known "${qt}" || continue
+    list+=("%{${qt}}")
+  done
+  QF_PROVIDES+="${t}\\n[${list[@]}\\n]\\n"
+done
+
+# don't look at RELEASE, it contains our build number
+QF_TAGS="%{NAME} %{VERSION} %{EPOCH}\\n"
+QF_TAGS="${QF_TAGS}%{SUMMARY}\\n%{DESCRIPTION}\\n"
+# the DISTURL tag can be used as checkin ID
+QF_TAGS="${QF_TAGS}%{VENDOR} %{DISTRIBUTION} %{DISTURL}\\n"
+QF_TAGS="${QF_TAGS}%{LICENSE}\\n"
+QF_TAGS="${QF_TAGS}%{GROUP} %{URL} %{EXCLUDEARCH} %{EXCLUDEOS} %{EXCLUSIVEARCH}\\n"
+QF_TAGS="${QF_TAGS}%{EXCLUSIVEOS} %{RPMVERSION} %{PLATFORM}\\n"
+QF_TAGS="${QF_TAGS}%{PAYLOADFORMAT} %{PAYLOADCOMPRESSOR} %{PAYLOADFLAGS}\\n"
+
+# XXX We also need to check the existence (but not the content (!))
+# of SIGGPG (and perhaps the other SIG*)
+# XXX We don't look at triggers
+# Only the first ChangeLog entry; should be enough
+QF_TAGS="${QF_TAGS}%{CHANGELOGTIME} %{CHANGELOGNAME} %{CHANGELOGTEXT}\\n"
+
+# scripts, might contain release number
+QF_SCRIPT=
+type=(
+  PRETRANS
+  PREIN
+  POSTIN
+  PREUN
+  POSTUN
+  POSTTRANS
+  VERIFYSCRIPT
+)
+variant=(
+  PROG
+  FLAGS
+  ''
+)
+for t in "${type[@]}"
+do
+  unset list
+  list=()
+  for v in "${variant[@]}"
+  do
+    qt="${t}${v}"
+    rpmtag_known "${qt}" || continue
+    list+=("%{${qt}}")
+  done
+  QF_SCRIPT+="${t}\\n[${list[@]}\\n]\\n"
+done
 
-  return 0
+# Now the files. We leave out mtime and size.  For normal files
+# the size will influence the MD5 anyway.  For directories the sizes can
+# differ, depending on which file system the package was built.  To not
+# have to filter out directories we simply ignore all sizes.
+# Also leave out FILEDEVICES, FILEINODES (depends on the build host),
+# FILECOLORS, FILECLASS (normally useful but file output contains mtimes),
+# FILEDEPENDSX and FILEDEPENDSN.
+# Also FILELANGS (or?)
+QF_FILELIST="[%{FILENAMES} %{FILEFLAGS} %{FILESTATES} %{FILEMODES:octal} %{FILEUSERNAME} %{FILEGROUPNAME} %{FILERDEVS} %{FILEVERIFYFLAGS} %{FILELINKTOS}\n]\\n"
+# ??? what to do with FILEPROVIDE and FILEREQUIRE?
+
+QF_CHECKSUM="[%{FILENAMES} %{FILEMD5S} %{FILEFLAGS}\n]\\n"
+
+QF_SOURCERPM="%{SOURCERPM}\\n"
+
+QF_ALL="\n___QF_NAME___\n${QF_NAME}\n___QF_NAME___\n"
+QF_ALL="$QF_ALL\n___QF_TAGS___\n${QF_TAGS}\n___QF_TAGS___\n"
+QF_ALL="$QF_ALL\n___QF_VER_REL___\n${QF_VER_REL}\n___QF_VER_REL___\n"
+QF_ALL="$QF_ALL\n___QF_NAME_VER_REL___\n${QF_NAME_VER_REL}\n___QF_NAME_VER_REL___\n"
+QF_ALL="$QF_ALL\n___QF_PROVIDES___\n${QF_PROVIDES}\n___QF_PROVIDES___\n"
+QF_ALL="$QF_ALL\n___QF_SCRIPT___\n${QF_SCRIPT}\n___QF_SCRIPT___\n"
+QF_ALL="$QF_ALL\n___QF_FILELIST___\n${QF_FILELIST}\n___QF_FILELIST___\n"
+QF_ALL="$QF_ALL\n___QF_CHECKSUM___\n${QF_CHECKSUM}\n___QF_CHECKSUM___\n"
+QF_ALL="$QF_ALL\n___QF_SOURCERPM___\n${QF_SOURCERPM}\n___QF_SOURCERPM___\n"
 }
 
+check_header()
+{
+   $RPM --qf "$1" "$2"
+}
 
 # Trim version-release string:
 # - it is used as direntry below certain paths
 # - it is assigned to some variable in scripts, at the end of a line
 # - it is used in PROVIDES, at the end of a line
+#   - special-case KMP package:
+#     PROVIDES version_k.*-release at end of line, trim release
+#     [   23s] -acpi_call-kmp-default 8 1.2.2_k5.17.0_rc5_1.ga9b2c1d-6.110
+#     [   23s] +acpi_call-kmp-default 8 1.2.2_k5.17.0_rc5_1.ga9b2c1d-6.111
 # Trim name-version-release string:
 # - it is used in update-scripts which are called by libzypp
+#   - special-case KMP package:
+#     [   64s]  PREIN
+#     [   64s]  /bin/sh (none)  /usr/lib/module-init-tools/kernel-scriptlets/kmp-pre --name "acpi_call-kmp-default" \
+#     [   64s] -  --version "1.2.2_k5.17.0_rc5_1.ga9b2c1d" --release "6.112" --kernelrelease "5.17.0-rc5-1.ga9b2c1d" \
+#     [   64s] +  --version "1.2.2_k5.17.0_rc5_1.ga9b2c1d" --release "6.113" --kernelrelease "5.17.0-rc5-1.ga9b2c1d" \
 function trim_release_old()
 {
+  local rel_regex_l=${version_release_old_regex_l##*-}
   sed -e "
-  /\(\/boot\|\/lib\/modules\|\/lib\/firmware\|\/usr\/src\|$version_release_old_regex_l\$\)/{s,$version_release_old_regex_l,@VERSION@-@RELEASE_LONG@,g;s,$version_release_old_regex_s,@VERSION@-@RELEASE_SHORT@,g}
+  /\(\/boot\|\/lib\/modules\|\/lib\/firmware\|\/usr\/src\|$version_release_old_regex_l\$\|$version_release_old_regex_l)\)/{s,$version_release_old_regex_l,@VERSION@-@RELEASE_LONG@,g;s,$version_release_old_regex_s,@VERSION@-@RELEASE_SHORT@,g}
   s/\(\/var\/adm\/update-scripts\/\)${name_ver_rel_old_regex_l}\([^[:blank:]]\+\)/\1@NAME_VER_REL@\2/g
+  s/\(\/var\/adm\/update-messages\/\)${name_ver_rel_old_regex_l}\([^[:blank:]]\+\)/\1@NAME_VER_REL@\2/g
+  s/\(^[^[:blank:]].*-kmp-.*[[:blank:]].*_k.*-\)${rel_regex_l}$/\1@RELEASE_LONG@/g
+  s/--release \"${rel_regex_l}\" --kernel/--release \"@RELEASE_LONG@\" --kernel/g
+  /\/usr\/lib\/\.build-id/d
   "
 }
 function trim_release_new()
 {
+  local rel_regex_l=${version_release_new_regex_l##*-}
   sed -e "
-  /\(\/boot\|\/lib\/modules\|\/lib\/firmware\|\/usr\/src\|$version_release_new_regex_l\$\)/{s,$version_release_new_regex_l,@VERSION@-@RELEASE_LONG@,g;s,$version_release_new_regex_s,@VERSION@-@RELEASE_SHORT@,g}
+  /\(\/boot\|\/lib\/modules\|\/lib\/firmware\|\/usr\/src\|$version_release_new_regex_l\$\|$version_release_new_regex_l)\)/{s,$version_release_new_regex_l,@VERSION@-@RELEASE_LONG@,g;s,$version_release_new_regex_s,@VERSION@-@RELEASE_SHORT@,g}
   s/\(\/var\/adm\/update-scripts\/\)${name_ver_rel_new_regex_l}\([^[:blank:]]\+\)/\1@NAME_VER_REL@\2/g
+  s/\(\/var\/adm\/update-messages\/\)${name_ver_rel_new_regex_l}\([^[:blank:]]\+\)/\1@NAME_VER_REL@\2/g
+  s/\(^[^[:blank:]].*-kmp-.*[[:blank:]].*_k.*-\)${rel_regex_l}$/\1@RELEASE_LONG@/g
+  s/--release \"${rel_regex_l}\" --kernel/--release \"@RELEASE_LONG@\" --kernel/g
+  /\/usr\/lib\/\.build-id/d
   "
 }
 # Get single directory or filename with long or short release string
 function grep_release_old()
 {
-  grep -E "(/boot|/lib/modules|/lib/firmware|/usr/src)/[^/]+(${version_release_old_regex_l}(\$|[^/]+\$)|${version_release_old_regex_s}(\$|[^/]+\$))"
+  grep -E "(/boot|/lib/modules|/lib/firmware|/usr/src|/var/adm/update-scripts)/[^/]*(${version_release_old_regex_l}(\$|[^/]+\$)|${version_release_old_regex_s}(\$|[^/]+\$))"
 }
 function grep_release_new()
 {
-  grep -E "(/boot|/lib/modules|/lib/firmware|/usr/src)/[^/]+(${version_release_new_regex_l}(\$|[^/]+\$)|${version_release_new_regex_s}(\$|[^/]+\$))"
-}
-
-function check_provides()
-{
-  local pkg=$1
-  # provides destroy this because at least the self-provide includes the
-  # -buildnumber :-(
-  QF="[%{PROVIDENAME} %{PROVIDEFLAGS} %{PROVIDEVERSION}\\n]\\n"
-  QF="$QF [%{REQUIRENAME} %{REQUIREFLAGS} %{REQUIREVERSION}\\n]\\n"
-  QF="$QF [%{CONFLICTNAME} %{CONFLICTFLAGS} %{CONFLICTVERSION}\\n]\\n"
-  QF="$QF [%{OBSOLETENAME} %{OBSOLETEFLAGS} %{OBSOLETEVERSION}\\n]\\n"
-  check_header "$pkg"
+  grep -E "(/boot|/lib/modules|/lib/firmware|/usr/src|/var/adm/update-scripts)/[^/]*(${version_release_new_regex_l}(\$|[^/]+\$)|${version_release_new_regex_s}(\$|[^/]+\$))"
 }
 
 #usage unpackage <file> $dir
@@ -95,177 +217,215 @@ function unpackage()
             CPIO_OPTS="--extract --unconditional --preserve-modification-time --make-directories --quiet"
             rpm2cpio $file | cpio ${CPIO_OPTS}
             ;;
+        *.ipk|*.deb)
+            ar x $file
+            tar xf control.tar.gz
+            rm control.tar.gz
+            tar xf data.tar.[xg]z
+            rm data.tar.[xg]z
+            ;;
     esac
     popd 1>/dev/null
 }
 
+# Run diff command on the files
+# $1: printed info
+# $2: file1
+# $3: file2
+# $4, $5: rpm_meta_old and rpm_meta_new, for cleanup.
+function comp_file()
+{
+    echo "comparing $1"
+    if ! diff --label old-$1 --label new-$1 -au $2 $3; then
+      if test -z "$check_all"; then
+        rm $2 $3 $4 $5
+        return 1
+      fi
+      difffound=1
+    fi
+    return 0
+}
+
+# Get var's value from specfile.
+# $1: var name
+# $2: specfile
+function get_value()
+{
+    sed -n -e "/^___${1}___/,/^___${1}___/p" $2 | sed -e "/^___${1}___/d"
+}
+
+# Set version_release_old_regex_s, version_release_old_regex_l and
+# name_ver_rel_old_regex_l, also the new ones.
+function set_regex() {
+  local rel_old=${version_release_old##*-}
+  local rel_new=${version_release_new##*-}
+
+  # Short version without B_CNT
+  # release may not contain a dot
+  case "${rel_old}" in
+    *.*)
+    version_release_old_regex_s=${version_release_old%.*}
+    ;;
+    *)
+    version_release_old_regex_s=${version_release_old}
+    ;;
+  esac
+  # Remember to quote the . which is in release
+  version_release_old_regex_s=${version_release_old_regex_s//./\\.}
+  # Long version with B_CNT
+  version_release_old_regex_l=${version_release_old//./\\.}
+  name_ver_rel_old_regex_l=${name_ver_rel_old//./\\.}
+
+  case "${rel_new}" in
+    *.*)
+    version_release_new_regex_s=${version_release_new%.*}
+    ;;
+    *)
+    version_release_new_regex_s=${version_release_new}
+    ;;
+  esac
+  version_release_new_regex_s=${version_release_new_regex_s//./\\.}
+  version_release_new_regex_l=${version_release_new//./\\.}
+  name_ver_rel_new_regex_l=${name_ver_rel_new//./\\.}
+}
+
+# Trim a block starting with a keyword and ending with an empty line
+# $1: enable
+# $2: keyword
+function trim_section() {
+  if test "${1}" -gt 0 ; then
+    sed -e "/^${2}$/,/^$/d"
+  else
+    cat
+  fi
+}
+
 # Compare just the rpm meta data of two rpms
 # Returns:
 # 0 in case of same content
 # 1 in case of errors or difference
 # 2 in case of differences that need further investigation
-# Sets $files with list of files that need further investigation
-function cmp_spec ()
+# Sets ${files[@]} array with list of files that need further investigation
+function cmp_rpm_meta ()
 {
     local RES
-    local file1 file2
     local f
     local sh=$1
     local oldrpm=$2
     local newrpm=$3
+    local tmpdir="$(mktemp -d)"
+    local file1="$tmpdir/file1"
+    local file2="$tmpdir/file2"
+    local rpm_meta_old="$tmpdir/rpm-meta-old"
+    local rpm_meta_new="$tmpdir/rpm-meta-new"
 
-    QF="%{NAME}"
-    
-    # don't look at RELEASE, it contains our build number
-    QF="$QF %{VERSION} %{EPOCH}\\n"
-    QF="$QF %{SUMMARY}\\n%{DESCRIPTION}\\n"
-    QF="$QF %{VENDOR}\\n"
-    QF="$QF %{LICENSE} %{LICENSE}\\n"
-    QF="$QF %{GROUP} %{URL} %{EXCLUDEARCH} %{EXCLUDEOS} %{EXCLUSIVEARCH}\\n"
-    QF="$QF %{EXCLUSIVEOS} %{RPMVERSION} %{PLATFORM}\\n"
-    QF="$QF %{PAYLOADFORMAT} %{PAYLOADCOMPRESSOR} %{PAYLOADFLAGS}\\n"
-    
-    # XXX We also need to check the existence (but not the content (!))
-    # of SIGGPG (and perhaps the other SIG*)
-    
-    # XXX We don't look at triggers
-    
-    QF="$QF [%{VERIFYSCRIPTPROG} %{VERIFYSCRIPT}]\\n"
-    
-    # Only the first ChangeLog entry; should be enough
-    QF="$QF %{CHANGELOGTIME} %{CHANGELOGNAME} %{CHANGELOGTEXT}\\n"
-    
-    file1=`mktemp`
-    file2=`mktemp`
-    
-    check_header $oldrpm > $file1
-    check_header $newrpm > $file2
-
-    if [ -n $newrpm ]; then
-      # if the rpm is from prerelease projects, do not compare project name.
-      QF="%{DISTRIBUTION}"
-      dist=$(check_header $newrpm | sed -r 's/(.*)\/.*/\1/')
-      if ! is_prerelease_project $dist; then
-        echo "This is a prerelease project. Do not compare the project name."
-        QF="%{DISTURL}\\n"
-        echo `check_header $oldrpm | sed -r 's/.*\/(.*\/.*)/\1/'` >> $file1
-        echo `check_header $newrpm | sed -r 's/.*\/(.*\/.*)/\1/'` >> $file2
-      else
-        QF="%{DISTURL} %{DISTRIBUTION}\\n"
-        echo "This is not a prerelease project. Compare the project name."
-        check_header $oldrpm >> $file1
-        check_header $newrpm >> $file2
-      fi
+    collect_rpm_querytags
+    set_rpm_meta_global_variables $oldrpm
+
+    check_header "$QF_ALL" $oldrpm > $rpm_meta_old
+    check_header "$QF_ALL" $newrpm > $rpm_meta_new
+
+    # rpm returns 0 even in case of error
+    if test -s $rpm_meta_old && test -s $rpm_meta_new ; then
+      : some output provided, all query tags understood by rpm
+    else
+      ls -l $rpm_meta_old $rpm_meta_new
+      echo "empty 'rpm -qp' output..."
+      rm -rf "$tmpdir"
+      return 1
     fi
-    
-    # the DISTURL tag can be used as checkin ID
-    #echo "$QF"
-    echo "comparing rpmtags"
-    if ! diff -au $file1 $file2; then
-      if test -z "$check_all"; then
-        rm $file1 $file2
-        return 1
-      fi
+
+    name_new="$(get_value QF_NAME $rpm_meta_new)"
+    version_release_new="$(get_value QF_VER_REL $rpm_meta_new)"
+    name_ver_rel_new="$(get_value QF_NAME_VER_REL $rpm_meta_new)"
+
+    version_release_old="$(get_value QF_VER_REL $rpm_meta_old)"
+    name_ver_rel_old="$(get_value QF_NAME_VER_REL $rpm_meta_old)"
+
+    set_regex
+
+    # Check the whole spec file at first, return 0 immediately if they
+    # are the same.
+    trim_release_old < $rpm_meta_old > $file1
+    trim_release_new < $rpm_meta_new > $file2
+    echo "comparing the rpm tags of $name_new"
+    if diff --speed-large-files --label old-rpm-tags --label new-rpm-tags -au0 $file1 $file2; then
+      rm -rf "$tmpdir"
+      return 0
     fi
-    
-    # Remember to quote the . which is in release
-    version_release_old=$($RPM --qf "%{VERSION}-%{RELEASE}" "$oldrpm")
-    version_release_new=$($RPM --qf "%{VERSION}-%{RELEASE}" "$newrpm")
-    name_ver_rel_old=$($RPM --qf "%{NAME}-%{VERSION}-%{RELEASE}" "$oldrpm")
-    name_ver_rel_new=$($RPM --qf "%{NAME}-%{VERSION}-%{RELEASE}" "$newrpm")
-    # Short version without B_CNT
-    version_release_old_regex_s=${version_release_old%.*}
-    version_release_old_regex_s=${version_release_old_regex_s//./\\.}
-    version_release_new_regex_s=${version_release_new%.*}
-    version_release_new_regex_s=${version_release_new_regex_s//./\\.}
-    # Long version with B_CNT
-    version_release_old_regex_l=${version_release_old//./\\.}
-    version_release_new_regex_l=${version_release_new//./\\.}
-    name_ver_rel_old_regex_l=${name_ver_rel_old//./\\.}
-    name_ver_rel_new_regex_l=${name_ver_rel_new//./\\.}
+
+    get_value QF_TAGS $rpm_meta_old > $file1
+    get_value QF_TAGS $rpm_meta_new > $file2
+    if ! comp_file rpmtags $file1 $file2 $rpm_meta_old $rpm_meta_new; then
+      rm -rf "$tmpdir"
+      return 1
+    fi
+
     # This might happen when?!
     echo "comparing RELEASE"
     if [ "${version_release_old%.*}" != "${version_release_new%.*}" ] ; then
-      case $($RPM --qf '%{NAME}' "$newrpm") in
+      case $name_new in
         kernel-*)
           # Make sure all kernel packages have the same %RELEASE
           echo "release prefix mismatch"
           if test -z "$check_all"; then
+            rm -rf "$tmpdir"
             return 1
           fi
+          difffound=1
           ;;
         # Every other package is allowed to have a different RELEASE
         *) ;;
       esac
     fi
-    
-    check_provides $oldrpm | trim_release_old | sort > $file1
-    check_provides $newrpm | trim_release_new | sort > $file2
-    
-    echo "comparing PROVIDES"
-    if ! diff -au $file1 $file2; then
-      if test -z "$check_all"; then
-        rm $file1 $file2
-        return 1
-      fi
-    fi
 
-    # scripts, might contain release number
-    QF="[%{PREINPROG} %{PREIN}\\n]\\n[%{POSTINPROG} %{POSTIN}\\n]\\n[%{PREUNPROG} %{PREUN}\\n]\\n[%{POSTUNPROG} %{POSTUN}\\n]\\n"
-    check_header $oldrpm | trim_release_old > $file1
-    check_header $newrpm | trim_release_new > $file2
+    # Built packages provide the sourcerpm, for the sourcerpm itself it is "(none)"
+    [ "x$(get_value QF_SOURCERPM $rpm_meta_new)" == "x(none)" ] && is_sourcerpm=1 || is_sourcerpm=0
 
-    echo "comparing scripts"
-    if ! diff -au $file1 $file2; then
-      if test -z "$check_all"; then
-        rm $file1 $file2
-        return 1
-      fi
+    # FIXME: PROVIDE needs to be handled independent from the other tags
+    get_value QF_PROVIDES $rpm_meta_old | trim_section ${is_sourcerpm} 'PROVIDE' | trim_release_old | sort > $file1
+    get_value QF_PROVIDES $rpm_meta_new | trim_section ${is_sourcerpm} 'PROVIDE' | trim_release_new | sort > $file2
+    if ! comp_file PROVIDES $file1 $file2 $rpm_meta_old $rpm_meta_new; then
+      rm -rf "$tmpdir"
+      return 1
     fi
-    
+
+    get_value QF_SCRIPT $rpm_meta_old | trim_release_old > $file1
+    get_value QF_SCRIPT $rpm_meta_new | trim_release_new > $file2
+    if ! comp_file scripts $file1 $file2 $rpm_meta_old $rpm_meta_new; then
+      rm -rf "$tmpdir"
+      return 1
+    fi
+
     # First check the file attributes and later the md5s
-    
-    # Now the files.  We leave out mtime and size.  For normal files
-    # the size will influence the MD5 anyway.  For directories the sizes can
-    # differ, depending on which file system the package was built.  To not
-    # have to filter out directories we simply ignore all sizes.
-    # Also leave out FILEDEVICES, FILEINODES (depends on the build host),
-    # FILECOLORS, FILECLASS (normally useful but file output contains mtimes), 
-    # FILEDEPENDSX and FILEDEPENDSN. 
-    # Also FILELANGS (or?)
-    QF="[%{FILENAMES} %{FILEFLAGS} %{FILESTATES} %{FILEMODES:octal} %{FILEUSERNAME} %{FILEGROUPNAME} %{FILERDEVS} %{FILEVERIFYFLAGS} %{FILELINKTOS}\n]\\n"
-    # ??? what to do with FILEPROVIDE and FILEREQUIRE?
-
-    check_header $oldrpm | trim_release_old > $file1
-    check_header $newrpm | trim_release_new > $file2
-    
-    echo "comparing filelist"
-    if ! diff -au $file1 $file2; then
-      if test -z "$check_all"; then
-        rm $file1 $file2
-        return 1
-      fi
+    get_value QF_FILELIST $rpm_meta_old | trim_release_old > $file1
+    get_value QF_FILELIST $rpm_meta_new | trim_release_new > $file2
+    if ! comp_file filelist $file1 $file2 $rpm_meta_old $rpm_meta_new; then
+      rm -rf "$tmpdir"
+      return 1
     fi
-    
+
     # now the md5sums. if they are different, we check more detailed
     # if there are different filenames, we will already have aborted before
     # file flag 64 means "ghost", filter those out.
-    QF="[%{FILENAMES} %{FILEMD5S} %{FILEFLAGS}\n]\\n"
-    check_header $oldrpm |grep -v " 64$"| trim_release_old > $file1
-    check_header $newrpm |grep -v " 64$"| trim_release_new > $file2
-    
+    get_value QF_CHECKSUM $rpm_meta_old | grep -v " 64$" | trim_release_old > $file1
+    get_value QF_CHECKSUM $rpm_meta_new | grep -v " 64$" | trim_release_new > $file2
     RES=2
     # done if the same
+    files=()
     echo "comparing file checksum"
     if cmp -s $file1 $file2; then
       RES=0
+    else
+      # Get only files with different MD5sums
+      while read
+      do
+        : "${REPLY}"
+        files+=( "${REPLY}" )
+      done < <(diff -U0 $file1 $file2 | sed --regexp-extended -n -e '/^\+\//{s/^\+//;s/ [0-9a-f]+ [0-9]+$//;p}')
     fi
-    
-    # Get only files with different MD5sums
-    files=`diff -U0 $file1 $file2 | fgrep -v +++ | grep ^+ | cut -b2- | awk '{print $1}'`
 
-    if test -f "$sh"; then
+    if test -n "$sh"; then
       echo "creating rename script"
       # Create a temporary helper script to rename files/dirs with release in it
       for f in `$RPM --qf '[%{FILENAMES} %{FILEFLAGS}\n]\n' "$oldrpm" | grep_release_old | grep -vw 64$ | awk '{ print $1}'`
@@ -278,8 +438,23 @@ function cmp_spec ()
         echo mv -v \"new/${f}\" \"new/`echo ${f} | trim_release_new`\"
       done >> "${sh}"
     fi
-    #
-    rm $file1 $file2
+
+    rm -rf "$tmpdir"
+    [ "$difffound" = 1 ] && RES=1
     return $RES
 }
+
+function adjust_controlfile() {
+    version_release_old="`sed -ne 's/^Version: \(.*\)/\1/p' $1/control`"
+    name_ver_rel_old="`sed -n -e 's/^Package: \(.*\)/\1/p' $1/control`-`sed -n -e 's/^Version: \(.*\)/\1/p' $1/control`"
+    version_release_new="`sed -ne 's/^Version: \(.*\)/\1/p' $2/control`"
+    name_ver_rel_new="`sed -n -e 's/^Package: \(.*\)/\1/p' $2/control`-`sed -n -e 's/^Version: \(.*\)/\1/p' $2/control`"
+    set_regex
+    trim_release_old < $1/control > $1/control.fixed
+    mv $1/control.fixed $1/control
+    trim_release_new < $2/control > $2/control.fixed
+    mv $2/control.fixed $2/control
+}
+
+
 # vim: tw=666 ts=2 shiftwidth=2 et
old mode 100644 (file)
new mode 100755 (executable)
index 1ac4190..13d1e5f
 #
 # Written by Michael Matz and Stephan Coolo
 # Enhanced by Andreas Jaeger
+declare -i watchdog_host_timeout_seconds='3600'
+declare -i watchdog_touch_percent_prior_timeout='25'
+declare -i watchdog_next_touch_seconds=0
 
-FUNCTIONS=${0%/*}/functions.sh
-
-check_all=
-case $1 in
-  -a | --check-all)
-    check_all=1
-    shift
-esac
-
-if test "$#" != 2; then
-   echo "usage: $0 [-a|--check-all] old.rpm new.rpm"
-   exit 1
-fi
-
-# Always clean up on exit
-local_tmpdir=`mktemp -d`
-if test -z "${local_tmpdir}"
-then
-  exit 1
-fi
-function _exit()
+function watchdog_reset
 {
-  chmod -R u+w "${local_tmpdir}"
-  rm -rf "${local_tmpdir}"
-}
-trap _exit EXIT
-# Let further mktemp refer to private tmpdir
-export TMPDIR=$local_tmpdir
+  local uptime idle
+  local -i next_touch now
 
-self_script=$(cd $(dirname $0); echo $(pwd)/$(basename $0))
+  read uptime idle < /proc/uptime
 
-source $FUNCTIONS
+  now="${uptime%.*}"
+  next_touch=$(( ${now} + ( (${watchdog_host_timeout_seconds} * ${watchdog_touch_percent_prior_timeout}) / 100 ) ))
+  watchdog_next_touch_seconds=${next_touch}
+}
 
-oldpkg=`readlink -f $1`
-newpkg=`readlink -f $2`
-rename_script=`mktemp`
+function watchdog_touch
+{
+  local uptime idle
+  local -i next_touch now
 
-if test ! -f "$oldpkg"; then
-    echo "can't open $1"
-    exit 1
-fi
+  read uptime idle < /proc/uptime
 
-if test ! -f "$newpkg"; then
-    echo "can't open $2"
-    exit 1
-fi
+  now="${uptime%.*}"
+  if test "${now}" -lt "${watchdog_next_touch_seconds}"
+  then
+    return
+  fi
+  echo 'build-compare touching host-watchdog.'
+  watchdog_reset
+}
 
-#usage unjar <file>
-function unjar()
+function wprint
 {
-    local file
-    file=$1
-
-    if [[ $(type -p fastjar) ]]; then
-        UNJAR=fastjar
-    elif [[ $(type -p jar) ]]; then
-        UNJAR=jar
-    elif [[ $(type -p unzip) ]]; then
-        UNJAR=unzip
-    else
-        echo "ERROR: jar, fastjar, or unzip is not installed (trying file $file)"
-        exit 1
-    fi
-
-    case $UNJAR in
-        jar|fastjar)
-        # echo jar -xf $file
-        ${UNJAR} -xf $file
-        ;;
-        unzip)
-        unzip -oqq $file
-        ;;
-    esac
+  echo "$@"
+  watchdog_reset
 }
 
-# list files in directory
-#usage unjar_l <file>
-function unjar_l()
+filter_disasm()
 {
-    local file
-    file=$1
-
-    if [[ $(type -p fastjar) ]]; then
-        UNJAR=fastjar
-    elif [[ $(type -p jar) ]]; then
-        UNJAR=jar
-    elif [[ $(type -p unzip) ]]; then
-        UNJAR=unzip
-    else
-        echo "ERROR: jar, fastjar, or unzip is not installed (trying file $file)"
-        exit 1
-    fi
+  [[ $nofilter ]] && return
+  sed -e '
+    s/^ *[0-9a-f]\+://
+    s/\$0x[0-9a-f]\+/$something/
+    s/callq *[0-9a-f]\+/callq /
+    s/# *[0-9a-f]\+/#  /
+    s/\(0x\)\?[0-9a-f]\+(/offset(/
+    s/[0-9a-f]\+ </</
+    s/^<\(.*\)>:/\1:/
+    s/<\(.*\)+0x[0-9a-f]\+>/<\1 + ofs>/
+  '
+}
 
-    case $UNJAR in
-        jar|fastjar)
-        ${UNJAR} -tf $file
-        ;;
-        unzip)
-        unzip -l $file
-        ;;
-    esac
+filter_xenefi() {
+   # PE32+ executable (EFI application) x86-64 (stripped to external PDB), for MS Windows
+   perl -e "open fh, '+<', '$f'; seek fh, 0x80 + 0x08, SEEK_SET; print fh 'time'; seek fh, 0x80 + 0x58, SEEK_SET; print fh 'chck';"
 }
 
-filter_disasm()
-{
-   sed -e 's/^ *[0-9a-f]\+://' -e 's/\$0x[0-9a-f]\+/$something/' -e 's/callq *[0-9a-f]\+/callq /' -e 's/# *[0-9a-f]\+/#  /' -e 's/\(0x\)\?[0-9a-f]\+(/offset(/' -e 's/[0-9a-f]\+ </</' -e 's/^<\(.*\)>:/\1:/' -e 's/<\(.*\)+0x[0-9a-f]\+>/<\1 + ofs>/' 
+filter_pyc() {
+   perl -e '
+   my $ts_off = 4;
+   my $f = shift;
+   open fh, "+<", $f;
+   my $data;
+   die "Unexpected EOF while reading $f" if read(fh, $data, 2) < 2;
+   my $magic1 = unpack "v", $data;
+   die "Unexpected EOF while reading $f" if read(fh, $data, 2) < 2;
+   my $magic2 = unpack "v", $data;
+   die "File $f is not a compiled Python module" if $magic2 != 0x0a0d;
+   if ($magic1 >= 3392 && $magic1 < 20000) {
+     $ts_off += 4;
+     die "Unexpected EOF while reading $f" if read(fh, $data, 4) < 4;
+     my $flags = unpack "V", $data;
+     $ts_off += 8 if $flags & 0x1;
+   }
+   seek fh, $ts_off, SEEK_SET;
+   print fh "0000";
+   close fh;
+   ' "$f"
 }
 
-echo "Comparing `basename $oldpkg` to `basename $newpkg`"
+filter_dvi() {
+   # Opcodes 247: pre; i[1], num[4], den[4], mag[4], k[1], x[k]
+   perl -e "
+   my \$rec;
+   open fh, '+<', '$f';
+   my \$dummy = read fh, \$rec, 15;
+   (\$pre, \$i, \$num, \$den, \$mag, \$k) = unpack('C2 N3 C', \$rec);
+   seek fh, 15, SEEK_SET;
+   while (\$k > 0) {
+     print fh '0';
+     \$k--;
+   }
+   "
+}
 
-case $oldpkg in
-  *.rpm)
-     cmp_spec $rename_script $oldpkg $newpkg
-     RES=$?
-     case $RES in
-       0)
-          echo "RPM meta information is identical"
-          if test -z "$check_all"; then
-             exit 0
-          fi
-          ;;
-       1)
-          echo "RPM meta information is different"
-          if test -z "$check_all"; then
-             exit 1
-          fi
-          ;;
-       2)
-          echo "RPM file checksum differs."
-          RES=0
-          ;;
-       *)
-          echo "Wrong exit code!"
-          exit 1
-          ;;
-     esac
-     ;;
-esac
+filter_png() {
+  perl -e '
+  use strict;
+  use warnings;
+  my $a, my $b, my $c, my $d, my $f;
+  open ($f, "+<", shift);
+  $d = read($f, $c, 8);
+  ($a,$b) = unpack("N2", $c);
+  unless($a == 0x89504e47 && $b == 0x0d0a1a0a) {
+    die("bogus png file.");
+  }
+  sub fn {
+    my ($fd, $l) = @_;
+    my $d = sprintf("%d", $l + 4);
+    $d = pack("a$d", "");
+    print($fd $d);
+  }
+  for ($d = read($f, $c, 8); $d > 0; $d = read($f, $c, 8)) {
+    ($a,$b) = unpack("N a4", $c);
+    if ($b eq "tIME") {
+      fn($f, $a);
+    } elsif ($b eq "tEXt") {
+      $d = read($f, $c, $a);
+      $b = unpack("Z$a", $c);
+      if ($b eq "date:create" || $b eq "date:modify") {
+        $d = seek($f, -$a, 1);
+        fn($f, $a);
+      }
+    } else {
+      $d = seek($f, $a + 4, 1);
+    }
+  }
+  close($f);
+  ' "$f"
+}
 
-file1=`mktemp`
-file2=`mktemp`
+filter_emacs_lisp() {
+   sed -i -e '
+    s|^;;; .ompiled by abuild@.* on ... ... .. ..:..:.. ....|;;; compiled by abuild@buildhost on Wed Jul 01 00:00:00 2009|
+    s|^;;; from file .*\.el|;;; from file /home/abuild/rpmbuild/BUILD/anthy-9100h/src-util/elc.8411/anthy-azik.el|
+    s|^;;; emacs version .*|;;; emacs version 21.5  (beta34) "kale" XEmacs Lucid.|
+    s|^;;; bytecomp version .*|;;; bytecomp version 2.28 XEmacs; 2009-08-09.|
+    ' "$f"
+}
 
-dir=`mktemp -d`
-echo "Extracting packages"
-unpackage $oldpkg $dir/old
-unpackage $newpkg $dir/new
+filter_pdf() {
+   # PDF files contain a unique ID, remove it
+   # Format of the ID is:
+   # /ID [<9ACE247A70CF9BEAFEE15E116259BD6D> <9ACE247A70CF9BEAFEE15E116259BD6D>]
+   # with optional spaces. pdftex creates also:
+   # /CreationDate (D:20120103083206Z)
+   # /ModDate (D:20120103083206Z)
+   # and possibly XML metadata as well
+   sed -i \
+        '/obj/,/endobj/{
+           s%/ID \?\[ \?<[^>]\+> \?<[^>]\+> \?\]%/IDrandom%g;
+           s%/CreationDate \?(D:[^)]*)%/CreationDate (D: XXX)%g;
+           s%/ModDate \?(D:[^)]*)%/ModDate (D: XXX)%g;
+           s%<pdf:CreationDate>[^<]*</pdf:CreationDate>%<pdf:CreationDate>XXX</pdf:CreationDate>%g;
+           s%<pdf:ModDate>[^<]*</pdf:ModDate>%<pdf:ModDate>XXX</pdf:ModDate>%g;
+           s%<xap:CreateDate>[^<]*</xap:CreateDate>%<xap:CreateDate>XXX</xap:CreateDate>%g;
+           s%<xap:ModifyDate>[^<]*</xap:ModifyDate>%<xap:ModifyDate>XXX</xap:ModifyDate>%g;
+           s%<xap:MetadataDate>[^<]*</xap:MetadataDate>%<xap:MetadataDate>XXX</xap:MetadataDate>%g;
+        }' "$f"
+}
 
-# files is set in cmp_spec for rpms, so if RES is empty we should assume
-# it wasn't an rpm and pick all files for comparison.
-if [ -z $RES ]; then
-    oldfiles=`cd $dir/old; find . -type f`
-    newfiles=`cd $dir/new; find . -type f`
+filter_ps() {
+   sed -i -e '
+    /^%%CreationDate:[[:blank:]]/d
+    /^%%Creator:[[:blank:]]groff[[:blank:]]version[[:blank:]]/d
+    /^%DVIPSSource:[[:blank:]]/d
+   ' "$f"
+}
 
-    files=`echo -e "$oldfiles\n$newfiles" | sort -u`
-fi
+filter_mo() {
+   sed -i -e "s,POT-Creation-Date: ....-..-.. ..:..+....,POT-Creation-Date: 1970-01-01 00:00+0000," "$f"
+}
 
-cd $dir
-bash $rename_script
+filter_linuxrc_config() {
+   sed -i '/^InitrdID:/s@^.*@InitrdID: something@' "$f"
+}
 
-dfile=`mktemp`
+# call specified filter on old and new file
+filter_generic()
+{
+   filtertype=$1
+   [[ $nofilter ]] && return
+   local f
+   for f in "old/$file" "new/$file" ; do
+      eval "filter_$filtertype $f"
+   done
+}
 
-diff_two_files()
+# returns 0 if both files are identical
+# returns 1 if files differ or one is missing
+# returns 2 if files must be processed further
+verify_before_processing()
 {
-  if test ! -e old/$file; then
-    echo "Missing in old package: $file"
+  local file="$1"
+  local cmpout="$2"
+
+  if test ! -e "old/$file"; then
+    wprint "Missing in old package: $file"
     return 1
   fi
-  if test ! -e new/$file; then
-    echo "Missing in new package: $file"
+  if test ! -e "new/$file"; then
+    wprint "Missing in new package: $file"
     return 1
   fi
 
-  if cmp -s old/$file new/$file; then
+  # consider only files and symlinks
+  if test ! -f "old/$file"; then
+    return 0
+  fi
+  if test ! -f "new/$file"; then
     return 0
   fi
 
-  echo "$file differs ($ftype)"
-  hexdump -C old/$file > $file1 &
-  hexdump -C new/$file > $file2 &
-  wait
-  diff -u $file1 $file2 | head -n 200
+  if cmp -b "old/$file" "new/$file" > "${cmpout}" ; then
+    return 0
+  fi
+
+  if test -s "${cmpout}" ; then
+    # cmp produced output for futher processing
+    return 2
+  fi
+
+  # cmp failed
+  return 1
+}
+
+diff_two_files()
+{
+  local offset length
+
+  verify_before_processing "${file}" "${dfile}"
+  case "$?" in
+    0) return 0 ;;
+    1) return 1 ;;
+    *) ;;
+  esac
+
+  offset=`sed 's@^.*differ: byte @@;s@,.*@@' < $dfile`
+  wprint "$file differs at offset '$offset' ($ftype)"
+  offset=$(( ($offset >> 6) << 6 ))
+  length=512
+  diff -u \
+    --label "old $file (hex)" \
+    --label "new $file (hex)" \
+    <( hexdump -C -s $offset -n $length "old/$file" ) \
+    <( hexdump -C -s $offset -n $length "new/$file" ) | $buildcompare_head
   return 1
 }
 
@@ -194,10 +259,12 @@ trim_man_first_line()
 {
     # Handles the first line if it is like:
     #.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+    #.\" Automatically generated by Pandoc 2.9.2.1
     #.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.43.3.
     local f=$1
+    [[ $nofilter ]] && return
     sed -i -e '1{
-    s|^\.\\"[[:blank:]]\+Automatically[[:blank:]]generated[[:blank:]]by[[:blank:]]Pod::Man[[:blank:]].*|.\\" Overly verbose Pod::Man|
+    s|^\.\\"[[:blank:]]\+Automatically[[:blank:]]generated[[:blank:]]by[[:blank:]].*|.\\" Automatically generated by SomeTool|
     s|^\.\\"[[:blank:]]\+DO[[:blank:]]NOT[[:blank:]]MODIFY[[:blank:]]THIS[[:blank:]]FILE![[:blank:]]\+It[[:blank:]]was[[:blank:]]generated[[:blank:]]by[[:blank:]]help2man[[:blank:]].*|.\\" Overly verbose help2man|
     }' $f
 }
@@ -222,10 +289,7 @@ trim_man_TH()
     # .TH "GCM-CALIBRATE" "1" "03 February 2012" "" ""
     #.TH Locale::Po4a::Xml.pm 3pm "2015-01-30" "Po4a Tools" "Po4a Tools"
     local f=$1
-
-    #.TH dos2unix 1 "2016-08-30" "dos2unix" "2016-08-30"
-    sed -i -e 's|\(\.TH dos2unix.*\)"[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}"\(.*\)"[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}"|\1"uuu2000-05-05"\2"uuu2000-05-05"|g' $f
-
+    [[ $nofilter ]] && return
     # (.TH   quoted section) (quoted_date)(*)
     sed -i -e 's|^\([[:blank:]]*\.TH[[:blank:]]\+"[^"]\+"[[:blank:]]\+[^[:blank:]]\+\)[[:blank:]]\+\("[^"]\+"\)\([[:blank:]]\+.*\)\?|\1 "qq2000-01-01"\3|' $f
     # (.TH unquoted section) (quoted_date)(*)
@@ -239,13 +303,33 @@ trim_man_TH()
 strip_numbered_anchors()
 {
   # Remove numbered anchors on Docbook / HTML files.
-  # This should be save since we remove them from old and new files.
-  # A trailing </a> or </div> tag will stay also on both files.
+  #  <a id="idp270624" name=
+  #  "idp270624"></a>
+  # <a href="#ftn.id32751" class="footnote" id="id32751">
+  # <a href="#id32751" class="para">
+  # <a href="#tex">1 TeX</a>
+  # <a href="dh-manual.html#id599116">
+  # <a id="id479058">
+  # <div id="ftn.id43927" class="footnote">
+  # <div class="section" id="id46">
+
+  [[ $nofilter ]] && return
   for f in old/$file new/$file; do
-     sed -i -e 's%<[ ]*a[ ]\+name[^<]*[0-9]\+[^<]*%%g' \
-     -e 's%<[ ]*a[ ]\+href[^<]*#[^<]*[0-9]\+[^<]*%%g' \
-     -e 's%<[^<]*id="ftn\.[^<]*[0-9]\+[^<]*%%g' $f
+    sed -ie '
+      1 {
+      : N
+        $ {
+          s@\(<a[^>]\+id=\n\?"\)\(id[a-z0-9]\+\)\("[^>]*>\)@\1a_idN\3@g
+          s@\(<a[^>]\+name=\n\?"\)\(id[a-z0-9]\+\)\("[^>]*>\)@\1a_nameN\3@g
+          s@\(<a[^>]\+href="#\)\([^"]\+\)\("[^>]*>\)@\1href_anchor\3@g
+          s@\(<a[^>]\+href="[^#]\+#\)\([^"]\+\)\("[^>]*>\)@\1href_anchor\3@g
+          s@\(<div[^>]\+id="\)\([\.a-z0-9]\+\)\("[^>]*>\)@\1div_idN\3@g
+        }
+      N
+      b N
+      }' $f &
   done
+  wait
 }
 
 
@@ -256,7 +340,7 @@ check_compressed_file()
   local tmpdir=`mktemp -d`
   local ftype
   local ret=0
-  echo "$ext file with odd filename: $file"
+  wprint "$ext file with odd filename: $file"
   if test -n "$tmpdir"; then
     mkdir $tmpdir/{old,new}
     cp --parents --dereference old/$file $tmpdir/
@@ -284,11 +368,18 @@ check_compressed_file()
           xz -d new/$file.xz &
           wait
           ;;
+        zst)
+          mv old/$file{,.zst}
+          mv new/$file{,.zst}
+          zstd -d old/$file.zst &
+          zstd -d new/$file.zst &
+          wait
+          ;;
       esac
       ftype=`/usr/bin/file old/$file | sed 's@^[^:]\+:[[:blank:]]*@@'`
       case $ftype in
         POSIX\ tar\ archive)
-          echo "$ext content is: $ftype"
+          wprint "$ext content is: $ftype"
           mv old/$file{,.tar}
           mv new/$file{,.tar}
           if ! check_single_file ${file}.tar; then
@@ -296,15 +387,21 @@ check_compressed_file()
           fi
           ;;
         ASCII\ cpio\ archive\ *)
-          echo "$ext content is: $ftype"
+          wprint "$ext content is: $ftype"
           mv old/$file{,.cpio}
           mv new/$file{,.cpio}
           if ! check_single_file ${file}.cpio; then
             ret=1
           fi
           ;;
+        fifo*pipe*)
+          ftype_new="`/usr/bin/file new/$file | sed -e 's@^[^:]\+:[[:blank:]]*@@' -e 's@[[:blank:]]*$@@'`"
+          if [ "$ftype_new" != "$ftype"  ]; then
+            ret=1
+          fi
+          ;;
         *)
-          echo "unhandled $ext content: $ftype"
+          wprint "unhandled $ext content: $ftype"
           if ! diff_two_files; then
             ret=1
           fi
@@ -317,485 +414,853 @@ check_compressed_file()
   return $ret
 }
 
-check_single_file()
+# returns 0 if file should be skipped
+file_is_on_ignorelist()
 {
   local file="$1"
-  case $file in
+  local ret=0
+
+  case "${file}" in
+    # Just debug information, we can skip them
+    *.exe.mdb|*.dll.mdb) ;;
+
+    # binary dump of TeX and Metafont formats, we can ignore them for good
+    /var/lib/texmf/web2c/*/*fmt|\
+    /var/lib/texmf/web2c/metafont/*.base|\
+    /var/lib/texmf/web2c/metapost/*.mem) ;;
+
+    # ruby documentation, file just contains a timestamp and nothing else
+    */created.rid) ;;
+
+    # R binary cache of DESCRIPTION
+    /usr/lib*/R/library/*/Meta/package.rds) ;;
+
+    # binary cache of interpreted R code
+    /usr/lib*/R/library/*/R/*.rd[bx]) ;;
+
+    # LibreOffice log file
+    /usr/lib/libreoffice/solver/inc/*/deliver.log) ;;
+
+    # packaged by libguestfs
+    */ld.so.cache|*/etc/machine-id) ;;
+
+    # everything else will be processed
+    *) ret=1 ;;
+  esac
+
+  return ${ret}
+}
+
+# void
+normalize_file()
+{
+  local file="$1"
+  local f
+
+  case "$file" in
     *.spec)
-       sed -i -e "s,Release:.*$release1,Release: @RELEASE@," old/$file
-       sed -i -e "s,Release:.*$release2,Release: @RELEASE@," new/$file
-       ;;
-    *.exe.mdb|*.dll.mdb)
-       # Just debug information, we can skip them
-       echo "$file skipped as debug file."
-       return 0
-       ;;
-    *.a)
-       flist=`ar t new/$file`
-       pwd=$PWD
-       fdir=`dirname $file`
-       cd old/$fdir
-       ar x `basename $file`
-       cd $pwd/new/$fdir
-       ar x `basename $file`
-       cd $pwd
-       for f in $flist; do
-          if ! check_single_file $fdir/$f; then
-             return 1
-          fi
-       done
-       return 0
-       ;;
-    *.cpio)
-       flist=`cpio --quiet --list --force-local < "new/$file" | sort`
-       pwd=$PWD
-       fdir=$file.extract.$PPID.$$
-       mkdir old/$fdir new/$fdir
-       cd old/$fdir
-       cpio --quiet --extract --force-local < "../${file##*/}"
-       cd $pwd/new/$fdir
-       cpio --quiet --extract --force-local < "../${file##*/}"
-       cd $pwd
-       local ret=0
-       for f in $flist; do
-         if ! check_single_file $fdir/$f; then
-           ret=1
-           if test -z "$check_all"; then
-             break
-           fi
-         fi
-       done
-       rm -rf old/$fdir new/$fdir
-       return $ret
-       ;;
-    *.squashfs)
-       flist=`unsquashfs -no-progress -ls -dest '' "new/$file" | grep -Ev '^(Parallel unsquashfs:|[0-9]+ inodes )' | sort`
-       fdir=$file.extract.$PPID.$$
-       unsquashfs -no-progress -dest old/$fdir "old/$file"
-       unsquashfs -no-progress -dest new/$fdir "new/$file"
-       local ret=0
-       for f in $flist; do
-         if ! check_single_file $fdir/$f; then
-           ret=1
-           if test -z "$check_all"; then
-             break
-           fi
-         fi
-       done
-       rm -rf old/$fdir new/$fdir
-       return $ret
-       ;;
-    *.tar|*.tar.bz2|*.tar.gz|*.tgz|*.tbz2)
-       flist=`tar tf new/$file`
-       pwd=$PWD
-       fdir=`dirname $file`
-       cd old/$fdir
-       tar xf `basename $file`
-       cd $pwd/new/$fdir
-       tar xf `basename $file`
-       cd $pwd
-       local ret=0
-       for f in $flist; do
-         if ! check_single_file $fdir/$f; then
-           ret=1
-           if test -z "$check_all"; then
-             break
-           fi
-         fi
-       done
-       return $ret
-       ;;
-    *.zip|*.jar|*.war)
-       cd old
-       unjar_l ./$file |sort > flist
-       #  10-05-2010 14:39
-       sed -i -e "s, [0-9][0-9]-[0-9][0-9]-[0-9]\+ [0-9][0-9]:[0-9][0-9] , date ," flist
-       # 2012-02-03 07:59
-       sed -i -e "s, 20[0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9] , date ," flist
-       cd ../new
-       unjar_l ./$file |sort> flist
-       sed -i -e "s, [0-9][0-9]-[0-9][0-9]-[0-9]\+ [0-9][0-9]:[0-9][0-9] , date ,; " flist
-       sed -i -e "s, 20[0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9] , date ," flist
-       cd ..
-       if ! cmp -s old/flist new/flist; then
-          echo "$file has different file list"
-          diff -u old/flist new/flist
-          return 1
-       fi
-       flist=`grep date new/flist | sed -e 's,.* date ,,'`
-       pwd=$PWD
-       fdir=`dirname $file`
-       cd old/$fdir
-       unjar `basename $file`
-       cd $pwd/new/$fdir
-       unjar `basename $file`
-       cd $pwd
-       local ret=0
-       for f in $flist; do
-         if test -f new/$fdir/$f && ! check_single_file $fdir/$f; then
-           ret=1
-           if test -z "$check_all"; then
-             break
-           fi
-         fi
-       done
-       return $ret;;
-     *.pyc|*.pyo)
-        perl -e "open fh, '+<', 'old/$file'; seek fh, 4, SEEK_SET; print fh '0000';"
-        perl -e "open fh, '+<', 'new/$file'; seek fh, 4, SEEK_SET; print fh '0000';"
-        ;;
-     *.bz2)
-        bunzip2 -c old/$file > old/${file/.bz2/}
-        bunzip2 -c new/$file > new/${file/.bz2/}
-        check_single_file ${file/.bz2/}
-        return $?
-        ;;
-     *.gz)
-        gunzip -c old/$file > old/${file/.gz/}
-        gunzip -c new/$file > new/${file/.gz/}
-        check_single_file ${file/.gz/}
-        return $?
-        ;;
-     *.rpm)
-       $self_script -a old/$file new/$file
-        return $?
-        ;;
-     *png)
-        # Try to remove timestamps, only if convert from ImageMagick is installed
-        if [[ $(type -p convert) ]]; then
-          convert old/$file +set date:create +set date:modify old/${file}.$PPID.$$
-          convert new/$file +set date:create +set date:modify new/${file}.$PPID.$$
-          mv -f old/${file}.$PPID.$$ old/${file}
-          mv -f new/${file}.$PPID.$$ new/${file}
-          if ! diff_two_files; then
-            return 1
-          fi
-          return 0
-        fi
-        ;;
-     /usr/share/locale/*/LC_MESSAGES/*.mo|/usr/share/locale-bundle/*/LC_MESSAGES/*.mo)
-       for f in old/$file new/$file; do
-         sed -i -e "s,POT-Creation-Date: ....-..-.. ..:..+....,POT-Creation-Date: 1970-01-01 00:00+0000," $f
-       done
-       ;;
-     /usr/share/doc/packages/*/*.html|\
-     /usr/share/doc/kde/HTML/*/*/*.html|/usr/share/doc/*/html/*.html)
-       for f in old/$file new/$file; do
-         # texi2html output, e.g. in kvm, indent, qemu
-        sed -i -e "s|^<!-- Created on .*, 20.. by texi2html .\...|<!-- Created on August 7, 2009 by texi2html 1.82|" $f
-        sed -i -e 's|^ *This document was generated by <em>Autobuild</em> on <em>.*, 20..</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html .\...</em></a>.$|  This document was generated by <em>Autobuild</em> on <em>August 7, 2009</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html 1.82</em></a>.|' $f
-        # doxygen docu, e.g. in libssh and log4c
-        sed -i -e 's|Generated on ... ... [0-9]* [0-9]*:[0-9][0-9]:[0-9][0-9] 20[0-9][0-9] for |Generated on Mon May 10 20:45:00 2010 for |' $f
-        # Generated on Sat Aug 14 2010 16:49:48 for libssh
-        sed -i -e 's|Generated on ... ... [0-9]* 20[0-9][0-9] [0-9]*:[0-9][0-9]:[0-9][0-9] for |Generated on Mon May 10 20:45:00 2010 for |' $f
-       done
-       strip_numbered_anchors
-       ;;
-     /usr/share/javadoc/*.html |\
-     /usr/share/javadoc/*/*.html|/usr/share/javadoc/*/*/*.html)
-       strip_numbered_anchors
-       # There are more timestamps in html, so far we handle only some primitive versions.
-       for f in old/$file new/$file; do
-         # Javadoc:
-          # <head>
-          # <!-- Generated by javadoc (version 1.7.0_75) on Tue Feb 03 02:20:12 GMT 2015 -->
-          # <!-- Generated by javadoc on Tue Feb 03 00:02:48 GMT 2015 -->
-          # <meta name="date" content="2015-02-03">
-          # </head>
-          sed -i -e '
-            /^<head>/{
-              : next
-              n
-              /^<\/head>/{
-                b end_head
-              }
-              s/^\(<!-- Generated by javadoc\) \((\(build\|version\) [0-9._]\+) on ... ... .. ..:..:.. \(GMT\|UTC\) ....\) \(-->\)/\1 some-date-removed-by-build-compare \5/
-              t next
-              s/^\(<!-- Generated by javadoc\) \(on ... ... .. ..:..:.. \(GMT\|UTC\) ....\) \(-->\)/\1 some-date-removed-by-build-compare \3/
-              t next
-              s/^<meta name="date" content="[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}">/<meta name="date" content="some-date-removed-by-build-compare">/
-              b next
+      sed -i -e "s,Release:.*$release1,Release: @RELEASE@," "old/$file"
+      sed -i -e "s,Release:.*$release2,Release: @RELEASE@," "new/$file"
+      ;;
+    */xen*.efi)
+      filter_generic xenefi
+      ;;
+    *.pyc|*.pyo)
+      filter_generic pyc
+      ;;
+    *.dvi)
+      filter_generic dvi
+      ;;
+    *.png)
+      filter_generic png
+      ;;
+    /usr/share/locale/*/LC_MESSAGES/*.mo|\
+    /usr/share/locale-bundle/*/LC_MESSAGES/*.mo|\
+    /usr/share/vdr/locale/*/LC_MESSAGES/*.mo)
+      filter_generic mo
+    ;;
+    */rdoc/files/*.html)
+      # ruby documentation
+      # <td>Mon Sep 20 19:02:43 +0000 2010</td>
+      for f in old/$file new/$file; do
+        sed -i -e 's%<td>[A-Z][a-z][a-z] [A-Z][a-z][a-z] [0-9]\+ [0-9]\+:[0-9]\+:[0-9]\+ +0000 201[0-9]</td>%<td>Mon Sep 20 19:02:43 +0000 2010</td>%g' $f
+      done
+      strip_numbered_anchors
+    ;;
+    /usr/share/doc/HTML/*/*/index.cache|\
+    /usr/share/doc//HTML/*/*/*/index.cache|\
+    /usr/share/doc/kde/HTML/*/*/index.cache|\
+    /usr/share/doc/kde/HTML/*/*/*/index.cache|\
+    /usr/share/gtk-doc/html/*/*.html|\
+    /usr/share/gtk-doc/html/*/*.devhelp2)
+      # various kde and gtk packages
+      strip_numbered_anchors
+      for f in old/$file new/$file; do
+        sed -i -e '
+          /^<head>/{
+            : next
+            n
+            /^<\/head>/{
+            b end_head
             }
-            : end_head
+            s/^<meta name="generator" content="[^"]\+">/<meta name="generator" content="GTK-Doc V1.29 (XML mode)">/
+            b next
+          }
+          : end_head
           ' $f
-         # Gjdoc HtmlDoclet:
-        sed -i -e 's%Generated by Gjdoc HtmlDoclet [0-9,.]*, part of <a href="http://www.gnu.org/software/classpath/cp-tools/" title="" target="_top">GNU Classpath Tools</a>, on .*, 20.. [0-9]*:..:.. \(a\|p\)\.m\. GMT.%Generated by Gjdoc.%' $f
-        sed -i -e 's%<!DOCTYPE html PUBLIC "-//gnu.org///DTD XHTML 1.1 plus Target 1.0//EN"\(.*\)GNU Classpath Tools</a>, on [A-Z][a-z]* [0-9]*, 20?? [0-9]*:??:?? \(a|p\)\.m\. GMT.</p>%<!DOCTYPE html PUBLIC "-//gnu.org///DTD XHTML 1.1 plus Target 1.0//EN"\1GNU Classpath Tools</a>, on January 1, 2009 0:00:00 a.m. GMT.</p>%' $f
-        sed -i -e 's%<!DOCTYPE html PUBLIC "-//gnu.org///DTD\(.*GNU Classpath Tools</a>\), on [a-zA-Z]* [0-9][0-9], 20.. [0-9]*:..:.. \(a\|p\)\.m\. GMT.</p>%<!DOCTYPE html PUBLIC "-//gnu.org///DTD\1,on May 1, 2010 1:11:42 p.m. GMT.</p>%' $f
-        # deprecated-list is randomly ordered, sort it for comparison
-        case $f in
-          */deprecated-list.html)
-            sort -o $f $f
-            ;;
-        esac
-       done
-       ;;
-     /usr/share/javadoc/gjdoc.properties |\
-     /usr/share/javadoc/*/gjdoc.properties)
-       for f in old/$file new/$file; do
-        sed -i -e 's|^#[A-Z][a-z]\{2\} [A-Z][a-z]\{2\} [0-9]\{2\} ..:..:.. GMT 20..$|#Fri Jan 01 11:27:36 GMT 2009|' $f
-       done
-       ;;
-     */fonts.scale|*/fonts.dir|*/encodings.dir)
-       for f in old/$file new/$file; do
-         # sort files before comparing
-         sort -o $f $f
-       done
-       ;;
-     /var/adm/perl-modules/*)
-       for f in old/$file new/$file; do
-         sed -i -e 's|^=head2 ... ... .. ..:..:.. ....: C<Module>|=head2 Wed Jul  1 00:00:00 2009: C<Module>|' $f
-       done
-       ;;
-     /usr/share/man/man3/*3pm)
-       for f in old/$file new/$file; do
-         sed -i -e 's| 3 "20..-..-.." "perl v5....." "User Contributed Perl Documentation"$| 3 "2009-01-01" "perl v5.10.0" "User Contributed Perl Documentation"|' $f
-         trim_man_TH $f
-         trim_man_first_line $f
-       done
-       ;;
-     /usr/share/man/*/man*|/usr/share/man/man*|/usr/lib/texmf/doc/man/*/*)
-
-       for f in old/$file new/$file; do
-         trim_man_TH $f
-         trim_man_first_line $f
-         # generated by docbook xml:
-         #.\"      Date: 09/13/2010
-         sed -i -e 's|Date: [0-1][0-9]/[0-9][0-9]/201[0-9]|Date: 09/13/2010|' $f
-       done
-       ;;
-     *.elc)
-       # emacs lisp files
-       for f in old/$file new/$file; do
-         sed -i -e 's|Compiled by abuild@.* on ... ... .. ..:..:.. 20..$|compiled by abuild@buildhost on Wed Jul 01 00:00:00 2009|' $f
-       done
-       ;;
-     /var/lib/texmf/web2c/*/*fmt |\
-     /var/lib/texmf/web2c/metafont/*.base|\
-     /var/lib/texmf/web2c/metapost/*.mem)
-       # binary dump of TeX and Metafont formats, we can ignore them for good
-       echo "difference in $file ignored."
-       return 0
-       ;;
-     */libtool)
-       for f in old/$file new/$file; do
-         sed -i -e 's|^# Libtool was configured on host [A-Za-z0-9]*:$|# Libtool was configured on host x42:|' $f
-       done
-       ;;
-     /etc/mail/*cf|/etc/sendmail.cf)
-       # from sendmail package
-       for f in old/$file new/$file; do
-         # - ##### built by abuild@build33 on Thu May 6 11:21:17 UTC 2010
-         sed -i -e 's|built by abuild@[a-z0-9]* on ... ... [0-9]* [0-9]*:[0-9][0-9]:[0-9][0-9] .* 20[0-9][0-9]|built by abuild@build42 on Thu May 6 11:21:17 UTC 2010|' $f
-       done
-       ;;
-     /usr/share/doc/kde/HTML/*/*/index.cache|/usr/share/doc/kde/HTML/*/*/*/index.cache|\
-     /usr/share/gtk-doc/html/*/*.html|/usr/share/gtk-doc/html/*/*.devhelp2)
-       # various kde and gtk packages
-       strip_numbered_anchors
-       ;;
-    */created.rid)
-       # ruby documentation
-       # file just contains a timestamp and nothing else, so ignore it
-       echo "Ignore $file"
-       return 0
-       ;;
-    */rdoc/files/*.html)
-       # ruby documentation
-       # <td>Mon Sep 20 19:02:43 +0000 2010</td>
-       for f in old/$file new/$file; do
-          sed -i -e 's%<td>[A-Z][a-z][a-z] [A-Z][a-z][a-z] [0-9]\+ [0-9]\+:[0-9]\+:[0-9]\+ +0000 201[0-9]</td>%<td>Mon Sep 20 19:02:43 +0000 2010</td>%g' $f
-       done
-       strip_numbered_anchors
-       ;;
+      done
+    ;;
+    /usr/share/doc/packages/*/*.html|\
+    /usr/share/doc/packages/*/*/*.html|\
+    /usr/share/doc/*/html/*.html|\
+    /usr/share/doc/kde/HTML/*/*/*.html)
+      for f in old/$file new/$file; do
+        sed -i -e '
+          s|META NAME="Last-modified" CONTENT="[^"]\+"|META NAME="Last-modified" CONTENT="Thu Mar  3 10:32:44 2016"|
+          s|<!-- Created on [^,]\+, [0-9]\+ [0-9]\+ by texi2html [0-9\.]\+ -->|<!-- Created on July, 14 2015 by texi2html 1.78 -->|
+          s|<!-- Created on [^,]\+, [0-9]\+ by texi2html [0-9\.]\+$|<!-- Created on October 1, 2015 by texi2html 5.0|
+          s|^<!-- Created on .*, 20.. by texi2html .\...|<!-- Created on August 7, 2009 by texi2html 1.82|
+          s|This document was generated by <em>Autobuild</em> on <em>[^,]\+, [0-9]\+ [0-9]\+</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html [0-9\.]\+</em></a>.|This document was generated by <em>Autobuild</em> on <em>July, 15 2015</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html 1.78</em></a>.|
+          s|^ *This document was generated by <em>Autobuild</em> on <em>.*, 20..</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html .\...</em></a>.$|  This document was generated by <em>Autobuild</em> on <em>August 7, 2009</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html 1.82</em></a>.|
+          s|^ *This document was generated on <i>[a-zA-Z]\+ [0-9]\+, [0-9]\+</i> using <a href="http://www.nongnu.org/texi2html/"><i>texi2html [0-9\.]\+</i></a>.|  This document was generated on <i>October 1, 2015</i> using <a href="http://www.nongnu.org/texi2html/"><i>texi2html 5.0</i></a>.|
+          s|Generated on ... ... [0-9]* [0-9]*:[0-9][0-9]:[0-9][0-9] 20[0-9][0-9] for |Generated on Mon May 10 20:45:00 2010 for |
+          s|Generated on ... ... [0-9]* 20[0-9][0-9] [0-9]*:[0-9][0-9]:[0-9][0-9] for |Generated on Mon May 10 20:45:00 2010 for |
+          ' $f
+      done
+      strip_numbered_anchors
+    ;;
+    /usr/*/javadoc/*.html)
+      strip_numbered_anchors
+      # There are more timestamps in html, so far we handle only some primitive versions.
+      for f in old/$file new/$file; do
+        # Javadoc:
+        # <head>
+        # <!-- Generated by javadoc (version 1.7.0_75) on Tue Feb 03 02:20:12 GMT 2015 -->
+        # <!-- Generated by javadoc on Tue Feb 03 00:02:48 GMT 2015 -->
+        # <!-- Generated by javadoc (1.8.0_72) on Thu Mar 03 12:50:28 GMT 2016 -->
+        # <!-- Generated by javadoc (10-internal) on Wed Feb 07 06:33:41 GMT 2018 -->
+        # <meta name="dc.created" content="2019-02-07">
+        # <meta name="date" content="2015-02-03">
+        # </head>
+        sed -i -e '
+          /^<head>/{
+            : next
+            n
+            /^<\/head>/{
+            b end_head
+            }
+            s/^<!-- Generated by javadoc ([0-9._]\+) on ... ... .. ..:..:.. \(GMT\|UTC\) .... -->/<!-- Generated by javadoX (1.8.0_72) on Thu Mar 03 12:50:28 GMT 2016 -->/
+            t next
+            s/^\(<!-- Generated by javadoc\) \((\(build\|version\) [0-9._]\+) on ... ... .. ..:..:.. \(GMT\|UTC\) ....\) \(-->\)/\1 some-date-removed-by-build-compare \5/
+            t next
+            s/^\(<!-- Generated by javadoc\) ([0-9._]\+-internal) on ... ... .. ..:..:.. \(GMT\|UTC\) .... \(-->\)/\1 some-date-removed-by-build-compare \3/
+            t next
+            s/^\(<!-- Generated by javadoc\) \(on ... ... .. ..:..:.. \(GMT\|UTC\) ....\) \(-->\)/\1 some-date-removed-by-build-compare \3/
+            t next
+            s/^<meta name="dc.created" content="[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}">/<meta name="dc.created" content="some-date-removed-by-build-compare">/
+            t next
+            s/^<meta name="date" content="[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}">/<meta name="date" content="some-date-removed-by-build-compare">/
+            b next
+          }
+          : end_head
+          s%Generated by Gjdoc HtmlDoclet [0-9,.]*, part of <a href="http://www.gnu.org/software/classpath/cp-tools/" title="" target="_top">GNU Classpath Tools</a>, on .*, 20.. [0-9]*:..:.. \(a\|p\)\.m\. GMT.%Generated by Gjdoc.%
+          s%<!DOCTYPE html PUBLIC "-//gnu.org///DTD XHTML 1.1 plus Target 1.0//EN"\(.*\)GNU Classpath Tools</a>, on [A-Z][a-z]* [0-9]*, 20?? [0-9]*:??:?? \(a|p\)\.m\. GMT.</p>%<!DOCTYPE html PUBLIC "-//gnu.org///DTD XHTML 1.1 plus Target 1.0//EN"\1GNU Classpath Tools</a>, on January 1, 2009 0:00:00 a.m. GMT.</p>%
+          s%<!DOCTYPE html PUBLIC "-//gnu.org///DTD\(.*GNU Classpath Tools</a>\), on [a-zA-Z]* [0-9][0-9], 20.. [0-9]*:..:.. \(a\|p\)\.m\. GMT.</p>%<!DOCTYPE html PUBLIC "-//gnu.org///DTD\1,on May 1, 2010 1:11:42 p.m. GMT.</p>%
+          ' $f
+        # deprecated-list is randomly ordered, sort it for comparison
+        case $f in
+          */deprecated-list.html)
+            [[ $nofilter ]] || sort -o $f $f
+          ;;
+        esac
+      done
+    ;;
+    /usr/share/javadoc/gjdoc.properties|\
+    /usr/share/javadoc/*/gjdoc.properties)
+      for f in old/$file new/$file; do
+        sed -i -e 's|^#[A-Z][a-z]\{2\} [A-Z][a-z]\{2\} [0-9]\{2\} ..:..:.. GMT 20..$|#Fri Jan 01 11:27:36 GMT 2009|' $f
+      done
+    ;;
+    */fonts.scale|\
+    */fonts.dir|\
+    */encodings.dir)
+      for f in old/$file new/$file; do
+        # sort files before comparing
+        [[ $nofilter ]] || sort -o $f $f
+      done
+      ;;
+    /var/adm/perl-modules/*)
+      for f in old/$file new/$file; do
+        sed -i -e 's|^=head2 ... ... .. ..:..:.. ....: C<Module>|=head2 Wed Jul  1 00:00:00 2009: C<Module>|' $f
+      done
+      ;;
+    /usr/share/man/man3/*3pm)
+      for f in old/$file new/$file; do
+        sed -i -e 's| 3 "20..-..-.." "perl v5....." "User Contributed Perl Documentation"$| 3 "2009-01-01" "perl v5.10.0" "User Contributed Perl Documentation"|' $f
+        trim_man_TH $f
+        trim_man_first_line $f
+      done
+      ;;
+    */share/man/*|\
+    /usr/lib/texmf/doc/man/*/*)
+      for f in old/$file new/$file; do
+        trim_man_TH $f
+        trim_man_first_line $f
+        # generated by docbook xml:
+        #.\"      Date: 09/13/2010
+        # Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+        #.\"      Date: 2021-08-05
+        sed -i -e '
+          s|Date: [0-1][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]|Date: DD/MM/YYYY|
+          s|Date: [0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]|Date: YYYY-MM-DD|
+        ' $f
+      done
+      ;;
+    *.elc)
+      filter_generic emacs_lisp
+      ;;
+    */libtool)
+      for f in old/$file new/$file; do
+        sed -i -e 's|^# Libtool was configured on host [A-Za-z0-9]*:$|# Libtool was configured on host x42:|' $f
+      done
+      ;;
+    /etc/mail/*cf|\
+    /etc/sendmail.cf)
+      # from sendmail package
+      for f in old/$file new/$file; do
+        # - ##### built by abuild@build33 on Thu May 6 11:21:17 UTC 2010
+        sed -i -e 's|built by abuild@[a-z0-9]* on ... ... [0-9]* [0-9]*:[0-9][0-9]:[0-9][0-9] .* 20[0-9][0-9]|built by abuild@build42 on Thu May 6 11:21:17 UTC 2010|' $f
+      done
+      ;;
+    /usr/lib*/R/library/*/DESCRIPTION)
+      # Simulate R CMD INSTALL --built-timestamp=''
+      # Built: R 3.6.1; x86_64-suse-linux-gnu; 2019-08-13 04:19:49 UTC; unix
+      sed -i -e 's|\(Built: [^;]*; [^;]*; \)20[0-9][0-9]-[01][0-9]-[0123][0-9] [012][0-9]:[0-5][0-9]:[0-5][0-9] UTC\(; .*\)$|\1\2|' old/$file new/$file
+      ;;
     */Linux*Env.Set.sh)
-       # LibreOffice files, contains:
-       # Generated on: Mon Apr 18 13:19:22 UTC 2011
-       for f in old/$file new/$file; do
-        sed -i -e 's%^# Generated on:.*UTC 201[0-9] *$%# Generated on: Sometime%g' $f
-       done
-       ;;
-    /usr/lib/libreoffice/solver/inc/*/deliver.log)
-       # LibreOffice log file
-      echo "Ignore $file"
-      return 0
+      # LibreOffice files, contains:
+      # Generated on: Mon Apr 18 13:19:22 UTC 2011
+      for f in old/$file new/$file; do
+        sed -i -e 's%^# Generated on:.*UTC 201[0-9] *$%# Generated on: Sometime%g' $f
+      done
       ;;
-    /var/adm/update-messages/*|/var/adm/update-scripts/*)
-      # encode version-release inside
-      oldfn=`echo "$file"|sed -e s/-$release2/-$release1/;`
-
+    /var/adm/update-messages/*|\
+    /var/adm/update-scripts/*)
       # fetchmsttfonts embeds the release number in the update shell script.
-      echo sed -i -e "s/-$release1/-$release2/g;" "old/$oldfn"
-      sed -i -e "s/-$release1/-$release2/g;" "old/$oldfn"
-
-      if ! diff -u old/$oldfn new/$file; then
-           echo "$oldfn is not same as $file"
-           return 1
-      fi
-      echo "$file and $oldfn are same"
-      return 0
+      sed -i "s/${name_ver_rel_old_regex_l}/@NAME_VER_REL@/" old/$file
+      sed -i "s/${name_ver_rel_new_regex_l}/@NAME_VER_REL@/" new/$file
       ;;
     *.ps)
-      for f in "old/$file" "new/$file"; do
-        sed -i -e '
-          /^%%CreationDate:[[:blank:]]/d
-          /^%%Creator:[[:blank:]]groff[[:blank:]]version[[:blank:]]/d
-          /^%DVIPSSource:[[:blank:]]/d
-        ' "$f"
-      done
-    ;;
-    *pdf)
-      # PDF files contain a unique ID, remove it
-      # Format of the ID is:
-      # /ID [<9ACE247A70CF9BEAFEE15E116259BD6D> <9ACE247A70CF9BEAFEE15E116259BD6D>]
-      # with optional spaces. pdftex creates also:
-      # /CreationDate (D:20120103083206Z)
-      # /ModDate (D:20120103083206Z)
-      # and possibly XML metadata as well
-      for f in "old/$file" "new/$file"; do
-        sed -i \
-            '/obj/,/endobj/{
-               s%/ID \?\[ \?<[^>]\+> \?<[^>]\+> \?\]%/IDrandom%g;
-               s%/CreationDate \?(D:[^)]*)%/CreationDate (D: XXX)%g;
-               s%/ModDate \?(D:[^)]*)%/ModDate (D: XXX)%g;
-               s%<pdf:CreationDate>[^<]*</pdf:CreationDate>%<pdf:CreationDate>XXX</pdf:CreationDate>%g;
-               s%<pdf:ModDate>[^<]*</pdf:ModDate>%<pdf:ModDate>XXX</pdf:ModDate>%g;
-               s%<xap:CreateDate>[^<]*</xap:CreateDate>%<xap:CreateDate>XXX</xap:CreateDate>%g;
-               s%<xap:ModifyDate>[^<]*</xap:ModifyDate>%<xap:ModifyDate>XXX</xap:ModifyDate>%g;
-               s%<xap:MetadataDate>[^<]*</xap:MetadataDate>%<xap:MetadataDate>XXX</xap:MetadataDate>%g;
-            }' "$f"
+      filter_generic ps
+      ;;
+    *.pdf)
+      filter_generic pdf
+      ;;
+    */linuxrc.config)
+      filter_generic linuxrc_config
+      ;;
+    */etc/hosts)
+      # packaged by libguestfs
+      sed -i 's/^127.0.0.1[[:blank:]].*/127.0.0.1 hst/' "old/$file"
+      sed -i 's/^127.0.0.1[[:blank:]].*/127.0.0.1 hst/' "new/$file"
+      ;;
+    */dune-package)
+      sed -i '1s@^(lang dune [^)]\+)@(lang dune 0.0)@' "old/$file" "new/$file"
+      ;;
+  esac
+}
+
+archive_a()
+{
+  local cmd=$1
+  local file=$2
+  case "${cmd}" in
+  f)
+    test -x "$(type -P ar)" && return 0
+    echo "ERROR: ar missing for ${file}"
+    return 1
+  ;;
+  l)
+    ar t "${file}"
+    test "$?" = "0" && return 0
+    return 1
+  ;;
+  x)
+    ar x "${file}"
+    test "$?" = "0" && return 0
+    return 1
+  ;;
+  esac
+}
+
+archive_cpio()
+{
+  local cmd=$1
+  local file=$2
+  case "${cmd}" in
+  f)
+    test -x "$(type -P cpio)" && return 0
+    echo "ERROR: cpio missing for ${file}"
+    return 1
+  ;;
+  l)
+    cpio --quiet --list --force-local < "${file}"
+    test "$?" = "0" && return 0
+    return 1
+  ;;
+  x)
+    cpio --quiet --extract --force-local < "${file}"
+    test "$?" = "0" && return 0
+    return 1
+  ;;
+  esac
+}
+
+archive_squashfs()
+{
+  local cmd=$1
+  local file=$2
+  case "${cmd}" in
+  f)
+    test -x "$(type -P unsquashfs)" && return 0
+    echo "ERROR: unsquashfs missing for ${file}"
+    return 1
+  ;;
+  l)
+    unsquashfs -no-progress -ls -dest '' "${file}" | grep -Ev '^(Parallel unsquashfs:|[0-9]+ inodes )'
+    test "$?" = "0" && return 0
+    return 1
+  ;;
+  x)
+    unsquashfs -no-progress -dest "." "${file}"
+    test "$?" = "0" && return 0
+    return 1
+  ;;
+  esac
+}
+
+archive_tar()
+{
+  local cmd=$1
+  local file=$2
+  case "${cmd}" in
+  f)
+    test -x "$(type -P tar)" && return 0
+    echo "ERROR: tar missing for ${file}"
+    return 1
+  ;;
+  l)
+    tar tf "${file}"
+    test "$?" = "0" && return 0
+    return 1
+  ;;
+  x)
+    tar xf "${file}"
+    test "$?" = "0" && return 0
+    return 1
+  ;;
+  esac
+}
+
+UNJAR=
+archive_zip()
+{
+  local cmd=$1
+  local file=$2
+  case "${cmd}" in
+  f)
+    if test -x "$(type -P fastjar)"
+     then
+      UNJAR="${_}"
+    elif test -x "$(type -P jar)"
+    then
+      UNJAR="${_}"
+    elif test -x "$(type -P unzip)"
+    then
+      UNJAR="${_}"
+    else
+      echo "ERROR: jar/fastjar/unzip missing for ${file}"
+      return 1
+    fi
+    return 0
+  ;;
+  l)
+    case "${UNJAR##*/}" in
+      jar|fastjar)
+        "${UNJAR}" -tf "${file}"
+      ;;
+      unzip)
+        "${UNJAR}" -Z -1 "${file}"
+      ;;
+    esac
+    test "$?" = "0" && return 0
+    return 1
+  ;;
+  x)
+    case "${UNJAR##*/}" in
+      jar|fastjar)
+        "${UNJAR}" -xf "${file}"
+      ;;
+      unzip)
+        "${UNJAR}" -oqq "${file}"
+      ;;
+    esac
+    test "$?" = "0" && return 0
+    return 1
+  ;;
+  esac
+}
+
+# returns 0 if content is identical
+# returns 1 if at least one file differs
+# handler f returns 1 if required tool for inspection is missing
+# handler l lists content, returns 1 if tool failed
+# handler x extracts content, returns 1 if tool failed
+compare_archive()
+{
+  local file="$1"
+  local handler="$2"
+  local old="`readlink -f \"old/$file\"`"
+  local new="`readlink -f \"new/$file\"`"
+  local f
+  local -a content
+  local -i ret=1
+  local -a filelist
+
+  "${handler}" 'f' "${file}" || return 1
+
+  mkdir -p "d/old/${file}" "d/new/${file}"
+  if pushd "d" > /dev/null
+  then
+    "${handler}" 'l' "${old}" | ${sort} > 'co'
+    test "${PIPESTATUS[0]}" = "0" || return 1
+    "${handler}" 'l' "${new}" | ${sort} > 'cn'
+    test "${PIPESTATUS[0]}" = "0" || return 1
+    if cmp -s 'co' 'cn'
+    then
+      if pushd "old/${file}" > /dev/null
+      then
+        "${handler}" 'x' "${old}" || return 1
+        popd > /dev/null
+      fi
+      if pushd "new/${file}" > /dev/null
+      then
+        "${handler}" 'x' "${new}" || return 1
+        popd > /dev/null
+      fi
+      while read
+      do
+        : "${REPLY}"
+        filelist+=( "${REPLY}" )
+      done < 'cn'
+      ret=0
+      for f in "${filelist[@]}"
+      do
+        if ! check_single_file "${file}/${f}"
+        then
+          ret=1
+          if test -z "$check_all"
+          then
+            break
+          fi
+        fi
+        watchdog_touch
       done
+    else
+      wprint "$file has different file list"
+      diff -u 'co' 'cn'
+    fi
+    popd > /dev/null
+    rm -rf "d"
+  fi
+
+  return ${ret}
+}
+
+check_single_file()
+{
+  local file="$1"
+  local ret=0
+  local i
+  local failed
+  local elfdiff elf_executable_sections
+  local sections
+  local -a pipestatus
+
+  if file_is_on_ignorelist "${file}"
+  then
+    return 0
+  fi
+
+  verify_before_processing "${file}" "${dfile}"
+  case "$?" in
+    0) return 0 ;;
+    1) test -z "$check_all" && return 1 ;;
+    *) ;;
+  esac
+
+  normalize_file "${file}"
+
+  case "$file" in
+    *.a)
+      compare_archive "${file}" 'archive_a'
+      return $?
+       ;;
+    *.cpio)
+      compare_archive "${file}" 'archive_cpio'
+      return $?
+       ;;
+    *.squashfs)
+      compare_archive "${file}" 'archive_squashfs'
+      return $?
+       ;;
+    *.tar|*.tar.bz2|*.tar.gz|*.tgz|*.tbz2|*.tar.zst)
+      compare_archive "${file}" 'archive_tar'
+      return $?
+      ;;
+    *.zip|*.egg|*.jar|*.war)
+      compare_archive "${file}" 'archive_zip'
+      return $?
+      ;;
+    *.bz2)
+      bunzip2 -c old/$file > old/${file/.bz2/}
+      bunzip2 -c new/$file > new/${file/.bz2/}
+      check_single_file ${file/.bz2/}
+      return $?
+      ;;
+    *.gz)
+      gunzip -c old/$file > old/${file/.gz/}
+      gunzip -c new/$file > new/${file/.gz/}
+      check_single_file ${file/.gz/}
+      return $?
       ;;
-      */linuxrc.config)
-        echo "${file}"
-        sed -i '/^InitrdID:/s@^.*@InitrdID: something@' "old/$file"
-        sed -i '/^InitrdID:/s@^.*@InitrdID: something@' "new/$file"
+    *.zst)
+      zstd -dc old/$file > old/${file/.zst/}
+      zstd -dc new/$file > new/${file/.zst/}
+      check_single_file ${file/.zst/}
+      return $?
+      ;;
+    *.rpm)
+      $self_script -a old/$file new/$file
+      return $?
       ;;
   esac
 
-  ftype=`/usr/bin/file old/$file | sed 's@^[^:]\+:[[:blank:]]*@@'`
+  ftype=`/usr/bin/file "old/$file" | sed -e 's@^[^:]\+:[[:blank:]]*@@' -e 's@[[:blank:]]*$@@'`
   case $ftype in
-     PE32\ executable*Mono\/\.Net\ assembly*)
-       echo "PE32 Mono/.Net assembly: $file"
-       if [ -x /usr/bin/monodis ] ; then
-         monodis old/$file 2>/dev/null|sed -e 's/GUID = {.*}/GUID = { 42 }/;'> ${file1}
-         monodis new/$file 2>/dev/null|sed -e 's/GUID = {.*}/GUID = { 42 }/;'> ${file2}
-         if ! cmp -s ${file1} ${file2}; then
-           echo "$file differs ($ftype)"
-           diff -u ${file1} ${file2}
+    PE32\ executable*Mono\/\.Net\ assembly*)
+      wprint "PE32 Mono/.Net assembly: $file"
+      if [ -x /usr/bin/monodis ] ; then
+        monodis "old/$file" 2>/dev/null|sed -e 's/GUID = {.*}/GUID = { 42 }/;'> ${file1}
+         monodis "new/$file" 2>/dev/null|sed -e 's/GUID = {.*}/GUID = { 42 }/;'> ${file2}
+         if ! cmp -s "${file1}" "${file2}"; then
+           wprint "$file differs ($ftype)"
+           diff --speed-large-files -u \
+             --label "old $file (monodis)" "${file1}" \
+             --label "new $file (monodis)" "${file2}"
            return 1
          fi
        else
-         echo "Cannot compare, no monodis installed"
+         wprint "Cannot compare, no monodis installed"
          return 1
        fi
        ;;
-    ELF*executable*|ELF*[LM]SB\ relocatable*|ELF*[LM]SB\ shared\ object*)
-       objdump -d --no-show-raw-insn old/$file | filter_disasm > $file1
-       if ! test -s $file1; then
-         # objdump has no idea how to handle it
-         if ! diff_two_files; then
-           ret=1
-           break
-         fi
-       fi       
-       elfdiff=
-       sed -i -e "s,old/,," $file1
-       objdump -d --no-show-raw-insn new/$file | filter_disasm > $file2
-       sed -i -e "s,new/,," $file2
-       if ! diff -u $file1 $file2 > $dfile; then
-          echo "$file differs in assembler output"
-          head -n 200 $dfile
-          elfdiff="1"
-       fi
-       echo "" >$file1
-       echo "" >$file2
-       # Don't compare .build-id and .gnu_debuglink sections
-       sections="$(objdump -s new/$file | grep "Contents of section .*:" | sed -r "s,.* (.*):,\1,g" | grep -v -e "\.build-id" -e "\.gnu_debuglink" | tr "\n" " ")"
-       for section in $sections; do
-          objdump -s -j $section old/$file | sed "s,^old/,," > $file1
-          objdump -s -j $section new/$file | sed "s,^new/,," > $file2
-          if ! diff -u $file1 $file2 > $dfile; then
-             echo "$file differs in ELF section $section"
-             head -n 200 $dfile
-             elfdiff="1"
-          fi
-       done
-       if test -z "$elfdiff"; then
-          echo "$file: only difference was in build-id or gnu_debuglink, GOOD."
+    ELF*executable*|\
+    set?id\ ELF*executable*|\
+    ELF*[LM]SB\ relocatable*|\
+    set?id\ ELF*[LM]SB\ relocatable*|\
+    ELF*[LM]SB\ shared\ object*|\
+    set?id\ ELF*[LM]SB\ shared\ object*|\
+    ELF*[LM]SB\ pie\ executable*|\
+    set?id\ ELF*[LM]SB\ pie\ executable*)
+      local sections=($(
+      $OBJDUMP -s new/$file |
+        sed -n --regexp-extended -e '
+          /Contents of section .*:/ {
+            s,.* (.*):,-j \1,g
+            /\.build-id/d
+            /\.gnu_debuglink/d
+            /\.gnu_debugdata/d
+            /\.note\.package/d
+            /\.note\.go\.buildid/d
+            p
+          }
+        '))
+      (cd old && exec $OBJDUMP -s ${sections[@]} ./$file ) > old/$file.objdump &
+      (cd new && exec $OBJDUMP -s ${sections[@]} ./$file ) > new/$file.objdump &
+      wait
+      if ! test -s old/$file.objdump
+      then
+        wprint "ELF section: objdump failed for old/$file"
+        elfdiff='failed'
+      fi
+      if ! test -s new/$file.objdump
+      then
+        wprint "ELF section: objdump failed for new/$file"
+        elfdiff='failed'
+      fi
+      if test -z "${elfdiff}"
+      then
+        diff --speed-large-files --unified \
+          --label "old $file (objdump)" \
+          --label "new $file (objdump)" \
+          old/$file.objdump new/$file.objdump > $dfile
+        ret=$?
+        if test "$ret" != "0"
+        then
+          wprint "$file differs in ELF sections"
+          $buildcompare_head $dfile
+          elfdiff='elfdiff'
+        fi
+      fi
+      if test -z "$elfdiff"
+      then
+        rm old/$file.objdump new/$file.objdump &
+        return 0
+      fi
+      watchdog_touch
+      (cd old && exec $OBJDUMP -d --no-show-raw-insn ./$file | filter_disasm
+        echo "${PIPESTATUS[@]}" > $file1 ) > old/$file.objdump &
+      (cd new && exec $OBJDUMP -d --no-show-raw-insn ./$file | filter_disasm
+        echo "${PIPESTATUS[@]}" > $file2 ) > new/$file.objdump &
+      wait
+      read i < ${file1}
+      pipestatus=( $i )
+      if [[ ${pipestatus[*]} =~ [1-9] ]]
+      then
+        wprint "ELF disassembly: pipe command failed for old/$file"
+        elf_executable_sections='failed'
+      fi
+      read i < ${file2}
+      pipestatus=( $i )
+      if [[ ${pipestatus[*]} =~ [1-9] ]]
+      then
+        wprint "ELF disassembly: pipe command failed for new/$file"
+        elf_executable_sections='failed'
+      fi
+      if test -n "${elf_executable_sections}"
+      then
+        # objdump had no idea how to handle it
+        rm old/$file.objdump new/$file.objdump &
+        if diff_two_files; then
           return 0
-       fi
-       return 1
-       ;;
-     *ASCII*|*text*)
-       if ! cmp -s old/$file new/$file; then
-         echo "$file differs ($ftype)"
-         diff -u old/$file new/$file | head -n 200
-         return 1
-       fi
-       ;;
-     directory|setuid\ directory|setuid,\ directory|sticky,\ directory)
-       # tar might package directories - ignore them here
-       return 0
-       ;;
-     bzip2\ compressed\ data*)
-       if ! check_compressed_file "$file" "bz2"; then
-           return 1
-       fi
-       ;;
-     gzip\ compressed\ data*)
-       if ! check_compressed_file "$file" "gzip"; then
-           return 1
-       fi
-       ;;
-     XZ\ compressed\ data*)
-       if ! check_compressed_file "$file" "xz"; then
-           return 1
-       fi
-       ;;
-     POSIX\ tar\ archive)
-          mv old/$file{,.tar}
-          mv new/$file{,.tar}
-          if ! check_single_file ${file}.tar; then
-            return 1
-          fi
-       ;;
-     cpio\ archive)
-          mv old/$file{,.cpio}
-          mv new/$file{,.cpio}
-          if ! check_single_file ${file}.cpio; then
-            return 1
-          fi
-     ;;
-     Squashfs\ filesystem,*)
-        echo "$file ($ftype)"
-        mv old/$file{,.squashfs}
-        mv new/$file{,.squashfs}
-        if ! check_single_file ${file}.squashfs; then
-          return 1
         fi
-     ;;
-     symbolic\ link\ to\ *)
-       readlink "old/$file" > $file1
-       readlink "new/$file" > $file2
-       if ! diff -u $file1 $file2; then
-         echo "symlink target for $file differs"
-         return 1
-       fi
-       ;;
-     block\ special\ *)
-     ;;
-     character\ special\ *)
-     ;;
-     *)
-       if ! diff_two_files; then
-           return 1
-       fi
-       ;;
+        return 1
+      fi
+      diff --speed-large-files --unified \
+        --label "old $file (disasm)" \
+        --label "new $file (disasm)" \
+        old/$file.objdump new/$file.objdump > $dfile
+      ret=$?
+      rm old/$file.objdump new/$file.objdump &
+      if test "$ret" != "0"
+      then
+        wprint "$file differs in assembler output"
+        $buildcompare_head $dfile
+        elf_executable_sections='elf_executable_sections'
+      else
+        watchdog_touch
+      fi
+      if test -n "$elfdiff" || test -n "$elf_executable_sections"
+      then
+        return 1
+      fi
+      ;;
+    *ASCII*|*text*)
+      if ! cmp -s "old/$file" "new/$file" ; then
+        wprint "$file differs ($ftype)"
+        diff -u "old/$file" "new/$file" | $buildcompare_head
+        return 1
+      fi
+      ;;
+    directory|setuid\ directory|setuid,\ directory|sticky,\ directory)
+      # tar might package directories - ignore them here
+      return 0
+      ;;
+    bzip2\ compressed\ data*)
+      if ! check_compressed_file "$file" "bz2" ; then
+        return 1
+      fi
+      ;;
+    gzip\ compressed\ data*)
+      if ! check_compressed_file "$file" "gzip" ; then
+        return 1
+      fi
+      ;;
+    XZ\ compressed\ data*)
+      if ! check_compressed_file "$file" "xz" ; then
+        return 1
+      fi
+      ;;
+    Zstandard\ compressed\ data*)
+      if ! check_compressed_file "$file" "zst" ; then
+        return 1
+      fi
+      ;;
+    Zip\ archive\ data,*)
+      if ! compare_archive "${file}" 'archive_zip' ; then
+        return 1
+      fi
+      ;;
+    POSIX\ tar\ archive)
+      mv old/$file{,.tar}
+      mv new/$file{,.tar}
+      if ! check_single_file ${file}.tar; then
+        return 1
+      fi
+      ;;
+    cpio\ archive)
+      mv old/$file{,.cpio}
+      mv new/$file{,.cpio}
+      if ! check_single_file ${file}.cpio; then
+        return 1
+      fi
+      ;;
+    Squashfs\ filesystem,*)
+      wprint "$file ($ftype)"
+      mv old/$file{,.squashfs}
+      mv new/$file{,.squashfs}
+      if ! check_single_file ${file}.squashfs; then
+        return 1
+      fi
+      ;;
+    broken\ symbolic\ link\ to\ *|symbolic\ link\ to\ *)
+      readlink "old/$file" > $file1
+      readlink "new/$file" > $file2
+      if ! diff -u $file1 $file2; then
+        wprint "symlink target for $file differs"
+        return 1
+      fi
+      ;;
+    block\ special\ *)
+      ;;
+    character\ special\ *)
+      ;;
+    *)
+      if ! diff_two_files; then
+        return 1
+      fi
+      ;;
   esac
   return 0
 }
 
+case "${0}" in
+  */*) FUNCTIONS=${0%/*}/functions.sh ;;
+  *)   FUNCTIONS=functions.sh ;;
+esac
+: ${buildcompare_head:="head -n 200"}
+nofilter=${buildcompare_nofilter}
+sort=sort
+[[ $nofilter ]] && sort=cat
+
+check_all=
+case $1 in
+  -a | --check-all)
+    check_all=1
+    shift
+esac
+
+if test "$#" != 2; then
+   echo "usage: $0 [-a|--check-all] old.rpm new.rpm"
+   exit 1
+fi
+
+test -z $OBJDUMP && OBJDUMP=objdump
+
+# Always clean up on exit
+local_tmpdir=`mktemp -d`
+if test -z "${local_tmpdir}"
+then
+  exit 1
+fi
+function _exit()
+{
+  chmod -R u+w "${local_tmpdir}"
+  rm -rf "${local_tmpdir}"
+}
+trap _exit EXIT
+# Let further mktemp refer to private tmpdir
+export TMPDIR=$local_tmpdir
+
+self_script=$(cd $(dirname $0); echo $(pwd)/$(basename $0))
+
+source $FUNCTIONS
+
+oldpkg=`readlink -f $1`
+newpkg=`readlink -f $2`
+rename_script=`mktemp`
+
+file1=`mktemp`
+file2=`mktemp`
+dir=`mktemp -d`
+dfile=`mktemp`
+
+if test ! -f "$oldpkg"; then
+    echo "can't open $1"
+    exit 1
+fi
+
+if test ! -f "$newpkg"; then
+    echo "can't open $2"
+    exit 1
+fi
+
+echo "Comparing `basename $oldpkg` to `basename $newpkg`"
+
+case $oldpkg in
+  *.deb|*.ipk)
+    : cmp_deb_meta missing
+    RES=0
+  ;;
+  *.rpm)
+    cmp_rpm_meta "$rename_script" "$oldpkg" "$newpkg"
+    RES=$?
+    case $RES in
+    0)
+      echo "RPM meta information is identical"
+      if test -z "$check_all"; then
+        exit 0
+      fi
+      ;;
+    1)
+      echo "RPM meta information is different"
+      if test -z "$check_all"; then
+        exit 1
+      fi
+      ;;
+    2)
+      echo "RPM file checksum differs."
+      RES=0
+      ;;
+    *)
+      echo "Wrong exit code!"
+      exit 1
+      ;;
+    esac
+  ;;
+esac
+
+wprint "Extracting packages"
+unpackage $oldpkg $dir/old &
+unpackage $newpkg $dir/new &
+wait
+
+case $oldpkg in
+  *.deb|*.ipk)
+    adjust_controlfile $dir/old $dir/new
+    files=()
+    while read
+    do
+      : "${REPLY}"
+      files+=( "${REPLY}" )
+    done < <(cd ${dir} ; find old new -type f | sed -e 's/^...//' | sort -u)
+  ;;
+esac
+
+cd $dir
+bash $rename_script
+
 # We need /proc mounted for some tests, so check that it's mounted and
 # complain if not.
 PROC_MOUNTED=0
@@ -805,15 +1270,15 @@ if [ ! -d /proc/self/ ]; then
   PROC_MOUNTED=1
 fi
 
-# preserve cmp_spec result for check_all runs
+# preserve cmp_rpm_meta result for check_all runs
 ret=$RES
-for file in $files; do
-   if ! check_single_file $file; then
-       ret=1
-       if test -z "$check_all"; then
-           break
-       fi
-   fi
+for file in "${files[@]}"; do
+  if ! check_single_file "$file"; then
+    ret=1
+    if test -z "$check_all"; then
+      break
+    fi
+  fi
 done
 
 if [ "$PROC_MOUNTED" -eq "1" ]; then
@@ -821,10 +1286,8 @@ if [ "$PROC_MOUNTED" -eq "1" ]; then
   umount /proc
 fi
 
-rm $file1 $file2 $dfile $rename_script
-rm -rf $dir
 if test "$ret" = 0; then
-     echo "Package content is identical"
+  echo "Package content is identical"
 fi
 exit $ret
 # vim: tw=666 ts=2 shiftwidth=2 et
index 701ccf2..5549207 100644 (file)
 
 CMPSCRIPT=${0%/*}/pkg-diff.sh
 SCMPSCRIPT=${0%/*}/srpm-check.sh
-FUNCTIONS=${0%/*}/functions.sh
 
-check_all=1
+declare -a exit_code
+# exit_code[0]='' # binaries_differ
+# exit_code[1]='' # rpmlint_differs
+# exit_code[2]='' # appdata_differs
+# exit_code[3]='' # srcrpm_differs
+file1=`mktemp`
+file2=`mktemp`
+_x() {
+  rm -f ${file1} ${file2}
+}
+trap _x EXIT
+#
+remove_check_time_report() {
+  local f=$1
+  awk '
+    BEGIN {
+      ctr_seen=0;
+    }
+    /Check time report .*:$/ {
+      ctr_seen=1;
+      next;
+    }
+    /TOTAL[[:blank:]]+[0-9]/ {
+      if (ctr_seen == 1) {
+        ctr_seen=0;
+        next;
+      }
+    }
+    {
+      if (ctr_seen == 1) {
+        next;
+      }
+      print $0;
+    }
+  ' < "${f}"
+}
+#
+check_all=
+if test "$1" = "-a"
+then
+  check_all="-a"
+  shift
+fi
+#
 OLDDIR="$1"
 shift
 NEWDIRS="$*"
@@ -31,45 +73,34 @@ if [ -z "$NEWDIRS" ]; then
   exit 1
 fi
 
-source $FUNCTIONS
-
-first_rpm=$(find $NEWDIRS -name *.rpm | head -1)
-dist=$(rpm -qp --nodigest --nosignature --qf "%{DISTRIBUTION}" $first_rpm | sed -r 's/(.*)\/.*/\1/')
-prerelease=0
-if ! is_prerelease_project $dist; then
-  echo "This is a prerelease project. Do not check the existence of source rpm files."
-
-  prerelease=1
-  num_new_pkgs=`find $NEWDIRS -name '*.rpm' -and ! -name '*.delta.rpm' -and ! -name '*.src.rpm' | wc -l`
-  num_old_pkgs=`find $OLDDIR  -name '*.rpm' -and ! -name '*.delta.rpm' -and ! -name '*.src.rpm' | wc -l`
-  if test $num_new_pkgs != $num_old_pkgs; then
-     echo "different number of subpackages"
-     find $OLDDIR $NEWDIRS -name '*.rpm' -and ! -name '*.delta.rpm' -and ! -name '*.src.rpm'
-     exit 1
-  fi
-
-else
-  if test `find $NEWDIRS -name '*.rpm' -and ! -name '*.delta.rpm' | wc -l` != `find $OLDDIR -name '*.rpm' -and ! -name '*.delta.rpm' | wc -l`; then
-     echo "different number of subpackages"
-     find $OLDDIR $NEWDIRS -name '*.rpm' -and ! -name '*.delta.rpm'
-     exit 1
-  fi
+if test `find $NEWDIRS -name '*.rpm' -and ! -name '*.delta.rpm' | wc -l` != `find $OLDDIR -name '*.rpm' -and ! -name '*.delta.rpm' | wc -l`; then
+   echo "different number of subpackages"
+   find $OLDDIR  -name '*.rpm' -and ! -name '*.delta.rpm' -print0 | xargs -0 rpm -qp --qf '%{NAME}\n' | sort > ${file1}
+   find $NEWDIRS -name '*.rpm' -and ! -name '*.delta.rpm' -print0 | xargs -0 rpm -qp --qf '%{NAME}\n' | sort > ${file2}
+   diff -u ${file1} ${file2}
+   exit 1
+fi
 
-  osrpm=$(find "$OLDDIR" -name \*src.rpm)
-  nsrpm=$(find $NEWDIRS -name \*src.rpm)
+osrpm=$(find "$OLDDIR" -name \*src.rpm)
+nsrpm=$(find $NEWDIRS -name \*src.rpm)
 
-  if test ! -f "$osrpm"; then
-    echo no old source rpm in $OLDDIR
-    exit 1
-  fi
+if test ! -f "$osrpm"; then
+  echo no old source rpm in $OLDDIR
+  exit 1
+fi
 
-  if test ! -f "$nsrpm"; then
-    echo no new source rpm in $NEWDIRS
-    exit 1
-  fi
+if test ! -f "$nsrpm"; then
+  echo no new source rpm in $NEWDIRS
+  exit 1
+fi
 
-  echo "compare $osrpm $nsrpm"
-  bash $SCMPSCRIPT "$osrpm" "$nsrpm" || exit 1
+echo "compare $osrpm $nsrpm"
+if bash $SCMPSCRIPT $check_all "$osrpm" "$nsrpm"
+then
+  : src.rpm identical
+else
+  test -z "${check_all}" && exit 1
+  exit_code[3]='srcrpm_differs'
 fi
 
 # technically we should not all exclude all -32bit but filter for different archs,
@@ -79,15 +110,28 @@ fi
 # problem: a package can contain both noarch and arch subpackages, so we have to 
 # take care of proper sorting of NEWRPMS, e.g. noarch/x.rpm and x86_64/w.rpm since OLDRPMS 
 # has all the packages in a single directory and would sort this as w.rpm, x.rpm.
-OLDRPMS=($(find "$OLDDIR" -type f -name \*rpm -a ! -name \*src.rpm  -a ! -name \*.delta.rpm|sort|grep -v -- -32bit-|grep -v -- -64bit-|grep -v -- '-x86-.*\.ia64\.rpm'))
-NEWRPMS=($(find $NEWDIRS -type f -name \*rpm -a ! -name \*src.rpm -a ! -name \*.delta.rpm|sort --field-separator=/ --key=7|grep -v -- -32bit-|grep -v -- -64bit-|grep -v -- '-x86-.*\.ia64\.rpm'))
+find $OLDDIR  -type f -name '*.rpm' \
+  -a ! -name '*src.rpm' \
+  -a ! -name '*.delta.rpm' \
+  -a ! -name '*-32bit-*' \
+  -a ! -name '*-64bit-*' \
+  -a ! -name '*-x86-*.ia64.rpm' \
+  > ${file1}
+find $NEWDIRS -type f -name '*.rpm' \
+  -a ! -name '*src.rpm' \
+  -a ! -name '*.delta.rpm' \
+  -a ! -name '*-32bit-*' \
+  -a ! -name '*-64bit-*' \
+  -a ! -name '*-x86-*.ia64.rpm' \
+  > ${file2}
+OLDRPMS=($( sort --field-separator=/ --key=` sed -n '1s@[^/]@@gp' ${file1} | wc -c ` ${file1} ))
+NEWRPMS=($( sort --field-separator=/ --key=` sed -n '1s@[^/]@@gp' ${file2} | wc -c ` ${file2} ))
 
 # Get version-release from first RPM and keep for rpmlint check
 # Remember to quote the "." for future regexes
 ver_rel1=$(rpm -qp --nodigest --nosignature --qf "%{VERSION}-%{RELEASE}" "${OLDRPMS[0]}"|sed -e 's/\./\\./g')
 ver_rel2=$(rpm -qp --nodigest --nosignature --qf "%{VERSION}-%{RELEASE}" "${NEWRPMS[0]}"|sed -e 's/\./\\./g')
 
-SUCCESS=1
 rpmqp='rpm -qp --qf %{NAME} --nodigest --nosignature '
 for opac in ${OLDRPMS[*]}; do
   npac=${NEWRPMS[0]}
@@ -104,11 +148,7 @@ for opac in ${OLDRPMS[*]}; do
       echo "skipping -debuginfo package"
     ;;
     *)
-      bash $CMPSCRIPT "$opac" "$npac" || SUCCESS=0
-      if test $SUCCESS -eq 0 -a -z "$check_all"; then
-        echo "differences between $opac and $npac"
-        exit 1
-      fi
+      bash $CMPSCRIPT $check_all "$opac" "$npac" || exit_code[0]='binaries_differ'
     ;;
   esac
 done
@@ -118,61 +158,87 @@ if [ -n "${NEWRPMS[0]}" ]; then
   exit 1
 fi
 
+OTHERDIR=
 # Compare rpmlint.log files
 if test -d /home/abuild/rpmbuild/OTHER; then
   OTHERDIR=/home/abuild/rpmbuild/OTHER
 elif test -d /usr/src/packages/OTHER; then
   OTHERDIR=/usr/src/packages/OTHER
 else
-  echo "no OTHERDIR"
-  OTHERDIR=
+  for newdir in $NEWDIRS
+  do
+    test -f "${newdir}/rpmlint.log" || continue
+    OTHERDIR="${newdir}"
+    break
+  done
+  test -n "$OTHERDIR" || echo "no OTHERDIR"
 fi
 
 if test -n "$OTHERDIR"; then
-  if [ $prerelease -eq 1 ] ; then
-    echo "do not compare rpmlint.log if it is a prerelease project!"
+  old_log=$OLDDIR/rpmlint.log
+  new_log=$OTHERDIR/rpmlint.log
+  if test -e ${old_log} && test -e ${new_log} ; then
+    echo "comparing ${old_log} and ${new_log}"
+    # Remove --time-report from rpmlint
+    # Sort the files first since the order of messages is not deterministic
+    # Remove release from files
+    remove_check_time_report ${old_log}|sort -u|sed -e "s,$ver_rel1,@VERSION@-@RELEASE@,g" -e "s|/tmp/rpmlint\..*spec|.spec|g" > $file1
+    remove_check_time_report ${new_log}|sort -u|sed -e "s,$ver_rel2,@VERSION@-@RELEASE@,g" -e "s|/tmp/rpmlint\..*spec|.spec|g" > $file2
+    # Remove odd warning about not-hardlinked files
+    # Remove odd warning about data and time, it comes and goes
+    # Remove warning about python mtime mismatch, a republish will not help
+    # Remove odd warning about filenames, they contain VERSION-RELEASE
+    # Remove durations from progress reports
+    # Remove odd output about number of checks and packages
+    sed -i -e "
+    /: W: files-duplicate /d
+    /: W: file-contains-date-and-time /d
+    /: W: python-bytecode-inconsistent-mtime /d
+    /: W: filename-too-long-for-joliet /d
+    /: I: \(filelist-initialization\|check-completed\) /s| [0-9]\+\.[0-9] s| x.x s|
+    s/; has taken [0-9]\+\.[0-9] s/; has taken x.x s/
+    /^checks: [0-9]\+, packages: [0-9]\+/d
+    " $file1 $file2
+    if ! cmp -s $file1 $file2; then
+      echo "rpmlint.log files differ:"
+      diff -u $file1 $file2 |head -n 20
+      exit_code[1]='rpmlint_differs'
+    fi
+    rm $file1 $file2
   else
-    if test -e $OLDDIR/rpmlint.log -a -e $OTHERDIR/rpmlint.log; then
-      file1=`mktemp`
-      file2=`mktemp`
-      echo "comparing $OLDDIR/rpmlint.log and $OTHERDIR/rpmlint.log"
-      # Sort the files first since the order of messages is not deterministic
-      # Remove release from files
-      sort -u $OLDDIR/rpmlint.log|sed -e "s,$ver_rel1,@VERSION@-@RELEASE@,g" -e "s|/tmp/rpmlint\..*spec|.spec|g" > $file1
-      sort -u $OTHERDIR/rpmlint.log|sed -e "s,$ver_rel2,@VERSION@-@RELEASE@,g" -e "s|/tmp/rpmlint\..*spec|.spec|g"  > $file2
-      if ! cmp -s $file1 $file2; then
-        echo "rpmlint.log files differ:"
-        diff -u $file1 $file2 |head -n 20
-        SUCCESS=0
-      fi
-      rm $file1 $file2
-    elif test -e $OTHERDIR/rpmlint.log; then
+    if test -e "${new_log}"
+    then
+      exit_code[1]='rpmlint_new'
       echo "rpmlint.log is new"
-      SUCCESS=0
+    elif test -e "${old_log}"
+    then
+      exit_code[1]='rpmlint_old'
+      echo "rpmlint.log disappeared"
+    else
+      echo "No rpmlint.log available"
     fi
   fi
 
-  appdatas=`cd $OTHERDIR && find . -name *-appdata.xml`
+  appdatas=$(cd $OTHERDIR && find . -name "*-appdata.xml")
   for xml in $appdatas; do
     # compare appstream data
-    if test -e $OLDDIR/$xml -a -e $OTHERDIR/$xml; then
+    if test -e $OLDDIR/$xml && test -e $OTHERDIR/$xml; then
       file1=$OLDDIR/$xml
       file2=$OTHERDIR/$xml
       if ! cmp -s $file1 $file2; then
         echo "$xml files differ:"
         diff -u0 $file1 $file2 |head -n 20
-        SUCCESS=0
+        exit_code[2]='appdata_differs'
       fi
     elif test -e $OTHERDIR/$xml; then
       echo "$xml is new"
-      SUCCESS=0
+      exit_code[2]='appdata_new'
     fi
   done
 fi
-
-if test $SUCCESS -eq 0; then
+if test -n "${exit_code[*]}"; then
   exit 1
 fi
-echo 'compare validated built as identical !'
+echo 'compare validated build as identical !'
 exit 0
 # vim: tw=666 ts=2 shiftwidth=2 et
old mode 100644 (file)
new mode 100755 (executable)
index b0ceacb..722bbde
@@ -1,10 +1,11 @@
 #!/bin/bash
 #
 # Copyright (c) 2009, 2010 SUSE Linux Product GmbH, Germany.
+# Copyright (c) 2022 SUSE LLC
 # Licensed under GPL v2, see COPYING file for details.
 #
-# Written by Michael Matz and Stephan Coolo
-# Enhanced by Andreas Jaeger
+# Written by Michael Matz and Stephan Kulow
+# Enhanced by Andreas Jaeger and Dirk Müller
 
 # Compare two source RPMs
 
@@ -18,25 +19,21 @@ case $1 in
 esac
 
 if test "$#" != 2; then
-   echo "usage: $0 [-a|--check-all] old.rpm new.rpm"
-   exit 1
+  echo "usage: $0 [-a|--check-all] old.rpm new.rpm"
+  exit 1
 fi
 
 source $FUNCTIONS
 
-oldrpm=`readlink -f $1`
-newrpm=`readlink -f $2`
-
-# Get version-release from first RPM and keep for rpmlint check
-# Remember to quote the "." for future regexes
-ver_rel_old=$(rpm -qp --nodigest --nosignature --qf "%{RELEASE}" "${oldrpm}"|sed -e 's/\./\\./g')
-ver_rel_new=$(rpm -qp --nodigest --nosignature --qf "%{RELEASE}" "${newrpm}"|sed -e 's/\./\\./g')
+oldrpm=$(readlink -f $1)
+newrpm=$(readlink -f $2)
+rename_script=
 
 # For source RPMs, we can just check the metadata in the spec file
 # if those are not the same, the source RPM has changed and therefore 
 # the resulting files are needed.
 
-cmp_spec
+cmp_rpm_meta "$rename_script" "$oldrpm" "$newrpm"
 RES=$?
 case $RES in
   0)
@@ -58,41 +55,38 @@ esac
 # Now check that only the spec file has a changed release number and
 # nothing else
 
-dir=`mktemp -d`
-unrpm $oldrpm $dir/old
-unrpm $newrpm $dir/new
+dir=$(mktemp -d)
+unpackage $oldrpm $dir/old &
+unpackage $newrpm $dir/new &
 cd $dir
+wait
 
 check_single_file()
 { 
   local file=$1
   case $file in
     *.spec)
-       sed -i -e "s,Release:.*${ver_rel_old}$,Release: @RELEASE@," old/$file
-       sed -i -e "s,Release:.*${ver_rel_new}$,Release: @RELEASE@," new/$file
-       if ! cmp -s old/$file new/$file; then
-         echo "$file differs (spec file)"
-         diff -u old/$file new/$file | head -n 20
-         return 1
-       fi
-       return 0
-       ;;
+      sed -i -e 's,^Release:.*$,Release: @RELEASE@,' old/$file
+      sed -i -e 's,^Release:.*$,Release: @RELEASE@,' new/$file
+      diff --speed-large-files -su0 old/$file new/$file | head -n 20
+      return "${PIPESTATUS[0]}"
+      ;;
     *)
-       echo "$file differs"
-       # Nothing else should be changed
-       ;;
-   esac
-   return 1
+      echo "$file differs"
+      # Nothing else should be changed
+      ;;
+  esac
+  return 1
 }
 
 ret=0
-for file in $files; do
-   if ! check_single_file $file; then
-       ret=1
-       if test -z "$check_all"; then
-           break
-       fi
-   fi
+for file in "${files[@]}"; do
+  if ! check_single_file $file; then
+    ret=1
+    if test -z "$check_all"; then
+      break
+    fi
+  fi
 done
 
 rm -rf $dir