← Back to issue list

Dump follows symlink and fails

View original Launchpad issue

Metadata

Project
snapcraft (launchpad)
Number
#1754010
Type
issue
State
open
Author
~r4co0n
Labels
—
Created
Updated
Closed
—

Current evaluation

Snapcraft 2.39.3's dump plugin dereferenced an in-tree directory symlink during staging and crashed. Later symlink-preservation fixes and current no-dereference behavior resolve the defect, but the tracker remains open.

Suggested action: close resolved

Reason: Commit 7768cd33b (#1063) changed file copying to preserve directory symlinks, while d4b104887 (#1064) addressed directory/symlink collisions in pluginhandler. Current craft-parts migration defaults to follow_symlinks=False and the dump plugin uses cp with --no-dereference, resolving the reported 2.39.3 failure mode.

Evaluated by: mr-cal-bot

Impact: 48 Quick Win: 20 Complexity: 45 Confidence: 92 Actionability: 76

Issue body

Hello, when trying to use dump on a directory containing a relative symlink to another subdirectory of the source, dump follows the symlink instead of copying it. The script at the following url reproduces a simple environment in which snapcraft exhibits the described error: https://gist.github.com/r4co0n/5766f0452cd5cc94e3b2b19959d48892 The following is snapcraft's debug output, note the additional "Checking if ...", "Found link ..." and "Migrating file ..." lines I added via some print() statements to find out what is going on. Preparing to pull one Pulling one Preparing to build one Building one Checking if source /vagrant/parts/one/build/four is link. Destination is /vagrant/parts/one/install/four. Boundary is /vagrant/parts/one/install Found link two. Normalized desination path is /vagrant/parts/one/install/two Checking if source /vagrant/parts/one/build/two/three is link. Destination is /vagrant/parts/one/install/two/three. Boundary is /vagrant/parts/one/install Staging one Migrating file /vagrant/parts/one/install/two/three to /vagrant/stage/two/three Migrating file /vagrant/parts/one/install/four/three to /vagrant/stage/four/three Migrating file /vagrant/parts/one/install/four to /vagrant/stage/four Traceback (most recent call last): File "/usr/bin/snapcraft", line 9, in <module> load_entry_point('snapcraft==2.39.3', 'console_scripts', 'snapcraft')() File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 542, in load_entry_point return get_distribution(dist).load_entry_point(group, name) File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2569, in load_entry_point return ep.load() File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2229, in load return self.resolve() File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2235, in resolve module = __import__(self.module_name, fromlist=['__name__'], level=0) File "/usr/lib/python3/dist-packages/snapcraft/cli/__main__.py", line 43, in <module> run(prog_name='snapcraft') File "/usr/lib/python3/dist-packages/click/core.py", line 716, in __call__ return self.main(*args, **kwargs) File "/usr/lib/python3/dist-packages/click/core.py", line 696, in main rv = self.invoke(ctx) File "/usr/lib/python3/dist-packages/click/core.py", line 1037, in invoke return Command.invoke(self, ctx) File "/usr/lib/python3/dist-packages/click/core.py", line 889, in invoke return ctx.invoke(self.callback, **ctx.params) File "/usr/lib/python3/dist-packages/click/core.py", line 534, in invoke return callback(*args, **kwargs) File "/usr/lib/python3/dist-packages/click/decorators.py", line 17, in new_func return f(get_current_context(), *args, **kwargs) File "/usr/lib/python3/dist-packages/snapcraft/cli/_runner.py", line 72, in run ctx.forward(lifecyclecli.commands['snap']) File "/usr/lib/python3/dist-packages/click/core.py", line 552, in forward return self.invoke(cmd, **kwargs) File "/usr/lib/python3/dist-packages/click/core.py", line 534, in invoke return callback(*args, **kwargs) File "/usr/lib/python3/dist-packages/snapcraft/cli/lifecycle.py", line 139, in snap project_options, directory=directory, output=output) File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle/_packer.py", line 46, in snap execute('prime', project_options) File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle/_runner.py", line 79, in execute _Executor(config, project_options).run(step, part_names) File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle/_runner.py", line 185, in run self._run_step(step, part, part_names) File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle/_runner.py", line 222, in _run_step getattr(part, step)() File "/usr/lib/python3/dist-packages/snapcraft/internal/pluginhandler/__init__.py", line 477, in stage self.stagedir, fixup_func=fixup_func) File "/usr/lib/python3/dist-packages/snapcraft/internal/pluginhandler/__init__.py", line 841, in _migrate_files os.remove(dst) IsADirectoryError: [Errno 21] Is a directory: '/vagrant/stage/four'

Evaluation history

Date Model Scores Action Summary
stealth/space-bunny-alpha
Impact: 48
Quick Win: 20
Complexity: 45
Confidence: 92
Actionability: 76
close resolved Snapcraft 2.39.3's dump plugin dereferenced an in-tree directory symlink during staging and crashed. Later symlink-preservation fixes and current no-dereference behavior resolve the defect, but the tracker remains open.
stealth/space-bunny-alpha
Impact: 58
Quick Win: 21
Complexity: 58
Confidence: 87
Actionability: 86
close resolved Dump followed an in-tree directory symlink and failed staging with IsADirectoryError; historical tests and later craft-parts symlink-preservation behavior indicate the defect was fixed.
qwen/qwen3.6-35b-a3b
Impact: 70
Quick Win: 39
Complexity: 30
Confidence: 85
Actionability: 80
close resolved Dump plugin follows symlinks during stage migration causing IsADirectoryError. Resolved: craft-parts now defaults follow_symlinks=False with proper symlink handling and tests.
qwen/qwen3.8-27b
Impact: 30
Quick Win: 18
Staleness: 95
Complexity: 40
Confidence: 85
Support Request: 10
close stale Dump plugin in snapcraft 2.39.3 follows relative symlinks during copy, causing IsADirectoryError in _migrate_files during staging. Legacy 2.x code path no longer exists; current craft-parts dump plugin uses cp --no-dereference.
qwen/qwen3.6-35b-a3b
Staleness: 98
Complexity: 30
Confidence: 95
Support Request: 5
close stale Bug report for snapcraft 2.39.3 where the dump step follows relative symlinks and crashes with IsADirectoryError during file migration. Unaddressed for over 8 years.
qwen/qwen3.6-35b-a3b
Staleness: 98
Complexity: 45
Confidence: 85
Support Request: 5
close stale Bug report where snapcraft's dump command follows a relative symlink instead of copying it, causing an IsADirectoryError during staging. Issue is over 8 years old with no maintainer response.
qwen3.6-35b-a3b-mtp-q6
Staleness: 95
Complexity: 40
Confidence: 90
Support Request: 5
close stale Snapcraft dump command follows relative symlinks instead of copying them, causing an IsADirectoryError during migration. Untriaged, inactive for over 8 years.

Update history

Date Change
created

Related work

  • Likely Fixed By: snapcraft#1063 (confidence 97%)

    Commit 7768cd33b explicitly changes file copying to preserve symlinks to directories.

  • Likely Fixed By: snapcraft#1064 (confidence 90%)

    Commit d4b104887 handles collisions between directories and symlinks in pluginhandler.

Related issues

Issue Project State Summary Similarity
#1614913 FAIL: test_dump_symlinks (snapcraft.tests.test_plugin_dump.DumpPluginTestCase) snapcraft (launchpad) closed Fixed by merged PR snapcraft#767 (commit d14329836), which copied common.SNAPCRAFT_FILES before use, preventing leaked test state from breaking dump symlink tests.
75%
#1658774 Symlinks to libc are followed by the dump and copy plugins snapcraft (launchpad) closed Merged snapcraft#1174 as commit 2b8bac953, changing copy and dump plugins to ignore staged-package symlinks to libc instead of following or removing them.
70%