diff -Nru tzdata-2024a/debian/changelog tzdata-2024a/debian/changelog --- tzdata-2024a/debian/changelog 2024-02-21 13:37:28.000000000 +0100 +++ tzdata-2024a/debian/changelog 2024-04-30 23:24:22.000000000 +0200 @@ -1,3 +1,15 @@ +tzdata (2024a-0ubuntu0.23.10.1) mantic; urgency=medium + + * Do not replace CET, CST6CDT, EET, EST*, HST, MET, MST*, PST8PDT, WET. + The replacements differed in using daylight saving. (LP: #2055718) + * Fix updating US/Indiana-Starke to America/Indiana/Knox + * Correct timezone symlinks when using BACKWARD=backward PACKRATDATA=backzone + to fix (at least) the timezone symlinks Africa/Asmera, + Antarctica/South_Pole, Iceland, Pacific/Ponape, and Pacific/Truk. + * test_timezone_conversions: Check symlink targets + + -- Benjamin Drung Tue, 30 Apr 2024 23:24:22 +0200 + tzdata (2024a-0ubuntu0.23.10) mantic; urgency=medium * New upstream version (LP: #2052739): diff -Nru tzdata-2024a/debian/patches/Correct-timezone-symlinks-when-using-BACKWARD-backward-PA.patch tzdata-2024a/debian/patches/Correct-timezone-symlinks-when-using-BACKWARD-backward-PA.patch --- tzdata-2024a/debian/patches/Correct-timezone-symlinks-when-using-BACKWARD-backward-PA.patch 1970-01-01 01:00:00.000000000 +0100 +++ tzdata-2024a/debian/patches/Correct-timezone-symlinks-when-using-BACKWARD-backward-PA.patch 2024-04-30 23:23:07.000000000 +0200 @@ -0,0 +1,74 @@ +From: Benjamin Drung +Date: Wed, 3 Apr 2024 15:14:50 +0200 +Subject: Correct timezone symlinks when using BACKWARD=backward + PACKRATDATA=backzone + +When using BACKWARD=backward PACKRATDATA=backzone the symlinks might +point to the incorrect file (e.g. Africa/Asmera points to Africa/Nairobi +instead of Africa/Asmara). + +Move the link to link feature from vanguard to main dataform to produce +correct symlink (e.g. Africa/Asmera -> Africa/Asmara) in this case. Drop +those link from `backward` that would cause symlinks to symlinks. + +See https://bugs.launchpad.net/ubuntu/+source/tzdata/+bug/2062522 + +Forwarded: https://mm.icann.org/pipermail/tz/2024-April/058853.html +--- + backward | 6 +++--- + ziguard.awk | 4 ++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/backward b/backward +index 65c711b..08c95b1 100644 +--- a/backward ++++ b/backward +@@ -30,7 +30,7 @@ + # Pre-1993 naming conventions + + # Link TARGET LINK-NAME #= TARGET1 +-Link Australia/Sydney Australia/ACT #= Australia/Canberra ++Link Australia/Sydney Australia/ACT + Link Australia/Lord_Howe Australia/LHI + Link Australia/Sydney Australia/NSW + Link Australia/Darwin Australia/North +@@ -40,7 +40,7 @@ Link Australia/Hobart Australia/Tasmania + Link Australia/Melbourne Australia/Victoria + Link Australia/Perth Australia/West + Link Australia/Broken_Hill Australia/Yancowinna +-Link America/Rio_Branco Brazil/Acre #= America/Porto_Acre ++Link America/Rio_Branco Brazil/Acre + Link America/Noronha Brazil/DeNoronha + Link America/Sao_Paulo Brazil/East + Link America/Manaus Brazil/West +@@ -101,7 +101,7 @@ Link America/Mazatlan Mexico/BajaSur + Link America/Mexico_City Mexico/General + Link Pacific/Auckland NZ + Link Pacific/Chatham NZ-CHAT +-Link America/Denver Navajo #= America/Shiprock ++Link America/Denver Navajo + Link Asia/Shanghai PRC + Link Europe/Warsaw Poland + Link Europe/Lisbon Portugal +diff --git a/ziguard.awk b/ziguard.awk +index 7a3404f..f6b8d24 100644 +--- a/ziguard.awk ++++ b/ziguard.awk +@@ -340,7 +340,7 @@ function make_linkline(oldline, target, linkname, oldtarget, comment, \ + return "Link\t" target "\t" replsuffix comment + } + +-/^Link/ && $4 == "#=" && DATAFORM == "vanguard" { ++/^Link/ && $4 == "#=" && (DATAFORM != "rearguard") { + $0 = make_linkline($0, $5, $3, $2) + } + +@@ -378,7 +378,7 @@ function cut_link_chains_short( \ + } + + END { +- if (DATAFORM != "vanguard") { ++ if (DATAFORM == "rearguard") { + cut_link_chains_short() + } + for (i = 1; i <= NR; i++) diff -Nru tzdata-2024a/debian/patches/series tzdata-2024a/debian/patches/series --- tzdata-2024a/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 +++ tzdata-2024a/debian/patches/series 2024-04-30 23:23:07.000000000 +0200 @@ -0,0 +1 @@ +Correct-timezone-symlinks-when-using-BACKWARD-backward-PA.patch diff -Nru tzdata-2024a/debian/tests/python tzdata-2024a/debian/tests/python --- tzdata-2024a/debian/tests/python 2024-02-21 13:34:01.000000000 +0100 +++ tzdata-2024a/debian/tests/python 2024-04-30 23:23:07.000000000 +0200 @@ -28,6 +28,12 @@ return backwards_links +def read_link(link: pathlib.Path) -> pathlib.Path: + """Return the absolute path to which the symbolic link points.""" + destination = link.parent / link.readlink() + return pathlib.Path(os.path.normpath(destination)) + + class TestZoneinfo(unittest.TestCase): """Test timezones using Python's zoneinfo module.""" @@ -132,6 +138,28 @@ future = now + datetime.timedelta(days=30 * 6) self._assert_equal_zones_at_date(future, tz_link, tz_target) + def assert_not_symlink_to_symlink(self, timezone_path: pathlib.Path) -> None: + """Assert that the timezone is not a symlink to another symlink.""" + if not timezone_path.is_symlink(): + return + destination = read_link(timezone_path) + if not destination.is_symlink(): + return + self.fail( + f"Symlink to symlink found: {timezone_path} -> {destination}" + f" -> {read_link(destination)}" + ) + + def test_no_symlinks_to_symlinks(self) -> None: + """Check that no timezone is a symlink to another symlink.""" + for timezone in sorted(zoneinfo.available_timezones()): + if timezone == "localtime": + continue + with self.subTest(timezone): + for tzpath in zoneinfo.TZPATH: + timezone_path = pathlib.Path(tzpath) / timezone + self.assert_not_symlink_to_symlink(timezone_path) + def test_timezones(self) -> None: """Test all zones to load, have a name, and have a reasonable offset.""" for zone in zoneinfo.available_timezones(): @@ -168,6 +196,7 @@ date = datetime.datetime(2024, 3, 2, tzinfo=tzinfo) self.assertEqual(self._hours(date.utcoffset()), 5) + def main() -> None: """Run unit tests in verbose mode.""" argv = sys.argv.copy() diff -Nru tzdata-2024a/debian/test_timezone_conversions tzdata-2024a/debian/test_timezone_conversions --- tzdata-2024a/debian/test_timezone_conversions 2024-02-03 20:07:42.000000000 +0100 +++ tzdata-2024a/debian/test_timezone_conversions 2024-04-30 23:21:48.000000000 +0200 @@ -5,6 +5,7 @@ """Check convert_timezone from tzdata.config for consistency.""" import argparse +import functools import logging import pathlib import re @@ -47,6 +48,7 @@ assert match, f"convert_timezone function not found in {tzdata_config}" self.convert_timezone = match.group(0) + @functools.lru_cache(maxsize=8192) def __call__(self, timezone: str) -> str: shell_script = f"{self.convert_timezone}\nconvert_timezone '{timezone}'\n" shell = subprocess.run( @@ -57,17 +59,18 @@ ) return shell.stdout.strip() - def filter_converted_timezones(self, timezones: set[str]) -> set[str]: - """Return set of timezones that will be converted by convert_timezone.""" - converted = set() + def filter_converted_timezones(self, timezones: set[str]) -> dict[str, str]: + """Return dict of timezones that will be converted by convert_timezone.""" + converted = {} for timezone in timezones: - if self(timezone) != timezone: - converted.add(timezone) + conversion = self(timezone) + if conversion != timezone: + converted[timezone] = conversion return converted def filter_unconverted_timezones(self, timezones: set[str]) -> set[str]: """Return set of timezones that will not be converted by convert_timezone.""" - return timezones - self.filter_converted_timezones(timezones) + return timezones - set(self.filter_converted_timezones(timezones)) def get_targets(self) -> set[str]: """Return set of conversion targets.""" @@ -115,6 +118,27 @@ return debconf_choices +def _check_symlink(source: str, target: str) -> bool: + """Check if the given timezone source symlinks to the given target.""" + for tzpath in zoneinfo.TZPATH: + timezone = pathlib.Path(tzpath) / source + if timezone.exists(): + expected_target = pathlib.Path(tzpath) / target + return timezone.resolve() == expected_target.resolve() + return True + + +def check_symlinks(timezones: dict[str, str]) -> set[str]: + """Check timezone replacements are identical to the symlinks on disk.""" + mismatch = set() + for source, target in timezones.items(): + if source.startswith("right/"): + continue + if not _check_symlink(source, target): + mismatch.add(source) + return mismatch + + def existing_dir_path(string: str) -> pathlib.Path: """Convert string to existing dir path or raise ArgumentTypeError.""" path = pathlib.Path(string) @@ -160,7 +184,7 @@ conversion_targets = convert_timezone.get_targets() failures = 0 - converted = convert_timezone.filter_converted_timezones(selectable) + converted = set(convert_timezone.filter_converted_timezones(selectable)) if converted: logger.error( "Following %i timezones can be selected, but will be converted:\n%s", @@ -206,6 +230,16 @@ ) failures += 1 + mismatch = check_symlinks(convert_timezone.filter_converted_timezones(available)) + if mismatch: + logger.error( + "Following %i timezones are converted," + " but they do not match their symlink targets:\n%s", + len(mismatch), + "\n".join(sorted(mismatch)), + ) + failures += 1 + return failures diff -Nru tzdata-2024a/debian/tzdata.config tzdata-2024a/debian/tzdata.config --- tzdata-2024a/debian/tzdata.config 2024-02-03 20:07:42.000000000 +0100 +++ tzdata-2024a/debian/tzdata.config 2024-04-30 23:21:48.000000000 +0200 @@ -23,13 +23,13 @@ "America/Cordoba" | "America/Rosario") echo "America/Argentina/Cordoba" ;; - "America/Fort_Wayne" | "America/Indianapolis" | "EST" | "SystemV/EST5" | "US/East-Indiana" | "US/Indiana-Starke") + "America/Fort_Wayne" | "America/Indianapolis" | "SystemV/EST5" | "US/East-Indiana") echo "America/Indiana/Indianapolis" ;; "America/Jujuy") echo "America/Argentina/Jujuy" ;; - "America/Knox_IN") + "America/Knox_IN" | "US/Indiana-Starke") echo "America/Indiana/Knox" ;; "America/Louisville") @@ -140,31 +140,25 @@ "Canada/Yukon") echo "America/Whitehorse" ;; - "CET" | "MET") - echo "Europe/Paris" - ;; "Chile/Continental") echo "America/Santiago" ;; "Chile/EasterIsland") echo "Pacific/Easter" ;; - "CST6CDT" | "SystemV/CST6CDT" | "US/Central") + "SystemV/CST6CDT" | "US/Central") echo "America/Chicago" ;; "Cuba") echo "America/Havana" ;; - "EET") - echo "Europe/Helsinki" - ;; "Egypt") echo "Africa/Cairo" ;; "Eire") echo "Europe/Dublin" ;; - "EST5EDT" | "SystemV/EST5EDT" | "US/Eastern") + "SystemV/EST5EDT" | "US/Eastern") echo "America/New_York" ;; "Europe/Kiev") @@ -197,7 +191,7 @@ "Hongkong") echo "Asia/Hong_Kong" ;; - "HST" | "SystemV/HST10" | "US/Hawaii") + "SystemV/HST10" | "US/Hawaii") echo "Pacific/Honolulu" ;; "Iceland") @@ -230,10 +224,10 @@ "Mexico/General") echo "America/Mexico_City" ;; - "MST" | "SystemV/MST7" | "US/Arizona") + "SystemV/MST7" | "US/Arizona") echo "America/Phoenix" ;; - "MST7MDT" | "Navajo" | "SystemV/MST7MDT" | "US/Mountain") + "Navajo" | "SystemV/MST7MDT" | "US/Mountain") echo "America/Denver" ;; "NZ") @@ -254,13 +248,13 @@ "Poland") echo "Europe/Warsaw" ;; - "Portugal" | "WET") + "Portugal") echo "Europe/Lisbon" ;; "PRC") echo "Asia/Shanghai" ;; - "PST8PDT" | "SystemV/PST8PDT" | "US/Pacific") + "SystemV/PST8PDT" | "US/Pacific") echo "America/Los_Angeles" ;; "ROC")