Skip to content

feat: remove input hash from lockfile#5011

Merged
ruben-arts merged 26 commits intoprefix-dev:bas/wip/develop-dependenciesfrom
nichmor:feat/remove-input-hash-from-lockfile
Dec 16, 2025
Merged

feat: remove input hash from lockfile#5011
ruben-arts merged 26 commits intoprefix-dev:bas/wip/develop-dependenciesfrom
nichmor:feat/remove-input-hash-from-lockfile

Conversation

@nichmor
Copy link
Contributor

@nichmor nichmor commented Nov 30, 2025

Description

The general idea is that we remove writing/reading the input_hash in the lockfile.
Instead, we compute/ask for the source metadata, and then compare if depends, build_string, and version are the same as the locked source record.

Also, in this PR, we change the locking of the build metadata cache because we are having a deadlock. Instead, we are using optimistic locking instead of pessimistic one - this means that we don't hold the rwlock anymore, but instead record a cache version and verify it when trying to write.

How Has This Been Tested?

AI Disclosure

  • This PR contains AI-generated content.
    • I have tested any AI-generated content in my PR.
    • I take responsibility for any AI-generated content in my PR.

Tools: Claude

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added sufficient tests to cover my changes.

@nichmor nichmor force-pushed the feat/remove-input-hash-from-lockfile branch from eec42c7 to 0e2c540 Compare November 30, 2025 18:36
@nichmor nichmor changed the title Feat/remove input hash from lockfile feat: remove input hash from lockfile Nov 30, 2025
@nichmor nichmor marked this pull request as ready for review December 4, 2025 08:27
Copy link
Contributor

@baszalmstra baszalmstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this and it seems to work as expected, great work!

The only thing missing for me, is that some of the satisfiability tests are now a bit nonsense. I would like to see a test that is satisfiable where the source locked information is satisfiable and another where it is not. You can use the passthrough backend.

@ruben-arts
Copy link
Contributor

What I've been testing with this new feature:

  • Test the [dev] feature installation locally and in CI on this project: add the [dev] table ruben-arts/ros_workspace#6 👍
  • Test normal pixi installation in this project ^ 👍
  • Test breaking the env by removing metadata files. Works 👍
  • Comparing source_metadata-v0 to metadata-v0 for inconsistencies. None found 👍
  • Test --locked with updating package.run-dependencies (works as expected, not locked when adding run-deps but locked when changing (metadata) code) 👍
  • Test --frozen, correctly rebuilds but doesn't install, without errors 👍
  • Ran install of all examples. 👍
  • Testing projects with backends from source, encountered ╰─▶ ⚠ the operation was cancelled error but can't reproduce after a metadata cleanup.
  • Walked into exactly this issue: Switching from remote to local package does not refresh lockfile #5065 but that is not related to this change.
Full `operation was cancelled` error ``` ❯ pixi i -vv WARN pixi_core::workspace::discovery: Using local manifest /Users/rubenarts/envs/demos/pixi.toml rather than /Users/rubenarts/dev/pixi/pixi.toml from environment variable `PIXI_PROJECT_MANIFEST` DEBUG pixi_config: Loading config from /etc/pixi/config.toml DEBUG pixi_config: Loading config from /Users/rubenarts/Library/Application Support/pixi/config.toml DEBUG pixi_config: Loaded config from: /Users/rubenarts/Library/Application Support/pixi/config.toml DEBUG pixi_config: Loading config from /Users/rubenarts/.pixi/config.toml DEBUG pixi_config: Loaded config from: /Users/rubenarts/.pixi/config.toml DEBUG pixi_config: Loading config from /Users/rubenarts/envs/demos/.pixi/config.toml DEBUG pixi_config: Failed to load local config: /Users/rubenarts/envs/demos/.pixi/config.toml (error: no file was found at /Users/rubenarts/envs/demos/.pixi/config.toml) DEBUG pixi_core::environment: verifying prefix location is unchanged, with prefix file: /Users/rubenarts/envs/demos/.pixi/envs/conda-meta/pixi_env_prefix DEBUG pixi_utils::reqwest: Using mirrors: {Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("my.private-channel")), port: None, path: "/", query: None, fragment: None }: [Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("prefix.dev")), port: None, path: "/ruben-arts", query: None, fragment: None }]} DEBUG backend-metadata{manifest_source=Path(PinnedPathSpec { path: Unix(Utf8PathBuf { _encoding: "unix", inner: "action_tutorials/action_tutorials_cpp" }) }) build_source=None platform=osx-arm64}: pixi_command_dispatcher::build_backend_metadata: metadata cache disabled for backend backend=pixi-build-ros reason="mutable-environment" command_kind="mutable-environment" WARN backend-metadata{manifest_source=Path(PinnedPathSpec { path: Unix(Utf8PathBuf { _encoding: "unix", inner: "action_tutorials/action_tutorials_cpp" }) }) build_source=None platform=osx-arm64}: pixi_command_dispatcher::build_backend_metadata: metadata cache disabled for build backend 'pixi-build-ros' (system/path-based backends always regenerate metadata) DEBUG pixi_command_dispatcher::instantiate_tool_env: Installing tool env for: pixi-build-ros DEBUG pixi_command_dispatcher::instantiate_tool_env: Installing tool env for: pixi-build-ros DEBUG solve{name="pixi-build-ros" platform=osx-arm64}: pixi_utils::reqwest: instantiating reqwest Client took 88.785042ms DEBUG pixi_glob::glob_set::walk: Determining hidden folder handling: user_includes_hidden=false has_negation_for_all_folders=false search_all_hidden=false requested_everything=false DEBUG pixi_glob::glob_set::walk: Determining hidden folder handling: user_includes_hidden=false has_negation_for_all_folders=false search_all_hidden=false requested_everything=false DEBUG pixi_glob::glob_set::walk: glob pass completed include="recipe.yaml, variants.yaml" excludes="" matched=1 elapsed_ms=2 root="/Users/rubenarts/dev/pixi-build-backends/recipe/pixi-build-api-version" DEBUG pixi_glob::glob_set::walk: glob pass completed include="pyproject.toml" excludes="" matched=1 elapsed_ms=2 root="/Users/rubenarts/dev/pixi-build-backends/backends/pixi-build-ros" INFO source-metadata{manifest_source=~/dev/pixi-build-backends/recipe/pixi-build-api-version preferred_build_source=None name=pixi-build-api-version platform=osx-arm64}: pixi_command_dispatcher::source_metadata: Retrieving source metadata for package pixi-build-api-version INFO source-metadata{manifest_source=/Users/rubenarts/dev/pixi-build-backends/backends/pixi-build-ros preferred_build_source=None name=pixi-build-ros platform=osx-arm64}: pixi_command_dispatcher::source_metadata: Retrieving source metadata for package pixi-build-ros DEBUG source-metadata{manifest_source=/Users/rubenarts/dev/pixi-build-backends/backends/pixi-build-ros preferred_build_source=None name=pixi-build-ros platform=osx-arm64}: pixi_command_dispatcher::source_metadata: no cached metadata passed. DEBUG source-metadata{manifest_source=~/dev/pixi-build-backends/recipe/pixi-build-api-version preferred_build_source=None name=pixi-build-api-version platform=osx-arm64}: pixi_command_dispatcher::source_metadata: Using cached source metadata for package pixi-build-api-version DEBUG pixi_core::lock_file::satisfiability: Source package metadata changed for '~/dev/pixi-build-backends/recipe/pixi-build-api-version'. Rebuild may be needed. INFO pixi_core::lock_file::outdated: the dependencies of environment 'default' for platform osx-arm64 are out of date because the locked metadata of 'pixi-build-api-version' package changed DEBUG backend-metadata{manifest_source=Path(PinnedPathSpec { path: Unix(Utf8PathBuf { _encoding: "unix", inner: "action_tutorials/action_tutorials_cpp" }) }) build_source=None platform=linux-64}: pixi_command_dispatcher::build_backend_metadata: metadata cache disabled for backend backend=pixi-build-ros reason="mutable-environment" command_kind="mutable-environment" INFO pixi_core::lock_file::outdated: the dependencies of environment 'default' for platform linux-64 are out of date because the operation was cancelled Error: × failed to solve requirements of environment 'default' for platform 'osx-arm64' ╰─▶ ⚠ the operation was cancelled ```

As not blocking issues are found I'm going to approve this! Great work!

@baszalmstra baszalmstra added the test:extra_slow Run the extra slow tests label Dec 11, 2025
@ruben-arts ruben-arts merged commit cc2d335 into prefix-dev:bas/wip/develop-dependencies Dec 16, 2025
37 checks passed
@uwu-420
Copy link

uwu-420 commented Dec 17, 2025

@nichmor I'm happy that this PR got merged, thanks! Are there already plans to also omit the hash for pypi dependencies in the lockfile, because this seems to only change it for conda dependencies. I couldn't find anything in the issues and open PRs.

@tdejager
Copy link
Contributor

@uwu-420 for sure! As you saw we just removed editable and the input hash will be next :) It's a bit more difficult though :)

nichmor pushed a commit that referenced this pull request Dec 19, 2025
Replace hash-based validation for path-based PyPI packages with
metadata-based validation. Instead of computing and storing a hash
of pyproject.toml, setup.py, and setup.cfg, we now:

1. Don't store any hash in the lock file for path-based packages
2. During satisfiability checks, parse pyproject.toml and compare
   the name and version with the locked metadata

This approach is similar to how PR #5011 removed input_hash for
conda packages. The metadata comparison is more explicit about what
changed (name vs version) rather than just indicating "something
changed via hash mismatch".

Changes:
- pypi.rs: Stop computing and storing hash for SourceDist::Path and
  SourceDist::Directory
- satisfiability/mod.rs: Replace PypiSourceTreeHashable hash comparison
  with metadata parsing and comparison
- Add PypiSourceMetadataMismatch and PypiSourceMetadataError types
- Remove SourceTreeHashMismatch type and related imports
nichmor pushed a commit that referenced this pull request Jan 3, 2026
Replace hash-based validation for path-based PyPI packages with
metadata-based validation. Instead of computing and storing a hash
of pyproject.toml, setup.py, and setup.cfg, we now:

1. Don't store any hash in the lock file for path-based packages
2. During satisfiability checks, parse pyproject.toml and compare
   the name and version with the locked metadata

This approach is similar to how PR #5011 removed input_hash for
conda packages. The metadata comparison is more explicit about what
changed (name vs version) rather than just indicating "something
changed via hash mismatch".

Changes:
- pypi.rs: Stop computing and storing hash for SourceDist::Path and
  SourceDist::Directory
- satisfiability/mod.rs: Replace PypiSourceTreeHashable hash comparison
  with metadata parsing and comparison
- Add PypiSourceMetadataMismatch and PypiSourceMetadataError types
- Remove SourceTreeHashMismatch type and related imports
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:extra_slow Run the extra slow tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants