diff --git a/pagure/lib/git.py b/pagure/lib/git.py index bc10fcb..166747c 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -996,6 +996,36 @@ class TemporaryClone(object): """ Exit the context manager, removing the temorary clone. """ shutil.rmtree(self.repopath) + def change_project_association(self, new_project): + """ Make this instance "belong" to another project. + + This is useful when you want to create TemporaryClone of one project + and then push some of its content into a different project just + by running ``push`` or ``mirror`` methods. + + Args: + new_project (pagure.lib.model.Project): project to associate + this TemporaryClone instance with + """ + self._project = new_project + if not new_project.is_on_repospanner: + self.repo.remotes.set_push_url( + "origin", new_project.repopath("main") + ) + + def mirror(self, username, force=False, **extra): + """ Run ``git push --mirror`` of the repo to its origin. + + Args: + username (string): The user on who's account this push is + force (bool): whether or not to use ``--force`` when pushing + extra (dict): Extra fields passed to the remote side. Either via + environment variables, or as X-Extra- HTTP headers. + """ + # git push --mirror fails if there are no branches + if len(list(self.repo.branches)) > 0: + self._push(username, "--mirror", force, **extra) + def push(self, username, sbranch, tbranch=None, force=False, **extra): """ Push the repo back to its origin. @@ -1003,11 +1033,23 @@ class TemporaryClone(object): username (string): The user on who's account this push is sbranch (string): Source branch to push tbranch (string): Target branch if different from sbranch + force (bool): whether or not to use ``--force`` when pushing extra (dict): Extra fields passed to the remote side. Either via environment variables, or as X-Extra- HTTP headers. """ pushref = "%s:%s" % (sbranch, tbranch if tbranch else sbranch) + self._push(username, pushref, force, **extra) + + def _push(self, username, pushref, force, **extra): + """ Push the repo back to its origin. + Args: + username (string): The user on who's account this push is + pushref(string): either ``:`` or ``--mirror`` + force (bool): whether or not to use ``--force`` when pushing + extra (dict): Extra fields passed to the remote side. Either via + environment variables, or as X-Extra- HTTP headers. + """ if "pull_request" in extra: extra["pull_request_uid"] = extra["pull_request"].uid del extra["pull_request"] diff --git a/pagure/lib/tasks.py b/pagure/lib/tasks.py index 3592c9d..193dcf3 100644 --- a/pagure/lib/tasks.py +++ b/pagure/lib/tasks.py @@ -471,26 +471,22 @@ def fork( ) with pagure.lib.git.TemporaryClone( - repo_to, "main", "fork" + repo_from, "main", "fork" ) as tempclone: - fork_repo = tempclone.repo - - fork_repo.remotes.create("forkedfrom", repo_from.repopath("main")) - fork_repo.remotes["forkedfrom"].fetch() - - for branchname in fork_repo.branches.remote: - if not branchname.startswith("forkedfrom/"): - continue - localname = branchname.replace("forkedfrom/", "") - if localname == "HEAD": - # HEAD will be created automatically as a symref - continue - tempclone.push( - "pagure", - "remotes/%s" % branchname, - "refs/heads/%s" % localname, - internal_no_hooks="yes", - ) + for branchname in tempclone.repo.branches.remote: + if ( + branchname.startswith("origin/") + and branchname != "origin/HEAD" + ): + locbranch = branchname[len("origin/") :] + if locbranch in tempclone.repo.branches.local: + continue + branch = tempclone.repo.branches.remote.get(branchname) + tempclone.repo.branches.local.create( + locbranch, branch.peel() + ) + tempclone.change_project_association(repo_to) + tempclone.mirror("pagure", internal_no_hooks="yes") if not repo_to.is_on_repospanner and not repo_to.private: # Create the git-daemon-export-ok file on the clone