def _run_bin(self, cwd: pathlib.Path, cmd: str, *args): """ Execute binary with arguments in specified directory. :param cwd: Directory in which the binary will be invoked :param cmd: Binary definition invoked with shell :param args: :raises exceptions.RepoException: If the binary exited with non-zero status :return: """ os.chdir(str(cwd)) full_cmd = f'{cmd} {" ".join(args)}' logger.info(f'Running shell command "{full_cmd}" with cwd={cwd}') r = subprocess.run(full_cmd, shell=True, capture_output=True) if r.returncode != 0: r.stderr and logger.debug(f'STDERR: {r.stderr.decode("utf-8")}') r.stdout and logger.debug(f'STDOUT: {r.stdout.decode("utf-8")}') raise exceptions.RepoException( f'\'{cmd}\' binary exited with non-zero code!')
def _remove_glob(self, path: pathlib.Path, glob: str): """ Removes all files from path that matches the glob string. :param path: :param glob: :return: """ for path_to_delete in path.glob(glob): path_to_delete = path_to_delete.resolve() if not path_to_delete.exists(): continue if path not in path_to_delete.parents: raise exceptions.RepoException( f'Trying to delete file outside the repo temporary directory! {path_to_delete}' ) if path_to_delete.is_file(): path_to_delete.unlink() else: shutil.rmtree(str(path_to_delete))
def __init__(self, git_repo_url, **kwargs): if not is_github_url(git_repo_url): raise exceptions.RepoException('The passed Git repo URL is not related to GitHub!') super().__init__(git_repo_url=git_repo_url, **kwargs)
def bootstrap_repo(cls, config: config_module.Config, name=None, git_repo_url=None, branch=None, secret=None, ipns_key=None, ipns_lifetime=None, pin=None, republish=None, after_publish_bin=None, build_bin=None, publish_dir: typing.Optional[str] = None, ipns_ttl=None) -> 'GenericRepo': """ Method that interactively bootstraps the repository by asking interactive questions. :param ipns_ttl: :param config: :param name: :param git_repo_url: :param branch: :param secret: :param ipns_key: :param ipns_lifetime: :param pin: :param republish: :param after_publish_bin: :param build_bin: :param publish_dir: :return: """ git_repo_url = cls.bootstrap_property('Git repo URL', 'text', 'Git URL of the repo', git_repo_url, validate=lambda _, x: validate_repo(x)) name = cls.bootstrap_property('Name', 'text', 'Name of the new repo', name, default=get_name_from_url(git_repo_url), validate=lambda _, x: validate_name(x, config)).lower() branch = cls.bootstrap_property('Branch name', 'text', 'Which branch name should be build?', branch, default=DEFAULT_BRANCH_PLACEHOLDER, validate=lambda _, x: validate_branch(git_repo_url, x)) if branch == DEFAULT_BRANCH_PLACEHOLDER: branch = get_default_branch(git_repo_url) ipns_key, ipns_addr = bootstrap_ipns(config, name, ipns_key) if secret is None: secret = ''.join( secrets.choice(string.ascii_uppercase + string.digits) for _ in range(DEFAULT_LENGTH_OF_SECRET)) pin = cls.bootstrap_property('Pin flag', 'confirm', 'Do you want to pin the published IPFS objects?', pin, default=True) if build_bin is None: build_bin = inquirer.shortcuts.text('Path to build binary, if you want to do some pre-processing ' 'before publishing', default='') if after_publish_bin is None: after_publish_bin = inquirer.shortcuts.text('Path to after-publish binary, if you want to do some ' 'actions after publishing', default='') if publish_dir is None: publish_dir = inquirer.shortcuts.text('Directory to be published inside the repo. Path related to the root ' 'of the repo', default='/') ipns_lifetime = ipns_lifetime or '24h' if not validate_time_span(ipns_lifetime): raise exceptions.RepoException('Passed lifetime is not valid! Supported units are: h(our), m(inute), ' 's(seconds)!') ipns_ttl = ipns_ttl or '15m' if not validate_time_span(ipns_ttl): raise exceptions.RepoException('Passed ttl is not valid! Supported units are: h(our), m(inute), ' 's(seconds)!') if ipns_key is None and after_publish_bin is None: raise exceptions.RepoException( 'You have choose not to use IPNS and you also have not specified any after publish command. ' 'This does not make sense! What do you want to do with this setting?! I have no idea, so aborting!') return cls(config=config, name=name, git_repo_url=git_repo_url, branch=branch, secret=secret, pin=pin, publish_dir=publish_dir, ipns_key=ipns_key, ipns_addr=ipns_addr, build_bin=build_bin, after_publish_bin=after_publish_bin, republish=republish, ipns_lifetime=ipns_lifetime, ipns_ttl=ipns_ttl)
def bootstrap_ipns(config: config_module.Config, name: str, ipns_key: str = None) -> typing.Tuple[str, str]: """ Functions that handle bootstraping of IPNS informations. :param config: :param name: :param ipns_key: :return: """ ipns_addr = None if ipns_key is None: wanna_ipns = inquirer.shortcuts.confirm( 'Do you want to publish to IPNS?', default=True) if wanna_ipns: ipns_key = f'{IPNS_KEYS_NAME_PREFIX}_{name}' try: out = config.ipfs.key_gen(ipns_key, IPNS_KEYS_TYPE) except ipfsapi.exceptions.Error: use_existing = inquirer.shortcuts.confirm( f'There is already IPNS key with name \'{ipns_key}\', ' f'do you want to use it?', default=True) if use_existing: keys = config.ipfs.key_list() out = next( (x for x in keys['Keys'] if x['Name'] == ipns_key), None) if out is None: raise exceptions.RepoException( 'We were not able to generate or fetch the IPNS key' ) else: while True: ipns_key = inquirer.shortcuts.text( 'Then please provide non-existing name for the IPNS key' ) try: out = config.ipfs.key_gen(ipns_key, IPNS_KEYS_TYPE) break except ipfsapi.exceptions.Error: click.echo( 'There is already existing key with this name!' ) continue ipns_addr = f'/ipns/{out["Id"]}/' else: keys = config.ipfs.key_list() key_object = next((x for x in keys['Keys'] if x['Name'] == ipns_key), None) if key_object is None: logger.info( 'The passed IPNS key name \'{}\' was not found, generating new key with this name' ) key_object = config.ipfs.key_gen(ipns_key, IPNS_KEYS_TYPE) ipns_addr = f'/ipns/{key_object["Id"]}/' return ipns_key, ipns_addr