Skip to content

Consider equal timestamps to be outdated#4833

Open
sigurdm wants to merge 12 commits into
dart-lang:masterfrom
sigurdm:timestamp_equals
Open

Consider equal timestamps to be outdated#4833
sigurdm wants to merge 12 commits into
dart-lang:masterfrom
sigurdm:timestamp_equals

Conversation

@sigurdm
Copy link
Copy Markdown
Contributor

@sigurdm sigurdm commented May 28, 2026

On windows the timestamp resolution is quite poor, and two files having same timestamp can easily happen.
We cannot conclude ordering when the timestamps are equal, and should therefore not use the fast-path.

Using dart setMtime also gets a poor resolution, this can result in the touched file being seen as actually older than the new one, so we shell out to touch where available.

sigurdm added 12 commits May 28, 2026 14:15
Treat identical/equal timestamps (common under low timestamp filesystem
resolutions, especially on Windows) as potentially out-of-date. This
forces fallback to content-level validation checks rather than silently
ignoring modifications within the same clock tick.

- Fall back to isLockFileUpToDate and isPackageConfigUpToDate when timestamps are equal.
- Track whether a dependency was strictly newer, and only touch pubspec.lock or package_config.json if so, preventing tooling cascading invalidation when nothing has changed.
- Optimize test suite by removing unnecessary 1-second sleeps from standard tests, yielding a 68% speedup.
…fterSecond

Introduce isAfterSecond to ignore millisecond/microsecond precision variations when
comparing timestamps. This fully resolves subtle filesystem/runtime truncation bugs where
manually set modification times (e.g., setLastModifiedSync) are truncated to seconds (.000)
while automatic OS writes preserve sub-second precision, causing touched files to incorrectly
look older than automatically written files.

Also add a comprehensive comment explaining the purpose of pubspecStrictlyNewer.
Fix a pre-existing workspace bug in isPackagePathsMappingUpToDateWithLockfile where relative
package config paths were resolved relative to the sub-package's directory instead of the
workspaceRoot, causing path mapping checks to incorrectly reject workspace packages.

- Declare root and workspaceRoot closure-captured at the start of isResolutionUpToDate.
- Initialize workspaceRoot once the workspace root directory (rootDir) is finalized.
- Resolve packageConfig paths relative to workspaceRoot.path and allow all workspace packages in packagePathsMapping.keys.
Handle language version validation checks for workspace packages inside the package config
up-to-date check. Since workspace packages are not resolved in lockFile.packages, looking up
their PackageId was throwing an assertion error. We now resolve and compare their language
version directly using transitive workspace members from workspaceRoot.
Traverse parent directories upward from the working directory (dir) to find the nearest
enclosing package directory containing a pubspec.yaml, and load the root package from there.
This prevents crashes when running pub commands inside sub-directories (like workspace package
groupings or lib/src) that do not contain a pubspec.yaml themselves.
Revert isAfterSecond back to high-precision isAfter in entrypoint.dart. Instead, resolve
sub-second timestamp truncation flakiness by shelling out to the system 'touch' utility
on POSIX platforms (Linux/macOS). The system 'touch' command preserves full sub-second/microsecond
precision, eliminating any discrepancy between manual Dart setLastModifiedSync writes and
automatic OS file writes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant