Provide visible yaml settings or document organize plugin behavior for directory merging
Metadata
Current evaluation
Organize wildcard and directory-merging semantics remain poorly documented; a maintainer linked the gap to the still-open craft-parts explanation effort.
Suggested action: keep open
Reason: The report provides a concrete snap-libvirt commit and traces the cryptic "path ./ already exists" failure to wildcard handling and shutil.move. A maintainer explicitly linked canonical/craft-parts#1644, an open maintainer-created documentation issue, confirming that the gap remains valid and is already being tracked in the component that now owns organize behavior.
Evaluated by: mr-cal-bot
Impact:
40
Quick Win:
25
Complexity:
25
Confidence:
96
Actionability:
84
Issue body
Hi,
I was working on a change for snap-libvirt and encountered a behavior which is not apparent on the first sight.
https://github.com/openstack-snaps/snap-libvirt/commit/8cd9af031a9b01f360975bddc1964e9380b983e6
Originally '*' has been used in the organize plugin which lead to an error due to the fact that the directory structure used by both parts (libvirt and qemu) is similar:
"path ./ already exists"
This error is cryptic unless you look at the source code of snapcraft:
def _organize:
https://github.com/snapcore/snapcraft/blob/9e00ffc151b46026b414c8b4b8e44a3a9d4c0b75/snapcraft/internal/pluginhandler/__init__.py#L449
calls def _organize_filesets(fileset, base_dir):
https://github.com/snapcore/snapcraft/blob/9e00ffc151b46026b414c8b4b8e44a3a9d4c0b75/snapcraft/internal/pluginhandler/__init__.py#L907
Now this function has 3 code paths:
def _organize_filesets(fileset, base_dir):
for key in sorted(fileset, key=lambda x: ['*' in x, x]):
src = os.path.join(base_dir, key)
dst = os.path.join(base_dir, fileset[key])
sources = iglob(src, recursive=True)
for src in sources:
if os.path.isdir(src) and '*' not in key: # <---- first
file_utils.link_or_copy_tree(src, dst)
# TODO create alternate organization location to avoid
# deletions.
shutil.rmtree(src)
elif os.path.isfile(dst): # <----- second
raise EnvironmentError(
'Trying to organize file {key!r} to {dst!r}, '
'but {dst!r} already exists'.format(
key=key, dst=os.path.relpath(dst, base_dir)))
else: # <----- third
os.makedirs(os.path.dirname(dst), exist_ok=True)
shutil.move(src, dst)
The third code path is what gets picked in case there is a '*' in the key and the destination in not a file.
shutil.move is the call that gave 'path ./ already exists' error which I learned by grepping cpython source code:
def move function
https://hg.python.org/cpython/file/2.7/Lib/shutil.py#l306
Now, looking at an alternative code path (the first one) which calls link_or_copy_tree I see:
https://github.com/snapcore/snapcraft/blob/05ba34a324c781f3e454d88f88267c5356771f9a/snapcraft/file_utils.py#L93
def link_or_copy_tree(source_tree, destination_tree,
copy_function=link_or_copy):
"""Copy a source tree into a destination, hard-linking if possile.
:param str source_tree: Source directory to be copied.
:param str destination_tree: Destination directory. If this directory
already exists, the files in
`source_tree` will take precedence.
The destination_tree argument gives a very good description in terms of what is going to happen but it is "hidden" in the source code which forces a regular snapcrafter to do some grepping.
Avoiding '*' helped me to select the right code path but it would be nice to have more visibility for that (either in a form of a knob in snapcraft.yaml or in the docs).
Thanks!
Evaluation history
| Date | Model | Scores | Action | Summary |
|---|---|---|---|---|
| stealth/space-bunny-alpha |
Impact:
40
Quick Win:
25
Complexity:
25
Confidence:
96
Actionability:
84
|
keep open | Organize wildcard and directory-merging semantics remain poorly documented; a maintainer linked the gap to the still-open craft-parts explanation effort. | |
| stealth/space-bunny-alpha |
Impact:
36
Quick Win:
20
Complexity:
29
Confidence:
93
Actionability:
78
|
keep open | Organize wildcard and directory-merging semantics remain insufficiently documented; craft-parts#1644 is an acknowledged, still-open effort covering how organize handles existing directories. | |
| qwen/qwen3.6-35b-a3b |
Impact:
30
Quick Win:
14
Complexity:
20
Confidence:
70
Actionability:
60
|
keep open | Feature request to document or add a knob for organize plugin directory merging behavior when using wildcards | |
| qwen/qwen3.8-27b |
Impact:
30
Quick Win:
16
Staleness:
55
Complexity:
45
Confidence:
55
Support Request:
35
|
needs triage | Request to document or expose a snapcraft.yaml knob for the organize plugin's directory-merging behavior, after a cryptic 'path ./ already exists' error from shutil.move when using '*' keys. No labels, no maintainer response, 0 comments; last activity 47 days ago on a ~9.5-year-old issue. | |
| qwen/qwen3.6-35b-a3b |
Staleness:
95
Complexity:
10
Confidence:
85
Support Request:
20
|
needs triage | Request to document or add YAML configuration for the snapcraft organize plugin's directory merging behavior, which currently causes cryptic errors when using wildcards. Untriaged, no maintainer response. | |
| qwen/qwen3.6-35b-a3b |
Staleness:
88
Complexity:
25
Confidence:
85
Support Request:
20
|
close stale | Request to document or add YAML configuration for the organize plugin directory merging behavior, which causes cryptic errors when paths conflict. Unlabelled, no maintainer response, open for nearly a decade. | |
| qwen3.6-35b-a3b-mtp-q6 |
Staleness:
100
Complexity:
10
Confidence:
90
Support Request:
5
|
close stale | Request to document or add YAML configuration for the organize plugin's directory merging behavior, which currently causes cryptic errors when using wildcards. Unaddressed for over 9 years. |
Update history
| Date | Change |
|---|---|
| created |
Related work
-
Related To:
canonical/craft-parts#1644
(confidence 100%)
Explicitly linked in the maintainer comment and focused on documenting how organize works.
Related issues
No related issues found above the similarity threshold.