[PATCH] git: add references for Git pull request heads
Mads Kiilerich
mads at kiilerich.com
Fri Jan 6 20:17:38 UTC 2017
On 01/06/2017 08:07 PM, Andrew Shadura wrote:
> # HG changeset patch
> # User Andrew Shadura <andrew at shadura.me>
> # Date 1474617925 -7200
> # Fri Sep 23 10:05:25 2016 +0200
> # Node ID d55296180cd477d84545d97d2abf1073ca8f0711
> # Parent 1341be63734a5b90253bdd1589caf1a01e9266d1
> git: add references for Git pull request heads
>
> When a pull request is created, stick a reference to it in the refs/pull
> namespace, similarly to what GitHub does, and remove it when the pull
> request is deleted.
How likely is it that our use of refs/pull will conflict with other uses
of it? Are these names local to the repo managed by Kallithea and not
shared with clients?
> That reference guarantees the commits stay around
> and don't get garbage-collected when a PR is rebased or revised.
> Also, that makes it possible to access head of the historis
(typo)
> pull
> requests using Git by fetching a ref from the source repository.
What does that mean?
Is it so that the pull command shown on a git PR also introduce a local
name for it so it is possible to check the revision out without getting
into detached head mode?
> Unlike Git though,
But this is Git. Do you mean github?
> we don't put the ref into the destination repository
> and don't copy commits there to prevent undesired repository growth.
> Kallithea uses global pull request identifiers, so there should not be
> any confusion as to what pull request the ref corresponds to.
That would be because the PR id is a part of the ref? Perhaps clarify
the exact refs naming scheme first.
> We may later provide a shim to redirect users to the source repository
> if that deems needed.
>
> diff --git a/kallithea/controllers/pullrequests.py b/kallithea/controllers/pullrequests.py
> --- a/kallithea/controllers/pullrequests.py
> +++ b/kallithea/controllers/pullrequests.py
> @@ -330,6 +330,8 @@ class PullrequestsController(BaseRepoCon
> if org_ref_type == 'rev':
> cs = org_repo.scm_instance.get_changeset(org_rev)
> org_ref = 'branch:%s:%s' % (cs.branch, cs.raw_id)
> + else:
> + cs = org_rev
In one branch cs is a changeset, in the other it is just the hash of it?
I suggest making it more consistent and just make the "cs =
org_repo.scm_instance.get_changeset(org_rev)" unconditional.
Or perhaps even better: just use org_rev instead of cs?
> other_repo_name = _form['other_repo']
> other_ref = _form['other_ref'] # will have symbolic name and head revision
> @@ -385,6 +387,11 @@ class PullrequestsController(BaseRepoCon
> created_by, org_repo, org_ref, other_repo, other_ref, revisions,
> title, description, reviewer_ids)
> Session().commit()
> +
> + if org_repo.scm_instance.alias == 'git':
> + # create a ref under refs/pull/ so that commits don't get garbage-collected
> + org_repo.scm_instance._repo["refs/pull/%d/head" % pull_request.pull_request_id] = safe_str(cs)
> +
> h.flash(_('Successfully opened new pull request'),
> category='success')
> except UserInvalidException as u:
> @@ -579,6 +586,14 @@ class PullrequestsController(BaseRepoCon
> if pull_request.owner_id == c.authuser.user_id:
> PullRequestModel().delete(pull_request)
> Session().commit()
> +
> + if org_repo.scm_instance.alias == 'git':
> + # remove a ref under refs/pull/ so that commits can be garbage-collected
> + try:
> + del org_repo.scm_instance._repo["refs/pull/%s/head" % safe_str(pull_request_id)]
The safe_str is a bit odd when we know it is a number. Perhaps use
pull_request.pull_request_id instead? It is perhaps a bit dirty to use
pull_request outside the transaction ... but the id must already be
fetched and I think it is better than safe_str.
I wonder if it is better to do this deletion inside or outside the
transaction ... but I can see how it is safer to do it outside.
> + except KeyError:
> + pass
> +
> h.flash(_('Successfully deleted pull request'),
> category='success')
> raise HTTPFound(location=url('my_pullrequests'))
> @@ -803,8 +818,17 @@ class PullrequestsController(BaseRepoCon
> h.HasRepoPermissionAny('repository.admin')(pull_request.org_repo.repo_name) or
> h.HasRepoPermissionAny('repository.admin')(pull_request.other_repo.repo_name)
> ) and not pull_request.is_closed():
> + org_repo = RepoModel()._get_repo(pull_request.org_repo.repo_name)
> PullRequestModel().delete(pull_request)
> Session().commit()
> +
> + if org_repo.scm_instance.alias == 'git':
> + # remove a ref under refs/pull/ so that commits can be garbage-collected
> + try:
> + del org_repo.scm_instance._repo["refs/pull/%s/head" % safe_str(pull_request_id)]
> + except KeyError:
> + pass
This looks a bit like there should be a function for PR deletion so we
don't have to repeat this.
/Mads
> +
> h.flash(_('Successfully deleted pull request %s') % pull_request_id,
> category='success')
> return {
> _______________________________________________
> kallithea-general mailing list
> kallithea-general at sfconservancy.org
> https://lists.sfconservancy.org/mailman/listinfo/kallithea-general
More information about the kallithea-general
mailing list