# HG changeset patch # User Andrew Shadura # Date 2017-04-15 14:10:39 # Node ID 2cf6d49b6073621299eef8f6e522cb3a2e745414 # Parent 6f6ee1cfe2d6716db26141615d268e8d27bb6474 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. 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 historic pull requests using Git by fetching a ref from the source repository. Unlike GitHub though, 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. We may later provide a shim to redirect users to the source repository if that deems needed. diff --git a/kallithea/model/pull_request.py b/kallithea/model/pull_request.py --- a/kallithea/model/pull_request.py +++ b/kallithea/model/pull_request.py @@ -39,7 +39,7 @@ from kallithea.lib import helpers as h from kallithea.model.db import PullRequest, PullRequestReviewer, Notification, \ ChangesetStatus, User from kallithea.model.notification import NotificationModel -from kallithea.lib.utils2 import extract_mentioned_users, safe_unicode +from kallithea.lib.utils2 import extract_mentioned_users, safe_str, safe_unicode log = logging.getLogger(__name__) @@ -139,6 +139,12 @@ class PullRequestModel(object): def delete(self, pull_request): pull_request = PullRequest.guess_instance(pull_request) Session().delete(pull_request) + if pull_request.org_repo.scm_instance.alias == 'git': + # remove a ref under refs/pull/ so that commits can be garbage-collected + try: + del pull_request.org_repo.scm_instance._repo["refs/pull/%d/head" % pull_request.pull_request_id] + except KeyError: + pass def close_pull_request(self, pull_request): pull_request = PullRequest.guess_instance(pull_request) @@ -228,6 +234,7 @@ class CreatePullRequestAction(object): self.org_repo = org_repo self.other_repo = other_repo self.org_ref = org_ref + self.org_rev = org_rev self.other_ref = other_ref self.title = title self.description = description @@ -252,6 +259,10 @@ class CreatePullRequestAction(object): Session().add(pr) Session().flush() # make database assign pull_request_id + if self.org_repo.scm_instance.alias == 'git': + # create a ref under refs/pull/ so that commits don't get garbage-collected + self.org_repo.scm_instance._repo["refs/pull/%d/head" % pr.pull_request_id] = safe_str(self.org_rev) + #reset state to under-review from kallithea.model.changeset_status import ChangesetStatusModel from kallithea.model.comment import ChangesetCommentsModel