def perform(self): for i in listdir(self.entry.path): if i.lower() == 'readme.md' and i != 'README.md': shutil.move(join(self.entry.path, i), join(self.entry.path, 'README.md')) creator = CreateAction(None, self.entry.name.replace('-skill', '')) creator.path = self.entry.path creator.initialize_template({'.git', '.gitignore', 'README.md'}) self.git.add('README.md') creator.commit_changes() skill_repo = creator.create_github_repo(lambda: input('Repo name:')) if skill_repo: self.entry.url = skill_repo.html_url self.entry.author = self.user.login else: skill_repo = self.github.get_repo(skill_repo_name(self.entry.url)) if not skill_repo.permissions.push: print('Warning: You do not have write permissions to the provided skill repo.') if ask_yes_no('Create a fork and use that instead? (Y/n)', True): skill_repo = self.user.create_fork(skill_repo) print('Created fork:', skill_repo.html_url) self.git.remote('rename', 'origin', 'upstream') self.git.remote('add', 'origin', skill_repo.html_url) self.entry.name = input('Enter a unique skill name (ie. npr-news or grocery-list): ') readme_file = {i.lower(): i for i in os.listdir(self.entry.path)}['readme.md'] readme = read_file(self.entry.path, readme_file) last_section = None sections = {last_section: ''} for line in readme.split('\n'): line = line.strip() if line.startswith('#'): last_section = line.strip('# ').lower() sections[last_section] = '' else: sections[last_section] += '\n' + line del sections[None] if 'description' in sections: description = sections['description'] else: description = ask_choice( 'Which section contains the description?', list(sections), on_empty='Please create a description section in the README' ) branch = SkillData(self.entry).add_to_repo() self.repo.push_to_fork(branch) pull = create_or_edit_pr( title='Add {}'.format(self.entry.name), body=body_template.format( description=description, skill_name=self.entry.name, skill_url=skill_repo.html_url ), user=self.user, branch=branch, skills_repo=self.repo.hub ) print('Created pull request: ', pull.html_url)
class SkillData(GlobalContext): def __init__(self, skill: SkillEntry): self.entry = skill name = property(lambda self: self.entry.name) repo = Lazy(lambda s: RepoData()) # type: RepoData repo_git = Lazy(lambda s: Git(join(s.repo.msminfo.path, s.submodule_name))) # type: Git git = Lazy(lambda s: Git(s.entry.path)) # type: Git hub = Lazy(lambda s: s.github.get_repo(skill_repo_name(s.entry.url))) # type: Repository @Lazy def submodule_name(self): name_to_path = {name: path for name, path, url, sha in self.repo.msminfo.get_skill_data()} if self.name not in name_to_path: raise NotUploaded('The skill {} has not yet been uploaded to the skill store'.format( self.name )) return name_to_path[self.name] def upgrade(self) -> str: skill_module = self.submodule_name self.repo.msminfo.update() self.repo_git.fetch() default_branch = self.repo_git.symbolic_ref('refs/remotes/origin/HEAD') self.repo_git.reset(default_branch, hard=True) upgrade_branch = 'upgrade/' + self.name self.repo.checkout_branch(upgrade_branch) if not self.repo.git.diff(skill_module) and self.repo.git.ls_files(skill_module): raise AlreadyUpdated( 'The latest version of {} is already uploaded to the skill repo'.format( self.name ) ) self.repo.git.add(skill_module) self.repo.git.commit(message='Upgrade ' + self.name) return upgrade_branch def add_to_repo(self) -> str: self.repo.msminfo.update() elements = [i.split() for i in self.git.ls_tree('HEAD').split('\n')] existing_mods = [folder for size, typ, sha, folder in elements] if self.name not in existing_mods: self.repo.git.submodule('add', self.entry.url, self.name) # Upgrade skill in case it is outdated self.repo_git.fetch() default_branch = self.repo_git.symbolic_ref('refs/remotes/origin/HEAD') self.repo_git.reset(default_branch, hard=True) branch_name = 'add/' + self.name self.repo.checkout_branch(branch_name) self.repo.git.add(self.name) self.repo.git.commit(message='Add ' + self.name) return branch_name def init_existing(self): self.repo.git.submodule('update', '--init', self.submodule_name)
class RepoData(GlobalContext): msminfo = Lazy(lambda s: s.msm.repo) # type: SkillRepo git = Lazy(lambda s: Git(s.msminfo.path)) # type: Git hub = Lazy(lambda s: s.github.get_repo(skill_repo_name(s.msminfo.url))) # type: Repository fork = Lazy(lambda s: s.github.get_user().create_fork(s.hub)) # type: Repository def push_to_fork(self, branch: str): remotes = self.git.remote().split('\n') command = 'set-url' if 'fork' in remotes else 'add' self.git.remote(command, 'fork', self.fork.html_url) # Use call to ensure the environment variable GIT_ASKPASS is used call(['git', 'push', '-u', 'fork', branch, '--force'], cwd=self.msminfo.path) def checkout_branch(self, branch): with suppress(GitCommandError): self.git.branch('-D', branch) try: self.git.checkout(b=branch) except GitCommandError: self.git.checkout(branch)
def perform(self): print('Uploading a new skill to the skill repo...') for i in listdir(self.entry.path): if i.lower() == 'readme.md' and i != 'README.md': shutil.move(join(self.entry.path, i), join(self.entry.path, 'README.md')) creator = CreateAction(None, self.entry.name.replace('-skill', '')) creator.path = self.entry.path creator.initialize_template({'.git', '.gitignore', 'README.md'}) self.git.add('README.md') creator.commit_changes() try: skill_repo = creator.create_github_repo( lambda: input('Repo name:')) except GithubRepoExists: try: print("A repository with that name already exists") skill_repo = creator.link_github_repo( lambda: input('Remote repo name:')) except UnrelatedGithubHistory: print("Repository history does not seem to be related") skill_repo = creator.force_push( lambda: input('Confirm repo name:')) if skill_repo: self.entry.url = skill_repo.html_url self.entry.author = self.user.login else: if not self.entry.url: raise NoGitRepository skill_repo = self.github.get_repo(skill_repo_name(self.entry.url)) if not skill_repo.permissions.push: print( 'Warning: You do not have write permissions to the provided skill repo.' ) if ask_yes_no('Create a fork and use that instead? (Y/n)', True): skill_repo = self.user.create_fork(skill_repo) print('Created fork:', skill_repo.html_url) self.git.remote('rename', 'origin', 'upstream') self.git.remote('add', 'origin', skill_repo.html_url) # verify that the required files exists in origin and contain the # required content. if not self.check_valid(): print("Please add the missing information and rerun the command.") return self.entry.name = input( 'Enter a unique skill name (ie. npr-news or grocery-list): ') readme_file = {i.lower(): i for i in os.listdir(self.entry.path)}['readme.md'] readme = read_file(self.entry.path, readme_file) last_section = None sections = {last_section: ''} for line in readme.split('\n'): line = line.strip() if line.startswith('#'): last_section = line.strip('# ').lower() sections[last_section] = '' else: sections[last_section] += '\n' + line del sections[None] if 'about' in sections: description = sections['about'] elif 'description' in sections: description = sections['description'] branch = SkillData(self.entry).add_to_repo() self.repo.push_to_fork(branch) pull = create_or_edit_pr(title='Add {}'.format(self.entry.name), body=body_template.format( description=description, skill_name=self.entry.name, skill_url=skill_repo.html_url), user=self.user, branch=branch, skills_repo=self.repo.hub, repo_branch=self.branch) print('Created pull request: ', pull.html_url)