def get_commits(self, repository, start=None): results = [] resource = "commits" url = self._build_api_url(self._get_repo_api_url(repository), resource) if start: url += "&sha=%s" % start try: rsp = self._api_get(url) except Exception as e: logging.warning("Failed to fetch commits from %s: %s", url, e) return results for item in rsp: commit = Commit( item["commit"]["author"]["name"], item["sha"], item["commit"]["committer"]["date"], item["commit"]["message"], ) if item["parents"]: commit.parent = item["parents"][0]["sha"] results.append(commit) return results
def get_change(self, revision, cache_key): """Get an individual change. This returns a tuple with the commit message and the diff contents. """ revision = int(revision) commit = cache.get(cache_key) if commit: message = commit.message author_name = commit.author_name date = commit.date base_revision = commit.parent else: commits = list(self.ra.iter_log(None, revision, 0, limit=2)) rev, props = commits[0][1:3] message = props[SVN_LOG] author_name = props[SVN_AUTHOR] date = props[SVN_DATE] if len(commits) > 1: base_revision = commits[1][1] else: base_revision = 0 out, err = self.client.diff(base_revision, revision, self.repopath, self.repopath, diffopts=DIFF_UNIFIED) commit = Commit(author_name, six.text_type(revision), date, message, six.text_type(base_revision)) commit.diff = out.read() return commit
def get_commits(self, repository, start=None): results = [] resource = 'commits' url = self._build_api_url(self._get_repo_api_url(repository), resource) if start: url += '&sha=%s' % start try: rsp = self._api_get(url) except Exception as e: logging.warning('Failed to fetch commits from %s: %s', url, e) return results for item in rsp: commit = Commit(item['commit']['author']['name'], item['sha'], item['commit']['committer']['date'], item['commit']['message']) if item['parents']: commit.parent = item['parents'][0]['sha'] results.append(commit) return results
def get_commits(self, start): """Returns a list of commits.""" commits = self.client.log(self.repopath, revision_start=Revision( opt_revision_kind.number, int(start)), limit=31) results = [] # We fetch one more commit than we care about, because the entries in # the svn log doesn't include the parent revision. for i in range(len(commits) - 1): commit = commits[i] parent = commits[i + 1] date = datetime.utcfromtimestamp(commit['date']) results.append( Commit(commit.get('author', ''), six.text_type(commit['revision'].number), date.isoformat(), commit['message'], six.text_type(parent['revision'].number))) # If there were fewer than 31 commits fetched, also include the last # one in the list so we don't leave off the initial revision. if len(commits) < 31: commit = commits[-1] date = datetime.utcfromtimestamp(commit['date']) results.append( Commit(commit['author'], six.text_type(commit['revision'].number), date.isoformat(), commit['message'])) return results
def get_commits(self, repository, branch=None, start=None): url = self._build_repository_api_url(repository, 'changesets/?limit=20') start = start or branch if start: url += '&start=%s' % start results = [] # The API returns them in order from oldest to newest. for changeset in reversed(self._api_get(url)['changesets']): commit = Commit( author_name=changeset['author'], id=changeset['raw_node'], date=self._parse_timestamp(changeset['utctimestamp']), message=changeset['message'], base_commit_id=changeset['raw_node']) if changeset['parents']: commit.parent = changeset['parents'][0] results.append(commit) return results
def test_get_commits(self): """Testing Gerrit.get_commits""" payload = self._make_json_rsp([ { 'message': 'Backport a fix for screenshot commenting.\n', 'revision': '77c174669b7018936f16b98547445624c6738e1e', 'author': 'David Trowbridge', 'parents': [ 'ecfbf578d31f550a135580cee26fa20fbaea36d9', ], 'time': '2016-09-05T23:28:30-07:00', }, { 'message': 'Fix some issues with screenshot commenting.' '\n', 'revision': '8a39b87f0124f27225234014a87914e434b223a9', 'author': 'David Trowbridge', 'parents': [ '3fb32c83993cd8c07fbbb605cf0cc523010da7c8', ], 'time': '2016-09-05T22:58:29-07:00', }, { 'message': 'Fix draggability of the comment dialog.\n', 'revision': '3fb32c83993cd8c07fbbb605cf0cc523010da7c8', 'author': 'David Trowbridge', 'parents': [ '7619f51371b55bfcdf4cb3fccf5d3c76bf5002c0', ], 'time': '2016-09-05T22:47:55-07:00', }, ]) with self.setup_http_test(payload=payload, expected_http_calls=1) as ctx: commits = ctx.service.get_commits(ctx.create_repository()) ctx.assertHTTPCall( 0, url='http://gerrit.example.com/a/projects/Project/all-commits/') self.assertEqual(commits, [ Commit(author_name='David Trowbridge', id='77c174669b7018936f16b98547445624c6738e1e', date='2016-09-05T23:28:30-07:00', message='Backport a fix for screenshot commenting.\n', parent='ecfbf578d31f550a135580cee26fa20fbaea36d9'), Commit(author_name='David Trowbridge', id='8a39b87f0124f27225234014a87914e434b223a9', date='2016-09-05T22:58:29-07:00', message='Fix some issues with screenshot commenting.\n', parent='3fb32c83993cd8c07fbbb605cf0cc523010da7c8'), Commit(author_name='David Trowbridge', id='3fb32c83993cd8c07fbbb605cf0cc523010da7c8', date='2016-09-05T22:47:55-07:00', message='Fix draggability of the comment dialog.\n', parent='7619f51371b55bfcdf4cb3fccf5d3c76bf5002c0'), ]) for commit in commits: self.assertIsNone(commit.diff)
def get_change(self, revision): """Get an individual change. This returns a Commit object containing the details of the commit. """ revision = int(revision) commits = self.client.get_log('/', start=revision, limit=2) commit = commits[0] message = commit.get('message', b'').decode('utf-8', 'replace') author_name = commit.get('author', b'').decode('utf-8', 'replace') date = commit['date'].isoformat() if len(commits) > 1: base_revision = commits[1]['revision'] else: base_revision = 0 try: enc, diff = convert_to_unicode( self.client.diff(base_revision, revision), self.repository.get_encoding_list()) except Exception as e: raise self.normalize_error(e) commit = Commit(author_name, six.text_type(revision), date, message, six.text_type(base_revision)) commit.diff = diff return commit
def get_commits(self, repository, branch=None, start=None): url = self._build_repository_api_url(repository, 'changesets/?limit=20') start = start or branch if start: url += '&start=%s' % start results = [] # The API returns them in order from oldest to newest. for changeset in reversed(self._api_get(url)['changesets']): commit = Commit(author_name=changeset['author'], id=changeset['raw_node'], date=self._parse_timestamp( changeset['utctimestamp']), message=changeset['message'], base_commit_id=changeset['raw_node']) if changeset['parents']: commit.parent = changeset['parents'][0] results.append(commit) return results
def _parse_commit(self, meta, diff=None): """Parse and return the meta response and return a Commit. Args: meta (dict): A member of the JSON response from the ``all-commits`` endpoint corresponding to a single commit. diff (bytes, optional): The diff corresponding to the commit. Returns: reviewboard.scmtools.core.Commit: The parsed commit. """ commit = Commit( author_name=meta['author'], id=meta['revision'], date=meta['time'], message=meta['message'], diff=diff ) if meta['parents']: commit.parent = meta['parents'][0] return commit
def get_commits(self, repository, start=None): results = [] resource = 'commits' url = self._build_api_url(self._get_repo_api_url(repository), resource) if start: url += '&sha=%s' % start try: rsp = self._api_get(url) except Exception as e: logging.warning('Failed to fetch commits from %s: %s', url, e) return results for item in rsp: commit = Commit( item['commit']['author']['name'], item['sha'], item['commit']['committer']['date'], item['commit']['message']) if item['parents']: commit.parent = item['parents'][0]['sha'] results.append(commit) return results
def get_commits(self, branch=None, start=None): """Return a list of commits.""" commits = self.client.get_log(branch or '/', start=start, limit=self.COMMITS_PAGE_LIMIT, limit_to_path=False) results = [] # We fetch one more commit than we care about, because the entries in # the svn log doesn't include the parent revision. for i in range(len(commits) - 1): commit = commits[i] parent = commits[i + 1] results.append( Commit(commit.get('author', ''), commit['revision'], commit['date'].isoformat(), commit.get('message', ''), parent['revision'])) # If there were fewer than the requested number of commits fetched, # also include the last one in the list so we don't leave off the # initial revision. if len(commits) < self.COMMITS_PAGE_LIMIT: commit = commits[-1] results.append( Commit(commit.get('author', ''), commit['revision'], commit['date'].isoformat(), commit.get('message', ''))) return results
def test_get_commits_with_branch(self): """Testing SVN (<backend>) get_commits with branch""" commits = self.tool.get_commits(branch='/branches/branch1', start='5') self.assertEqual(len(commits), 5) self.assertEqual( commits[0], Commit('chipx86', '5', '2010-05-21T09:33:40.893946', 'Add an unterminated keyword for testing bug #1523\n', '4')) commits = self.tool.get_commits(branch='/branches/branch1', start='7') self.assertEqual(len(commits), 6) self.assertEqual( commits[0], Commit('david', '7', '2013-06-13T07:43:27.259554', 'Add a branch', '5')) self.assertEqual( commits[1], Commit('chipx86', '5', '2010-05-21T09:33:40.893946', 'Add an unterminated keyword for testing bug #1523\n', '4'))
def get_change(repository, commit_to_get): commit = Commit( message='* This is a summary\n\n* This is a description.') diff_filename = os.path.join(self.testdata_dir, 'git_readme.diff') with open(diff_filename, 'r') as f: commit.diff = f.read() return commit
def get_change(repository, commit_to_get): self.assertEqual(commit_id, commit_to_get) commit = Commit(message='This is my commit message\n\n' 'With a summary line too.') diff_filename = os.path.join(self.testdata_dir, 'git_readme.diff') with open(diff_filename, 'r') as f: commit.diff = f.read() return commit
def get_commits(self, repository, branch=None, start=None): repo_api_url = self._get_repo_api_url(repository) commits = self.client.api_get_commits(repo_api_url, start=start) results = [] for item in commits: commit = Commit(item['commit']['author']['name'], item['sha'], item['commit']['committer']['date'], item['commit']['message']) if item['parents']: commit.parent = item['parents'][0]['sha'] results.append(commit) return results
def get_change(self, revision): """Get an individual change. This returns a tuple with the commit message and the diff contents. """ cache_key = self.repository.get_commit_cache_key(revision) revision = int(revision) head_revision = Revision(opt_revision_kind.number, revision) commit = cache.get(cache_key) if commit: message = commit.message author_name = commit.author_name date = commit.date base_revision = Revision(opt_revision_kind.number, commit.parent) else: commits = self.client.log( self.repopath, revision_start=head_revision, limit=2) commit = commits[0] message = commit['message'] author_name = commit['author'] date = datetime.datetime.utcfromtimestamp(commit['date']).\ isoformat() try: commit = commits[1] base_revision = commit['revision'] except IndexError: base_revision = Revision(opt_revision_kind.number, 0) tmpdir = mkdtemp(prefix='reviewboard-svn.') diff = self.client.diff( tmpdir, self.repopath, revision1=base_revision, revision2=head_revision, diff_options=['-u']) rmtree(tmpdir) commit = Commit(author_name, six.text_type(head_revision.number), date, message, six.text_type(base_revision.number)) commit.diff = diff return commit
def get_commits(self, repository, branch=None, start=None): if start is not None: url = ('%s/repos/%s/branches/%s/commits?start=%s' % (self.account.hosting_url, repository.extra_data['rbgateway_repo_name'], branch, start)) else: url = ('%s/repos/%s/branches/%s/commits' % (self.account.hosting_url, repository.extra_data['rbgateway_repo_name'], branch)) try: data, headers = self._api_get(url) commits = json.loads(data) results = [] for commit in commits: results.append(Commit(commit['author'], commit['id'], commit['date'], commit['message'], commit['parent_id'])) return results except Exception as e: logger.exception('Failed to fetch commits from %s: %s', url, e) raise SCMError(six.text_type(e))
def get_commits(self, branch=None, start=None): return [ Commit('user%d' % i, six.text_type(i), '2013-01-01T%02d:00:00.0000000' % i, 'Commit %d' % i, six.text_type(i - 1)) for i in range(int(start or 10), 0, -1) ]
def _get_commits(self, revset): """Return a list of commit objects. This method calls the given revset and parses the returned JSON data to retrieve detailed information about changesets. Args: revset (list of unicode): Hg command line that will be executed with JSON template as log command. Returns: list of reviewboard.scmtools.core.Commit: The list of commit objects. """ cmd = ['log'] + revset + ['--template', 'json'] p = self._run_hg(cmd) if p.wait() != 0: raise SCMError('Cannot load commits: %s' % p.stderr.read()) results = [] for data in json.load(p.stdout): p = data['parents'][0] results.append( Commit(id=data['node'], message=data['desc'], author_name=data['user'], date=HgTool.date_tuple_to_iso8601(data['date']), parent=p, base_commit_id=p)) return results
def _get_commit(self, revision): """Return detailed information about a single changeset. Receive changeset from hgweb in JSON format. Args: revision (unicode): An identifier of changeset. Returns: reviewboard.scmtools.core.Commit: The commit object. """ try: url = '%s/json-rev/%s' % (self.path_stripped, revision) contents = self.get_file_http(url, '', '', 'application/json') except Exception as e: logging.exception('Cannot load detail of changeset from hgweb: %s', e) return None if contents: data = json.loads(contents) parent = data['parents'][0] return Commit(id=data['node'], message=data['desc'], author_name=data['user'], date=HgTool.date_tuple_to_iso8601(data['date']), parent=parent, base_commit_id=parent) return None
def _get_commit(self, revision): """Return detailed information about a single changeset. Receive changeset from hgweb in JSON format. Args: revision (unicode): An identifier of changeset. Returns: reviewboard.scmtools.core.Commit: The commit object. """ try: rsp = self._get_http_json('%s/json-rev/%s' % (self.path_stripped, revision)) except Exception as e: logging.exception('Cannot load detail of changeset from hgweb: %s', e) return None if not rsp: return None try: parent = rsp['parents'][0] except IndexError: parent = None return Commit(id=rsp['node'], message=rsp['desc'], author_name=rsp['user'], date=HgTool.date_tuple_to_iso8601(rsp['date']), parent=parent)
def get_change(self, repository, revision): # We try to pull the commit's metadata out of the cache. The diff API # endpoint is just the raw content of the diff and contains no # metadata. commit = cache.get(repository.get_commit_cache_key(revision)) if not commit: # However, if it is not in the cache, we have to hit the API to # get the metadata. commit = self.get_commits(repository, revision)[0] url = self._build_repository_api_url(repository, 'diff/%s' % revision, version='2.0') diff = self._api_get(url, raw_content=True) if not diff.endswith('\n'): diff += '\n' return Commit(author_name=commit.author_name, id=commit.id, date=commit.date, message=commit.message, diff=diff, base_commit_id=commit.base_commit_id)
def get_change(self, repository, revision): # We try to pull the commit's metadata out of the cache. The diff API # endpoint is just the raw content of the diff and contains no # metadata. commit = cache.get(repository.get_commit_cache_key(revision)) if not commit: # However, if it is not in the cache, we have to hit the API to # get the metadata. commit_rsp = self.api_get( self._build_repository_api_url( repository, 'commit/%s' % revision, query={ 'fields': self._get_commit_fields_query(), })) commit = self._build_commit_from_rsp(commit_rsp) # Now fetch the diff and normalize it to always end with a newline, # so patch is happy. diff_url = self._build_repository_api_url(repository, 'diff/%s' % revision) diff = self.api_get(diff_url, raw_content=True) if not diff.endswith(b'\n'): diff += b'\n' return Commit(author_name=commit.author_name, id=commit.id, date=commit.date, message=commit.message, diff=diff, parent=commit.parent)
def get_commits(self, repository, branch, start=None): """Return a list of commits for a repository. Args: repository (reviewboard.scmtools.models.Repository): The repository to fetch commits on. branch (unicode): The name of the branch to list commits on. start (unicode, optional): The optional starting commit ID for the list. This is used for pagination purposes. Returns: list of reviewboard.scmtools.core.Commit: The list of commits in the repository. Raises: reviewboard.hostingsvcs.errors.HostingServiceError: Error retrieving the branch information. There may be a more specific subclass raised. """ repo_name = self._get_repo_name(repository) return [ Commit(author_name=commit_info['author'], id=commit_info['id'], date=commit_info['date'], message=commit_info['message'], parent=commit_info['parent_id']) for commit_info in self.client.api_get_commits(repo_name, branch) ]
def test_get_commits(self): """Testing SVN (<backend>) get_commits""" commits = self.tool.get_commits(start='5') self.assertEqual(len(commits), 5) self.assertEqual( commits[0], Commit('chipx86', '5', '2010-05-21T09:33:40.893946', 'Add an unterminated keyword for testing bug #1523\n', '4')) commits = self.tool.get_commits(start='7') self.assertEqual(len(commits), 7) self.assertEqual( commits[1], Commit('david', '6', '2013-06-13T07:43:04.725088', 'Add a branches directory', '5'))
def get_change(self, repository, revision): """Return a commit at a given revision/commit ID. Args: repository (reviewboard.scmtools.models.Repository): The repository to fetch the commit from. revision (unicode): The revision/ID of the commit to fetch. Returns: reviewboard.scmtools.core.Commit: The commit from the repository. Raises: reviewboard.hostingsvcs.errors.HostingServiceError: Error retrieving the branch information. There may be a more specific subclass raised. """ repo_name = self._get_repo_name(repository) commit_info = self.client.api_get_commit(repo_name, revision) return Commit(author_name=commit_info['author'], id=commit_info['id'], date=commit_info['date'], message=commit_info['message'], parent=commit_info['parent_id'], diff=commit_info['diff'].encode('utf-8'))
def get_change(self, revision, cache_key): """Get an individual change. This returns a tuple with the commit message and the diff contents. """ revision = int(revision) head_revision = Revision(opt_revision_kind.number, revision) commit = cache.get(cache_key) if commit: message = commit.message author_name = commit.author_name date = commit.date base_revision = Revision(opt_revision_kind.number, commit.parent) else: commits = self.client.log( self.repopath, revision_start=head_revision, limit=2) commit = commits[0] message = commit['message'].decode('utf-8', 'replace') author_name = commit['author'].decode('utf-8', 'replace') date = datetime.utcfromtimestamp(commit['date']).\ isoformat() try: commit = commits[1] base_revision = commit['revision'] except IndexError: base_revision = Revision(opt_revision_kind.number, 0) tmpdir = mkdtemp(prefix='reviewboard-svn.') diff = self.client.diff( tmpdir, self.repopath, revision1=base_revision, revision2=head_revision, header_encoding='utf-8', diff_options=['-u']).decode('utf-8') rmtree(tmpdir) commit = Commit(author_name, six.text_type(head_revision.number), date, message, six.text_type(base_revision.number)) commit.diff = diff return commit
def get_change(repository, commit_to_get): self.assertEqual(commit_id, commit_to_get) commit = Commit(message='This is my commit message\n\n' 'With a summary line too.', diff=self.DEFAULT_GIT_README_DIFF) return commit
def _build_commit(self, data, parent=''): date = data.get('date', '') if date: date = date.isoformat() return Commit(data.get('author', ''), data['revision'], date, data.get('message', ''), parent)
def get_commits(self, repository, branch=None, start=None): repo_api_url = self._get_repo_api_url(repository) commits = self.client.api_get_commits(repo_api_url, start=start) results = [] for item in commits: commit = Commit( item['commit']['author']['name'], item['sha'], item['commit']['committer']['date'], item['commit']['message']) if item['parents']: commit.parent = item['parents'][0]['sha'] results.append(commit) return results
def get_commits(self, repository, branch=None, start=None): repo_api_url = self._get_repo_api_url(repository) commits = self.client.api_get_commits(repo_api_url, start=start) results = [] for item in commits: commit = Commit( item["commit"]["author"]["name"], item["sha"], item["commit"]["committer"]["date"], item["commit"]["message"], ) if item["parents"]: commit.parent = item["parents"][0]["sha"] results.append(commit) return results
def get_commits(self, repository, branch=None, start=None): """Get a list of commits This will perform an API request to fetch a list of commits. The start parameter is a 40-character commit id. """ # Ask GitLab for 21 commits per page. GitLab's API doesn't # include the parent IDs, so we use subsequent commits to fill # them in (allowing us to return 20 commits with parent IDs). page_size = self.COMMITS_PER_PAGE + 1 repo_api_url = ('%s/repository/commits?private_token=%s&per_page=%s' % (self._get_repo_api_url(repository), self._get_private_token(), page_size)) if start: # If start parameter is given, use it as the latest commit to log # from, so that we fetch a page of commits, and the first commit id # on the page is the start parameter. repo_api_url += '&ref_name=%s' % start elif branch: # The branch is optional. If it is not given, use the default # branch. The default branch is set to 'master' in get_branches() repo_api_url += '&ref_name=%s' % branch # The GitLab API will return a tuple consists of two elements. # The first one is a list of commits, and the other one is an instance # type object containing all kinds of headers, which is not required. commits = self._api_get(repo_api_url)[0] results = [] for idx, item in enumerate(commits): commit = Commit( author_name=item['author_name'], id=item['id'], date=item['created_at'], message=item.get('message', ''), parent='') if idx > 0: # Note that GitLab API documents do not show any returned # 'parent_id' from the query for a list of commits. So we use # the current commit id as the previous commit's parent id, and # remove the last commit from results. results[idx - 1].parent = commit.id results.append(commit) # Strip off the last commit since we don't know its parent id yet. if len(commits) == page_size: results.pop() return results
def get_commits(self, repository, start=None): resource = 'commits' url = self._build_api_url(repository, resource) if start: url += '&sha=%s' % start rsp = self._api_get(url) results = [] for item in rsp: commit = Commit(item['commit']['author']['name'], item['sha'], item['commit']['committer']['date'], item['commit']['message']) if item['parents']: commit.parent = item['parents'][0]['sha'] results.append(commit) return results
def get_commits(self, branch=None, start=None): if branch == 'bad:hosting-service-error': raise HostingServiceError('This is a HostingServiceError') elif branch == 'bad:scm-error': raise SCMError('This is a SCMError') return [ Commit('user%d' % i, str(i), '2013-01-01T%02d:00:00.0000000' % i, 'Commit %d' % i, str(i - 1)) for i in range(int(start or 10), 0, -1) ]
def get_commits(self, repository, start=None): resource = 'commits' url = self._build_api_url(repository, resource) if start: url += '&sha=%s' % start rsp = self._api_get(url) results = [] for item in rsp: commit = Commit( item['commit']['author']['name'], item['sha'], item['commit']['committer']['date'], item['commit']['message']) if item['parents']: commit.parent = item['parents'][0]['sha'] results.append(commit) return results
def _build_commit(self, data, parent=''): date = data.get('date', '') if date: date = date.isoformat() return Commit( author_name=force_text(data.get('author', ''), errors='replace'), id=force_text(data['revision']), date=force_text(date), message=force_text(data.get('message', ''), errors='replace'), parent=force_text(parent))
def get_commits(self, branch=None, start=None): """Return detailed information about a changeset. Receive changeset from hgweb in JSON format. Args: branch (unicode, optional): An optional branch name to filter by. start (unicode, optional): An optional changeset revision to start with. Returns: list of reviewboard.scmtools.core.Commit: The list of commit objects. """ query_parts = [] if start: query_parts.append('ancestors(%s)' % start) query_parts.append('branch(%s)' % (branch or '.')) query = '+and+'.join(query_parts) try: url = '%s/json-log/?rev=%s' % (self.path_stripped, query) contents = self.get_file_http(url, '', '', 'application/json') except Exception as e: logging.exception('Cannot load commits from hgweb: %s', e) return [] results = [] if contents and contents != '"not yet implemented"': for data in json.loads(contents)['entries']: try: parent = data['parents'][0] except IndexError: parent = None iso8601 = HgTool.date_tuple_to_iso8601(data['date']) changeset = Commit(id=data['node'], message=data['desc'], author_name=data['user'], date=iso8601, parent=parent, base_commit_id=parent) results.append(changeset) return results
def _build_commit_from_rsp(self, commit_rsp): """Return a Commit from an API reesponse. This will parse a response from the API and return a structured commit. Args: commit_rsp (dict): The API payload for a commit. Returns: reviewboard.scmtools.core.Commit: A commit based on the payload. """ commit = Commit( author_name=commit_rsp['author']['raw'], id=commit_rsp['hash'], date=commit_rsp['date'], message=commit_rsp['message']) if commit_rsp['parents']: commit.parent = commit_rsp['parents'][0]['hash'] return commit
def get_change(self, repository, revision): repo_api_url = self._get_repo_api_url(repository) # Step 1: fetch the commit itself that we want to review, to get # the parent SHA and the commit message. Hopefully this information # is still in cache so we don't have to fetch it again. commit = cache.get(repository.get_commit_cache_key(revision)) if commit: author_name = commit.author_name date = commit.date parent_revision = commit.parent message = commit.message else: url = self._build_api_url(repo_api_url, "commits") url += "&sha=%s" % revision commit = self._api_get(url)[0] author_name = commit["commit"]["author"]["name"] date = (commit["commit"]["committer"]["date"],) parent_revision = commit["parents"][0]["sha"] message = commit["commit"]["message"] # Step 2: fetch the "compare two commits" API to get the diff. url = self._build_api_url(repo_api_url, "compare/%s...%s" % (parent_revision, revision)) comparison = self._api_get(url) tree_sha = comparison["base_commit"]["commit"]["tree"]["sha"] files = comparison["files"] # Step 3: fetch the tree for the original commit, so that we can get # full blob SHAs for each of the files in the diff. url = self._build_api_url(repo_api_url, "git/trees/%s" % tree_sha) url += "&recursive=1" tree = self._api_get(url) file_shas = {} for file in tree["tree"]: file_shas[file["path"]] = file["sha"] diff = [] for file in files: filename = file["filename"] status = file["status"] patch = file["patch"] diff.append("diff --git a/%s b/%s" % (filename, filename)) if status == "modified": old_sha = file_shas[filename] new_sha = file["sha"] diff.append("index %s..%s 100644" % (old_sha, new_sha)) diff.append("--- a/%s" % filename) diff.append("+++ b/%s" % filename) elif status == "added": new_sha = file["sha"] diff.append("new file mode 100644") diff.append("index %s..%s" % ("0" * 40, new_sha)) diff.append("--- /dev/null") diff.append("+++ b/%s" % filename) elif status == "removed": old_sha = file_shas[filename] diff.append("deleted file mode 100644") diff.append("index %s..%s" % (old_sha, "0" * 40)) diff.append("--- a/%s" % filename) diff.append("+++ /dev/null") diff.append(patch) diff = "\n".join(diff) # Make sure there's a trailing newline if not diff.endswith("\n"): diff += "\n" commit = Commit(author_name, revision, date, message, parent_revision) commit.diff = diff return commit
resource = 'commits' url = self._build_api_url(repository, resource) if start: url += '&sha=%s' % start try: rsp = self._api_get(url) except Exception, e: logging.warning('Failed to fetch commits from %s: %s', url, e) return results for item in rsp: commit = Commit( item['commit']['author']['name'], item['sha'], item['commit']['committer']['date'], item['commit']['message']) if item['parents']: commit.parent = item['parents'][0]['sha'] results.append(commit) return results def get_change(self, repository, revision): # Step 1: fetch the commit itself that we want to review, to get # the parent SHA and the commit message. Hopefully this information # is still in cache so we don't have to fetch it again. commit = cache.get(repository.get_commit_cache_key(revision)) if commit:
def get_change(self, repository, revision): # Step 1: fetch the commit itself that we want to review, to get # the parent SHA and the commit message. Hopefully this information # is still in cache so we don't have to fetch it again. commit = cache.get(repository.get_commit_cache_key(revision)) if commit: author_name = commit.author_name date = commit.date parent_revision = commit.parent message = commit.message else: url = self._build_api_url(repository, 'commits') url += '&sha=%s' % revision commit = self._api_get(url)[0] author_name = commit['commit']['author']['name'] date = commit['commit']['committer']['date'], parent_revision = commit['parents'][0]['sha'] message = commit['commit']['message'] # Step 2: fetch the "compare two commits" API to get the diff. url = self._build_api_url( repository, 'compare/%s...%s' % (parent_revision, revision)) comparison = self._api_get(url) tree_sha = comparison['base_commit']['commit']['tree']['sha'] files = comparison['files'] # Step 3: fetch the tree for the original commit, so that we can get # full blob SHAs for each of the files in the diff. url = self._build_api_url(repository, 'git/trees/%s' % tree_sha) url += '&recursive=1' tree = self._api_get(url) file_shas = {} for file in tree['tree']: file_shas[file['path']] = file['sha'] diff = [] for file in files: filename = file['filename'] status = file['status'] patch = file['patch'] diff.append('diff --git a/%s b/%s' % (filename, filename)) if status == 'modified': old_sha = file_shas[filename] new_sha = file['sha'] diff.append('index %s..%s 100644' % (old_sha, new_sha)) diff.append('--- a/%s' % filename) diff.append('+++ b/%s' % filename) elif status == 'added': new_sha = file['sha'] diff.append('new file mode 100644') diff.append('index %s..%s' % ('0' * 40, new_sha)) diff.append('--- /dev/null') diff.append('+++ b/%s' % filename) elif status == 'removed': old_sha = file_shas[filename] diff.append('deleted file mode 100644') diff.append('index %s..%s' % (old_sha, '0' * 40)) diff.append('--- a/%s' % filename) diff.append('+++ /dev/null') diff.append(patch) diff = '\n'.join(diff) # Make sure there's a trailing newline if not diff.endswith('\n'): diff += '\n' commit = Commit(author_name, revision, date, message, parent_revision) commit.diff = diff return commit