def get_credentials_for_remote(self, remote): if not remote: return p = giturlparse(remote.url) remote_username = p._user if p.protocol == 'ssh': credentials = pygit2.KeypairFromAgent(remote_username) elif p.protocol == 'https': # TODO: What if this fails? (platform, pwd not stored,...) try: import subprocess out = subprocess.check_output([ 'security', 'find-internet-password', '-r', 'htps', '-s', p.domain, '-p', '', '-g', ], stderr=subprocess.STDOUT) username = re.search(rb'"acct"<blob>="([^"]+)"', out) username = username.group(1) password = re.search(rb'password: "******"]+)"', out) password = password.group(1) if password == TOKEN_USER: username, password = password, username except: raise NotImplementedError('No authentication support.') credentials = pygit2.UserPass(username, password) return credentials
def get_credentials_for_remote(self, remote): if not remote: return p = giturlparse(remote.url) remote_username = p.user if p.protocol == "ssh": credentials = pygit2.KeypairFromAgent(remote_username) elif p.protocol == "https": raise NotImplementedError("No authentication support.") # credentials = pygit2.UserPass(username, password) return credentials
def parse_vcs_url(url): wat = watdarepo(url) parts = { "vcs": wat["vcs"], "host": wat["hosting_service"], "url": url, } if wat["vcs"] == "git": parsed = giturlparse(url) if not parsed.valid: raise URLFormatError(url) parts["host"] = parsed.host parts["owner"] = parsed.owner parts["repo"] = parsed.repo parts["url"] = parsed.url2ssh parts["slug"] = slugify_vcs_url(parts["url"]) while parts["host"] and "." in parts["host"]: parts["host"] = parts["host"].partition(".")[0] return parts
def create_pull_request(self, source_branch, target_branch, summary, description): remote = self.repo.lookup_remote(self.remote_name) project_path = giturlparse(remote.url).pathname if project_path.endswith(".git"): project_path = project_path[:-4] prj = self.api.projects.get(urlquote(project_path)) try: mr = prj.mergerequests.create({ "source_branch": source_branch, "target_branch": target_branch, "title": summary, "description": description, "remove_source_branch": True, }) except GitlabCreateError as e: if e.error_message and "already exists" in e.error_message[0]: # TODO: fetch PR and pass in raise PullRequestAlreadyExists(None) return GitlabPullRequest(self, mr)
def create_pull_request( self, source_branch, target_branch, summary, description ): remote = self.repo.lookup_remote(self.remote_name) project_path = giturlparse(remote.url).pathname if project_path.endswith(".git"): project_path = project_path[:-4] prj = self.api.projects.get(urlquote(project_path)) try: mr = prj.mergerequests.create( { "source_branch": source_branch, "target_branch": target_branch, "title": summary, "description": description, "remove_source_branch": True, } ) except GitlabCreateError as e: if e.error_message and "already exists" in e.error_message[0]: # TODO: fetch PR and pass in raise PullRequestAlreadyExists(None) return GitlabPullRequest(self, mr)
def github_repo(self): remote_name = self.config.get("repository", "remote_name") remote = self.repo.lookup_remote(remote_name) p = giturlparse(remote.url) return self.github.repository(p.owner, p.repo)
def pull_request(ctx, base_branch, open_pr, stop_timer): """Create a new pull request for this issue.""" lancet = ctx.obj username = lancet.config.get('tracker', 'username') review_status = lancet.config.get('tracker', 'review_status') remote_name = lancet.config.get('repository', 'remote_name') if not base_branch: base_branch = lancet.config.get('repository', 'base_branch') # Get the issue issue = get_issue(lancet) transition = get_transition(ctx, lancet, issue, review_status) # Get the working branch branch = get_branch(lancet, issue, create=False) with taskstatus('Checking pre-requisites') as ts: if not branch: ts.abort('No working branch found') assignee = issue.fields.assignee if not assignee or assignee.name != username: ts.abort('Issue currently not assigned to you') # TODO: Check mergeability # TODO: Check remote status (PR does not already exist) # Push to remote with taskstatus('Pushing to "{}"', remote_name) as ts: remote = lancet.repo.lookup_remote(remote_name) if not remote: ts.abort('Remote "{}" not found', remote_name) remote.credentials = lancet.repo.get_credentials_for_remote(remote) remote.push([branch.name]) ts.ok('Pushed latest changes to "{}"', remote_name) # Create pull request with taskstatus('Creating pull request') as ts: p = giturlparse(remote.url) gh_repo = lancet.github.repository(p.owner, p.repo) template_path = lancet.config.get('repository', 'pr_template') message = edit_template(template_path, issue=issue) if not message: ts.abort('You didn\'t provide a title for the pull request') title, body = message.split('\n', 1) title = title.strip() if not title: ts.abort('You didn\'t provide a title for the pull request') try: pr = gh_repo.create_pull(title, base_branch, branch.branch_name, body.strip('\n')) except github3.GitHubError as e: if len(e.errors) == 1: error = e.errors[0] if 'pull request already exists' in error['message']: ts.ok('Pull request does already exist') else: ts.abort('Could not create pull request ({})', error['message']) else: raise else: ts.ok('Pull request created at {}', pr.html_url) # Update issue set_issue_status(lancet, issue, review_status, transition) # TODO: Post to activity stream on JIRA # TODO: Post to HipChat? # Stop harvest timer if stop_timer: with taskstatus('Pausing harvest timer') as ts: lancet.timer.pause() ts.ok('Harvest timer paused') # Open the pull request page in the browser if requested if open_pr: click.launch(pr.html_url)