def _cmd_init(args, extra=None): if os.path.isfile( os.path.join(JustUpdateConstants.REPO_FOLDER, "config.ju")) or os.path.isdir( JustUpdateConstants.REPO_FOLDER): logging.warning( "A JustUpdate repository already exists at this location.") return True # setup a new repo. app_name = prompt("Application Name:", "MyAwezomeApp") app_author = prompt("Application Author:", "MyAwesomeCompany") update_url = prompt("Url to ping for updates:") client_config_dir = prompt( "Where to place the client_config.py file (used by your application): ", default=".") if update_url.endswith("/") == False: update_url += "/" logging.info("Creating folder structure.") os.makedirs(JustUpdateConstants.REPO_FOLDER) logging.info("Creating config.") c = Config() c.set("app_name", app_name) c.set("app_author", app_author) c.set("update_url", update_url) c.save(os.path.join(JustUpdateConstants.REPO_FOLDER, "config.ju")) logging.info("Saving config.") logging.info("Copying templates.") shutil.copytree( os.path.join(JustUpdateConstants.MODULE_FOLDER, "templates"), os.path.join(JustUpdateConstants.REPO_FOLDER, "templates")) logging.info("Templates copied.") logging.info("Creating client config.") client_config_data = """class ClientConfig(): app_name = "{}" app_author = "{}" update_url = "{}" """.format(app_name, app_author, update_url) with open(os.path.join(client_config_dir, "client_config.py"), "w") as cc: cc.write(client_config_data) logging.info("Initialization done.")
def prepare_template(version): config = Config() config.load(os.path.join(JustUpdateConstants.REPO_FOLDER, "config.ju")) cmd = getattr(sys.modules[__name__], "_prepare_template_{}".format(get_platform_name_short())) return cmd(version, config)
def __init__(self): self.config = Config() self.config.load( os.path.join(JustUpdateConstants.REPO_FOLDER, "config.ju"))
class Builder(): def __init__(self): self.config = Config() self.config.load( os.path.join(JustUpdateConstants.REPO_FOLDER, "config.ju")) def clean(self): try: shutil.rmtree(os.path.join(JustUpdateConstants.REPO_FOLDER, "work")) except FileNotFoundError: pass # It's ok if the folder doesn't exist. cmd = getattr(self, f"_clean_{get_platform_name_short()}") return cmd() def _clean_win(self): try: shutil.rmtree( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "win")) except FileNotFoundError: pass # It's ok if the folder doesn't exist. def _clean_mac(self): try: shutil.rmtree( os.path.join(os.getcwd(), JustUpdateConstants.REPO_FOLDER, "dist", "mac")) except FileNotFoundError: pass # It's ok if the folder doesn't exist. try: shutil.rmtree( os.path.join(os.getcwd(), JustUpdateConstants.REPO_FOLDER, "dist", "{}.app".format(self.config.get("app_name")))) except FileNotFoundError: pass # It's ok if the folder doesn't exist. try: os.remove( os.path.join(os.getcwd(), JustUpdateConstants.REPO_FOLDER, "dist", "mac")) except FileNotFoundError: pass # It's ok if the folder doesn't exist. def build(self, args, extra_args): cmd = [ "pyinstaller", "--distpath", os.path.join(os.getcwd(), JustUpdateConstants.REPO_FOLDER, "dist"), "--workpath", os.path.join(os.getcwd(), JustUpdateConstants.REPO_FOLDER, "work"), "-y", args ] + extra_args executor = CommandExecutor() logging.info("Building.") result, stdout = executor.execute(cmd, CommandType.RAW) if result > 0: # error print(stdout) logging.error("Please correct the errors above and try again.") else: logging.info("Build completed.") return result == 0 def post_build(self): cmd = getattr(self, f"_post_build_{get_platform_name_short()}") return cmd() def _post_build_win(self): logging.info("Checking build integrity") if os.path.isdir( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "win")) == False: logging.error("Unable to find the build fonder.") app_name = self.config.get("app_name") # First look for .exe.manifest, and rename that if it exists. try: os.rename( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "win", "win.exe.manifest"), os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "win", f"{app_name}.exe.manifest")) except: pass # then try for the exe itself. try: os.rename( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "win", "win.exe"), os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "win", f"{app_name}.exe")) except: raise logging.info("Done") def _post_build_mac(self): if os.path.isfile( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "mac")): # asume unix executable. raise ValueError( "--onefile is not supported at the moment. For now the only mode supported are --onedir --windowed (creating an application bundle)" ) return if os.path.isdir( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "mac.app")): # asume mac application bundle. os.rename( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "mac.app", "Contents", "MacOS", "mac"), os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "mac.app", "Contents", "MacOS", self.config.get("app_name"))) os.rename( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "mac.app"), os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "{}.app".format(self.config.get("app_name")))) # also temporary update the plist file (note it will be overwritten in commit, only reason to do this, is so the end developer can test the app before commiting). with open(os.path.join( JustUpdateConstants.REPO_FOLDER, "dist", "{}.app".format(self.config.get("app_name")), "Contents", "Info.plist"), encoding="utf-8") as f: plist_data = f.readlines() new_plist_data = [] for d in plist_data: if "mac" in d: new_plist_data.append( d.replace("mac", self.config.get("app_name"))) else: new_plist_data.append(d) with open(os.path.join( JustUpdateConstants.REPO_FOLDER, "dist", "{}.app".format(self.config.get("app_name")), "Contents", "Info.plist"), "w", encoding="utf-8") as f: for d in new_plist_data: f.write(d)
def __init__(self, version): self.config = Config() self.config.load( os.path.join(JustUpdateConstants.REPO_FOLDER, "config.ju")) self.version = Version(version) self.executor = CommandExecutor()
class Committer(): def __init__(self, version): self.config = Config() self.config.load( os.path.join(JustUpdateConstants.REPO_FOLDER, "config.ju")) self.version = Version(version) self.executor = CommandExecutor() def setup(self): if os.path.isdir(os.path.join(JustUpdateConstants.REPO_FOLDER, "new")) == False: os.makedirs(os.path.join(JustUpdateConstants.REPO_FOLDER, "new")) if os.path.isdir( os.path.join(JustUpdateConstants.REPO_FOLDER, "deploy")) == False: os.makedirs(os.path.join(JustUpdateConstants.REPO_FOLDER, "deploy")) def insure_build_availability(self): cmd = getattr( self, "_insure_build_availability_{}".format(get_platform_name_short())) return cmd() def produce_executable(self): cmd = getattr( self, "_produce_executable_{}".format(get_platform_name_short())) return cmd() def create_metadata(self): cmd = getattr(self, "_create_metadata_{}".format(get_platform_name_short())) return cmd() def finalize(self): cmd = getattr(self, "_finalize_{}".format(get_platform_name_short())) return cmd() def _insure_build_availability_win(self): if os.path.isdir( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "win")) == False: return False if not os.listdir( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "win")): return False return True def _insure_build_availability_mac(self): if not os.path.isdir( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "{}.app".format(self.config.get("app_name")))): return False return True def _produce_executable_win(self): tmp = template.prepare_template(self.version) cmd = ["makensis", "/V1", "-"] result, stdout = self.executor.execute(cmd, CommandType.RAW, stdin=tmp) if result != 0: print(stdout) logging.error("Please correct the errors above and try again.") return False return True def _produce_executable_mac(self): logging.debug("Updating Info.plist and installation scripts.") tmp = template.prepare_template(self.version) logging.debug("Assembling pkg installer.") cmd = [ "productbuild", "--scripts", os.path.join(JustUpdateConstants.REPO_FOLDER, "templates", "mac", "scripts"), "--component", os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "{}.app".format(self.config.get("app_name"))), "/Applications", os.path.join( JustUpdateConstants.REPO_FOLDER, "new", "{0}-{1}.pkg".format(self.config.get("app_name"), self.version.to_string())) ] result, stdout = self.executor.execute(cmd, CommandType.RAW) if result != 0: print(stdout) logging.error("Please correct the errors above and try again.") return False return True def _create_metadata_win(self): logging.info("Calculating checksum.") checksum = data_manager.calculate_checksum( os.path.join( JustUpdateConstants.REPO_FOLDER, "new", "{0}-{1}.exe".format(self.config.get("app_name"), self.version.to_string()))) logging.info("Looking for existing metadata.") md = MetaData() md.apply_metadata(md.load()) md.add_metadata( "{0}-{1}.exe".format(self.config.get("app_name"), self.version.to_string()), checksum, self.version.to_string()) logging.info("Saving updated metadata.") md.save( ) # The updated metadata is saved to "ju-repo/deploy/metadata.ju". return True def _create_metadata_mac(self): logging.info("Calculating checksum.") checksum = data_manager.calculate_checksum( os.path.join( JustUpdateConstants.REPO_FOLDER, "new", "{0}-{1}.pkg".format(self.config.get("app_name"), self.version.to_string()))) logging.info("Looking for existing metadata.") md = MetaData() md.apply_metadata(md.load()) md.add_metadata( "{0}-{1}.pkg".format(self.config.get("app_name"), self.version.to_string()), checksum, self.version.to_string()) logging.info("Saving updated metadata.") md.save( ) # The updated metadata is saved to "ju-repo/deploy/metadata.ju". return True def _finalize_win(self): logging.info("Moving executable.") shutil.move( os.path.join( JustUpdateConstants.REPO_FOLDER, "new", "{0}-{1}.exe".format(self.config.get("app_name"), self.version.to_string())), os.path.join(JustUpdateConstants.REPO_FOLDER, "deploy")) #cleanup ju-repo/dist/win shutil.rmtree( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "win")) def _finalize_mac(self): logging.info("Moving executable.") shutil.move( os.path.join( JustUpdateConstants.REPO_FOLDER, "new", "{0}-{1}.pkg".format(self.config.get("app_name"), self.version.to_string())), os.path.join(JustUpdateConstants.REPO_FOLDER, "deploy")) #cleanup ju-repo/dist/mac try: shutil.rmtree( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "mac")) except: pass try: shutil.rmtree( os.path.join(JustUpdateConstants.REPO_FOLDER, "dist", "{}.app".format(self.config.get("app_name")))) except: pass