Browse Source

Integrate repoSpanner

This allows configuring new repositories to be created on repoSpanner, and allows
existing ones to be migrated over.
Support is included for multiple regions/setups, although migrating between regions
is not supported (technically nothing limiting, but not required for first version).

The actual repoSpanner parts require a repoSpanner enlightened libgit2 build.

The test suite requires the patched libgit2 and a repoSpanner daemon binary.
This binary can either be in /usr/bin/repospanner, or in the top level directory.
If this binary can't be found, the test will be marked as Skipped.
In addition, it requires an /etc/hosts entry with:
127.0.0.1	nodea.regiona.repospanner.local

Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org>
Patrick Uiterwijk 5 years ago
parent
commit
3f97f6a980
68 changed files with 1591 additions and 1646 deletions
  1. 3 0
      .gitignore
  2. 22 0
      alembic/versions/19b67f4b9fe4_add_repospanner_region_column.py
  3. 29 0
      files/pagure.cfg.sample
  4. 1 2
      pagure/api/__init__.py
  5. 1 6
      pagure/api/ci/jenkins.py
  6. 8 17
      pagure/api/fork.py
  7. 0 10
      pagure/api/issue.py
  8. 6 11
      pagure/api/project.py
  9. 3 2
      pagure/decorators.py
  10. 27 0
      pagure/default_config.py
  11. 1 1
      pagure/docs_server.py
  12. 5 2
      pagure/flask_app.py
  13. 19 1
      pagure/forms.py
  14. 5 10
      pagure/internal/__init__.py
  15. 91 168
      pagure/lib/__init__.py
  16. 549 507
      pagure/lib/git.py
  17. 9 1
      pagure/lib/git_auth.py
  18. 2 9
      pagure/lib/lib_ci.py
  19. 106 0
      pagure/lib/model.py
  20. 158 205
      pagure/lib/tasks.py
  21. 1 3
      pagure/lib/tasks_services.py
  22. 3 0
      pagure/templates/new_project.html
  23. 7 0
      pagure/templates/settings.html
  24. 37 0
      pagure/templates/settings_repospanner.html
  25. 5 4
      pagure/ui/app.py
  26. 8 48
      pagure/ui/fork.py
  27. 5 29
      pagure/ui/issues.py
  28. 69 13
      pagure/ui/repo.py
  29. 4 8
      pagure/utils.py
  30. 36 0
      tests/__init__.py
  31. 2 24
      tests/test_pagure_flask_api_fork.py
  32. 0 20
      tests/test_pagure_flask_api_issue.py
  33. 0 2
      tests/test_pagure_flask_api_issue_change_status.py
  34. 0 2
      tests/test_pagure_flask_api_issue_comment.py
  35. 0 1
      tests/test_pagure_flask_api_issue_custom_fields.py
  36. 0 2
      tests/test_pagure_flask_api_pr_flag.py
  37. 4 8
      tests/test_pagure_flask_api_project.py
  38. 0 1
      tests/test_pagure_flask_api_project_update_watch.py
  39. 1 13
      tests/test_pagure_flask_api_ui_private_repo.py
  40. 0 14
      tests/test_pagure_flask_api_user.py
  41. 8 8
      tests/test_pagure_flask_docs.py
  42. 1 10
      tests/test_pagure_flask_dump_load_ticket.py
  43. 0 10
      tests/test_pagure_flask_internal.py
  44. 1 10
      tests/test_pagure_flask_ui_app.py
  45. 0 12
      tests/test_pagure_flask_ui_fork.py
  46. 0 3
      tests/test_pagure_flask_ui_issue_pr_link.py
  47. 2 44
      tests/test_pagure_flask_ui_issues.py
  48. 0 12
      tests/test_pagure_flask_ui_issues_acl_checks.py
  49. 0 2
      tests/test_pagure_flask_ui_issues_private.py
  50. 0 2
      tests/test_pagure_flask_ui_issues_read_only.py
  51. 3 12
      tests/test_pagure_flask_ui_plugins_default_hook.py
  52. 0 1
      tests/test_pagure_flask_ui_pr_no_sources.py
  53. 4 55
      tests/test_pagure_flask_ui_repo.py
  54. 0 4
      tests/test_pagure_flask_ui_repo_delete_project.py
  55. 0 1
      tests/test_pagure_flask_ui_repo_milestones.py
  56. 2 8
      tests/test_pagure_flask_ui_repo_slash_name.py
  57. 46 231
      tests/test_pagure_lib.py
  58. 4 7
      tests/test_pagure_lib_drop_issue.py
  59. 4 32
      tests/test_pagure_lib_git.py
  60. 0 6
      tests/test_pagure_lib_git_diff_pr.py
  61. 0 3
      tests/test_pagure_lib_link.py
  62. 0 2
      tests/test_pagure_lib_model.py
  63. 0 10
      tests/test_pagure_lib_notify.py
  64. 0 4
      tests/test_pagure_lib_notify_email.py
  65. 0 2
      tests/test_pagure_lib_task_services.py
  66. 0 8
      tests/test_pagure_lib_watch_list.py
  67. 289 0
      tests/test_pagure_repospanner.py
  68. 0 3
      tests/test_stream_server.py

+ 3 - 0
.gitignore

@@ -52,3 +52,6 @@ dev/docker/test_env
 
 # Tox virtualenvs
 .tox
+
+# A possible symlink for the testsuite
+/repospanner

+ 22 - 0
alembic/versions/19b67f4b9fe4_add_repospanner_region_column.py

@@ -0,0 +1,22 @@
+"""Add repoSpanner region column
+
+Revision ID: 19b67f4b9fe4
+Revises: ef98dcb838e4
+Create Date: 2018-09-08 13:27:31.978954
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '19b67f4b9fe4'
+down_revision = 'ef98dcb838e4'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.add_column('projects', sa.Column('repospanner_region', sa.Text(), nullable=True))
+
+
+def downgrade():
+    op.drop_column('projects', 'repospanner_region')

+ 29 - 0
files/pagure.cfg.sample

@@ -73,6 +73,12 @@ GIT_FOLDER = os.path.join(
     'repos'
 )
 
+REPOSPANNER_PSEUDO_FOLDER = os.path.join(
+    os.path.abspath(os.path.dirname(__file__)),
+    '..',
+    'pseudo'
+)
+
 ### Folder containing the clones for the remote pull-requests
 REMOTE_GIT_FOLDER = os.path.join(
     os.path.abspath(os.path.dirname(__file__)),
@@ -203,3 +209,26 @@ APPLICATION_ROOT = '/'
 # was running since before version 1.3 and if you care about backward
 # compatibility in your URLs.
 OLD_VIEW_COMMIT_ENABLED = False
+
+# repoSpanner integration settings
+# https://repospanner.org/
+# Whether to create new repositories on repoSpanner by default.
+# Either None or a region name.
+REPOSPANNER_NEW_REPO = None
+# Whether to allow admins to override region selection on creation.
+REPOSPANNER_NEW_REPO_ADMIN_OVERRIDE = False
+# Whether to create new forks on repoSpanner.
+# Either None (no repoSpanner), True (same as origin project) or a region name.
+REPOSPANNER_NEW_FORK = True
+# Whether to allow an admin to manually migrate an individual project.
+REPOSPANNER_ADMIN_MIGRATION = False
+# The repoSpanner regions to be used in this Pagure instance.
+# Example entry:
+# 'default': {'url': 'https://nodea.regiona.repospanner.local:8444',
+#             'repo_prefix': 'pagure/',
+#             'ca': '',
+#             'admin_cert': {'cert': '',
+#                            'key': ''},
+#             'push_cert': {'cert': '',
+#                           'key': ''}}
+REPOSPANNER_REGIONS = {}

+ 1 - 2
pagure/api/__init__.py

@@ -319,7 +319,6 @@ from pagure.api import fork  # noqa: E402
 from pagure.api import project  # noqa: E402
 from pagure.api import user  # noqa: E402
 from pagure.api import group  # noqa: E402
-
 if pagure_config.get("PAGURE_CI_SERVICES", False):
     from pagure.api.ci import jenkins  # noqa: E402
 
@@ -592,7 +591,7 @@ def api():
         issues.append(load_doc(user.api_view_user_issues))
 
     ci_doc = []
-    if pagure_config.get("PAGURE_CI_SERVICES", True):
+    if pagure_config.get("PAGURE_CI_SERVICES", False):
         if "jenkins" in pagure_config["PAGURE_CI_SERVICES"]:
             ci_doc.append(load_doc(jenkins.jenkins_ci_notification))
 

+ 1 - 6
pagure/api/ci/jenkins.py

@@ -94,12 +94,7 @@ def jenkins_ci_notification(
         raise pagure.exceptions.APIError(400, error_code=APIERROR.EINVALIDREQ)
 
     try:
-        lib_ci.process_jenkins_build(
-            flask.g.session,
-            project,
-            build_id,
-            requestfolder=pagure.config.config["REQUESTS_FOLDER"],
-        )
+        lib_ci.process_jenkins_build(flask.g.session, project, build_id)
     except pagure.exceptions.NoCorrespondingPR as err:
         raise pagure.exceptions.APIError(
             400, error_code=APIERROR.ENOCODE, error=str(err)

+ 8 - 17
pagure/api/fork.py

@@ -11,7 +11,6 @@
 from __future__ import unicode_literals
 
 import logging
-import os
 
 import flask
 import pygit2
@@ -289,8 +288,11 @@ def api_pull_request_by_uid_view(uid):
     # that we're allowed to access it
     username = request.project.user.user if request.project.is_fork else None
     repo = get_authorized_api_project(
-        flask.g.session, request.project.name,
-        user=username, namespace=request.project.namespace)
+        flask.g.session,
+        request.project.name,
+        user=username,
+        namespace=request.project.namespace,
+    )
     if repo is None:
         raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOREQ)
 
@@ -572,11 +574,7 @@ def api_pull_request_close(repo, requestid, username=None, namespace=None):
 
     try:
         pagure.lib.close_pull_request(
-            flask.g.session,
-            request,
-            flask.g.fas_user.username,
-            requestfolder=pagure_config["REQUESTS_FOLDER"],
-            merged=False,
+            flask.g.session, request, flask.g.fas_user.username, merged=False
         )
         flask.g.session.commit()
         output["message"] = "Pull-request closed!"
@@ -701,7 +699,6 @@ def api_pull_request_add_comment(
                 row=row,
                 comment=comment,
                 user=flask.g.fas_user.username,
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
             )
             flask.g.session.commit()
             output["message"] = message
@@ -907,7 +904,6 @@ def api_pull_request_add_flag(repo, requestid, username=None, namespace=None):
                 uid=uid,
                 user=flask.g.fas_user.username,
                 token=flask.g.token.id,
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
             )
             flask.g.session.commit()
             pr_flag = pagure.lib.get_pull_request_flag_by_uid(
@@ -1202,12 +1198,8 @@ def api_pull_request_create(repo, username=None, namespace=None):
             401, error_code=APIERROR.ENOTHIGHENOUGH
         )
 
-    repo_obj = pygit2.Repository(
-        os.path.join(pagure_config["GIT_FOLDER"], repo.path)
-    )
-    orig_repo = pygit2.Repository(
-        os.path.join(pagure_config["GIT_FOLDER"], parent.path)
-    )
+    repo_obj = pygit2.Repository(repo.repopath("main"))
+    orig_repo = pygit2.Repository(parent.repopath("main"))
 
     try:
         diff, diff_commits, orig_commit = pagure.lib.git.get_diff_info(
@@ -1246,7 +1238,6 @@ def api_pull_request_create(repo, username=None, namespace=None):
         title=form.title.data,
         initial_comment=initial_comment,
         user=flask.g.fas_user.username,
-        requestfolder=pagure_config["REQUESTS_FOLDER"],
         commit_start=commit_start,
         commit_stop=commit_stop,
     )

+ 0 - 10
pagure/api/issue.py

@@ -306,7 +306,6 @@ def api_new_issue(repo, username=None, namespace=None):
                 priority=priority,
                 tags=tags,
                 user=flask.g.fas_user.username,
-                ticketfolder=pagure_config["TICKETS_FOLDER"],
             )
             flask.g.session.flush()
             # If there is a file attached, attach it.
@@ -850,7 +849,6 @@ def api_change_status_issue(repo, issueid, username=None, namespace=None):
                 status=new_status,
                 close_status=close_status,
                 user=flask.g.fas_user.username,
-                ticketfolder=pagure_config["TICKETS_FOLDER"],
             )
             flask.g.session.commit()
             if message:
@@ -864,7 +862,6 @@ def api_change_status_issue(repo, issueid, username=None, namespace=None):
                     obj=issue,
                     messages=message,
                     user=flask.g.fas_user.username,
-                    gitfolder=pagure_config["TICKETS_FOLDER"],
                 )
         except pagure.exceptions.PagureException as err:
             raise pagure.exceptions.APIError(
@@ -956,7 +953,6 @@ def api_change_milestone_issue(repo, issueid, username=None, namespace=None):
                 issue=issue,
                 milestone=new_milestone,
                 user=flask.g.fas_user.username,
-                ticketfolder=pagure_config["TICKETS_FOLDER"],
             )
             flask.g.session.commit()
             if message:
@@ -970,7 +966,6 @@ def api_change_milestone_issue(repo, issueid, username=None, namespace=None):
                     obj=issue,
                     messages=message,
                     user=flask.g.fas_user.username,
-                    gitfolder=pagure_config["TICKETS_FOLDER"],
                 )
         except pagure.exceptions.PagureException as err:
             raise pagure.exceptions.APIError(
@@ -1054,7 +1049,6 @@ def api_comment_issue(repo, issueid, username=None, namespace=None):
                 issue=issue,
                 comment=comment,
                 user=flask.g.fas_user.username,
-                ticketfolder=pagure_config["TICKETS_FOLDER"],
             )
             flask.g.session.commit()
             output["message"] = message
@@ -1144,7 +1138,6 @@ def api_assign_issue(repo, issueid, username=None, namespace=None):
                 issue=issue,
                 assignee=assignee,
                 user=flask.g.fas_user.username,
-                ticketfolder=pagure_config["TICKETS_FOLDER"],
             )
             flask.g.session.commit()
             if message:
@@ -1153,7 +1146,6 @@ def api_assign_issue(repo, issueid, username=None, namespace=None):
                     obj=issue,
                     messages=message,
                     user=flask.g.fas_user.username,
-                    gitfolder=pagure_config["TICKETS_FOLDER"],
                 )
                 output["message"] = message
             else:
@@ -1345,7 +1337,6 @@ def api_update_custom_field(
                 obj=issue,
                 messages=message,
                 user=flask.g.fas_user.username,
-                gitfolder=pagure_config["TICKETS_FOLDER"],
             )
         else:
             output["message"] = "No changes"
@@ -1469,7 +1460,6 @@ def api_update_custom_fields(repo, issueid, username=None, namespace=None):
                     obj=issue,
                     messages=message,
                     user=flask.g.fas_user.username,
-                    gitfolder=pagure_config["TICKETS_FOLDER"],
                 )
             else:
                 output["messages"].append({key.name: "No changes"})

+ 6 - 11
pagure/api/project.py

@@ -757,12 +757,17 @@ def api_new_project():
         private = False
         if pagure_config.get("PRIVATE_PROJECTS", False):
             private = form.private.data
+        if form.repospanner_region:
+            repospanner_region = form.repospanner_region.data
+        else:
+            repospanner_region = None
 
         try:
             task = pagure.lib.new_project(
                 flask.g.session,
                 name=name,
                 namespace=namespace,
+                repospanner_region=repospanner_region,
                 description=description,
                 private=private,
                 url=url,
@@ -770,10 +775,6 @@ def api_new_project():
                 user=flask.g.fas_user.username,
                 blacklist=pagure_config["BLACKLISTED_PROJECTS"],
                 allowed_prefix=pagure_config["ALLOWED_PREFIX"],
-                gitfolder=pagure_config["GIT_FOLDER"],
-                docfolder=pagure_config.get("DOCS_FOLDER"),
-                ticketfolder=pagure_config.get("TICKETS_FOLDER"),
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
                 add_readme=create_readme,
                 userobj=user,
                 prevent_40_chars=pagure_config.get(
@@ -1039,13 +1040,7 @@ def api_fork_project():
 
         try:
             task = pagure.lib.fork_project(
-                flask.g.session,
-                user=flask.g.fas_user.username,
-                repo=repo,
-                gitfolder=pagure_config["GIT_FOLDER"],
-                docfolder=pagure_config.get("DOCS_FOLDER"),
-                ticketfolder=pagure_config.get("TICKETS_FOLDER"),
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
+                flask.g.session, user=flask.g.fas_user.username, repo=repo
             )
             flask.g.session.commit()
             output = {"message": "Project forking queued", "taskid": task.id}

+ 3 - 2
pagure/decorators.py

@@ -47,8 +47,9 @@ def has_trackers(function):
     @wraps(function)
     def check_trackers(*args, **kwargs):
         repo = flask.g.repo
-        if not repo.settings.get("issue_tracker", True) and \
-           not repo.settings.get("pull_requests", True):
+        if not repo.settings.get(
+            "issue_tracker", True
+        ) and not repo.settings.get("pull_requests", True):
             flask.abort(404, "No ticket trackers found for this project")
         return function(*args, **kwargs)
 

+ 27 - 0
pagure/default_config.py

@@ -146,6 +146,11 @@ ATTACHMENTS_FOLDER = os.path.join(
     os.path.abspath(os.path.dirname(__file__)), "..", "lcl", "attachments"
 )
 
+# Folder for repoSpanner pseudo repos
+REPOSPANNER_PSEUDO_FOLDER = os.path.join(
+    os.path.abspath(os.path.dirname(__file__)), "..", "lcl", "pseudo"
+)
+
 # Whether to enable scanning for viruses in attachments
 VIRUS_SCAN_ATTACHMENTS = False
 
@@ -469,3 +474,25 @@ REACTIONS = [
 ]
 # This is used for faster indexing. Do not change.
 _REACTIONS_DICT = dict(REACTIONS)
+
+# repoSpanner integration settings
+# Whether to create new repositories on repoSpanner by default.
+# Either None or a region name.
+REPOSPANNER_NEW_REPO = None
+# Whether to allow admins to override region selection on creation.
+REPOSPANNER_NEW_REPO_ADMIN_OVERRIDE = False
+# Whether to create new forks on repoSpanner.
+# Either None (no repoSpanner), True (same as origin project) or a region name.
+REPOSPANNER_NEW_FORK = True
+# Whether to allow an admin to manually migrate an individual project.
+REPOSPANNER_ADMIN_MIGRATION = False
+# The repoSpanner regions to be used in this Pagure instance.
+# Example entry:
+# 'default': {'url': 'https://nodea.regiona.repospanner.local:8444',
+#             'repo_prefix': 'pagure/',
+#             'ca': '',
+#             'admin_cert': {'cert': '',
+#                            'key': ''},
+#             'push_cert': {'cert': '',
+#                           'key': ''}}
+REPOSPANNER_REGIONS = {}

+ 1 - 1
pagure/docs_server.py

@@ -163,7 +163,7 @@ def view_docs(repo, username=None, namespace=None, filename=None):
     if not repo.settings.get("project_documentation", True):
         flask.abort(404, "This project has documentation disabled")
 
-    reponame = os.path.join(APP.config["DOCS_FOLDER"], repo.path)
+    reponame = repo.repopath("docs")
     if not os.path.exists(reponame):
         flask.abort(404, "Documentation not found")
 

+ 5 - 2
pagure/flask_app.py

@@ -124,7 +124,8 @@ def create_app(config=None):
 
     themename = pagure_config.get("THEME", "default")
     here = os.path.abspath(
-        os.path.join(os.path.dirname(os.path.abspath(__file__))))
+        os.path.join(os.path.dirname(os.path.abspath(__file__)))
+    )
     themeblueprint = flask.Blueprint(
         "theme",
         __name__,
@@ -136,8 +137,10 @@ def create_app(config=None):
     template_folders = os.path.join(
         app.root_path,
         app.template_folder,
-        os.path.join(here, "themes", themename, "templates"))
+        os.path.join(here, "themes", themename, "templates"),
+    )
     import jinja2
+
     # Jinja looks for the template in the order of the folders specified
     templ_loaders = [
         jinja2.FileSystemLoader(template_folders),

+ 19 - 1
pagure/forms.py

@@ -30,7 +30,7 @@ import wtforms
 
 import pagure.lib
 from pagure.config import config as pagure_config
-from pagure.utils import urlpattern
+from pagure.utils import urlpattern, is_admin
 
 
 STRICT_REGEX = "^[a-zA-Z0-9-_]+$"
@@ -167,6 +167,19 @@ class ProjectForm(ProjectFormSimplified):
         choices=[],
         coerce=convert_value,
     )
+    repospanner_region = wtforms.SelectField(
+        "repoSpanner Region",
+        [wtforms.validators.optional()],
+        choices=(
+            [("none", "Disabled")]
+            + [
+                (region, region)
+                for region in pagure_config["REPOSPANNER_REGIONS"].keys()
+            ]
+        ),
+        coerce=convert_value,
+        default=pagure_config["REPOSPANNER_NEW_REPO"],
+    )
 
     def __init__(self, *args, **kwargs):
         """ Calls the default constructor with the normal argument but
@@ -189,6 +202,11 @@ class ProjectForm(ProjectFormSimplified):
             ]
             if not pagure_config.get("USER_NAMESPACE", False):
                 self.namespace.choices.insert(0, ("", ""))
+        if not (
+            is_admin()
+            and pagure_config.get("REPOSPANNER_NEW_REPO_ADMIN_OVERRIDE")
+        ):
+            self.repospanner_region = None
 
 
 class IssueFormSimplied(PagureForm):

+ 5 - 10
pagure/internal/__init__.py

@@ -118,7 +118,6 @@ def pull_request_add_comment():
             row=row,
             comment=comment,
             user=useremail,
-            requestfolder=pagure.config.config["REQUESTS_FOLDER"],
         )
         flask.g.session.commit()
     except SQLAlchemyError as err:  # pragma: no cover
@@ -176,7 +175,6 @@ def ticket_add_comment():
             issue=issue,
             comment=comment,
             user=useremail,
-            ticketfolder=pagure.config.config["TICKETS_FOLDER"],
             notify=True,
         )
         flask.g.session.commit()
@@ -233,7 +231,6 @@ def mergeable_request_pull():
             session=flask.g.session,
             request=request,
             username=None,
-            request_folder=None,
             domerge=False,
         )
     except pygit2.GitError as err:
@@ -428,9 +425,7 @@ def get_ticket_template(repo, namespace=None, username=None):
         response.status_code = 404
         return response
 
-    ticketrepopath = os.path.join(
-        pagure.config.config["TICKETS_FOLDER"], repo.path
-    )
+    ticketrepopath = repo.repopath("tickets")
     content = None
     if os.path.exists(ticketrepopath):
         ticketrepo = pygit2.Repository(ticketrepopath)
@@ -494,7 +489,7 @@ def get_branches_of_commit():
         response.status_code = 404
         return response
 
-    repopath = os.path.join(pagure.config.config["GIT_FOLDER"], repo.path)
+    repopath = repo.repopath("main")
 
     if not os.path.exists(repopath):
         response = flask.jsonify(
@@ -601,7 +596,7 @@ def get_branches_head():
         response.status_code = 404
         return response
 
-    repopath = os.path.join(pagure.config.config["GIT_FOLDER"], repo.path)
+    repopath = repo.repopath("main")
 
     if not os.path.exists(repopath):
         response = flask.jsonify(
@@ -675,7 +670,7 @@ def get_stats_commits():
         response.status_code = 404
         return response
 
-    repopath = os.path.join(pagure.config.config["GIT_FOLDER"], repo.path)
+    repopath = repo.repopath("main")
 
     task = pagure.lib.tasks.commits_author_stats.delay(repopath)
 
@@ -719,7 +714,7 @@ def get_stats_commits_trend():
         response.status_code = 404
         return response
 
-    repopath = os.path.join(pagure.config.config["GIT_FOLDER"], repo.path)
+    repopath = repo.repopath("main")
 
     task = pagure.lib.tasks.commits_history_stats.delay(repopath)
 

+ 91 - 168
pagure/lib/__init__.py

@@ -67,6 +67,7 @@ from pagure.lib import tasks_services
 
 REDIS = None
 PAGURE_CI = None
+REPOTYPES = ("main", "docs", "tickets", "requests")
 _log = logging.getLogger(__name__)
 
 
@@ -374,7 +375,6 @@ def add_issue_comment(
     issue,
     comment,
     user,
-    ticketfolder,
     notify=True,
     date_created=None,
     notification=False,
@@ -395,9 +395,7 @@ def add_issue_comment(
     # Make sure we won't have SQLAlchemy error before we continue
     session.commit()
 
-    pagure.lib.git.update_git(
-        issue, repo=issue.project, repofolder=ticketfolder
-    )
+    pagure.lib.git.update_git(issue, repo=issue.project)
 
     if not notification:
         log_action(session, "commented", issue, user_obj)
@@ -453,7 +451,7 @@ def add_issue_comment(
     return "Comment added"
 
 
-def add_tag_obj(session, obj, tags, user, gitfolder):
+def add_tag_obj(session, obj, tags, user):
     """ Add a tag to an object (either an issue or a project). """
     user_obj = get_user(session, user)
 
@@ -508,7 +506,7 @@ def add_tag_obj(session, obj, tags, user, gitfolder):
         added_tags.append(tagobj.tag)
 
     if isinstance(obj, model.Issue):
-        pagure.lib.git.update_git(obj, repo=obj.project, repofolder=gitfolder)
+        pagure.lib.git.update_git(obj, repo=obj.project)
 
         if not obj.private:
             pagure.lib.notify.log(
@@ -535,7 +533,7 @@ def add_tag_obj(session, obj, tags, user, gitfolder):
                 ),
             )
     elif isinstance(obj, model.PullRequest):
-        pagure.lib.git.update_git(obj, repo=obj.project, repofolder=gitfolder)
+        pagure.lib.git.update_git(obj, repo=obj.project)
 
         if not obj.private:
             pagure.lib.notify.log(
@@ -571,9 +569,7 @@ def add_tag_obj(session, obj, tags, user, gitfolder):
         return "Nothing to add"
 
 
-def add_issue_assignee(
-    session, issue, assignee, user, ticketfolder, notify=True
-):
+def add_issue_assignee(session, issue, assignee, user, notify=True):
     """ Add an assignee to an issue, in other words, assigned an issue. """
     user_obj = get_user(session, user)
 
@@ -584,9 +580,7 @@ def add_issue_assignee(
         issue.last_updated = datetime.datetime.utcnow()
         session.add(issue)
         session.commit()
-        pagure.lib.git.update_git(
-            issue, repo=issue.project, repofolder=ticketfolder
-        )
+        pagure.lib.git.update_git(issue, repo=issue.project)
 
         if notify:
             pagure.lib.notify.notify_assigned_issue(issue, None, user_obj)
@@ -621,9 +615,7 @@ def add_issue_assignee(
         issue.assignee_id = assignee_obj.id
         session.add(issue)
         session.commit()
-        pagure.lib.git.update_git(
-            issue, repo=issue.project, repofolder=ticketfolder
-        )
+        pagure.lib.git.update_git(issue, repo=issue.project)
 
         if notify:
             pagure.lib.notify.notify_assigned_issue(
@@ -656,7 +648,7 @@ def add_issue_assignee(
         return output
 
 
-def add_pull_request_assignee(session, request, assignee, user, requestfolder):
+def add_pull_request_assignee(session, request, assignee, user):
     """ Add an assignee to a request, in other words, assigned an issue. """
     get_user(session, assignee)
     user_obj = get_user(session, user)
@@ -666,9 +658,7 @@ def add_pull_request_assignee(session, request, assignee, user, requestfolder):
         request.last_updated = datetime.datetime.utcnow()
         session.add(request)
         session.commit()
-        pagure.lib.git.update_git(
-            request, repo=request.project, repofolder=requestfolder
-        )
+        pagure.lib.git.update_git(request, repo=request.project)
 
         pagure.lib.notify.notify_assigned_request(request, None, user_obj)
 
@@ -695,9 +685,7 @@ def add_pull_request_assignee(session, request, assignee, user, requestfolder):
         request.last_updated = datetime.datetime.utcnow()
         session.add(request)
         session.flush()
-        pagure.lib.git.update_git(
-            request, repo=request.project, repofolder=requestfolder
-        )
+        pagure.lib.git.update_git(request, repo=request.project)
 
         pagure.lib.notify.notify_assigned_request(
             request, assignee_obj, user_obj
@@ -717,7 +705,7 @@ def add_pull_request_assignee(session, request, assignee, user, requestfolder):
         return "Request assigned"
 
 
-def add_issue_dependency(session, issue, issue_blocked, user, ticketfolder):
+def add_issue_dependency(session, issue, issue_blocked, user):
     """ Add a dependency between two issues. """
     user_obj = get_user(session, user)
 
@@ -733,12 +721,8 @@ def add_issue_dependency(session, issue, issue_blocked, user, ticketfolder):
         session.add(i2i)
         # Make sure we won't have SQLAlchemy error before we continue
         session.flush()
-        pagure.lib.git.update_git(
-            issue, repo=issue.project, repofolder=ticketfolder
-        )
-        pagure.lib.git.update_git(
-            issue_blocked, repo=issue_blocked.project, repofolder=ticketfolder
-        )
+        pagure.lib.git.update_git(issue, repo=issue.project)
+        pagure.lib.git.update_git(issue_blocked, repo=issue_blocked.project)
 
         if not issue.private:
             pagure.lib.notify.log(
@@ -779,7 +763,7 @@ def add_issue_dependency(session, issue, issue_blocked, user, ticketfolder):
         return "Issue marked as depending on: #%s" % issue_blocked.id
 
 
-def remove_issue_dependency(session, issue, issue_blocked, user, ticketfolder):
+def remove_issue_dependency(session, issue, issue_blocked, user):
     """ Remove a dependency between two issues. """
     user_obj = get_user(session, user)
 
@@ -797,12 +781,8 @@ def remove_issue_dependency(session, issue, issue_blocked, user, ticketfolder):
 
         # Make sure we won't have SQLAlchemy error before we continue
         session.flush()
-        pagure.lib.git.update_git(
-            issue, repo=issue.project, repofolder=ticketfolder
-        )
-        pagure.lib.git.update_git(
-            issue_blocked, repo=issue_blocked.project, repofolder=ticketfolder
-        )
+        pagure.lib.git.update_git(issue, repo=issue.project)
+        pagure.lib.git.update_git(issue_blocked, repo=issue_blocked.project)
 
         if not issue.private:
             pagure.lib.notify.log(
@@ -845,7 +825,7 @@ def remove_issue_dependency(session, issue, issue_blocked, user, ticketfolder):
         )
 
 
-def remove_tags(session, project, tags, gitfolder, user):
+def remove_tags(session, project, tags, user):
     """ Removes the specified tag of a project. """
     user_obj = get_user(session, user)
 
@@ -876,9 +856,7 @@ def remove_tags(session, project, tags, gitfolder, user):
             if issue_tag.tag in tags:
                 tag = issue_tag.tag
                 session.delete(issue_tag)
-        pagure.lib.git.update_git(
-            issue, repo=issue.project, repofolder=gitfolder
-        )
+        pagure.lib.git.update_git(issue, repo=issue.project)
 
     pagure.lib.notify.log(
         project,
@@ -894,7 +872,7 @@ def remove_tags(session, project, tags, gitfolder, user):
     return msgs
 
 
-def remove_tags_obj(session, obj, tags, gitfolder, user):
+def remove_tags_obj(session, obj, tags, user):
     """ Removes the specified tag(s) of a given object. """
     user_obj = get_user(session, user)
 
@@ -922,7 +900,7 @@ def remove_tags_obj(session, obj, tags, gitfolder, user):
                 session.delete(objtag)
 
     if isinstance(obj, model.Issue):
-        pagure.lib.git.update_git(obj, repo=obj.project, repofolder=gitfolder)
+        pagure.lib.git.update_git(obj, repo=obj.project)
 
         pagure.lib.notify.log(
             obj.project,
@@ -943,7 +921,7 @@ def remove_tags_obj(session, obj, tags, gitfolder, user):
                 json.dumps({"removed_tags": removed_tags}),
             )
     elif isinstance(obj, model.PullRequest):
-        pagure.lib.git.update_git(obj, repo=obj.project, repofolder=gitfolder)
+        pagure.lib.git.update_git(obj, repo=obj.project)
 
         pagure.lib.notify.log(
             obj.project,
@@ -977,7 +955,6 @@ def edit_issue_tags(
     new_tag,
     new_tag_description,
     new_tag_color,
-    ticketfolder,
     user,
 ):
     """ Removes the specified tag of a project. """
@@ -1041,9 +1018,7 @@ def edit_issue_tags(
     )
     for issue in issues:
         # Update the git version
-        pagure.lib.git.update_git(
-            issue, repo=issue.project, repofolder=ticketfolder
-        )
+        pagure.lib.git.update_git(issue, repo=issue.project)
 
     msgs = []
     msgs.append(
@@ -1321,7 +1296,6 @@ def add_pull_request_comment(
     row,
     comment,
     user,
-    requestfolder,
     notify=True,
     notification=False,
     trigger_ci=None,
@@ -1345,9 +1319,7 @@ def add_pull_request_comment(
 
     request.last_updated = datetime.datetime.utcnow()
 
-    pagure.lib.git.update_git(
-        request, repo=request.project, repofolder=requestfolder
-    )
+    pagure.lib.git.update_git(request, repo=request.project)
 
     log_action(session, "commented", request, user_obj)
 
@@ -1424,7 +1396,7 @@ def add_pull_request_comment(
     return "Comment added"
 
 
-def edit_comment(session, parent, comment, user, updated_comment, folder):
+def edit_comment(session, parent, comment, user, updated_comment):
     """ Edit a comment. """
     user_obj = get_user(session, user)
     comment.comment = updated_comment
@@ -1437,7 +1409,7 @@ def edit_comment(session, parent, comment, user, updated_comment, folder):
     # Make sure we won't have SQLAlchemy error before we continue
     session.flush()
 
-    pagure.lib.git.update_git(parent, repo=parent.project, repofolder=folder)
+    pagure.lib.git.update_git(parent, repo=parent.project)
 
     topic = "unknown"
     key = "unknown"
@@ -1498,17 +1470,7 @@ def edit_comment(session, parent, comment, user, updated_comment, folder):
 
 
 def add_pull_request_flag(
-    session,
-    request,
-    username,
-    percent,
-    comment,
-    url,
-    status,
-    uid,
-    user,
-    token,
-    requestfolder,
+    session, request, username, percent, comment, url, status, uid, user, token
 ):
     """ Add a flag to a pull-request. """
     user_obj = get_user(session, user)
@@ -1542,9 +1504,7 @@ def add_pull_request_flag(
     if request.project.settings.get("notify_on_pull-request_flag"):
         pagure.lib.notify.notify_pull_request_flag(pr_flag, username)
 
-    pagure.lib.git.update_git(
-        request, repo=request.project, repofolder=requestfolder
-    )
+    pagure.lib.git.update_git(request, repo=request.project)
 
     pagure.lib.notify.log(
         request.project,
@@ -1644,10 +1604,7 @@ def new_project(
     name,
     blacklist,
     allowed_prefix,
-    gitfolder,
-    docfolder,
-    ticketfolder,
-    requestfolder,
+    repospanner_region,
     description=None,
     url=None,
     avatar_email=None,
@@ -1705,14 +1662,6 @@ def new_project(
     if namespace:
         path = "%s/%s" % (namespace, name)
 
-    # Repo exists on disk
-    gitrepo = os.path.join(gitfolder, "%s.git" % path)
-    if os.path.exists(gitrepo):
-        if not ignore_existing_repo:
-            raise pagure.exceptions.RepoExistsException(
-                'The project repo "%s" already exists' % path
-            )
-
     # Repo exists in the DB
     repo = _get_project(session, name, namespace=namespace)
     # this is leaking private repos but we're leaking them anyway if we fail
@@ -1722,9 +1671,21 @@ def new_project(
             'It is not possible to create the repo "%s"' % (path)
         )
 
+    if repospanner_region == "none":
+        repospanner_region = None
+    elif repospanner_region is None:
+        repospanner_region = pagure_config["REPOSPANNER_NEW_REPO"]
+
+    if (
+        repospanner_region
+        and repospanner_region not in pagure_config["REPOSPANNER_REGIONS"]
+    ):
+        raise Exception("repoSpanner region %s invalid" % repospanner_region)
+
     project = model.Project(
         name=name,
         namespace=namespace,
+        repospanner_region=repospanner_region,
         description=description if description else None,
         url=url if url else None,
         avatar_email=avatar_email if avatar_email else None,
@@ -1763,7 +1724,6 @@ def new_issue(
     title,
     content,
     user,
-    ticketfolder,
     issue_id=None,
     issue_uid=None,
     private=False,
@@ -1839,7 +1799,7 @@ def new_issue(
 
     session.commit()
 
-    pagure.lib.git.update_git(issue, repo=repo, repofolder=ticketfolder)
+    pagure.lib.git.update_git(issue, repo=repo)
 
     log_action(session, "created", issue, user_obj)
 
@@ -1861,20 +1821,19 @@ def new_issue(
     return issue
 
 
-def drop_issue(session, issue, user, ticketfolder):
+def drop_issue(session, issue, user):
     """ Delete a specified issue. """
     user_obj = get_user(session, user)
 
+    repotype = issue.repotype
+    uid = issue.uid
+
     private = issue.private
     session.delete(issue)
 
     # Make sure we won't have SQLAlchemy error before we create the issue
     session.flush()
 
-    pagure.lib.git.clean_git(
-        issue, repo=issue.project, repofolder=ticketfolder
-    )
-
     if not private:
         pagure.lib.notify.log(
             issue.project,
@@ -1887,6 +1846,10 @@ def drop_issue(session, issue, user, ticketfolder):
             redis=REDIS,
         )
 
+    session.commit()
+
+    pagure.lib.git.clean_git(issue.project, repotype, uid)
+
     return issue
 
 
@@ -1897,7 +1860,6 @@ def new_pull_request(
     branch_to,
     title,
     user,
-    requestfolder,
     initial_comment=None,
     repo_from=None,
     remote_git=None,
@@ -1938,9 +1900,7 @@ def new_pull_request(
     # Make sure we won't have SQLAlchemy error before we create the request
     session.flush()
 
-    pagure.lib.git.update_git(
-        request, repo=request.project, repofolder=requestfolder
-    )
+    pagure.lib.git.update_git(request, repo=request.project)
 
     pagure.lib.tasks.link_pr_to_ticket.delay(request.uid)
 
@@ -2000,7 +1960,6 @@ def new_tag(session, tag_name, tag_description, tag_color, project_id):
 def edit_issue(
     session,
     issue,
-    ticketfolder,
     user,
     repo=None,
     title=None,
@@ -2015,8 +1974,6 @@ def edit_issue(
 
     :arg session: the session to use to connect to the database.
     :arg issue: the pagure.lib.model.Issue object to edit.
-    :arg ticketfolder: the path to the git repo storing the meta-data of
-        the issues of this repo
     :arg user: the username of the user editing the issue,
     :kwarg repo: somehow this isn't used anywhere here...
     :kwarg title: the new title of the issue if it's being changed
@@ -2114,9 +2071,7 @@ def edit_issue(
     # uniquify the list of edited fields
     edit = list(set(edit))
 
-    pagure.lib.git.update_git(
-        issue, repo=issue.project, repofolder=ticketfolder
-    )
+    pagure.lib.git.update_git(issue, repo=issue.project)
 
     if "status" in edit:
         log_action(session, issue.status.lower(), issue, user_obj)
@@ -2251,37 +2206,28 @@ def update_user_settings(session, settings, user):
         return "Successfully edited your settings"
 
 
-def fork_project(
-    session,
-    user,
-    repo,
-    gitfolder,
-    docfolder,
-    ticketfolder,
-    requestfolder,
-    editbranch=None,
-    editfile=None,
-):
+def fork_project(session, user, repo, editbranch=None, editfile=None):
     """ Fork a given project into the user's forks. """
-    forkreponame = "%s.git" % os.path.join(
-        gitfolder,
-        "forks",
-        user,
-        repo.namespace if repo.namespace else "",
-        repo.name,
-    )
-
-    if os.path.exists(forkreponame):
+    if _get_project(session, repo.name, user, repo.namespace) is not None:
         raise pagure.exceptions.RepoExistsException(
             'Repo "forks/%s/%s" already exists' % (user, repo.name)
         )
 
     user_obj = get_user(session, user)
 
+    fork_repospanner_setting = pagure_config["REPOSPANNER_NEW_FORK"]
+    if fork_repospanner_setting is None:
+        repospanner_region = None
+    elif fork_repospanner_setting is True:
+        repospanner_region = repo.repospanner_region
+    else:
+        repospanner_region = fork_repospanner_setting
+
     project = model.Project(
         name=repo.name,
         namespace=repo.namespace,
         description=repo.description,
+        repospanner_region=repospanner_region,
         private=repo.private,
         user_id=user_obj.id,
         parent_id=repo.id,
@@ -2770,7 +2716,10 @@ def _get_project(session, name, user=None, namespace=None):
     else:
         query = query.filter(model.Project.is_fork == False)  # noqa: E712
 
-    return query.first()
+    try:
+        return query.one()
+    except sqlalchemy.orm.exc.NoResultFound:
+        return None
 
 
 def search_issues(
@@ -3241,7 +3190,7 @@ def search_pull_requests(
     return output
 
 
-def reopen_pull_request(session, request, user, requestfolder):
+def reopen_pull_request(session, request, user):
     """ Re-Open the provided pull request
     """
     if request.status != "Closed":
@@ -3254,9 +3203,7 @@ def reopen_pull_request(session, request, user, requestfolder):
     session.flush()
     log_action(session, request.status.lower(), request, user_obj)
     pagure.lib.notify.notify_reopen_pull_request(request, user_obj)
-    pagure.lib.git.update_git(
-        request, repo=request.project, repofolder=requestfolder
-    )
+    pagure.lib.git.update_git(request, repo=request.project)
     pagure.lib.add_pull_request_comment(
         session,
         request,
@@ -3266,7 +3213,6 @@ def reopen_pull_request(session, request, user, requestfolder):
         row=None,
         comment="Pull-Request has been reopened by %s" % (user),
         user=user,
-        requestfolder=requestfolder,
         notify=False,
         notification=True,
     )
@@ -3280,7 +3226,7 @@ def reopen_pull_request(session, request, user, requestfolder):
     )
 
 
-def close_pull_request(session, request, user, requestfolder, merged=True):
+def close_pull_request(session, request, user, merged=True):
     """ Close the provided pull-request.
     """
     user_obj = get_user(session, user)
@@ -3301,9 +3247,7 @@ def close_pull_request(session, request, user, requestfolder, merged=True):
     else:
         pagure.lib.notify.notify_cancelled_pull_request(request, user_obj)
 
-    pagure.lib.git.update_git(
-        request, repo=request.project, repofolder=requestfolder
-    )
+    pagure.lib.git.update_git(request, repo=request.project)
 
     pagure.lib.add_pull_request_comment(
         session,
@@ -3315,7 +3259,6 @@ def close_pull_request(session, request, user, requestfolder, merged=True):
         comment="Pull-Request has been %s by %s"
         % (request.status.lower(), user),
         user=user,
-        requestfolder=requestfolder,
         notify=False,
         notification=True,
     )
@@ -3553,17 +3496,20 @@ def set_up_user(
 
 
 def allowed_emailaddress(email):
-    ''' check if email domains are restricted and if a given email address
-    is allowed. '''
-    allowed_email_domains = pagure_config.get('ALLOWED_EMAIL_DOMAINS', None)
+    """ check if email domains are restricted and if a given email address
+    is allowed. """
+    allowed_email_domains = pagure_config.get("ALLOWED_EMAIL_DOMAINS", None)
     if allowed_email_domains:
         for domain in allowed_email_domains:
             if email.endswith(domain):
                 return
         raise pagure.exceptions.PagureException(
-            'The email address ' + email + ' ' +
-            'is not in the list of allowed email domains:\n' +
-            "\n".join(allowed_email_domains))
+            "The email address "
+            + email
+            + " "
+            + "is not in the list of allowed email domains:\n"
+            + "\n".join(allowed_email_domains)
+        )
 
 
 def add_email_to_user(session, user, user_email):
@@ -3616,7 +3562,7 @@ def avatar_url_from_email(email, size=64, default="retro", dns=False):
         return "https://seccdn.libravatar.org/avatar/%s?%s" % (hashhex, query)
 
 
-def update_tags(session, obj, tags, username, gitfolder):
+def update_tags(session, obj, tags, username):
     """ Update the tags of a specified object (adding or removing them).
     This object can be either an issue or a project.
 
@@ -3628,18 +3574,14 @@ def update_tags(session, obj, tags, username, gitfolder):
     torm = set(obj.tags_text) - set(tags)
     messages = []
     if toadd:
-        add_tag_obj(
-            session, obj=obj, tags=toadd, user=username, gitfolder=gitfolder
-        )
+        add_tag_obj(session, obj=obj, tags=toadd, user=username)
         messages.append(
             "%s tagged with: %s"
             % (obj.isa.capitalize(), ", ".join(sorted(toadd)))
         )
 
     if torm:
-        remove_tags_obj(
-            session, obj=obj, tags=torm, user=username, gitfolder=gitfolder
-        )
+        remove_tags_obj(session, obj=obj, tags=torm, user=username)
         messages.append(
             "%s **un**tagged with: %s"
             % (obj.isa.capitalize(), ", ".join(sorted(torm)))
@@ -3650,9 +3592,7 @@ def update_tags(session, obj, tags, username, gitfolder):
     return messages
 
 
-def update_dependency_issue(
-    session, repo, issue, depends, username, ticketfolder
-):
+def update_dependency_issue(session, repo, issue, depends, username):
     """ Update the dependency of a specified issue (adding or removing them)
 
     """
@@ -3674,11 +3614,7 @@ def update_dependency_issue(
             continue
 
         add_issue_dependency(
-            session,
-            issue=issue_depend,
-            issue_blocked=issue,
-            user=username,
-            ticketfolder=ticketfolder,
+            session, issue=issue_depend, issue_blocked=issue, user=username
         )
 
     # Remove issue depending
@@ -3694,18 +3630,14 @@ def update_dependency_issue(
             continue
 
         remove_issue_dependency(
-            session,
-            issue=issue,
-            issue_blocked=issue_depend,
-            user=username,
-            ticketfolder=ticketfolder,
+            session, issue=issue, issue_blocked=issue_depend, user=username
         )
 
     session.commit()
     return messages
 
 
-def update_blocked_issue(session, repo, issue, blocks, username, ticketfolder):
+def update_blocked_issue(session, repo, issue, blocks, username):
     """ Update the upstream dependency of a specified issue (adding or
     removing them)
 
@@ -3728,11 +3660,7 @@ def update_blocked_issue(session, repo, issue, blocks, username, ticketfolder):
             continue
 
         add_issue_dependency(
-            session,
-            issue=issue,
-            issue_blocked=issue_block,
-            user=username,
-            ticketfolder=ticketfolder,
+            session, issue=issue, issue_blocked=issue_block, user=username
         )
         session.commit()
 
@@ -3750,11 +3678,7 @@ def update_blocked_issue(session, repo, issue, blocks, username, ticketfolder):
             continue
 
         remove_issue_dependency(
-            session,
-            issue=issue_block,
-            issue_blocked=issue,
-            user=username,
-            ticketfolder=ticketfolder,
+            session, issue=issue_block, issue_blocked=issue, user=username
         )
 
     session.commit()
@@ -5067,7 +4991,7 @@ def get_active_milestones(session, project):
     return sorted([item[0] for item in query.distinct()])
 
 
-def add_metadata_update_notif(session, obj, messages, user, gitfolder):
+def add_metadata_update_notif(session, obj, messages, user):
     """ Add a notification to the specified issue with the given messages
     which should reflect changes made to the meta-data of the issue.
     """
@@ -5125,8 +5049,7 @@ def add_metadata_update_notif(session, obj, messages, user, gitfolder):
             ),
         )
 
-    if gitfolder:
-        pagure.lib.git.update_git(obj, repo=obj.project, repofolder=gitfolder)
+    pagure.lib.git.update_git(obj, repo=obj.project)
 
 
 def tokenize_search_string(pattern):

File diff suppressed because it is too large
+ 549 - 507
pagure/lib/git.py


+ 9 - 1
pagure/lib/git_auth.py

@@ -44,7 +44,15 @@ def get_git_auth_helper(backend, *args, **kwargs):
     points = pkg_resources.iter_entry_points("pagure.git_auth.helpers")
     classes = dict([(point.name, point) for point in points])
     _log.debug("Found the following installed helpers %r" % classes)
-    cls = classes[backend].load()
+    if len(classes) == 0:
+        _log.debug("Was unable to find any helpers, registering built-in")
+        cls = {
+            "test_auth": GitAuthTestHelper,
+            "gitolite2": Gitolite2Auth,
+            "gitolite3": Gitolite3Auth,
+        }[backend]
+    else:
+        cls = classes[backend].load()
     _log.debug("Instantiating helper %r from backend key %r" % (cls, backend))
     return cls(*args, **kwargs)
 

+ 2 - 9
pagure/lib/lib_ci.py

@@ -33,9 +33,7 @@ BUILD_STATS = {
 }
 
 
-def process_jenkins_build(
-    session, project, build_id, requestfolder, iteration=0
-):
+def process_jenkins_build(session, project, build_id, iteration=0):
     """  Gets the build info from jenkins and flags that particular
     pull-request.
     """
@@ -61,11 +59,7 @@ def process_jenkins_build(
             _log.info("Build is still going, let's wait a sec and try again")
             time.sleep(1)
             return process_jenkins_build(
-                session,
-                project,
-                build_id,
-                requestfolder,
-                iteration=iteration + 1,
+                session, project, build_id, iteration=iteration + 1
             )
         _log.info(
             "We've been waiting for 5 seconds and the build is still "
@@ -130,7 +124,6 @@ def process_jenkins_build(
         uid=uid,
         user=project.user.username,
         token=None,
-        requestfolder=requestfolder,
     )
     session.commit()
 

+ 106 - 0
pagure/lib/model.py

@@ -20,6 +20,8 @@ import logging
 import json
 import operator
 import re
+import pygit2
+import os
 
 import six
 import sqlalchemy as sa
@@ -33,6 +35,7 @@ from sqlalchemy.orm import scoped_session
 from sqlalchemy.orm import relation
 
 import pagure.exceptions
+from pagure.config import config as pagure_config
 from pagure.utils import is_true
 
 
@@ -410,6 +413,7 @@ class Project(BASE):
         backref="projects",
     )
     private = sa.Column(sa.Boolean, nullable=False, default=False)
+    repospanner_region = sa.Column(sa.Text, nullable=True)
 
     users = relation(
         "User",
@@ -490,11 +494,103 @@ class Project(BASE):
         """
         return "%s-project-%s" % (self.fullname, self.id)
 
+    @property
+    def is_on_repospanner(self):
+        """ Returns whether this repo is on repoSpanner. """
+        return self.repospanner_region is not None
+
     @property
     def path(self):
         """ Return the name of the git repo on the filesystem. """
         return "%s.git" % self.fullname
 
+    def repospanner_repo_info(self, repotype, region=None):
+        """ Returns info for getting a repoSpanner repo for a project.
+
+        Args:
+            repotype (string): Type of repository
+            region (string): If repo is not on repoSpanner, return url as if
+                it was in this region. Used for migrating to repoSpanner.
+        Return type: (url, dict): First is the clone url, then a dict with
+            the regioninfo.
+        """
+        if not self.is_on_repospanner and region is None:
+            raise ValueError("Repo %s is not on repoSpanner" % self.fullname)
+        if self.is_on_repospanner and region is not None:
+            raise ValueError(
+                "Repo %s is already on repoSpanner" % self.fullname
+            )
+        if region is None:
+            region = self.repospanner_region
+        regioninfo = pagure_config["REPOSPANNER_REGIONS"].get(region)
+        if not regioninfo:
+            raise ValueError(
+                "Invalid repoSpanner region %s looked up" % region
+            )
+
+        url = "%s/repo/%s.git" % (
+            regioninfo["url"],
+            self._repospanner_repo_name(repotype, region),
+        )
+        return url, regioninfo
+
+    def _repospanner_repo_name(self, repotype, region):
+        """ Returns the name of a repo as named in repoSpanner.
+
+        Args:
+            repotype (string): Type of repository
+            region (string): repoSpanner region name
+        Return type: (string)
+        """
+        return os.path.join(
+            pagure_config["REPOSPANNER_REGIONS"][region].get(
+                "repo_prefix", ""
+            ),
+            repotype,
+            self.fullname,
+        )
+
+    def repopath(self, repotype):
+        """ Return the full repository path of the git repo on the filesystem.
+
+        If the repository is on repoSpanner, this will be a pseudo repository,
+        which is "git repo enough" to be considered a valid repo, but any
+        access should go through a repoSpanner enlightened libgit2.
+        """
+        if self.is_on_repospanner:
+            pseudopath = os.path.join(
+                pagure_config["REPOSPANNER_PSEUDO_FOLDER"], repotype, self.path
+            )
+            if not os.path.exists(pseudopath):
+                repourl, regioninfo = self.repospanner_repo_info(repotype)
+                fake = pygit2.init_repository(pseudopath, bare=True)
+                fake.config["repospanner.url"] = repourl
+                fake.config["repospanner.cert"] = regioninfo["push_cert"][
+                    "cert"
+                ]
+                fake.config["repospanner.key"] = regioninfo["push_cert"]["key"]
+                fake.config["repospanner.cacert"] = regioninfo["ca"]
+                fake.config["repospanner.enabled"] = True
+                del fake
+            return pseudopath
+
+        maindir = None
+        if repotype == "main":
+            maindir = pagure_config["GIT_FOLDER"]
+        elif repotype == "docs":
+            maindir = pagure_config["DOCS_FOLDER"]
+        elif repotype == "tickets":
+            maindir = pagure_config["TICKETS_FOLDER"]
+        elif repotype == "requests":
+            maindir = pagure_config["REQUESTS_FOLDER"]
+        else:
+            return ValueError("Repotype %s is invalid" % repotype)
+        if maindir is None:
+            if repotype == "main":
+                raise Exception("No maindir for main repos?")
+            return None
+        return os.path.join(maindir, self.path)
+
     @property
     def fullname(self):
         """ Return the name of the git repo as user/project if it is a
@@ -1231,6 +1327,11 @@ class Issue(BASE):
         """ A string to allow finding out that this is an issue. """
         return "issue"
 
+    @property
+    def repotype(self):
+        """ A string returning the repotype for repopath() calls. """
+        return "tickets"
+
     @property
     def mail_id(self):
         """ Return a unique reprensetation of the issue as string that
@@ -1868,6 +1969,11 @@ class PullRequest(BASE):
         """ A string to allow finding out that this is an pull-request. """
         return "pull-request"
 
+    @property
+    def repotype(self):
+        """ A string returning the repotype for repopath() calls. """
+        return "requests"
+
     @property
     def mail_id(self):
         """ Return a unique reprensetation of the issue as string that

+ 158 - 205
pagure/lib/tasks.py

@@ -17,7 +17,7 @@ import hashlib
 import os
 import os.path
 import shutil
-import tempfile
+import subprocess
 import time
 
 from functools import wraps
@@ -230,28 +230,7 @@ def delete_project(
     helper.remove_acls(session=session, project=project)
 
     # Remove the git repositories on disk
-    paths = []
-    for key in [
-        "GIT_FOLDER",
-        "DOCS_FOLDER",
-        "TICKETS_FOLDER",
-        "REQUESTS_FOLDER",
-    ]:
-        if pagure_config.get(key):
-            path = os.path.join(pagure_config[key], project.path)
-            if os.path.exists(path):
-                paths.append(path)
-
-    try:
-        for path in paths:
-            _log.info("Deleting: %s" % path)
-            shutil.rmtree(path)
-    except (OSError, IOError) as err:
-        _log.exception(err)
-        raise RuntimeError("Could not delete all the repos from the system")
-
-    for path in paths:
-        _log.info("Path: %s - exists: %s" % (path, os.path.exists(path)))
+    pagure.lib.git.delete_project_repos(project)
 
     # Remove the project from the DB
     username = project.user.user
@@ -300,10 +279,8 @@ def create_project(
 
     with project.lock("WORKER"):
         userobj = pagure.lib.search_user(session, username=username)
-        gitrepo = os.path.join(pagure_config["GIT_FOLDER"], project.path)
 
         # Add the readme file if it was asked
-        _log.debug("Create git repo at: %s", gitrepo)
         templ = None
         if project.is_fork:
             templ = pagure_config.get("FORK_TEMPLATE_PATH")
@@ -319,106 +296,36 @@ def create_project(
             else:
                 _log.debug("  Using template at: %s", templ)
 
-        pygit2.init_repository(gitrepo, bare=True, template_path=templ)
-        if add_readme:
-            # Clone main project
-            temp_gitrepo_path = tempfile.mkdtemp(prefix="pagure-")
-            temp_gitrepo = pygit2.clone_repository(
-                gitrepo, temp_gitrepo_path, bare=False
-            )
-
-            # Add README file
-            author = userobj.fullname or userobj.user
-            author_email = userobj.default_email
-            if six.PY2:
-                author = author.encode("utf-8")
-                author_email = author_email.encode("utf-8")
-            author = pygit2.Signature(author, author_email)
-            content = "# %s\n\n%s" % (name, project.description)
-            readme_file = os.path.join(temp_gitrepo.workdir, "README.md")
-            with open(readme_file, "wb") as stream:
-                stream.write(content.encode("utf-8"))
-            temp_gitrepo.index.add_all()
-            temp_gitrepo.index.write()
-            tree = temp_gitrepo.index.write_tree()
-            temp_gitrepo.create_commit(
-                "HEAD", author, author, "Added the README", tree, []
-            )
-
-            # Push the README back to the main project
-            ori_remote = temp_gitrepo.remotes[0]
-            master_ref = temp_gitrepo.lookup_reference("HEAD").resolve()
-            refname = "%s:%s" % (master_ref.name, master_ref.name)
-
-            _log.info("Pushing to %s: %s", ori_remote.name, refname)
-            pagure.lib.repo.PagureRepo.push(ori_remote, refname)
-
-            shutil.rmtree(temp_gitrepo_path)
-
-        if not project.private:
-            # Make the repo exportable via apache
-            http_clone_file = os.path.join(gitrepo, "git-daemon-export-ok")
-            if not os.path.exists(http_clone_file):
-                with open(http_clone_file, "w") as stream:
-                    pass
-
-        docrepo = None
-        if pagure_config.get("DOCS_FOLDER"):
-            docrepo = os.path.join(pagure_config["DOCS_FOLDER"], project.path)
-            if os.path.exists(docrepo):
-                if not ignore_existing_repo:
-                    shutil.rmtree(gitrepo)
-                    session.remove()
-                    raise pagure.exceptions.RepoExistsException(
-                        'The docs repo "%s" already exists' % project.path
-                    )
-            else:
-                _log.debug("Create git repo at: %s", docrepo)
-                pygit2.init_repository(docrepo, bare=True)
+        pagure.lib.git.create_project_repos(
+            project, project.repospanner_region, templ, ignore_existing_repo
+        )
 
-        ticketrepo = None
-        if pagure_config.get("TICKETS_FOLDER"):
-            ticketrepo = os.path.join(
-                pagure_config["TICKETS_FOLDER"], project.path
-            )
-            if os.path.exists(ticketrepo):
-                if not ignore_existing_repo:
-                    shutil.rmtree(gitrepo)
-                    if docrepo:
-                        shutil.rmtree(docrepo)
-                    session.remove()
-                    raise pagure.exceptions.RepoExistsException(
-                        'The tickets repo "%s" already exists' % project.path
-                    )
-            else:
-                _log.debug("Create git repo at: %s", ticketrepo)
-                pygit2.init_repository(
-                    ticketrepo,
-                    bare=True,
-                    mode=pygit2.C.GIT_REPOSITORY_INIT_SHARED_GROUP,
+        if add_readme:
+            with pagure.lib.git.TemporaryClone(
+                project, "main", "add_readme"
+            ) as tempclone:
+                temp_gitrepo = tempclone.repo
+
+                # Add README file
+                author = userobj.fullname or userobj.user
+                author_email = userobj.default_email
+                if six.PY2:
+                    author = author.encode("utf-8")
+                    author_email = author_email.encode("utf-8")
+                author = pygit2.Signature(author, author_email)
+                content = "# %s\n\n%s" % (name, project.description)
+                readme_file = os.path.join(temp_gitrepo.workdir, "README.md")
+                with open(readme_file, "wb") as stream:
+                    stream.write(content.encode("utf-8"))
+                temp_gitrepo.index.add_all()
+                temp_gitrepo.index.write()
+                tree = temp_gitrepo.index.write_tree()
+                temp_gitrepo.create_commit(
+                    "HEAD", author, author, "Added the README", tree, []
                 )
 
-        requestrepo = os.path.join(
-            pagure_config["REQUESTS_FOLDER"], project.path
-        )
-        if os.path.exists(requestrepo):
-            if not ignore_existing_repo:
-                shutil.rmtree(gitrepo)
-                if docrepo:
-                    shutil.rmtree(docrepo)
-                if ticketrepo:
-                    shutil.rmtree(ticketrepo)
-                session.remove()
-                raise pagure.exceptions.RepoExistsException(
-                    'The requests repo "%s" already exists' % project.path
-                )
-        else:
-            _log.debug("Create git repo at: %s", requestrepo)
-            pygit2.init_repository(
-                requestrepo,
-                bare=True,
-                mode=pygit2.C.GIT_REPOSITORY_INIT_SHARED_GROUP,
-            )
+                master_ref = temp_gitrepo.lookup_reference("HEAD").resolve()
+                tempclone.push(master_ref.name)
 
         # Install the default hook
         plugin = pagure.lib.plugins.get_plugin("default")
@@ -462,24 +369,22 @@ def update_git(
     with project.lock(project_lock):
         if ticketuid is not None:
             obj = pagure.lib.get_issue_by_uid(session, ticketuid)
-            folder = pagure_config["TICKETS_FOLDER"]
         elif requestuid is not None:
             obj = pagure.lib.get_request_by_uid(session, requestuid)
-            folder = pagure_config["REQUESTS_FOLDER"]
         else:
             raise NotImplementedError("No ticket ID or request ID provided")
 
         if obj is None:
             raise Exception("Unable to find object")
 
-        result = pagure.lib.git._update_git(obj, project, folder)
+        result = pagure.lib.git._update_git(obj, project)
 
     return result
 
 
 @conn.task(queue=pagure_config.get("SLOW_CELERY_QUEUE", None), bind=True)
 @pagure_task
-def clean_git(self, session, name, namespace, user, ticketuid):
+def clean_git(self, session, name, namespace, user, obj_repotype, obj_uid):
     """ Remove the JSON representation of a ticket on the git repository
     for tickets.
     """
@@ -488,13 +393,7 @@ def clean_git(self, session, name, namespace, user, ticketuid):
     )
 
     with project.lock("WORKER_TICKET"):
-        obj = pagure.lib.get_issue_by_uid(session, ticketuid)
-        folder = pagure_config["TICKETS_FOLDER"]
-
-        if obj is None:
-            raise Exception("Unable to find object")
-
-        result = pagure.lib.git._clean_git(obj, project, folder)
+        result = pagure.lib.git._clean_git(project, obj_repotype, obj_uid)
 
     return result
 
@@ -607,68 +506,37 @@ def fork(
     )
 
     with repo_to.lock("WORKER"):
-        reponame = os.path.join(pagure_config["GIT_FOLDER"], repo_from.path)
-        forkreponame = os.path.join(pagure_config["GIT_FOLDER"], repo_to.path)
-
-        frepo = pygit2.clone_repository(reponame, forkreponame, bare=True)
-        # Clone all the branches as well
-        for branch in frepo.listall_branches(pygit2.GIT_BRANCH_REMOTE):
-            branch_obj = frepo.lookup_branch(branch, pygit2.GIT_BRANCH_REMOTE)
-            branchname = branch_obj.branch_name.replace(
-                branch_obj.remote_name, "", 1
-            )[1:]
-            if branchname in frepo.listall_branches(pygit2.GIT_BRANCH_LOCAL):
-                continue
-            frepo.create_branch(branchname, frepo.get(branch_obj.target.hex))
-
-        # Create the git-daemon-export-ok file on the clone
-        http_clone_file = os.path.join(forkreponame, "git-daemon-export-ok")
-        if not os.path.exists(http_clone_file):
-            with open(http_clone_file, "w"):
-                pass
-
-        # Only fork the doc folder if the pagure instance supports the doc
-        # service/server.
-        if pagure_config.get("DOCS_FOLDER"):
-            docrepo = os.path.join(pagure_config["DOCS_FOLDER"], repo_to.path)
-            if os.path.exists(docrepo):
-                shutil.rmtree(forkreponame)
-                raise pagure.exceptions.RepoExistsException(
-                    'The docs "%s" already exists' % repo_to.path
-                )
-            pygit2.init_repository(docrepo, bare=True)
+        pagure.lib.git.create_project_repos(
+            repo_to, repo_to.repospanner_region, None, False
+        )
 
-        if pagure_config.get("TICKETS_FOLDER"):
-            ticketrepo = os.path.join(
-                pagure_config["TICKETS_FOLDER"], repo_to.path
-            )
-            if os.path.exists(ticketrepo):
-                shutil.rmtree(forkreponame)
-                shutil.rmtree(docrepo)
-                raise pagure.exceptions.RepoExistsException(
-                    'The tickets repo "%s" already exists' % repo_to.path
+        with pagure.lib.git.TemporaryClone(
+            repo_to, "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(
+                    "remotes/%s" % branchname, "refs/heads/%s" % localname
                 )
-            pygit2.init_repository(
-                ticketrepo,
-                bare=True,
-                mode=pygit2.C.GIT_REPOSITORY_INIT_SHARED_GROUP,
-            )
 
-        requestrepo = os.path.join(
-            pagure_config["REQUESTS_FOLDER"], repo_to.path
-        )
-        if os.path.exists(requestrepo):
-            shutil.rmtree(forkreponame)
-            shutil.rmtree(docrepo)
-            shutil.rmtree(ticketrepo)
-            raise pagure.exceptions.RepoExistsException(
-                'The requests repo "%s" already exists' % repo_to.path
+        if not repo_to.is_on_repospanner and not repo_to.private:
+            # Create the git-daemon-export-ok file on the clone
+            http_clone_file = os.path.join(
+                repo_to.repopath("main"), "git-daemon-export-ok"
             )
-        pygit2.init_repository(
-            requestrepo,
-            bare=True,
-            mode=pygit2.C.GIT_REPOSITORY_INIT_SHARED_GROUP,
-        )
+            if not os.path.exists(http_clone_file):
+                with open(http_clone_file, "w"):
+                    pass
 
         pagure.lib.notify.log(
             repo_to,
@@ -676,8 +544,6 @@ def fork(
             msg=dict(project=repo_to.to_json(public=True), agent=user_forker),
         )
 
-    del frepo
-
     _log.info("Project created, refreshing auth async")
     task = generate_gitolite_acls.delay(
         namespace=repo_to.namespace,
@@ -759,6 +625,98 @@ def refresh_remote_pr(self, session, name, namespace, user, requestid):
     )
 
 
+@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
+@pagure_task
+def move_to_repospanner(self, session, name, namespace, user, region):
+    """ Move a repository to a repoSpanner region.
+    """
+    project = pagure.lib._get_project(
+        session, namespace=namespace, name=name, user=user
+    )
+    regioninfo = pagure_config.get("REPOSPANNER_REGIONS", {}).get(region)
+    if not regioninfo:
+        raise Exception("Missing region config")
+
+    with project.lock("WORKER"):
+        # Perform some pre-flight checks
+        if project.is_on_repospanner:
+            raise Exception("Project is already on repoSpanner")
+
+        #  Make sure that no non-runner hooks are enabled for this project
+        compatible_targets = [pagure.lib.HOOK_DNE_TARGET]
+        incompatible_hooks = []
+        for repotype in pagure.lib.REPOTYPES:
+            path = project.repopath(repotype)
+            hookpath = os.path.join(path, "hooks")
+            for hook in os.listdir(hookpath):
+                if not hook.startswith(
+                    ("pre-receive.", "update.", "post-receive.")
+                ):
+                    continue
+                hookfile = os.path.join(hookpath, hook)
+                if os.path.realpath(hookfile) not in compatible_targets:
+                    incompatible_hooks.append((repotype, hook))
+
+        if incompatible_hooks:
+            raise Exception(
+                "Repository contains repoSpanner-incompatible "
+                "hooks: %s" % ", ".join(incompatible_hooks)
+            )
+
+        # Create the repositories
+        pagure.lib.git.create_project_repos(project, region, None, False)
+
+        for repotype in pagure.lib.REPOTYPES:
+            repourl, _ = project.repospanner_repo_info(repotype, region)
+            repopath = project.repopath(repotype)
+            repo_obj = pagure.lib.repo.PagureRepo(repopath)
+            repo_obj.create_remote("repospanner_push", repourl)
+
+            command = [
+                "git",
+                "-c",
+                "http.sslcainfo=%s" % regioninfo["ca"],
+                "-c",
+                "http.sslcert=%s" % regioninfo["push_cert"]["cert"],
+                "-c",
+                "http.sslkey=%s" % regioninfo["push_cert"]["key"],
+                "push",
+                "--mirror",
+                "repospanner_push",
+            ]
+            _log.debug("Running push command: %s", command)
+            out = subprocess.check_output(
+                command, cwd=repopath, stderr=subprocess.STDOUT
+            )
+            _log.debug("Out: %s" % out)
+
+        for repotype in pagure.lib.REPOTYPES:
+            repopath = project.repopath(repotype)
+            repo_obj = pagure.lib.repo.PagureRepo(repopath)
+
+            # At this moment, this subrepo has been migrated
+            # Move the "refs" folder to "refsold", so that we don't actually
+            # delete any data, but it's no longer a valid git repo.
+            # On next use, a pseudo repository will be created.
+            refsdir = os.path.join(repopath, "refs")
+            shutil.move(refsdir, refsdir + "old")
+            with open(
+                os.path.join(repopath, "repospanner_status"), "w"
+            ) as info:
+                info.write(
+                    "This repository has migrated to repoSpanner region %s"
+                    % region
+                )
+
+        project.repospanner_region = region
+        session.add(project)
+        session.commit()
+
+    return ret(
+        "ui_ns.view_repo", username=user, namespace=namespace, repo=name
+    )
+
+
 @conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
 @pagure_task
 def refresh_pr_cache(self, session, name, namespace, user):
@@ -798,9 +756,7 @@ def merge_pull_request(
             request.project.fullname,
             request.id,
         )
-        pagure.lib.git.merge_pull_request(
-            session, request, user_merger, pagure_config["REQUESTS_FOLDER"]
-        )
+        pagure.lib.git.merge_pull_request(session, request, user_merger)
 
     if delete_branch_after:
         _log.debug(
@@ -842,12 +798,14 @@ def add_file_to_git(
         user_attacher = pagure.lib.search_user(session, username=user_attacher)
 
         from_folder = pagure_config["ATTACHMENTS_FOLDER"]
-        to_folder = pagure_config["TICKETS_FOLDER"]
         _log.info(
-            "Adding file %s from %s to %s", filename, from_folder, to_folder
+            "Adding file %s from %s to %s",
+            filename,
+            from_folder,
+            project.fullname,
         )
         pagure.lib.git._add_file_to_git(
-            project, issue, from_folder, to_folder, user_attacher, filename
+            project, issue, from_folder, user_attacher, filename
         )
 
 
@@ -1058,12 +1016,7 @@ def link_pr_to_ticket(self, session, pr_uid):
     orig_repo = pygit2.Repository(parentpath)
 
     diff_commits = pagure.lib.git.diff_pull_request(
-        session,
-        request,
-        repo_obj,
-        orig_repo,
-        requestfolder=pagure_config["REQUESTS_FOLDER"],
-        with_diff=False,
+        session, request, repo_obj, orig_repo, with_diff=False
     )
 
     _log.info(

+ 1 - 3
pagure/lib/tasks_services.py

@@ -100,9 +100,7 @@ def call_web_hooks(project, topic, msg, urls):
         url = url.strip()
         _log.info("Calling url %s" % url)
         try:
-            req = requests.post(
-                url, headers=headers, data=content, timeout=60
-            )
+            req = requests.post(url, headers=headers, data=content, timeout=60)
             if not req:
                 _log.info(
                     "An error occured while querying: %s - "

+ 3 - 0
pagure/templates/new_project.html

@@ -24,6 +24,9 @@
               {{ render_bootstrap_field(form.private, field_description="To mark the repo private") }}
             {% endif %}
             {{ render_bootstrap_field(form.create_readme, field_description="Create a README file automatically") }}
+            {% if form.repospanner_region %}
+              {{ render_bootstrap_field(form.repospanner_region, field_description="repoSpanner region to create the project in") }}
+            {% endif %}
             <input class="btn btn-primary" type="submit" value="Create" title="Update description">
             <input type="button" class="btn btn-default float-right"
               value="Cancel" onclick="history.back();">

+ 7 - 0
pagure/templates/settings.html

@@ -82,6 +82,9 @@
             href="#giveproject" role="tab" aria-controls="giveproject">Give Project</a>
           {% endif %}
 
+          <a class="nav-item nav-link" id="repospanner-tab" data-toggle="tab"
+            href="#repospanner" role="tab" aria-controls="repospanner">repoSpanner state</a>
+
           {% if (not repo.is_fork and config.get('ENABLE_DEL_PROJECTS', True))
             or
             (repo.is_fork and config.get('ENABLE_DEL_FORKS',
@@ -1156,6 +1159,10 @@
           </div>
           {% endif %}
 
+          <div class="tab-pane fade" id="repospanner" role="tabpanel" aria-labelledby="repospanner-tab">
+              {% include 'settings_repospanner.html' %}
+          </div>
+
 
     {% if (not repo.is_fork and config.get('ENABLE_DEL_PROJECTS', True))
     or

+ 37 - 0
pagure/templates/settings_repospanner.html

@@ -0,0 +1,37 @@
+<h3 class="font-weight-bold mb-3">
+  repoSpanner status
+</h3>
+<div class="row">
+  <div class="col">
+    {% if repo.is_on_repospanner %}
+      This repository is on repoSpanner region {{ repo.repospanner_region }}
+    {% else %}
+      This repository is NOT yet on repoSpanner
+      {% if pagure_admin and config.get('REPOSPANNER_ADMIN_MIGRATION') %}
+  </div>
+</div>
+<div class="row">
+  <div class="col">
+    <form action="{{ url_for(
+        'ui_ns.move_to_repospanner',
+        repo=repo.name,
+        username=username,
+        namespace=repo.namespace) }}"
+      method="post" class="icon">
+      {{ tag_form.csrf_token }}
+      Select region to move to:
+      <select class="form-control" name="region" id="region"
+              style="margin-bottom:1%" >
+        {% for region in config.get('REPOSPANNER_REGIONS') %}
+          <option value="{{region}}">{{ region }}</option>
+        {% endfor %}
+      </select>
+      <button class="btn" type="submit"
+              title="Move to repoSpanner">
+        <i class="fa fa-share-square-o"></i>&nbsp; Move the {{repo.name}} project to repoSpanner
+      </button>
+    </form>
+      {% endif %}
+    {% endif %}
+  </div>
+</div>

+ 5 - 4
pagure/ui/app.py

@@ -1019,6 +1019,10 @@ def new_project():
         namespace = form.namespace.data
         if namespace:
             namespace = namespace.strip()
+        if form.repospanner_region:
+            repospanner_region = form.repospanner_region.data
+        else:
+            repospanner_region = None
 
         try:
             task = pagure.lib.new_project(
@@ -1027,15 +1031,12 @@ def new_project():
                 private=private,
                 description=description,
                 namespace=namespace,
+                repospanner_region=repospanner_region,
                 url=url,
                 avatar_email=avatar_email,
                 user=flask.g.fas_user.username,
                 blacklist=pagure_config["BLACKLISTED_PROJECTS"],
                 allowed_prefix=pagure_config["ALLOWED_PREFIX"],
-                gitfolder=pagure_config["GIT_FOLDER"],
-                docfolder=pagure_config.get("DOCS_FOLDER"),
-                ticketfolder=pagure_config.get("TICKETS_FOLDER"),
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
                 add_readme=create_readme,
                 userobj=user,
                 prevent_40_chars=pagure_config.get(

+ 8 - 48
pagure/ui/fork.py

@@ -51,13 +51,9 @@ def _get_parent_request_repo_path(repo):
     provided Repository object from the DB.
     """
     if repo.parent:
-        parentpath = os.path.join(
-            pagure_config["REQUESTS_FOLDER"], repo.parent.path
-        )
+        return repo.parent.repopath("requests")
     else:
-        parentpath = os.path.join(pagure_config["REQUESTS_FOLDER"], repo.path)
-
-    return parentpath
+        return repo.repopath("requests")
 
 
 @UI_NS.route("/<repo>/pull-requests/")
@@ -297,11 +293,7 @@ def request_pull(repo, requestid, username=None, namespace=None):
     else:
         try:
             diff_commits, diff = pagure.lib.git.diff_pull_request(
-                flask.g.session,
-                request,
-                repo_obj,
-                orig_repo,
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
+                flask.g.session, request, repo_obj, orig_repo
             )
         except pagure.exceptions.PagureException as err:
             flask.flash("%s" % err, "error")
@@ -435,12 +427,7 @@ def request_pull_to_diff_or_patch(
     else:
         try:
             diff_commits = pagure.lib.git.diff_pull_request(
-                flask.g.session,
-                request,
-                repo_obj,
-                orig_repo,
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
-                with_diff=False,
+                flask.g.session, request, repo_obj, orig_repo, with_diff=False
             )
         except pagure.exceptions.PagureException as err:
             flask.flash("%s" % err, "error")
@@ -641,7 +628,6 @@ def pull_request_add_comment(
                 row=row,
                 comment=comment,
                 user=flask.g.fas_user.username,
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
                 trigger_ci=pagure_config["TRIGGER_CI"],
             )
             flask.g.session.commit()
@@ -835,7 +821,6 @@ def pull_request_edit_comment(
                 comment=comment,
                 user=flask.g.fas_user.username,
                 updated_comment=updated_comment,
-                folder=pagure_config["REQUESTS_FOLDER"],
             )
             flask.g.session.commit()
             if not is_js:
@@ -917,10 +902,7 @@ def reopen_request_pull(repo, requestid, username=None, namespace=None):
 
         try:
             pagure.lib.reopen_pull_request(
-                flask.g.session,
-                request,
-                flask.g.fas_user.username,
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
+                flask.g.session, request, flask.g.fas_user.username
             )
         except pagure.exceptions.PagureException as err:
             flask.flash(str(err), "error")
@@ -1181,11 +1163,7 @@ def cancel_request_pull(repo, requestid, username=None, namespace=None):
             )
 
         pagure.lib.close_pull_request(
-            flask.g.session,
-            request,
-            flask.g.fas_user.username,
-            requestfolder=pagure_config["REQUESTS_FOLDER"],
-            merged=False,
+            flask.g.session, request, flask.g.fas_user.username, merged=False
         )
         try:
             flask.g.session.commit()
@@ -1328,7 +1306,6 @@ def update_pull_requests(repo, requestid, username=None, namespace=None):
                 obj=request,
                 tags=tags,
                 username=flask.g.fas_user.username,
-                gitfolder=pagure_config["TICKETS_FOLDER"],
             )
             messages = messages.union(set(msgs))
 
@@ -1340,7 +1317,6 @@ def update_pull_requests(repo, requestid, username=None, namespace=None):
                     assignee=flask.request.form.get("user", "").strip()
                     or None,
                     user=flask.g.fas_user.username,
-                    requestfolder=pagure_config["REQUESTS_FOLDER"],
                 )
                 if msg:
                     messages.add(msg)
@@ -1353,7 +1329,6 @@ def update_pull_requests(repo, requestid, username=None, namespace=None):
                     obj=request,
                     messages=messages - not_needed,
                     user=flask.g.fas_user.username,
-                    gitfolder=pagure_config["REQUESTS_FOLDER"],
                 )
                 messages.add("Metadata fields updated")
 
@@ -1414,13 +1389,7 @@ def fork_project(repo, username=None, namespace=None):
 
     try:
         task = pagure.lib.fork_project(
-            session=flask.g.session,
-            repo=repo,
-            gitfolder=pagure_config["GIT_FOLDER"],
-            docfolder=pagure_config.get("DOCS_FOLDER"),
-            ticketfolder=pagure_config.get("TICKETS_FOLDER"),
-            requestfolder=pagure_config["REQUESTS_FOLDER"],
-            user=flask.g.fas_user.username,
+            session=flask.g.session, repo=repo, user=flask.g.fas_user.username
         )
 
         flask.g.session.commit()
@@ -1532,9 +1501,7 @@ def new_request_pull(
                     "%s is not part of %s's family"
                     % (project_to, repo.url_path),
                 )
-            orig_repo = pygit2.Repository(
-                os.path.join(pagure_config["GIT_FOLDER"], parent.path)
-            )
+            orig_repo = pygit2.Repository(parent.repopath("main"))
         else:
             flask.abort(404, "No project found for %s" % project_to)
 
@@ -1588,7 +1555,6 @@ def new_request_pull(
                 title=form.title.data,
                 initial_comment=initial_comment,
                 user=flask.g.fas_user.username,
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
                 commit_start=commit_start,
                 commit_stop=commit_stop,
             )
@@ -1813,7 +1779,6 @@ def new_remote_request_pull(repo, username=None, namespace=None):
                 remote_git=remote_git,
                 title=form.title.data,
                 user=flask.g.fas_user.username,
-                requestfolder=pagure_config["REQUESTS_FOLDER"],
             )
 
             if form.initial_comment.data.strip() != "":
@@ -1826,7 +1791,6 @@ def new_remote_request_pull(repo, username=None, namespace=None):
                     row=None,
                     comment=form.initial_comment.data.strip(),
                     user=flask.g.fas_user.username,
-                    requestfolder=pagure_config["REQUESTS_FOLDER"],
                 )
 
             try:
@@ -1934,10 +1898,6 @@ def fork_edit_file(repo, branchname, filename, username=None, namespace=None):
         task = pagure.lib.fork_project(
             session=flask.g.session,
             repo=repo,
-            gitfolder=pagure_config["GIT_FOLDER"],
-            docfolder=pagure_config["DOCS_FOLDER"],
-            ticketfolder=pagure_config["TICKETS_FOLDER"],
-            requestfolder=pagure_config["REQUESTS_FOLDER"],
             user=flask.g.fas_user.username,
             editbranch=branchname,
             editfile=filename,

+ 5 - 29
pagure/ui/issues.py

@@ -151,11 +151,7 @@ def update_issue(repo, issueid, username=None, namespace=None):
             issue.last_updated = datetime.datetime.utcnow()
             flask.g.session.add(issue)
             flask.g.session.delete(comment)
-            pagure.lib.git.update_git(
-                issue,
-                repo=issue.project,
-                repofolder=pagure_config["TICKETS_FOLDER"],
-            )
+            pagure.lib.git.update_git(issue, repo=issue.project)
             try:
                 flask.g.session.commit()
                 if not is_js:
@@ -237,7 +233,6 @@ def update_issue(repo, issueid, username=None, namespace=None):
                         milestone=issue.milestone,
                         private=issue.private,
                         user=flask.g.fas_user.username,
-                        ticketfolder=pagure_config["TICKETS_FOLDER"],
                     )
                     flask.g.session.commit()
                     if msgs:
@@ -253,7 +248,6 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     issue,
                     tags,
                     username=flask.g.fas_user.username,
-                    gitfolder=pagure_config["TICKETS_FOLDER"],
                 )
                 messages = messages.union(set(msgs))
 
@@ -267,7 +261,6 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     issue=issue,
                     assignee=assignee or None,
                     user=flask.g.fas_user.username,
-                    ticketfolder=pagure_config["TICKETS_FOLDER"],
                 )
                 flask.g.session.commit()
                 if message and message != "Nothing to change":
@@ -286,7 +279,6 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     priority=new_priority,
                     private=form.private.data,
                     user=flask.g.fas_user.username,
-                    ticketfolder=pagure_config["TICKETS_FOLDER"],
                 )
                 if msgs:
                     messages = messages.union(set(msgs))
@@ -325,7 +317,6 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     issue,
                     depends,
                     username=flask.g.fas_user.username,
-                    ticketfolder=pagure_config["TICKETS_FOLDER"],
                 )
                 messages = messages.union(set(msgs))
 
@@ -336,7 +327,6 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     issue,
                     blocks,
                     username=flask.g.fas_user.username,
-                    ticketfolder=pagure_config["TICKETS_FOLDER"],
                 )
                 messages = messages.union(set(msgs))
 
@@ -349,7 +339,6 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     issue=issue,
                     comment=comment,
                     user=flask.g.fas_user.username,
-                    ticketfolder=pagure_config["TICKETS_FOLDER"],
                 )
 
                 if not is_js:
@@ -370,7 +359,6 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     obj=issue,
                     messages=messages - not_needed,
                     user=flask.g.fas_user.username,
-                    gitfolder=pagure_config["TICKETS_FOLDER"],
                 )
                 messages.add("Metadata fields updated")
 
@@ -528,7 +516,6 @@ def edit_tag(repo, tag, username=None, namespace=None):
             new_tag_description,
             new_tag_color,
             user=flask.g.fas_user.username,
-            ticketfolder=pagure_config["TICKETS_FOLDER"],
         )
 
         try:
@@ -684,11 +671,7 @@ def remove_tag(repo, username=None, namespace=None):
         tags = [tag.strip() for tag in tags.split(",")]
 
         msgs = pagure.lib.remove_tags(
-            flask.g.session,
-            repo,
-            tags,
-            user=flask.g.fas_user.username,
-            gitfolder=pagure_config["TICKETS_FOLDER"],
+            flask.g.session, repo, tags, user=flask.g.fas_user.username
         )
 
         try:
@@ -1164,7 +1147,6 @@ def new_issue(repo, username=None, namespace=None):
                 milestone=milestone,
                 priority=priority,
                 tags=tags,
-                ticketfolder=pagure_config["TICKETS_FOLDER"],
             )
             flask.g.session.commit()
 
@@ -1223,7 +1205,7 @@ def new_issue(repo, username=None, namespace=None):
 
     types = None
     default = None
-    ticketrepopath = os.path.join(pagure_config["TICKETS_FOLDER"], repo.path)
+    ticketrepopath = repo.repopath("tickets")
     if os.path.exists(ticketrepopath):
         ticketrepo = pygit2.Repository(ticketrepopath)
         if not ticketrepo.is_empty and not ticketrepo.head_is_unborn:
@@ -1375,10 +1357,7 @@ def delete_issue(repo, issueid, username=None, namespace=None):
     if form.validate_on_submit():
         try:
             pagure.lib.drop_issue(
-                flask.g.session,
-                issue,
-                user=flask.g.fas_user.username,
-                ticketfolder=pagure_config["TICKETS_FOLDER"],
+                flask.g.session, issue, user=flask.g.fas_user.username
             )
             flask.g.session.commit()
             flask.flash("Issue deleted")
@@ -1474,7 +1453,6 @@ def edit_issue(repo, issueid, username=None, namespace=None):
                 content=content,
                 status=status,
                 user=flask.g.fas_user.username,
-                ticketfolder=pagure_config["TICKETS_FOLDER"],
                 private=private,
             )
             flask.g.session.commit()
@@ -1484,7 +1462,6 @@ def edit_issue(repo, issueid, username=None, namespace=None):
                     obj=issue,
                     messages=messages,
                     user=flask.g.fas_user.username,
-                    gitfolder=pagure_config["TICKETS_FOLDER"],
                 )
 
             # If there is a file attached, attach it.
@@ -1645,7 +1622,7 @@ def view_issue_raw_file(repo, filename=None, username=None, namespace=None):
             os.makedirs(attachdir)
 
         # Try to copy from git repo to attachments folder
-        reponame = os.path.join(pagure_config["TICKETS_FOLDER"], repo.path)
+        reponame = repo.repopath("tickets")
         repo_obj = pygit2.Repository(reponame)
 
         if repo_obj.is_empty:
@@ -1757,7 +1734,6 @@ def edit_comment_issue(
                 comment=comment,
                 user=flask.g.fas_user.username,
                 updated_comment=updated_comment,
-                folder=pagure_config["TICKETS_FOLDER"],
             )
             flask.g.session.commit()
             if not is_js:

+ 69 - 13
pagure/ui/repo.py

@@ -216,10 +216,9 @@ def view_repo_branch(repo, branchname, username=None, namespace=None):
     diff_commits = []
 
     if repo.is_fork and repo.parent:
-        parentname = os.path.join(
-            pagure_config['GIT_FOLDER'], repo.parent.path)
+        parentname = repo.parent.repopath('main')
     else:
-        parentname = os.path.join(pagure_config['GIT_FOLDER'], repo.path)
+        parentname = repo.repopath('main')
 
     orig_repo = pygit2.Repository(parentname)
 
@@ -373,11 +372,9 @@ def view_commits(repo, branchname=None, username=None, namespace=None):
     diff_commits = []
     diff_commits_full = []
     if repo.is_fork and repo.parent:
-        parentname = os.path.join(
-            pagure_config["GIT_FOLDER"], repo.parent.path
-        )
+        parentname = repo.parent.repopath("main")
     else:
-        parentname = os.path.join(pagure_config["GIT_FOLDER"], repo.path)
+        parentname = repo.repopath("main")
 
     orig_repo = pygit2.Repository(parentname)
 
@@ -1015,9 +1012,7 @@ def view_tags(repo, username=None, namespace=None):
 
     upload_folder_path = pagure_config["UPLOAD_FOLDER_PATH"] or ""
     pagure_checksum = os.path.exists(
-        os.path.join(
-            upload_folder_path, repo.fullname, "CHECKSUMS"
-        )
+        os.path.join(upload_folder_path, repo.fullname, "CHECKSUMS")
     )
 
     return flask.render_template(
@@ -1285,7 +1280,7 @@ def test_web_hook(repo, username=None, namespace=None):
             project=repo,
             topic="Test.notification",
             msg={"content": "Test message"},
-            redis=True
+            redis=True,
         )
         flask.flash("Notification triggered")
 
@@ -1328,7 +1323,6 @@ def update_project(repo, username=None, namespace=None):
                 repo,
                 tags=[t.strip() for t in form.tags.data.split(",")],
                 username=flask.g.fas_user.username,
-                gitfolder=None,
             )
             flask.g.session.add(repo)
             flask.g.session.commit()
@@ -2599,7 +2593,7 @@ def view_stargazers(repo, username=None, namespace=None):
         repo=flask.g.repo,
         username=username,
         namespace=namespace,
-        users=users
+        users=users,
     )
 
 
@@ -2942,6 +2936,68 @@ def delete_report(repo, username=None, namespace=None):
     )
 
 
+@UI_NS.route("/<repo>/torepospanner", methods=["POST"])
+@UI_NS.route("/<namespace>/<repo>/torepospanner", methods=["POST"])
+@UI_NS.route("/fork/<username>/<repo>/torepospanner", methods=["POST"])
+@UI_NS.route(
+    "/fork/<username>/<namespace>/<repo>/torepospanner", methods=["POST"]
+)
+@login_required
+@is_admin_sess_timedout
+@is_repo_admin
+def move_to_repospanner(repo, username=None, namespace=None):
+    """ Give a project to someone else.
+    """
+    repo = flask.g.repo
+
+    if not pagure.utils.is_admin():
+        flask.abort(
+            403, "You are not allowed to transfer this project to repoSpanner"
+        )
+
+    if not pagure_config.get("REPOSPANNER_ADMIN_MIGRATION"):
+        flask.abort(403, "It is not allowed to request migration of a repo")
+
+    form = pagure.forms.ConfirmationForm()
+
+    if form.validate_on_submit():
+        region = flask.request.form.get("region", "").strip()
+        if not region:
+            flask.abort(404, "No target region specified")
+
+        if region not in pagure_config.get("REPOSPANNER_REGIONS"):
+            flask.abort(404, "Invalid region specified")
+
+        _log.info(
+            "Repo %s requested to be migrated to repoSpanner region %s",
+            repo.fullname,
+            region,
+        )
+
+        task = pagure.lib.tasks.move_to_repospanner.delay(
+            repo.name, namespace, username, region
+        )
+
+        return pagure.utils.wait_for_task(
+            task,
+            prev=flask.url_for(
+                "ui_ns.view_repo",
+                username=username,
+                repo=repo.name,
+                namespace=namespace,
+            ),
+        )
+
+    return flask.redirect(
+        flask.url_for(
+            "ui_ns.view_repo",
+            username=username,
+            repo=repo.name,
+            namespace=namespace,
+        )
+    )
+
+
 @UI_NS.route("/<repo>/give", methods=["POST"])
 @UI_NS.route("/<namespace>/<repo>/give", methods=["POST"])
 @UI_NS.route("/fork/<username>/<repo>/give", methods=["POST"])

+ 4 - 8
pagure/utils.py

@@ -392,7 +392,7 @@ def get_repo_path(repo):
     """ Return the path of the git repository corresponding to the provided
     Repository object from the DB.
     """
-    repopath = os.path.join(pagure_config["GIT_FOLDER"], repo.path)
+    repopath = repo.repopath("main")
     if not os.path.exists(repopath):
         flask.abort(404, "No git repo found")
 
@@ -470,18 +470,14 @@ def split_project_fullname(project_name):
     return (user, namespace, project_name)
 
 
-def get_parent_repo_path(repo):
+def get_parent_repo_path(repo, repotype="main"):
     """ Return the path of the parent git repository corresponding to the
     provided Repository object from the DB.
     """
     if repo.parent:
-        parentpath = os.path.join(
-            pagure_config["GIT_FOLDER"], repo.parent.path
-        )
+        return repo.parent.repopath(repotype)
     else:
-        parentpath = os.path.join(pagure_config["GIT_FOLDER"], repo.path)
-
-    return parentpath
+        return repo.repopath(repotype)
 
 
 def stream_template(app, template_name, **context):

+ 36 - 0
tests/__init__.py

@@ -56,6 +56,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 
 import pagure
 import pagure.api
+from pagure.api.ci import jenkins
 import pagure.flask_app
 import pagure.lib
 import pagure.lib.model
@@ -85,12 +86,26 @@ GIT_FOLDER = '%(path)s/repos'
 REQUESTS_FOLDER = '%(path)s/repos/requests'
 TICKETS_FOLDER = %(tickets_folder)r
 DOCS_FOLDER = %(docs_folder)r
+REPOSPANNER_PSEUDO_FOLDER = '%(path)s/repos/pseudo'
 ATTACHMENTS_FOLDER = '%(path)s/attachments'
 BROKER_URL = 'redis+socket://%(global_path)s/broker'
 CELERY_CONFIG = {
     "task_always_eager": True,
     #"task_eager_propagates": True,
 }
+REPOSPANNER_NEW_REPO = %(repospanner_new_repo)s
+REPOSPANNER_NEW_REPO_ADMIN_OVERRIDE = %(repospanner_admin_override)s
+REPOSPANNER_NEW_FORK = %(repospanner_new_fork)s
+REPOSPANNER_ADMIN_MIGRATION = %(repospanner_admin_migration)s
+REPOSPANNER_REGIONS = {
+    'default': {'url': 'https://nodea.regiona.repospanner.local:%(repospanner_gitport)s',
+                'repo_prefix': 'pagure/',
+                'ca': '%(path)s/repospanner/pki/ca.crt',
+                'admin_cert': {'cert': '%(path)s/repospanner/pki/admin.crt',
+                               'key': '%(path)s/repospanner/pki/admin.key'},
+                'push_cert': {'cert': '%(path)s/repospanner/pki/pagure.crt',
+                              'key': '%(path)s/repospanner/pki/pagure.key'}}
+}
 """
 # The Celery docs warn against using task_always_eager:
 # http://docs.celeryproject.org/en/latest/userguide/testing.html
@@ -352,6 +367,12 @@ class SimplePagureTest(unittest.TestCase):
             'enable_tickets': True,
             'tickets_folder': '%s/repos/tickets' % self.path,
             'global_path': tests_state["path"],
+
+            'repospanner_gitport': '8443',
+            'repospanner_new_repo': 'None',
+            'repospanner_admin_override': 'False',
+            'repospanner_new_fork': 'True',
+            'repospanner_admin_migration': 'False',
         }
         config_values.update(self.config_values)
         config_path = os.path.join(self.path, 'config')
@@ -512,6 +533,14 @@ class FakeUser(object):     # pylint: disable=too-few-public-methods
         return self.dic[key]
 
 
+def create_locks(session, project):
+    for ltype in ('WORKER', 'WORKER_TICKET', 'WORKER_REQUEST'):
+        lock = pagure.lib.model.ProjectLock(
+            project_id=project.id,
+            lock_type=ltype)
+        session.add(lock)
+
+
 def create_projects(session, is_fork=False, user_id=1, hook_token_suffix=''):
     """ Create some projects in the database. """
     item = pagure.lib.model.Project(
@@ -524,6 +553,8 @@ def create_projects(session, is_fork=False, user_id=1, hook_token_suffix=''):
     )
     item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
     session.add(item)
+    session.flush()
+    create_locks(session, item)
 
     item = pagure.lib.model.Project(
         user_id=user_id,  # pingou
@@ -981,6 +1012,11 @@ def get_alerts(html):
     return alerts
 
 
+def definitely_wait(result):
+    """ Helper function for definitely waiting in _maybe_wait. """
+    result.wait()
+
+
 if __name__ == '__main__':
     SUITE = unittest.TestLoader().loadTestsFromTestCase(Modeltests)
     unittest.TextTestRunner(verbosity=2).run(SUITE)

+ 2 - 24
tests/test_pagure_flask_api_fork.py

@@ -62,7 +62,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -107,7 +106,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -145,7 +143,7 @@ class PagureFlaskApiForktests(tests.Modeltests):
 
         # Close the PR and try again
         pagure.lib.close_pull_request(
-            self.session, request=req, user='pingou', requestfolder=None,
+            self.session, request=req, user='pingou',
             merged=False)
 
         output = self.app.get('/api/0/test/pull-requests?status=closed')
@@ -187,7 +185,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -213,7 +210,7 @@ class PagureFlaskApiForktests(tests.Modeltests):
 
         # Close the PR and try again
         pagure.lib.close_pull_request(
-            self.session, request=req, user='pingou', requestfolder=None,
+            self.session, request=req, user='pingou',
             merged=False)
 
         output = self.app.get('/api/0/test/pull-requests?status=all')
@@ -255,7 +252,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -442,7 +438,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -485,7 +480,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -658,7 +652,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -819,7 +812,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -866,7 +858,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -984,7 +975,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1038,7 +1028,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1094,7 +1083,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1151,7 +1139,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1205,7 +1192,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1322,7 +1308,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1472,7 +1457,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1550,7 +1534,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1594,7 +1577,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1691,7 +1673,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1815,7 +1796,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1917,7 +1897,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -2068,7 +2047,6 @@ class PagureFlaskApiForktests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)

+ 0 - 20
tests/test_pagure_flask_api_issue.py

@@ -1184,7 +1184,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
             status="Closed"
         )
@@ -2436,7 +2435,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
             issue_uid='aaabbbccc',
         )
@@ -2661,7 +2659,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -2713,7 +2710,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -2768,7 +2764,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -2819,7 +2814,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -2894,7 +2888,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -2967,7 +2960,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -3013,7 +3005,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -3053,7 +3044,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
             issue_uid='aaabbbccc1',
         )
@@ -3167,7 +3157,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='foo',
-            ticketfolder=None,
             private=True,
             issue_uid='aaabbbccc1',
         )
@@ -3300,7 +3289,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
             issue_uid='aaabbbccc1',
         )
@@ -3436,7 +3424,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue',
             content='We should work on this',
             user='foo',
-            ticketfolder=None,
             private=True,
             issue_uid='aaabbbccc#2',
         )
@@ -3516,7 +3503,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
             issue_uid='aaabbbccc1',
             assignee='foo',
@@ -3628,7 +3614,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='foo',
-            ticketfolder=None,
             private=False,
             issue_uid='aaabbbccc1',
         )
@@ -3785,7 +3770,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -3968,7 +3952,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -4019,7 +4002,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
             status="Closed"
         )
@@ -4050,7 +4032,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
             status="Closed"
         )
@@ -4169,7 +4150,6 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
             status="Closed"
         )

+ 0 - 2
tests/test_pagure_flask_api_issue_change_status.py

@@ -58,7 +58,6 @@ class PagureFlaskApiIssueChangeStatustests(tests.Modeltests):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -71,7 +70,6 @@ class PagureFlaskApiIssueChangeStatustests(tests.Modeltests):
             title='Test issue #2',
             content='We should work on this',
             user='foo',
-            ticketfolder=None,
             private=True,
         )
         self.session.commit()

+ 0 - 2
tests/test_pagure_flask_api_issue_comment.py

@@ -52,7 +52,6 @@ class PagureFlaskApiIssueCommenttests(tests.Modeltests):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -65,7 +64,6 @@ class PagureFlaskApiIssueCommenttests(tests.Modeltests):
             title='Test issue #2',
             content='We should work on this',
             user='foo',
-            ticketfolder=None,
             private=True,
         )
         self.session.commit()

+ 0 - 1
tests/test_pagure_flask_api_issue_custom_fields.py

@@ -46,7 +46,6 @@ class PagureFlaskApiCustomFieldIssuetests(tests.Modeltests):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()

+ 0 - 2
tests/test_pagure_flask_api_pr_flag.py

@@ -53,7 +53,6 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -590,7 +589,6 @@ class PagureFlaskApiPRFlagUserTokentests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)

+ 4 - 8
tests/test_pagure_flask_api_project.py

@@ -375,8 +375,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
 
         # Adding a tag
         output = pagure.lib.update_tags(
-            self.session, repo, 'infra', 'pingou',
-            None)
+            self.session, repo, 'infra', 'pingou')
         self.assertEqual(output, ['Project tagged with: infra'])
 
         # Check after adding
@@ -857,8 +856,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
 
         # Adding a tag
         output = pagure.lib.update_tags(
-            self.session, repo, 'infra', 'pingou',
-            gitfolder=None)
+            self.session, repo, 'infra', 'pingou')
         self.assertEqual(output, ['Project tagged with: infra'])
 
         # Check after adding
@@ -927,8 +925,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
 
         # Adding a tag
         output = pagure.lib.update_tags(
-            self.session, repo, 'infra', 'pingou',
-            gitfolder=None)
+            self.session, repo, 'infra', 'pingou')
         self.assertEqual(output, ['Project tagged with: infra'])
 
         # Check after adding
@@ -1023,8 +1020,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
 
         # Adding a tag
         output = pagure.lib.update_tags(
-            self.session, repo, 'infra', 'pingou',
-            gitfolder=None)
+            self.session, repo, 'infra', 'pingou')
         self.assertEqual(output, ['Project tagged with: infra'])
 
         # Check after adding

+ 0 - 1
tests/test_pagure_flask_api_project_update_watch.py

@@ -55,7 +55,6 @@ class PagureFlaskApiProjectUpdateWatchTests(tests.Modeltests):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()

+ 1 - 13
tests/test_pagure_flask_api_ui_private_repo.py

@@ -366,7 +366,6 @@ class PagurePrivateRepotest(tests.Modeltests):
             branch_to='master',
             title='PR from the %s branch' % branch_from,
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -943,7 +942,6 @@ class PagurePrivateRepotest(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -1207,8 +1205,7 @@ class PagurePrivateRepotest(tests.Modeltests):
 
         # Adding a tag
         output = pagure.lib.update_tags(
-            self.session, repo, 'infra', 'pingou',
-            gitfolder=None)
+            self.session, repo, 'infra', 'pingou')
         self.assertEqual(output, ['Project tagged with: infra'])
 
         # Check after adding
@@ -1468,7 +1465,6 @@ class PagurePrivateRepotest(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1788,7 +1784,6 @@ class PagurePrivateRepotest(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1925,7 +1920,6 @@ class PagurePrivateRepotest(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -2101,7 +2095,6 @@ class PagurePrivateRepotest(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -2211,7 +2204,6 @@ class PagurePrivateRepotest(tests.Modeltests):
         self.session.add(item)
         self.session.commit()
 
-        tests.create_projects(self.session)
         tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
         tests.create_projects_git(os.path.join(self.path, 'requests'),
                                   bare=True)
@@ -2245,7 +2237,6 @@ class PagurePrivateRepotest(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -2544,7 +2535,6 @@ class PagurePrivateRepotest(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
         )
         self.session.commit()
@@ -3098,7 +3088,6 @@ class PagurePrivateRepotest(tests.Modeltests):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
         )
         self.session.commit()
@@ -3235,7 +3224,6 @@ class PagurePrivateRepotest(tests.Modeltests):
             title='Test issue #1',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=False,
             issue_uid='aaabbbccc1',
         )

+ 0 - 14
tests/test_pagure_flask_api_user.py

@@ -272,7 +272,6 @@ class PagureFlaskApiUSertests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -644,7 +643,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             branch_to='master',
             title='open pullrequest by user foo on repo test',
             user='foo',
-            requestfolder=None,
         )
 
         repo = pagure.lib.get_authorized_project(self.session, 'test2')
@@ -657,7 +655,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             branch_to='master',
             title='open pullrequest by user foo on repo test2',
             user='foo',
-            requestfolder=None,
         )
         self.session.commit()
 
@@ -672,7 +669,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             title='closed pullrequest by user foo on repo test',
             user='foo',
             status='Closed',
-            requestfolder=None,
         )
 
         repo = pagure.lib.get_authorized_project(self.session, 'test2')
@@ -686,7 +682,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             title='closed pullrequest by user foo on repo test2',
             user='foo',
             status='Closed',
-            requestfolder=None,
         )
         self.session.commit()
 
@@ -701,7 +696,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             title='merged pullrequest by user foo on repo test',
             user='foo',
             status='Merged',
-            requestfolder=None,
         )
 
         repo = pagure.lib.get_authorized_project(self.session, 'test2')
@@ -715,7 +709,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             title='merged pullrequest by user foo on repo test2',
             user='foo',
             status='Merged',
-            requestfolder=None,
         )
         self.session.commit()
 
@@ -729,7 +722,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             branch_to='master',
             title='open pullrequest by user pingou on repo test',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
 
@@ -743,7 +735,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             branch_to='master',
             title='open pullrequest by user pingou on repo test2',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
 
@@ -758,7 +749,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             title='closed pullrequest by user pingou on repo test',
             user='pingou',
             status="Closed",
-            requestfolder=None,
         )
         self.session.commit()
 
@@ -773,7 +763,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             title='closed pullrequest by user pingou on repo test2',
             user='pingou',
             status="Closed",
-            requestfolder=None,
         )
         self.session.commit()
 
@@ -788,7 +777,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             title='merged pullrequest by user pingou on repo test',
             user='pingou',
             status="Merged",
-            requestfolder=None,
         )
         self.session.commit()
 
@@ -803,7 +791,6 @@ class PagureFlaskApiUsertestrequests(tests.Modeltests):
             title='merged pullrequest by user pingou on repo test2',
             user='pingou',
             status="Merged",
-            requestfolder=None,
         )
         self.session.commit()
 
@@ -1078,7 +1065,6 @@ class PagureFlaskApiUsertestissues(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')

+ 8 - 8
tests/test_pagure_flask_docs.py

@@ -48,12 +48,12 @@ class PagureFlaskDocstests(tests.SimplePagureTest):
         pagure.docs_server.APP.config['TICKETS_FOLDER'] = os.path.join(
             self.path, 'tickets')
         pagure.docs_server.APP.config['DOCS_FOLDER'] = os.path.join(
-            self.path, 'docs')
+            self.path, 'repos', 'docs')
         self.app = pagure.docs_server.APP.test_client()
 
     def _set_up_doc(self):
         # forked doc repo
-        docrepo = os.path.join(self.path, 'docs', 'test', 'test.git')
+        docrepo = os.path.join(self.path, 'repos', 'docs', 'test', 'test.git')
         repo = pygit2.init_repository(docrepo)
 
         # Create files in that git repo
@@ -88,7 +88,7 @@ class PagureFlaskDocstests(tests.SimplePagureTest):
 
         # Push the changes to the bare repo
         remote = repo.create_remote(
-            'origin', os.path.join(self.path, 'docs', 'test.git'))
+            'origin', os.path.join(self.path, 'repos', 'docs', 'test.git'))
 
         PagureRepo.push(remote, 'refs/heads/master:refs/heads/master')
 
@@ -132,7 +132,7 @@ class PagureFlaskDocstests(tests.SimplePagureTest):
         """
         tests.create_projects(self.session)
         repo = pagure.lib.get_authorized_project(self.session, 'test')
-        tests.create_projects_git(os.path.join(self.path, 'docs'))
+        tests.create_projects_git(os.path.join(self.path, 'repos', 'docs'))
 
         output = self.app.get('/test/docs')
         self.assertEqual(output.status_code, 404)
@@ -148,7 +148,7 @@ class PagureFlaskDocstests(tests.SimplePagureTest):
         """ Test the view_docs endpoint when the git repo is empty. """
         tests.create_projects(self.session)
         repo = pygit2.init_repository(
-            os.path.join(self.path, 'docs', 'test.git'), bare=True)
+            os.path.join(self.path, 'repos', 'docs', 'test.git'), bare=True)
 
         # Turn on the docs project since it's off by default
         repo = pagure.lib.get_authorized_project(self.session, 'test')
@@ -168,7 +168,7 @@ class PagureFlaskDocstests(tests.SimplePagureTest):
         """ Test the view_docs endpoint. """
         tests.create_projects(self.session)
         repo = pygit2.init_repository(
-            os.path.join(self.path, 'docs', 'test.git'), bare=True)
+            os.path.join(self.path, 'repos', 'docs', 'test.git'), bare=True)
 
         output = self.app.get('/test/docs')
         self.assertEqual(output.status_code, 404)
@@ -213,7 +213,7 @@ class PagureFlaskDocstests(tests.SimplePagureTest):
         """ Test viewing a file of which we cannot find the encoding. """
         tests.create_projects(self.session)
         repo = pygit2.init_repository(
-            os.path.join(self.path, 'docs', 'test.git'), bare=True)
+            os.path.join(self.path, 'repos', 'docs', 'test.git'), bare=True)
 
         output = self.app.get('/test/docs')
         self.assertEqual(output.status_code, 404)
@@ -237,7 +237,7 @@ class PagureFlaskDocstests(tests.SimplePagureTest):
         """ Test viewing a file of which we cannot find the encoding. """
         tests.create_projects(self.session)
         repo = pygit2.init_repository(
-            os.path.join(self.path, 'docs', 'test.git'), bare=True)
+            os.path.join(self.path, 'repos', 'docs', 'test.git'), bare=True)
 
         output = self.app.get('/test/docs')
         self.assertEqual(output.status_code, 404)

+ 1 - 10
tests/test_pagure_flask_dump_load_ticket.py

@@ -60,7 +60,6 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=repopath
         )
         self.assertEqual(msg.title, 'Test issue')
 
@@ -71,7 +70,6 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             title='Test issue #2',
             content='Another bug',
             user='pingou',
-            ticketfolder=repopath
         )
         self.assertEqual(msg.title, 'Test issue #2')
         msg = pagure.lib.new_issue(
@@ -80,7 +78,6 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             title='Test issue #3',
             content='That would be nice feature no?',
             user='foo',
-            ticketfolder=repopath
         )
         self.assertEqual(msg.title, 'Test issue #3')
 
@@ -94,7 +91,6 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             issue=issue,
             comment='Hey look a comment!',
             user='foo',
-            ticketfolder=repopath,
         )
         self.session.commit()
         self.assertEqual(msg, 'Comment added')
@@ -103,7 +99,6 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             issue=issue,
             comment='crazy right?',
             user='pingou',
-            ticketfolder=repopath,
         )
         self.session.commit()
         self.assertEqual(msg, 'Comment added')
@@ -113,7 +108,6 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             issue=issue,
             assignee='pingou',
             user='pingou',
-            ticketfolder=repopath,
         )
         self.session.commit()
         self.assertEqual(msg, 'Issue assigned to pingou')
@@ -123,7 +117,6 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             obj=issue,
             tags=[' feature ', 'future '],
             user='pingou',
-            gitfolder=repopath,
         )
         self.session.commit()
         self.assertEqual(msg, 'Issue tagged with: feature, future')
@@ -133,7 +126,6 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             issue=issue,
             issue_blocked=issue2,
             user='pingou',
-            ticketfolder=repopath,
         )
         self.session.commit()
         self.assertEqual(msg, 'Issue marked as depending on: #2')
@@ -142,13 +134,12 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             issue=issue3,
             issue_blocked=issue,
             user='foo',
-            ticketfolder=repopath,
         )
         self.session.commit()
         self.assertEqual(msg, 'Issue marked as depending on: #1')
 
         # Dump the JSON
-        pagure.lib.git.update_git(issue, repo, repopath).wait()
+        pagure.lib.git.update_git(issue, repo).wait()
         repo = pygit2.Repository(self.gitrepo)
         cnt = len([commit
             for commit in repo.walk(

+ 0 - 10
tests/test_pagure_flask_internal.py

@@ -66,7 +66,6 @@ class PagureFlaskInternaltests(tests.Modeltests):
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -148,7 +147,6 @@ class PagureFlaskInternaltests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -229,7 +227,6 @@ class PagureFlaskInternaltests(tests.Modeltests):
             content='We should work on this, really',
             user='pingou',
             private=True,
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -318,7 +315,6 @@ class PagureFlaskInternaltests(tests.Modeltests):
             content='We should work on this, really',
             user='pingou',
             private=True,
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -516,7 +512,6 @@ class PagureFlaskInternaltests(tests.Modeltests):
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -638,7 +633,6 @@ class PagureFlaskInternaltests(tests.Modeltests):
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -793,7 +787,6 @@ class PagureFlaskInternaltests(tests.Modeltests):
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -962,7 +955,6 @@ class PagureFlaskInternaltests(tests.Modeltests):
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1116,7 +1108,6 @@ class PagureFlaskInternaltests(tests.Modeltests):
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1255,7 +1246,6 @@ class PagureFlaskInternaltests(tests.Modeltests):
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)

+ 1 - 10
tests/test_pagure_flask_ui_app.py

@@ -1480,7 +1480,6 @@ class PagureFlaskApptests(tests.Modeltests):
             branch_to='master',
             title='test pull-request #1',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1515,7 +1514,6 @@ class PagureFlaskApptests(tests.Modeltests):
             branch_to='master',
             title='tést pull-request #2',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1548,7 +1546,6 @@ class PagureFlaskApptests(tests.Modeltests):
             branch_to='master',
             title='test pull-request #1',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1564,7 +1561,6 @@ class PagureFlaskApptests(tests.Modeltests):
             branch_to='master',
             title='test pull-request #2',
             user='foo',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 2)
@@ -1608,7 +1604,6 @@ class PagureFlaskApptests(tests.Modeltests):
             branch_to='master',
             title='test pull-request #1',
             user='foo',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -1643,7 +1638,6 @@ class PagureFlaskApptests(tests.Modeltests):
             content='We should work on this for the second time',
             user='pingou',
             status='Open',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #1')
@@ -1676,7 +1670,6 @@ class PagureFlaskApptests(tests.Modeltests):
             content='We should work on this for the second time',
             user='pingou',
             status='Open',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #2')
@@ -1689,7 +1682,6 @@ class PagureFlaskApptests(tests.Modeltests):
             content='This issue created by foo, but assigned to pingou',
             user='foo',
             status='Open',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #3')
@@ -1699,7 +1691,7 @@ class PagureFlaskApptests(tests.Modeltests):
             issue=msg,
             assignee='pingou',
             user='foo',
-            ticketfolder=None)
+        )
         self.session.commit()
         self.assertEqual(msg, 'Issue assigned to pingou')
 
@@ -1731,7 +1723,6 @@ class PagureFlaskApptests(tests.Modeltests):
             content='We should work on this for the second time',
             user='pingou',
             status='Open',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #1')

+ 0 - 12
tests/test_pagure_flask_ui_fork.py

@@ -214,7 +214,6 @@ class PagureFlaskForktests(tests.Modeltests):
             branch_to='master',
             title='PR from the %s branch' % branch_from,
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, prid)
@@ -765,8 +764,6 @@ class PagureFlaskForktests(tests.Modeltests):
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
-
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -834,8 +831,6 @@ class PagureFlaskForktests(tests.Modeltests):
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
-
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -893,7 +888,6 @@ class PagureFlaskForktests(tests.Modeltests):
             title='PR from the feature branch',
             user='pingou',
             status='Open',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -909,7 +903,6 @@ class PagureFlaskForktests(tests.Modeltests):
             title='test PR',
             user='pingou',
             status='Open',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.title, 'test PR')
@@ -924,7 +917,6 @@ class PagureFlaskForktests(tests.Modeltests):
             title='test Invalid PR',
             user='pingou',
             status='Closed',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.title, 'test Invalid PR')
@@ -939,7 +931,6 @@ class PagureFlaskForktests(tests.Modeltests):
             user='pingou',
             branch_to='master',
             status='Open',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.title, 'test PR for sort')
@@ -1323,7 +1314,6 @@ index 9f44358..2a552bb 100644
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
 
         )
         self.session.commit()
@@ -1414,7 +1404,6 @@ index 0000000..2a552bb
             branch_to='master',
             title='PR from the feature branch',
             user='pingou',
-            requestfolder=None,
 
         )
         self.session.commit()
@@ -3508,7 +3497,6 @@ index 0000000..2a552bb
             row=None,
             comment='Hello',
             user='jdoe',
-            requestfolder=None,
         )
         self.session.commit()
 

+ 0 - 3
tests/test_pagure_flask_ui_issue_pr_link.py

@@ -60,7 +60,6 @@ class PagureFlaskPrIssueLinkTest(tests.Modeltests):
             title='tést íssüé',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'tést íssüé')
@@ -71,7 +70,6 @@ class PagureFlaskPrIssueLinkTest(tests.Modeltests):
             title='tést íssüé #2',
             content='We should still work on this',
             user='foo',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'tést íssüé #2')
@@ -128,7 +126,6 @@ class PagureFlaskPrIssueLinkTest(tests.Modeltests):
             branch_to='master',
             title='test PR',
             user='foo',
-            requestfolder=None,
             initial_comment=None,
             repo_from=fork_repo,
         )

+ 2 - 44
tests/test_pagure_flask_ui_issues.py

@@ -710,7 +710,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='tést íssüé',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'tést íssüé')
@@ -730,7 +729,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             content='Testing search',
             user='pingou',
             milestone='1.1',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Tést íssüé with milestone')
@@ -743,7 +741,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             user='pingou',
             status='Closed',
             close_status='Invalid',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test invalid issue')
@@ -890,7 +887,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Big problÈm!',
             content='I need help ASAP',
             user='foo',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Big problÈm!')
@@ -1081,7 +1077,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue ☃',
             content='We should work on this ❤',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue ☃')
@@ -1093,7 +1088,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             content='Testing search',
             user='pingou',
             milestone='1.1',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue with milestone')
@@ -1143,7 +1137,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -1185,7 +1178,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -1251,7 +1243,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
         )
         self.session.commit()
@@ -1318,7 +1309,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -1399,7 +1389,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -1524,7 +1513,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -1537,7 +1525,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             milestone=stone,
             private=False,
             user='pingou',
-            ticketfolder=None
         )
         self.assertEqual(
             message,
@@ -1603,7 +1590,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Big problÈm!',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Big problÈm!')
@@ -1653,7 +1639,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -1889,7 +1874,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -1936,7 +1920,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
         )
         self.session.commit()
@@ -1979,7 +1962,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2094,7 +2076,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2106,7 +2087,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue #2',
             content='We should work on this again',
             user='foo',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #2')
@@ -2189,7 +2169,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2201,7 +2180,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue #2',
             content='We should work on this again',
             user='foo',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #2')
@@ -2315,7 +2293,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2412,7 +2389,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2464,7 +2440,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2521,7 +2496,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2621,7 +2595,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2707,7 +2680,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2777,7 +2749,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2789,7 +2760,7 @@ class PagureFlaskIssuestests(tests.Modeltests):
             obj=issue,
             tags='tag1',
             user='pingou',
-            gitfolder=None)
+        )
         self.session.commit()
         self.assertEqual(msg, 'Issue tagged with: tag1')
 
@@ -2882,7 +2853,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -2894,7 +2864,7 @@ class PagureFlaskIssuestests(tests.Modeltests):
             obj=issue,
             tags='tag1',
             user='pingou',
-            gitfolder=None)
+        )
         self.session.commit()
         self.assertEqual(msg, 'Issue tagged with: tag1')
 
@@ -2958,7 +2928,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -3040,7 +3009,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -3184,7 +3152,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='foo',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -3353,7 +3320,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -3636,7 +3602,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -3708,7 +3673,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='test issue',
             content='content test issue',
             user='pingou',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 1)
@@ -3722,7 +3686,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='test issue2',
             content='content test issue2',
             user='pingou',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 2)
@@ -3790,7 +3753,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='test issue',
             content='content test issue',
             user='pingou',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 1)
@@ -3804,7 +3766,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='test issue2',
             content='content test issue2',
             user='pingou',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 2)
@@ -3847,7 +3808,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -3914,7 +3874,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             title='Test issue',
             content='Fix me',
             user='pingou',
-            ticketfolder=None,
             private=private,
         )
         pagure.lib.add_issue_comment(
@@ -3922,7 +3881,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
             issue=msg,
             comment='How about no',
             user='naysayer',
-            ticketfolder=None,
         )
         self.session.commit()
 

+ 0 - 12
tests/test_pagure_flask_ui_issues_acl_checks.py

@@ -65,7 +65,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
 
         self.session.commit()
@@ -83,7 +82,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
         pagure.lib.edit_issue(
             self.session,
             issue,
-            pagure.config.config.get('TICKETS_FOLDER'),
             user='pingou',
             milestone='77'
         )
@@ -251,7 +249,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
         )
         self.session.commit()
@@ -322,7 +319,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
 
         self.session.commit()
@@ -340,7 +336,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
         pagure.lib.edit_issue(
             self.session,
             issue,
-            pagure.config.config.get('TICKETS_FOLDER'),
             user='pingou',
             milestone='77'
         )
@@ -509,7 +504,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
         )
         self.session.commit()
@@ -580,7 +574,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
 
         self.session.commit()
@@ -598,7 +591,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
         pagure.lib.edit_issue(
             self.session,
             issue,
-            pagure.config.config.get('TICKETS_FOLDER'),
             user='pingou',
             milestone='77'
         )
@@ -765,7 +757,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
         )
         self.session.commit()
@@ -836,7 +827,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
 
         self.session.commit()
@@ -854,7 +844,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
         pagure.lib.edit_issue(
             self.session,
             issue,
-            pagure.config.config.get('TICKETS_FOLDER'),
             user='pingou',
             milestone='77'
         )
@@ -1019,7 +1008,6 @@ class PagureFlaskIssuesACLtests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             private=True,
         )
         self.session.commit()

+ 0 - 2
tests/test_pagure_flask_ui_issues_private.py

@@ -59,7 +59,6 @@ class PagureFlaskIssuesPrivatetests(tests.Modeltests):
             user='foo',
             status='Open',
             private=True,
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #1')
@@ -72,7 +71,6 @@ class PagureFlaskIssuesPrivatetests(tests.Modeltests):
             user='foo',
             status='Open',
             private=False,
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #2')

+ 0 - 2
tests/test_pagure_flask_ui_issues_read_only.py

@@ -54,7 +54,6 @@ class PagureFlaskIssuesReadOnlytests(tests.Modeltests):
             user='foo',
             status='Open',
             private=True,
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #1')
@@ -67,7 +66,6 @@ class PagureFlaskIssuesReadOnlytests(tests.Modeltests):
             user='foo',
             status='Open',
             private=False,
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #2')

+ 3 - 12
tests/test_pagure_flask_ui_plugins_default_hook.py

@@ -53,12 +53,9 @@ class PagureFlaskPluginDefaultHooktests(tests.Modeltests):
             self.session,
             user='pingou',
             name='test',
+            repospanner_region=None,
             blacklist=[],
             allowed_prefix=[],
-            gitfolder=os.path.join(self.path, 'repos'),
-            docfolder=os.path.join(self.path, 'docs'),
-            ticketfolder=os.path.join(self.path, 'tickets'),
-            requestfolder=os.path.join(self.path, 'requests'),
             description=None,
             url=None, avatar_email=None,
             parent_id=None,
@@ -86,12 +83,9 @@ class PagureFlaskPluginDefaultHooktests(tests.Modeltests):
             self.session,
             user='pingou',
             name='test',
+            repospanner_region=None,
             blacklist=[],
             allowed_prefix=[],
-            gitfolder=os.path.join(self.path, 'repos'),
-            docfolder=os.path.join(self.path, 'docs'),
-            ticketfolder=os.path.join(self.path, 'tickets'),
-            requestfolder=os.path.join(self.path, 'requests'),
             description=None,
             url=None, avatar_email=None,
             parent_id=None,
@@ -127,12 +121,9 @@ class PagureFlaskPluginDefaultHooktests(tests.Modeltests):
                 self.session,
                 user='pingou',
                 name='test',
+                repospanner_region=None,
                 blacklist=[],
                 allowed_prefix=[],
-                gitfolder=os.path.join(self.path, 'repos'),
-                docfolder=os.path.join(self.path, 'docs'),
-                ticketfolder=os.path.join(self.path, 'tickets'),
-                requestfolder=os.path.join(self.path, 'requests'),
                 description=None,
                 url=None, avatar_email=None,
                 parent_id=None,

+ 0 - 1
tests/test_pagure_flask_ui_pr_no_sources.py

@@ -168,7 +168,6 @@ class PagureFlaskPrNoSourcestests(tests.Modeltests):
             branch_to='master',
             title='PR from the %s branch' % branch_from,
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)

+ 4 - 55
tests/test_pagure_flask_ui_repo.py

@@ -3173,41 +3173,15 @@ index 0000000..fb7093d
 
         with tests.user_set(self.app.application, user):
             # Only git repo
-            item = pagure.lib.model.Project(
-                user_id=1,  # pingou
-                name='test',
-                description='test project #1',
-                hook_token='aaabbbggg',
-            )
-            self.session.add(item)
-            self.session.commit()
             output = self.app.post('/test/delete', follow_redirects=True)
             self.assertEqual(output.status_code, 404)
 
             # Only git and doc repo
-            item = pagure.lib.model.Project(
-                user_id=1,  # pingou
-                name='test',
-                description='test project #1',
-                hook_token='aaabbbhhh',
-            )
-            self.session.add(item)
-            self.session.commit()
             tests.create_projects_git(os.path.join(self.path, 'repos'))
             tests.create_projects_git(os.path.join(self.path, 'docs'))
             output = self.app.post('/test/delete', follow_redirects=True)
             self.assertEqual(output.status_code, 404)
 
-            # All repo there
-            item = pagure.lib.model.Project(
-                user_id=1,  # pingou
-                name='test',
-                description='test project #1',
-                hook_token='aaabbbiii',
-            )
-            self.session.add(item)
-            self.session.commit()
-
             # Create all the git repos
             tests.create_projects_git(os.path.join(self.path, 'repos'))
             tests.create_projects_git(os.path.join(self.path, 'docs'))
@@ -3222,7 +3196,7 @@ index 0000000..fb7093d
             output_text = output.get_data(as_text=True)
             self.assertIn(
                 '<span class="btn btn-outline-secondary disabled opacity-100 '
-                'border-0 ml-auto font-weight-bold">6 projects</span>', output_text)
+                'border-0 ml-auto font-weight-bold">3 projects</span>', output_text)
             self.assertNotIn(
                 '<span class="d-none d-md-inline">Forks&nbsp;</span>',
                 output_text)
@@ -3235,7 +3209,6 @@ index 0000000..fb7093d
                 title='Test issue',
                 content='We should work on this',
                 user='pingou',
-                ticketfolder=os.path.join(self.path, 'tickets')
             )
             self.session.commit()
             self.assertEqual(msg.title, 'Test issue')
@@ -3246,7 +3219,6 @@ index 0000000..fb7093d
                 title='Test issue #2',
                 content='We should work on this, really',
                 user='pingou',
-                ticketfolder=os.path.join(self.path, 'tickets')
             )
             self.session.commit()
             self.assertEqual(msg.title, 'Test issue #2')
@@ -3258,7 +3230,6 @@ index 0000000..fb7093d
                 issue=issue,
                 comment='Hey look a comment!',
                 user='foo',
-                ticketfolder=None
             )
             self.session.commit()
             self.assertEqual(msg, 'Comment added')
@@ -3272,7 +3243,6 @@ index 0000000..fb7093d
                 branch_to='master',
                 title='test pull-request',
                 user='pingou',
-                requestfolder=os.path.join(self.path, 'requests'),
             )
             self.session.commit()
             self.assertEqual(req.id, 3)
@@ -3286,7 +3256,6 @@ index 0000000..fb7093d
                 branch_to='master',
                 title='test pull-request',
                 user='pingou',
-                requestfolder=os.path.join(self.path, 'requests'),
             )
             self.session.commit()
             self.assertEqual(req.id, 4)
@@ -3305,7 +3274,6 @@ index 0000000..fb7093d
                 row=None,
                 comment='This is awesome, I got to remember it!',
                 user='foo',
-                requestfolder=None,
             )
             self.assertEqual(msg, 'Comment added')
 
@@ -3315,7 +3283,7 @@ index 0000000..fb7093d
             output_text = output.get_data(as_text=True)
             self.assertIn(
                 '<span class="btn btn-outline-secondary disabled opacity-100 '
-                'border-0 ml-auto font-weight-bold">6 projects</span>', output_text)
+                'border-0 ml-auto font-weight-bold">3 projects</span>', output_text)
             self.assertNotIn(
                 '<span class="d-none d-md-inline">Forks&nbsp;</span>',
                 output_text)
@@ -3353,7 +3321,7 @@ index 0000000..fb7093d
             output_text = output.get_data(as_text=True)
             self.assertIn(
                 '<span class="btn btn-outline-secondary disabled opacity-100 '
-                'border-0 ml-auto font-weight-bold">6 projects</span>', output_text)
+                'border-0 ml-auto font-weight-bold">3 projects</span>', output_text)
             self.assertIn(
                 """<span>
               <i class="fa fa-fw text-muted fa-code-fork"></i>
@@ -3379,16 +3347,6 @@ index 0000000..fb7093d
         tests.create_projects(self.session)
         tests.create_projects_git(os.path.join(self.path, 'repos'))
 
-        # All repo there
-        item = pagure.lib.model.Project(
-            user_id=1,  # pingou
-            name='test',
-            description='test project #1',
-            hook_token='aaabbbiii',
-        )
-        self.session.add(item)
-        self.session.commit()
-
         # Create all the git repos
         tests.create_projects_git(os.path.join(self.path, 'repos'))
         tests.create_projects_git(os.path.join(self.path, 'docs'))
@@ -3603,7 +3561,6 @@ index 0000000..fb7093d
                 title='Test issue',
                 content='We should work on this',
                 user='pingou',
-                ticketfolder=os.path.join(self.path, 'tickets')
             )
             self.session.commit()
             self.assertEqual(msg.title, 'Test issue')
@@ -3614,7 +3571,6 @@ index 0000000..fb7093d
                 title='Test issue #2',
                 content='We should work on this, really',
                 user='pingou',
-                ticketfolder=os.path.join(self.path, 'tickets')
             )
             self.session.commit()
             self.assertEqual(msg.title, 'Test issue #2')
@@ -3626,7 +3582,6 @@ index 0000000..fb7093d
                 issue=issue,
                 comment='Hey look a comment!',
                 user='foo',
-                ticketfolder=None
             )
             self.session.commit()
             self.assertEqual(msg, 'Comment added')
@@ -3640,7 +3595,6 @@ index 0000000..fb7093d
                 branch_to='master',
                 title='test pull-request',
                 user='pingou',
-                requestfolder=os.path.join(self.path, 'requests'),
             )
             self.session.commit()
             self.assertEqual(req.id, 3)
@@ -3654,7 +3608,6 @@ index 0000000..fb7093d
                 branch_to='master',
                 title='test pull-request',
                 user='pingou',
-                requestfolder=os.path.join(self.path, 'requests'),
             )
             self.session.commit()
             self.assertEqual(req.id, 4)
@@ -3673,7 +3626,6 @@ index 0000000..fb7093d
                 row=None,
                 comment='This is awesome, I got to remember it!',
                 user='foo',
-                requestfolder=None,
             )
             self.assertEqual(msg, 'Comment added')
 
@@ -4130,7 +4082,6 @@ index 0000000..fb7093d
                 title='Test issue',
                 content='We should work on this',
                 user='pingou',
-                ticketfolder=os.path.join(self.path, 'tickets')
             )
             self.session.commit()
             self.assertEqual(msg.title, 'Test issue')
@@ -4143,7 +4094,7 @@ index 0000000..fb7093d
                 obj=issue,
                 tags='tag1',
                 user='pingou',
-                gitfolder=None)
+            )
             self.session.commit()
             self.assertEqual(msg, 'Issue tagged with: tag1')
 
@@ -4308,7 +4259,6 @@ index 0000000..fb7093d
                 title='Test issue',
                 content='We should work on this',
                 user='pingou',
-                ticketfolder=None
             )
             self.session.commit()
             self.assertEqual(msg.title, 'Test issue')
@@ -4332,7 +4282,6 @@ index 0000000..fb7093d
                 branch_to='master',
                 title='Test pull-request',
                 user='pingou',
-                requestfolder=None,
             )
             self.session.commit()
             self.assertEqual(msg.title, 'Test pull-request')

+ 0 - 4
tests/test_pagure_flask_ui_repo_delete_project.py

@@ -59,10 +59,6 @@ class PagureFlaskDeleteRepotests(tests.Modeltests):
             session=self.session,
             user='pingou',
             repo=project,
-            gitfolder=os.path.join(self.path, 'repos'),
-            docfolder=os.path.join(self.path, 'repos', 'docs'),
-            ticketfolder=os.path.join(self.path, 'repos', 'tickets'),
-            requestfolder=os.path.join(self.path, 'repos', 'requests'),
         )
         task.get()
 

+ 0 - 1
tests/test_pagure_flask_ui_repo_milestones.py

@@ -46,7 +46,6 @@ class PagureFlaskRepoMilestonestests(tests.Modeltests):
             content='We should work on this for the second time',
             user='foo',
             status='Open',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #1')

+ 2 - 8
tests/test_pagure_flask_ui_repo_slash_name.py

@@ -111,16 +111,13 @@ class PagureFlaskSlashInNametests(tests.SimplePagureTest):
             self.session,
             name='test',
             namespace='forks',
+            repospanner_region=None,
             description='test project forks/test',
             url='',
             avatar_email='',
             user='pingou',
             blacklist=pagure.config.config['BLACKLISTED_PROJECTS'],
             allowed_prefix=pagure.config.config['ALLOWED_PREFIX'],
-            gitfolder=pagure.config.config['GIT_FOLDER'],
-            docfolder=pagure.config.config['DOCS_FOLDER'],
-            ticketfolder=pagure.config.config['TICKETS_FOLDER'],
-            requestfolder=pagure.config.config['REQUESTS_FOLDER'],
         )
 
         # So just put it in the DB
@@ -188,16 +185,13 @@ class PagureFlaskSlashInNametests(tests.SimplePagureTest):
             self.session,
             name='test',
             namespace='forks',
+            repospanner_region=None,
             description='test project forks/test',
             url='',
             avatar_email='',
             user='pingou',
             blacklist=pagure.config.config['BLACKLISTED_PROJECTS'],
             allowed_prefix=pagure.config.config['ALLOWED_PREFIX'],
-            gitfolder=pagure.config.config['GIT_FOLDER'],
-            docfolder=pagure.config.config['DOCS_FOLDER'],
-            ticketfolder=pagure.config.config['TICKETS_FOLDER'],
-            requestfolder=pagure.config.config['REQUESTS_FOLDER'],
         )
 
         # So just put it in the DB

File diff suppressed because it is too large
+ 46 - 231
tests/test_pagure_lib.py


+ 4 - 7
tests/test_pagure_lib_drop_issue.py

@@ -60,7 +60,6 @@ class PagureLibDropIssuetests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue')
@@ -74,7 +73,6 @@ class PagureLibDropIssuetests(tests.Modeltests):
             content='We should work on this for the second time',
             user='foo',
             status='Open',
-            ticketfolder=None
         )
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #2')
@@ -103,6 +101,7 @@ class PagureLibDropIssuetests(tests.Modeltests):
 
     @patch('pagure.lib.git.update_git')
     @patch('pagure.lib.notify.send_email')
+    @patch('pagure.lib.git._maybe_wait', tests.definitely_wait)
     def test_drop_issue(self, p_send_email, p_ugt):
         """ Test the drop_issue of pagure.lib.
 
@@ -122,7 +121,6 @@ class PagureLibDropIssuetests(tests.Modeltests):
             issue,
             tags=['red'],
             username='pingou',
-            gitfolder=None,
         )
         self.session.commit()
 
@@ -139,7 +137,7 @@ class PagureLibDropIssuetests(tests.Modeltests):
         # Drop the issue #2
         issue = pagure.lib.search_issues(self.session, repo, issueid=2)
         pagure.lib.drop_issue(
-            self.session, issue, user='pingou', ticketfolder=None)
+            self.session, issue, user='pingou')
         self.session.commit()
 
         repo = pagure.lib.get_authorized_project(self.session, 'test')
@@ -147,6 +145,7 @@ class PagureLibDropIssuetests(tests.Modeltests):
 
     @patch('pagure.lib.git.update_git')
     @patch('pagure.lib.notify.send_email')
+    @patch('pagure.lib.git._maybe_wait', tests.definitely_wait)
     def test_drop_issue_two_issues_one_tag(self, p_send_email, p_ugt):
         """ Test the drop_issue of pagure.lib.
 
@@ -166,7 +165,6 @@ class PagureLibDropIssuetests(tests.Modeltests):
             issue,
             tags=['red'],
             username='pingou',
-            gitfolder=None,
         )
         self.session.commit()
         self.assertEqual(msgs, ['Issue tagged with: red'])
@@ -177,7 +175,6 @@ class PagureLibDropIssuetests(tests.Modeltests):
             issue,
             tags=['red'],
             username='pingou',
-            gitfolder=None,
         )
         self.session.commit()
         self.assertEqual(msgs, ['Issue tagged with: red'])
@@ -198,7 +195,7 @@ class PagureLibDropIssuetests(tests.Modeltests):
         # Drop the issue #2
         issue = pagure.lib.search_issues(self.session, repo, issueid=2)
         pagure.lib.drop_issue(
-            self.session, issue, user='pingou', ticketfolder=None)
+            self.session, issue, user='pingou')
         self.session.commit()
 
         repo = pagure.lib.get_authorized_project(self.session, 'test')

+ 4 - 32
tests/test_pagure_lib_git.py

@@ -1415,12 +1415,10 @@ repo requests/forks/pingou/test3
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=os.path.join(self.path, 'repos', 'tickets')
         )
         self.assertEqual(msg.title, 'Test issue')
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
-        pagure.lib.git.update_git(issue, repo, os.path.join(self.path,
-                                                            'repos', 'tickets')).get()
+        pagure.lib.git.update_git(issue, repo).get()
 
         repo = pygit2.Repository(self.gitrepo)
         commit = repo.revparse_single('HEAD')
@@ -1512,16 +1510,12 @@ index 0000000..60f7480
 
         # Test again after adding a comment
         # We need to make sure we wait for worker to commit the comment
-        def _definitely_wait(result):
-            result.wait()
-
-        with patch('pagure.lib.git._maybe_wait', _definitely_wait):
+        with patch('pagure.lib.git._maybe_wait', tests.definitely_wait):
             msg = pagure.lib.add_issue_comment(
                 session=self.session,
                 issue=issue,
                 comment='Hey look a comment!',
                 user='foo',
-                ticketfolder=os.path.join(self.path, 'repos', 'tickets')
             )
         self.session.commit()
         self.assertEqual(msg, 'Comment added')
@@ -1615,8 +1609,6 @@ index 458821a..77674a8
 
     def test_clean_git(self):
         """ Test the clean_git method of pagure.lib.git. """
-        pagure.lib.git.clean_git(None, None, None)
-
         self.test_update_git()
 
         gitpath = os.path.join(self.path, 'repos', 'tickets',
@@ -1638,8 +1630,7 @@ index 458821a..77674a8
 
         repo = pagure.lib.get_authorized_project(self.session, 'test_ticket_repo')
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
-        pagure.lib.git.clean_git(issue, repo,
-                                 os.path.join(self.path, 'tickets')).get()
+        pagure.lib.git.clean_git(repo, issue.repotype, issue.uid).get()
 
         # No more files in the git repo
         commit = gitrepo.revparse_single('HEAD')
@@ -1677,7 +1668,6 @@ index 458821a..77674a8
             branch_to='master',
             title='test PR',
             user='pingou',
-            requestfolder=os.path.join(self.path, 'requests'),
             requestuid='foobar',
             requestid=None,
             status='Open',
@@ -1688,8 +1678,7 @@ index 458821a..77674a8
 
         request = repo.requests[0]
         self.assertEqual(request.title, 'test PR')
-        pagure.lib.git.update_git(request, request.project,
-                                  os.path.join(self.path, 'requests')).get()
+        pagure.lib.git.update_git(request, request.project).get()
 
         repo = pygit2.Repository(self.gitrepo)
         commit = repo.revparse_single('HEAD')
@@ -2777,7 +2766,6 @@ index 0000000..60f7480
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None,
             issue_uid='someuid'
         )
         self.session.commit()
@@ -2894,10 +2882,6 @@ index 0000000..60f7480
             session=self.session,
             user='foo',
             repo=repo,
-            gitfolder=gitfolder,
-            docfolder=docfolder,
-            ticketfolder=ticketfolder,
-            requestfolder=requestfolder,
         )
         self.session.commit()
         self.assertEqual(task.get(),
@@ -2921,7 +2905,6 @@ index 0000000..60f7480
             branch_to='master',
             title='test PR',
             user='pingou',
-            requestfolder=os.path.join(self.path, 'requests'),
             requestuid='foobar',
             requestid=None,
             status='Open',
@@ -2935,7 +2918,6 @@ index 0000000..60f7480
             self.session,
             request=req,
             username='pingou',
-            request_folder=os.path.join(self.path, 'requests'),
             domerge=False
         )
         self.assertEqual(msg, 'FFORWARD')
@@ -2964,10 +2946,6 @@ index 0000000..60f7480
         self.session.commit()
 
         repo = pagure.lib.get_authorized_project(self.session, 'test')
-        gitrepo = os.path.join(gitfolder, repo.path)
-        docrepo = os.path.join(docfolder, repo.path)
-        ticketrepo = os.path.join(ticketfolder, repo.path)
-        requestrepo = os.path.join(requestfolder, repo.path)
         os.makedirs(os.path.join(self.path, 'repos', 'forks', 'foo'))
 
         self.gitrepo = os.path.join(self.path, 'repos', 'test.git')
@@ -2980,10 +2958,6 @@ index 0000000..60f7480
             session=self.session,
             user='foo',
             repo=repo,
-            gitfolder=gitfolder,
-            docfolder=docfolder,
-            ticketfolder=ticketfolder,
-            requestfolder=requestfolder,
         )
         self.session.commit()
         self.assertEqual(task.get(),
@@ -3007,7 +2981,6 @@ index 0000000..60f7480
             branch_to='master',
             title='test PR',
             user='pingou',
-            requestfolder=os.path.join(self.path, 'requests'),
             requestuid='foobar',
             requestid=None,
             status='Open',
@@ -3032,7 +3005,6 @@ index 0000000..60f7480
             self.session,
             request=req,
             username='pingou',
-            request_folder=os.path.join(self.path, 'requests'),
             domerge=False
         )
 

+ 0 - 6
tests/test_pagure_lib_git_diff_pr.py

@@ -222,7 +222,6 @@ class PagureFlaskForkPrtests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.assertEqual(req.id, 1)
         self.assertEqual(req.title, 'test pull-request')
@@ -292,7 +291,6 @@ class PagureFlaskForkPrtests(tests.Modeltests):
             request=request,
             repo_obj=PagureRepo(gitrepo2),
             orig_repo=PagureRepo(gitrepo),
-            requestfolder=None,
             with_diff=True
         )
 
@@ -344,7 +342,6 @@ class PagureFlaskForkPrtests(tests.Modeltests):
             request=request,
             repo_obj=PagureRepo(gitrepo2),
             orig_repo=PagureRepo(gitrepo),
-            requestfolder=None,
             with_diff=True
         )
 
@@ -412,7 +409,6 @@ class PagureFlaskForkPrtests(tests.Modeltests):
             request=request,
             repo_obj=PagureRepo(gitrepo2),
             orig_repo=PagureRepo(gitrepo),
-            requestfolder=None,
             with_diff=True
         )
         self.assertEqual(len(diff_commits), 3)
@@ -459,7 +455,6 @@ class PagureFlaskForkPrtests(tests.Modeltests):
             request=request,
             repo_obj=PagureRepo(gitrepo2),
             orig_repo=PagureRepo(gitrepo),
-            requestfolder=None,
             with_diff=True
         )
 
@@ -493,7 +488,6 @@ class PagureFlaskForkPrtests(tests.Modeltests):
             request=request,
             repo_obj=PagureRepo(gitrepo2),
             orig_repo=PagureRepo(gitrepo),
-            requestfolder=None,
             with_diff=True
         )
         self.assertEqual(len(diff_commits2), 2)

+ 0 - 3
tests/test_pagure_lib_link.py

@@ -76,7 +76,6 @@ class PagureLibLinktests(tests.Modeltests):
             title='foo',
             content='bar',
             user='pingou',
-            ticketfolder=None,
             issue_id=5,
             notify=False)
         self.session.commit()
@@ -114,7 +113,6 @@ class PagureLibLinktests(tests.Modeltests):
             title='another foo',
             content='another bar',
             user='pingou',
-            ticketfolder=None,
             issue_id=6,
             notify=False)
         self.session.commit()
@@ -172,7 +170,6 @@ class PagureLibLinktests(tests.Modeltests):
             title='issue 3',
             content='content issue 3',
             user='pingou',
-            ticketfolder=None,
             issue_id=3,
             notify=False)
         self.session.commit()

+ 0 - 2
tests/test_pagure_lib_model.py

@@ -55,7 +55,6 @@ class PagureLibModeltests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
         self.assertEqual(msg.title, 'Test issue')
 
@@ -98,7 +97,6 @@ class PagureLibModeltests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.assertEqual(req.id, 1)
         self.assertEqual(req.title, 'test pull-request')

+ 0 - 10
tests/test_pagure_lib_notify.py

@@ -57,7 +57,6 @@ class PagureLibNotifytests(tests.Modeltests):
             title='test issue',
             content='content test issue',
             user='pingou',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 4)
@@ -73,7 +72,6 @@ class PagureLibNotifytests(tests.Modeltests):
             issue=iss,
             comment='This is a comment',
             user='foo',
-            ticketfolder=None,
             notify=False)
         self.assertEqual(out, 'Comment added')
 
@@ -126,7 +124,6 @@ class PagureLibNotifytests(tests.Modeltests):
             title='test issue',
             content='content test issue',
             user='pingou',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 4)
@@ -142,7 +139,6 @@ class PagureLibNotifytests(tests.Modeltests):
             issue=iss,
             comment='This is a comment',
             user='foo',
-            ticketfolder=None,
             notify=False)
         self.assertEqual(out, 'Comment added')
 
@@ -203,7 +199,6 @@ class PagureLibNotifytests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -224,7 +219,6 @@ class PagureLibNotifytests(tests.Modeltests):
             row=None,
             comment='This is a comment',
             user='foo',
-            requestfolder=None,
             notify=False)
         self.assertEqual(out, 'Comment added')
 
@@ -283,7 +277,6 @@ class PagureLibNotifytests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='pingou',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -304,7 +297,6 @@ class PagureLibNotifytests(tests.Modeltests):
             row=None,
             comment='This is a comment',
             user='foo',
-            requestfolder=None,
             notify=False)
         self.assertEqual(out, 'Comment added')
 
@@ -360,7 +352,6 @@ class PagureLibNotifytests(tests.Modeltests):
             content='content test issue',
             user='pingou',
             private=True,
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 4)
@@ -376,7 +367,6 @@ class PagureLibNotifytests(tests.Modeltests):
             issue=iss,
             comment='This is a comment',
             user='foo',
-            ticketfolder=None,
             notify=False)
         self.assertEqual(out, 'Comment added')
 

+ 0 - 4
tests/test_pagure_lib_notify_email.py

@@ -68,7 +68,6 @@ class PagureLibNotifyEmailtests(tests.Modeltests):
             title='issue',
             content='a bug report',
             user='pingou',
-            ticketfolder=None,
         )
 
         # Add a comment on the issue
@@ -77,7 +76,6 @@ class PagureLibNotifyEmailtests(tests.Modeltests):
             self.issue1,
             comment='Test comment',
             user='pingou',
-            ticketfolder=None,
         )
         self.comment1 = pagure.lib.get_issue_comment(self.session, self.issue1.uid, 1)
 
@@ -88,7 +86,6 @@ class PagureLibNotifyEmailtests(tests.Modeltests):
             title='namespaced project issue',
             content='a bug report on a namespaced project',
             user='pingou',
-            ticketfolder=None,
         )
 
         # report an issue on foo's fork of project #1
@@ -98,7 +95,6 @@ class PagureLibNotifyEmailtests(tests.Modeltests):
             title='forked project issue',
             content='a bug report on a forked project',
             user='pingou',
-            ticketfolder=None,
         )
 
         patcher.stop()

+ 0 - 2
tests/test_pagure_lib_task_services.py

@@ -626,7 +626,6 @@ class PagureLibTaskServicesLoadJsonTickettests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=repopath
         )
         self.assertEqual(msg.title, 'Test issue')
 
@@ -638,7 +637,6 @@ class PagureLibTaskServicesLoadJsonTickettests(tests.Modeltests):
             issue=issue,
             comment='Hey look a comment!',
             user='foo',
-            ticketfolder=repopath,
         )
         self.session.commit()
         self.assertEqual(msg, 'Comment added')

+ 0 - 8
tests/test_pagure_lib_watch_list.py

@@ -78,7 +78,6 @@ class PagureLibGetWatchListtests(tests.Modeltests):
             title='test issue',
             content='content test issue',
             user='pingou',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 4)
@@ -112,7 +111,6 @@ class PagureLibGetWatchListtests(tests.Modeltests):
             title='test issue',
             content='content test issue',
             user='foo',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 4)
@@ -170,7 +168,6 @@ class PagureLibGetWatchListtests(tests.Modeltests):
             title='test issue',
             content='content test issue',
             user='foo',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 4)
@@ -256,7 +253,6 @@ class PagureLibGetWatchListtests(tests.Modeltests):
             title='test issue',
             content='content test issue',
             user='foo',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 4)
@@ -324,7 +320,6 @@ class PagureLibGetWatchListtests(tests.Modeltests):
             title='test issue',
             content='content test issue',
             user='foo',
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 4)
@@ -383,7 +378,6 @@ class PagureLibGetWatchListtests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='foo',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -449,7 +443,6 @@ class PagureLibGetWatchListtests(tests.Modeltests):
             branch_to='master',
             title='test pull-request',
             user='foo',
-            requestfolder=None,
         )
         self.session.commit()
         self.assertEqual(req.id, 1)
@@ -511,7 +504,6 @@ class PagureLibGetWatchListtests(tests.Modeltests):
             content='content test issue',
             user='pingou',
             private=True,
-            ticketfolder=None,
         )
         self.session.commit()
         self.assertEqual(iss.id, 4)

+ 289 - 0
tests/test_pagure_repospanner.py

@@ -0,0 +1,289 @@
+# -*- coding: utf-8 -*-
+
+"""
+ (c) 2015-2018 - Copyright Red Hat Inc
+
+ Authors:
+   Patrick Uiterwijk <puiterwijk@redhat.com>
+
+"""
+
+from __future__ import unicode_literals
+
+__requires__ = ['SQLAlchemy >= 0.8']
+import pkg_resources
+
+import datetime
+import unittest
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+import os
+
+import six
+import json
+import pygit2
+import requests
+from requests.adapters import HTTPAdapter
+from requests.packages.urllib3.util.retry import Retry
+from mock import patch, MagicMock
+
+sys.path.insert(0, os.path.join(os.path.dirname(
+    os.path.abspath(__file__)), '..'))
+
+import pagure.lib
+import tests
+
+
+REPOSPANNER_CONFIG_TEMPLATE = """
+---
+ca:
+  path: %(path)s/repospanner/pki
+admin:
+  url:  https://nodea.regiona.repospanner.local:%(gitport)s/
+  ca:   %(path)s/repospanner/pki/ca.crt
+  cert: %(path)s/repospanner/pki/admin.crt
+  key:  %(path)s/repospanner/pki/admin.key
+storage:
+  state: %(path)s/repospanner/state
+  git:
+    type: tree
+    clustered: true
+    directory: %(path)s/repospanner/git
+listen:
+  rpc:  127.0.0.1:%(rpcport)s
+  http: 127.0.0.1:%(gitport)s
+certificates:
+  ca: %(path)s/repospanner/pki/ca.crt
+  client:
+    cert: %(path)s/repospanner/pki/nodea.regiona.crt
+    key:  %(path)s/repospanner/pki/nodea.regiona.key
+  server:
+    default:
+      cert: %(path)s/repospanner/pki/nodea.regiona.crt
+      key:  %(path)s/repospanner/pki/nodea.regiona.key
+hooks:
+  bubblewrap:
+    enabled: true
+    unshare:
+    - net
+    - ipc
+    - pid
+    - uts
+    share_net: false
+    mount_proc: true
+    mount_dev: true
+    uid:
+    gid:
+    hostname: myhostname
+    bind:
+    ro_bind:
+      /usr: /usr
+    symlink:
+      usr/lib64: /lib64
+      usr/bin: /bin
+  runner: /usr/bin/repohookrunner
+  user: 0
+"""
+
+
+class PagureRepoSpannerTests(tests.Modeltests):
+    """ Tests for repoSpanner integration of pagure """
+    repospanner_binary = None
+    repospanner_runlog = None
+    repospanner_proc = None
+
+    def run_cacmd(self, logfile, *args):
+        """ Run a repoSpanner CA command. """
+        subprocess.check_call(
+            [self.repospanner_binary,
+             '--config',
+             os.path.join(self.path, 'repospanner', 'config.yml'),
+             # NEVER use this in a production system! It makes repeatable keys
+             'ca'] + list(args) + ['--very-insecure-weak-keys'],
+            stdout=logfile,
+            stderr=subprocess.STDOUT,
+        )
+
+    def setUp(self):
+        """ set up the environment. """
+        possible_paths = [
+            './repospanner',
+            '/usr/bin/repospanner',
+        ]
+
+        for option in possible_paths:
+            option = os.path.abspath(option)
+            if os.path.exists(option):
+                self.repospanner_binary = option
+                break
+
+        if not self.repospanner_binary:
+            raise unittest.SkipTest('repoSpanner not found')
+
+        # Only run the setUp() function if we are actually going ahead and run
+        # this test. The reason being that otherwise, setUp will set up a
+        # database, but because we "error out" from setUp, the tearDown()
+        # function never gets called, leaving it behind.
+        super(PagureRepoSpannerTests, self).setUp()
+
+        # TODO: Find free ports
+        configvals = {
+            'path': self.path,
+            'gitport': 8443,
+            'rpcport': 8444,
+        }
+
+        os.mkdir(os.path.join(self.path, 'repospanner'))
+        cfgpath = os.path.join(self.path, 'repospanner', 'config.yml')
+        with open(cfgpath, 'w') as cfg:
+            cfg.write(REPOSPANNER_CONFIG_TEMPLATE % configvals)
+
+        with open(os.path.join(self.path, 'repospanner', 'keylog'),
+                  'w') as keylog:
+            # Create the CA
+            self.run_cacmd(keylog, 'init', 'repospanner.local')
+            # Create the node cert
+            self.run_cacmd(keylog, 'node', 'regiona', 'nodea')
+            # Create the admin cert
+            self.run_cacmd(keylog, 'leaf', 'admin',
+                           '--admin', '--region', '*', '--repo', '*')
+            # Create the Pagure cert
+            self.run_cacmd(keylog, 'leaf', 'pagure',
+                           '--read', '--write',
+                           '--region', '*', '--repo', '*')
+
+        with open(os.path.join(self.path, 'repospanner', 'spawnlog'),
+                  'w') as spawnlog:
+            # Initialize state
+            subprocess.check_call(
+                [self.repospanner_binary,
+                 '--config', cfgpath,
+                 'serve', '--spawn'],
+                stdout=spawnlog,
+                stderr=subprocess.STDOUT,
+            )
+
+        self.repospanner_runlog = open(
+            os.path.join(self.path, 'repospanner', 'runlog'), 'w')
+
+        try:
+            self.repospanner_proc = subprocess.Popen(
+                [self.repospanner_binary,
+                 '--config', cfgpath,
+                 'serve', '--debug'],
+                stdout=self.repospanner_runlog,
+                stderr=subprocess.STDOUT,
+            )
+
+            # Give repoSpanner time to start
+            time.sleep(1)
+
+            # Wait for the instance to become available
+            resp = requests.get(
+                'https://nodea.regiona.repospanner.local:%d/'
+                % configvals['gitport'],
+                verify=os.path.join(self.path, 'repospanner', 'pki', 'ca.crt'),
+                cert=(
+                    os.path.join(self.path, 'repospanner', 'pki', 'pagure.crt'),
+                    os.path.join(self.path, 'repospanner', 'pki', 'pagure.key'),
+                )
+            )
+            resp.raise_for_status()
+
+            print('repoSpanner identification: %s' % resp.text)
+        except:
+            # Make sure to clean up repoSpanner, since we did start it
+            self.tearDown()
+            raise
+
+    def tearDown(self):
+        """ Tear down the repoSpanner instance. """
+        if self.repospanner_proc:
+            # Tear down
+            self.repospanner_proc.terminate()
+            exitcode = self.repospanner_proc.wait()
+            if exitcode != 0:
+                print('repoSpanner exit code: %d' % exitcode)
+
+        if self.repospanner_runlog:
+            self.repospanner_runlog.close()
+
+        super(PagureRepoSpannerTests, self).tearDown()
+
+
+class PagureRepoSpannerTestsNewRepoDefault(PagureRepoSpannerTests):
+    config_values = {
+        'repospanner_new_repo': "'default'"
+    }
+
+    @patch('pagure.ui.app.admin_session_timedout')
+    def test_new_project(self, ast):
+        """ Test creating a new repo by default on repoSpanner works. """
+        ast.return_value = False
+
+        user = tests.FakeUser(username='foo')
+        with tests.user_set(self.app.application, user):
+            output = self.app.get('/new/')
+            self.assertEqual(output.status_code, 200)
+            output_text = output.get_data(as_text=True)
+            self.assertIn(
+                '<strong>Create new Project</strong>', output_text)
+
+            csrf_token = output_text.split(
+                'name="csrf_token" type="hidden" value="')[1].split('">')[0]
+
+            data = {
+                'name': 'project-1',
+                'description': 'Project #1',
+                'create_readme': 'y',
+                'csrf_token': csrf_token,
+            }
+
+            output = self.app.post('/new/', data=data, follow_redirects=True)
+            self.assertEqual(output.status_code, 200)
+            output_text = output.get_data(as_text=True)
+            self.assertIn(
+                '<div class="projectinfo my-3">\nProject #1',
+                output_text)
+            self.assertIn(
+                '<title>Overview - project-1 - Pagure</title>', output_text)
+            self.assertIn('Added the README', output_text)
+
+            output = self.app.get('/project-1/settings')
+            self.assertIn(
+                'This repository is on repoSpanner region default',
+                output.get_data(as_text=True))
+
+        with tests.user_set(self.app.application, tests.FakeUser(username='pingou')):
+            csrf_token = self.get_csrf()
+            data = {
+                'csrf_token': csrf_token,
+            }
+
+            output = self.app.post(
+                '/do_fork/project-1', data=data,
+                follow_redirects=True)
+            self.assertEqual(output.status_code, 200)
+            output_text = output.get_data(as_text=True)
+            self.assertIn(
+                '<div class="projectinfo my-3">\nProject #1',
+                output_text)
+            self.assertIn(
+                '<title>Overview - project-1 - Pagure</title>', output_text)
+            self.assertIn('Added the README', output_text)
+
+            output = self.app.get('/fork/pingou/project-1/settings')
+            self.assertIn(
+                'This repository is on repoSpanner region default',
+                output.get_data(as_text=True))
+
+        # Verify that only pseudo repos exist, and no on-disk repos got created
+        repodirlist = os.listdir(os.path.join(self.path, 'repos'))
+        self.assertEqual(repodirlist, ['pseudo'])
+
+
+if __name__ == '__main__':
+    unittest.main(verbosity=2)

+ 0 - 3
tests/test_stream_server.py

@@ -78,7 +78,6 @@ class StreamingServerTests(tests.Modeltests):
             title='Test issue',
             content='We should work on this',
             user='pingou',
-            ticketfolder=None
         )
 
         # Create a private issue
@@ -89,7 +88,6 @@ class StreamingServerTests(tests.Modeltests):
             content='The world can see my porn folder',
             user='pingou',
             private=True,
-            ticketfolder=None
         )
 
         # Create a PR
@@ -101,7 +99,6 @@ class StreamingServerTests(tests.Modeltests):
             branch_to='master',
             title='Test PR',
             user='pingou',
-            requestfolder=None
         )
 
     def tearDown(self):

Some files were not shown because too many files changed in this diff