Skip to content
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

Allow customization of the domains attribute in pkg installers #745

Merged
merged 12 commits into from
Jan 11, 2024
11 changes: 11 additions & 0 deletions CONSTRUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,17 @@ to `/Library` in a "Just me" installation will give you `~/Library/<PKG_NAME>`.
Internally, this is passed to `pkgbuild --install-location`.
macOS only.

### `pkg_domains`

_required:_ no<br/>
_type:_ dictionary<br/>

The domains the package can be installed into. For a detailed explanation, see:
https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html
constructor defaults to `enable_anywhere=true` and `enable_currentUserHome=true`.
`enable_localSystem` should not be set to true unless `default_location_pkg` is set as well.
macOS only.

### `pkg_name`

_required:_ no<br/>
Expand Down
8 changes: 8 additions & 0 deletions constructor/construct.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,14 @@
to `/Library` in a "Just me" installation will give you `~/Library/<PKG_NAME>`.
Internally, this is passed to `pkgbuild --install-location`.
macOS only.
'''),

('pkg_domains', False, dict, '''
The domains the package can be installed into. For a detailed explanation, see:
https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html
constructor defaults to `enable_anywhere=true` and `enable_currentUserHome=true`.
`enable_localSystem` should not be set to true unless `default_location_pkg` is set as well.
macOS only.
'''),

('pkg_name', False, str, '''
Expand Down
27 changes: 27 additions & 0 deletions constructor/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,33 @@ def main_build(dir_path, output_dir='.', platform=cc_platform,
)
)

if 'pkg' in itypes:
if (domains := info.get('pkg_domains')) is not None:
domains = {key: str(val).lower() for key, val in domains.items()}
allowed_fields = ['enable_anywhere', 'enable_currentUserHome', 'enable_localSystem']
if any(key not in allowed_fields for key in domains.keys()):
sys.exit(
'Error: unrecognized field name(s) for pkg_domains.'
f' Allowed fields are {", ".join(allowed_fields)}'
)
if any(val != 'true' and val != 'false' for val in domains.values()):
sys.exit('Error: values for pkg_domains must be boolean.')
if (
str(domains.get('enable_localSystem', '')).lower() == 'true'
and not info.get('default_location_pkg')
):
logger.warning(
'enable_localSystem should not be enabled without setting'
' `default_location_pkg` to avoid installing directly '
' into the root directory.'
)
info['pkg_domains'] = domains
else:
info['pkg_domains'] = {
'enable_anywhere': 'true',
'enable_currentUserHome': 'true',
}

info['installer_type'] = itypes[0]
fcp_main(info, verbose=verbose, dry_run=dry_run, conda_exe=conda_exe)
if dry_run:
Expand Down
11 changes: 6 additions & 5 deletions constructor/osxpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,16 +276,17 @@ def modify_xml(xml_path, info):
# - Install on a specific disk: /<custom_root>/<name>
# On modern Mac systems, installing in root is not allowed. So
# we remove this option by not supplying enable_localSystem
# below. Alternatively, we could have chosen not to set the
# in the default value for pkg_domains. enable_localSystem
# should only be set to true if default_location_pkg is supplied
jaimergp marked this conversation as resolved.
Show resolved Hide resolved
# in the construct.yaml file.
# Alternatively, we could have chosen not to set the
# value of customLocation and we would have obtained this:
# - Install for all users: /Applications/<name>
# - Install for this user: /Users/<username>/Applications/<name>
# - Install on a specific disk: /<custom_root>/<name>
# We have chosen not to do this so that this installer
# produces the same results as a shell install.
domains = ET.Element('domains',
enable_anywhere='true',
enable_currentUserHome='true')
# can produce the same results as a shell install.
domains = ET.Element('domains', **info['pkg_domains'])
root.append(domains)
tree.write(xml_path)

Expand Down
11 changes: 11 additions & 0 deletions docs/source/construct-yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,17 @@ to `/Library` in a "Just me" installation will give you `~/Library/<PKG_NAME>`.
Internally, this is passed to `pkgbuild --install-location`.
macOS only.

### `pkg_domains`

_required:_ no<br/>
_type:_ dictionary<br/>

The domains the package can be installed into. For a detailed explanation, see:
https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html
constructor defaults to `enable_anywhere=true` and `enable_currentUserHome=true`.
`enable_localSystem` should not be set to true unless `default_location_pkg` is set as well.
macOS only.

### `pkg_name`

_required:_ no<br/>
Expand Down
19 changes: 19 additions & 0 deletions news/745-customize-pkg-domains
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Enhancements

* Add `pkg_domains` setting to allow customization of the `domains` attribute in `PKG` installers. (#731 via #744)

### Bug fixes

* <news item>

### Deprecations

* <news item>

### Docs

* <news item>

### Other

* <news item>
27 changes: 27 additions & 0 deletions tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sys
import time
import warnings
import xml.etree.ElementTree as ET
from datetime import timedelta
from functools import lru_cache
from pathlib import Path
Expand Down Expand Up @@ -524,6 +525,32 @@ def test_register_envs(tmp_path, request):
assert str(install_dir) not in environments_txt


@pytest.mark.skipif(sys.platform != 'darwin', reason='MacOS only')
@pytest.mark.parametrize('domains', ({}, {'enable_anywhere': 'false', 'enable_localSystem': True}))
def test_pkg_distribution_domains(tmp_path, domains):
jaimergp marked this conversation as resolved.
Show resolved Hide resolved
recipe_path = _example_path('osxpkg')
input_path = tmp_path / 'input'
output_path = tmp_path / 'output'
shutil.copytree(str(recipe_path), str(input_path))
if domains:
with open(input_path / "construct.yaml", "a") as cyml:
cyml.write('pkg_domains:\n')
for key, val in domains.items():
cyml.write(f" {key}: {val}\n")

installer, install_dir = next(create_installer(input_path, output_path))
cmd = ['pkgutil', '--expand', installer, output_path / "expanded"]
_execute(cmd)
domains_file = output_path / "expanded" / 'Distribution'
assert domains_file.exists()

tree = ET.parse(domains_file)
found = {key: val for key, val in tree.find('domains').items()}
defaults = {'enable_anywhere': 'true', 'enable_currentUserHome': 'true'}
expected = {key: str(val).lower() for key, val in domains.items()} if domains else defaults
assert expected == found


@pytest.mark.skipif(sys.platform != "darwin", reason="macOS only")
def test_cross_osx_building(tmp_path):
input_path = _example_path("noconda")
Expand Down