def _get_pr_info(self): '''Fill in basic information about a pull request.''' pr = self._api(github.get_pull_request, self._number) # get a list of files which have been affected by this PR, base to # head. sha1 = pr['base']['sha'] sha2 = pr['head']['sha'] diff_info = self._api(github.get_diff_info, sha1, sha2) files = diff_info['files'] # get a list of commits in the pull request. The API does not return # "outdated" commits or the base commit. We add these using auxiliary # data. commit_shas = [c['sha'] for c in self._api(github.get_pull_request_commits, self._number)] comments = self._api(github.get_pull_request_comments, self._number) # NOTE: need to do some more thinking about outdated commits. # Since the PR's base sha sha may have changed since the commit, it # could be hard to show a meaningful diff. # outdated_commit_shas = self._get_outdated_commit_shas(commit_shas, comments) # commit_shas.extend(outdated_commit_shas) commit_shas.append(pr['base']['sha']) # Get "thick" commit data. # This includes a list of modified files, whereas # get_pull_request_commits does not. This gives us information about # reverted files. commits = [] for sha in commit_shas: commits.append(self._api(github.get_commit_info, sha)) commits.sort(key=lambda c: c['commit']['committer']['date']) commits.reverse() # Merge draft and published comments. draft_comments = self._db.get_draft_comments( self._login, self._owner, self._repo, self._number) for comment in draft_comments: comments['diff_level'].append(self._db.githubify_comment(comment)) github_comments.add_line_numbers_to_comments( self._token, self._owner, self._repo, pr['base']['sha'], comments['diff_level']) github_comments.add_in_response_to(pr, comments['diff_level']) self.pull_request = pr self.commits = commits self.comments = comments self.files = files self._attach_comments() self.reverted_files = self._find_reverted_files() self._augment_commits() self._augment_files()
def file_diff(user, repo, number): path = request.args.get('path', '') sha1 = request.args.get('sha1', '') sha2 = request.args.get('sha2', '') if not (path and sha1 and sha2): return "Incomplete request (need path, sha1, sha2)" # TODO(danvk): consolidate this code with the pull route token = session['token'] commits = github.get_pull_request_commits(token, user, repo, number) pr = github.get_pull_request(token, user, repo, number) comments = github.get_pull_request_comments(token, user, repo, number) open('/tmp/commits.txt', 'wb').write(json.dumps(commits, indent=2)) commit_to_comments = defaultdict(int) for comment in comments['diff_level']: commit_to_comments[comment['original_commit_id']] += 1 commits.reverse() # Add an entry for the base commit. commits.append({ 'sha': pr['base']['sha'], 'commit': { 'message': '(%s)' % pr['base']['ref'], 'author': {'date': ''} }, 'author': {'login': ''} }) # github excludes the first four header lines of "git diff" diff_info = github.get_diff_info(token, user, repo, sha1, sha2) unified_diff = github.get_file_diff(token, user, repo, path, sha1, sha2) if not unified_diff or not diff_info: return "Unable to get diff for %s..%s" % (sha1, sha2) github_diff = '\n'.join(unified_diff.split('\n')[4:]) # TODO(danvk): only annotate comments on this file. github_comments.add_line_numbers_to_comments(token, user, repo, pr['base']['sha'], comments['diff_level']) differing_files = [f['filename'] for f in diff_info['files']] before = github.get_file_at_ref(token, user, repo, path, sha1) after = github.get_file_at_ref(token, user, repo, path, sha2) def diff_url(path): return (url_for('file_diff', user=user, repo=repo, number=number) + '?path=' + urllib.quote(path) + '&sha1=' + urllib.quote(sha1) + '&sha2=' + urllib.quote(sha2)) linked_files = [{'path':p, 'link': diff_url(p)} for p in differing_files] if path in differing_files: file_idx = differing_files.index(path) prev_file = linked_files[file_idx - 1] if file_idx > 0 else None next_file = linked_files[file_idx + 1] if file_idx < len(linked_files) - 1 else None else: # The current file is not part of this diff. # Just do something sensible. prev_file = None next_file = linked_files[0] if len(linked_files) > 0 else None pull_request_url = url_for('pull', user=user, repo=repo, number=number) return render_template('file_diff.html', commits=commits, user=user, repo=repo, pull_request=pr, comments=comments, path=path, sha1=sha1, sha2=sha2, before_contents=before, after_contents=after, differing_files=linked_files, prev_file=prev_file, next_file=next_file, github_diff=github_diff, pull_request_url=pull_request_url)