-
-
Notifications
You must be signed in to change notification settings - Fork 15.5k
wrap-gapps-hook.sh: only wrap links when required #54909
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wrap-gapps-hook.sh: only wrap links when required #54909
Conversation
find "${targetDirsThatExist[@]}" -type l -xtype f -executable -print0 \ | ||
| while IFS= read -r -d '' linkPath; do | ||
linkPathReal=$(realpath "${linkPath}") | ||
for targetPath in "${targetDirsRealPath[@]}"; do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making targetDirsRealPath an associative array would be preferable here to avoid
quadratic complexity.
if [[ -n ${targetDirsRealPath[$linkpath]} ]]; then
echo "Not wrapping link: '$linkPath' (already wrapped)"
continue
fi
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The alternative would be to memoize each wrapped programs once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Mic92 Thanks for the review and for the nix-review program which proved very helpful in testing.
I'm not sure if an associative array will help here as the comparison at line 63 is intended to match any linkPathReal that starts with the prefix targetPath:
if [[ "$linkPathReal" == "$targetPath"* ]]; then
In the context of this script, targetDirsRealPath should have at most two elements, so performance should remain linear with respect to iterating over the symbolic links.
That said, your comment prompted me to review the code again and I think that there is a bug if neither /bin or /libexec exists in a package. I'll need to fix that!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@GrahamcOfBorg eval |
this needs to target staging |
9dadac9
to
2ed1a3c
Compare
continue 2 | ||
fi | ||
done | ||
echo "Wrapping link: '$linkPath'" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation here is off.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jtojnar Thanks for the review. I made the indentation fix.
Other than that, LGTM. |
Unless dontWrapGapps is set, the wrap-gapps-hook.sh will currently wrap all executables (and symbolic links to executables) found under the target directories: bin and libexec. As a result, if a symbolic link in a target directory points to an executable in a target directory, both will get wrapped. This causes an extra shell/exec when following the symbolic link, as well as increasing the size of the final executable's environment. To avoid wrapping a link to an already wrapped executable, this commit splits the determination of what gets wrapped into two phases: 1. All binaries under the target directories are wrapped and logged with "Wrapping program ..." 2. All links to executables under the target directories are identified and checked to see if they reference an executable under one of the target directories. If yes, the required wrapping has already been performed on the associated binary (in phase 1), so no wrapping is done and "Not wrapping link: ... (already wrapped)" is logged. If no, the link points at an executable that hasn't been wrapped, so the link is wrapped and "Wrapping link: ..." is logged. As an example, the yelp package has a bin directory that contains an executable "yelp" and a symbolic link "gnome-help" -> "yelp". Prior to this commit, the bin directory would contain these files after wrapping: gnome-help -- wrapper to exec .gnome-help-wrapped .gnome-help-wrapped -- a symbolic link to yelp yelp -- wrapper to exec .yelp-wrapped .yelp-wrapped -- the original yelp binary After this commit, the bin directory will instead contain: gnome-help -- a symbolic link to yelp yelp -- wrapper to exec .yelp-wrapped .yelp-wrapped -- the original yelp binary NOTE: The primary motivation for this commit is to avoid obscuring the fact that two or more paths are simple aliases and expected to behave identically. It also reduces the likelihood of hitting limits related to environment variable size. LIMITATION: The method used above is intended to be conservative and will still wrap symbolic links to other symbolic links when the ultimate target is outside of bin or libexec.
2ed1a3c
to
bbb2f93
Compare
Thank you. |
Unless dontWrapGapps is set, the wrap-gapps-hook.sh will currently
wrap all executables (and symbolic links to executables) found under
the target directories: bin and libexec.
As a result, if a symbolic link in a target directory points to an
executable in a target directory, both will get wrapped. This
causes an extra shell/exec when following the symbolic link,
as well as increasing the size of the final executable's environment.
To avoid wrapping a link to an already wrapped executable, this
commit splits the determination of what gets wrapped into two phases:
All binaries under the target directories are wrapped and logged
with "Wrapping program ..."
All links to executables under the target directories are
identified and checked to see if they reference an executable
under one of the target directories.
If yes, the required wrapping has already been performed on
the associated binary (in phase 1), so no wrapping is done
and "Not wrapping link: ... (already wrapped)" is logged.
If no, the link points at an executable that hasn't been
wrapped, so the link is wrapped and "Wrapping link: ..." is logged.
As an example, the yelp package has a bin directory that contains
an executable "yelp" and a symbolic link "gnome-help" -> "yelp".
Prior to this commit, the bin directory would contain these files
after wrapping:
After this commit, the bin directory will instead contain:
NOTE: The primary motivation for this commit is to avoid obscuring
the fact that two or more paths are simple aliases and expected to
behave identically. It also reduces the likelihood of hitting
limits related to environment variable size.
LIMITATION: The method used above is intended to be conservative
and will still wrap symbolic links to other symbolic links when
the ultimate target is outside of bin or libexec.
sandbox
innix.conf
on non-NixOS)nix-shell -p nox --run "nox-review wip"
./result/bin/
)nix path-info -S
before and after)NOTE: Tested with nix-review. Used grep on logs to find packages with symbolic links that would no longer be wrapped after this commit. Here's a list:
You can build any of these packages to test this commit. Also, there is a default.nix that can be used to test link wrapping more comprehensively here:
https://gist.github.com/tollb/4a21b890058ca3ab7d44618e345d0e28