← Back to issue list

Organizing files fails if equivalent file already exists

View original Github issue

Metadata

Project
craft-parts
Number
#673
Type
issue
State
closed
Author
dilyn-corner
Labels
—
Created
Updated
Closed

Current evaluation

Organize collisions were fixed by PR #689 (commit c349e740), making organize_files() use part install directories instead of cwd-relative paths.

Resolution: closed resolved

Reason: Closed as likely fixed by PR #689, commit c349e740. The change corrects path resolution for organized files in non-default partitions, addressing the reported equivalent-file collision.

Evaluated by: mr-cal-bot

No scores available.

Issue body

### Bug Description When a `part` defines an `organize:` which includes moving a file into a (not `default`) component partition, the organize will fail just in case the file already exists in that partition. This behavior breaks from how that functionality works when not organizing into a component, where the collision of identical files is ignored. This problem only seems to impact organizing into a partition which isn't `default`. To see this, remove the `organize:` from `my-part` in the below `snapcraft.yaml` and run `snapcraft build my-part --verbose` twice. It should not fail. I would expect the behavior to match regardless of the name of the partition the file is being organized into. ### To Reproduce Install snapcraft from a feature branch and create a boilerplate snap: ``` snap switch --channel=latest/edge/components snapcraft; snap refresh snapcraft # Tested with revision 10677 mkdir test; cd test; snapcraft init ``` Create some simple files: ``` mkdir src/ touch src/default-file src/foo-file ``` Use the below `snapcraft.yaml` and run `snapcraft build my-part --verbose` twice. To compare the behavior when not organizing into a component not named `default`, remove the `organize` section. To compare the behavior when not using components, remove the `components:` section and the usage of `organize:`. Both of these comparisons should succeed, while the provided example fails. ### part yaml ```shell name: my-snap-name # you probably want to 'snapcraft register <name>' base: core24 # the base snap is the execution environment for this snap build-base: devel version: '0.1' # just for humans, typically '1.2+git' or '1.3.2' summary: Single-line elevator pitch for your amazing snap # 79 char long summary description: | This is my-snap's description. You have a paragraph or two to tell the most important story about your snap. Keep it under 100 words though, we live in tweetspace and your description wants to look good in the snap store. grade: devel # must be 'stable' to release into candidate/stable channels confinement: devmode # use 'strict' once you have the right plugs and slots parts: my-part: plugin: dump source: src/ organize: foo-file: (component/foo)/foo-file components: foo: type: test summary: test description: test ``` ### Relevant log output ```shell dilyn@Ares:~/test -> snapcraft build my-part --verbose Starting snapcraft Logging execution to '/home/dilyn/.local/state/snapcraft/log/snapcraft-20240227-175558.077912.log' Starting snapcraft Logging execution to '/home/dilyn/.local/state/snapcraft/log/snapcraft-20240227-175558.077912.log' deleting current features configuration Running on amd64 for amd64 Running snapcraft with a devel instance is for testing purposes only. Launching instance... Creating instance from base instance Starting instance \ (11.7s) Starting instance \ (14.1s) Starting instance Starting snapcraft Logging execution to '/root/.local/state/snapcraft/log/snapcraft-20240227-175622.766916.log' Starting snapcraft Logging execution to '/root/.local/state/snapcraft/log/snapcraft-20240227-175622.766916.log' deleting current features configuration Running on amd64 for amd64 Initializing parts lifecycle Installing build-packages Installing build-snaps Pulling my-part Building my-part :: + cp --archive --link --no-dereference . /root/parts/my-part/install/default dilyn@Ares:~/test -> snapcraft build my-part --verbose Starting snapcraft Logging execution to '/home/dilyn/.local/state/snapcraft/log/snapcraft-20240227-175642.418888.log' Starting snapcraft Logging execution to '/home/dilyn/.local/state/snapcraft/log/snapcraft-20240227-175642.418888.log' deleting current features configuration Running on amd64 for amd64 Running snapcraft with a devel instance is for testing purposes only. Launching instance... Starting instance Starting snapcraft Logging execution to '/root/.local/state/snapcraft/log/snapcraft-20240227-175653.254644.log' Starting snapcraft Logging execution to '/root/.local/state/snapcraft/log/snapcraft-20240227-175653.254644.log' deleting current features configuration Running on amd64 for amd64 Initializing parts lifecycle Installing build-packages Installing build-snaps Skipping pull for my-part (already ran) Rebuilding my-part (requested step) :: + cp --archive --link --no-dereference . /root/parts/my-part/install/default Failed to organize part 'my-part': trying to organize file 'foo-file' to '(component/foo)/foo-file', but '(component/foo)/foo-file' already exists. Failed to execute build in instance. Recommended resolution: Run the same command again with --debug to shell into the environment if you wish to introspect this failure. Full execution log: '/home/dilyn/.local/state/snapcraft/log/snapcraft-20240227-175642.418888.log' ```

Evaluation history

Date Model Scores Action Summary
stealth/space-bunny-alpha — closed resolved Organize collisions were fixed by PR #689 (commit c349e740), making organize_files() use part install directories instead of cwd-relative paths.
stealth/space-bunny-alpha — closed resolved Closed as likely fixed by craft-parts#689 (c349e740): organize_files() now uses the part's install directories rather than cwd-relative paths.
qwen/qwen3.6-35b-a3b — — Closed as likely fixed. Commit c349e740 (PR #68) corrected path handling in organize_files(), resolving the duplicate file collision error that broke idempotent builds. Maintainers requested reopening if the issue persists.
qwen/qwen3.6-35b-a3b
Staleness: 25
Complexity: 45
Confidence: 90
Support Request: 5
keep open Bug where snapcraft fails when organizing files to an existing location, breaking idempotent builds. Acknowledged by maintainers and on backlog, but unfixed.
qwen3.6-35b-a3b-mtp-q6
Staleness: 40
Complexity: 45
Confidence: 85
Support Request: 10
keep open Bug where snapcraft's organize step fails on duplicate files instead of being idempotent. Acknowledged by maintainers, on backlog, with recent user reports and discussion.

Update history

Date Change
closed

Related work

  • Likely Fixed By: craft-parts#689 (confidence 99%)

    Merged as commit c349e740 and cited by the closing maintainer comment.

Related issues

Issue Project State Summary Similarity
#690 fix(organize): use the part's install directories (#689) craft-parts merged Merged PR #690 in commit 0eff7cc9 (change c349e740), fixing organize_files() to use part install directories and organize under base_dir.
75%
#1366 Unhandled error when organizing a file to a directory where the file already exists craft-parts closed Fixed by merged PR canonical/craft-parts#1370 (commit 7fe7c84e), which checks whether an organize destination exists before moving files.
73%
#1544 fix: prevent organizing a directory into itself craft-parts closed PR #1544 was closed unmerged as incomplete; the solution was replaced by the organize-from-build rework in #1598 (commit cc02958b).
72%
#1007 Organize fails with an unhelpful error when attempting to overwrite a file craft-parts closed Closed as stale without a direct fix; the organize-overwrite failure was later fixed by merged PR #1370 (commit 7fe7c84e), ensuring the destination does not exist before moving files.
72%
#1525 Directory traversal issue when organizing a part craft-parts closed Fixed by merged PR #1562 (commit 32b95b4f), rejecting organize sources that escape the install directory via absolute paths or traversal.
70%