latest bacloud work

This commit is contained in:
Eric Froemling 2020-01-14 12:24:32 -08:00
parent 9228d5fd82
commit 4255a2d048
2 changed files with 45 additions and 42 deletions

View File

@ -49,8 +49,6 @@ TOOL_NAME = 'bacloud'
MASTER_SERVER_ADDRESS = ('http://localhost:23524' MASTER_SERVER_ADDRESS = ('http://localhost:23524'
if os.environ.get('BACLOUD_LOCAL') == '1' else if os.environ.get('BACLOUD_LOCAL') == '1' else
'https://bamaster.appspot.com') 'https://bamaster.appspot.com')
STATE_DIR = Path('.cache/bacloud')
STATE_DATA_PATH = Path(STATE_DIR, 'state')
CLRHDR = '\033[95m' # Header. CLRHDR = '\033[95m' # Header.
CLRGRN = '\033[92m' # Green. CLRGRN = '\033[92m' # Green.
@ -109,7 +107,7 @@ def get_tz_offset_seconds() -> float:
@dataclass @dataclass
class File: class PackageFile:
"""Represents a single file within a Package.""" """Represents a single file within a Package."""
filehash: str filehash: str
filesize: int filesize: int
@ -120,7 +118,7 @@ class Package:
def __init__(self) -> None: def __init__(self) -> None:
self.path = Path('') self.path = Path('')
self.files: Dict[str, File] = {} self.files: Dict[str, PackageFile] = {}
@classmethod @classmethod
def load_from_disk(cls, path: Path) -> Package: def load_from_disk(cls, path: Path) -> Package:
@ -143,7 +141,7 @@ class Package:
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from multiprocessing import cpu_count from multiprocessing import cpu_count
def _get_file_info(filepath: str) -> Tuple[str, File]: def _get_file_info(filepath: str) -> Tuple[str, PackageFile]:
sha = hashlib.sha256() sha = hashlib.sha256()
fullfilepath = os.path.join(packagepathstr, filepath) fullfilepath = os.path.join(packagepathstr, filepath)
if not os.path.isfile(fullfilepath): if not os.path.isfile(fullfilepath):
@ -152,8 +150,8 @@ class Package:
filebytes = infile.read() filebytes = infile.read()
filesize = len(filebytes) filesize = len(filebytes)
sha.update(filebytes) sha.update(filebytes)
return (filepath, File(filehash=sha.hexdigest(), return (filepath,
filesize=filesize)) PackageFile(filehash=sha.hexdigest(), filesize=filesize))
# Now use all procs to hash the files efficiently. # Now use all procs to hash the files efficiently.
with ThreadPoolExecutor(max_workers=cpu_count()) as executor: with ThreadPoolExecutor(max_workers=cpu_count()) as executor:
@ -168,49 +166,60 @@ class App:
def __init__(self) -> None: def __init__(self) -> None:
self._state = StateData() self._state = StateData()
self._package: Optional[Package] = None self._package: Optional[Package] = None
self._project_root: Optional[Path] = None
def run(self) -> None: def run(self) -> None:
"""Run the tool.""" """Run the tool."""
# Make reasonably sure we're being run from project root. # Make sure we can locate the project bacloud is being run from.
if not os.path.exists(f'tools/{TOOL_NAME}'): self._project_root = Path(sys.argv[0]).parents[1]
raise CleanError( if not all(
'This tool must be run from ballistica project root.') Path(self._project_root, name).is_dir()
for name in ('tools', 'config', 'tests')):
raise CleanError('Unable to locate project directory.')
# Also run project prereqs checks so we can hopefully inform the user # Also run project prereqs checks so we can hopefully inform the user
# of missing python modules/etc. instead of just failing cryptically. # of missing python modules/etc. instead of just failing cryptically.
try: try:
subprocess.run(['make', '--quiet', 'prereqs'], check=True) subprocess.run(['make', '--quiet', 'prereqs'],
check=True,
cwd=self._project_root)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
raise CleanError('"make prereqs" check failed. ' raise CleanError('"make prereqs" check failed. '
'Install missing requirements and try again.') 'Install missing requirements and try again.')
self._load_state() self._load_state()
if len(sys.argv) < 2:
print(f'{CLRRED}You must provide one or more arguments.{CLREND}')
self.run_command(['help'])
raise CleanError()
# Simply pass all args to the server and let it do the thing. # Simply pass all args to the server and let it do the thing.
self.run_command(sys.argv[1:]) self.run_user_command(sys.argv[1:])
self._save_state() self._save_state()
@property
def _state_dir(self) -> Path:
"""The full path to the state dir."""
assert self._project_root is not None
return Path(self._project_root, '.cache/bacloud')
@property
def _state_data_path(self) -> Path:
"""The full path to the state data file."""
return Path(self._state_dir, 'state')
def _load_state(self) -> None: def _load_state(self) -> None:
if not os.path.exists(STATE_DATA_PATH): if not os.path.exists(self._state_data_path):
return return
try: try:
with open(STATE_DATA_PATH, 'r') as infile: with open(self._state_data_path, 'r') as infile:
self._state = StateData(**json.loads(infile.read())) self._state = StateData(**json.loads(infile.read()))
except Exception: except Exception:
print(f'{CLRRED}Error loading {TOOL_NAME} data;' print(f'{CLRRED}Error loading {TOOL_NAME} data;'
f' resetting to defaults.{CLREND}') f' resetting to defaults.{CLREND}')
def _save_state(self) -> None: def _save_state(self) -> None:
if not STATE_DIR.exists(): if not self._state_dir.exists():
STATE_DIR.mkdir(parents=True, exist_ok=True) self._state_dir.mkdir(parents=True, exist_ok=True)
with open(STATE_DATA_PATH, 'w') as outfile: with open(self._state_data_path, 'w') as outfile:
outfile.write(json.dumps(self._state.__dict__)) outfile.write(json.dumps(self._state.__dict__))
def _servercmd(self, def _servercmd(self,
@ -242,12 +251,12 @@ class App:
# Handle common responses (can move these out of here at some point) # Handle common responses (can move these out of here at some point)
if response.error is not None:
raise CleanError(response.error)
if response.message is not None: if response.message is not None:
print(response.message) print(response.message)
if response.error is not None:
raise CleanError(response.error)
return response return response
def _upload_file(self, filename: str, call: str, args: Dict) -> None: def _upload_file(self, filename: str, call: str, args: Dict) -> None:
@ -319,16 +328,15 @@ class App:
# Lastly, run the 'upload complete' command we were passed. # Lastly, run the 'upload complete' command we were passed.
return completecmd, completeargs return completecmd, completeargs
def run_command(self, args: List[str]) -> None: def run_user_command(self, args: List[str]) -> None:
"""Run a command to completion.""" """Run a single user command to completion."""
nextcall: Optional[Tuple[str, Dict]] = ('toplevel', {'a': args}) nextcall: Optional[Tuple[str, Dict]] = ('user', {'a': args})
# Now talk to the server in a loop until they are done with us. # Now talk to the server in a loop until there's nothing left to do.
while nextcall is not None: while nextcall is not None:
response = self._servercmd(*nextcall) response = self._servercmd(*nextcall)
nextcall = None nextcall = None
if response.loadpackage is not None: if response.loadpackage is not None:
nextcall = self._handle_loadpackage_response(response) nextcall = self._handle_loadpackage_response(response)
if response.upload is not None: if response.upload is not None:

View File

@ -33,12 +33,6 @@ if TYPE_CHECKING:
# Overall version we're using for the game currently. # Overall version we're using for the game currently.
PYTHON_VERSION_MAJOR = "3.7" PYTHON_VERSION_MAJOR = "3.7"
# Specific version we're using on apple builds.
# PYTHON_VERSION_APPLE = "3.7.0"
# Specific version we're using on android builds.
# PYTHON_VERSION_ANDROID = "3.7.2"
ENABLE_OPENSSL = True ENABLE_OPENSSL = True
@ -51,7 +45,10 @@ def build_apple(arch: str, debug: bool = False) -> None:
'git@github.com:pybee/Python-Apple-support.git "' + 'git@github.com:pybee/Python-Apple-support.git "' +
builddir + '"') builddir + '"')
os.chdir(builddir) os.chdir(builddir)
efrotools.run('git checkout 3.7')
# TEMP: Check out a particular commit while the branch head is broken.
# efrotools.run('git checkout 1a9c71dca298c03517e8236b81cf1d9c8c521cbf')
efrotools.run(f'git checkout {PYTHON_VERSION_MAJOR}')
# On mac we currently have to add the _scproxy module or urllib will # On mac we currently have to add the _scproxy module or urllib will
# fail. # fail.
@ -137,9 +134,6 @@ def build_apple(arch: str, debug: bool = False) -> None:
txt = efrotools.replace_one( txt = efrotools.replace_one(
txt, '&& PATH=$(PROJECT_DIR)/$(PYTHON_DIR-macOS)/dist/bin:$(PATH) .', txt, '&& PATH=$(PROJECT_DIR)/$(PYTHON_DIR-macOS)/dist/bin:$(PATH) .',
'&& PATH="$(PROJECT_DIR)/$(PYTHON_DIR-macOS)/dist/bin:$(PATH)" .') '&& PATH="$(PROJECT_DIR)/$(PYTHON_DIR-macOS)/dist/bin:$(PATH)" .')
# txt = efrotools.replace_one(
# txt, '&& PATH=$(PROJECT_DIR)/$(PYTHON_DIR-macOS)/dist/bin:$(PATH) m',
# '&& PATH="$(PROJECT_DIR)/$(PYTHON_DIR-macOS)/dist/bin:$(PATH)" m')
# Remove makefile dependencies so we don't build the # Remove makefile dependencies so we don't build the
# libs we're not using. # libs we're not using.
@ -304,7 +298,8 @@ def build_android(rootdir: str, arch: str, debug: bool = False) -> None:
# Set this to a particular cpython commit to target exact releases from git # Set this to a particular cpython commit to target exact releases from git
# commit = 'e09359112e250268eca209355abeb17abf822486' # 3.7.4 release # commit = 'e09359112e250268eca209355abeb17abf822486' # 3.7.4 release
commit = '5c02a39a0b31a330e06b4d6f44835afb205dc7cc' # 3.7.5 release # commit = '5c02a39a0b31a330e06b4d6f44835afb205dc7cc' # 3.7.5 release
commit = '43364a7ae01fbe4288ef42622259a0038ce1edcc' # 3.7.6 release
if commit is not None: if commit is not None:
ftxt = efrotools.readfile('pybuild/source.py') ftxt = efrotools.readfile('pybuild/source.py')