def check_ue4_file_association(): if os.name == 'nt': file_assoc_result = pbtools.get_combined_output( ["assoc", uproject_ext]) return "Unreal.ProjectFile" in file_assoc_result else: return True
def check_remote_connection(): current_url = pbtools.get_one_line_output( ["git", "remote", "get-url", "origin"]) recent_url = pbconfig.get("git_url") if current_url != recent_url: output = pbtools.get_combined_output( ["git", "remote", "set-url", "origin", recent_url]) pblog.info(output) current_url = pbtools.get_one_line_output( ["git", "remote", "get-url", "origin"]) out = pbtools.run_with_output(["git", "ls-remote", "--exit-code", "-h"]).returncode return out == 0, current_url
def push_package(version_number, file_name): if not os.path.exists(file_name): pblog.error(f"Provided file {file_name} doesn't exist") return False try: output = pbtools.get_combined_output([hub_executable_path, "release", "edit", version_number, "-m", "", "-a", file_name]) if "Attaching 1 asset..." in output: return True else: pblog.error(output) except Exception as e: pblog.exception(str(e)) pblog.error(f"Error occurred while attaching {file_name} into release {version_number}") return False
def get_latest_available_engine_version(bucket_url): output = pbtools.get_combined_output(["gsutil", "ls", bucket_url]) build_type = pbconfig.get("ue4v_default_bundle") if pbconfig.get("is_ci"): # We should get latest version of ciengine instead build_type = pbconfig.get("ue4v_ci_bundle") # e.g, "engine-4.24-PB" regex_prefix = f"{build_type}-{pbconfig.get('engine_base_version')}-{engine_version_prefix}" versions = re.findall(regex_prefix + "-[0-9]{8}", output) if len(versions) == 0: return None # Find the latest version by sorting versions.sort() # Strip the build type prefix back result = str(versions[len(versions) - 1]) result = result.replace(f"{build_type}-", '') return result.rstrip()
def stash_pop(): pblog.info("Trying to pop stash...") output = pbtools.get_combined_output(["git", "stash", "pop"]) pblog.info(output) lower_case_output = output.lower() if "auto-merging" in lower_case_output and "conflict" in lower_case_output and "should have been pointers" in lower_case_output: pbtools.error_state( """git stash pop failed. Some of your stashed local changes would be overwritten by incoming changes. Request help in #tech-support to resolve conflicts, and please do not run StartProject.bat until the issue is resolved.""", True) elif "dropped refs" in lower_case_output: return elif "no stash entries found" in lower_case_output: return else: pbtools.error_state( """git stash pop failed due to an unknown error. Request help in #tech-support to resolve possible conflicts, and please do not run StartProject.bat until the issue is resolved.""", True)
def set_tracking_information(upstream_branch_name: str): output = pbtools.get_combined_output([ "git", "branch", f"--set-upstream-to=origin/{upstream_branch_name}", upstream_branch_name ]) pblog.info(output)
def sync_handler(sync_val: str, repository_val=None, requested_bundle_name=None): sync_val = sync_val.lower() if sync_val == "all" or sync_val == "force": # Firstly, check our remote connection before doing anything remote_state, remote_url = pbgit.check_remote_connection() if not remote_state: pbtools.error_state( f"Remote connection was not successful. Please verify that you have a valid git remote URL & internet connection. Current git remote URL: {remote_url}") else: pblog.info("Remote connection is up") pblog.info("------------------") pblog.info(f"Executing {sync_val} sync command") pblog.info(f"PBpy Library Version: {pbpy_version.ver}") pblog.info(f"PBSync Program Version: {pbsync_version.ver}") pblog.info("------------------") detected_git_version = pbgit.get_git_version() needs_git_update = False if detected_git_version == pbconfig.get('supported_git_version'): pblog.info(f"Current Git version: {detected_git_version}") else: pblog.error("Git is not updated to the supported version in your system") pblog.error(f"Supported Git Version: {pbconfig.get('supported_git_version')}") pblog.error(f"Current Git Version: {detected_git_version}") pblog.error("Please install the supported Git version from https://github.com/microsoft/git/releases") pblog.error("Visit https://github.com/ProjectBorealisTeam/pb/wiki/Prerequisites for installation instructions") if os.name == "nt": webbrowser.open(f"https://github.com/microsoft/git/releases/download/v{pbconfig.get('supported_git_version')}/Git-{pbconfig.get('supported_git_version')}-64-bit.exe") needs_git_update = True if os.name == "nt": # find Git/cmd/git.exe git_paths = [path for path in pbtools.whereis("git") if "cmd" in path.parts] if len(git_paths) > 0: bundled_git_lfs = False is_admin = pbuac.isUserAdmin() delete_paths = [] for git_path in git_paths: # find Git from Git/cmd/git.exe git_root = git_path.parents[1] possible_lfs_paths = ["cmd/git-lfs.exe", "mingw64/bin/git-lfs.exe", "mingw64/libexec/git-core/git-lfs.exe"] for possible_lfs_path in possible_lfs_paths: path = git_root / possible_lfs_path if path.exists(): try: if is_admin: path.unlink() else: delete_paths.append(str(path)) except FileNotFoundError: pass except OSError: pblog.error(f"Git LFS is bundled with Git, overriding your installed version. Please remove {path}.") bundled_git_lfs = True if not is_admin and len(delete_paths) > 0: pblog.info("Requesting permission to delete bundled Git LFS which is overriding your installed version...") quoted_paths = [f'"{path}"' for path in delete_paths] delete_cmdline = ["cmd.exe", "/c", "DEL", "/q", "/f"] + quoted_paths try: ret = pbuac.runAsAdmin(delete_cmdline) except OSError: pblog.error("User declined permission. Automatic delete failed.") for delete_path in delete_paths: path = pathlib.Path(delete_path) if path.exists(): bundled_git_lfs = True pblog.error(f"Git LFS is bundled with Git, overriding your installed version. Please remove {path}.") if bundled_git_lfs: pbtools.error_state() detected_lfs_version = pbgit.get_lfs_version() if detected_lfs_version == pbconfig.get('supported_lfs_version'): pblog.info(f"Current Git LFS version: {detected_lfs_version}") else: pblog.error("Git LFS is not updated to the supported version in your system") pblog.error(f"Supported Git LFS Version: {pbconfig.get('supported_lfs_version')}") pblog.error(f"Current Git LFS Version: {detected_lfs_version}") pblog.error("Please install the supported Git LFS version from https://git-lfs.github.com") if os.name == "nt": supported_lfs_version = pbconfig.get('supported_lfs_version').split("/")[1] webbrowser.open(f"https://github.com/git-lfs/git-lfs/releases/download/v{supported_lfs_version}/git-lfs-windows-v{supported_lfs_version}.exe") needs_git_update = True if needs_git_update: pbtools.error_state() pblog.info("------------------") # Do not execute if Unreal Editor is running if pbtools.get_running_process("UE4Editor") is not None: pbtools.error_state("Unreal Editor is currently running. Please close it before running PBSync. It may be listed only in Task Manager as a background process. As a last resort, you should log off and log in again.") current_branch = pbgit.get_current_branch_name() # repo was already fetched in StartProject.bat if current_branch != "promoted": pblog.info("Fetching recent changes on the repository...") fetch_base = ["git", "fetch", "origin"] branches = {"promoted", "master", "trunk", current_branch} fetch_base.extend(branches) pbtools.get_combined_output(fetch_base) # Do some housekeeping for git configuration pbgit.setup_config() # Check if we have correct credentials pbgit.check_credentials() pblog.info("------------------") # Execute synchronization part of script if we're on the expected branch, or force sync is enabled is_on_expected_branch = pbgit.compare_with_current_branch_name(pbconfig.get('expected_branch_name')) if sync_val == "force" or is_on_expected_branch: pbtools.resolve_conflicts_and_pull() pblog.info("------------------") project_version = pbunreal.get_project_version() if project_version is not None: pblog.info(f"Current project version: {project_version}") else: pbtools.error_state( "Something went wrong while fetching project version. Please request help in #tech-support.") if pbhub.is_pull_binaries_required(): pblog.info("Binaries are not up to date, trying to pull new binaries...") ret = pbhub.pull_binaries(project_version) if ret == 0: pblog.info("Binaries were pulled successfully") elif ret < 0: pbtools.error_state("Binaries pull failed, please view log for instructions.") elif ret > 0: pbtools.error_state("An error occurred while pulling binaries. Please request help in #tech-support to resolve it, and please do not run StartProject.bat until the issue is resolved.", True) else: pblog.info("Binaries are up-to-date") else: pblog.warning(f"Current branch is not supported for repository synchronization: {pbgit.get_current_branch_name()}. Auto synchronization " "will be disabled") pblog.info("------------------") pblog.info("Checking for engine updates...") if pbgit.sync_file("ProjectBorealis.uproject") != 0: pbtools.error_state( "Something went wrong while updating the .uproject file. Please request help in #tech-support.") engine_version = pbunreal.get_engine_version(False) pblog.info("Trying to register current engine build if it exists. Otherwise, the build will be downloaded...") symbols_needed = pbunreal.is_versionator_symbols_enabled() bundle_name = pbconfig.get("ue4v_default_bundle") if pbunreal.run_ue4versionator(bundle_name, symbols_needed) != 0: pblog.error(f"Something went wrong while registering engine build {bundle_name}-{engine_version}. Please request help in #tech-support.") sys.exit(1) else: pblog.info(f"Engine build {bundle_name}-{engine_version} successfully registered") # Clean old engine installations, do that only in expected branch if is_on_expected_branch: if pbunreal.clean_old_engine_installations(): pblog.info("Old engine installations are successfully cleaned") else: pblog.warning("Something went wrong while cleaning old engine installations. You may want to clean them manually.") pblog.info("------------------") if pbunreal.check_ue4_file_association(): try: os.startfile(os.path.normpath(os.path.join(os.getcwd(), "ProjectBorealis.uproject"))) except NotImplementedError: pblog.info("You may now launch ProjectBorealis.uproject with Unreal Engine 4.") else: pbtools.error_state(".uproject extension is not correctly set into Unreal Engine. Make sure you have Epic Games Launcher installed. If problem still persists, please get help in #tech-support.") elif sync_val == "engineversion": if repository_val is None: pblog.error("--repository <URL> argument should be provided with --sync engine command") sys.exit(1) engine_version = pbunreal.get_latest_available_engine_version(str(repository_val)) if engine_version is None: pblog.error("Error while trying to fetch latest engine version") sys.exit(1) if not pbunreal.set_engine_version(engine_version): pblog.error("Error while trying to update engine version in .uproject file") sys.exit(1) pblog.info(f"Successfully changed engine version as {str(engine_version)}") elif sync_val == "ddc": pbunreal.generate_ddc_data() elif sync_val == "binaries": project_version = pbunreal.get_project_version() ret = pbhub.pull_binaries(project_version, True) if ret == 0: pblog.info(f"Binaries for {project_version} pulled & extracted successfully") else: pblog.error(f"Failed to pull binaries for {project_version}") sys.exit(1) elif sync_val == "engine": # Pull engine build with ue4versionator & register it if requested_bundle_name is None: requested_bundle_name = pbconfig.get("ue4v_default_bundle") engine_version = pbunreal.get_engine_version(False) if pbunreal.run_ue4versionator(requested_bundle_name) != 0: pblog.error(f"Something went wrong while registering engine build {requested_bundle_name}-{engine_version}") sys.exit(1) else: pblog.info(f"Engine build {requested_bundle_name}-{engine_version} successfully registered")
def pull_binaries(version_number: str, pass_checksum=False): if not os.path.isfile(hub_executable_path): pblog.error(f"Hub executable is not found at {hub_executable_path}") return 1 # Backward compatibility with old PBGet junctions. If it still exists, remove the junction if pbtools.is_junction("Binaries") and not pbtools.remove_junction("Binaries"): pblog.error("Something went wrong while removing junction for 'Binaries' folder. You should remove that folder manually to solve the problem") return -1 # Remove binary package if it exists, hub is not able to overwrite existing files if os.path.exists(binary_package_name): try: os.remove(binary_package_name) except Exception as e: pblog.exception(str(e)) pblog.error(f"Exception thrown while trying to remove {binary_package_name}. Please remove it manually") return -1 if not os.path.isfile(hub_config_path): pblog.info("You will now be asked to log in to your GitHub account. Please note that for security reasons, your password will not be shown as you type it.") # If user didn't login with hub yet, do it now for once output = pbtools.run([hub_executable_path, "release", "-L", "1"]) if not os.path.isfile(hub_config_path): pblog.error("Failed to login into hub with git credentials. Please check if your provided credentials are valid.") return pull_binaries(version_number, pass_checksum) else: pblog.info("Login to hub API was successful") try: output = pbtools.get_combined_output([hub_executable_path, "release", "download", version_number, "-i", binary_package_name]) if f"Downloading {binary_package_name}" in output: pass elif "Unable to find release with tag name" in output: pblog.error(f"Failed to find release tag {version_number}. Please wait and try again later.") return -1 elif "The file exists" in output: pblog.error(f"File {binary_package_name} was not able to be overwritten. Please remove it manually and run StartProject again.") return -1 elif "did not match any available assets" in output: pblog.error("Binaries for release {version_number} are not pushed into GitHub yet. Please wait and try again later.") return -1 elif not output: # hub doesn't print any output if package doesn't exist in release pblog.error(f"Failed to find binary package for release {version_number}") return 1 else: pblog.error(f"Unknown error occurred while pulling binaries for release {version_number}") pblog.error(f"Command output was: {output}") return 1 except Exception as e: pblog.exception(str(e)) pblog.error( f"Exception thrown while trying do pull binaries for {version_number}") return 1 # Temp fix for Binaries folder with unnecessary content if os.path.isdir("Binaries"): try: shutil.rmtree("Binaries") except Exception as e: pblog.exception(str(e)) pblog.error("Exception thrown while trying do clean Binaries folder") return 1 try: if pass_checksum: checksum_json_path = None else: checksum_json_path = pbconfig.get("checksum_file") if not os.path.exists(checksum_json_path): pblog.error(f"Checksum json file is not found at {checksum_json_path}") return 1 if not pbtools.compare_md5_single(binary_package_name, checksum_json_path): return 1 with ZipFile(binary_package_name) as zip_file: zip_file.extractall() if pass_checksum: return 0 elif not pbtools.compare_md5_all(checksum_json_path, True): return 1 except Exception as e: pblog.exception(str(e)) pblog.error(f"Exception thrown while trying do extract binary package for {version_number}") return 1 return 0