def list_generate(bad, good): notable_hashes = [] start = None end = None if git.is_ancestor('fix-pack-base-7010', bad): if git.is_ancestor('fix-pack-base-7010', good): start = bad if git.is_ancestor(bad, good) else good end = bad if start == good else good notable_hashes = sublist_generate(start + '~1', end) else: start = bad end = good notable_hashes = notable_hashes + sublist_generate( 'cc57347219da4911d30b154188a99c6a628f6079', end) notable_hashes = notable_hashes + sublist_generate( start + '~1', 'fix-pack-de-27-7010') else: if git.is_ancestor('fix-pack-base-7010', good): start = good end = bad notable_hashes = notable_hashes + sublist_generate( 'cc57347219da4911d30b154188a99c6a628f6079', end) notable_hashes = notable_hashes + sublist_generate( start + '~1', 'fix-pack-de-27-7010') else: bad_first = git.is_ancestor(bad, good) good_first = git.is_ancestor(good, bad) if bad_first and not good_first: start = bad end = good elif good_first and not bad_first: start = good end = bad else: common_ancestor = git.merge_base(bad, good).strip() bad_first = len( git.log('--pretty=%H', '%s..%s' % (common_ancestor, bad)).split('\n')) good_first = len( git.log('--pretty=%H', '%s..%s' % (common_ancestor, good)).split('\n')) start = common_ancestor end = bad if bad_first > good_first else good notable_hashes = sublist_generate(start + '~1', end) if end == good: notable_hashes[0]['status'] = 'good' notable_hashes[-1]['status'] = 'bad' else: notable_hashes[-1]['status'] = 'good' notable_hashes[0]['status'] = 'bad' generate_html(notable_hashes)
def post(self): review_req = flask.request.json print review_req try: project = review_req['project'] title = review_req.get('title', '') latest_round = review_req['latest_round'] project_id = project['project_id'] base_branch = latest_round['merge_base_branch'] base_commit = latest_round['merge_base_commit'] review_branch = latest_round['branch_tip_name'] review_commit = latest_round['branch_tip_commit'] reviewers = review_req.get('reviewers', []) or [] observers = review_req.get('observers', []) or [] except KeyError as e: flask.abort(400, str(e)) # TODO: make sure there isn't already a review with these specs # find common ancestor base_commit = git.merge_base(project_id, base_commit, review_commit) authors = list(git.rev_list_authors(project_id, base_commit, review_commit)) reviewers = list(set(reviewers)) observers = list(set(observers)) logger.debug('Creating review from %s@%s -> %s@%s; title=%s', review_branch, review_commit[0:7], base_branch, base_commit[0:7], title) review = model.Review(project_id=project_id, status='new', title=title, authors=authors, reviewers=reviewers, observers=observers) db.session().add(review) round = create_round(review, base_branch, base_commit, review_branch, review_commit) db.session().add(round) db.session().commit() logger.debug('Review %d: created.', review.review_id) return {'review_id': review.review_id}
def put(self, review_id): # for adding rounds print flask.request.json review = db.session().query(model.Review).filter_by(review_id=review_id).one() branches = git.branch_list(review.project_id) # extract and validate arguments base_branch = flask.request.json.get('merge_base_branch') review_branch = flask.request.json.get('branch_tip_name') base_commit = [branch for branch in branches if branch['name'] == base_branch] review_commit = [branch for branch in branches if branch['name'] == review_branch] if review_branch is None or len(base_commit) != 1 or len(review_commit) != 1: flask.abort(400) base_commit = base_commit[0]['commit'] review_commit = review_commit[0]['commit'] # replace HEAD of base branch with merge-base of the two branches base_commit = git.merge_base(review.project_id, base_commit, review_commit) # if this is the same as the latest round, don't add it latest_round = review.rounds[-1] if (latest_round.merge_base_branch == base_branch and latest_round.merge_base_commit == base_commit and latest_round.branch_tip_name == review_branch and latest_round.branch_tip_commit == review_commit): return self.get(review_id) # create round from base to branch round = create_round(review, base_branch, base_commit, review_branch, review_commit) db.session().add(round) db.session().commit() return self.get(review_id)
def _check_new_branch(self, branch, input_work_dir, output_work_dir, output_reference): # try to find merge-base in input tree, # assumes master branch is always mirrored # # this handles the case of having created a new branch, # and asking for that to be mirrored into the prune tree. base_id = git.merge_base('origin/' + self.master, 'origin/' + branch, tree=input_work_dir) git.clone(output_reference, output_work_dir, options=['-q']) git.set_origin_url(self._output_tree, output_work_dir) # try to find the merge-base or its parent/grandparent/... in the # output tree - since it should have been branched from the master # (or in any case we look at the merge-base between master and it) # this should exist - HOWEVER: some commits might not be mirrored, # so look for the *parent [with a reasonable limit] for offset in range(0, self.max_parents): search = git.rev_parse(rev='%s~%d' % (base_id, offset), tree=input_work_dir) self.debug('search for %s~%d=%s:' % (base_id, offset, search)) grep = '%s: %s' % (self._commit_id_prefix, search) out_commits = git.log(options=[ '--grep', grep, '--format=format:%H', 'origin/' + self.output_branch_name(self.master) ], tree=output_work_dir) out_commits = out_commits.split() if not out_commits or len(out_commits) > 1: self.debug('not found') continue start_commit = out_commits[0] self.debug('found at %s' % start_commit) return start_commit raise Exception('failed to find parent/grandparent/...')
def _check_new_branch(self, branch, input_work_dir, output_work_dir, output_reference): # This handles the case of having created a new branch, # and asking for that to be mirrored into the prune tree. # # Try to find a starting point in the input tree. We assume # this will basically always succeed, since the master branch # is always mirrored, we _should_ find something (but can fail # if somebody created a branch without a merge-base.) # unfortunately we now need to do this first, to sort out which # branches we already know in the output git.clone(output_reference, output_work_dir, options=['-q']) self.debug("trying to find starting point for new branch %s" % branch) candidate_branches = [] for other in self._branches: if other == branch: continue out_branch = 'origin/' + self.output_branch_name(other) try: git.rev_parse(out_branch, tree=output_work_dir) except: self.debug(" branch %s doesn't exist in output %s (yet)" % (out_branch, output_work_dir)) continue candidate_branches.append(other) potential_merge_bases = [] for other in candidate_branches: try: base = git.merge_base('origin/' + other, 'origin/' + branch, tree=input_work_dir) potential_merge_bases.append(base) self.debug(" base to %s is %s" % (other, base)) except git.GitError: self.debug(" no base to %s" % (other, )) bases = git.independent_commits(potential_merge_bases, tree=input_work_dir) self.debug("found starting points %s" % (", ".join(bases))) assert len(bases) == 1, "No single merge base found: %r" % bases base_id = bases[0] base_branch = None for other in candidate_branches: if git.merge_base('origin/' + other, base_id, tree=input_work_dir) == base_id: base_branch = 'origin/' + self.output_branch_name(other) break assert base_branch, "This shouldn't happen, found no base branch?!" # try to find the merge-base or its parent/grandparent/... in the # output tree - since it should have been branched from the master # (or in any case we look at the merge-base between master and it) # this should exist - HOWEVER: some commits might not be mirrored, # so look for the *parent [with a reasonable limit] for offset in range(0, self.max_parents): search = git.rev_parse(rev='%s~%d' % (base_id, offset), tree=input_work_dir) self.debug('search for %s~%d=%s:' % (base_id, offset, search)) grep = '%s: %s' % (self._commit_id_prefix, search) out_commits = git.log( options=['--grep', grep, '--format=format:%H', base_branch], tree=output_work_dir) out_commits = out_commits.split() if not out_commits or len(out_commits) > 1: self.debug('not found') continue start_commit = out_commits[0] self.debug('found at %s' % start_commit) return start_commit raise Exception('failed to find parent/grandparent/...')