Skip to content

Commit 62f4973

Browse files
authored
Use cp --no-dereference when saving the cache (#1909)
When copying files, `cp` can either follow (dereference) symlinks or preserve them. If no explicit `--dereference` or `--no-dereference` option is passed, the default behaviour is currently unspecified by the POSIX specification, and in practice arbitrarily varies based on other options that are passed. Specifically, when using `--link`, cp now defaults to following symlinks, which: (a) means the files aren't copied/linked verbatim (b) means the copy will fail if any of the symlinks are broken For the files owned by the buildpack there are no broken symlinks, however, Python packages in the wild can contain broken symlinks, which causes the build to fail with errors like: ``` -----> Saving cache cp: cannot stat '/tmp/build_123/.heroku/python/src/django-admin-autocomplete-list-filter/.pylintrc': No such file or directory ``` Now, `--no-dereference` is passed, to explicitly disable dereferencing, so we're not dependant on the unspecified defaults. GUS-W-19714036.
1 parent 2debd95 commit 62f4973

2 files changed

Lines changed: 5 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [Unreleased]
44

5+
- Fixed errors saving the build cache when installed packages contain broken symlinks. ([#1909](https://github.com/heroku/heroku-buildpack-python/pull/1909))
56
- Improved metrics for failed uv archive downloads. ([#1908](https://github.com/heroku/heroku-buildpack-python/pull/1908))
67

78
## [v309] - 2025-09-19

lib/cache.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,10 @@ function cache::save() {
189189
local additional_copy_args=()
190190
fi
191191

192-
cp --recursive "${additional_copy_args[@]}" "${build_dir}/.heroku/python" "${cache_dir}/.heroku/"
192+
# We must explicitly use `--no-dereference` since the default cp behaviour varies based on other
193+
# options used (such as `--link`), and we don't want symlinks to be resolved since otherwise the
194+
# copy will fail when copying packages that contain broken symlinks.
195+
cp --recursive --no-dereference "${additional_copy_args[@]}" "${build_dir}/.heroku/python" "${cache_dir}/.heroku/"
193196

194197
# Metadata used by subsequent builds to determine whether the cache can be reused.
195198
# These are written/consumed via separate files and not the build data store for compatibility

0 commit comments

Comments
 (0)