def test_register_with_full_commit(self, client, **kwargs): git_commit = Commit( repository_id='safari', branch='main', id='8eba280e32daaf5fddbbb65aea37932ea9ad85df', timestamp=1601650100, order=0, committer='*****@*****.**', message='custom commit', ) self.assertEqual( 200, client.post(self.URL + '/api/commits', data=Commit.Encoder().default(git_commit)).status_code) response = client.get(self.URL + '/api/commits?repository_id=safari') self.assertEqual(200, response.status_code) self.assertEqual(Commit.from_json(response.json()[0]), git_commit) svn_commit = Commit( repository_id='webkit', branch='trunk', id='1234', timestamp=1601650100, order=0, committer='*****@*****.**', message='custom commit', ) self.assertEqual( 200, client.post(self.URL + '/api/commits', data=Commit.Encoder().default(svn_commit)).status_code) response = client.get(self.URL + '/api/commits?repository_id=webkit') self.assertEqual(200, response.status_code) self.assertEqual(Commit.from_json(response.json()[0]), svn_commit)
def test_encoding(self): commits_to_test = [ Commit( repository_id='safari', branch='master', id='e64810a40c3fecb728871e12ca31482ca715b383', timestamp=1537550685, ), Commit( repository_id='safari', branch='master', id='7be4084258a452e8fe22f36287c5b321e9c8249b', timestamp=1537550685, order=1, committer='*****@*****.**', message='Changelog', ), Commit( repository_id='webkit', branch='master', id=236522, timestamp=1537826614, ), ] for commit in commits_to_test: converted_commit = Commit.from_json(commit.to_json()) self.assertEqual(commit, converted_commit) self.assertEqual(commit.repository_id, converted_commit.repository_id) self.assertEqual(commit.id, converted_commit.id) self.assertEqual(commit.timestamp, converted_commit.timestamp) self.assertEqual(commit.order, converted_commit.order) self.assertEqual(commit.committer, converted_commit.committer) self.assertEqual(commit.message, converted_commit.message)
def _find_comparison(commit_context, repository_id, branch, id, uuid, timestamp, priority=min): if bool(id) + bool(uuid) + bool(timestamp) > 1: abort(400, description='Can only search by one of [commit id, commit uuid, timestamp] in a single request') try: if uuid: # We don't need real commit to search by uuid and CommitContexts have trouble diffrentiating between uuids and timestamps. uuid = priority([int(element) for element in uuid]) return Commit('?', '?', '?', uuid // Commit.TIMESTAMP_TO_UUID_MULTIPLIER, uuid % Commit.TIMESTAMP_TO_UUID_MULTIPLIER) if timestamp: return priority([round(float(element)) for element in timestamp]) except ValueError: abort(400, description='Timestamp and uuid must be integers') if not repository_id and not id: return None if not repository_id: repository_id = commit_context.repositories.keys() for repository in repository_id: if repository not in commit_context.repositories.keys(): abort(404, description=f"\'{repository}\' is not a registered repository") result = [] for repository in repository_id: for b in branch: if id: for elm in id: result += commit_context.find_commits_by_id(repository, b, elm) else: result += commit_context.find_commits_in_range(repository, b, limit=1) if not result: abort(404, description='No commits found matching the specified criteria') return priority(result)
def commit_for_id(self, id, branch=DEFAULT_BRANCH): with self.session(): try: commit_data = self.get( branch=branch, revision=id )['D:multistatus']['D:response']['D:propstat'][0]['D:prop'] if commit_data['lp1:version-name'] != str(id): raise SCMException( f'Revision {id} does not exist on branch {branch}') # Of the form '2018-09-24T22:03:34.436217Z' timestamp = datetime.datetime.strptime( commit_data['lp1:creationdate'], '%Y-%m-%dT%H:%M:%S.%fZ') return Commit( repository_id=self.key, id=str(id), branch=branch, timestamp=timestamp, order=0, committer=commit_data['lp1:creator-displayname'], ) except ExpatError: raise SCMException(f'Failed to connect to {self.url}') except KeyError: raise SCMException( f'Revision {id} does not exist on branch {branch}')
def test_invalid(self): with self.assertRaises(ValueError): Commit( repository_id='safari', branch='master', id='7be4084258a452e8fe22f36287c5b321e9c8249b', timestamp=None, )
def to_commit(self): return Commit( repository_id=self.repository_id, branch=self.branch, id=self.commit_id, timestamp=self.uuid // Commit.TIMESTAMP_TO_UUID_MULTIPLIER, order=self.uuid % Commit.TIMESTAMP_TO_UUID_MULTIPLIER, committer=self.committer, message=self.message, )
def test_udid(self): self.assertEqual( Commit( repository_id='safari', branch='master', id='7be4084258a452e8fe22f36287c5b321e9c8249b', timestamp=1537550685, order=1, ).uuid, 153755068501)
def commit_for_id(self, id): commit = self.remote.commit(revision=id, include_identifier=False) return Commit( repository_id=self.key, id=commit.revision, branch=commit.branch, timestamp=commit.timestamp, order=commit.order, committer=commit.author.email, message=commit.message, )
def test_compare(self): commit1 = Commit( repository_id='safari', branch='master', id='e64810a40c3fecb728871e12ca31482ca715b383', timestamp=1537550685, ) commit2 = Commit( repository_id='safari', branch='master', id='7be4084258a452e8fe22f36287c5b321e9c8249b', timestamp=1537550685, order=1, ) commit3 = Commit( repository_id='safari', branch='master', id='bb6bda5f44dd24d0b54539b8ff6e8c17f519249a', timestamp=1537810281, ) commit4 = Commit( repository_id='webkit', branch='master', id=236522, timestamp=1537826614, ) self.assertTrue(commit2 > commit1) self.assertTrue(commit2 >= commit1) self.assertTrue(commit1 >= commit1) self.assertTrue(commit1 < commit2) self.assertTrue(commit1 <= commit2) self.assertTrue(commit1 <= commit1) self.assertTrue(commit1 == commit1) self.assertTrue(commit2 < commit3) self.assertTrue(commit3 > commit2) self.assertEqual(commit1.timestamp, commit2.timestamp) self.assertTrue(commit4 > commit3) self.assertNotEqual(commit3.repository_id, commit4.repository_id)
def commit_for_id(self, id, branch=Repository.DEFAULT_BRANCH): try: with self.session(): commit_data = self.get(f'commits/{id}') if not commit_data: raise SCMException( f'Commit {id} does not exist on branch {branch}') timestamp = int(commit_data['committerTimestamp'] ) // self.COMMIT_TIMESTAMP_CONVERSION branch_filter = urllib.parse.quote(f'refs/heads/{branch}') commits_between_commit_and_branch_head = self.get( f"commits?since={commit_data['id']}&until={branch_filter}&limit=1", cache=False) if commits_between_commit_and_branch_head[ 'isLastPage'] and commits_between_commit_and_branch_head[ 'size'] == 0: # We may have missed the case the commit in question is the HEAD of the branch commits_at_branch_head = self.get( f'commits?until={branch_filter}&limit=20', cache=False) if all([ commit['id'] != commit_data['id'] for commit in commits_at_branch_head['values'] ]): raise SCMException(f'{id} exists, but not on {branch}') # Ordering commits by timestamp in git is a bit problematic because multiple commits can share a timestamp. # Generally, if your parent shares your timestamp, your order needs to be incremented. order = 0 loop_data = commit_data while len(loop_data['parents']) == 1 and int( loop_data['parents'][0]['committerTimestamp'] ) // self.COMMIT_TIMESTAMP_CONVERSION == timestamp: order += 1 loop_data = self.get( f"commits/{loop_data['parents'][0]['id']}") return Commit( repository_id=self.key, id=commit_data['id'], branch=branch, timestamp=timestamp, order=order, committer=commit_data['committer']['emailAddress'], message=commit_data['message'], ) except ValueError: raise SCMException(f'Failed to connect to {self.url}')
def test_basic_svn(self, redis=StrictRedis): svn_repo = MockSVNRepository(url='svn.webkit.org/repository/webkit/', name='webkit', redis=redis()) svn_repo.add_commit( Commit( repository_id=svn_repo.name, branch='trunk', id=236544, timestamp=1538052408, order=0, committer='*****@*****.**', message='Change 1 description.', )) commit = svn_repo.commit_for_id(236544, branch='trunk') self.assertEqual(commit.uuid, 153805240800) self.assertIsNone(commit.message, None)
def safari(redis=None): result = MockStashRepository('https://fake-stash-instance.apple.com/projects/BROWSER/repos/safari', name='safari', redis=redis) result.add_commit(Commit( repository_id=result.name, branch='master', id='bb6bda5f44dd24d0b54539b8ff6e8c17f519249a', timestamp=1537810281, order=0, committer='*****@*****.**', message='Change 1 description.', )) result.add_commit(Commit( repository_id=result.name, branch='master', id='336610a84fdcf14ddcf1db65075af95480516fda', timestamp=1537809818, order=0, committer='*****@*****.**', message='Change 2 description.', )) result.add_commit(Commit( repository_id=result.name, branch='master', id='336610a40c3fecb728871e12ca31482ca715b383', timestamp=1537566386, order=0, committer='*****@*****.**', message='<rdar://problem/99999999> Change 3 description.', )) result.add_commit(Commit( repository_id=result.name, branch='master', id='e64810a40c3fecb728871e12ca31482ca715b383', timestamp=1537550685, order=0, committer='*****@*****.**', message=u'Change 4 \u2014 (Part 1) description.', )) result.add_commit(Commit( repository_id=result.name, branch='master', id='7be4084258a452e8fe22f36287c5b321e9c8249b', timestamp=1537550685, order=1, committer='*****@*****.**', message=u'Change 4 \u2014 (Part 2) description.\nReviewed by person.', )) result.add_commit(Commit( repository_id=result.name, branch='safari-606-branch', id='79256c32a855ac8612112279008334d90e901c55', timestamp=1537897367, order=0, committer='*****@*****.**', message='Change 5 description.', )) result.add_commit(Commit( repository_id=result.name, branch='safari-606-branch', id='d85222d9407fdbbf47406509400a9cecb73ac6de', timestamp=1537563383, order=0, committer='*****@*****.**', message='Change 6 description.', )) return result
def webkit(redis=None): result = MockWebKitRepository(redis=redis) result.add_commit(Commit( repository_id=result.name, branch='trunk', id=236544, timestamp=1538052408, order=0, committer='*****@*****.**', message='Change 1 description.', )) result.add_commit(Commit( repository_id=result.name, branch='trunk', id=236543, timestamp=1538050458, order=0, committer='*****@*****.**', message='Change 2 description.', )) result.add_commit(Commit( repository_id=result.name, branch='trunk', id=236542, timestamp=1538049108, order=0, committer='*****@*****.**', message='Change 3 description.', )) result.add_commit(Commit( repository_id=result.name, branch='trunk', id=236541, timestamp=1538041792, order=0, committer='*****@*****.**', message='Change 4 (Part 2) description.', )) result.add_commit(Commit( repository_id=result.name, branch='trunk', id=236540, timestamp=1538029479, order=0, committer='*****@*****.**', message='Change 4 (Part 1) description.', )) result.add_commit(Commit( repository_id=result.name, branch='safari-606-branch', id=236335, timestamp=1538029480, order=0, committer='*****@*****.**', message='Integration 1.', )) result.add_commit(Commit( repository_id=result.name, branch='safari-606-branch', id=236334, timestamp=1538029479, order=0, committer='*****@*****.**', message='Integration 2.', )) return result
def register(self, commit=None, fast=True): is_endpoint = not bool(commit) if is_endpoint: AssertRequest.is_type(['POST']) AssertRequest.no_query() if is_endpoint: try: commit = request.form or json.loads(request.get_data()) if 'api_key' in commit: del commit['api_key'] except ValueError: abort(400, description='Expected uploaded data to be json') try: candidate = ScmCommit.from_json(commit) # Commit needs to be sufficiently defined if candidate.repository_id and candidate.branch and candidate.timestamp and ( candidate.revision or candidate.hash): self.commit_context.register_commit(candidate) if is_endpoint: return jsonify({'status': 'ok'}) return candidate except ValueError: pass required_args = ['repository_id'] for arg in required_args: if arg not in commit: abort(400, description=f"'{arg}' required to define commit") has_ref = False one_of_args = ['id', 'ref', 'hash', 'revision', 'identifier'] for arg in one_of_args: if arg in commit: if has_ref: abort(400, description='Multiple commit references specified') has_ref = True if not has_ref: abort(400, description='No commit reference specified') for arg in commit.keys(): if arg in required_args or arg in one_of_args: continue if arg in ['branch', 'timestamp', 'order', 'committer', 'message']: abort( 400, description= 'Not enough arguments provided to define a commit, but too many to search for a commit' ) abort(400, description=f"'{arg}' is not valid for defining commits") try: commit = self.commit_context.register_partial_commit( repository_id=commit.get('repository_id'), ref=commit.get('id') or commit.get('ref'), hash=commit.get('hash'), revision=commit.get('revision'), identifier=commit.get('identifier'), fast=fast, ) except (RuntimeError, ScmBase.Exception) as error: abort(404, description=str(error)) if is_endpoint: return jsonify({'status': 'ok'}) return Commit( repository_id=commit.repository_id, id=commit.revision or commit.hash, branch=commit.branch, timestamp=commit.timestamp, order=commit.order, committer=commit.author.email if commit.author else None, message=commit.message, )
def test_invalid(self): with self.assertRaises(ValueError) as error: Commit( repository_id='safari', branch='master', id='7be4084258a452e8fe22f36287c5b321e9c8249b', timestamp=None, ) self.assertEqual(str(error.exception), 'timestamp is not defined for commit') with self.assertRaises(ValueError) as error: Commit( repository_id='invalid-repo', branch='master', id='7be4084258a452e8fe22f36287c5b321e9c8249b', timestamp=1537550685, ) self.assertEqual(str(error.exception), "'invalid-repo' is an invalid repository id") with self.assertRaises(ValueError) as error: Commit( repository_id='i' * 129, branch='master', id='7be4084258a452e8fe22f36287c5b321e9c8249b', timestamp=1537550685, ) self.assertEqual(str(error.exception), f"'{'i' * 129}' is an invalid repository id") with self.assertRaises(ValueError) as error: Commit( repository_id='safari', branch='<html>invalid-branch</html>', id='7be4084258a452e8fe22f36287c5b321e9c8249b', timestamp=1537550685, ) self.assertEqual( str(error.exception), "'<html>invalid-branch</html>' is an invalid branch name") with self.assertRaises(ValueError) as error: Commit( repository_id='safari', branch='i' * 129, id='7be4084258a452e8fe22f36287c5b321e9c8249b', timestamp=1537550685, ) self.assertEqual(str(error.exception), f"'{'i' * 129}' is an invalid branch name") with self.assertRaises(ValueError) as error: Commit( repository_id='safari', branch='master', id='<html>1234</html>', timestamp=1537550685, ) self.assertEqual(str(error.exception), "'<html>1234</html>' is an invalid commit id") with self.assertRaises(ValueError) as error: Commit( repository_id='safari', branch='master', id='0' * 41, timestamp=1537550685, ) self.assertEqual(str(error.exception), f"'{'0' * 41}' is an invalid commit id")