From c178beec283ea5815767082cfe5a6dca4dc54b91 Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Wed, 16 Sep 2026 23:20:10 -0500 Subject: [PATCH] Don't drop most of the commit date from ./mach vendor --check-for-update for some hosts `check_for_update` splits mach's " " output on every space and keeps the second field. For a github-hosted library that second field is the whole timestamp: 3f3735e3f39c68d33104add994bfe5d055b32e17 2026-09-09T17:56:48Z googlesource reports commit dates with spaces in them, so there the second field is only the weekday and the rest of the date is thrown away: 3f3735e3f39c68d33104add994bfe5d055b32e17 Wed Sep 09 17:56:48 2026 dateutil resolves a bare "Wed" against today's date, which is how https://bugzilla.mozilla.org/show_bug.cgi?id=2070891, filed on 2026-09-10 for a commit made on 2026-09-09, ended up titled "from 2026-09-16 00:00:00": the next Wednesday, at midnight. libvpx, aom, irregexp and chromium-cdm are affected the same way. host_git.py has the same problem more quietly: `git show --format=%ci` gives "2026-09-16 23:20:10 -0500", so there we kept the date and threw away the time. Rather than make every host agree on one format, parse whatever the host reports; dateutil already copes with all of them. --- components/mach_vendor.py | 6 +++-- test.py | 3 ++- tests/mach_vendor.py | 53 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 tests/mach_vendor.py diff --git a/components/mach_vendor.py b/components/mach_vendor.py index 88493dd0..77ca5a6b 100644 --- a/components/mach_vendor.py +++ b/components/mach_vendor.py @@ -35,8 +35,10 @@ def check_for_update(self, library): if not result: return (None, None) - parts = result.split(" ") - return (parts[0], string_date_to_uniform_string_date(parts[1])) + # ./mach vendor prints " ", and the timestamp is not + # space-free on every host (googlesource: "Wed Sep 09 17:56:48 2026"). + revision, timestamp = result.split(" ", 1) + return (revision, string_date_to_uniform_string_date(timestamp)) @logEntryExit def vendor(self, library, revision): diff --git a/test.py b/test.py index ed608d16..34c463ac 100755 --- a/test.py +++ b/test.py @@ -21,7 +21,8 @@ "library", "lambda_capture", "class_passing", - "frequency" + "frequency", + "mach_vendor" ] modules = [] diff --git a/tests/mach_vendor.py b/tests/mach_vendor.py new file mode 100644 index 00000000..3c014235 --- /dev/null +++ b/tests/mach_vendor.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import sys +import unittest + +sys.path.append(".") +sys.path.append("..") + +from components.logging import SimpleLoggerConfig +from components.mach_vendor import VendorProvider +from components.utilities import Struct +from tests.mock_commandprovider import TestCommandProvider + +LIBRARY = Struct(**{'yaml_path': 'media/libyuv/moz.yaml'}) +REVISION = "3f3735e3f39c68d33104add994bfe5d055b32e17" + + +class TestVendorProvider(unittest.TestCase): + def _check_for_update(self, mach_output): + """Run check_for_update against a mocked `./mach vendor` stdout.""" + commandProvider = TestCommandProvider({ + 'test_mappings': { + "./mach vendor --check-for-update": lambda: mach_output + } + }) + commandProvider.update_config(SimpleLoggerConfig) + + vendorProvider = VendorProvider({}) + vendorProvider.update_config(dict(SimpleLoggerConfig, CommandProvider=commandProvider)) + return vendorProvider.check_for_update(LIBRARY) + + def testGooglesourceTimestamp(self): + # googlesource reports commit dates in git's default format, so the + # timestamp field contains spaces and must not be split on them. + self.assertEqual( + self._check_for_update(REVISION + " Wed Sep 09 17:56:48 2026"), + (REVISION, "2026-09-09 17:56:48")) + + def testISO8601Timestamp(self): + self.assertEqual( + self._check_for_update(REVISION + " 2026-09-09T17:56:48Z"), + (REVISION, "2026-09-09 17:56:48")) + + def testNoUpdateAvailable(self): + self.assertEqual(self._check_for_update(""), (None, None)) + + +if __name__ == "__main__": + unittest.main(verbosity=0)