Skip to content

Commit

Permalink
pkg installer: Fix ownership of files installed into $HOME (#784)
Browse files Browse the repository at this point in the history
* Change permissions for .conda directory

* Fix owner of files created by conda init

* Ensure that only files from HOME or PREFIX are looped over

* Add news items

* Test file ownership for pkg installers

* Remove install target

* Use getpass.getuser instead of os.getlogin

* Apply suggestions from code review

Co-authored-by: jaimergp <[email protected]>

* Use bash to update path

* Update constructor/osx/update_path.sh

Co-authored-by: jaimergp <[email protected]>

* Change ownership of .condarc

* Add conda config files to test files

---------

Co-authored-by: jaimergp <[email protected]>
  • Loading branch information
marcoesters and jaimergp authored May 8, 2024
1 parent a838162 commit c17eed5
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 3 deletions.
4 changes: 3 additions & 1 deletion constructor/osx/run_installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,11 @@ if ! "$PREFIX/bin/python" -V; then
exit 1
fi

# This is unneeded for the default install to ~, but if the user changes the
# This is not needed for the default install to ~, but if the user changes the
# install location, the permissions will default to root unless this is done.
chown -R "$USER" "$PREFIX"
chown -R "$USER" "${HOME}/.conda"
test -f "${HOME}/.condarc" && chown "${USER}" "${HOME}/.condarc"

notify "Done! Installation is available in $PREFIX."

Expand Down
34 changes: 32 additions & 2 deletions constructor/osx/update_path.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# Copyright (c) 2012-2017 Anaconda, Inc.
# All rights reserved.

Expand All @@ -8,4 +8,34 @@ set -eux

PREFIX="$2/__NAME_LOWER__"
PREFIX=$(cd "$PREFIX"; pwd)
"$PREFIX/bin/python" -m conda init --all
INIT_FILES=$("$PREFIX/bin/python" -m conda init --all | tee)

# Just like in run_install.sh, the files generated by the installer
# are owned by root when installed outside of $HOME. So, ownership of
# files modified by conda init must be changed to belong to $USER.
# For shells like fish or powershell, conda init creates subdirectories
# inside $HOME and/or $PREFIX, so ensure that parent directories also
# have the correct owner.
if [[ "${USER}" != "root" ]]; then
echo "Fixing permissions..."
read -r -a MODIFIED_FILES <<< "$(\
echo "${INIT_FILES}" |\
awk '/modified/{print $2}' |\
# Only grab files inside $HOME or $PREFIX.
# All init files should be there, but that may change, and it
# is better to miss files than to have an infinite loop below.
grep -E "^(${HOME}|${PREFIX})"\
)"
for file in "${MODIFIED_FILES[@]}"; do
while [[ "${file}" != "${HOME}" ]] && [[ "${file}" != "${PREFIX}" ]]; do
# Check just in case the file wasn't created due to flaky conda init
if [[ -f "${file}" ]] || [[ -d "${file}" ]]; then
OWNER=$(stat -f "%u" "${file}" | id -un)
if [[ "${OWNER}" == "root" ]]; then
chown "${USER}" "${file}"
fi
fi
file="${file%/*}"
done
done
fi
19 changes: 19 additions & 0 deletions news/784-pkg-installation-file-ownership
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Enhancements

* <news item>

### Bug fixes

* Fix ownership of files created by the PKG installer outside of `$PREFIX`. (#784)

### Deprecations

* <news item>

### Docs

* <news item>

### Other

* <news item>
26 changes: 26 additions & 0 deletions tests/test_examples.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import getpass
import os
import shutil
import subprocess
Expand Down Expand Up @@ -413,8 +414,33 @@ def test_example_noconda(tmp_path, request):
@pytest.mark.skipif(sys.platform != "darwin", reason="macOS only")
def test_example_osxpkg(tmp_path, request):
input_path = _example_path("osxpkg")
ownership_test_files_home = [
".bash_profile",
".conda",
".condarc",
".config",
".config/fish",
".config/fish/fish.config",
".config/powershell",
".config/powershell/profile.ps1",
".tcshrc",
".xonshrc",
".zshrc",
]
ownership_test_files_home = [Path.home() / file for file in ownership_test_files_home]
# getpass.getuser is more reliable than os.getlogin:
# https://docs.python.org/3/library/os.html#os.getlogin
expected_owner = getpass.getuser()
for installer, install_dir in create_installer(input_path, tmp_path):
_run_installer(input_path, installer, install_dir, request=request)
expected = {}
found = {}
for file in ownership_test_files_home:
if not file.exists():
continue
expected[file] = expected_owner
found[file] = file.owner()
assert expected == found


def test_example_scripts(tmp_path, request):
Expand Down

0 comments on commit c17eed5

Please sign in to comment.