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, 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(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 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_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, 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_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 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, 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_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_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_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 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_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_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_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_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_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_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_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, 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_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 _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 test_get_change(self): """Testing Gerrit.get_change""" revision = '77c174669b7018936f16b98547445624c6738e1e' paths = { '/a/projects/Project/commits/%s/diff/' % revision: { 'payload': b'fake diff', }, '/a/projects/Project/all-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', }]), }, } with self.setup_http_test(self.make_handler_for_paths(paths), expected_http_calls=2) as ctx: commit = ctx.service.get_change( repository=ctx.create_repository(), revision='77c174669b7018936f16b98547445624c6738e1e') self.assertEqual( commit, 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')) self.assertEqual(commit.diff, b'fake diff') ctx.assertHTTPCall( 0, url=('http://gerrit.example.com/a/projects/Project/all-commits/' '?limit=1&start=77c174669b7018936f16b98547445624c6738e1e')) ctx.assertHTTPCall( 1, url=('http://gerrit.example.com/a/projects/Project/commits/' '77c174669b7018936f16b98547445624c6738e1e/diff/'))
def test_get_change(self): """Testing BitBucket.get_change""" commit_sha = '1c44b461cebe5874a857c51a4a13a849a4d1e52d' parent_sha = '44568f7d33647d286691517e6325fea5c7a21d5e' paths = { '/api/2.0/repositories/myuser/myrepo/commit/%s' % commit_sha: { 'payload': self.dump_json({ 'hash': commit_sha, 'author': { 'raw': 'Some User <*****@*****.**>', }, 'date': '2017-01-24T13:11:22+00:00', 'message': 'This is a message.', 'parents': [{ 'hash': parent_sha }], }), }, '/api/2.0/repositories/myuser/myrepo/diff/%s' % commit_sha: { 'payload': b'This is a test \xc7.', }, } with self.setup_http_test(self.make_handler_for_paths(paths), expected_http_calls=2) as ctx: repository = ctx.create_repository(tool_name='Git') commit = ctx.service.get_change(repository, commit_sha) ctx.assertHTTPCall( 0, url=('https://bitbucket.org/api/2.0/repositories/myuser/myrepo/' 'commit/1c44b461cebe5874a857c51a4a13a849a4d1e52d' '?fields=author.raw%2Chash%2Cdate%2Cmessage%2Cparents.hash')) ctx.assertHTTPCall( 1, url=('https://bitbucket.org/api/2.0/repositories/myuser/myrepo/' 'diff/1c44b461cebe5874a857c51a4a13a849a4d1e52d')) self.assertEqual( commit, Commit(author_name='Some User <*****@*****.**>', date='2017-01-24T13:11:22+00:00', id=commit_sha, message='This is a message.', parent=parent_sha)) self.assertEqual(commit.diff, b'This is a test \xc7.\n')
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