a few spinoff fset copy/delete improvements

This commit is contained in:
Eric 2023-09-01 13:53:17 -07:00
parent 66bf931b46
commit 7b8a98bf98
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
5 changed files with 112 additions and 62 deletions

32
.efrocachemap generated
View File

@ -4072,18 +4072,18 @@
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "ab0cb59c874beb50e554d3d7c552565e", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "ab0cb59c874beb50e554d3d7c552565e",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "dec2c09bd136aa413b9b94729f7d6d2e", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "dec2c09bd136aa413b9b94729f7d6d2e",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "a5c43eb8befc810d693ec9c9f83fcba4", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "a5c43eb8befc810d693ec9c9f83fcba4",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "92bef80f4f6a5feda383035470ea2131", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "56bf9b14517f0a579964b39218498fcf",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "d6a10e3a6bc1a07609598f962439c6c8", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "d6a10e3a6bc1a07609598f962439c6c8",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "0150dcf48cb6a34adecaaa27d8940d29", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "ab5cb01ed4a8a8db80ca65ab5cd0133b",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "231bd6e18145b06028e4f90fd7de106c", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "231bd6e18145b06028e4f90fd7de106c",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "27c074268b5d1665ad45af2b5d62d03c", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "3cc88ed5471e9b7f2b84af4ee58a8061",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "4586629e8f114c1b5a22444ae26b5917", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "4586629e8f114c1b5a22444ae26b5917",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "2a776f145931be151cfc2f90907a1ddd", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "e1177b377c3e48d60057a9719bf9d0e3",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "518c529a7133d5ea41d730d12ae156c4", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "518c529a7133d5ea41d730d12ae156c4",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "dc1424b526bd15a53a1f26346416b09e", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "41e7afae9395843c575c65593aab423c",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "8ee060e63821fc3f0775ffaca476d3b5", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d95e4cc445b722f111e51b3d4b7bdde9",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "33ca30ccfb51b1b047f5564edb505e79", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d75e3afcc1db962cd483f8b80a65c930",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "174581fbf846e3f14c3ef6f139ceefa1", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "2b1b27fc2ca79803d79796a7414db3a2",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "a3607fd941915ab11503f82acfc392b5", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "a3607fd941915ab11503f82acfc392b5",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b5a129d83796c9e7015ab5e319d2c22f", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b5a129d83796c9e7015ab5e319d2c22f",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "a3607fd941915ab11503f82acfc392b5", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "a3607fd941915ab11503f82acfc392b5",
@ -4100,14 +4100,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c5c40967e63471c9c4abd6dfbef892df", "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c5c40967e63471c9c4abd6dfbef892df",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "d34c0a142e7d391a109a33ea3cc77c08", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "d34c0a142e7d391a109a33ea3cc77c08",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c5c40967e63471c9c4abd6dfbef892df", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c5c40967e63471c9c4abd6dfbef892df",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "88b6da386b4044afa482da6ad85f704d", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "aa15bc38411a8a4194b3711c9c6ebf56",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "d2cbb43b7a5e4f7ddb7d70703f49ddf1", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "3539534ba129d95e99f89ddf79d14f28",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "997d010eeae0181b249f5936a891e9b1", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "75e16f083a18621fe4502bc170e6a696",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0b8e42d5d61d953ea4e0df9b435a795a", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "29b9a8543b1612c0451eaaf90647b905",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "dd5e4e4b58e59054330a905b35337c67", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "4fb61373afaa6ce350601b245fcb1b7a",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "8036025f45cb9c536dfe9fec83c6ef21", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "d8e606cdfef72b6170721d87ee1d9b11",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "ef0330100297333917d1b68b98c002b2", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "240b54fa0d4334591c0876a2b72a4663",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "f3ca2b3dd2fd16bfe3e5253b087a6c28", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "a7887447024ce5570da3f468bad5bbb4",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318", "src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "ad347097a38e0d7ede9eb6dec6a80ee9", "src/ballistica/base/mgen/pyembed/binding_base.inc": "ad347097a38e0d7ede9eb6dec6a80ee9",

View File

@ -50,7 +50,8 @@ class AppComponentSubsystem:
# Currently limiting this to logic-thread use; can revisit if # Currently limiting this to logic-thread use; can revisit if
# needed (would need to guard access to our implementations # needed (would need to guard access to our implementations
# dict). # dict).
assert _babase.in_logic_thread() if not _babase.in_logic_thread():
raise RuntimeError('this must be called from the logic thread.')
if not issubclass(implementation, baseclass): if not issubclass(implementation, baseclass):
raise TypeError( raise TypeError(
@ -73,7 +74,8 @@ class AppComponentSubsystem:
If no custom implementation has been set, the provided If no custom implementation has been set, the provided
base-class is returned. base-class is returned.
""" """
assert _babase.in_logic_thread() if not _babase.in_logic_thread():
raise RuntimeError('this must be called from the logic thread.')
del baseclass # Unused. del baseclass # Unused.
return cast(T, None) return cast(T, None)
@ -87,7 +89,9 @@ class AppComponentSubsystem:
loop. Note that any further setclass calls before the callback loop. Note that any further setclass calls before the callback
runs will not result in additional callbacks. runs will not result in additional callbacks.
""" """
assert _babase.in_logic_thread() if not _babase.in_logic_thread():
raise RuntimeError('this must be called from the logic thread.')
self._change_callbacks.setdefault(baseclass, []).append(callback) self._change_callbacks.setdefault(baseclass, []).append(callback)
def _run_change_callbacks(self) -> None: def _run_change_callbacks(self) -> None:

View File

@ -10,6 +10,7 @@ from dataclasses import dataclass
from typing import TYPE_CHECKING, final from typing import TYPE_CHECKING, final
from bacommon.login import LoginType from bacommon.login import LoginType
import _babase import _babase
if TYPE_CHECKING: if TYPE_CHECKING:

View File

@ -208,6 +208,62 @@ class FeatureSet:
' not allowed.' ' not allowed.'
) )
@property
def path_config_file(self) -> str:
"""Project-relative path to the file defining this feature-set."""
return f'config/featuresets/featureset_{self.name}.py'
@property
def path_python_package(self) -> str:
"""Project-relative path for this feature-set's Python package.
Note that this does not mean that the package actually exists;
this just shows where it would.
"""
return f'src/assets/ba_data/python/{self.name_python_package}'
@property
def path_python_package_meta(self) -> str:
"""Project-relative path for this feature-set's Python meta package.
Note that this does not mean that the package actually exists;
this just shows where it would.
"""
return f'src/meta/{self.name_python_package_meta}'
@property
def path_python_package_tests(self) -> str:
"""Project-relative path for this feature-set's Python tests package.
Note that this does not mean that the package actually exists;
this just shows where it would.
"""
return f'tests/{self.name_python_package_tests}'
@property
def path_native_source(self) -> str:
"""Project-relative path for this feature-set's native source.
Note that this does not mean that such source actually exists;
this just shows where it would.
"""
return f'src/ballistica/{self.name}'
@property
def paths(self) -> list[str]:
"""Return all file/dir paths associated with this feature-set.
Paths are project relative and may not actually exist; this just
gives their theoretical locations.
"""
return [
self.path_config_file,
self.path_python_package,
self.path_native_source,
self.path_python_package_meta,
self.path_python_package_tests,
]
@classmethod @classmethod
def get_active(cls) -> FeatureSet: def get_active(cls) -> FeatureSet:
"""Return the FeatureSet currently being defined. """Return the FeatureSet currently being defined.

View File

@ -33,9 +33,9 @@ class Command(Enum):
OVERRIDE = 'override' OVERRIDE = 'override'
DIFF = 'diff' DIFF = 'diff'
BACKPORT = 'backport' BACKPORT = 'backport'
FEATURESETS = 'featuresets'
CREATE = 'create' CREATE = 'create'
ADD_SUBMODULE_PARENT = 'add-submodule-parent' ADD_SUBMODULE_PARENT = 'add-submodule-parent'
FEATURE_SET_LIST = 'fset-list'
FEATURE_SET_COPY = 'fset-copy' FEATURE_SET_COPY = 'fset-copy'
FEATURE_SET_DELETE = 'fset-delete' FEATURE_SET_DELETE = 'fset-delete'
@ -98,7 +98,7 @@ def _main() -> None:
_do_override(src_root, dst_root) _do_override(src_root, dst_root)
elif cmd is Command.BACKPORT: elif cmd is Command.BACKPORT:
_do_backport(src_root, dst_root) _do_backport(src_root, dst_root)
elif cmd is Command.FEATURESETS: elif cmd is Command.FEATURE_SET_LIST:
_do_featuresets(dst_root) _do_featuresets(dst_root)
elif cmd is Command.CREATE: elif cmd is Command.CREATE:
_do_create(src_root, dst_root) _do_create(src_root, dst_root)
@ -166,7 +166,9 @@ def _do_create(src_root: str | None, dst_root: str) -> None:
if len(args) != 2: if len(args) != 2:
raise CleanError(f'Expected a name and path arg; got {args}.') raise CleanError(f'Expected a name and path arg; got {args}.')
# pylint: disable=useless-suppression
name, path = args # pylint: disable=unbalanced-tuple-unpacking name, path = args # pylint: disable=unbalanced-tuple-unpacking
# pylint: enable=useless-suppression
if not name: if not name:
raise CleanError('Name cannot be an empty string.') raise CleanError('Name cannot be an empty string.')
@ -260,24 +262,6 @@ def _do_featuresets(dst_root: str) -> None:
print(f' {Clr.BLU}{fset.name}{Clr.RST}') print(f' {Clr.BLU}{fset.name}{Clr.RST}')
def _fset_paths() -> list[str]:
"""Given a feature-set, return all paths associated with it."""
return [
'config/featuresets/featureset_$(NAME).py',
'src/assets/ba_data/python/$(NAME_PY_PKG)',
'src/ballistica/$(NAME)',
'src/meta/$(NAME_PY_PKG_META)',
]
def _filter_fset_path(path: str, fset: FeatureSet) -> str:
return (
path.replace('$(NAME)', fset.name)
.replace('$(NAME_PY_PKG)', fset.name_python_package)
.replace('$(NAME_PY_PKG_META)', fset.name_python_package_meta)
)
def _do_featureset_delete() -> None: def _do_featureset_delete() -> None:
from batools.featureset import FeatureSet from batools.featureset import FeatureSet
@ -294,9 +278,7 @@ def _do_featureset_delete() -> None:
if not os.path.exists('config/featuresets'): if not os.path.exists('config/featuresets'):
raise CleanError('Cannot run from this directory.') raise CleanError('Cannot run from this directory.')
paths_to_delete: list[str] = [] paths_to_delete: list[str] = fset.paths
for path in _fset_paths():
paths_to_delete.append(_filter_fset_path(path, fset))
print( print(
'\n' + '' * 80 + f'\n{Clr.BLD}Deleting feature-set{Clr.RST}' '\n' + '' * 80 + f'\n{Clr.BLD}Deleting feature-set{Clr.RST}'
@ -309,7 +291,7 @@ def _do_featureset_delete() -> None:
for path in paths_to_delete: for path in paths_to_delete:
if os.path.exists(path): if os.path.exists(path):
found_something = True found_something = True
print(f' Deleting {Clr.MAG}{path}{Clr.RST}') print(f' Deleting {Clr.RED}{path}{Clr.RST}')
subprocess.run(['rm', '-rf', path], check=True) subprocess.run(['rm', '-rf', path], check=True)
if not found_something: if not found_something:
print( print(
@ -362,17 +344,15 @@ def _do_featureset_copy() -> None:
raise CleanError(f"Src feature-set '{src}' not found.") raise CleanError(f"Src feature-set '{src}' not found.")
# Make sure dst does *not* exist (unless we're forcing). # Make sure dst does *not* exist (unless we're forcing).
if os.path.exists(f'config/featuresets/featureset_{dst}.py') and not force: if os.path.exists(dstfs.path_config_file) and not force:
raise CleanError( raise CleanError(
f"Dst feature-set '{dst}' already exists." f"Dst feature-set '{dst}' already exists."
' Use --force to blow it away.' ' Use --force to blow it away.'
) )
paths_to_copy: list[tuple[str, str]] = [] paths_to_copy: list[tuple[str, str]] = []
for path in _fset_paths(): for srcpath, dstpath in zip(srcfs.paths, dstfs.paths):
paths_to_copy.append( paths_to_copy.append((srcpath, dstpath))
(_filter_fset_path(path, srcfs), _filter_fset_path(path, dstfs))
)
# Replace variations of our name. Note that we don't have to include # Replace variations of our name. Note that we don't have to include
# stuff like name_python_package_meta here because that is covered # stuff like name_python_package_meta here because that is covered
@ -387,10 +367,10 @@ def _do_featureset_copy() -> None:
] ]
# Sanity check: we don't currently support renaming subdirs, so error # Sanity check: we don't currently support renaming subdirs, so error
# if that would happen. # if that would need to happen.
for srcpath, _dstpath in paths_to_copy: for srcpath, _dstpath in paths_to_copy:
for root, dirs, _fnames in os.walk(srcpath): for root, dnames, _fnames in os.walk(srcpath):
for dname in dirs: for dname in dnames:
if any(sub[0] in dname for sub in subs): if any(sub[0] in dname for sub in subs):
raise CleanError( raise CleanError(
'Directory name filtering is not supported' 'Directory name filtering is not supported'
@ -451,6 +431,10 @@ def _do_featureset_copy_dir(
# Eww; reinventing the wheel here; should tap into existing # Eww; reinventing the wheel here; should tap into existing
# spinoff logic or something. # spinoff logic or something.
cruft_names = ['.DS_Store', 'mgen', '_mgen'] cruft_names = ['.DS_Store', 'mgen', '_mgen']
cruft_exts = ['.pyc']
def _is_cruft(name: str) -> bool:
return name in cruft_names or any(name.endswith(x) for x in cruft_exts)
# We currently just copy the full dir and then rename/filter # We currently just copy the full dir and then rename/filter
# individual files. If we need to filter subdir names at some point # individual files. If we need to filter subdir names at some point
@ -458,16 +442,19 @@ def _do_featureset_copy_dir(
subprocess.run(['cp', '-r', srcpath, dstpath], check=True) subprocess.run(['cp', '-r', srcpath, dstpath], check=True)
for root, dnames, fnames in os.walk(dstpath, topdown=True): for root, dnames, fnames in os.walk(dstpath, topdown=True):
for dname in dnames: for dname in dnames:
if dname in cruft_names: if _is_cruft(dname):
# Prevent us from recursing into it and blow it away. # Blow away cruft dirs and don't recurse into them.
dnames.remove(dname) dnames.remove(dname)
subprocess.run( subprocess.run(
['rm', '-rf', os.path.join(root, dname)], check=True ['rm', '-rf', os.path.join(root, dname)], check=True
) )
for fname in fnames: for fname in fnames:
if fname in cruft_names: if _is_cruft(fname):
# Blow away and ignore cruft files.
os.unlink(os.path.join(root, fname)) os.unlink(os.path.join(root, fname))
continue continue
# Rename files.
fnamefilt = fname fnamefilt = fname
for subsrc, subdst in subs: for subsrc, subdst in subs:
fnamefilt = fnamefilt.replace(subsrc, subdst) fnamefilt = fnamefilt.replace(subsrc, subdst)
@ -480,7 +467,8 @@ def _do_featureset_copy_dir(
], ],
check=True, check=True,
) )
# Now filter contents.
# Filter file contents.
if not any(fname.endswith(ext) for ext in filtered_exts): if not any(fname.endswith(ext) for ext in filtered_exts):
print( print(
f'{Clr.YLW}WARNING:' f'{Clr.YLW}WARNING:'
@ -593,8 +581,6 @@ def _print_available_commands() -> None:
'Remove files from spinoff, leaving local copies in place.\n' 'Remove files from spinoff, leaving local copies in place.\n'
f' {bgn}backport [file]{end} ' f' {bgn}backport [file]{end} '
'Help get changes to spinoff dst files back to src.\n' 'Help get changes to spinoff dst files back to src.\n'
f' {bgn}featuresets{end} '
'List featuresets present in the current project.\n'
f' {bgn}create [name, path]{end} ' f' {bgn}create [name, path]{end} '
'Create a new spinoff project based on this src one.\n' 'Create a new spinoff project based on this src one.\n'
' Name should be passed in CamelCase form.\n' ' Name should be passed in CamelCase form.\n'
@ -620,13 +606,16 @@ def _print_available_commands() -> None:
' achieved by passing --submodule-parent to' ' achieved by passing --submodule-parent to'
' the \'create\'\n' ' the \'create\'\n'
' command.\n' ' command.\n'
f' {bgn}fset-copy [src, dst]{end} Copy feature-set src to dst.' f' {bgn}fset-list{end} '
' Replaces variations of src\n' 'List featuresets present in the current project.\n'
' feature-set name with dst equivalent,' f' {bgn}fset-copy [src, dst]{end} Copy feature-set src to dst'
' though may need\n' ' in the current project.\n'
' Replaces variations of src feature-set'
' name with equivalent from dst, though may need\n'
' some manual correction afterwards to be' ' some manual correction afterwards to be'
' functional.\n' ' functional.\n'
f' {bgn}fset-delete [name]{end} Delete a feature-set.' f' {bgn}fset-delete [name]{end} Delete a feature-set from the'
' current project.'
), ),
file=sys.stderr, file=sys.stderr,
) )