#1282 Move from fake namespace to real ones
Merged 8 years ago by pingou. Opened 8 years ago by pingou.

@@ -0,0 +1,61 @@ 

+ """Add namespace to project

+ 

+ Revision ID: 350efb3f6baf

+ Revises: 1d18843a1994

+ Create Date: 2016-08-30 22:02:07.645138

+ 

+ """

+ 

+ # revision identifiers, used by Alembic.

+ revision = '350efb3f6baf'

+ down_revision = '1d18843a1994'

+ 

+ from alembic import op

+ import sqlalchemy as sa

+ 

+ try:

+     from pagure.lib import model

+ except ImportError:

+     import sys

+     sys.path.insert(0, '.')

+     from pagure.lib import model

+ 

+ 

+ def upgrade():

+     ''' Add the column namespace to the table projects.

+     '''

+     op.add_column(

+         'projects',

+         sa.Column('namespace', sa.String(255), nullable=True, index=True)

+     )

+ 

+     # Update all the existing projects

+     engine = op.get_bind()

+     Session = sa.orm.scoped_session(sa.orm.sessionmaker())

+     Session.configure(bind=engine)

+     session = Session()

+     for project in session.query(model.Project).filter(

+             model.Project.name.ilike('%/%')).all():

+         nspace, name = project.name.split('/', 1)

+         project.name = name

+         project.namespace = nspace

+         session.add(project)

+     session.commit()

+ 

+ 

+ def downgrade():

+     ''' Remove the column namespace from the table projects.

+     '''

+     # Update all the existing projects

+     engine = op.get_bind()

+     Session = sa.orm.scoped_session(sa.orm.sessionmaker())

+     Session.configure(bind=engine)

+     session = Session()

+     for project in session.query(model.Project).filter(

+             model.Project.namespace != None).all():

+         if project.namespace.strip():

+             project.name = '%s/%s' % (project.namespace, project.name)

+             session.add(project)

+     session.commit()

+ 

+     op.drop_column('projects', 'namespace')

@@ -24,6 +24,6 @@ 

  

  

  def downgrade():

-     ''' Remove the column merge_status from the table projects.

+     ''' Remove the column url from the table projects.

      '''

      op.drop_column('projects', 'url')

@@ -67,13 +67,17 @@ 

          pr_id = data['pr']['id']

          branch = data['pr']['branch_from']

          projectname = data['pr']['project']['name']

+         namespace = data['pr']['project'].get('namespace')

  

          username = None

          if data['pr'].get('parent'):

              username = data['pr']['project']['user']['user']

  

          project = pagure.lib.get_project(

-             session=pagure.SESSION, name=projectname, user=username)

+             session=pagure.SESSION,

+             name=projectname,

+             user=username,

+             namespace=namespace)

  

          if not project:

              LOG.warning(

file modified
+14 -15
@@ -80,18 +80,6 @@ 

      ]

  

  

- class RepoConverter(BaseConverter):

- 

-     """Like the default :class:`UnicodeConverter`, but it allows matching

-     a single slash.

-     :param map: the :class:`Map`.

-     """

-     regex = r'[^/]*(/[^/]+)?'

-     # weight = 200

- 

- 

- APP.url_map.converters['repo'] = RepoConverter

- 

  import pagure.doc_utils

  import pagure.forms

  import pagure.lib
@@ -355,11 +343,14 @@ 

      if justlogedout:

          flask.session['_justloggedout'] = None

  

-     def is_watching(reponame, username=None):

+     def is_watching(reponame, username=None, namespace=None):

          watch = False

          if authenticated():

              watch = pagure.lib.is_watching(

-                 SESSION, flask.g.fas_user, reponame, repouser=username)

+                 SESSION, flask.g.fas_user,

+                 reponame,

+                 repouser=username,

+                 namespace=namespace)

          return watch

  

      return dict(
@@ -393,12 +384,20 @@ 

      # Check if there is a `repo` and an `username`

      repo = args.get('repo')

      username = args.get('username')

+     namespace = args.get('namespace')

  

      # If there isn't a `repo` in the URL path, or if there is but the

      # endpoint called is part of the API, just don't do anything

      if repo:

          flask.g.repo = pagure.lib.get_project(

-             SESSION, repo, user=username)

+             SESSION, repo, user=username, namespace=namespace)

+ 

+         if not flask.g.repo \

+             and APP.config.get('OLD_VIEW_COMMIT_ENABLED', False) \

+             and len(repo) == 40:

+             return flask.redirect(flask.url_for(

+                 'view_commit', repo=namespace, commitid=repo,

+                 username=username, namespace=None))

  

          if flask.g.repo is None:

              flask.abort(404, 'Project not found')

file modified
+11 -5
@@ -21,12 +21,17 @@ 

  from pagure.api import API, APIERROR, api_method

  

  

- @API.route('/ci/jenkins/<repo:repo>/<pagure_ci_token>/build-finished',

+ @API.route('/ci/jenkins/<repo>/<pagure_ci_token>/build-finished',

             methods=['POST'])

- @API.route('/ci/jenkins/forks/<username>/<repo:repo>/'

+ @API.route('/ci/jenkins/<namespace>/<repo>/<pagure_ci_token>/build-finished',

+            methods=['POST'])

+ @API.route('/ci/jenkins/forks/<username>/<repo>/'

+            '<pagure_ci_token>/build-finished', methods=['POST'])

+ @API.route('/ci/jenkins/forks/<username>/<namespace>/<repo>/'

             '<pagure_ci_token>/build-finished', methods=['POST'])

  @api_method

- def jenkins_ci_notification(repo, pagure_ci_token, username=None):

+ def jenkins_ci_notification(

+         repo, pagure_ci_token, username=None, namespace=None):

      """

      Jenkins Build Notification

      --------------------------
@@ -35,11 +40,12 @@ 

  

      ::

  

-         POST /api/0/ci/jenkins/<token>/build-finished

+         POST /api/0/ci/jenkins/<repo>/<token>/build-finished

  

      """

  

-     project = pagure.lib.get_project(SESSION, repo, user=username)

+     project = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

      if repo is None:

          raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)

  

file modified
+57 -12
@@ -20,9 +20,11 @@ 

  

  

  @API.route('/<repo>/pull-requests')

+ @API.route('/<namespace>/<repo>/pull-requests')

  @API.route('/fork/<username>/<repo>/pull-requests')

+ @API.route('/fork/<username>/<namespace>/<repo>/pull-requests')

  @api_method

- def api_pull_request_views(repo, username=None):

+ def api_pull_request_views(repo, username=None, namespace=None):

      """

      List project's Pull-Requests

      ----------------------------
@@ -31,10 +33,12 @@ 

      ::

  

          GET /api/0/<repo>/pull-requests

+         GET /api/0/<namespace>/<repo>/pull-requests

  

      ::

  

          GET /api/0/fork/<username>/<repo>/pull-requests

+         GET /api/0/fork/<username>/<namespace>/<repo>/pull-requests

  

      Parameters

      ^^^^^^^^^^
@@ -119,7 +123,8 @@ 

  

      """

  

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

  

      if repo is None:

          raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
@@ -172,9 +177,11 @@ 

  

  

  @API.route('/<repo>/pull-request/<int:requestid>')

+ @API.route('/<namespace>/<repo>/pull-request/<int:requestid>')

  @API.route('/fork/<username>/<repo>/pull-request/<int:requestid>')

+ @API.route('/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>')

  @api_method

- def api_pull_request_view(repo, requestid, username=None):

+ def api_pull_request_view(repo, requestid, username=None, namespace=None):

      """

      Pull-request information

      ------------------------
@@ -183,10 +190,12 @@ 

      ::

  

          GET /api/0/<repo>/pull-request/<request id>

+         GET /api/0/<namespace>/<repo>/pull-request/<request id>

  

      ::

  

          GET /api/0/fork/<username>/<repo>/pull-request/<request id>

+         GET /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id>

  

      Sample response

      ^^^^^^^^^^^^^^^
@@ -238,7 +247,8 @@ 

  

      """

  

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

  

      if repo is None:

          raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
@@ -258,11 +268,17 @@ 

  

  

  @API.route('/<repo>/pull-request/<int:requestid>/merge', methods=['POST'])

+ @API.route(

+     '/<namespace>/<repo>/pull-request/<int:requestid>/merge',

+     methods=['POST'])

  @API.route('/fork/<username>/<repo>/pull-request/<int:requestid>/merge',

             methods=['POST'])

+ @API.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/merge',

+     methods=['POST'])

  @api_login_required(acls=['pull_request_merge'])

  @api_method

- def api_pull_request_merge(repo, requestid, username=None):

+ def api_pull_request_merge(repo, requestid, username=None, namespace=None):

      """

      Merge a pull-request

      --------------------
@@ -271,10 +287,12 @@ 

      ::

  

          POST /api/0/<repo>/pull-request/<request id>/merge

+         POST /api/0/<namespace>/<repo>/pull-request/<request id>/merge

  

      ::

  

          POST /api/0/fork/<username>/<repo>/pull-request/<request id>/merge

+         POST /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id>/merge

  

      Sample response

      ^^^^^^^^^^^^^^^
@@ -288,7 +306,8 @@ 

      """

      output = {}

  

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

  

      if repo is None:

          raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
@@ -336,11 +355,17 @@ 

  

  

  @API.route('/<repo>/pull-request/<int:requestid>/close', methods=['POST'])

+ @API.route(

+     '/<namespace>/<repo>/pull-request/<int:requestid>/close',

+     methods=['POST'])

  @API.route('/fork/<username>/<repo>/pull-request/<int:requestid>/close',

             methods=['POST'])

+ @API.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/close',

+     methods=['POST'])

  @api_login_required(acls=['pull_request_close'])

  @api_method

- def api_pull_request_close(repo, requestid, username=None):

+ def api_pull_request_close(repo, requestid, username=None, namespace=None):

      """

      Close a pull-request

      --------------------
@@ -349,10 +374,12 @@ 

      ::

  

          POST /api/0/<repo>/pull-request/<request id>/close

+         POST /api/0/<namespace>/<repo>/pull-request/<request id>/close

  

      ::

  

          POST /api/0/fork/<username>/<repo>/pull-request/<request id>/close

+         POST /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id>/close

  

      Sample response

      ^^^^^^^^^^^^^^^
@@ -366,7 +393,8 @@ 

      """

      output = {}

  

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

  

      if repo is None:

          raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
@@ -405,11 +433,17 @@ 

  

  @API.route('/<repo>/pull-request/<int:requestid>/comment',

             methods=['POST'])

+ @API.route('/<namespace>/<repo>/pull-request/<int:requestid>/comment',

+            methods=['POST'])

  @API.route('/fork/<username>/<repo>/pull-request/<int:requestid>/comment',

             methods=['POST'])

+ @API.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/comment',

+     methods=['POST'])

  @api_login_required(acls=['pull_request_comment'])

  @api_method

- def api_pull_request_add_comment(repo, requestid, username=None):

+ def api_pull_request_add_comment(

+         repo, requestid, username=None, namespace=None):

      """

      Comment on a pull-request

      -------------------------
@@ -418,10 +452,12 @@ 

      ::

  

          POST /api/0/<repo>/pull-request/<request id>/comment

+         POST /api/0/<namespace>/<repo>/pull-request/<request id>/comment

  

      ::

  

          POST /api/0/fork/<username>/<repo>/pull-request/<request id>/comment

+         POST /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id>/comment

  

      Input

      ^^^^^
@@ -460,7 +496,8 @@ 

          }

  

      """

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

      output = {}

  

      if repo is None:
@@ -518,11 +555,16 @@ 

  

  @API.route('/<repo>/pull-request/<int:requestid>/flag',

             methods=['POST'])

+ @API.route('/<namespace>/<repo>/pull-request/<int:requestid>/flag',

+            methods=['POST'])

  @API.route('/fork/<username>/<repo>/pull-request/<int:requestid>/flag',

             methods=['POST'])

+ @API.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/flag',

+     methods=['POST'])

  @api_login_required(acls=['pull_request_flag'])

  @api_method

- def api_pull_request_add_flag(repo, requestid, username=None):

+ def api_pull_request_add_flag(repo, requestid, username=None, namespace=None):

      """

      Flag a pull-request

      -------------------
@@ -531,10 +573,12 @@ 

      ::

  

          POST /api/0/<repo>/pull-request/<request id>/flag

+         POST /api/0/<namespace>/<repo>/pull-request/<request id>/flag

  

      ::

  

          POST /api/0/fork/<username>/<repo>/pull-request/<request id>/flag

+         POST /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id>/flag

  

      Input

      ^^^^^
@@ -594,7 +638,8 @@ 

          }

  

      """

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

      output = {}

  

      if repo is None:

file modified
+60 -15
@@ -22,10 +22,12 @@ 

  

  

  @API.route('/<repo>/new_issue', methods=['POST'])

+ @API.route('/<namespace>/<repo>/new_issue', methods=['POST'])

  @API.route('/fork/<username>/<repo>/new_issue', methods=['POST'])

+ @API.route('/fork/<username>/<namespace>/<repo>/new_issue', methods=['POST'])

  @api_login_required(acls=['issue_create'])

  @api_method

- def api_new_issue(repo, username=None):

+ def api_new_issue(repo, username=None, namespace=None):

      """

      Create a new issue

      ------------------
@@ -34,10 +36,12 @@ 

      ::

  

          POST /api/0/<repo>/new_issue

+         POST /api/0/<namespace>/<repo>/new_issue

  

      ::

  

          POST /api/0/fork/<username>/<repo>/new_issue

+         POST /api/0/fork/<username>/<namespace>/<repo>/new_issue

  

      Input

      ^^^^^
@@ -65,7 +69,8 @@ 

          }

  

      """

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

      output = {}

  

      if repo is None:
@@ -140,11 +145,13 @@ 

      return jsonout

  

  

- @API.route('/<repo>/issues')

+ @API.route('/<namespace>/<repo>/issues')

  @API.route('/fork/<username>/<repo>/issues')

+ @API.route('/<repo>/issues')

+ @API.route('/fork/<username>/<namespace>/<repo>/issues')

  @api_login_optional()

  @api_method

- def api_view_issues(repo, username=None):

+ def api_view_issues(repo, username=None, namespace=None):

      """

      List project's issues

      ---------------------
@@ -153,10 +160,12 @@ 

      ::

  

          GET /api/0/<repo>/issues

+         GET /api/0/<namespace>/<repo>/issues

  

      ::

  

          GET /api/0/fork/<username>/<repo>/issues

+         GET /api/0/fork/<username>/<namespace>/<repo>/issues

  

      Parameters

      ^^^^^^^^^^
@@ -225,7 +234,8 @@ 

  

      """

  

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

  

      if repo is None:

          raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
@@ -285,10 +295,12 @@ 

  

  

  @API.route('/<repo>/issue/<issueid>')

+ @API.route('/<namespace>/<repo>/issue/<issueid>')

  @API.route('/fork/<username>/<repo>/issue/<issueid>')

+ @API.route('/fork/<username>/<namespace>/<repo>/issue/<issueid>')

  @api_login_optional()

  @api_method

- def api_view_issue(repo, issueid, username=None):

+ def api_view_issue(repo, issueid, username=None, namespace=None):

      """

      Issue information

      -----------------
@@ -297,10 +309,12 @@ 

      ::

  

          GET /api/0/<repo>/issue/<issue id>

+         GET /api/0/<namespace>/<repo>/issue/<issue id>

  

      ::

  

          GET /api/0/fork/<username>/<repo>/issue/<issue id>

+         GET /api/0/fork/<username>/<namespace>/<repo>/issue/<issue id>

  

      The identifier provided can be either the unique identifier or the

      regular identifier used in the UI (for example ``24`` in
@@ -334,7 +348,8 @@ 

      if str(comments).lower() in ['0', 'False']:

          comments = False

  

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

  

      if repo is None:

          raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
@@ -372,10 +387,15 @@ 

  

  

  @API.route('/<repo>/issue/<issueid>/comment/<int:commentid>')

+ @API.route('/<namespace>/<repo>/issue/<issueid>/comment/<int:commentid>')

  @API.route('/fork/<username>/<repo>/issue/<issueid>/comment/<int:commentid>')

+ @API.route(

+     '/fork/<username>/<namespace>/<repo>/issue/<issueid>/'

+     'comment/<int:commentid>')

  @api_login_optional()

  @api_method

- def api_view_issue_comment(repo, issueid, commentid, username=None):

+ def api_view_issue_comment(

+         repo, issueid, commentid, username=None, namespace=None):

      """

      Comment of an issue

      --------------------
@@ -384,10 +404,12 @@ 

      ::

  

          GET /api/0/<repo>/issue/<issue id>/comment/<comment id>

+         GET /api/0/<namespace>/<repo>/issue/<issue id>/comment/<comment id>

  

      ::

  

          GET /api/0/fork/<username>/<repo>/issue/<issue id>/comment/<comment id>

+         GET /api/0/fork/<username>/<namespace>/<repo>/issue/<issue id>/comment/<comment id>

  

      The identifier provided can be either the unique identifier or the

      regular identifier used in the UI (for example ``24`` in
@@ -413,7 +435,8 @@ 

  

      """

  

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

  

      if repo is None:

          raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
@@ -460,11 +483,15 @@ 

  

  

  @API.route('/<repo>/issue/<int:issueid>/status', methods=['POST'])

+ @API.route('/<namespace>/<repo>/issue/<int:issueid>/status', methods=['POST'])

  @API.route(

      '/fork/<username>/<repo>/issue/<int:issueid>/status', methods=['POST'])

+ @API.route(

+     '/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/status',

+     methods=['POST'])

  @api_login_required(acls=['issue_change_status'])

  @api_method

- def api_change_status_issue(repo, issueid, username=None):

+ def api_change_status_issue(repo, issueid, username=None, namespace=None):

      """

      Change issue status

      -------------------
@@ -473,10 +500,12 @@ 

      ::

  

          POST /api/0/<repo>/issue/<issue id>/status

+         POST /api/0/<namespace>/<repo>/issue/<issue id>/status

  

      ::

  

          POST /api/0/fork/<username>/<repo>/issue/<issue id>/status

+         POST /api/0/fork/<username>/<namespace>/<repo>/issue/<issue id>/status

  

      Input

      ^^^^^
@@ -497,7 +526,9 @@ 

          }

  

      """

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

+ 

      output = {}

  

      if repo is None:
@@ -556,11 +587,15 @@ 

  

  

  @API.route('/<repo>/issue/<int:issueid>/comment', methods=['POST'])

+ @API.route('/<namespace>/<repo>/issue/<int:issueid>/comment', methods=['POST'])

  @API.route(

      '/fork/<username>/<repo>/issue/<int:issueid>/comment', methods=['POST'])

+ @API.route(

+     '/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/comment',

+     methods=['POST'])

  @api_login_required(acls=['issue_comment'])

  @api_method

- def api_comment_issue(repo, issueid, username=None):

+ def api_comment_issue(repo, issueid, username=None, namespace=None):

      """

      Comment to an issue

      -------------------
@@ -569,10 +604,12 @@ 

      ::

  

          POST /api/0/<repo>/issue/<issue id>/comment

+         POST /api/0/<namespace>/<repo>/issue/<issue id>/comment

  

      ::

  

          POST /api/0/fork/<username>/<repo>/issue/<issue id>/comment

+         POST /api/0/fork/<username>/<namespace>/<repo>/issue/<issue id>/comment

  

      Input

      ^^^^^
@@ -594,7 +631,8 @@ 

          }

  

      """

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

      output = {}

  

      if repo is None:
@@ -647,11 +685,15 @@ 

  

  

  @API.route('/<repo>/issue/<int:issueid>/assign', methods=['POST'])

+ @API.route('/<namespace>/<repo>/issue/<int:issueid>/assign', methods=['POST'])

  @API.route(

      '/fork/<username>/<repo>/issue/<int:issueid>/assign', methods=['POST'])

+ @API.route(

+     '/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/assign',

+     methods=['POST'])

  @api_login_required(acls=['issue_assign'])

  @api_method

- def api_assign_issue(repo, issueid, username=None):

+ def api_assign_issue(repo, issueid, username=None, namespace=None):

      """

      Assign an issue

      ---------------
@@ -660,10 +702,12 @@ 

      ::

  

          POST /api/0/<repo>/issue/<issue id>/assign

+         POST /api/0/<namespace>/<repo>/issue/<issue id>/assign

  

      ::

  

          POST /api/0/fork/<username>/<repo>/issue/<issue id>/assign

+         POST /api/0/fork/<username>/<namespace>/<repo>/issue/<issue id>/assign

  

      Input

      ^^^^^
@@ -685,7 +729,8 @@ 

          }

  

      """

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

      output = {}

  

      if repo is None:

file modified
+28 -4
@@ -20,9 +20,11 @@ 

  

  

  @API.route('/<repo>/git/tags')

+ @API.route('/<namespace>/<repo>/git/tags')

  @API.route('/fork/<username>/<repo>/git/tags')

+ @API.route('/fork/<username>/<namespace>/<repo>/git/tags')

  @api_method

- def api_git_tags(repo, username=None):

+ def api_git_tags(repo, username=None, namespace=None):

      """

      Project git tags

      ----------------
@@ -31,10 +33,12 @@ 

      ::

  

          GET /api/0/<repo>/git/tags

+         GET /api/0/<namespace>/<repo>/git/tags

  

      ::

  

          GET /api/0/fork/<username>/<repo>/git/tags

+         GET /api/0/fork/<username>/<namespace>/<repo>/git/tags

  

      Sample response

      ^^^^^^^^^^^^^^^
@@ -47,7 +51,8 @@ 

          }

  

      """

-     repo = pagure.lib.get_project(SESSION, repo, user=username)

+     repo = pagure.lib.get_project(

+         SESSION, repo, user=username, namespace=namespace)

  

      if repo is None:

          raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
@@ -194,6 +199,9 @@ 

      | ``description``  | string  | Mandatory    | | A short description of  |

      |                  |         |              |   the new project.        |

      +------------------+---------+--------------+---------------------------+

+     | ``namespace``    | string  | Optional     | | The namespace of the    |

+     |                  |         |              |   project to fork.        |

+     +------------------+---------+--------------+---------------------------+

      | ``url``          | string  | Optional     | | An url providing more   |

      |                  |         |              |   information about the   |

      |                  |         |              |   project.                |
@@ -224,10 +232,18 @@ 

          raise pagure.exceptions.APIError(

              404, error_code=APIERROR.ENEWPROJECTDISABLED)

  

-     form = pagure.forms.ProjectForm(csrf_enabled=False)

+     namespaces = APP.config['ALLOWED_PREFIX'][:]

+     if user:

+         namespaces.extend([grp for grp in user.groups])

+ 

+     form = pagure.forms.ProjectForm(

+         namespaces=namespaces, csrf_enabled=False)

      if form.validate_on_submit():

          name = form.name.data

          description = form.description.data

+         namespace = form.namespace.data

+         if namespace:

+             namespace = namespace.strip()

          url = form.url.data

          avatar_email = form.avatar_email.data

          create_readme = form.create_readme.data
@@ -236,6 +252,7 @@ 

              message = pagure.lib.new_project(

                  SESSION,

                  name=name,

+                 namespace=namespace,

                  description=description,

                  url=url,

                  avatar_email=avatar_email,
@@ -292,6 +309,9 @@ 

      | ``repo``         | string  | Mandatory    | | The name of the project |

      |                  |         |              |   to fork.                |

      +------------------+---------+--------------+---------------------------+

+     | ``namespace``    | string  | Optional     | | The namespace of the    |

+     |                  |         |              |   project to fork.        |

+     +------------------+---------+--------------+---------------------------+

      | ``username``     | string  | Optional     | | The username of the user|

      |                  |         |              |   of the fork.            |

      +------------------+---------+--------------+---------------------------+
@@ -313,8 +333,12 @@ 

      if form.validate_on_submit():

          repo = form.repo.data

          username = form.username.data or None

+         namespace = form.namespace.data.strip() or None

+         if namespace == 'None':

+             namespace = None

  

-         repo = pagure.lib.get_project(SESSION, repo, user=username)

+         repo = pagure.lib.get_project(

+             SESSION, repo, user=username, namespace=namespace)

          if repo is None:

              raise pagure.exceptions.APIError(

                  404, error_code=APIERROR.ENOPROJECT)

file modified
+24 -2
@@ -25,7 +25,7 @@ 

  STRICT_REGEX = '^[a-zA-Z0-9-_]+$'

  TAGS_REGEX = '^[a-zA-Z0-9-_, .]+$'

  PROJECT_NAME_REGEX = \

-     '^[a-zA-z0-9_][a-zA-Z0-9-_]*(/?[a-zA-z0-9_][a-zA-Z0-9-_]+)?$'

+     '^[a-zA-z0-9_][a-zA-Z0-9-_]*$'

  

  

  def file_virus_validator(form, field):
@@ -91,6 +91,24 @@ 

          'Create README',

          [wtforms.validators.optional()],

      )

+     namespace = wtforms.SelectField(

+         'Project Namespace',

+         [wtforms.validators.optional()],

+         choices=[],

+         coerce=lambda val: unicode(val) if val else None

+     )

+ 

+     def __init__(self, *args, **kwargs):

+         """ Calls the default constructor with the normal argument but

+         uses the list of collection provided to fill the choices of the

+         drop-down list.

+         """

+         super(ProjectForm, self).__init__(*args, **kwargs)

+         if 'namespaces' in kwargs:

+             self.namespace.choices = [

+                 (namespace, namespace) for namespace in kwargs['namespaces']

+             ]

+             self.namespace.choices.insert(0, ('', ''))

  

  

  class IssueFormSimplied(wtf.Form):
@@ -474,9 +492,13 @@ 

  class ForkRepoForm(wtf.Form):

      ''' Form to fork a project in the API. '''

      repo = wtforms.TextField(

-         'The project name <span class="error">*</span>',

+         'The project name',

          [wtforms.validators.Required()]

      )

      username = wtforms.TextField(

          'User who forked the project',

          [wtforms.validators.optional()])

+     namespace = wtforms.TextField(

+         'The project namespace',

+         [wtforms.validators.optional()]

+     )

@@ -50,9 +50,12 @@ 

  

      revs = pagure.lib.git.get_revs_between(

          oldrev, newrev, abspath, refname, forced=forced)

+ 

      project_name = pagure.lib.git.get_repo_name(abspath)

      username = pagure.lib.git.get_username(abspath)

-     project = pagure.lib.get_project(pagure.SESSION, project_name, username)

+     namespace = pagure.lib.git.get_repo_namespace(abspath)

+     project = pagure.lib.get_project(

+         pagure.SESSION, project_name, username, namespace=namespace)

      if not project:

          project = project_name

  

@@ -1,8 +1,7 @@ 

  #! /usr/bin/env python2

  

  

- """Pagure specific hook to add comment on issues if the commits fixes or

- relates to an issue.

+ """Pagure specific hook to block non-fastforward pushes.

  """

  

  import os
@@ -27,14 +26,18 @@ 

  

  def run_as_pre_receive_hook():

      reponame = pagure.lib.git.get_repo_name(abspath)

+     namespace = pagure.lib.git.get_repo_namespace(abspath)

      username = pagure.lib.git.get_username(abspath)

      if pagure.APP.config.get('HOOK_DEBUG', False):

-         print 'repo:', reponame

-         print 'user:', username

+         print 'repo:     ', reponame

+         print 'user:     ', username

+         print 'namspaces:', namespace

  

-     repo = pagure.lib.get_project(pagure.SESSION, reponame, user=username)

+     repo = pagure.lib.get_project(

+         pagure.SESSION, reponame, user=username, namespace=namespace)

      if not repo:

-         print 'Unknown repo %s of username: %s' % (reponame, username)

+         print 'Unknown repo %s of username: %s in namespace %s' % (

+             reponame, username, namespace)

          sys.exit(1)

  

      plugin = pagure.ui.plugins.get_plugin('Block non fast-forward pushes')

@@ -41,6 +41,7 @@ 

                  pagure.SESSION,

                  pagure.lib.git.get_repo_name(abspath),

                  pagure.lib.git.get_username(abspath),

+                 pagure.lib.git.get_repo_namespace(abspath),

                  line,

                  'fixes',

                  include_prs=True):
@@ -51,6 +52,7 @@ 

                  pagure.SESSION,

                  pagure.lib.git.get_repo_name(abspath),

                  pagure.lib.git.get_username(abspath),

+                 pagure.lib.git.get_repo_namespace(abspath),

                  line,

                  'relates'):

              relates_commit(commitid, issue, pagure.APP.config.get('APP_URL'))

@@ -67,7 +67,8 @@ 

  

      reponame = pagure.lib.git.get_repo_name(abspath)

      username = pagure.lib.git.get_username(abspath)

-     print 'repo:', reponame, username

+     namespace = pagure.lib.git.get_repo_namespace(abspath)

+     print 'repo:', reponame, username, namespace

  

      for filename in file_list:

          print 'To load: %s' % filename
@@ -84,6 +85,7 @@ 

              pagure.lib.git.update_request_from_git(

                  pagure.SESSION,

                  reponame=reponame,

+                 namespace=namespace,

                  username=username,

                  request_uid=filename,

                  json_data=json_data,

@@ -72,7 +72,8 @@ 

  

      reponame = pagure.lib.git.get_repo_name(abspath)

      username = pagure.lib.git.get_username(abspath)

-     print 'repo:', reponame, username

+     namespace = pagure.lib.git.get_repo_namespace(abspath)

+     print 'repo:', reponame, username, namespace

  

      for filename in file_list:

          print 'To load: %s' % filename
@@ -89,6 +90,7 @@ 

              pagure.lib.git.update_ticket_from_git(

                  pagure.SESSION,

                  reponame=reponame,

+                 namespace=namespace,

                  username=username,

                  issue_uid=filename,

                  json_data=json_data)

@@ -29,11 +29,14 @@ 

  def run_as_post_receive_hook():

      reponame = pagure.lib.git.get_repo_name(abspath)

      username = pagure.lib.git.get_username(abspath)

+     namespace = pagure.lib.git.get_repo_namespace(abspath)

      if pagure.APP.config.get('HOOK_DEBUG', False):

-         print 'repo:', reponame

-         print 'user:', username

+         print 'repo:     ', reponame

+         print 'user:     ', username

+         print 'namespace:', namespace

  

-     repo = pagure.lib.get_project(pagure.SESSION, reponame, user=username)

+     repo = pagure.lib.get_project(

+         pagure.SESSION, reponame, user=username, namespace=namespace)

      if not repo:

          print 'Unknown repo %s of username: %s' % (reponame, username)

          sys.exit(1)

file modified
+34 -14
@@ -1007,10 +1007,11 @@ 

                  gitfolder, docfolder, ticketfolder, requestfolder,

                  description=None, url=None, avatar_email=None,

                  parent_id=None, add_readme=False, userobj=None,

-                 prevent_40_chars=False):

+                 prevent_40_chars=False, namespace=None):

      ''' Create a new project based on the information provided.

      '''

-     if name in blacklist:

+     if name in blacklist or (

+             namespace and '%s/%s' % (namespace, name) in blacklist):

          raise pagure.exceptions.RepoExistsException(

              'No project "%s" are allowed to be created due to potential '

              'conflicts in URLs with pagure itself' % name
@@ -1019,15 +1020,14 @@ 

      user_obj = get_user(session, user)

      allowed_prefix = allowed_prefix + [grp for grp in user_obj.groups]

  

-     first_part, _, second_part = name.partition('/')

-     if second_part and first_part not in allowed_prefix:

+     if namespace and namespace not in allowed_prefix:

          raise pagure.exceptions.PagureException(

-             'The prefix of your project must be in the list of allowed '

-             'prefixes set by the admins of this pagure instance, or the name '

-             'of a group of which you are a member.'

+             'The namespace of your project must be in the list of allowed '

+             'namespaces set by the admins of this pagure instance, or the '

+             'name of a group of which you are a member.'

          )

  

-     if len(second_part) == 40 and prevent_40_chars:

+     if len(name) == 40 and prevent_40_chars:

          # We must block project with a name <foo>/<bar> where the length

          # of <bar> is exactly 40 characters long as this would otherwise

          # conflict with the old URL schema used for commit that was
@@ -1039,14 +1039,19 @@ 

              'the `/`'

          )

  

-     gitrepo = os.path.join(gitfolder, '%s.git' % name)

+     path = name

+     if namespace:

+         path = '%s/%s' % (namespace, name)

+ 

+     gitrepo = os.path.join(gitfolder, '%s.git' % path)

      if os.path.exists(gitrepo):

          raise pagure.exceptions.RepoExistsException(

-             'The project repo "%s" already exists' % name

+             'The project repo "%s" already exists' % path

          )

  

      project = model.Project(

          name=name,

+         namespace=namespace,

          description=description if description else None,

          url=url if url else None,

          avatar_email=avatar_email if avatar_email else None,
@@ -1486,7 +1491,8 @@ 

  

  

  def search_projects(

-         session, username=None, fork=None, tags=None, pattern=None,

+         session, username=None,

+         fork=None, tags=None, namespace=None, pattern=None,

          start=None, limit=None, count=False, sort=None):

      '''List existing projects

      '''
@@ -1570,6 +1576,12 @@ 

              projects = projects.filter(

                  model.Project.name == pattern

              )

+ 

+     if namespace:

+         projects = project.filter(

+             model.Project.namespace == namespace

+         )

+ 

      query = session.query(

          model.Project

      ).filter(
@@ -1601,13 +1613,15 @@ 

          return query.all()

  

  

- def get_project(session, name, user=None):

+ def get_project(session, name, user=None, namespace=None):

      '''Get a project from the database

      '''

      query = session.query(

          model.Project

      ).filter(

          model.Project.name == name

+     ).filter(

+         model.Project.namespace == namespace

      )

  

      if user is not None:
@@ -2914,7 +2928,7 @@ 

      return msg_success

  

  

- def is_watching(session, user, reponame, repouser=None):

+ def is_watching(session, user, reponame, repouser=None, namespace=None):

      ''' Check user watching the project. '''

  

      if user is None:
@@ -2947,12 +2961,18 @@ 

              model.Project.is_fork == False

          )

  

+     if namespace is not None:

+         query = query.filter(

+             model.Project.namespace == namespace

+         )

+ 

      watcher = query.first()

  

      if watcher:

          return watcher.watch

  

-     project = pagure.lib.get_project(session, reponame, user=repouser)

+     project = pagure.lib.get_project(

+         session, reponame, user=repouser, namespace=namespace)

      if not project:

          return False

  

file modified
+35 -11
@@ -414,7 +414,7 @@ 

  

  

  def update_ticket_from_git(

-         session, reponame, username, issue_uid, json_data):

+         session, reponame, namespace,  username, issue_uid, json_data):

      """ Update the specified issue (identified by its unique identifier)

      with the data present in the json blob provided.

  
@@ -426,10 +426,12 @@ 

  

      """

  

-     repo = pagure.lib.get_project(session, reponame, user=username)

+     repo = pagure.lib.get_project(

+         session, reponame, user=username, namespace=namespace)

      if not repo:

          raise pagure.exceptions.PagureException(

-             'Unknown repo %s of username: %s' % (reponame, username))

+             'Unknown repo %s of username: %s in namespace: %s' % (

+                 reponame, username, namespace))

  

      user = get_user_from_json(session, json_data)

  
@@ -511,7 +513,7 @@ 

  

  

  def update_request_from_git(

-         session, reponame, username, request_uid, json_data,

+         session, reponame, namespace, username, request_uid, json_data,

          gitfolder, docfolder, ticketfolder, requestfolder):

      """ Update the specified request (identified by its unique identifier)

      with the data present in the json blob provided.
@@ -526,10 +528,12 @@ 

  

      """

  

-     repo = pagure.lib.get_project(session, reponame, user=username)

+     repo = pagure.lib.get_project(

+         session, reponame, user=username, namespace=namespace)

      if not repo:

          raise pagure.exceptions.PagureException(

-             'Unknown repo %s of username: %s' % (reponame, username))

+             'Unknown repo %s of username: %s in namespace: %s' % (

+                 reponame, username, namespace))

  

      user = get_user_from_json(session, json_data)

  
@@ -915,19 +919,39 @@ 

  def get_repo_name(abspath):

      ''' Return the name of the git repo based on its path.

      '''

-     repo_name = '.'.join(abspath.split(os.path.sep)[-1].split('.')[:-1])

+     repo_name = '.'.join(

+         abspath.rsplit(os.path.sep, 1)[-1].rsplit('.', 1)[:-1])

      return repo_name

  

  

+ def get_repo_namespace(abspath):

+     ''' Return the name of the git repo based on its path.

+     '''

+     namespace = None

+ 

+     short_path = os.path.abspath(abspath).replace(

+         os.path.abspath(pagure.APP.config['GIT_FOLDER']),

+         ''

+     ).strip('/')

+ 

+     if short_path.startswith('forks/'):

+         username, projectname = short_path.split('forks/', 1)[1].split('/', 1)

+     else:

+         projectname = short_path

+ 

+     if '/' in projectname:

+         namespace = projectname.rsplit('/', 1)[0]

+ 

+     return namespace

+ 

+ 

  def get_username(abspath):

      ''' Return the username of the git repo based on its path.

      '''

      username = None

      repo = os.path.abspath(os.path.join(abspath, '..'))

-     if pagure.APP.config['FORK_FOLDER'] in repo:

-         username = repo.split(pagure.APP.config['FORK_FOLDER'])[1]

-         if username.startswith('/'):

-             username = username[1:]

+     if '/forks/' in repo:

+         username = repo.split('/forks/', 1)[1].split('/', 1)[0]

      return username

  

  

file modified
+4 -3
@@ -40,8 +40,8 @@ 

  ]

  

  

- def get_relation(session, reponame, username, text, reftype='relates',

-                  include_prs=False):

+ def get_relation(session, reponame, username, namespace, text,

+                  reftype='relates', include_prs=False):

      ''' For a given text, searches using regex if the text contains

      reference to another issue in this project or another one.

  
@@ -57,7 +57,8 @@ 

  

      '''

  

-     repo = pagure.lib.get_project(session, reponame, user=username)

+     repo = pagure.lib.get_project(

+         session, reponame, user=username, namespace=namespace)

      if not repo:

          return []

  

file modified
+4
@@ -301,6 +301,7 @@ 

          ),

          nullable=False,

          index=True)

+     namespace = sa.Column(sa.String(255), nullable=True, index=True)

      name = sa.Column(sa.String(255), nullable=False, index=True)

      description = sa.Column(sa.Text, nullable=True)

      url = sa.Column(sa.Text, nullable=True)
@@ -358,6 +359,8 @@ 

          project forked, otherwise it returns the project name.

          '''

          str_name = self.name

+         if self.namespace:

+             str_name = '%s/%s' % (self.namespace, str_name)

          if self.is_fork:

              str_name = "forks/%s/%s" % (self.user.user, str_name)

          return str_name
@@ -479,6 +482,7 @@ 

              'id': self.id,

              'name': self.name,

              'description': self.description,

+             'namespace': self.namespace,

              'parent': self.parent.to_json(

                  public=public, api=api) if self.parent else None,

              'date_created': self.date_created.strftime('%s'),

@@ -189,8 +189,11 @@ 

        {% if g.repo_admin or (

          g.fas_user and g.fas_user.username == comment.user.username) %}

        <a class="btn btn-primary btn-sm" href="{{

-           url_for('edit_issue', username=username,

-                   repo=repo.name, issueid=issueid)

+           url_for('edit_issue',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace,

+                   issueid=issueid)

            }}" title="Edit this issue">

        <span class="oi" data-glyph="pencil"></span></a>

        {% endif %}

@@ -1,10 +1,8 @@ 

  {% macro render_row(items) -%}

      {% for repo in items %}

-         {% if repo.is_fork %}

-         {% set url = url_for('view_repo', username=repo.user.username, repo=repo.name) %}

-         {% else %}

-         {% set url = url_for('view_repo', repo=repo.name) %}

-         {% endif %}

+       {% set url = url_for('view_repo',

+         username=repo.user.username if repo.is_fork else None,

+         repo=repo.name, namespace=repo.namespace) %}

    <div class="col-lg-4 col-md-6">

      <div class="project_wrapper m-b-1">

        {% if repo.avatar_email %}
@@ -13,14 +11,28 @@ 

          <div class="projecticon pull-xs-left"><span class="oi" data-glyph="document"></span></div>

        {% endif %}

        <a class="project_link logo_link" href="{{ url }}">

-         <div class="repo_name"><strong>{{ repo.name }}</strong></div>

+         <div class="repo_name">

+           <strong>

+             {{ repo.namespace + '/' if repo.namespace }}{{ repo.name }}

+           </strong>

+         </div>

        </a>

        <div class="repo_desc" title="{{ repo.description }}" data-toggle="tooltip">

-         <small>{% if repo.description %}{{ repo.description }}{%else%}<span class="text-muted">no description<span>{% endif %}</small>

+         <small>

+           {% if repo.description %}{{ repo.description }}{% else %}

+           <span class="text-muted">no description<span>{% endif %}

+         </small>

        </div>

        <div class="project_metadata">

-         <span class="p-l-1"><small>created {{repo.date_created|humanize}}</small></span>

-         <div style="text-align:right;" class="p-r-1 text-muted pull-xs-right"><span title="Forks" data-toggle="tooltip"><span class="oi" data-glyph="fork"></span>{{repo.forks|count}}</span></div>

+         <span class="p-l-1">

+           <small>created {{repo.date_created|humanize}}</small>

+         </span>

+         <div style="text-align:right;" class="p-r-1 text-muted pull-xs-right">

+           <span title="Forks" data-toggle="tooltip">

+             <span class="oi" data-glyph="fork"></span>

+             {{repo.forks|count}}

+           </span>

+         </div>

        </div>

      </div>

    </div>
@@ -136,10 +148,15 @@ 

                  <a class="project_link logo_link" href="{{

                      url_for(

                      'view_repo',

+                     repo=repo.name,

                      username=repo.user.username if repo.is_fork else None,

-                     repo=repo.name)

+                     namespace=repo.namespace)

                  }}">

-                     <div><strong>{{ repo.name }}</strong></div>

+                   <div>

+                     <strong>

+                       {{ repo.namespace + '/' if repo.namespace }}{{ repo.name }}

+                     </strong>

+                   </div>

                 </a>

              {% else %}

              <p>No projects found</p>
@@ -207,11 +224,10 @@ 

              <div class="list-group">

              {% for repo in list %}

                <div class="list-group-item">

-                 {% if repo.is_fork %}

-                   {% set url = url_for('view_repo', username=repo.user.username, repo=repo.name) %}

-                 {% else %}

-                   {% set url = url_for('view_repo', repo=repo.name) %}

-                 {% endif %}

+                 {% set url = url_for('view_repo',

+                   repo=repo.name,

+                   username=repo.user.username if repo.is_fork else None,

+                   namespace=repo.namespace) %}

  

                  {% if repo.avatar_email %}

                    <img class="projecticon pull-xs-left"
@@ -224,7 +240,9 @@ 

                  {% endif %}

                  <a class="project_link logo_link" href="{{ url }}">

                      <div class="repo_name">

-                       <strong>{{ repo.name }}</strong>

+                       <strong>

+                         {{ repo.namespace + '/' if repo.namespace }}{{ repo.name }}

+                       </strong>

                      </div>

                  </a>

                  <div class="repo_desc" title="{{ repo.description }}"

@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}Activity - {{ repo.name }}{% endblock %}

+ {% block title %}Activity - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

Perhaps it's an idea to instead just add a property "repo.fullname", which includes the namespace, rather than reproduce this every time?

Fullname includes the prefix forks/ for forks, I'm not sure it's ideal

  {% set tag = "home" %}

  

  

@@ -8,7 +8,8 @@ 

    rel="stylesheet" />

  {% endblock %}

  

- {% block title %}Add group - {{ repo.name }}{% endblock %}

+ {% block title %}Add group - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  

  

  {% block repo %}
@@ -19,8 +20,10 @@ 

        <strong>Add group to the {{repo.name}} project</strong>

      </div>

      <div class="card-block">

-       <form action="{{ url_for('.add_group_project',

-                        username=username, repo=repo.name) }}" method="post">

+       <form action="{{

+         url_for('.add_group_project',

+             username=username, repo=repo.name, namespace=repo.namespace)

+         }}" method="post">

  

        <fieldset class="form-group">

          <label for="group"><strong>Username</strong></label>

@@ -14,7 +14,8 @@ 

          </div>

          <div class="card-block">

            <form action="{{

-               url_for('.add_token', username=username, repo=repo.name)

+               url_for('.add_token', username=username,

+                       repo=repo.name, namespace=repo.namespace)

            }}" method="post">

              {% for acl in acls %}

              <div>

@@ -8,7 +8,8 @@ 

    rel="stylesheet" />

  {% endblock %}

  

- {% block title %}Add user - {{ repo.name }}{% endblock %}

+ {% block title %}Add user - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  

  {% block repo %}

  <div class="row col-sm-6 col-sm-offset-3">
@@ -18,7 +19,8 @@ 

      </div>

      <div class="card-block">

        <form action="{{ url_for('.add_user',

-                        username=username, repo=repo.name) }}" method="post">

+                        username=username, repo=repo.name,

+                        namespace=repo.namespace) }}" method="post">

  

        <fieldset class="form-group">

          <label for="user"><strong>Username</strong></label>

@@ -44,8 +44,8 @@ 

      }

      $("#update_comment").atwho(userConfig);

    });

-    $.when($.get("{{ url_for('api_ns.api_view_issues', repo=repo.name, username=username, status='all') }}"),

-           $.get("{{ url_for('api_ns.api_pull_request_views', repo=repo.name, username=username, status='all') }}")

+    $.when($.get("{{ url_for('api_ns.api_view_issues', namespace=repo.namespace, repo=repo.name, username=username, status='all') }}"),

+           $.get("{{ url_for('api_ns.api_pull_request_views', namespace=repo.namespace, repo=repo.name, username=username, status='all') }}")

     ).done(function(issuesResp, prResp) {

       // 0 is the api response

       var issuesAndPrs = issuesResp[0]['issues'].concat(prResp[0]['requests']);

file modified
+55 -24
@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}Commit - {{ repo.name }} - {{ commitid }}{% endblock %}

+ {% block title %}Commit - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }} - {{ commitid }}{% endblock %}

  {% set tag = "commit"%}

  

  {% block repo %}
@@ -11,24 +12,43 @@ 

      <span class="label label-default" title="{{ commitid }}">Commit {{ commitid|short }}</span>

      <span>{{ splitted_message[0] }}</span>

      <div class="pull-xs-right btn-group">

-       <a class="btn btn-secondary btn-sm" href="{{ url_for('view_raw_file', username=username,

-             repo=repo.name, identifier=commitid) }}" title="View as raw">raw</a>

-       <a class="btn btn-secondary btn-sm" href="{{ url_for('view_commit_patch', username=username,

-             repo=repo.name, commitid=commitid) }}">patch</a>

-       <a class="btn btn-secondary btn-sm" href="{{ url_for('view_tree', username=username,

-             repo=repo.name, identifier=commitid) }}">tree</a>

+       <a class="btn btn-secondary btn-sm" href="{{ url_for(

+         'view_raw_file',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         identifier=commitid) }}" title="View as raw">raw</a>

+       <a class="btn btn-secondary btn-sm" href="{{ url_for(

+         'view_commit_patch',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         commitid=commitid) }}">patch</a>

+       <a class="btn btn-secondary btn-sm" href="{{ url_for(

+         'view_tree', username=username, namespace=repo.namespace,

+         repo=repo.name, identifier=commitid) }}">tree</a>

        {% if commit.parents|length == 1 %}

-       <a class="btn btn-secondary btn-sm" title={{commit.parents[0].oid.hex}} href="{{ url_for('view_commit', username=username,

-             repo=repo.name, commitid=commit.parents[0].oid.hex) }}">parent</a>

+       <a class="btn btn-secondary btn-sm" title={{commit.parents[0].oid.hex}} href="{{ url_for(

+         'view_commit',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         commitid=commit.parents[0].oid.hex) }}">parent</a>

        {% elif commit.parents|length > 1 %}

        <div class="btn-group" role="group">

-         <button id="parentsDrop" type="button" class="btn btn-secondary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">

+         <button id="parentsDrop" type="button" class="btn btn-secondary btn-sm dropdown-toggle"

+             data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">

            parents

          </button>

          <div class="dropdown-menu dropdown-menu-right" aria-labelledby="parentsDrop">

            {% for parent in commit.parents %}

-             <a class="dropdown-item" href="{{ url_for('view_commit', username=username,

-                   repo=repo.name, commitid=parent.oid.hex) }}" class="commitid">{{parent.oid.hex}}</a>

+             <a class="dropdown-item" href="{{ url_for(

+                 'view_commit',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 commitid=parent.oid.hex)

+             }}" class="commitid">{{parent.oid.hex}}</a>

            {% endfor %}

          </div>

        </div>
@@ -37,13 +57,21 @@ 

    </h4>

    <h5 class="text-muted">

      {% if commit.author| author2user == commit.committer| author2user %}

-       <a href="#" id="diff_list_link">{{diff|count}} file{{'s' if diff|count > 1}}</a> Authored and Committed by {{ commit.author | author2user |safe }}

-       <span data-toggle="tooltip" title="{{commit.commit_time | format_ts}}">{{commit.commit_time | humanize}}</span>

+       <a href="#" id="diff_list_link">{{ diff|count}} file{{'s' if diff|count > 1 }}</a>

+       Authored and Committed by {{ commit.author | author2user |safe }}

+       <span data-toggle="tooltip" title="{{ commit.commit_time | format_ts }}">

+         {{ commit.commit_time | humanize }}

+       </span>

      {% else %}

-     <a href="#" id="diff_list_link">{{diff|count}} file{{'s' if diff|count > 1}}</a> Authored by {{ commit.author | author2user |safe }}

-       <span data-toggle="tooltip" title="{{commit.commit_time | format_ts}}">{{commit.commit_time | humanize}}</span>,

-     Committed by {{ commit.committer | author2user |safe }}

-       <span data-toggle="tooltip" title="{{commit.commit_time | format_ts}}">{{commit.commit_time | humanize}}</span>,

+       <a href="#" id="diff_list_link">{{ diff|count}} file{{'s' if diff|count > 1 }}</a>

+       Authored by {{ commit.author | author2user |safe }}

+       <span data-toggle="tooltip" title="{{ commit.commit_time | format_ts }}">

+         {{ commit.commit_time | humanize }}

+       </span>,

+       Committed by {{ commit.committer | author2user |safe }}

+       <span data-toggle="tooltip" title="{{ commit.commit_time | format_ts }}">

+         {{ commit.commit_time | humanize }}

+       </span>,

      {% endif%}

    </h5>

  </div>
@@ -99,15 +127,17 @@ 

  <div class="card" id="diff-file-{{filecount}}">

    <div class="card-header">

      {% if patch | hasattr('new_file_path') %}

-       <a href="{{ url_for('view_file', username=username,

-                 repo=repo.name, identifier=commitid,

-                 filename=patch.new_file_path) }}" title="View file as of {{ commitid|short }}">

+       <a href="{{ url_for(

+           'view_file', username=username, namespace=repo.namespace,

+           repo=repo.name, identifier=commitid,

+           filename=patch.new_file_path) }}" title="View file as of {{ commitid|short }}">

          {{  patch.new_file_path | unicode }}

        </a>

      {% elif patch | hasattr('delta') %}

-       <a href="{{ url_for('view_file', username=username,

-                 repo=repo.name, identifier=commitid,

-                 filename=patch.delta.new_file.path) }}" title="View file as of {{ commitid|short }}">

+       <a href="{{ url_for(

+           'view_file', username=username, namespace=repo.namespace,

+           repo=repo.name, identifier=commitid,

+           filename=patch.delta.new_file.path) }}" title="View file as of {{ commitid|short }}">

          {{  patch.delta.new_file.path | unicode }}

        </a>

      {% endif %}
@@ -159,6 +189,7 @@ 

          data: {

            repo: "{{ repo.name }}",

            repouser: "{{ repo.user.user if repo.is_fork else '' }}",

+           namespace: "{{ repo.namespace }}",

            commit_id: "{{ commitid }}",

            csrf_token: "{{ form.csrf_token.current_token }}",

          },

file modified
+33 -12
@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}{{ select.capitalize() }} - {{ repo.name }}{% endblock %}

+ {% block title %}{{ select.capitalize() }} - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  {% block repo %}
@@ -38,8 +39,12 @@ 

            </button>

            <div class="dropdown-menu dropdown-menu-right">

              {% for branch in g.branches %}

-                 <a class="dropdown-item" href="{{ url_for('view_commits',

-                             username=username, repo=repo.name, branchname=branch) }}">

+                 <a class="dropdown-item" href="{{ url_for(

+                     'view_commits',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     branchname=branch) }}">

                    {{ branch }}

                  </a>

              {% endfor %}
@@ -73,7 +78,9 @@ 

            <div id="request_pull" class="pull-xs-right">

              <a class="btn btn-primary btn-sm"

                href="{{ url_for('new_request_pull',

-                     username=username, repo=repo.name,

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

                      branch_to=head, branch_from=branchname or 'master') }}">

                {% if g.repo_admin %}Request pull{% else %}Compare{% endif %}

              </a>
@@ -82,8 +89,11 @@ 

  

        <div id="diff_commits" class="list-group m-t-1" style="display:none;">

          {% for diff_commit_full in diff_commits_full %}

-            <a href="{{ url_for('view_commit', username=username,

-                       repo=repo.name, commitid=diff_commit_full.hex)

+            <a href="{{ url_for('view_commit',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     commitid=diff_commit_full.hex)

                }}" class="list-group-item">

                <h5>

                  <strong>{{ diff_commit_full.message.split('\n')[0] }}</strong>
@@ -109,8 +119,11 @@ 

  

        <div class="list-group m-t-1">

          {% for commit in last_commits %}

-           <a href="{{ url_for('view_commit', username=username,

-                   repo=repo.name, commitid=commit.hex, branch=branchname) }}"

+           <a href="{{ url_for('view_commit',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 commitid=commit.hex, branch=branchname) }}"

                class="list-group-item {%

                  if diff_commits and commit.oid.hex in diff_commits %}p-l-3{%

                  endif %}" style="position:relative;">
@@ -143,8 +156,12 @@ 

          <nav class="text-center">

            <ul class="pagination">

              <li {% if page <= 1%} class="disabled" {% endif %}>

-               <a href="{{ url_for('.%s' % origin, username=username,

-                           repo=repo.name, branchname=branchname, page=page-1)

+               <a href="{{ url_for('.%s' % origin,

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     branchname=branchname,

+                     page=page-1)

                  }}" aria-label="Previous">

                  <span aria-hidden="true">&laquo;</span>

                  <span class="sr-only">Newer</span>
@@ -152,8 +169,12 @@ 

              </li>

              <li class="active">page {{ page }} of {{total_page}}</li>

              <li {% if page >= total_page %}class="disabled"{%endif%}>

-               <a href="{{ url_for('.%s' % origin, username=username,

-                           repo=repo.name, branchname=branchname, page=page+1)

+               <a href="{{ url_for('.%s' % origin,

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     branchname=branchname,

+                     page=page+1)

                  }}" aria-label="Next">

                  <span aria-hidden="true">&raquo;</span>

                  <span class="sr-only">Older</span>

file modified
+9 -4
@@ -1,19 +1,24 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}Docs - {{ repo.name }}{% endblock %}

+ {% block title %}Docs - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  

  {% block repo %}

  

  <iframe id="docframe" src="{{ config['DOC_APP_URL'] + url_for('.view_repo',

-                 username=username, repo=repo.name, filename=filename) }}"

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         filename=filename) }}"

      frameborder="0" style="min-height:700px;width:100%"

      onload="resize_iframe()">

    <p>Your browser does not support iframe, please visit

    <a href="{{ config['DOC_APP_URL'] + url_for('.view_repo',

-                 username=username, repo=repo.name, filename=filename)

-            }}">the documentation directly</a>

+         namespace=repo.namespace, username=username,

+         repo=repo.name, filename=filename)

+     }}">the documentation directly</a>

    </p>

  </iframe>

  

file modified
+25 -10
@@ -1,7 +1,8 @@ 

  {% extends "repo_master.html" %}

  {% from "_formhelper.html" import render_field %}

  

- {% block title %}Edit - {{ repo.name }}{% endblock %}

+ {% block title %}Edit - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  {% block header %}

  <script src="{{ url_for('static', filename='codemirror/codemirror.js') }}"></script>
@@ -13,8 +14,11 @@ 

  <div class="card">

    <div class="card-header">

        <ol class="breadcrumb">

-       <li><a href="{{ url_for('view_tree', username=username,

-                   repo=repo.name, identifier=branchname)

+       <li><a href="{{ url_for('view_tree',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             identifier=branchname)

        }}"><span class="oi" data-glyph="random"></span>&nbsp; {{ branchname }}</a></li>{%

      for file in filename.split('/') %}

        {% if loop.first %}
@@ -23,16 +27,29 @@ 

        {% set path = path + '/' + file %}

        {% endif %}

        {% if loop.index != loop.length %}<li><a

-       href="{{ url_for('view_file', username=username,

-               repo=repo.name, identifier=branchname,

-               filename=path)}}"

-         ><span class="oi" data-glyph="folder"></span>&nbsp; {{ file }}</a></li>{% elif file %}<li class="active"><span class="oi" data-glyph="{% if output_type == 'tree' %}folder{% else %}file{% endif %}"></span>&nbsp; {{ file }}</li>{% endif %}

+       href="{{ url_for('view_file',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             identifier=branchname,

+             filename=path)}}"

+         ><span class="oi" data-glyph="folder"></span>&nbsp; {{ file }}</a>

+         </li>{%

+         elif file

+         %}<li class="active"><span class="oi" data-glyph="{%

+             if output_type == 'tree' %}folder{%

+             else %}file{%

+             endif %}"></span>&nbsp; {{ file }}</li>{%

+         endif %}

      {% endfor %}

      </ol>

    </div>

    <div class="card-block p-a-0">

      <form action="{{ url_for(

-           'edit_file', username=username, repo=repo.name,

+           'edit_file',

+           repo=repo.name,

+           username=username,

+           namespace=repo.namespace,

            branchname=branchname, filename=filename) }}"

            method="post">

      {{ form.csrf_token }}
@@ -111,10 +128,8 @@ 

  

  $("input[name=braction]:radio").change(function (e) {

    if ($(e.currentTarget).val() == 'new'){

-     console.log('new');

      $('#branch').html('<input type="text" placeholder="Branch name" name="branch">');

    } else {

-     console.log('not new');

      $('#branch').html(lbranch);

    }

  });

@@ -1,7 +1,8 @@ 

  {% extends "repo_master.html" %}

  {% from "_formhelper.html" import render_field_in_row %}

  

- {% block title %}Edit tag: {{ tag }} - {{ repo.name }}{% endblock %}

+ {% block title %}Edit tag: {{ tag }} - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  
@@ -11,7 +12,10 @@ 

  

  <section class="edit_tag">

      <form action="{{ url_for('.edit_tag',

-                      username=username, repo=repo.name, tag=edit_tag) }}" method="post">

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     tag=edit_tag) }}" method="post">

  

      <p>Enter in the field below the new name for the tag: "{{ edit_tag }}"</p>

      <table>

file modified
+56 -22
@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}Tree - {{ repo.name }}{% endblock %}

+ {% block title %}Tree - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  
@@ -34,13 +35,19 @@ 

                {% if origin == 'view_tree' %}

                  <a class="dropdown-item" href="{{ url_for(

                      'view_tree',

-                     username=username, repo=repo.name, identifier=branch) }}">

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     identifier=branch) }}">

                    {{ branch }}

                  </a>

                {% elif origin == 'view_file' %}

                  <a class="dropdown-item" href="{{ url_for(

                      'view_file',

-                     username=username, repo=repo.name, identifier=branch,

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     identifier=branch,

                      filename=filename | unicode ) }}">

                    {{ branch }}

                  </a>
@@ -56,8 +63,11 @@ 

        <div class="card-header">

          <ol class="breadcrumb">

            <li>

-             <a href="{{ url_for('view_tree', username=username,

-                       repo=repo.name, identifier=branchname)

+             <a href="{{ url_for('view_tree',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 identifier=branchname)

            }}">

                <span class="oi" data-glyph="random">

                </span>&nbsp; {{ branchname }}
@@ -70,9 +80,12 @@ 

            {% set path = path + '/' + file %}

            {% endif %}

            {% if loop.index != loop.length %}<li><a

-           href="{{ url_for('view_file', username=username,

-                   repo=repo.name, identifier=branchname,

-                   filename=path | unicode)}}">

+           href="{{ url_for('view_file',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 identifier=branchname,

+                 filename=path | unicode)}}">

              <span class="oi" data-glyph="folder"></span>&nbsp; {{ file }}</a>

            </li>

            {% elif file %}
@@ -93,14 +106,20 @@ 

              <div class="file-button-bar">

                  {% if output_type in ('file','markup') and g.repo_admin %}

                  <a class="btn btn-sm btn-secondary" href="{{ url_for(

-                     'edit_file', username=username,

-                     repo=repo.name, branchname=branchname,

+                     'edit_file',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     branchname=branchname,

                      filename=filename | unicode) }}" title="Edit file">Edit</a>

                  {% endif %}

                  {% if output_type in ('file','markup') %}

                  <form class="btn btn-sm" method="POST" name="fork_project"

-                     action="{{ url_for('.fork_edit_file', repo=repo.name,

-                         username=username, branchname=branchname, filename=filename) }}">

+                     action="{{ url_for('.fork_edit_file',

+                         repo=repo.name,

+                         username=username,

+                         namespace=repo.namespace,

+                         branchname=branchname, filename=filename) }}">

                      <button class="btn btn-sm btn-secondary"

                          onclick="fork_project.submit();">

                              Fork and Edit
@@ -110,19 +129,25 @@ 

                  {% endif %}

                  {% if output_type == 'markup'  %}

                  <a class="btn btn-sm btn-secondary" href="{{ url_for(

-                     'view_file', username=username,

+                     'view_file', username=username, namespace=repo.namespace,

                      repo=repo.name, identifier=branchname,

                      filename=filename | unicode, text=True) }}"

                      title="View as text">Text</a>

                  {% else %}

                  <a class="btn btn-secondary btn-sm" href="{{ url_for(

-                     'view_file', username=username,

-                     repo=repo.name, identifier=branchname,

+                     'view_file',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     identifier=branchname,

                      filename=filename | unicode) }}" title="View as blob">Blob</a>

                  {% endif %}

                  <a class="btn btn-secondary btn-sm" href="{{ url_for(

-                     'view_raw_file', username=username,

-                     repo=repo.name, identifier=branchname,

+                     'view_raw_file',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     identifier=branchname,

                      filename=filename) | unicode }}" title="View as raw">Raw</a>

              </div>

            {% endif %}
@@ -139,15 +164,21 @@ 

          {% endautoescape %}

        </div>

      {% elif output_type == 'image' %}

-         <img src="{{ url_for('view_raw_file', username=username,

-                     repo=repo.name, identifier=branchname,

+         <img src="{{ url_for('view_raw_file',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     identifier=branchname,

                      filename=filename | unicode) }}"/>

      {% elif output_type == 'binary' %}

          <p class="noresult">

            Binary files cannot be rendered.<br/>

            Please

-           <a href="{{ url_for('view_raw_file', username=username,

-                     repo=repo.name, identifier=branchname,

+           <a href="{{ url_for('view_raw_file',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     identifier=branchname,

                      filename=filename | unicode) }}">view the raw version

            </a>

          </p>
@@ -173,7 +204,10 @@ 

              <td class="pagure-table-filename table-expand-col">

                  {% if entry.filemode == 16384 %}<strong>{% endif -%}

                  <a href="{{ url_for(

-                     'view_file', username=username,repo=repo.name,

+                     'view_file',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

                      identifier=branchname,

                      filename=filename | unicode + '/' +

                      entry.name | unicode if filename else entry.name) }}">

file modified
+10 -4
@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}Forks - {{ repo.name }}{% endblock %}

+ {% block title %}Forks - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  
@@ -14,14 +15,19 @@ 

      {% for fork in repo.forks %}

        <div class="list-group-item">

          <h5>

-           <strong><a href="{{ url_for('view_repo', username=fork.user.user,repo=fork.name) }}">

+           <strong><a href="{{ url_for('view_repo',

+                 repo=fork.name,

+                 username=fork.user.user,

+                 namespace=repo.namespace) }}">

                <span class="oi text-muted" data-glyph="fork"></span>

                {{ fork.user.user }}/{{ fork.name }}

            </a></strong>

            <div class="pull-xs-right">

              <span>

-               <a href="{{ url_for('view_user', username=fork.user.user)}}">{{ fork.user.default_email | avatar(20) | safe }}

-                   {{ fork.user.fullname }}</a> forked this project

+               <a href="{{ url_for('view_user', username=fork.user.user)}}">

+                 {{ fork.user.default_email | avatar(20) | safe }}

+                 {{ fork.user.fullname }}

+               </a> forked this project

              </span>

              <span class="commitdate" data-toggle="tooltip" title="{{

                  fork.date_created.strftime('%Y-%m-%d %H:%M:%S') }}">

@@ -35,18 +35,18 @@ 

              <div class="list-group list-group-flush">

              {% for repo in repos %}

                <div class="list-group-item">

-                 {% if repo.is_fork %}

-                   {% set url = url_for('view_repo', username=repo.user.username, repo=repo.name) %}

-                 {% else %}

-                   {% set url = url_for('view_repo', repo=repo.name) %}

-                 {% endif %}

+                 {% set url = url_for(

+                     'view_repo',

+                     repo=repo.name,

+                     username=repo.user.username if repo.is_fork else None,

+                     namespace=repo.namespace) %}

                  <a href="{{ url }}">

                    {% if repo.avatar_email %}

                      <img class="projecticon pull-xs-left" src="{{ repo.avatar_email | avatar_url }}" width=20 height=20 />&nbsp;

                    {% else %}

                      <span class="oi text-muted" data-glyph="document"></span>

                    {% endif %}

-                   <strong>{{ repo.name }}</strong>

+                   <strong>{{ repo.namespace + '/' if repo.namespace }}{{ repo.name }}</strong>

                  </a>

                    <div class="pull-xs-right">

                      {% if config.get('ENABLE_TICKETS', True) and repo.settings.get('issue_tracker', True) %}
@@ -74,7 +74,10 @@ 

                        </span>

                      {% else %}

                        <a class="notblue" data-toggle="tooltip"

-                         href="{{ url_for('.request_pulls', repo=repo.name) }}"

+                         href="{{ url_for('.request_pulls',

+                         repo=repo.name,

+                         username=repo.user.username if repo.is_fork else None,

+                         namespace=repo.namespace) }}"

                          title="{{repo.open_requests}} open pull requests in {{repo.name}}">

                          <span class="oi" data-glyph="arrow-thick-bottom"></span>

                          {{- repo.open_requests}}
@@ -109,19 +112,23 @@ 

              <div class="list-group list-group-flush">

              {% for fork in forks %}

                <div class="list-group-item">

-                 {% if fork.is_fork %}

-                   {% set url = url_for('view_repo', username=fork.user.username, repo=fork.name) %}

-                 {% else %}

-                   {% set url = url_for('view_repo', repo=fork.name) %}

-                 {% endif %}

+                 {% set url = url_for(

+                     'view_repo',

+                     repo=fork.name,

+                     username=fork.user.username if fork.is_fork else None,

+                     namespace=fork.namespace) %}

+ 

                  <a href="{{ url }}">

                    <span class="oi text-muted" data-glyph="fork"></span>

-                   <strong>{{username}}/{{ fork.name }}</strong>

+                   <strong>{{username}}/{{ fork.namespace + '/' if fork.namespace }}{{ fork.name }}</strong>

                  </a>

                    <div class="pull-xs-right">

                    <span class="text-muted">forked from</span>

-                   <a href="{{ url_for('view_repo', repo=fork.parent.name) }}">

-                     {{fork.parent.name}}

+                   <a href="{{ url_for(

+                     'view_repo', repo=fork.parent.name,

+                     namespace=fork.parent.namespace) }}">

+                     {{ fork.parent.namespace + '/' if fork.parent.namespace

+                     }}{{fork.parent.name}}

                    </a>

                    {% if fork.settings.get('issue_tracker', True) %}

                      {% if fork.open_tickets_public == 0 %}
@@ -132,7 +139,9 @@ 

                        </span>

                      {% else %}

                        <a class="notblue" data-toggle="tooltip"

-                         href="{{ url_for('.view_issues', repo=fork.name) }}"

+                         href="{{ url_for(

+                           '.view_issues', repo=fork.name,

+                           namespace=fork.namespace) }}"

                          title="{{ fork.open_tickets_public }} open issues against {{fork.name}}">

                          <span class="oi" data-glyph="warning"></span>

                          {{- fork.open_tickets_public }}
@@ -148,7 +157,9 @@ 

                        </span>

                      {% else %}

                        <a class="notblue" data-toggle="tooltip"

-                         href="{{ url_for('.request_pulls', repo=fork.name) }}"

+                         href="{{ url_for(

+                             '.request_pulls', repo=fork.name,

+                             namespace=fork.namespace) }}"

                          title="{{fork.open_requests}} open pull requests in {{fork.name}}">

                          <span class="oi" data-glyph="arrow-thick-bottom"></span>

                          {{- fork.open_requests}}
@@ -197,16 +208,28 @@ 

                <div class="list-group">

                  {% if repo.is_fork %}

                    <a class="list-group-item" href="{{ url_for(

-                     'view_repo', username=repo.user.username, repo=repo.name) }}">

-                     <div class=""><strong><span class="oi" data-glyph="fork">

-                             </span> &nbsp;{{ repo.user.username }}/{{ repo.name }}</strong>

+                     'view_repo',

+                     repo=repo.name,

+                     username=repo.user.username,

+                     namespace=repo.namespace) }}">

+                     <div class="">

+                       <strong>

+                         <span class="oi" data-glyph="fork"></span>

+                         &nbsp;{{ repo.user.username }}/{{

+                           repo.namespace + '/' if repo.namespace

+                               }}{{ repo.name }}

+                       </strong>

                      </div>

                    </a>

                  {% else %}

                    <a class="list-group-item" href="{{ url_for(

-                     'view_repo', repo=repo.name) }}">

-                     <div class=""><strong><span class="oi" data-glyph="document">

-                           </span> &nbsp;{{ repo.name }}</strong>

+                     'view_repo', repo=repo.name, namespace=repo.namespace) }}">

+                     <div class="">

+                       <strong>

+                         <span class="oi" data-glyph="document"></span>

+                         &nbsp;{{ repo.namespace + '/' if repo.namespace

+                               }}{{ repo.name }}

+                       </strong>

                      </div>

                    </a>

                  {% endif %}

file modified
+69 -23
@@ -18,8 +18,8 @@ 

  {% block repo %}

  <div class="row m-t-2">

    <form action="{{ url_for('update_issue', username=username,

-                repo=repo.name, issueid=issueid) }}" method="post"

-                onsubmit="return try_async_comment(this)">

+     namespace=repo.namespace, repo=repo.name, issueid=issueid)

+     }}" method="post" onsubmit="return try_async_comment(this)">

    {{ form.csrf_token }}

  

    <div class="col-md-8">
@@ -135,8 +135,11 @@ 

                <h4 id="taglist">

                  {% for tag in issue.tags %}

                    <a id="tag-{{ tag.tag }}" class="label label-default"

-                     href="{{ url_for('view_issues', username=username,

-                             repo=repo.name, tags=tag.tag) }}">

+                     href="{{ url_for('view_issues',

+                         repo=repo.name,

+                         username=username,

+                         namespace=repo.namespace,

+                         tags=tag.tag) }}">

                      {{ tag.tag }}

                    </a>

                  {% endfor %}
@@ -157,7 +160,10 @@ 

              <div id="assignee_plain">

                {% if issue.assignee %}

                    <a href="{{ url_for(

-                     'view_issues', username=username, repo=repo.name,

+                     'view_issues',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

                      assignee=issue.assignee.username) }}">

                      {{ issue.assignee.username }}

                    </a>
@@ -188,8 +194,11 @@ 

              <div id="blocklist">

                {% for ticket in issue.parents %}

                  <a id="block-{{ ticket.id }}" class="label label-default"

-                   href="{{ url_for('view_issue', username=username,

-                             repo=repo.name, issueid=ticket.id)

+                   href="{{ url_for('view_issue',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     issueid=ticket.id)

                    }}" >#{{ ticket.id }}</a>

                {% endfor %}

              </div>
@@ -210,8 +219,11 @@ 

              <div id="dependlist">

                {% for ticket in issue.children %}

                  <a id="depend-{{ ticket.id }}" class="label label-default"

-                   href="{{ url_for('view_issue', username=username,

-                             repo=repo.name, issueid=ticket.id)

+                   href="{{ url_for('view_issue',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     issueid=ticket.id)

                      }}">#{{ ticket.id }}</a>

                {% endfor %}

              </div>
@@ -263,7 +275,7 @@ 

  {% block jscripts %}

  {{ super() }}

  <script type="text/javascript">

-   var UPLOAD_URL = "{{ url_for('upload_issue', repo=repo.name, issueid=issue.id, username=username) }}";

+   var UPLOAD_URL = "{{ url_for('upload_issue', repo=repo.name, username=username, namespace=repo.namespace, issueid=issue.id) }}";

  </script>

  <script type="text/javascript"

      src="{{ url_for('static', filename='emoji/jquery.textcomplete.min.js') }}">
@@ -302,8 +314,16 @@ 

      }

      $("#comment").atwho(userConfig);

    });

-    $.when($.get("{{ url_for('api_ns.api_view_issues', repo=repo.name, username=username, status='all') }}"),

-           $.get("{{ url_for('api_ns.api_pull_request_views', repo=repo.name, username=username, status='all') }}")

+    $.when($.get("{{ url_for('api_ns.api_view_issues',

+                             repo=repo.name,

+                             username=username,

+                             namespace=repo.namespace,

+                             status='all') }}"),

+           $.get("{{ url_for('api_ns.api_pull_request_views',

+                             repo=repo.name,

+                             username=username,

+                             namespace=repo.namespace,

+                             status='all') }}")

     ).done(function(issuesResp, prResp) {

       // 0 is the api response

       var issuesAndPrs = issuesResp[0]['issues'].concat(prResp[0]['requests']);
@@ -405,7 +425,10 @@ 

          'method': 'POST',

          'action': '{{

          url_for('.delete_issue',

-                  username=username, repo=repo.name, issueid=issueid) }}',

+                  repo=repo.name,

+                  username=username,

+                  namespace=repo.namespace,

+                  issueid=issueid) }}',

      }).append($('<input>', {

          'name': 'csrf_token',

          'value': '{{ form.csrf_token.current_token }}',
@@ -450,13 +473,22 @@ 

    console.log(e.data);

    var data = $.parseJSON(e.data);

    var _issues_url ='<a href="{{

-     url_for('view_issues', username=username, repo=repo.name)}}';

+     url_for('view_issues',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace)}}';

    var _api_issues_url ='{{

-     url_for('api_ns.api_view_issue', username=username,

-             repo=repo.name, issueid='-123456789')}}';

+     url_for('api_ns.api_view_issue',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             issueid='-123456789')}}';

    var _issue_url ='{{

-     url_for('view_issue', username=username,

-             repo=repo.name, issueid='-123456789')}}';

+     url_for('view_issue',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             issueid='-123456789')}}';

    process_event(data, "{{ issue.uid }}", _issue_url,

                  _issues_url, _api_issues_url,

                  "{{ g.fas_user.username }}");
@@ -578,7 +610,10 @@ 

      create: false,

      load: function(query, callback) {

        $.getJSON(

-         "{{ url_for('api_ns.api_view_issues', username=username, repo=repo.name) }}",

+         "{{ url_for('api_ns.api_view_issues',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace) }}",

          function( data ) {

            //console.log(data.issues);

            callback(data.issues);
@@ -604,7 +639,10 @@ 

      create: false,

      load: function(query, callback) {

        $.getJSON(

-         "{{ url_for('api_ns.api_view_issues', username=username, repo=repo.name) }}",

+         "{{ url_for('api_ns.api_view_issues',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace) }}",

          function( data ) {

            //console.log(data.issues);

            callback(data.issues);
@@ -640,8 +678,9 @@ 

        if ($( "#previewinmarkdown" ).hasClass("inactive")){

          var _text = $( "#comment" ).val();

          var _url = "{{ url_for('markdown_preview',

+                         repo=repo.name,

                          user=repo.user.user if repo.is_fork,

-                         repo=repo.name) | safe}}";

+                         namespace=repo.namespace) | safe}}";

          $.ajax({

            url: _url ,

            type: 'POST',
@@ -675,12 +714,19 @@ 

    {% if authenticated and g.repo_admin %}

      $("#take-btn").click(function(){

        var _url = "{{ url_for(

-         'api_ns.api_assign_issue', repo=repo.name, username=username, issueid=issueid

+         'api_ns.api_assign_issue',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         issueid=issueid

          ) }}";

        var _data = {assignee: "{{ g.fas_user.username }}"};

        $.post( _url, _data ).done(

          function(data) {

-           var _user_url = '\n<a href="{{ url_for("view_issues", repo=repo.name, username=username) }}'

+           var _user_url = '\n<a href="{{ url_for("view_issues",

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace) }}'

              + '?assignee={{ g.fas_user.username }}">'

              + '{{ g.fas_user.username }}</a>';

            $('#assignee_plain').html(_user_url);

file modified
+90 -44
@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}Issues - {{ repo.name }}{% endblock %}

+ {% block title %}Issues - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home"%}

  

  
@@ -16,7 +17,10 @@ 

      <span class="btn-group btn-group-sm pull-xs-right" role="group">

      {% if repo.milestones %}

        <a href="{{ url_for(

-           'view_roadmap', username=username, repo=repo.name) }}"

+           'view_roadmap',

+           repo=repo.name,

+           username=username,

+           namespace=repo.namespace) }}"

           class="btn btn-secondary btn-sm">

          Roadmap

        </a>
@@ -36,17 +40,29 @@ 

  <section id="tags">

    <span class="btn-group btn-group-sm issues-tagbar" role="group" aria-label="Basic example">

      {% if status and status != 'Open' %}

-       <a class="btn btn-secondary btn-sm" href="{{ url_for('view_issues', username=username,

-                  repo=repo.name, tags=tags, author=author, assignee=assignee) }}">Open</a>

-       <a class="btn btn-primary btn-sm" href="{{ url_for('view_issues', username=username,

-                  repo=repo.name, status='Closed', tags=tags, author=author,

-                  assignee=assignee) }}">Closed</a>

+       <a class="btn btn-secondary btn-sm" href="{{ url_for('view_issues',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         tags=tags, author=author, assignee=assignee) }}">Open</a>

+       <a class="btn btn-primary btn-sm" href="{{ url_for('view_issues',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         status='Closed', tags=tags, author=author,

+         assignee=assignee) }}">Closed</a>

      {% else %}

-       <a class="btn btn-primary btn-sm" href="{{ url_for('view_issues', username=username,

-                  repo=repo.name, tags=tags, author=author, assignee=assignee) }}">Open</a>

-       <a class="btn btn-secondary btn-sm" href="{{ url_for('view_issues', username=username,

-                  repo=repo.name, status='Closed', tags=tags, author=author,

-                  assignee=assignee) }}">Closed</a>

+       <a class="btn btn-primary btn-sm" href="{{ url_for('view_issues',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         tags=tags, author=author, assignee=assignee) }}">Open</a>

+       <a class="btn btn-secondary btn-sm" href="{{ url_for('view_issues',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         status='Closed', tags=tags, author=author,

+         assignee=assignee) }}">Closed</a>

      {% endif %}

    </span>

    <span class="oi m-l-2" data-glyph="tag"></span>
@@ -55,21 +71,28 @@ 

        {% if tag.tag in tags %}

          {% if status and status != 'Open' %}

          <a class="btn btn-secondary btn-sm {% if tag.tag in tags%}active{% endif %}"

-             href="{{ url_for('view_issues', username=username,

-                  repo=repo.name, status='Closed') }}"

-                    title="Filter issues by tag">

+             href="{{ url_for('view_issues',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 status='Closed') }}" title="Filter issues by tag">

           {% else %}

          <a class="btn btn-secondary btn-sm {% if tag.tag in tags%}active{% endif %}"

-             href="{{ url_for('view_issues', username=username,

-                  repo=repo.name) }}"

-                    title="Filter issues by tag">

+             href="{{ url_for('view_issues',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}"

+                 title="Filter issues by tag">

           {% endif %}

        {% else %}

          <a class="btn btn-secondary btn-sm {% if tag.tag in tags%}active{%endif%}"

-             href="{{ url_for('view_issues', username=username,

-                    repo=repo.name, tags=tag.tag,

-                    author=author, assignee=assignee, status=status) }}"

-                    title="Filter issues by tag">

+             href="{{ url_for('view_issues',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 tags=tag.tag,

+                 author=author, assignee=assignee, status=status) }}"

+                 title="Filter issues by tag">

        {% endif %}

  

          {{ tag.tag }}</a>
@@ -86,20 +109,29 @@ 

              <th class="close_date">Closed</th>

              {% endif %}

              <th class="priority" data-sort="int">

-                 Priority&nbsp;(<a href="{{ url_for('view_issues', username=username,

-                 repo=repo.name, tags=tags, author=author, assignee=assignee,

-                 status=status) }}">reset</a>)

+               Priority&nbsp;(<a href="{{ url_for('view_issues',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace,

+               tags=tags, author=author, assignee=assignee,

+               status=status) }}">reset</a>)

              </th>

              <th class="open_by">

-                 Reporter&nbsp;(<a href="{{ url_for('view_issues', username=username,

-                 repo=repo.name, tags=tags, assignee=assignee, priority=priority,

-                 status=status) }}">reset</a>)

+               Reporter&nbsp;(<a href="{{ url_for('view_issues',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace,

+               tags=tags, assignee=assignee, priority=priority,

+               status=status) }}">reset</a>)

              </th>

              {% if not status or status|lower == 'open' %}

              <th class="assigned">

-               Assignee&nbsp;(<a href="{{ url_for('view_issues', username=username,

-                 repo=repo.name, tags=tags, author=author, priority=priority,

-                 status=status) }}">reset</a>)

+               Assignee&nbsp;(<a href="{{ url_for('view_issues',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace,

+               tags=tags, author=author, priority=priority,

+               status=status) }}">reset</a>)

              </th>

              {% endif %}

          </tr>
@@ -122,8 +154,11 @@ 

                {% if issue.private %}

                <span class="oi red-icon" data-glyph="lock-locked" title="Private issue"></span>

                {% endif %}

-               <a href="{{ url_for('view_issue', username=username,

-                          repo=repo.name, issueid=issue.id) }}">

+               <a href="{{ url_for('view_issue',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace,

+                   issueid=issue.id) }}">

                  {{ issue.title | noJS("img") | safe }}

                </a>

                 &nbsp;&nbsp;
@@ -156,19 +191,24 @@ 

                else repo.priorities | increment_largest_priority | string }}">

                {% if issue.priority %}

  

-                 <a href="{{ url_for('view_issues', username=username,

-                     repo=repo.name, author=author,

-                     tags=tags, assignee=assignee, status=status,

-                     priority=issue.priority) }}"

+                 <a href="{{ url_for('view_issues',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     author=author, tags=tags, assignee=assignee,

+                     status=status, priority=issue.priority) }}"

                      title="Filter issues by priority">{{

                    repo.priorities[issue.priority | string] }}

                  </a>

                {% endif %}

              </td>

              <td class="nowrap">

-                 <a href="{{ url_for('view_issues', username=username,

-                     repo=repo.name, author=issue.user.user,

-                     tags=tags, assignee=assignee, status=status) }}"

+                 <a href="{{ url_for('view_issues',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     author=issue.user.user, tags=tags,

+                     assignee=assignee, status=status) }}"

                      title="Filter issues by reporter">

                      {{ issue.user.default_email | avatar(16) | safe }}

                      {{ issue.user.user }}
@@ -177,16 +217,22 @@ 

              <td class="nowrap">

              {% if not status or status|lower == 'open' %}

                {% if issue.assignee %}

-                 <a href="{{ url_for('view_issues', username=username,

-                   repo=repo.name, assignee=issue.assignee.username,

+                 <a href="{{ url_for('view_issues',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace,

+                   assignee=issue.assignee.username,

                    tags=tags, author=author, status=status) }}"

                    title="Filter issues by assignee">

                    {{ issue.assignee.default_email | avatar(16) | safe }}

                    {{ issue.assignee.user }}

                  </a>

                {% else %}

-                 <a class="text-muted" href="{{ url_for('view_issues', username=username,

-                   repo=repo.name, tags=tags, author=author, status=status,

+                 <a class="text-muted" href="{{ url_for('view_issues',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace,

+                   tags=tags, author=author, status=status,

                    assignee=0) }}">unassigned

                  </a>

                {% endif %}

@@ -3,7 +3,8 @@ 

  

  {% block title %}{% if not type or type == 'new'

      %}New issue{% elif type and type == 'edit'

-     %}Edit issue #{{ issueid }} {% endif %} - {{ repo.name }}{% endblock %}

+     %}Edit issue #{{ issueid }} {% endif %} - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  {% block header %}
@@ -26,12 +27,17 @@ 

        <div class="card-block">

          {% if not type or type == 'new' %}

            <form action="{{ url_for('.new_issue',

-                            username=username, repo=repo.name) }}" method="post"

-                 enctype="multipart/form-data">

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace)

+             }}" method="post" enctype="multipart/form-data">

  

          {% elif type and type == 'edit' %}

-           <form action="{{ url_for('.edit_issue', username=username,

-                              repo=repo.name, issueid=issueid) }}" method="post"

+           <form action="{{ url_for('.edit_issue',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 issueid=issueid) }}" method="post"

                  enctype="multipart/form-data">

          {% endif %}

          {{ render_bootstrap_field(form.title, field_description="Gist of your issue") }}
@@ -100,7 +106,10 @@ 

      {% if authenticated and g.repo_admin and type and type == 'edit' %}

      <form method="post" class="pull-xs-right" action="{{

          url_for('.delete_issue',

-                 username=username, repo=repo.name, issueid=issueid) }}">

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 issueid=issueid) }}">

        <button class="btn btn-danger" type="submit"

            onclick="return confirm('Are you sure to delete this ticket? \nThis is final and cannot be un-done.');"

            title="Delete this ticket">
@@ -134,7 +143,11 @@ 

      if (_txt) {

        _txt += '\n';

      }

-     var _loc = "{{ url_for('view_issue_raw_file', repo=repo.name, username=username, filename='') }}" + this.file;

+     var _loc = "{{ url_for('view_issue_raw_file',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         filename='') }}" + this.file;

  

      $("#issue_content").val(_txt + '<!!image>');

    });
@@ -159,8 +172,9 @@ 

      var _type = $("#type").val();

      var _url = "{{

        url_for('internal_ns.get_ticket_template',

+               repo=repo.name,

                username=repo.username if repo.is_fork else None,

-               repo=repo.name) }}";

+               namespace=repo.namespace) }}";

      _url += '?template=' + _type;

      $.ajax({

        url: _url ,
@@ -189,8 +203,9 @@ 

        if ($( "#previewinmarkdown" ).hasClass("inactive")){

          var _text = $( "#issue_content" ).val();

          var _url = "{{ url_for('markdown_preview',

+                         repo=repo.name,

                          user=repo.user.user if repo.is_fork,

-                         repo=repo.name) | safe}}";

+                         namespace=repo.namespace) | safe}}";

          $.ajax({

            url: _url ,

            type: 'POST',

@@ -17,6 +17,7 @@ 

            <form action="{{ url_for('.new_project') }}" method="post">

              {{ render_bootstrap_field(form.name, field_description="the name of your project") }}

              {{ render_bootstrap_field(form.description, field_description="short description of the project") }}

+             {{ render_bootstrap_field(form.namespace, field_description="namespace of the project") }}

              {{ render_bootstrap_field(form.url, field_description="url of the project's website") }}

              {{ render_bootstrap_field(form.avatar_email, field_description="libravatar email address avatar email") }}

              {{ render_bootstrap_field(form.create_readme, field_description="Create a README file automatically") }}

@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}New release - {{ repo.name }}{% endblock %}

+ {% block title %}New release - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  
@@ -13,7 +14,8 @@ 

    {{ config['MAX_CONTENT_LENGTH'] / 1024 /1024 }}MB.

  </p>

  

- <form action="{{ url_for('new_release', username=username, repo=repo.name) }}"

+ <form action="{{ url_for('new_release',

+     namespace=repo.namespace, username=username, repo=repo.name) }}"

      method="post" enctype="multipart/form-data">

  {{ form.csrf_token }}

  <input id="file-picker" type="file" name="filestream" multiple>

file modified
+6 -3
@@ -3,7 +3,8 @@ 

  {% if full %}

  {% extends "repo_master.html" %}

  

- {% block title %}{{ select.capitalize() }} {{ plugin.name }} - {{ repo.name }}{% endblock %}

+ {% block title %}{{ select.capitalize() }} {{ plugin.name }} - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  {% endif %}

  
@@ -13,8 +14,10 @@ 

  {% endif %}

  

    <form action="{{ url_for('.view_plugin',

-                   username=username, repo=repo.name, plugin=plugin.name,

-                   ) }}" method="post">

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         plugin=plugin.name) }}" method="post">

    {{ plugin.description | markdown | noJS | safe }}

  

    <table>

@@ -3,14 +3,15 @@ 

  

  {% block title %}

    {%- if pull_request -%}

-     PR#{{ requestid }}: {{ pull_request.title | noJS(ignore="img")}} - {{ repo.name }}

-   {% elif form and (g.repo_admin or remote_git) %}

-     Create new Pull Request for {{ branch_to }} - {{ repo.name }}

+     PR#{{ requestid }}: {{ pull_request.title | noJS(ignore="img")}}

+   {%- elif form and (g.repo_admin or remote_git) -%}

+     Create new Pull Request for {{ branch_to }}

    {%- elif origin == 'compare_commits' -%}

-     Diff from {{ commit1 }} to {{ commit2 }} - {{ repo.name }}

+     Diff from {{ commit1 }} to {{ commit2 }}

    {%- else -%}

-     Diff from {{ branch_from }} to {{ branch_to }} - {{ repo.name }}

-   {%- endif -%}

+     Diff from {{ branch_from }} to {{ branch_to }}

+   {%- endif

+   %} - {{ repo.namespace + '/' if repo.namespace }}{{ repo.name }}

  {% endblock %}

  

  {% set tag = "home" %}
@@ -38,13 +39,19 @@ 

       <span class="pull-xs-right">

       {% if pull_request.status == 'Open' and authenticated and

          (g.repo_admin or g.fas_user.username == pull_request.user.username) %}

-         <form style="display:inline;" action="{{ url_for('cancel_request_pull', username=username,

+         <form style="display:inline;" action="{{ url_for(

+             'cancel_request_pull', username=username,

+             namespace=repo.namespace,

              repo=repo.name, requestid=requestid) }}" method="POST">

       {% endif %}

            <div class="btn-group" role="group" aria-label="Basic example">

              <a class="btn btn-sm btn-primary"

-                href="{{ url_for('request_pull_edit', username=username,

-                repo=repo.name, requestid=requestid) }}"

+                href="{{ url_for(

+                 'request_pull_edit',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 requestid=requestid) }}"

                 title="Update title"><span class="oi" data-glyph="pencil"></span></a>

       {% if pull_request.status == 'Open' and authenticated and

          (g.repo_admin or g.fas_user.username == pull_request.user.username) %}
@@ -77,9 +84,10 @@ 

      }}</span> <span class="pr-toplabel">

      <span class="oi" data-glyph="random"> </span>

      <a href="{{ url_for('view_repo_branch',

+           repo=pull_request.project_from.name,

            username=pull_request.project_from.user.user

              if pull_request.project_from.is_fork else None,

-           repo=pull_request.project_from.name,

+           namespace=repo.namespace,

            branchname=pull_request.branch_from)

          }}">

      {{ pull_request.branch_from }}
@@ -89,9 +97,10 @@ 

      <span class="pr-toplabel">{{ pull_request.project.fullname }}</span>

      <span class="pr-toplabel"><span class="oi" data-glyph="random"></span>

      <a href="{{ url_for('view_repo_branch',

+           repo=pull_request.project.name,

            username=pull_request.project.user.user

              if pull_request.project.is_fork else None,

-           repo=pull_request.project.name,

+           namespace=repo.namespace,

            branchname=pull_request.branch)

          }}">

      {{ pull_request.branch }}
@@ -108,8 +117,11 @@ 

  <h2>Create pull request</h2>

  {% else %}

  <h2>Diff

-       (<a href="{{ url_for('view_tree', username=username,

-                repo=repo.name, identifier=commitid) }}"

+       (<a href="{{ url_for('view_tree',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             identifier=commitid) }}"

        >tree</a>)</h2>

  

      {% if origin == 'compare_commits' %}
@@ -121,13 +133,19 @@ 

  {% if form and (g.repo_admin or remote_git) %}

  <section class="new_project">

    {% if remote_git %}

-   <form action="{{ url_for('.new_remote_request_pull', username=username,

-     repo=repo.name, confirm=True) }}" method="post">

+   <form action="{{ url_for('.new_remote_request_pull',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         confirm=True) }}" method="post">

      <input type="hidden" value="{{ branch_from }}" name="branch_from" />

      <input type="hidden" value="{{ remote_git }}" name="git_repo" />

    {% else %}

-   <form action="{{ url_for('.new_request_pull', username=username,

-     repo=repo.name, commitid=commitid, branch_from=branch_from,

+   <form action="{{ url_for('.new_request_pull',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         commitid=commitid, branch_from=branch_from,

      branch_to=branch_to) }}" method="post">

    {% endif %}

      <div class="p-b-1">
@@ -187,7 +205,11 @@ 

      <p class="buttons indent">

        <input type="submit" class="btn btn-primary" value="Create">

        {{ form.csrf_token }}

-       <a class="btn btn-secondary" href="{{ url_for('view_repo', username=username, repo=repo.name)}}">

+       <a class="btn btn-secondary" href="{{ url_for(

+         'view_repo',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace)}}">

          Cancel

        </a>

      </p>
@@ -222,8 +244,12 @@ 

    </li>

    {% if pull_request %}

    <li class="nav-item pull-xs-right">

-     <a class="nav-link" href="{{ url_for('request_pull_patch', username=username,

-             repo=repo.name, requestid=requestid) }}">

+     <a class="nav-link" href="{{ url_for(

+         'request_pull_patch',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

+         requestid=requestid) }}">

        <span class="hidden-sm-down">Patch</span>

      </a>

    </li>
@@ -238,15 +264,22 @@ 

  

              {% if pull_request and pull_request.status and pull_request.project_from.is_fork %}

              <a class="list-group-item" href="{{

-                 url_for('view_commit', username=pull_request.project_from.user.user,

-                         repo=pull_request.project_from.name, commitid=commit.oid.hex)

+                 url_for(

+                     'view_commit',

+                     repo=pull_request.project_from.name,

+                     username=pull_request.project_from.user.user,

+                     namespace=repo.namespace,

+                     commitid=commit.oid.hex)

                  }}">

              {% elif pull_request and pull_request.remote %}

              <a>

              {% else %}

              <a class="list-group-item" href="{{

-                 url_for('view_commit', username=username,

-                         repo=repo.name, commitid=commit.oid.hex)}}">

+                 url_for('view_commit',

+                         repo=repo.name,

+                         username=username,

+                         namespace=repo.namespace,

+                         commitid=commit.oid.hex)}}">

              {% endif %}

  

              <h5>
@@ -272,8 +305,12 @@ 

        if not pull_request %}active{%

        endif %}" role="tabpanel" id="request_diff">

      {% if authenticated and pull_request %}

-     <form action="{{ url_for('.pull_request_drop_comment', username=username,

-         repo=repo.name, requestid=requestid) }}" method="post" class="icon"

+     <form action="{{ url_for('.pull_request_drop_comment',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             requestid=requestid)

+         }}" method="post" class="icon"

          onsubmit="return try_async_comment(this, null)" >

      {% endif %}

  
@@ -341,9 +378,10 @@ 

                <a href="{{

                    url_for(

                        'view_file',

+                       repo=pull_request.project_from.name,

                        username=pull_request.project_from.user.username

                            if pull_request.project_from.is_fork else None,

-                       repo=pull_request.project_from.name,

+                       namespace=pull_request.project_from.namespace,

                        identifier=identifier,

                        filename=filepath) }}"

                {% else %}
@@ -353,8 +391,9 @@ 

                <a href="{{

                    url_for(

                        'view_file',

-                       username=username,

                        repo=repo.name,

+                       username=username,

+                       namespace=repo.namespace,

                        identifier=identifier,

                        filename=filepath) }}"

                {% endif %}
@@ -469,8 +508,12 @@ 

    <div class="tab-pane active" role="tabpanel" id="comments">

      <section class="request_comment" id="request_comment">

      {% if pull_request.comments %}

-       <form action="{{ url_for('.pull_request_drop_comment', username=username,

-           repo=repo.name, requestid=requestid) }}" method="post"

+       <form action="{{ url_for('.pull_request_drop_comment',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             requestid=requestid)

+           }}" method="post"

            onsubmit="return try_async_comment(this, null)">

  

        {% for comment in pull_request.comments %}
@@ -522,7 +565,10 @@ 

  

            {% if authenticated %}

              <form action="{{ url_for(

-                 'pull_request_add_comment', username=username, repo=repo.name,

+                 'pull_request_add_comment',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

                  requestid=requestid) }}"

                  method="post" onsubmit="return try_async_comment(this, false)">

                {{ mergeform.csrf_token }}
@@ -574,8 +620,12 @@ 

        <div id="merge-alert" class="alert text-xs-center" style="display:none;" role="alert">

        {% if pull_request.status == 'Open' and g.repo_admin %}

         <div>

-         <form action="{{ url_for('merge_request_pull', username=username,

-             repo=repo.name, requestid=requestid) }}" method="POST">

+         <form action="{{ url_for('merge_request_pull',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 requestid=requestid)

+           }}" method="POST">

            {{ mergeform.csrf_token }}

            <button id="merge_btn" type="submit" class="btn btn-block">Merge</button>

          </form>
@@ -601,7 +651,11 @@ 

                <li class="list-group-item">

                  <div>

                    <span><a href="{{ flag.url }}">{{ flag.username }}</a></span>

-                   <div class="pull-xs-right"><span class="label {%if flag.percent <= 10%}label-danger{%elif flag.percent <= 90%}label-warning{%else%}label-success{%endif%}">{{ flag.percent }}%</label></div>

+                   <div class="pull-xs-right"><span class="label {%

+                     if flag.percent <= 10 %}label-danger{%

+                     elif flag.percent <= 90 %}label-warning{%

+                     else %}label-success{%

+                     endif %}">{{ flag.percent }}%</label></div>

                  </div>

                  <small><div class="clearfix">

                      <span>{{ flag.comment }}</span>
@@ -619,7 +673,10 @@ 

        <div class="card-block">

          {% if authenticated and mergeform and pull_request.status == 'Open' and g.repo_admin %}

            <form method="POST" action="{{ url_for('.set_assignee_requests',

-               username=username, repo=repo.name, requestid=requestid) }}">

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace,

+               requestid=requestid) }}">

              <fieldset class="form-group issue-metadata-form">

                <label><strong>Assignee</strong></label>

                <div>
@@ -846,8 +903,8 @@ 

        if (value != ""){

          var sel = $('#branch_select');

          var final_url = "{{ url_for('.new_request_pull', username=username,

-           repo=repo.name, branch_from=branch_from,

-           branch_to='--') }}";

+           namespace=repo.namespace, repo=repo.name,

+           branch_from=branch_from, branch_to='--') }}";

          final_url = final_url.replace('--', sel.val());

          window.location.href = final_url;

        }
@@ -878,7 +935,10 @@ 

        var filename = $( this ).attr('data-filename');

        var tree_id = $( this ).attr('data-tree');

        var url = "{{ url_for(

-         'pull_request_add_comment', username=username, repo=repo.name,

+         'pull_request_add_comment',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace,

          requestid=requestid, commit='', filename='', row='') }}".slice(0, -2);

        url = url + commit + '/' + filename + '/' + row

        if (tree_id) {
@@ -922,8 +982,9 @@ 

          if ($( "#previewinmarkdown" ).hasClass("inactive")){

            var _text = $( "#comment" ).val();

            var _url = "{{ url_for('markdown_preview',

+                         repo=repo.name,

                          user=repo.user.user if repo.is_fork,

-                         repo=repo.name) | safe}}";

+                         namespace=repo.namespace) | safe}}";

            $.ajax({

              url: _url ,

              type: 'POST',
@@ -1201,8 +1262,16 @@ 

     });

  

     {% if config.get('ENABLE_TICKETS', True) %}

-      $.when($.get("{{ url_for('api_ns.api_view_issues', repo=repo.name, username=username, status='all') }}"),

-             $.get("{{ url_for('api_ns.api_pull_request_views', repo=repo.name, username=username, status='all') }}")

+      $.when($.get("{{ url_for('api_ns.api_view_issues',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     status='all') }}"),

+             $.get("{{ url_for('api_ns.api_pull_request_views',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     status='all') }}")

       ).done(function(issuesResp, prResp) {

         // 0 is the api response

         var issuesAndPrs = issuesResp[0]['issues'].concat(prResp[0]['requests']);
@@ -1221,7 +1290,11 @@ 

         $("#comment").atwho(issueAndPrConfig);

        });

     {% else %}

-      $.get("{{ url_for('api_ns.api_pull_request_views', repo=repo.name, username=username, status='all') }}")

+      $.get("{{ url_for('api_ns.api_pull_request_views',

+                         repo=repo.name,

+                         username=username,

+                         namespace=repo.namespace,

+                         status='all') }}")

           .done(function(prResp) {

               var data = $.map(prResp['requests'], function(pr, idx) {

                   return {

@@ -3,7 +3,10 @@ 

  <section class="add_comment">

  

    <form action="{{ url_for(

-     'pull_request_add_comment', username=username, repo=repo.name,

+     'pull_request_add_comment',

+     repo=repo.name,

+     username=username,

+     namespace=repo.namespace,

      requestid=requestid, commit=commit, tree_id=tree_id, filename=filename,

      row=row) }}"

      method="post" onsubmit="return try_async_comment(this, true)">

@@ -1,7 +1,8 @@ 

  {% extends "repo_master.html" %}

  {% from "_formhelper.html" import render_bootstrap_field %}

  

- {% block title %}Edit PR#{{ request.id }}: {{ request.title }} - {{ repo.name }}{% endblock %}

+ {% block title %}Edit PR#{{ request.id }}: {{ request.title }} - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  {% block header %}
@@ -21,8 +22,10 @@ 

        </div>

        <div class="card-block" class="edit_tag">

          <form action="{{ url_for('.request_pull_edit',

-                            username=username, repo=repo.name, requestid=request.id)

-                          }}" method="post">

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             requestid=request.id) }}" method="post">

  

            <table>

              {{ render_bootstrap_field(
@@ -36,7 +39,10 @@ 

              <input type="submit" class="btn btn-primary" value="Edit">

              {{ form.csrf_token }}

              <a href="{{ url_for('request_pull',

-               username=username, repo=repo.name, requestid=request.id)}}">

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace,

+               requestid=request.id)}}">

                <input type="button" class="btn btn-secondary" value="Cancel" />

              </a>

              {{ form.csrf_token }}

@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}Releases - {{ repo.name }}{% endblock %}

+ {% block title %}Releases - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  {% block repo %}
@@ -9,7 +10,10 @@ 

    Releases

  {% if config.get('UPLOAD_FOLDER_PATH') and config.get('UPLOAD_FOLDER') %}

    {% if g.repo_admin %}

-     <a class="pull-xs-right" href="{{ url_for('.new_release', username=username, repo=repo.name) }}"

+     <a class="pull-xs-right" href="{{ url_for('.new_release',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace) }}"

          method="get" class="icon">

      <button class="btn btn-primary" type="submit" title="Upload a tarball">

        <span class="icon icon-plus blue"></span>
@@ -34,8 +38,10 @@ 

    <div class="list-group">

      {% for tag in tags %}

        <a class="list-group-item" href="{{ url_for('.view_tree',

-                     username=username, repo=repo.name,

-                     identifier=tag['object'].oid) }}">

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             identifier=tag['object'].oid) }}">

          <div class="pull-xs-right">{{tag['date'] | humanize}}

            <span id="tagid" class="label label-default">

              {{ tag['object'].oid | short }}

@@ -1,7 +1,8 @@ 

  {% extends "repo_master.html" %}

  {% from "_formhelper.html" import render_bootstrap_field %}

  

- {% block title %}Remote Pull request {{ repo.name }}{% endblock %}

+ {% block title %}Remote Pull request {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  {% block repo %}
@@ -28,8 +29,11 @@ 

  </p>

  

  {% if form %}

-   <form action="{{ url_for('.new_remote_request_pull', username=username,

-     repo=repo.name) }}" method="post">

+   <form action="{{ url_for(

+     '.new_remote_request_pull',

+     repo=repo.name,

+     username=username,

+     namespace=repo.namespace) }}" method="post">

      <div class="card-block">

        {{ render_bootstrap_field(

            form.title, size=80,
@@ -53,7 +57,11 @@ 

        <input type="submit" class="btn btn-primary" value="Preview">

        {{ form.csrf_token }}

  

-       <a href="{{ url_for('view_repo', username=username, repo=repo.name)}}">

+       <a href="{{ url_for(

+         'view_repo',

+         repo=repo.name,

+         username=username,

+         namespace=repo.namespace)}}">

          <input type="button" class="btn btn-secondary" value="Cancel" />

        </a>

      </p>

@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}{{ select.capitalize() }} - {{ repo.name }}{% endblock %}

+ {% block title %}{{ select.capitalize() }} - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  {% block repo %}
@@ -87,7 +88,10 @@ 

                    <span class="oi text-muted" data-glyph="random"

                      title="Default branch"></span>

                    <a href="{{ url_for('view_repo_branch',

-                     username=username, repo=repo.name, branchname=head) }}"

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     branchname=head) }}"

                      title="{{ head }}" data-toggle="tooltip">

                      {{ head }}

                    </a>
@@ -106,7 +110,10 @@ 

                    <span class="oi text-muted" data-glyph="random"></span>

                    {% if branchname != branch %}

                    <a class="" href="{{ url_for('view_repo_branch',

-                     username=username, repo=repo.name, branchname=branch) }}"

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     branchname=branch) }}"

                      title="{{ branch }}" data-toggle="tooltip">{{ branch }}

                    </a>

                    {% else %}
@@ -118,7 +125,10 @@ 

                    {% if g.repo_admin and branch != head %}

                    <form id="delete_branch_form-{{ branch | replace('/', '_') }}" action="{{

                      url_for('.delete_branch',

-                             username=username, repo=repo.name, branchname=branch)

+                             repo=repo.name,

+                             username=username,

+                             namespace=repo.namespace,

+                             branchname=branch)

                      }}" method="post" class="inline icon del_icon"

                      onsubmit="return confirm('Are you sure you want to remove the branch: {{ branch }}?\nThis cannot be un-done!');">

                      {{ form.csrf_token }}
@@ -220,8 +230,11 @@ 

                <div class="list-group list-group-flush">

                  {% for commit in last_commits %}

                    <a href="{{

-                       url_for('view_commit', username=username,

-                       repo=repo.name, commitid=commit.hex) }}" class="list-group-item">

+                       url_for('view_commit',

+                       repo=repo.name,

+                       username=username,

+                       namespace=repo.namespace,

+                       commitid=commit.hex) }}" class="list-group-item">

                      <div class="commitdate" title="{{ commit.commit_time|format_ts }}">

                        <small>

                          <strong>
@@ -283,6 +296,7 @@ 

              'new_request_pull',

              repo=repo.name,

              username=repo.user.user if repo.is_fork else None,

+             namespace=repo.namespace,

              branch_to=head or 'master',

              branch_from='') }}";

            html = '<div class="alert alert-info" role="alert"> \
@@ -321,6 +335,7 @@ 

                'request_pull',

                repo=repo.name,

                username=repo.user.user if repo.is_fork else None,

+               namespace=repo.namespace,

                requestid=-100) }}";

            url = url.replace(-100, res.message.branch_w_pr[branch]);

            var html = ' \

@@ -1,6 +1,7 @@ 

  {% extends "master.html" %}

  

- {% block title %}{{ repo.name }}{% endblock %}

+ {% block title %}{{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  
@@ -9,46 +10,67 @@ 

    <div class="container">

      <header>

          <h2 class="repo-name m-b-0">

-             <a href="{{ url_for('view_repo', username=username, repo=repo.name)}}">

+             <a href="{{ url_for('view_repo',

+                 namespace=repo.namespace, username=username, repo=repo.name)}}">

                {% if repo.is_fork -%}

                  <span class="oi" data-glyph="fork"></span>

-                 {{ repo.user.user }}/{{ repo.name}}

+                 {{ repo.user.user }}/{{

+                     repo.namespace + '/' if repo.namespace

+                 }}{{ repo.name}}

                {%- else -%}

-                 {{ repo.name }}

+                 {{ repo.namespace + '/' if repo.namespace }}{{ repo.name }}

                {%- endif -%}

              </a>

              {% if authenticated %}

              <div class="pull-xs-right">

                {% if repo.settings.get('issue_tracker', True)

                      and config.get('ENABLE_TICKETS', True)%}

-               <a href="{{ url_for('new_issue', username=username, repo=repo.name) }}"

+               <a href="{{ url_for('new_issue',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace) }}"

                  class="btn btn-success btn-sm">New Issue</a>

                {% endif %}

                <div class="btn-group">

                {% if not repo.is_fork %}

                  <form method="POST" name="fork_project" id="fork_project"

                    action="{{ url_for(

-                     '.fork_project', repo=repo.name, username=username) }}">

+                     '.fork_project',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace) }}">

                    {{ forkbuttonform.csrf_token }}

                  </form>

                  <button class="btn btn-sm btn-secondary"

                    onclick="$('#fork_project').submit();">

                    <span class="oi" data-glyph="fork"></span> Fork</button>

                {% endif %}

-                 <button title="{%- if is_watching(repo.name, repo.user.user if repo.is_fork else None)

+                 <button title="{%- if is_watching(

+                     repo.name,

+                     repo.user.user if repo.is_fork else None,

+                     repo.namespace)

                  %}You are watching this project{% else

                  %}You are not watching this project{% endif -%}"

                  type="button" class="btn btn-sm dropdown-toggle

-                 {%- if is_watching(repo.name, repo.user.user if repo.is_fork else None)

+                 {%- if is_watching(

+                     repo.name,

+                     repo.user.user if repo.is_fork else None,

+                     repo.namespace)

                  %} btn-primary{% else %} btn-secondary{% endif -%}"

                  data-toggle="dropdown" id="watch-button">

                    <span class="oi" data-glyph="eye"></span>

                  </button>

                  <div class="dropdown-menu dropdown-menu-right watch-menu">

                    <form method="POST" id="watch_project" name="watch_project"

-                       action="{{ url_for('.watch_repo', user=repo.user.user if repo.is_fork else None,

-                                          repo=repo.name, watch=0) }}">

-                    {%- if is_watching(repo.name, repo.user.user if repo.is_fork else None)

+                       action="{{ url_for('.watch_repo',

+                         repo=repo.name,

+                         user=repo.user.user if repo.is_fork else None,

+                         namespace=repo.namespace,

+                         watch=0) }}">

+                    {%- if is_watching(

+                         repo.name,

+                         repo.user.user if repo.is_fork else None,

+                         repo.namespace)

                     %}

                     <a class="dropdown-item" id="unwatch_button">Stop watching {{repo.name}}</a>

                     {% else %}
@@ -70,12 +92,12 @@ 

          {% if repo.is_fork and repo.parent %}

          <div class="m-t-0">

              Forked from

-             {% if repo.parent.is_fork %}

-             <a href="{{ url_for('view_repo', repo=repo.parent.name, username=repo.parent.user.user)}}">

-             {% else %}

-             <a href="{{ url_for('view_repo', repo=repo.parent.name)}}">

-             {% endif %}

-                 {{ repo.parent.fullname }}

+             <a href="{{ url_for(

+                 'view_repo',

+                 repo=repo.parent.name,

+                 username=repo.parent.user.user if repo.parent.is_fork else None,

+                 namespace=repo.parent.namespace)}}">

+                 {{ repo.parent.namespace + '/' if repo.parent.namespace }}{{ repo.parent.fullname }}

              </a>

          </div>

          {% elif repo.is_fork and not repo.parent %}
@@ -93,7 +115,11 @@ 

          <a {%

            if select == 'overview' %}class="nav-link active" {%

            else %}class="nav-link" {%

-           endif %}href="{{ url_for('view_repo',username=username, repo=repo.name) }}">

+           endif %}href="{{ url_for(

+               'view_repo',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace) }}">

              <span class="oi hidden-md-up" data-glyph="home"></span>

              <span class="hidden-sm-down">Overview</span>

          </a>
@@ -103,7 +129,11 @@ 

            <a  {%

              if select == 'docs' %}class="active nav-link" {%

              else %}class="nav-link" {%

-             endif %}href="{{ url_for('.view_docs', username=username, repo=repo.name) }}">

+             endif %}href="{{ url_for(

+                 '.view_docs',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}">

                <span class="oi hidden-md-up" data-glyph="book"></span>

                <span class="hidden-sm-down">Docs</span>

            </a>
@@ -115,8 +145,12 @@ 

            <a {%

              if select == 'commits' %}class="active nav-link" {%

              else %}class="nav-link" {%

-             endif %}href="{{ url_for('.view_commits', username=username,

-                      repo=repo.name, branchname=branchname) }}">

+             endif %}href="{{ url_for(

+                 '.view_commits',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 branchname=branchname) }}">

                <span class="oi hidden-md-up" data-glyph="spreadsheet">

                </span><span class="hidden-sm-down">Commits</span>

              </a>
@@ -127,8 +161,12 @@ 

            <a {%

              if select == 'tree' %}class="active nav-link" {%

              else %}class="nav-link"{%

-             endif %} href="{{ url_for('.view_tree', username=username,

-                      repo=repo.name, identifier=branchname) }}">

+             endif %} href="{{ url_for(

+                 '.view_tree',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 identifier=branchname) }}">

                <span class="oi hidden-md-up" data-glyph="file"></span>

                <span class="hidden-sm-down">Files</span>

            </a>
@@ -138,8 +176,11 @@ 

            <a {%

              if select == 'tags' %}class="active nav-link" {%

              else %}class="nav-link" {%

-             endif %}href="{{ url_for('.view_tags', username=username,

-                      repo=repo.name) }}">

+             endif %}href="{{ url_for(

+                 '.view_tags',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}">

                <span class="oi hidden-md-up" data-glyph="box"></span>

                <span class="hidden-sm-down">Releases</span>

            </a>
@@ -151,8 +192,11 @@ 

              <a {%

                if select == 'issues' %}class="active nav-link" {%

                else %}class="nav-link" {%

-               endif %}href="{{ url_for('.view_issues', username=username,

-                        repo=repo.name) }}">

+               endif %}href="{{ url_for(

+                   '.view_issues',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace) }}">

                  <span class="oi hidden-md-up" data-glyph="warning"></span>

                  <span class="hidden-sm-down">Issues&nbsp;</span>

                  <span class="label label-default label-pill hidden-sm-down">
@@ -167,8 +211,11 @@ 

            <a {%

              if select == 'requests' %}class="active nav-link" {%

              else %}class="nav-link" {%

-             endif %}href="{{ url_for('.request_pulls', username=username,

-                      repo=repo.name) }}">

+             endif %}href="{{ url_for(

+                 '.request_pulls',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}">

                <span class="oi hidden-md-up" data-glyph="task"></span>

                <span class="hidden-sm-down">Pull Requests&nbsp;</span>

                <span class="label label-default label-pill hidden-sm-down">
@@ -183,8 +230,11 @@ 

            <a {%

              if select == 'forks' %}class="active nav-link" {%

              else %}class="nav-link" {%

-             endif %}href="{{ url_for('.view_forks', username=username,

-                      repo=repo.name) }}">

+             endif %}href="{{ url_for(

+                 '.view_forks',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}">

                <span class="oi hidden-md-up" data-glyph="fork"></span>

                <span class="hidden-sm-down">Forks&nbsp;</span>

                <span class="hidden-sm-down label label-default label-pill">
@@ -201,7 +251,10 @@ 

                if select == 'settings' %}class="active nav-link" {%

                else %}class="nav-link" {%

                endif %}href="{{ url_for(

-                 '.view_settings', repo=repo.name, username=username) }}">

+                   '.view_settings',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace) }}">

                  <span class="oi" data-glyph="cog"></span>

                  <span class="hidden-sm-down">Settings</span>

              </a>
@@ -210,8 +263,12 @@ 

        {% endif %}

        {% if endpoint == 'view_docs' %}

        <li class="nav-item pull-xs-right">

-         <a class="nav-link" href="{{ config['DOC_APP_URL'] + url_for('.view_repo',

-                 username=username, repo=repo.name, filename=filename)

+         <a class="nav-link" href="{{ config['DOC_APP_URL'] + url_for(

+             '.view_repo',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             filename=filename)

            }}" target="_blank" title="Open to a new tab" rel="noopener noreferrer">

            <span class="oi" data-glyph="external-link"></span>

          </a>

file modified
+62 -21
@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}Pull requests - {{ repo.name }}{% endblock %}

+ {% block title %}Pull requests - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  
@@ -24,8 +25,11 @@ 

          File Pull Request

        </button>

        <div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenu1">

-         <a class="dropdown-item" href="{{ url_for('new_remote_request_pull',

-         username=username, repo=repo.name) }}">

+         <a class="dropdown-item" href="{{ url_for(

+             'new_remote_request_pull',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace) }}">

            <small>Remote pull-request</small>

          </a>

        </div>
@@ -38,16 +42,26 @@ 

        <a class="btn {%

              if status|lower in ['open', 'true'] %}btn-primary{%

              else %}btn-secondary{%

-             endif %} btn-sm" href="{{ url_for('request_pulls', username=username,

-                  repo=repo.name) }}">Open</a>

+             endif %} btn-sm" href="{{ url_for(

+                 'request_pulls',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}">Open</a>

        <a class="btn {%

          if status|lower in ['open', 'true'] %}btn-secondary{%

          else %}btn-primary{%

-         endif %} btn-sm" href="{{ url_for('request_pulls', username=username,

-                repo=repo.name) }}?status=0">Closed</a>

+         endif %} btn-sm" href="{{ url_for(

+             'request_pulls',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace,

+             status=0) }}">Closed</a>

    </span>

-   <a class="btn btn-secondary btn-sm pull-xs-right" href="{{ url_for('request_pulls',

-   username=username, repo=repo.name) }}">Reset Filters</a>

+   <a class="btn btn-secondary btn-sm pull-xs-right" href="{{ url_for(

+     'request_pulls',

+     repo=repo.name,

+     username=username,

+     namespace=repo.namespace) }}">Reset Filters</a>

  </div>

  </div>

  <div class="card m-t-1">
@@ -60,13 +74,21 @@ 

              <th class="close_date nowrap">Closed</th>

              {% endif %}

              <th class="open_by">

-               Reporter(<a href="{{ url_for('request_pulls', username=username,

-                 repo=repo.name, assignee=assignee, status=status) }}">reset</a>)

+               Reporter(<a href="{{ url_for(

+                 'request_pulls',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 assignee=assignee, status=status) }}">reset</a>)

              </th>

              {% if status|lower == 'open' %}

              <th class="assigned">

-               Assignee(<a href="{{ url_for('request_pulls', username=username,

-                 repo=repo.name, author=author, status=status) }}">reset</a>)

+               Assignee(<a href="{{ url_for(

+                 'request_pulls',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 author=author, status=status) }}">reset</a>)

              </th>

              {% endif %}

          </tr>
@@ -77,8 +99,12 @@ 

      {% for request in requests %}

          <tr>

              <td>

-               <a href="{{ url_for('request_pull', username=username,

-                   repo=repo.name, requestid=request.id) }}">

+               <a href="{{ url_for(

+                   'request_pull',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace,

+                   requestid=request.id) }}">

                  <span class="label label-default">PR#{{ request.id }}</span>

                  {% if status|lower not in ['open', 'true'] %}<span class="label {%

                      if request.status|lower == 'merged' %}label-success{%
@@ -110,8 +136,12 @@ 

              </td>

              {% endif %}

              <td class="nowrap">

-               <a href="{{ url_for('request_pulls', username=username,

-                   repo=repo.name, author=request.user.user,

+               <a href="{{ url_for(

+                   'request_pulls',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace,

+                   author=request.user.user,

                    assignee=assignee, status=status) }}"

                    title="Filter requests by reporter">

                  {{ request.user.default_email | avatar(16) | safe }}
@@ -121,16 +151,24 @@ 

              {% if status|lower in ['open', 'true'] %}

              <td class="nowrap">

                {% if request.assignee %}

-               <a href="{{ url_for('request_pulls', username=username,

-                 repo=repo.name, assignee=request.assignee.username,

+               <a href="{{ url_for(

+                 'request_pulls',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 assignee=request.assignee.username,

                  author=author, status=status) }}"

                  title="Filter issues by assignee">

                  {{ request.assignee.default_email | avatar(16) | safe }}

                  {{ request.assignee.user }}

                </a>

                {% else %}

-               <a class="text-muted" href="{{ url_for('request_pulls', username=username,

-                 repo=repo.name, author=author, status=status) }}">unassigned</a>

+               <a class="text-muted" href="{{ url_for(

+                 'request_pulls',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 author=author, status=status) }}">unassigned</a>

                {% endif %}

              </td>

              {% endif %}
@@ -157,6 +195,7 @@ 

      url: '{{ url_for("internal_ns.get_pull_request_ready_branch") }}' ,

      type: 'POST',

      data: {

+       namespace: "{{ repo.namespace }}",

        repo: "{{ repo.name }}",

        repouser: "{{ g.fas_user.username }}",

        csrf_token: "{{ form.csrf_token.current_token }}",
@@ -173,6 +212,7 @@ 

              'new_request_pull',

              repo=repo.name,

              username=g.fas_user.username,

+             namespace=repo.namespace,

              branch_to=head,

              branch_from='') }}" + branch;

            html = '<small><a class="dropdown-item" \
@@ -211,6 +251,7 @@ 

              'new_request_pull',

              repo=repo.name,

              username=repo.user.user if repo.is_fork else None,

+             namespace=repo.namespace,

              branch_to=head,

              branch_from='') }}";

            html = '<small><a class="dropdown-item" href="' + url + branch + '">'

file modified
+49 -17
@@ -1,6 +1,7 @@ 

  {% extends "repo_master.html" %}

  

- {% block title %}Roadmap - {{ repo.name }}{% endblock %}

+ {% block title %}Roadmap - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home"%}

  

  
@@ -11,12 +12,17 @@ 

      {{ issues|count }} Milestones

      <span class="btn-group btn-group-sm pull-xs-right" role="group">

        <a href="{{ url_for(

-           'view_issues', username=username, repo=repo.name) }}"

-          class="btn btn-secondary btn-sm">

+           'view_issues',

+           repo=repo.name,

+           username=username,

+           namespace=repo.namespace) }}" class="btn btn-secondary btn-sm">

          List

        </a>

-       <a href="{{ url_for('new_issue', username=username, repo=repo.name) }}"

-           class="btn btn-success btn-sm">

+       <a href="{{ url_for(

+           'new_issue',

+           repo=repo.name,

+           username=username,

+           namespace=repo.namespace) }}" class="btn btn-success btn-sm">

          New Issue

        </a>

      </span>
@@ -35,14 +41,28 @@ 

    <span class="btn-group btn-group-sm issues-tagbar" role="group">

      {% if not status %}

        <a class="btn btn-secondary btn-sm" href="{{ url_for(

-           'view_roadmap', username=username, repo=repo.name) }}">Open</a>

+           'view_roadmap',

+           repo=repo.name,

+           username=username,

+           namespace=repo.namespace) }}">Open</a>

        <a class="btn btn-primary btn-sm" href="{{ url_for(

-           'view_roadmap', username=username, repo=repo.name, status='All') }}">All</a>

+           'view_roadmap',

+           repo=repo.name,

+           username=username,

+           namespace=repo.namespace,

+           status='All') }}">All</a>

      {% else %}

        <a class="btn btn-primary btn-sm" href="{{ url_for(

-           'view_roadmap', username=username, repo=repo.name) }}">Open</a>

+           'view_roadmap',

+           repo=repo.name,

+           username=username,

+           namespace=repo.namespace) }}">Open</a>

        <a class="btn btn-secondary btn-sm" href="{{ url_for(

-           'view_roadmap', username=username, repo=repo.name, status='All') }}">All</a>

+           'view_roadmap',

+           repo=repo.name,

+           username=username,

+           namespace=repo.namespace,

+           status='All') }}">All</a>

      {% endif %}

    </span>

    <span class="oi m-l-2" data-glyph="tag"></span>
@@ -50,15 +70,23 @@ 

      {% for tag in tag_list %}

        {% if tag.tag in tags %}

          <a class="btn btn-secondary btn-sm {% if tag.tag in tags%}active{% endif %}"

-             href="{{ url_for('view_roadmap', username=username,

-                              repo=repo.name, milestone=tag.tag,

-                              status='All' if not status else None) }}"

+             href="{{ url_for(

+                 'view_roadmap',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 milestone=tag.tag,

+                 status='All' if not status else None) }}"

                     title="Filter issues by milestone">

        {% else %}

          <a class="btn btn-secondary btn-sm {% if tag.tag in tags%}active{%endif%}"

-             href="{{ url_for('view_roadmap', username=username,

-                              repo=repo.name, milestone=tag.tag,

-                              status='All' if not status else None) }}"

+             href="{{ url_for(

+                 'view_roadmap',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 milestone=tag.tag,

+                 status='All' if not status else None) }}"

                     title="Filter issues by milestone">

        {% endif %}

  
@@ -100,8 +128,12 @@ 

                {% if issue.private %}

                <span class="oi red-icon" data-glyph="lock-locked" title="Private issue"></span>

                {% endif %}

-               <a {% if issue.status != 'Open' %}class="text-muted"{% endif %} href="{{ url_for('view_issue', username=username,

-                          repo=repo.name, issueid=issue.id) }}">

+               <a {% if issue.status != 'Open' %}class="text-muted"{% endif %} href="{{ url_for(

+                   'view_issue',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace,

+                   issueid=issue.id) }}">

                  {{ issue.title | noJS("img") | safe }}

                </a>

                 &nbsp;&nbsp;

file modified
+94 -27
@@ -1,7 +1,8 @@ 

  {% extends "repo_master.html" %}

  {% from "_formhelper.html" import render_field_in_row %}

  

- {% block title %}{{ select.capitalize() }} - {{ repo.name }}{% endblock %}

+ {% block title %}{{ select.capitalize() }} - {{

+     repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

  

  {% block repo %}
@@ -16,7 +17,9 @@ 

          </div>

          <div class="card-block">

            <form action="{{ url_for('.update_project',

-                           username=username, repo=repo.name) }}" method="post">

+                           repo=repo.name,

+                           username=username,

+                           namespace=repo.namespace) }}" method="post">

              <fieldset class="form-group">

                <label for="description">Description</label>

                <input class="form-control" name="description" value="{{
@@ -53,7 +56,9 @@ 

          </div>

          <div class="card-block">

            <form action="{{ url_for('change_ref_head',

-                  username=username, repo=repo.name) }}" method="post">

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}" method="post">

              {{ branches_form.csrf_token }}

              {{ branches_form.branches(class_="c-select") }}

              <input class="btn btn-primary" type="submit" value="Make Default"/>
@@ -84,7 +89,9 @@ 

            </div>

  

            <form action="{{ url_for('.new_repo_hook_token',

-                         username=username, repo=repo.name) }}"

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}"

                method="post" class="icon">

            <button class="btn btn-primary" type="submit"

              onclick="return confirm('Are you sure to generate a new token for '
@@ -138,8 +145,12 @@ 

                <span class="text-danger btn-align"><strong>Expired</strong> since {{ token.expiration.date() }}</span>

              {% else %}

                <span class="text-success btn-align"><strong>Valid</strong> until: {{ token.expiration.date() }}</span>

-               <form class="pull-xs-right" action="{{ url_for('.revoke_api_token',

-                     username=username, repo=repo.name, token_id=token.id) }}"

+               <form class="pull-xs-right" action="{{ url_for(

+                   '.revoke_api_token',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace,

+                   token_id=token.id) }}"

                  method="post" class="icon">

                  <button class="btn btn-danger" type="submit"

                      onclick="return confirm('Are you sure to revoke this token ?'
@@ -182,7 +193,11 @@ 

          </ul>

          {% endif %}

          <div class="card-block">

-           <a href="{{ url_for('.add_token', username=username, repo=repo.name) }}"

+           <a href="{{ url_for(

+                 '.add_token',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}"

                method="post" class="icon">

            <button class="btn btn-primary" type="submit"

              title="Generate a new API token">
@@ -201,7 +216,9 @@ 

          </div>

          <div class="card-block">

            <form action="{{ url_for('.view_settings',

-                           username=username, repo=repo.name) }}" method="post">

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}" method="post">

              {% for key in repo.settings | sort %}

              {% if not config.get('ENABLE_TICKETS', True) and key in ['issue_tracker'] %}

              {% elif not config.get('DOC_APP_URL') and key in ['project_documentation'] %}
@@ -241,8 +258,11 @@ 

            Re-generate git repos

          </div>

          <div class="card-block">

-           <form action="{{ url_for('.regenerate_git',

-                           username=username, repo=repo.name) }}" method="post"

+           <form action="{{ url_for(

+               '.regenerate_git',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace) }}" method="post"

                  class="icon">

              <input name="regenerate" value="tickets" type="hidden"/>

              <button class="btn btn-primary" type="submit"
@@ -251,8 +271,11 @@ 

              </button>

              {{ form.csrf_token }}

            </form>

-           <form class="m-t-2" action="{{ url_for('.regenerate_git',

-                           username=username, repo=repo.name) }}" method="post"

+           <form class="m-t-2" action="{{ url_for(

+               '.regenerate_git',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace) }}" method="post"

                  class="icon">

              <input name="regenerate" value="requests" type="hidden"/>

              <button class="btn btn-primary" type="submit"
@@ -276,12 +299,20 @@ 

            <p>Below is the list of user having commit rights to this repo.</p>

  

            <p>

-             <a href="{{ url_for('.add_user', username=username, repo=repo.name) }}"

+             <a href="{{ url_for(

+                   '.add_user',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace) }}"

                  class="btn btn-primary">

                  add user

              </a>

  

-             <a href="{{ url_for('.add_group_project', username=username, repo=repo.name) }}"

+             <a href="{{ url_for(

+                   '.add_group_project',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace) }}"

                  class="btn btn-primary">

                  add group

              </a>
@@ -302,7 +333,12 @@ 

                  &nbsp; {{ user.user }}

                </a>

                <form class="pull-xs-right" method="POST"

-                 action="{{ url_for('.remove_user', username=username, repo=repo.name, userid=user.id) }}">

+                 action="{{ url_for(

+                     '.remove_user',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     userid=user.id) }}">

                  <button

                    onclick="return confirm('You sure you want to remove this user from this project?');"

                    title="Remove user" class="btn btn-danger btn-sm">
@@ -319,7 +355,12 @@ 

                  &nbsp; {{ group.group_name }}

                </a>

                <form class="pull-xs-right" method="POST"

-                 action="{{ url_for('.remove_group_project', username=username, repo=repo.name, groupid=group.id) }}">

+                 action="{{ url_for(

+                     '.remove_group_project',

+                     repo=repo.name,

+                     username=username,

+                     namespace=repo.namespace,

+                     groupid=group.id) }}">

                  <button

                    onclick="return confirm('You sure you want to remove this group from this project?');"

                    title="Remove group" class="btn btn-danger btn-sm pull-xs-right">
@@ -387,8 +428,11 @@ 

              </span>

            </p>

          </div>

-         <form action="{{ url_for('.update_priorities',

-                           username=username, repo=repo.name) }}"

+         <form action="{{ url_for(

+               '.update_priorities',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace) }}"

              method="post" class="icon">

            {{ tag_form.csrf_token }}

            <div class="card-block">
@@ -453,8 +497,11 @@ 

              corresponding to one of the milestones defined here.

            </p>

          </div>

-         <form action="{{ url_for('.update_milestones',

-                           username=username, repo=repo.name) }}"

+         <form action="{{ url_for(

+               '.update_milestones',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace) }}"

              method="post" class="icon">

            {{ tag_form.csrf_token }}

            <div class="card-block">
@@ -514,13 +561,21 @@ 

          <ul class="list-group list-group-flush">

          {% for tag in tags %}

            <li class="list-group-item clearfix">

-             <a href="{{ url_for('view_issues', username=username,

-               repo=repo.name, tags=tag.tag) }}">

+             <a href="{{ url_for(

+                 'view_issues',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace,

+                 tags=tag.tag) }}">

                <span class="oi" data-glyph="tag"></span>&nbsp; {{ tag.tag }}

              </a>

              <div class="pull-xs-right">

              <form class="icon del_icon pull-xs-right" method="POST"

-               action="{{ url_for('remove_tag', username=username, repo=repo.name) }}">

+               action="{{ url_for(

+                 'remove_tag',

+                 repo=repo.name,

+                 username=username,

+                 namespace=repo.namespace) }}">

                <input type="hidden" value="{{ tag.tag }}" name="tag" />

                {{ tag_form.csrf_token }}

                <button
@@ -530,7 +585,11 @@ 

                </button>

              </form>

              <a href="{{ url_for(

-                   '.edit_tag',username=username, repo=repo.name, tag=tag.tag) }}">

+                   '.edit_tag',

+                   repo=repo.name,

+                   username=username,

+                   namespace=repo.namespace,

+                   tag=tag.tag) }}">

                <button class="btn btn-default btn-sm" title="Edit tag">

                  <span class="oi" data-glyph="pencil"></span>

                </button>
@@ -550,8 +609,11 @@ 

            Delete Project

          </div>

          <div class="card-block">

-         <form action="{{ url_for('.delete_repo',

-                         username=username, repo=repo.name) }}"

+         <form action="{{ url_for(

+             '.delete_repo',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace) }}"

                method="post" class="icon">

            <button class="btn btn-danger" type="submit"

              onclick="return confirm('Are you sure to delete {{repo.name}}? \nThis is final and cannot be un-done.');"
@@ -597,7 +659,12 @@ 

    if (!_plugin) {

      return false;

    }

-   var _url = "{{ url_for('.view_plugin', repo=repo.name, username=username, plugin='') }}";

+   var _url = "{{ url_for(

+     '.view_plugin',

+     repo=repo.name,

+     username=username,

+     namespace=repo.namespace,

+     plugin='') }}";

    _url += _plugin + '/0';

    console.log(_url);

    $.ajax({

@@ -20,14 +20,14 @@ 

    <nav class="text-center">

      <ul class="pagination">

        <li {% if page <= 1%} class="disabled" {% endif %}>

-       <a href="{{ url_for('view_users') }}?page={{page - 1}}" aria-label="Previous">

+       <a href="{{ url_for('view_users', page=page -1) }}" aria-label="Previous">

            <span aria-hidden="true">&laquo;</span>

            <span class="sr-only">Newer</span>

          </a>

        </li>

        <li class="active">page {{ page }} of {{total_page}}</li>

        <li {% if page >= total_page %}class="disabled"{%endif%}>

-         <a href="{{ url_for('view_users') }}?page={{page + 1}}" aria-label="Next">

+         <a href="{{ url_for('view_users', page=page + 1) }}" aria-label="Next">

            <span aria-hidden="true">&raquo;</span>

            <span class="sr-only">Older</span>

          </a>
@@ -87,14 +87,14 @@ 

    <nav class="text-center">

      <ul class="pagination">

        <li {% if page <= 1%} class="disabled" {% endif %}>

-       <a href="{{ url_for('view_users') }}?page={{page - 1}}" aria-label="Previous">

+       <a href="{{ url_for('view_users', page=page -1) }}" aria-label="Previous">

            <span aria-hidden="true">&laquo;</span>

            <span class="sr-only">Newer</span>

          </a>

        </li>

        <li class="active">page {{ page }} of {{total_page}}</li>

        <li {% if page >= total_page %}class="disabled"{%endif%}>

-         <a href="{{ url_for('view_users') }}?page={{page + 1}}" aria-label="Next">

+         <a href="{{ url_for('view_users', page=page + 1) }}" aria-label="Next">

            <span aria-hidden="true">&raquo;</span>

            <span class="sr-only">Older</span>

          </a>

@@ -49,8 +49,12 @@ 

                      elif request.status|lower == 'open'%}label-primary{%

                      endif%}">{{request.status}}</span></td>

                  <td class="stretch-table-column">

-                   <a href="{{ url_for('request_pull', username=request.project.username if request.project.is_fork else None,

-                       repo=request.project.name, requestid=request.id) }}">

+                   <a href="{{ url_for(

+                       'request_pull',

+                       repo=request.project.name,

+                       username=request.project.username if request.project.is_fork else None,

+                       namespace=request.project.namespace,

+                       requestid=request.id) }}">

                      {{ request.title | noJS("img") | safe }}

                    </a>

                  </td>
@@ -61,9 +65,11 @@ 

                  <td class="nowrap">

                    <a href="{{ url_for(

                      'view_repo',

+                     repo=request.project.name,

                      username=request.project.username if request.project.is_fork else None,

-                     repo=request.project.name)}}">

+                     namespace=request.project.namespace) }}">

                      {{ request.project.username + '/' if request.project.is_fork }}

+                     {{ request.project.namespace + '/' if request.project.namespace }}

                      {{ request.project.name }}

                    </a>

                  </td>

file modified
+17 -5
@@ -214,8 +214,9 @@ 

  

  @APP.route('/projects/')

  @APP.route('/projects')

- @APP.route('/projects/<repo:pattern>')

- def view_projects(pattern=None):

+ @APP.route('/projects/<pattern>')

+ @APP.route('/projects/<namespace>/<pattern>')

+ def view_projects(pattern=None, namespace=None):

      """ Present the list of projects.

      """

      forks = flask.request.args.get('forks')
@@ -240,7 +241,8 @@ 

      start = limit * (page - 1)

  

      projects = pagure.lib.search_projects(

-         SESSION, pattern=pattern, fork=forks, start=start, limit=limit)

+         SESSION, pattern=pattern, namespace=namespace,

+         fork=forks, start=start, limit=limit)

  

      if len(projects) == 1:

          flask.flash('Only one result found, redirecting you to it')
@@ -372,19 +374,28 @@ 

          flask.abort(404, 'Creation of new project is not allowed on this \

                  pagure instance')

  

-     form = pagure.forms.ProjectForm()

+     namespaces = APP.config['ALLOWED_PREFIX'][:]

+     if user:

+         namespaces.extend([grp for grp in user.groups])

+ 

+     form = pagure.forms.ProjectForm(namespaces=namespaces)

+ 

      if form.validate_on_submit():

          name = form.name.data

          description = form.description.data

          url = form.url.data

          avatar_email = form.avatar_email.data

          create_readme = form.create_readme.data

+         namespace = form.namespace.data

+         if namespace:

+             namespace = namespace.strip()

  

          try:

              pagure.lib.new_project(

                  SESSION,

                  name=name,

                  description=description,

+                 namespace=namespace,

                  url=url,

                  avatar_email=avatar_email,

                  user=flask.g.fas_user.username,
@@ -401,7 +412,8 @@ 

              )

              SESSION.commit()

              pagure.lib.git.generate_gitolite_acls()

-             return flask.redirect(flask.url_for('view_repo', repo=name))

+             return flask.redirect(flask.url_for(

+                 'view_repo', repo=name, namespace=namespace))

          except pagure.exceptions.PagureException as err:

              flask.flash(str(err), 'error')

          except SQLAlchemyError as err:  # pragma: no cover

file modified
+199 -85
@@ -128,11 +128,15 @@ 

      return(diff, diff_commits, orig_commit)

  

  

- @APP.route('/<repo:repo>/pull-requests/')

- @APP.route('/<repo:repo>/pull-requests')

- @APP.route('/fork/<username>/<repo:repo>/pull-requests/')

- @APP.route('/fork/<username>/<repo:repo>/pull-requests')

- def request_pulls(repo, username=None):

+ @APP.route('/<repo>/pull-requests/')

+ @APP.route('/<repo>/pull-requests')

+ @APP.route('/<namespace>/<repo>/pull-requests/')

+ @APP.route('/<namespace>/<repo>/pull-requests')

+ @APP.route('/fork/<username>/<repo>/pull-requests/')

+ @APP.route('/fork/<username>/<repo>/pull-requests')

+ @APP.route('/fork/<username>/<namespace>/<repo>/pull-requests/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/pull-requests')

+ def request_pulls(repo, username=None, namespace=None):

      """ Request pulling the changes from the fork into the project.

      """

      status = flask.request.args.get('status', 'Open')
@@ -198,11 +202,17 @@ 

      )

  

  

- @APP.route('/<repo:repo>/pull-request/<int:requestid>/')

- @APP.route('/<repo:repo>/pull-request/<int:requestid>')

- @APP.route('/fork/<username>/<repo:repo>/pull-request/<int:requestid>/')

- @APP.route('/fork/<username>/<repo:repo>/pull-request/<int:requestid>')

- def request_pull(repo, requestid, username=None):

+ @APP.route('/<repo>/pull-request/<int:requestid>/')

+ @APP.route('/<repo>/pull-request/<int:requestid>')

+ @APP.route('/<namespace>/<repo>/pull-request/<int:requestid>/')

+ @APP.route('/<namespace>/<repo>/pull-request/<int:requestid>')

+ @APP.route('/fork/<username>/<repo>/pull-request/<int:requestid>/')

+ @APP.route('/fork/<username>/<repo>/pull-request/<int:requestid>')

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/')

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>')

+ def request_pull(repo, requestid, username=None, namespace=None):

      """ Request pulling the changes from the fork into the project.

      """

  
@@ -256,7 +266,8 @@ 

          except pagure.exceptions.PagureException as err:

              flask.flash(err.message, 'error')

              return flask.redirect(flask.url_for(

-                 'view_repo', username=username, repo=repo.name))

+                 'view_repo', username=username, repo=repo.name,

+                 namespace=namespace))

          except SQLAlchemyError as err:  # pragma: no cover

              SESSION.rollback()

              APP.logger.exception(err)
@@ -283,9 +294,12 @@ 

      )

  

  

- @APP.route('/<repo:repo>/pull-request/<int:requestid>.patch')

- @APP.route('/fork/<username>/<repo:repo>/pull-request/<int:requestid>.patch')

- def request_pull_patch(repo, requestid, username=None):

+ @APP.route('/<repo>/pull-request/<int:requestid>.patch')

+ @APP.route('/<namespace>/<repo>/pull-request/<int:requestid>.patch')

+ @APP.route('/fork/<username>/<repo>/pull-request/<int:requestid>.patch')

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>.patch')

+ def request_pull_patch(repo, requestid, username=None, namespace=None):

      """ Returns the commits from the specified pull-request as patches.

      """

      repo = flask.g.repo
@@ -336,7 +350,8 @@ 

          except pagure.exceptions.PagureException as err:

              flask.flash(err.message, 'error')

              return flask.redirect(flask.url_for(

-                 'view_repo', username=username, repo=repo.name))

+                 'view_repo', username=username, repo=repo.name,

+                 namespace=namespace))

          except SQLAlchemyError as err:  # pragma: no cover

              SESSION.rollback()

              APP.logger.exception(err)
@@ -350,16 +365,30 @@ 

      return flask.Response(patch, content_type="text/plain;charset=UTF-8")

  

  

- @APP.route('/<repo:repo>/pull-request/<int:requestid>/edit/',

-            methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/pull-request/<int:requestid>/edit',

-            methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/pull-request/<int:requestid>/edit/',

-            methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/pull-request/<int:requestid>/edit',

-            methods=('GET', 'POST'))

+ @APP.route(

+     '/<repo>/pull-request/<int:requestid>/edit/', methods=('GET', 'POST'))

+ @APP.route(

+     '/<repo>/pull-request/<int:requestid>/edit', methods=('GET', 'POST'))

+ @APP.route(

+     '/<namespace>/<repo>/pull-request/<int:requestid>/edit/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/<namespace>/<repo>/pull-request/<int:requestid>/edit',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<repo>/pull-request/<int:requestid>/edit/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<repo>/pull-request/<int:requestid>/edit',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/edit/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/edit',

+     methods=('GET', 'POST'))

  @login_required

- def request_pull_edit(repo, requestid, username=None):

+ def request_pull_edit(repo, requestid, username=None, namespace=None):

      """ Edit the title of a pull-request.

      """

  
@@ -396,7 +425,7 @@ 

                  'Could not edit this pull-request in the database',

                  'error')

          return flask.redirect(flask.url_for(

-             'request_pull', username=username,

+             'request_pull', username=username, namespace=namespace,

              repo=repo.name, requestid=requestid))

      elif flask.request.method == 'GET':

          form.title.data = request.title
@@ -412,18 +441,29 @@ 

      )

  

  

- @APP.route('/<repo:repo>/pull-request/<int:requestid>/comment',

+ @APP.route('/<repo>/pull-request/<int:requestid>/comment',

             methods=['POST'])

- @APP.route('/<repo:repo>/pull-request/<int:requestid>/comment/<commit>/'

+ @APP.route('/<repo>/pull-request/<int:requestid>/comment/<commit>/'

             '<path:filename>/<row>', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/pull-request/<int:requestid>/comment',

+ @APP.route('/<namespace>/<repo>/pull-request/<int:requestid>/comment',

+            methods=['POST'])

+ @APP.route(

+     '/<namespace>/<repo>/pull-request/<int:requestid>/comment/<commit>/'

+     '<path:filename>/<row>', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/pull-request/<int:requestid>/comment',

             methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/pull-request/<int:requestid>/comment/'

+ @APP.route('/fork/<username>/<repo>/pull-request/<int:requestid>/comment/'

             '<commit>/<path:filename>/<row>', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/'

+     'comment', methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/'

+     'comment/<commit>/<path:filename>/<row>', methods=('GET', 'POST'))

  @login_required

  def pull_request_add_comment(

          repo, requestid, commit=None,

-         filename=None, row=None, username=None):

+         filename=None, row=None, username=None, namespace=None):

      """ Add a comment to a commit in a pull-request.

      """

      repo = flask.g.repo
@@ -475,7 +515,7 @@ 

          if is_js:

              return 'ok'

          return flask.redirect(flask.url_for(

-             'request_pull', username=username,

+             'request_pull', username=username, namespace=namespace,

              repo=repo.name, requestid=requestid))

  

      if is_js and flask.request.method == 'POST':
@@ -495,13 +535,19 @@ 

      )

  

  

- @APP.route('/<repo:repo>/pull-request/<int:requestid>/comment/drop',

+ @APP.route('/<repo>/pull-request/<int:requestid>/comment/drop',

+            methods=['POST'])

+ @APP.route('/<namespace>/<repo>/pull-request/<int:requestid>/comment/drop',

             methods=['POST'])

  @APP.route(

-     '/fork/<username>/<repo:repo>/pull-request/<int:requestid>/comment/drop',

+     '/fork/<username>/<repo>/pull-request/<int:requestid>/comment/drop',

      methods=['POST'])

+ @APP.route(

+     '/fork/<namespace>/<username>/<repo>/pull-request/<int:requestid>/'

+     'comment/drop', methods=['POST'])

  @login_required

- def pull_request_drop_comment(repo, requestid, username=None):

+ def pull_request_drop_comment(

+         repo, requestid, username=None, namespace=None):

      """ Delete a comment of a pull-request.

      """

      repo = flask.g.repo
@@ -552,18 +598,26 @@ 

                      'Could not remove the comment: %s' % commentid, 'error')

  

      return flask.redirect(flask.url_for(

-         'request_pull', username=username,

+         'request_pull', username=username, namespace=namespace,

          repo=repo.name, requestid=requestid))

  

  

  @APP.route(

-     '/<repo:repo>/pull-request/<int:requestid>/comment/<int:commentid>/edit',

+     '/<repo>/pull-request/<int:requestid>/comment/<int:commentid>/edit',

      methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/pull-request/<int:requestid>/comment'

+     '/<namespace>/<repo>/pull-request/<int:requestid>/comment/'

+     '<int:commentid>/edit', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<repo>/pull-request/<int:requestid>/comment'

      '/<int:commentid>/edit', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/'

+     '<int:requestid>/comment/<int:commentid>/edit',

+     methods=('GET', 'POST'))

  @login_required

- def pull_request_edit_comment(repo, requestid, commentid, username=None):

+ def pull_request_edit_comment(

+         repo, requestid, commentid, username=None, namespace=None):

      """Edit comment of a pull request

      """

      is_js = flask.request.args.get('js', False)
@@ -618,7 +672,7 @@ 

          if is_js:

              return 'ok'

          return flask.redirect(flask.url_for(

-             'request_pull', username=username,

+             'request_pull', username=username, namespace=namespace,

              repo=project.name, requestid=requestid))

  

      if is_js and flask.request.method == 'POST':
@@ -636,11 +690,18 @@ 

      )

  

  

- @APP.route('/<repo:repo>/pull-request/<int:requestid>/merge', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/pull-request/<int:requestid>/merge',

-            methods=['POST'])

+ @APP.route('/<repo>/pull-request/<int:requestid>/merge', methods=['POST'])

+ @APP.route(

+     '/<namespace>/<repo>/pull-request/<int:requestid>/merge',

+     methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<repo>/pull-request/<int:requestid>/merge',

+     methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/merge',

+     methods=['POST'])

  @login_required

- def merge_request_pull(repo, requestid, username=None):

+ def merge_request_pull(repo, requestid, username=None, namespace=None):

      """ Request pulling the changes from the fork into the project.

      """

  
@@ -648,7 +709,8 @@ 

      if not form.validate_on_submit():

          flask.flash('Invalid input submitted', 'error')

          return flask.redirect(flask.url_for(

-             'request_pull', repo=repo, requestid=requestid, username=username))

+             'request_pull', repo=repo, requestid=requestid,

+             username=username, namespace=namespace))

  

      repo = flask.g.repo

  
@@ -671,12 +733,12 @@ 

              flask.flash(

                  'This request must be assigned to be merged', 'error')

              return flask.redirect(flask.url_for(

-                 'request_pull', username=username,

+                 'request_pull', username=username, namespace=namespace,

                  repo=repo.name, requestid=requestid))

          if request.assignee.username != flask.g.fas_user.username:

              flask.flash('Only the assignee can merge this review', 'error')

              return flask.redirect(flask.url_for(

-                 'request_pull', username=username,

+                 'request_pull', username=username, namespace=namespace,

                  repo=repo.name, requestid=requestid))

  

      threshold = repo.settings.get('Minimum_score_to_merge_pull-request', -1)
@@ -685,7 +747,7 @@ 

              'This request does not have the minimum review score necessary '

              'to be merged', 'error')

          return flask.redirect(flask.url_for(

-             'request_pull', username=username,

+             'request_pull', username=username, namespace=namespace,

              repo=repo.name, requestid=requestid))

  

      try:
@@ -697,22 +759,28 @@ 

          flask.flash(str(err.message), 'error')

          return flask.redirect(flask.url_for(

              'request_pull', repo=repo.name, requestid=requestid,

-             username=username))

+             username=username, namespace=namespace))

      except pagure.exceptions.PagureException as err:

          flask.flash(str(err), 'error')

          return flask.redirect(flask.url_for(

              'request_pull', repo=repo.name, requestid=requestid,

-             username=username))

+             username=username, namespace=namespace))

  

-     return flask.redirect(flask.url_for('view_repo', repo=repo.name))

+     return flask.redirect(flask.url_for(

+         'view_repo', repo=repo.name, username=username, namespace=namespace))

  

  

- @APP.route('/<repo:repo>/pull-request/cancel/<int:requestid>',

+ @APP.route('/<repo>/pull-request/cancel/<int:requestid>',

             methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/pull-request/cancel/<int:requestid>',

+ @APP.route('/<namespace>/<repo>/pull-request/cancel/<int:requestid>',

             methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/pull-request/cancel/<int:requestid>',

+            methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/cancel/<int:requestid>',

+    methods=['POST'])

  @login_required

- def cancel_request_pull(repo, requestid, username=None):

+ def cancel_request_pull(repo, requestid, username=None, namespace=None):

      """ Cancel request pulling request.

      """

  
@@ -750,16 +818,22 @@ 

      else:

          flask.flash('Invalid input submitted', 'error')

  

-     return flask.redirect(flask.url_for('view_repo', repo=repo))

+     return flask.redirect(flask.url_for(

+         'view_repo', repo=repo, username=username, namespace=namespace))

  

  

  @APP.route(

-     '/<repo:repo>/pull-request/<int:requestid>/assign', methods=['POST'])

+     '/<repo>/pull-request/<int:requestid>/assign', methods=['POST'])

+ @APP.route(

+     '/<namespace>/<repo>/pull-request/<int:requestid>/assign', methods=['POST'])

  @APP.route(

-     '/fork/<username>/<repo:repo>/pull-request/<int:requestid>/assign',

+     '/fork/<username>/<repo>/pull-request/<int:requestid>/assign',

+     methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/assign',

      methods=['POST'])

  @login_required

- def set_assignee_requests(repo, requestid, username=None):

+ def set_assignee_requests(repo, requestid, username=None, namespace=None):

      ''' Assign a pull-request. '''

      repo = flask.g.repo

  
@@ -800,17 +874,19 @@ 

              flask.flash(str(err), 'error')

  

      return flask.redirect(flask.url_for(

-         'request_pull', username=username,

+         'request_pull', username=username, namespace=namespace,

          repo=repo.name, requestid=requestid))

  

  

  # Specific actions

  

  

- @APP.route('/do_fork/<repo:repo>', methods=['POST'])

- @APP.route('/do_fork/fork/<username>/<repo:repo>', methods=['POST'])

+ @APP.route('/do_fork/<repo>', methods=['POST'])

+ @APP.route('/do_fork/<namespace>/<repo>', methods=['POST'])

+ @APP.route('/do_fork/fork/<username>/<repo>', methods=['POST'])

+ @APP.route('/do_fork/fork/<username>/<namespace>/<repo>', methods=['POST'])

  @login_required

- def fork_project(repo, username=None):

+ def fork_project(repo, username=None, namespace=None):

      """ Fork the project specified into the user's namespace

      """

      repo = flask.g.repo
@@ -820,11 +896,12 @@ 

          flask.abort(400)

  

      if pagure.lib.get_project(

-             SESSION, repo.name, user=flask.g.fas_user.username):

+             SESSION, repo.name, user=flask.g.fas_user.username,

+             namespace=namespace):

          flask.flash('You had already forked this project')

          return flask.redirect(flask.url_for(

-             'view_repo', repo=repo.name, username=flask.g.fas_user.username

-         ))

+             'view_repo', repo=repo.name, username=flask.g.fas_user.username,

+             namespace=namespace))

  

      try:

          message = pagure.lib.fork_project(
@@ -843,6 +920,7 @@ 

              flask.url_for(

                  'view_repo',

                  username=flask.g.fas_user.username,

+                 namespace=namespace,

                  repo=repo.name)

          )

      except pagure.exceptions.PagureException as err:
@@ -851,20 +929,33 @@ 

          SESSION.rollback()

          flask.flash(str(err), 'error')

  

-     return flask.redirect(flask.url_for('view_repo', repo=repo.name))

+     return flask.redirect(flask.url_for(

+         'view_repo', repo=repo.name, username=username, namespace=namespace

+     ))

  

  

- @APP.route('/<repo:repo>/diff/<path:branch_to>..<path:branch_from>/',

+ @APP.route('/<repo>/diff/<path:branch_to>..<path:branch_from>/',

+            methods=('GET', 'POST'))

+ @APP.route('/<repo>/diff/<path:branch_to>..<path:branch_from>',

+            methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/diff/<path:branch_to>..<path:branch_from>/',

             methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/diff/<path:branch_to>..<path:branch_from>',

+ @APP.route('/<namespace>/<repo>/diff/<path:branch_to>..<path:branch_from>',

             methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/diff/<path:branch_to>..<path:branch_from>/',

+     '/fork/<username>/<repo>/diff/<path:branch_to>..<path:branch_from>/',

      methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/diff/<path:branch_to>..<path:branch_from>',

+     '/fork/<username>/<repo>/diff/<path:branch_to>..<path:branch_from>',

      methods=('GET', 'POST'))

- def new_request_pull(repo, branch_to, branch_from, username=None):

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/diff/'

+     '<path:branch_to>..<path:branch_from>/', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/diff/'

+     '<path:branch_to>..<path:branch_from>', methods=('GET', 'POST'))

+ def new_request_pull(

+         repo, branch_to, branch_from, username=None, namespace=None):

      """ Request pulling the changes from the fork into the project.

      """

      branch_to = flask.request.values.get('branch_to', branch_to)
@@ -890,7 +981,8 @@ 

      except pagure.exceptions.PagureException as err:

          flask.flash(err.message, 'error')

          return flask.redirect(flask.url_for(

-             'view_repo', username=username, repo=repo.name))

+             'view_repo', username=username, repo=repo.name,

+             namespace=namespace))

  

      repo_admin = flask.g.repo_admin

  
@@ -933,11 +1025,12 @@ 

              if not parent.is_fork:

                  url = flask.url_for(

                      'request_pull', requestid=request.id,

-                     username=None, repo=parent.name)

+                     username=None, repo=parent.name, namespace=namespace)

              else:

                  url = flask.url_for(

                      'request_pull', requestid=request.id,

-                     username=parent.user, repo=parent.name)

+                     username=parent.user, repo=parent.name,

+                     namespace=namespace)

  

              return flask.redirect(url)

          except pagure.exceptions.PagureException as err:  # pragma: no cover
@@ -990,14 +1083,22 @@ 

      )

  

  

- @APP.route('/<repo:repo>/diff/remote/', methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/diff/remote', methods=('GET', 'POST'))

+ @APP.route('/<repo>/diff/remote/', methods=('GET', 'POST'))

+ @APP.route('/<repo>/diff/remote', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/diff/remote/', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/diff/remote', methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/diff/remote/', methods=('GET', 'POST'))

+     '/fork/<username>/<repo>/diff/remote/', methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/diff/remote', methods=('GET', 'POST'))

+     '/fork/<username>/<repo>/diff/remote', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/diff/remote/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/diff/remote',

+     methods=('GET', 'POST'))

  @login_required

- def new_remote_request_pull(repo, username=None):

+ def new_remote_request_pull(repo, username=None, namespace=None):

      """ Request pulling the changes from a remote fork into the project.

      """

      confirm = flask.request.values.get('confirm', False)
@@ -1027,7 +1128,8 @@ 

          except pagure.exceptions.PagureException as err:

              flask.flash(err.message, 'error')

              return flask.redirect(flask.url_for(

-                 'view_repo', username=username, repo=repo.name))

+                 'view_repo', username=username, repo=repo.name,

+                 namespace=namespace))

  

          if not confirm:

              flask.g.branches = sorted(orig_repo.listall_branches())
@@ -1099,11 +1201,13 @@ 

              if not parent.is_fork:

                  url = flask.url_for(

                      'request_pull', requestid=request.id,

-                     username=None, repo=parent.name)

+                     username=None, repo=parent.name,

+                     namespace=namespace)

              else:

                  url = flask.url_for(

                      'request_pull', requestid=request.id,

-                     username=parent.user, repo=parent.name)

+                     username=parent.user, repo=parent.name,

+                     namespace=namespace)

  

              return flask.redirect(url)

          except pagure.exceptions.PagureException as err:  # pragma: no cover
@@ -1129,13 +1233,20 @@ 

  

  

  @APP.route(

-     '/fork_edit/<repo:repo>/edit/<path:branchname>/f/<path:filename>',

+     '/fork_edit/<repo>/edit/<path:branchname>/f/<path:filename>',

+     methods=['POST'])

+ @APP.route(

+     '/fork_edit/<namespace>/<repo>/edit/<path:branchname>/f/<path:filename>',

      methods=['POST'])

  @APP.route(

-     '/fork_edit/fork/<username>/<repo:repo>/edit/<path:branchname>/'

+     '/fork_edit/fork/<username>/<repo>/edit/<path:branchname>/'

+     'f/<path:filename>', methods=['POST'])

+ @APP.route(

+     '/fork_edit/fork/<username>/<namespace>/<repo>/edit/<path:branchname>/'

      'f/<path:filename>', methods=['POST'])

  @login_required

- def fork_edit_file(repo, branchname, filename, username=None):

+ def fork_edit_file(

+         repo, branchname, filename, username=None, namespace=None):

      """ Fork the project specified and open the specific file to edit

      """

      repo = flask.g.repo
@@ -1150,6 +1261,7 @@ 

          return flask.redirect(flask.url_for(

              'edit_file',

              username=flask.g.fas_user.username,

+             namespace=namespace,

              repo=repo.name,

              branchname=branchname,

              filename=filename
@@ -1171,6 +1283,7 @@ 

          return flask.redirect(flask.url_for(

              'edit_file',

              username=flask.g.fas_user.username,

+             namespace=repo.namespace,

              repo=repo.name,

              branchname=branchname,

              filename=filename
@@ -1181,4 +1294,5 @@ 

          SESSION.rollback()

          flask.flash(str(err), 'error')

  

-     return flask.redirect(flask.url_for('view_repo', repo=repo.name))

+     return flask.redirect(flask.url_for(

+         'view_repo', repo=repo.name, username=username, namespace=namespace))

file modified
+143 -62
@@ -36,14 +36,32 @@ 

  

  # URLs

  

- @APP.route('/<repo:repo>/issue/<int:issueid>/update/', methods=['GET', 'POST'])

- @APP.route('/<repo:repo>/issue/<int:issueid>/update', methods=['GET', 'POST'])

- @APP.route('/fork/<username>/<repo:repo>/issue/<int:issueid>/update/',

-            methods=['GET', 'POST'])

- @APP.route('/fork/<username>/<repo:repo>/issue/<int:issueid>/update',

-            methods=['GET', 'POST'])

+ @APP.route(

+     '/<repo>/issue/<int:issueid>/update/',

+     methods=['GET', 'POST'])

+ @APP.route(

+     '/<repo>/issue/<int:issueid>/update',

+     methods=['GET', 'POST'])

+ @APP.route(

+     '/<namespace>/<repo>/issue/<int:issueid>/update/',

+     methods=['GET', 'POST'])

+ @APP.route(

+     '/<namespace>/<repo>/issue/<int:issueid>/update',

+     methods=['GET', 'POST'])

+ @APP.route(

+     '/fork/<username>/<repo>/issue/<int:issueid>/update/',

+     methods=['GET', 'POST'])

+ @APP.route(

+     '/fork/<username>/<repo>/issue/<int:issueid>/update',

+     methods=['GET', 'POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/update/',

+     methods=['GET', 'POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/update',

+     methods=['GET', 'POST'])

  @login_required

- def update_issue(repo, issueid, username=None):

+ def update_issue(repo, issueid, username=None, namespace=None):

      ''' Add a comment to an issue. '''

      is_js = flask.request.args.get('js', False)

  
@@ -53,7 +71,8 @@ 

          if not is_js:

              flask.flash('Invalid method: GET', 'error')

          return flask.redirect(flask.url_for(

-             'view_issue', username=username, repo=repo.name, issueid=issueid))

+             'view_issue', username=username, repo=repo.name,

+             namespace=repo.namespace, issueid=issueid))

  

      if not repo.settings.get('issue_tracker', True):

          flask.abort(404, 'No issue tracker found for this project')
@@ -117,7 +136,7 @@ 

              else:

                  return flask.redirect(flask.url_for(

                      'view_issue', username=username, repo=repo.name,

-                     issueid=issueid))

+                     namespace=repo.namespace, issueid=issueid))

  

          comment = form.comment.data

          depends = []
@@ -256,14 +275,24 @@ 

              'view_issue', username=username, repo=repo.name, issueid=issueid))

  

  

- @APP.route('/<repo:repo>/tag/<tag>/edit/', methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/tag/<tag>/edit', methods=('GET', 'POST'))

+ @APP.route('/<repo>/tag/<tag>/edit/', methods=('GET', 'POST'))

+ @APP.route('/<repo>/tag/<tag>/edit', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/tag/<tag>/edit/', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/tag/<tag>/edit', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<repo>/tag/<tag>/edit/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<repo>/tag/<tag>/edit',

+     methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/tag/<tag>/edit/', methods=('GET', 'POST'))

+     '/fork/<username>/<namespace>/<repo>/tag/<tag>/edit/',

+     methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/tag/<tag>/edit', methods=('GET', 'POST'))

+     '/fork/<username>/<namespace>/<repo>/tag/<tag>/edit',

+     methods=('GET', 'POST'))

  @login_required

- def edit_tag(repo, tag, username=None):

+ def edit_tag(repo, tag, username=None, namespace=None):

      """ Edit the specified tag associated with the issues of a project.

      """

      repo = flask.g.repo
@@ -302,7 +331,8 @@ 

              flask.flash('Could not edit tag: %s' % tag, 'error')

  

          return flask.redirect(flask.url_for(

-             '.view_settings', repo=repo.name, username=username))

+             '.view_settings', repo=repo.name, username=username,

+             namespace=repo.namespace))

  

      return flask.render_template(

          'edit_tag.html',
@@ -313,10 +343,12 @@ 

      )

  

  

- @APP.route('/<repo:repo>/droptag/', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/droptag/', methods=['POST'])

+ @APP.route('/<repo>/droptag/', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/droptag/', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/droptag/', methods=['POST'])

+ @APP.route('/fork/<username>/<namespace>/<repo>/droptag/', methods=['POST'])

  @login_required

- def remove_tag(repo, username=None):

+ def remove_tag(repo, username=None, namespace=None):

      """ Remove the specified tag, associated with the issues, from the project.

      """

      repo = flask.g.repo
@@ -351,16 +383,21 @@ 

              flask.flash(

                  'Could not remove tag: %s' % ','.join(tags), 'error')

  

-     return flask.redirect(

-         flask.url_for('.view_settings', repo=repo.name, username=username)

+     return flask.redirect(flask.url_for(

+         '.view_settings', repo=repo.name, username=username,

+         namespace=repo.namespace)

      )

  

  

- @APP.route('/<repo:repo>/issues/')

- @APP.route('/<repo:repo>/issues')

- @APP.route('/fork/<username>/<repo:repo>/issues/')

- @APP.route('/fork/<username>/<repo:repo>/issues')

- def view_issues(repo, username=None):

+ @APP.route('/<repo>/issues/')

+ @APP.route('/<repo>/issues')

+ @APP.route('/<namespace>/<repo>/issues/')

+ @APP.route('/<namespace>/<repo>/issues')

+ @APP.route('/fork/<username>/<repo>/issues/')

+ @APP.route('/fork/<username>/<repo>/issues')

+ @APP.route('/fork/<username>/<namespace>/<repo>/issues/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/issues')

+ def view_issues(repo, username=None, namespace=None):

      """ List all issues associated to a repo

      """

      status = flask.request.args.get('status', None)
@@ -454,11 +491,15 @@ 

      )

  

  

- @APP.route('/<repo:repo>/roadmap/')

- @APP.route('/<repo:repo>/roadmap')

- @APP.route('/fork/<username>/<repo:repo>/roadmap/')

- @APP.route('/fork/<username>/<repo:repo>/roadmap')

- def view_roadmap(repo, username=None):

+ @APP.route('/<repo>/roadmap/')

+ @APP.route('/<repo>/roadmap')

+ @APP.route('/<namespace>/<repo>/roadmap/')

+ @APP.route('/<namespace>/<repo>/roadmap')

+ @APP.route('/fork/<username>/<repo>/roadmap/')

+ @APP.route('/fork/<username>/<repo>/roadmap')

+ @APP.route('/fork/<username>/<namespace>/<repo>/roadmap/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/roadmap')

+ def view_roadmap(repo, username=None, namespace=None):

      """ List all issues associated to a repo as roadmap

      """

      status = flask.request.args.get('status', 'Open')
@@ -542,12 +583,20 @@ 

      )

  

  

- @APP.route('/<repo:repo>/new_issue/', methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/new_issue', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/new_issue/', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/new_issue', methods=('GET', 'POST'))

+ @APP.route('/<repo>/new_issue/', methods=('GET', 'POST'))

+ @APP.route('/<repo>/new_issue', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/new_issue/', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/new_issue', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/new_issue/', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/new_issue', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/new_issue/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/new_issue',

+     methods=('GET', 'POST'))

  @login_required

- def new_issue(repo, username=None):

+ def new_issue(repo, username=None, namespace=None):

      """ Create a new issue

      """

      repo = flask.g.repo
@@ -609,7 +658,7 @@ 

  

              return flask.redirect(flask.url_for(

                  '.view_issue', username=username, repo=repo.name,

-                 issueid=issue.id))

+                 namespace=namespace, issueid=issue.id))

          except pagure.exceptions.PagureException as err:

              flask.flash(str(err), 'error')

          except SQLAlchemyError as err:  # pragma: no cover
@@ -648,11 +697,15 @@ 

      )

  

  

- @APP.route('/<repo:repo>/issue/<int:issueid>/')

- @APP.route('/<repo:repo>/issue/<int:issueid>')

- @APP.route('/fork/<username>/<repo:repo>/issue/<int:issueid>/')

- @APP.route('/fork/<username>/<repo:repo>/issue/<int:issueid>')

- def view_issue(repo, issueid, username=None):

+ @APP.route('/<repo>/issue/<int:issueid>/')

+ @APP.route('/<repo>/issue/<int:issueid>')

+ @APP.route('/<namespace>/<repo>/issue/<int:issueid>/')

+ @APP.route('/<namespace>/<repo>/issue/<int:issueid>')

+ @APP.route('/fork/<username>/<repo>/issue/<int:issueid>/')

+ @APP.route('/fork/<username>/<repo>/issue/<int:issueid>')

+ @APP.route('/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/issue/<int:issueid>')

+ def view_issue(repo, issueid, username=None, namespace=None):

      """ List all issues associated to a repo

      """

  
@@ -694,10 +747,13 @@ 

      )

  

  

- @APP.route('/<repo:repo>/issue/<int:issueid>/drop', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/issue/<int:issueid>/drop',

+ @APP.route('/<repo>/issue/<int:issueid>/drop', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/issue/<int:issueid>/drop', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/issue/<int:issueid>/drop',

             methods=['POST'])

- def delete_issue(repo, issueid, username=None):

+ @APP.route('/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/drop',

+            methods=['POST'])

+ def delete_issue(repo, issueid, username=None, namespace=None):

      """ Delete the specified issue

      """

  
@@ -727,24 +783,36 @@ 

              SESSION.commit()

              flask.flash('Issue deleted')

              return flask.redirect(flask.url_for(

-                 'view_issues', username=username, repo=repo.name))

+                 'view_issues', username=username, repo=repo.name,

+                 namespace=namespace))

          except SQLAlchemyError as err:  # pragma: no cover

              SESSION.rollback()

              APP.logger.exception(err)

              flask.flash('Could not delete the issue', 'error')

  

      return flask.redirect(flask.url_for(

-         'view_issue', username=username, repo=repo.name, issueid=issueid))

+         'view_issue', username=username, repo=repo.name,

+         namespace=repo.namespace, issueid=issueid))

  

  

- @APP.route('/<repo:repo>/issue/<int:issueid>/edit/', methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/issue/<int:issueid>/edit', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/issue/<int:issueid>/edit/',

+ @APP.route('/<repo>/issue/<int:issueid>/edit/', methods=('GET', 'POST'))

+ @APP.route('/<repo>/issue/<int:issueid>/edit', methods=('GET', 'POST'))

+ @APP.route(

+     '/<namespace>/<repo>/issue/<int:issueid>/edit/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/<namespace>/<repo>/issue/<int:issueid>/edit',

+     methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/issue/<int:issueid>/edit/',

             methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/issue/<int:issueid>/edit',

+ @APP.route('/fork/<username>/<repo>/issue/<int:issueid>/edit',

+            methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/edit/',

+            methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/edit',

             methods=('GET', 'POST'))

  @login_required

- def edit_issue(repo, issueid, username=None):

+ def edit_issue(repo, issueid, username=None, namespace=None):

      """ Edit the specified issue

      """

      repo = flask.g.repo
@@ -807,6 +875,7 @@ 

                  filelocation = flask.url_for(

                      'view_issue_raw_file',

                      repo=repo.name,

+                     namespace=repo.namespace,

                      username=username,

                      filename=new_filename,

                  )
@@ -818,7 +887,7 @@ 

                  SESSION.commit()

              flask.flash(message)

              url = flask.url_for(

-                 'view_issue', username=username,

+                 'view_issue', username=username, namespace=namespace,

                  repo=repo.name, issueid=issueid)

              return flask.redirect(url)

          except pagure.exceptions.PagureException as err:
@@ -844,11 +913,14 @@ 

      )

  

  

- @APP.route('/<repo:repo>/issue/<int:issueid>/upload', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/issue/<int:issueid>/upload',

+ @APP.route('/<namespace>/<repo>/issue/<int:issueid>/upload', methods=['POST'])

+ @APP.route('/<repo>/issue/<int:issueid>/upload', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/issue/<int:issueid>/upload',

+            methods=['POST'])

+ @APP.route('/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/upload',

             methods=['POST'])

  @login_required

- def upload_issue(repo, issueid, username=None):

+ def upload_issue(repo, issueid, username=None, namespace=None):

      ''' Upload a file to a ticket.

      '''

      repo = flask.g.repo
@@ -888,6 +960,7 @@ 

                  'view_issue_raw_file',

                  repo=repo.name,

                  username=username,

+                 namespace=repo.namespace,

                  filename=new_filename,

              )

          })
@@ -895,9 +968,12 @@ 

          return flask.jsonify({'output': 'notok'})

  

  

- @APP.route('/<repo:repo>/issue/raw/<path:filename>')

- @APP.route('/fork/<username>/<repo:repo>/issue/raw/<path:filename>')

- def view_issue_raw_file(repo, filename=None, username=None):

+ @APP.route('/<repo>/issue/raw/<path:filename>')

+ @APP.route('/<namespace>/<repo>/issue/raw/<path:filename>')

+ @APP.route('/fork/<username>/<repo>/issue/raw/<path:filename>')

+ @APP.route('/fork/<username>/<namespace>/<repo>/issue/raw/<path:filename>')

+ def view_issue_raw_file(

+         repo, filename=None, username=None, namespace=None):

      """ Displays the raw content of a file of a commit for the specified

      ticket repo.

      """
@@ -953,12 +1029,17 @@ 

      return (data, 200, headers)

  

  

- @APP.route('/<repo:repo>/issue/<int:issueid>/comment/<int:commentid>/edit',

+ @APP.route('/<repo>/issue/<int:issueid>/comment/<int:commentid>/edit',

             methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/issue/<int:issueid>/comment'

+ @APP.route('/<namespace>/<repo>/issue/<int:issueid>/comment/<int:commentid>/edit',

+            methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/issue/<int:issueid>/comment'

+            '/<int:commentid>/edit', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<namespace>/<repo>/issue/<int:issueid>/comment'

             '/<int:commentid>/edit', methods=('GET', 'POST'))

  @login_required

- def edit_comment_issue(repo, issueid, commentid, username=None):

+ def edit_comment_issue(

+         repo, issueid, commentid, username=None, namespace=None):

      """Edit comment of an issue

      """

      is_js = flask.request.args.get('js', False)
@@ -1013,7 +1094,7 @@ 

              return 'ok'

  

          return flask.redirect(flask.url_for(

-             'view_issue', username=username,

+             'view_issue', username=username, namespace=namespace,

              repo=project.name, issueid=issueid))

  

      if is_js and flask.request.method == 'POST':

file modified
+28 -8
@@ -55,25 +55,45 @@ 

              return plugin

  

  

- @APP.route('/<repo:repo>/settings/<plugin>/', methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/settings/<plugin>', methods=('GET', 'POST'))

+ @APP.route('/<repo>/settings/<plugin>/', methods=('GET', 'POST'))

+ @APP.route('/<repo>/settings/<plugin>', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/settings/<plugin>/', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/settings/<plugin>', methods=('GET', 'POST'))

  @APP.route(

-     '/<repo:repo>/settings/<plugin>/<int:full>/',

+     '/<repo>/settings/<plugin>/<int:full>/',

      methods=('GET', 'POST'))

  @APP.route(

-     '/<repo:repo>/settings/<plugin>/<int:full>',

+     '/<repo>/settings/<plugin>/<int:full>',

      methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/settings/<plugin>/',

+     '/<namespace>/<repo>/settings/<plugin>/<int:full>/',

      methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/settings/<plugin>',

+     '/<namespace>/<repo>/settings/<plugin>/<int:full>',

      methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/settings/<plugin>/<int:full>/',

+     '/fork/<username>/<repo>/settings/<plugin>/',

      methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/settings/<plugin>/<int:full>',

+     '/fork/<username>/<namespace>/<repo>/settings/<plugin>/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<repo>/settings/<plugin>',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/settings/<plugin>',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<repo>/settings/<plugin>/<int:full>/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/settings/<plugin>/<int:full>/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<repo>/settings/<plugin>/<int:full>',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/settings/<plugin>/<int:full>',

      methods=('GET', 'POST'))

  @login_required

  def view_plugin(repo, plugin, username=None, full=True):

file modified
+338 -231
@@ -51,24 +51,30 @@ 

                      admin_session_timedout)

  

  

- @APP.route('/<repo:repo>.git')

- @APP.route('/fork/<username>/<repo:repo>.git')

- def view_repo_git(repo, username=None):

+ @APP.route('/<repo>.git')

+ @APP.route('/<namespace>/<repo>.git')

+ @APP.route('/fork/<username>/<repo>.git')

+ @APP.route('/fork/<username>/<namespace>/<repo>.git')

+ def view_repo_git(repo, username=None, namespace=None):

      ''' Redirect to the project index page when user wants to view

      the git repo of the project

      '''

      return flask.redirect(flask.url_for(

-         'view_repo', repo=repo, username=username))

- 

- 

- @APP.route('/<repo:repo>/')

- @APP.route('/<repo:repo>')

- @APP.route('/fork/<username>/<repo:repo>/')

- @APP.route('/fork/<username>/<repo:repo>')

- def view_repo(repo, username=None):

+         'view_repo', repo=repo, username=username, namespace=namespace))

+ 

+ 

+ @APP.route('/<repo>/')

+ @APP.route('/<repo>')

+ @APP.route('/<namespace>/<repo>/')

+ @APP.route('/<namespace>/<repo>')

+ @APP.route('/fork/<username>/<repo>/')

+ @APP.route('/fork/<username>/<repo>')

+ @APP.route('/fork/<username>/<namespace>/<repo>/')

+ @APP.route('/fork/<username>/<namespace>/<repo>')

+ def view_repo(repo, username=None, namespace=None):

      """ Front page of a specific repo.

      """

-     repo = flask.g.repo

+     repo_db = flask.g.repo

      reponame = flask.g.reponame

      repo_obj = flask.g.repo_obj

  
@@ -109,14 +115,14 @@ 

                  content, ext,

                  view_file_url=flask.url_for(

                      'view_raw_file', username=username,

-                     repo=repo.name, identifier=branchname, filename=''))

+                     repo=repo_db.name, identifier=branchname, filename=''))

  

      diff_commits = []

-     if repo.is_fork and repo.parent:

+     if repo_db.is_fork and repo_db.parent:

          parentname = os.path.join(

-             APP.config['GIT_FOLDER'], repo.parent.path)

+             APP.config['GIT_FOLDER'], repo_db.parent.path)

      else:

-         parentname = os.path.join(APP.config['GIT_FOLDER'], repo.path)

+         parentname = os.path.join(APP.config['GIT_FOLDER'], repo_db.path)

  

      orig_repo = pygit2.Repository(parentname)

  
@@ -144,7 +150,7 @@ 

      return flask.render_template(

          'repo_info.html',

          select='overview',

-         repo=repo,

+         repo=repo_db,

          username=username,

          head=head,

          readme=readme,
@@ -158,9 +164,11 @@ 

      )

  

  

- @APP.route('/<repo:repo>/branch/<path:branchname>')

- @APP.route('/fork/<username>/<repo:repo>/branch/<path:branchname>')

- def view_repo_branch(repo, branchname, username=None):

+ @APP.route('/<repo>/branch/<path:branchname>')

+ @APP.route('/<namespace>/<repo>/branch/<path:branchname>')

+ @APP.route('/fork/<username>/<repo>/branch/<path:branchname>')

+ @APP.route('/fork/<username>/<namespace>/<repo>/branch/<path:branchname>')

+ def view_repo_branch(repo, branchname, username=None, namespace=None):

      ''' Returns the list of branches in the repo. '''

  

      repo = flask.g.repo
@@ -232,6 +240,7 @@ 

                      content, ext,

                      view_file_url=flask.url_for(

                          'view_raw_file', username=username,

+                         namespace=repo.namespace,

                          repo=repo.name, identifier=branchname, filename=''))

  

      return flask.render_template(
@@ -251,13 +260,19 @@ 

      )

  

  

- @APP.route('/<repo:repo>/commits/')

- @APP.route('/<repo:repo>/commits')

- @APP.route('/<repo:repo>/commits/<path:branchname>')

- @APP.route('/fork/<username>/<repo:repo>/commits/')

- @APP.route('/fork/<username>/<repo:repo>/commits')

- @APP.route('/fork/<username>/<repo:repo>/commits/<path:branchname>')

- def view_commits(repo, branchname=None, username=None):

+ @APP.route('/<repo>/commits/')

+ @APP.route('/<repo>/commits')

+ @APP.route('/<repo>/commits/<path:branchname>')

+ @APP.route('/<namespace>/<repo>/commits/')

+ @APP.route('/<namespace>/<repo>/commits')

+ @APP.route('/<namespace>/<repo>/commits/<path:branchname>')

+ @APP.route('/fork/<username>/<repo>/commits/')

+ @APP.route('/fork/<username>/<repo>/commits')

+ @APP.route('/fork/<username>/<repo>/commits/<path:branchname>')

+ @APP.route('/fork/<username>/<namespace>/<repo>/commits/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/commits')

+ @APP.route('/fork/<username>/<namespace>/<repo>/commits/<path:branchname>')

+ def view_commits(repo, branchname=None, username=None, namespace=None):

      """ Displays the commits of the specified repo.

      """

      repo = flask.g.repo
@@ -359,9 +374,13 @@ 

  

  @APP.route('/<repo>/c/<commit1>..<commit2>/')

  @APP.route('/<repo>/c/<commit1>..<commit2>')

+ @APP.route('/<namespace>/<repo>/c/<commit1>..<commit2>/')

+ @APP.route('/<namespace>/<repo>/c/<commit1>..<commit2>')

  @APP.route('/fork/<username>/<repo>/c/<commit1>..<commit2>/')

  @APP.route('/fork/<username>/<repo>/c/<commit1>..<commit2>')

- def compare_commits(repo, commit1, commit2, username=None):

+ @APP.route('/fork/<username>/<namespace>/<repo>/c/<commit1>..<commit2>/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/c/<commit1>..<commit2>')

+ def compare_commits(repo, commit1, commit2, username=None, namespace=None):

      """ Compares two commits for specified repo

      """

      repo = flask.g.repo
@@ -423,10 +442,13 @@ 

      )

  

  

- @APP.route('/<repo:repo>/blob/<path:identifier>/f/<path:filename>')

+ @APP.route('/<repo>/blob/<path:identifier>/f/<path:filename>')

+ @APP.route('/<namespace>/<repo>/blob/<path:identifier>/f/<path:filename>')

+ @APP.route(

+     '/fork/<username>/<repo>/blob/<path:identifier>/f/<path:filename>')

  @APP.route(

-     '/fork/<username>/<repo:repo>/blob/<path:identifier>/f/<path:filename>')

- def view_file(repo, identifier, filename, username=None):

+     '/fork/<username>/<namespace>/<repo>/blob/<path:identifier>/f/<path:filename>')

+ def view_file(repo, identifier, filename, username=None, namespace=None):

      """ Displays the content of a file or a tree for the specified repo.

      """

      repo = flask.g.repo
@@ -547,14 +569,18 @@ 

      )

  

  

- @APP.route('/<repo:repo>/raw/<path:identifier>', defaults={'filename': None})

- @APP.route('/<repo:repo>/raw/<path:identifier>/f/<path:filename>')

+ @APP.route('/<repo>/raw/<path:identifier>',)

+ @APP.route('/<namespace>/<repo>/raw/<path:identifier>',)

+ @APP.route('/<repo>/raw/<path:identifier>/f/<path:filename>')

+ @APP.route('/<namespace>/<repo>/raw/<path:identifier>/f/<path:filename>')

+ @APP.route('/fork/<username>/<repo>/raw/<path:identifier>')

+ @APP.route('/fork/<username>/<namespace>/<repo>/raw/<path:identifier>')

  @APP.route(

-     '/fork/<username>/<repo:repo>/raw/<path:identifier>',

-     defaults={'filename': None})

+     '/fork/<username>/<repo>/raw/<path:identifier>/f/<path:filename>')

  @APP.route(

-     '/fork/<username>/<repo:repo>/raw/<path:identifier>/f/<path:filename>')

- def view_raw_file(repo, identifier, filename=None, username=None):

+     '/fork/<username>/<namespace>/<repo>/raw/<path:identifier>/f/<path:filename>')

+ def view_raw_file(

+         repo, identifier, filename=None, username=None, namespace=None):

      """ Displays the raw content of a file of a commit for the specified repo.

      """

      repo = flask.g.repo
@@ -632,34 +658,15 @@ 

      return (data, 200, headers)

  

  

- if APP.config.get('OLD_VIEW_COMMIT_ENABLED', False):

-     @APP.route('/<repo>/<string(length=40):commitid>/')

-     @APP.route('/<repo>/<string(length=40):commitid>')

-     @APP.route('/fork/<username>/<repo>/<string(length=40):commitid>/')

-     @APP.route('/fork/<username>/<repo>/<string(length=40):commitid>')

-     def view_commit_old(repo, commitid, username=None):

-         """ Redirect from the old view_commit to the new one.

- 

-         This method aims to provide backward compatibility with the old URL

-         scheme where the commit id was right after the repo name.

-         This is problematic since we now allow up to one slash ('/') in the

-         project name, making the url parsing a little trickier.

-         So if the element after the '/' is exactly 40 characters long, then we

-         consider it's a commit hash and redirect to the new URL scheme for

-         viewing commits.

-         If the element is more (not possible) or less than 40 characters, then

-         the other URLs should catch it.

- 

-         """

-         return flask.redirect(flask.url_for(

-             'view_commit', repo=repo, commitid=commitid, username=username))

- 

- 

- @APP.route('/<repo:repo>/c/<commitid>/')

- @APP.route('/<repo:repo>/c/<commitid>')

- @APP.route('/fork/<username>/<repo:repo>/c/<commitid>/')

- @APP.route('/fork/<username>/<repo:repo>/c/<commitid>')

- def view_commit(repo, commitid, username=None):

+ @APP.route('/<repo>/c/<commitid>/')

+ @APP.route('/<repo>/c/<commitid>')

+ @APP.route('/<namespace>/<repo>/c/<commitid>/')

+ @APP.route('/<namespace>/<repo>/c/<commitid>')

+ @APP.route('/fork/<username>/<repo>/c/<commitid>/')

+ @APP.route('/fork/<username>/<repo>/c/<commitid>')

+ @APP.route('/fork/<username>/<namespace>/<repo>/c/<commitid>/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/c/<commitid>')

+ def view_commit(repo, commitid, username=None, namespace=None):

      """ Render a commit in a repo

      """

      repo = flask.g.repo
@@ -701,9 +708,11 @@ 

      )

  

  

- @APP.route('/<repo:repo>/c/<commitid>.patch')

- @APP.route('/fork/<username>/<repo:repo>/c/<commitid>.patch')

- def view_commit_patch(repo, commitid, username=None):

+ @APP.route('/<repo>/c/<commitid>.patch')

+ @APP.route('/<namespace>/<repo>/c/<commitid>.patch')

+ @APP.route('/fork/<username>/<repo>/c/<commitid>.patch')

+ @APP.route('/fork/<username>/<namespace>/<repo>/c/<commitid>.patch')

+ def view_commit_patch(repo, commitid, username=None, namespace=None):

      """ Render a commit in a repo as patch

      """

      repo = flask.g.repo
@@ -723,13 +732,19 @@ 

      return flask.Response(patch, content_type="text/plain;charset=UTF-8")

  

  

- @APP.route('/<repo:repo>/tree/')

- @APP.route('/<repo:repo>/tree')

- @APP.route('/<repo:repo>/tree/<path:identifier>')

- @APP.route('/fork/<username>/<repo:repo>/tree/')

- @APP.route('/fork/<username>/<repo:repo>/tree')

- @APP.route('/fork/<username>/<repo:repo>/tree/<path:identifier>')

- def view_tree(repo, identifier=None, username=None):

+ @APP.route('/<repo>/tree/')

+ @APP.route('/<repo>/tree')

+ @APP.route('/<namespace>/<repo>/tree/')

+ @APP.route('/<namespace>/<repo>/tree')

+ @APP.route('/<repo>/tree/<path:identifier>')

+ @APP.route('/<namespace>/<repo>/tree/<path:identifier>')

+ @APP.route('/fork/<username>/<repo>/tree/')

+ @APP.route('/fork/<username>/<repo>/tree')

+ @APP.route('/fork/<username>/<namespace>/<repo>/tree/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/tree')

+ @APP.route('/fork/<username>/<repo>/tree/<path:identifier>')

+ @APP.route('/fork/<username>/<namespace>/<repo>/tree/<path:identifier>')

+ def view_tree(repo, identifier=None, username=None, namespace=None):

      """ Render the tree of the repo

      """

      repo = flask.g.repo
@@ -792,11 +807,15 @@ 

      )

  

  

- @APP.route('/<repo:repo>/forks/')

- @APP.route('/<repo:repo>/forks')

- @APP.route('/fork/<username>/<repo:repo>/forks/')

- @APP.route('/fork/<username>/<repo:repo>/forks')

- def view_forks(repo, username=None):

+ @APP.route('/<repo>/forks/')

+ @APP.route('/<repo>/forks')

+ @APP.route('/<namespace>/<repo>/forks/')

+ @APP.route('/<namespace>/<repo>/forks')

+ @APP.route('/fork/<username>/<repo>/forks/')

+ @APP.route('/fork/<username>/<repo>/forks')

+ @APP.route('/fork/<username>/<namespace>/<repo>/forks/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/forks')

+ def view_forks(repo, username=None, namespace=None):

      """ Presents all the forks of the project.

      """

      repo = flask.g.repo
@@ -811,11 +830,15 @@ 

      )

  

  

- @APP.route('/<repo:repo>/releases/')

- @APP.route('/<repo:repo>/releases')

- @APP.route('/fork/<username>/<repo:repo>/releases/')

- @APP.route('/fork/<username>/<repo:repo>/releases')

- def view_tags(repo, username=None):

+ @APP.route('/<repo>/releases/')

+ @APP.route('/<repo>/releases')

+ @APP.route('/<namespace>/<repo>/releases/')

+ @APP.route('/<namespace>/<repo>/releases')

+ @APP.route('/fork/<username>/<repo>/releases/')

+ @APP.route('/fork/<username>/<repo>/releases')

+ @APP.route('/fork/<username>/<namespace>/<repo>/releases/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/releases')

+ def view_tags(repo, username=None, namespace=None):

      """ Presents all the tags of the project.

      """

      repo = flask.g.repo
@@ -833,12 +856,18 @@ 

      )

  

  

- @APP.route('/<repo:repo>/upload/', methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/upload', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/upload/', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/upload', methods=('GET', 'POST'))

+ @APP.route('/<repo>/upload/', methods=('GET', 'POST'))

+ @APP.route('/<repo>/upload', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/upload/', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/upload', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/upload/', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/upload', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/upload/', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/upload', methods=('GET', 'POST'))

  @login_required

- def new_release(repo, username=None):

+ def new_release(repo, username=None, namespace=None):

      """ Upload a new release.

      """

      if not APP.config.get('UPLOAD_FOLDER_PATH') \
@@ -868,8 +897,9 @@ 

              except Exception as err:  # pragma: no cover

                  APP.logger.exception(err)

                  flask.flash('Upload failed', 'error')

-         return flask.redirect(

-             flask.url_for('view_tags', repo=repo.name, username=username))

+         return flask.redirect(flask.url_for(

+             'view_tags', repo=repo.name, username=username,

+             namespace=repo.namespace))

  

      return flask.render_template(

          'new_release.html',
@@ -880,12 +910,18 @@ 

      )

  

  

- @APP.route('/<repo:repo>/settings/', methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/settings', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/settings/', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/settings', methods=('GET', 'POST'))

+ @APP.route('/<repo>/settings/', methods=('GET', 'POST'))

+ @APP.route('/<repo>/settings', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/settings/', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/settings', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/settings/', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/settings', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/settings/', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/settings', methods=('GET', 'POST'))

  @login_required

- def view_settings(repo, username=None):

+ def view_settings(repo, username=None, namespace=None):

      """ Presents the settings of the project.

      """

      if admin_session_timedout():
@@ -929,7 +965,8 @@ 

              SESSION.commit()

              flask.flash(message)

              return flask.redirect(flask.url_for(

-                 'view_repo', username=username, repo=repo.name))

+                 'view_repo', username=username, repo=repo.name,

+                 namespace=repo.namespace))

          except pagure.exceptions.PagureException as msg:

              SESSION.rollback()

              flask.flash(msg, 'error')
@@ -959,16 +996,19 @@ 

      )

  

  

- @APP.route('/<repo:repo>/update', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/update', methods=['POST'])

+ @APP.route('/<repo>/update', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/update', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/update', methods=['POST'])

+ @APP.route('/fork/<username>/<namespace>/<repo>/update', methods=['POST'])

  @login_required

- def update_project(repo, username=None):

+ def update_project(repo, username=None, namespace=None):

      """ Update the description of a project.

      """

      if admin_session_timedout():

          flask.flash('Action canceled, try it again', 'error')

          url = flask.url_for(

-             'view_settings', username=username, repo=repo)

+             'view_settings', username=username, repo=repo,

+             namespace=namespace)

          return flask.redirect(

              flask.url_for('auth_login', next=url))

  
@@ -1000,19 +1040,25 @@ 

              flask.flash(str(err), 'error')

  

      return flask.redirect(flask.url_for(

-         'view_settings', username=username, repo=repo.name))

+         'view_settings', username=username, repo=repo.name,

+         namespace=repo.namespace))

  

  

- @APP.route('/<repo:repo>/update/priorities', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/update/priorities', methods=['POST'])

+ @APP.route('/<repo>/update/priorities', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/update/priorities', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/update/priorities', methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/update/priorities',

+     methods=['POST'])

  @login_required

- def update_priorities(repo, username=None):

+ def update_priorities(repo, username=None, namespace=None):

      """ Update the priorities of a project.

      """

      if admin_session_timedout():

          flask.flash('Action canceled, try it again', 'error')

          url = flask.url_for(

-             'view_settings', username=username, repo=repo)

+             'view_settings', username=username, repo=repo,

+             namespace=namespace)

          return flask.redirect(

              flask.url_for('auth_login', next=url))

  
@@ -1088,19 +1134,25 @@ 

                  flask.flash(str(err), 'error')

  

      return flask.redirect(flask.url_for(

-         'view_settings', username=username, repo=repo.name))

+         'view_settings', username=username, repo=repo.name,

+         namespace=repo.namespace))

  

  

- @APP.route('/<repo:repo>/update/milestones', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/update/milestones', methods=['POST'])

+ @APP.route('/<repo>/update/milestones', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/update/milestones', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/update/milestones', methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/update/milestones',

+     methods=['POST'])

  @login_required

- def update_milestones(repo, username=None):

+ def update_milestones(repo, username=None, namespace=None):

      """ Update the milestones of a project.

      """

      if admin_session_timedout():

          flask.flash('Action canceled, try it again', 'error')

          url = flask.url_for(

-             'view_settings', username=username, repo=repo)

+             'view_settings', username=username, repo=repo,

+             namespace=namespace)

          return flask.redirect(

              flask.url_for('auth_login', next=url))

  
@@ -1167,20 +1219,25 @@ 

                  flask.flash(str(err), 'error')

  

      return flask.redirect(flask.url_for(

-         'view_settings', username=username, repo=repo.name))

+         'view_settings', username=username, repo=repo.name,

+         namespace=namespace))

  

  

- @APP.route('/<repo:repo>/default/branch/', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/default/branch/', methods=['POST'])

+ @APP.route('/<repo>/default/branch/', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/default/branch/', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/default/branch/', methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/default/branch/', methods=['POST'])

  @login_required

- def change_ref_head(repo, username=None):

+ def change_ref_head(repo, username=None, namespace=None):

      """ Change HEAD reference

      """

  

      if admin_session_timedout():

          flask.flash('Action canceled, try it again', 'error')

          url = flask.url_for(

-             'view_settings', username=username, repo=repo)

+             'view_settings', username=username, repo=repo,

+             namespace=namespace)

          return flask.redirect(

              flask.url_for('auth_login', next=url))

  
@@ -1207,13 +1264,16 @@ 

              APP.logger.exception(err)

  

      return flask.redirect(flask.url_for(

-         'view_settings', username=username, repo=repo.name))

+         'view_settings', username=username, repo=repo.name,

+         namespace=namespace))

  

  

- @APP.route('/<repo:repo>/delete', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/delete', methods=['POST'])

+ @APP.route('/<repo>/delete', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/delete', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/delete', methods=['POST'])

+ @APP.route('/fork/<username>/<namespace>/<repo>/delete', methods=['POST'])

  @login_required

- def delete_repo(repo, username=None):

+ def delete_repo(repo, username=None, namespace=None):

      """ Delete the present project.

      """

      if not pagure.APP.config.get('ENABLE_DEL_PROJECTS', True):
@@ -1222,7 +1282,8 @@ 

      if admin_session_timedout():

          flask.flash('Action canceled, try it again', 'error')

          url = flask.url_for(

-             'view_settings', username=username, repo=repo)

+             'view_settings', username=username, repo=repo,

+             namespace=namespace)

          return flask.redirect(

              flask.url_for('auth_login', next=url))

  
@@ -1266,10 +1327,13 @@ 

          flask.url_for('view_user', username=flask.g.fas_user.username))

  

  

- @APP.route('/<repo:repo>/hook_token', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/hook_token', methods=['POST'])

+ @APP.route('/<repo>/hook_token', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/hook_token', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/hook_token', methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/hook_token', methods=['POST'])

  @login_required

- def new_repo_hook_token(repo, username=None):

+ def new_repo_hook_token(repo, username=None, namespace=None):

      """ Re-generate a hook token for the present project.

      """

      if not pagure.APP.config.get('WEBHOOK', False):
@@ -1278,7 +1342,8 @@ 

      if admin_session_timedout():

          flask.flash('Action canceled, try it again', 'error')

          url = flask.url_for(

-             'view_settings', username=username, repo=repo)

+             'view_settings', username=username, repo=repo,

+             namespace=namespace)

          return flask.redirect(

              flask.url_for('auth_login', next=url))

  
@@ -1302,15 +1367,19 @@ 

          APP.logger.exception(err)

          flask.flash('Could not generate a new token for this project', 'error')

  

-     return flask.redirect(

-         flask.url_for('view_settings', repo=repo.name, username=username))

+     return flask.redirect(flask.url_for(

+         'view_settings', repo=repo.name, username=username,

+         namespace=namespace))

  

  

- @APP.route('/<repo:repo>/dropuser/<int:userid>', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/dropuser/<int:userid>',

+ @APP.route('/<repo>/dropuser/<int:userid>', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/dropuser/<int:userid>', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/dropuser/<int:userid>',

+            methods=['POST'])

+ @APP.route('/fork/<username>/<namespace>/<repo>/dropuser/<int:userid>',

             methods=['POST'])

  @login_required

- def remove_user(repo, userid, username=None):

+ def remove_user(repo, userid, username=None, namespace=None):

      """ Remove the specified user from the project.

      """

  
@@ -1320,7 +1389,8 @@ 

      if admin_session_timedout():

          flask.flash('Action canceled, try it again', 'error')

          url = flask.url_for(

-             'view_settings', username=username, repo=repo)

+             'view_settings', username=username, repo=repo,

+             namespace=namespace)

          return flask.redirect(

              flask.url_for('auth_login', next=url))

  
@@ -1338,9 +1408,9 @@ 

          if str(userid) not in userids:

              flask.flash(

                  'User does not have commit or cannot loose it right', 'error')

-             return flask.redirect(

-                 flask.url_for(

-                     '.view_settings', repo=repo.name, username=username)

+             return flask.redirect(flask.url_for(

+                 '.view_settings', repo=repo.name, username=username,

+                 namespace=repo.namespace,)

              )

  

          for user in repo.users:
@@ -1356,17 +1426,23 @@ 

              APP.logger.exception(err)

              flask.flash('User could not be removed', 'error')

  

-     return flask.redirect(

-         flask.url_for('.view_settings', repo=repo.name, username=username)

-     )

+     return flask.redirect(flask.url_for(

+         '.view_settings', repo=repo.name, username=username,

+         namespace=namespace))

  

  

- @APP.route('/<repo:repo>/adduser/', methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/adduser', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/adduser/', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/adduser', methods=('GET', 'POST'))

+ @APP.route('/<repo>/adduser/', methods=('GET', 'POST'))

+ @APP.route('/<repo>/adduser', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/adduser/', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/adduser', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/adduser/', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/adduser', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/adduser/', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/adduser', methods=('GET', 'POST'))

  @login_required

- def add_user(repo, username=None):

+ def add_user(repo, username=None, namespace=None):

      """ Add the specified user from the project.

      """

  
@@ -1399,10 +1475,9 @@ 

              SESSION.commit()

              pagure.lib.git.generate_gitolite_acls()

              flask.flash(msg)

-             return flask.redirect(

-                 flask.url_for(

-                     '.view_settings', repo=repo.name, username=username)

-             )

+             return flask.redirect(flask.url_for(

+                 '.view_settings', repo=repo.name, username=username,

+                 namespace=namespace))

          except pagure.exceptions.PagureException as msg:

              SESSION.rollback()

              flask.flash(msg, 'error')
@@ -1419,11 +1494,15 @@ 

      )

  

  

- @APP.route('/<repo:repo>/dropgroup/<int:groupid>', methods=['POST'])

+ @APP.route('/<repo>/dropgroup/<int:groupid>', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/dropgroup/<int:groupid>', methods=['POST'])

  @APP.route(

-     '/fork/<username>/<repo:repo>/dropgroup/<int:groupid>', methods=['POST'])

+     '/fork/<username>/<repo>/dropgroup/<int:groupid>', methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/dropgroup/<int:groupid>',

+     methods=['POST'])

  @login_required

- def remove_group_project(repo, groupid, username=None):

+ def remove_group_project(repo, groupid, username=None, namespace=None):

      """ Remove the specified group from the project.

      """

  
@@ -1434,7 +1513,8 @@ 

      if admin_session_timedout():

          flask.flash('Action canceled, try it again', 'error')

          url = flask.url_for(

-             'view_settings', username=username, repo=repo)

+             'view_settings', username=username, repo=repo,

+             namespace=namespace)

          return flask.redirect(

              flask.url_for('auth_login', next=url))

  
@@ -1452,10 +1532,9 @@ 

          if groupid not in grpids:

              flask.flash(

                  'Group does not seem to be part of this project', 'error')

-             return flask.redirect(

-                 flask.url_for(

-                     '.view_settings', repo=repo.name, username=username)

-             )

+             return flask.redirect(flask.url_for(

+                 '.view_settings', repo=repo.name, username=username,

+                 namespace=namespace))

  

          for grp in repo.groups:

              if grp.id == groupid:
@@ -1470,17 +1549,23 @@ 

              APP.logger.exception(err)

              flask.flash('Group could not be removed', 'error')

  

-     return flask.redirect(

-         flask.url_for('.view_settings', repo=repo.name, username=username)

-     )

+     return flask.redirect(flask.url_for(

+         '.view_settings', repo=repo.name, username=username,

+         namespace=namespace))

  

  

- @APP.route('/<repo:repo>/addgroup/', methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/addgroup', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/addgroup/', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/addgroup', methods=('GET', 'POST'))

+ @APP.route('/<repo>/addgroup/', methods=('GET', 'POST'))

+ @APP.route('/<repo>/addgroup', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/addgroup/', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/addgroup', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/addgroup/', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/addgroup', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/addgroup/', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/addgroup', methods=('GET', 'POST'))

  @login_required

- def add_group_project(repo, username=None):

+ def add_group_project(repo, username=None, namespace=None):

      """ Add the specified group from the project.

      """

  
@@ -1515,10 +1600,9 @@ 

              SESSION.commit()

              pagure.lib.git.generate_gitolite_acls()

              flask.flash(msg)

-             return flask.redirect(

-                 flask.url_for(

-                     '.view_settings', repo=repo.name, username=username)

-             )

+             return flask.redirect(flask.url_for(

+                 '.view_settings', repo=repo.name, username=username,

+                 namespace=namespace))

          except pagure.exceptions.PagureException as msg:

              SESSION.rollback()

              flask.flash(msg, 'error')
@@ -1535,16 +1619,19 @@ 

      )

  

  

- @APP.route('/<repo:repo>/regenerate', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/regenerate', methods=['POST'])

+ @APP.route('/<repo>/regenerate', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/regenerate', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/regenerate', methods=['POST'])

+ @APP.route('/fork/<username>/<namespace>/<repo>/regenerate', methods=['POST'])

  @login_required

- def regenerate_git(repo, username=None):

+ def regenerate_git(repo, username=None, namespace=None):

      """ Regenerate the specified git repo with the content in the project.

      """

      if admin_session_timedout():

          flask.flash('Action canceled, try it again', 'error')

          url = flask.url_for(

-             'view_settings', username=username, repo=repo)

+             'view_settings', username=username, repo=repo,

+             namespace=namespace)

          return flask.redirect(

              flask.url_for('auth_login', next=url))

  
@@ -1575,17 +1662,25 @@ 

                      repofolder=APP.config['TICKETS_FOLDER'])

              flask.flash('Tickets git repo updated')

  

-     return flask.redirect(

-         flask.url_for('.view_settings', repo=repo.name, username=username)

-     )

+     return flask.redirect(flask.url_for(

+         '.view_settings', repo=repo.name, username=username,

+         namespace=namespace))

  

  

- @APP.route('/<repo:repo>/token/new/', methods=('GET', 'POST'))

- @APP.route('/<repo:repo>/token/new', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/token/new/', methods=('GET', 'POST'))

- @APP.route('/fork/<username>/<repo:repo>/token/new', methods=('GET', 'POST'))

+ @APP.route('/<repo>/token/new/', methods=('GET', 'POST'))

+ @APP.route('/<repo>/token/new', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/token/new/', methods=('GET', 'POST'))

+ @APP.route('/<namespace>/<repo>/token/new', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/token/new/', methods=('GET', 'POST'))

+ @APP.route('/fork/<username>/<repo>/token/new', methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/token/new/',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/token/new',

+     methods=('GET', 'POST'))

  @login_required

- def add_token(repo, username=None):

+ def add_token(repo, username=None, namespace=None):

      """ Add a token to a specified project.

      """

      if admin_session_timedout():
@@ -1614,10 +1709,9 @@ 

              )

              SESSION.commit()

              flask.flash(msg)

-             return flask.redirect(

-                 flask.url_for(

-                     '.view_settings', repo=repo.name, username=username)

-             )

+             return flask.redirect(flask.url_for(

+                 '.view_settings', repo=repo.name, username=username,

+                 namespace=namespace))

          except SQLAlchemyError as err:  # pragma: no cover

              SESSION.rollback()

              APP.logger.exception(err)
@@ -1633,17 +1727,22 @@ 

      )

  

  

- @APP.route('/<repo:repo>/token/revoke/<token_id>', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/token/revoke/<token_id>',

-            methods=['POST'])

+ @APP.route('/<repo>/token/revoke/<token_id>', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/token/revoke/<token_id>', methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<repo>/token/revoke/<token_id>', methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/token/revoke/<token_id>',

+     methods=['POST'])

  @login_required

- def revoke_api_token(repo, token_id, username=None):

+ def revoke_api_token(repo, token_id, username=None, namespace=None):

      """ Revokie a token to a specified project.

      """

      if admin_session_timedout():

          flask.flash('Action canceled, try it again', 'error')

          url = flask.url_for(

-             'view_settings', username=username, repo=repo)

+             'view_settings', username=username, repo=repo,

+             namespace=namespace)

          return flask.redirect(

              flask.url_for('auth_login', next=url))

  
@@ -1675,20 +1774,25 @@ 

                  'Token could not be revoked, please contact an admin',

                  'error')

  

-     return flask.redirect(

-         flask.url_for(

-             '.view_settings', repo=repo.name, username=username)

-     )

+     return flask.redirect(flask.url_for(

+         '.view_settings', repo=repo.name, username=username,

+         namespace=namespace))

  

  

  @APP.route(

-     '/<repo:repo>/edit/<path:branchname>/f/<path:filename>',

+     '/<repo>/edit/<path:branchname>/f/<path:filename>',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/<namespace>/<repo>/edit/<path:branchname>/f/<path:filename>',

      methods=('GET', 'POST'))

  @APP.route(

-     '/fork/<username>/<repo:repo>/edit/<path:branchname>/f/<path:filename>',

+     '/fork/<username>/<repo>/edit/<path:branchname>/f/<path:filename>',

+     methods=('GET', 'POST'))

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/edit/<path:branchname>/f/<path:filename>',

      methods=('GET', 'POST'))

  @login_required

- def edit_file(repo, branchname, filename, username=None):

+ def edit_file(repo, branchname, filename, username=None, namespace=None):

      """ Edit a file online.

      """

      repo = flask.g.repo
@@ -1734,7 +1838,7 @@ 

              return flask.redirect(

                  flask.url_for(

                      '.view_commits', repo=repo.name, username=username,

-                     branchname=form.branch.data)

+                     namespace=namespace, branchname=form.branch.data)

              )

          except pagure.exceptions.PagureException as err:  # pragma: no cover

              APP.logger.exception(err)
@@ -1766,14 +1870,16 @@ 

      )

  

  

- @APP.route('/<repo:repo>/b/<path:branchname>/delete', methods=['POST'])

- @APP.route('/fork/<username>/<repo:repo>/b/<path:branchname>/delete',

+ @APP.route('/<repo>/b/<path:branchname>/delete', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/b/<path:branchname>/delete', methods=['POST'])

+ @APP.route('/fork/<username>/<repo>/b/<path:branchname>/delete',

+            methods=['POST'])

+ @APP.route('/fork/<username>/<namespace>/<repo>/b/<path:branchname>/delete',

             methods=['POST'])

  @login_required

- def delete_branch(repo, branchname, username=None):

+ def delete_branch(repo, branchname, username=None, namespace=None):

      """ Delete the branch of a project.

      """

-     repo = flask.g.repo

      reponame = flask.g.reponame

      repo_obj = flask.g.repo_obj

  
@@ -1796,21 +1902,22 @@ 

          APP.logger.exception(err)

          flask.flash('Could not delete `%s`' % branchname, 'error')

  

-     return flask.redirect(

-         flask.url_for('view_repo', repo=repo.name, username=username))

- 

- 

- @APP.route('/docs/<repo:repo>/')

- @APP.route('/docs/<repo:repo>/<path:filename>')

- @APP.route('/docs/fork/<username>/<repo:repo>/')

- @APP.route('/docs/fork/<username>/<repo:repo>/<path:filename>')

- def view_docs(repo, username=None, filename=None):

+     return flask.redirect(flask.url_for(

+         'view_repo', repo=repo, username=username, namespace=namespace))

+ 

+ 

+ @APP.route('/docs/<repo>/')

+ @APP.route('/docs/<repo>/<path:filename>')

+ @APP.route('/docs/<namespace>/<repo>/')

+ @APP.route('/docs/<namespace>/<repo>/<path:filename>')

+ @APP.route('/docs/fork/<username>/<repo>/')

+ @APP.route('/docs/fork/<username>/<namespace>/<repo>/<path:filename>')

+ @APP.route('/docs/fork/<username>/<repo>/')

+ @APP.route('/docs/fork/<username>/<namespace>/<repo>/<path:filename>')

+ def view_docs(repo, username=None, filename=None, namespace=None):

      """ Display the documentation

      """

-     repo_obj = pagure.lib.get_project(SESSION, repo, user=username)

- 

-     if not repo_obj:

-         flask.abort(404, 'Project not found')

+     repo = flask.g.repo

  

      if not APP.config.get('DOC_APP_URL'):

          flask.abort(404, 'This pagure instance has no doc server')
@@ -1818,39 +1925,44 @@ 

      return flask.render_template(

          'docs.html',

          select='docs',

-         repo=repo_obj,

+         repo=repo,

          username=username,

          filename=filename,

          endpoint='view_docs',

      )

  

  

- @APP.route('/<repo:repo>/activity/')

- @APP.route('/<repo:repo>/activity')

- def view_project_activity(repo):

+ @APP.route('/<repo>/activity/')

+ @APP.route('/<repo>/activity')

+ @APP.route('/<namespace>/<repo>/activity/')

+ @APP.route('/<namespace>/<repo>/activity')

+ def view_project_activity(repo, namespace=None):

      """ Display the activity feed

      """

  

      if not APP.config.get('DATAGREPPER_URL'):

          flask.abort(404)

  

-     repo_obj = pagure.lib.get_project(SESSION, repo, user=None)

- 

-     if not repo_obj:

-         flask.abort(404, 'Project not found')

+     repo = flask.g.repo

  

      return flask.render_template(

          'activity.html',

-         repo=repo_obj,

+         repo=repo,

      )

  

  

- @APP.route('/watch/<repo:repo>/settings/<watch>', methods=['POST'])

- @APP.route('/watch/fork/<username>/<repo:repo>/settings/<watch>', methods=['POST'])

+ @APP.route('/<repo>/watch/settings/<watch>', methods=['POST'])

+ @APP.route('/<namespace>/<repo>/watch/settings/<watch>', methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<repo>/watch/settings/<watch>', methods=['POST'])

+ @APP.route(

+     '/fork/<username>/<namespace>/<repo>/watch/settings/<watch>',

+     methods=['POST'])

  @login_required

- def watch_repo(repo, watch, username=None):

+ def watch_repo(repo, watch, username=None, namespace=None):

      """ Marked for watching or Unwatching

      """

+ 

      return_point = flask.url_for('index')

      if pagure.is_safe_url(flask.request.referrer):

          return_point = flask.request.referrer
@@ -1862,15 +1974,10 @@ 

      if str(watch) not in ['0', '1']:

          flask.abort(400)

  

-     repo_obj = pagure.lib.get_project(SESSION, repo, user=username)

- 

-     if not repo_obj:

-         flask.abort(404, 'Project not found')

- 

      try:

          msg = pagure.lib.update_watch_status(

              SESSION,

-             repo_obj,

+             flask.g.repo,

              flask.g.fas_user.username,

              watch)

          SESSION.commit()

@@ -118,6 +118,7 @@ 

                      "description": "test project #1",

                      "id": 1,

                      "name": "test",

+                     "namespace": None,

                      "parent": None,

                      "priorities": {},

                      "tags": [],
@@ -132,6 +133,7 @@ 

                      "description": "test project #1",

                      "id": 1,

                      "name": "test",

+                     "namespace": None,

                      "parent": None,

                      "priorities": {},

                      "tags": [],
@@ -244,6 +246,7 @@ 

                  "description": "test project #1",

                  "id": 1,

                  "name": "test",

+                 "namespace": None,

                  "parent": None,

                  "priorities": {},

                  "tags": [],
@@ -258,6 +261,7 @@ 

                  "description": "test project #1",

                  "id": 1,

                  "name": "test",

+                 "namespace": None,

                  "parent": None,

                  "priorities": {},

                  "tags": [],

@@ -153,6 +153,7 @@ 

                    "description": "test project #1",

                    "id": 1,

                    "name": "test",

+                   "namespace": None,

                    "parent": None,

                    "priorities": {},

                    "tags": ["infra"],
@@ -179,6 +180,7 @@ 

                    "description": "test project #1",

                    "id": 1,

                    "name": "test",

+                   "namespace": None,

                    "parent": None,

                    "priorities": {},

                    "tags": ["infra"],
@@ -192,6 +194,7 @@ 

                    "description": "test project #2",

                    "id": 2,

                    "name": "test2",

+                   "namespace": None,

                    "parent": None,

                    "priorities": {},

                    "tags": [],
@@ -217,6 +220,7 @@ 

                    "description": "test project #1",

                    "id": 1,

                    "name": "test",

+                   "namespace": None,

                    "parent": None,

                    "priorities": {},

                    "tags": ["infra"],

@@ -207,6 +207,7 @@ 

          pagure.lib.git.update_ticket_from_git(

              self.session,

              reponame='test',

+             namespace=None,

              username=None,

              issue_uid='foobar',

              json_data=jsondata,

@@ -1379,16 +1379,16 @@ 

              output = self.app.get('/test/diff/feature..master')

              self.assertEqual(output.status_code, 200)

              self.assertIn(

-                 '<title>Diff from master to feature - test - Pagure</title>',

-                 output.data)

+                 '<title>Diff from master to feature - test\n - '

+                 'Pagure</title>', output.data)

              self.assertIn(

                  '<p class="error"> No commits found </p>', output.data)

  

              output = self.app.get('/test/diff/master..feature')

              self.assertEqual(output.status_code, 200)

              self.assertIn(

-                 '<title>Diff from feature to master - test - Pagure</title>',

-                 output.data)

+                 '<title>Diff from feature to master - test\n - '

+                 'Pagure</title>', output.data)

              self.assertNotIn(

                  '<input type="submit" class="submit positive button" '

                  'value="Create">', output.data)
@@ -1398,7 +1398,7 @@ 

              output = self.app.get('/test/diff/master..feature')

              self.assertEqual(output.status_code, 200)

              self.assertIn(

-                 '<title>    Create new Pull Request for master - test - '

+                 '<title>Create new Pull Request for master - test\n - '

                  'Pagure</title>', output.data)

              self.assertIn(

                  '<input type="submit" class="btn btn-primary" value="Create">',

@@ -1196,7 +1196,7 @@ 

              output = self.app.get('/test/c/%s..%s' % (c2.oid.hex, c1.oid.hex))

              self.assertEqual(output.status_code, 200)

              self.assertIn(

-                 '<title>Diff from %s to %s - test - Pagure</title>'

+                 '<title>Diff from %s to %s - test\n - Pagure</title>'

                  % (c2.oid.hex, c1.oid.hex),

                  output.data)

              self.assertIn(
@@ -1219,7 +1219,7 @@ 

              output = self.app.get('/test/c/%s..%s' % (c1.oid.hex, c2.oid.hex))

              self.assertEqual(output.status_code, 200)

              self.assertIn(

-                 '<title>Diff from %s to %s - test - Pagure</title>' %

+                 '<title>Diff from %s to %s - test\n - Pagure</title>' %

                  (c1.oid.hex, c2.oid.hex),

                  output.data)

              self.assertIn(
@@ -1245,7 +1245,7 @@ 

              output = self.app.get('/test/c/%s..%s' % (c1.oid.hex, c3.oid.hex))

              self.assertEqual(output.status_code, 200)

              self.assertIn(

-                 '<title>Diff from %s to %s - test - Pagure</title>' %

+                 '<title>Diff from %s to %s - test\n - Pagure</title>' %

                  (c1.oid.hex, c3.oid.hex), output.data)

              self.assertIn(

                  '<h5 class="text-muted">%s .. %s</h5>' %
@@ -1276,7 +1276,7 @@ 

                  '/test/c/%s..%s' % (c3.oid.hex, c1.oid.hex))

              self.assertEqual(output.status_code, 200)

              self.assertIn(

-                 '<title>Diff from %s to %s - test - Pagure</title>' %

+                 '<title>Diff from %s to %s - test\n - Pagure</title>' %

                  (c3.oid.hex, c1.oid.hex), output.data)

              self.assertIn(

                  '<h5 class="text-muted">%s .. %s</h5>' %
@@ -1618,8 +1618,8 @@ 

          self.assertTrue(

              '<div class="list-group" id="diff_list" style="display:none;">'

              in output.data)

-         self.assertTrue('</a> Authored by Alice Author' in output.data)

-         self.assertTrue('Committed by Cecil Committer' in output.data)

+         self.assertTrue('  Authored by Alice Author\n' in output.data)

+         self.assertTrue('  Committed by Cecil Committer\n' in output.data)

          self.assertTrue(

              '<span style="color: #00A000">+ Pagure</span>' in output.data)

          self.assertTrue(
@@ -1643,8 +1643,8 @@ 

          self.assertTrue(

              '<div class="list-group" id="diff_list" style="display:none;">'

              in output.data)

-         self.assertTrue('</a> Authored by Alice Author' in output.data)

-         self.assertTrue('Committed by Cecil Committer' in output.data)

+         self.assertTrue('  Authored by Alice Author\n' in output.data)

+         self.assertTrue('  Committed by Cecil Committer\n' in output.data)

          self.assertTrue(

              # new version of pygments

              '<div class="highlight" style="background: #f8f8f8">'
@@ -1704,8 +1704,8 @@ 

          self.assertTrue(

              '<div class="list-group" id="diff_list" style="display:none;">'

              in output.data)

-         self.assertTrue('</a> Authored by Alice Author' in output.data)

-         self.assertTrue('Committed by Cecil Committer' in output.data)

+         self.assertTrue('  Authored by Alice Author\n' in output.data)

+         self.assertTrue('  Committed by Cecil Committer\n' in output.data)

          self.assertTrue(

              '<span style="color: #00A000">+ Pagure</span>' in output.data)

          self.assertTrue(
@@ -3215,21 +3215,21 @@ 

              self.assertEqual(output.status_code, 404)

  

              output = self.app.post(

-                 '/watch/foo', data=data, follow_redirects=True)

+                 '/foo/watch/settings', data=data, follow_redirects=True)

              self.assertEqual(output.status_code, 404)

  

              output = self.app.post(

-                 '/watch/test/settings/2', data=data, follow_redirects=True)

+                 '/test/watch/settings/2', data=data, follow_redirects=True)

              self.assertEqual(output.status_code, 400)

  

              output = self.app.post(

-                 '/watch/test/settings/0', data=data, follow_redirects=True)

+                 '/test/watch/settings/0', data=data, follow_redirects=True)

              self.assertIn(

                  '</button>\n                      You are no longer'

                  ' watching this repo.', output.data)

  

              output = self.app.post(

-                 '/watch/test/settings/1', data=data, follow_redirects=True)

+                 '/test/watch/settings/1', data=data, follow_redirects=True)

              self.assertIn(

                  '</button>\n                      You are now'

                  ' watching this repo.', output.data)
@@ -3248,13 +3248,15 @@ 

              pygit2.init_repository(gitrepo, bare=True)

  

              output = self.app.post(

-                 '/watch/fork/foo/test/settings/0', data=data, follow_redirects=True)

+                 '/fork/foo/test/watch/settings/0', data=data,

+                 follow_redirects=True)

              self.assertIn(

                  '</button>\n                      You are no longer'

                  ' watching this repo.', output.data)

  

              output = self.app.post(

-                 '/watch/fork/foo/test/settings/1', data=data, follow_redirects=True)

+                 '/fork/foo/test/watch/settings/1', data=data,

+                 follow_redirects=True)

              self.assertIn(

                  '</button>\n                      You are now'

                  ' watching this repo.', output.data)

@@ -124,7 +124,8 @@ 

              pagure.exceptions.PagureException,

              pagure.lib.new_project,

              self.session,

-             name='forks/test',

+             name='test',

+             namespace='forks',

              description='test project forks/test',

              url='',

              avatar_email='',
@@ -140,7 +141,8 @@ 

          # So just put it in the DB

          item = pagure.lib.model.Project(

              user_id=1,  # pingou

-             name='forks/test',

+             name='test',

+             namespace='forks',

              description='test project forks/test',

              hook_token='aaabbbcccddd',

          )
@@ -194,7 +196,8 @@ 

              pagure.exceptions.PagureException,

              pagure.lib.new_project,

              self.session,

-             name='forks/test',

+             name='test',

+             namespace='forks',

              description='test project forks/test',

              url='',

              avatar_email='',
@@ -210,7 +213,8 @@ 

          # So just put it in the DB

          item = pagure.lib.model.Project(

              user_id=1,  # pingou

-             name='forks/test',

+             name='test',

+             namespace='forks',

              description='test project forks/test',

              hook_token='aaabbbcccddd',

          )

file modified
+2 -1
@@ -755,7 +755,8 @@ 

              pagure.lib.new_project,

              session=self.session,

              user='pingou',

-             name='pingou/' + 's' * 40,

+             name='s' * 40,

+             namespace='pingou',

              blacklist=['static'],

              allowed_prefix=['pingou'],

              gitfolder=gitfolder,

file modified
+49 -4
@@ -712,7 +712,7 @@ 

  index 0000000..60f7480

  --- /dev/null

  +++ b/456

- @@ -0,0 +1,83 @@

+ @@ -0,0 +1,85 @@

  +{

  +    "assignee": null,

  +    "branch": "master",
@@ -730,6 +730,7 @@ 

  +        "description": "test project for ticket",

  +        "id": 1,

  +        "name": "test_ticket_repo",

+ +        "namespace": null,

  +        "parent": null,

  +        "priorities": {},

  +        "settings": {
@@ -759,6 +760,7 @@ 

  +        "description": "test project for ticket",

  +        "id": 1,

  +        "name": "test_ticket_repo",

+ +        "namespace": null,

  +        "parent": null,

  +        "priorities": {},

  +        "settings": {
@@ -851,13 +853,14 @@ 

              pagure.lib.git.update_ticket_from_git,

              self.session,

              reponame='foobar',

+             namespace=None,

              username=None,

              issue_uid='foobar',

              json_data=data

          )

  

          pagure.lib.git.update_ticket_from_git(

-             self.session, reponame='test', username=None,

+             self.session, reponame='test', namespace=None, username=None,

              issue_uid='foobar', json_data=data

          )

          self.session.commit()
@@ -872,7 +875,7 @@ 

  

          data["title"] = "fake issue for tests"

          pagure.lib.git.update_ticket_from_git(

-             self.session, reponame='test', username=None,

+             self.session, reponame='test', namespace=None, username=None,

              issue_uid='foobar', json_data=data

          )

          self.session.commit()
@@ -935,7 +938,7 @@ 

          }

  

          pagure.lib.git.update_ticket_from_git(

-             self.session, reponame='test', username=None,

+             self.session, reponame='test', namespace=None, username=None,

              issue_uid='foobar2', json_data=data

          )

  
@@ -1098,6 +1101,7 @@ 

              pagure.lib.git.update_request_from_git,

              self.session,

              reponame='foobar',

+             namespace=None,

              username=None,

              request_uid='d4182a2ac2d541d884742d3037c26e56',

              json_data=data,
@@ -1110,6 +1114,7 @@ 

          pagure.lib.git.update_request_from_git(

              self.session,

              reponame='test',

+             namespace=None,

              username=None,

              request_uid='d4182a2ac2d541d884742d3037c26e56',

              json_data=data,
@@ -1213,6 +1218,7 @@ 

          pagure.lib.git.update_request_from_git(

              self.session,

              reponame='test',

+             namespace=None,

              username=None,

              request_uid='d4182a2ac2d541d884742d3037c26e57',

              json_data=data,
@@ -1383,6 +1389,45 @@ 

              os.path.join(tests.HERE, 'forks', 'pingou', 'foo.test.git'))

          self.assertEqual(repo_name, 'pingou')

  

+         repo_name = pagure.lib.git.get_username(

+             os.path.join(tests.HERE, 'forks', 'pingou', 'bar/foo.test.git'))

+         self.assertEqual(repo_name, 'pingou')

+ 

+         repo_name = pagure.lib.git.get_username(os.path.join(

+             tests.HERE, 'forks', 'pingou', 'fooo/bar/foo.test.git'))

+         self.assertEqual(repo_name, 'pingou')

+ 

+     def test_get_repo_namespace(self):

+         """ Test the get_repo_namespace method of pagure.lib.git. """

+         repo_name = pagure.lib.git.get_repo_namespace(

+             os.path.join(tests.HERE, 'repos', 'test_ticket_repo.git'))

+         self.assertEqual(repo_name, None)

+ 

+         repo_name = pagure.lib.git.get_repo_namespace(

+             os.path.join(tests.HERE, 'repos', 'foo/bar/baz/test.git'))

+         self.assertEqual(repo_name, 'foo/bar/baz')

+ 

+         repo_name = pagure.lib.git.get_repo_namespace(

+             os.path.join(tests.HERE, 'repos', 'foo.test.git'))

+         self.assertEqual(repo_name, None)

+ 

+         repo_name = pagure.lib.git.get_repo_namespace(os.path.join(

+             tests.HERE, 'repos', 'forks', 'user', 'foo.test.git'))

+         self.assertEqual(repo_name, None)

+ 

+         repo_name = pagure.lib.git.get_repo_namespace(os.path.join(

+             tests.HERE, 'repos', 'forks', 'user', 'bar/foo.test.git'))

+         self.assertEqual(repo_name, 'bar')

+ 

+         repo_name = pagure.lib.git.get_repo_namespace(os.path.join(

+             tests.HERE, 'repos', 'forks', 'user', 'ns/bar/foo.test.git'))

+         self.assertEqual(repo_name, 'ns/bar')

+ 

+         repo_name = pagure.lib.git.get_repo_namespace(os.path.join(

+             tests.HERE, 'repos', 'forks', 'user', '/bar/foo.test.git'))

+         self.assertEqual(repo_name, 'bar')

+ 

+ 

  

  if __name__ == '__main__':

      SUITE = unittest.TestLoader().loadTestsFromTestCase(PagureLibGittests)

file modified
+55 -24
@@ -43,21 +43,26 @@ 

          """ Test the get_relation function of pagure.lib.link with relates.

          """

  

-         self.assertEqual(

-             pagure.lib.link.get_relation(

-                 self.session,

-                 'test',

-                 None,

-                 COMMENTS[0],

-                 'relates',

-             ),

-             []

+         link = pagure.lib.link.get_relation(

+             self.session,

+             reponame='test',

+             namespace=None,

+             username=None,

+             text=COMMENTS[0],

+             reftype='relates',

          )

+         self.assertEqual(link, [])

  

          tests.create_projects(self.session)

  

          link = pagure.lib.link.get_relation(

-             self.session, 'test', None, COMMENTS[4], 'relates')

+             self.session,

+             reponame='test',

+             namespace=None,

+             username=None,

+             text=COMMENTS[4],

+             reftype='relates',

+         )

          self.assertEqual(link, [])

  

          # Create the issue
@@ -75,7 +80,12 @@ 

  

          for idx, comment in enumerate(COMMENTS):

              link = pagure.lib.link.get_relation(

-                 self.session, 'test', None, comment, 'relates')

+                 self.session,

+                 reponame='test',

+                 namespace=None,

+                 username=None,

+                 text=comment,

+                 reftype='relates')

              if idx == 4:

                  self.assertEqual(

                      str(link),
@@ -84,7 +94,13 @@ 

                  self.assertEqual(link, [])

  

          link = pagure.lib.link.get_relation(

-             self.session, 'test', None, COMMENTS[5], 'relates')

+             self.session,

+             reponame='test',

+             namespace=None,

+             username=None,

+             text=COMMENTS[5],

+             reftype='relates',

+         )

          self.assertEqual(link, [])

  

          # Create the issue
@@ -102,7 +118,12 @@ 

  

          for idx, comment in enumerate(COMMENTS):

              link = pagure.lib.link.get_relation(

-                 self.session, 'test', None, comment, 'relates')

+                 self.session,

+                 reponame='test',

+                 namespace=None,

+                 username=None,

+                 text=comment,

+                 reftype='relates')

              if idx == 4:

                  self.assertEqual(

                      str(link),
@@ -118,21 +139,26 @@ 

          """ Test the get_relation function of pagure.lib.link with fixes.

          """

  

-         self.assertEqual(

-             pagure.lib.link.get_relation(

-                 self.session,

-                 'test',

-                 None,

-                 COMMENTS[0],

-                 'fixes',

-             ),

-             []

+         link = pagure.lib.link.get_relation(

+             self.session,

+             reponame='test',

+             namespace=None,

+             username=None,

+             text=COMMENTS[0],

+             reftype='fixes',

          )

+         self.assertEqual(link, [])

  

          tests.create_projects(self.session)

  

          link = pagure.lib.link.get_relation(

-             self.session, 'test', None, COMMENTS[2], 'fixes')

+             self.session,

+             reponame='test',

+             namespace=None,

+             username=None,

+             text=COMMENTS[2],

+             reftype='fixes',

+         )

          self.assertEqual(link, [])

  

          # Create the issue
@@ -150,7 +176,12 @@ 

  

          for idx, comment in enumerate(COMMENTS):

              link = pagure.lib.link.get_relation(

-                 self.session, 'test', None, comment, 'fixes')

+                 self.session,

+                 reponame='test',

+                 namespace=None,

+                 username=None,

+                 text=comment,

+                 reftype='fixes')

              if idx == 2:

                  self.assertEqual(

                      str(link),

@@ -96,8 +96,8 @@ 

          self.assertTrue(

              '<div class="list-group" id="diff_list" style="display:none;">'

              in output.data)

-         self.assertTrue('</a> Authored by Alice Author' in output.data)

-         self.assertTrue('Committed by Cecil Committer' in output.data)

+         self.assertTrue('  Authored by Alice Author\n' in output.data)

+         self.assertTrue('  Committed by Cecil Committer\n' in output.data)

          self.assertTrue(

              '<span style="color: #00A000">+ Pagure</span>' in output.data)

          self.assertTrue(
@@ -111,8 +111,8 @@ 

          self.assertTrue(

              '<div class="list-group" id="diff_list" style="display:none;">'

              in output.data)

-         self.assertTrue('</a> Authored by Alice Author' in output.data)

-         self.assertTrue('Committed by Cecil Committer' in output.data)

+         self.assertTrue('  Authored by Alice Author\n' in output.data)

+         self.assertTrue('  Committed by Cecil Committer\n' in output.data)

          self.assertTrue(

              '<span style="color: #00A000">+ Pagure</span>' in output.data)

          self.assertTrue(
@@ -131,8 +131,8 @@ 

          self.assertTrue(

              '<div class="list-group" id="diff_list" style="display:none;">'

              in output.data)

-         self.assertTrue('</a> Authored by Alice Author' in output.data)

-         self.assertTrue('Committed by Cecil Committer' in output.data)

+         self.assertTrue('  Authored by Alice Author\n' in output.data)

+         self.assertTrue('  Committed by Cecil Committer\n' in output.data)

          self.assertTrue(

              # new version of pygments

              '<div class="highlight" style="background: #f8f8f8">'
@@ -179,8 +179,8 @@ 

          self.assertTrue(

              '<div class="list-group" id="diff_list" style="display:none;">'

              in output.data)

-         self.assertTrue('</a> Authored by Alice Author' in output.data)

-         self.assertTrue('Committed by Cecil Committer' in output.data)

+         self.assertTrue('  Authored by Alice Author\n' in output.data)

+         self.assertTrue('  Committed by Cecil Committer\n' in output.data)

          self.assertTrue(

              '<span style="color: #00A000">+ Pagure</span>' in output.data)

          self.assertTrue(
@@ -193,8 +193,8 @@ 

          self.assertTrue(

              '<div class="list-group" id="diff_list" style="display:none;">'

              in output.data)

-         self.assertTrue('</a> Authored by Alice Author' in output.data)

-         self.assertTrue('Committed by Cecil Committer' in output.data)

+         self.assertTrue('  Authored by Alice Author\n' in output.data)

+         self.assertTrue('  Committed by Cecil Committer\n' in output.data)

          self.assertTrue(

              '<span style="color: #00A000">+ Pagure</span>' in output.data)

          self.assertTrue(

@@ -115,10 +115,14 @@ 

              data = json.loads(reply.value)

              username = None

              if data['project'].startswith('forks'):

-                 _, username, projectname = data['project'].split('/', 2)

+                 username, projectname = data['project'].split('/', 1)

              else:

                  projectname = data['project']

  

+             namespace = None

+             if '/' in projectname:

+                 namespace, projectname = projectname.split('/', 1)

+ 

              project = pagure.lib.get_project(

                  session=pagure.SESSION, name=projectname, user=username)

              log.info('Got the project, going to the webhooks')

no initial comment

6 new commits added

  • Adjust the regex validating project names
  • Add unit-tests for pagure.lib.git.get_namespace
  • Expand unit-tests for pagure.lib.git.get_username
  • Let's get the namespace by rsplit rather than split
  • Adjust pagure-ci and pagure-webhook to account for namespaces
  • Rework the get_repo_namespace method in pagure.lib.git
8 years ago

1 new commit added

  • Fix typo in the edit_tag.html template
8 years ago

this, this, this, this, this and this should be commented, no ?

The activity endpoint is still very much WIP and not advertised, so I'm inclined to leave it as such.

The EventListener it still there because it's still most helpful when trying to debug SSE errors.

The two on edit_file.html could be dropped sure, but do we want to add this change to this PR or do it in another one since it's not quite related :)

namespace=repo.namespace here and the next one.

missed here and here and here?

btw, where is this render coming from ?

pagure.ui.filter :)

Good catch for the links, I'll adjust them

probably here, here, here, here, here, here, here, here, here, here, here also

we shouldn't need this or this, we do have repo in the view_args

I hope @pingou has covered all the files. Besides these, i haven't looked at the tests, will do tomorrow morning.

4 new commits added

  • Add missing namespaces arguments in the template/urls, thanks @vivekanand1101
  • Adjust the is_watching method for namespaces, thanks @vivekanand1101
  • Add missing namespace arguments and fix typos pointed out by @vivekanand1101
  • Drop the two console.log() call in edit_file.html
8 years ago

rebased

8 years ago

I don't like this one, as this introduces a hidden value that will break (not doe what someone expects).

How about just namesmace == '' if you really need something?

Why don't you reuse allowed_prefix here for consistency?

Why is namespace here the earlier argument, while everywhere else it's RUN (Repo, User, Namespace)?

Why do you use username, repo, namespace order here, while the rest uses RUN?

The problem is that is no namespace is provided, for some reason I end up with a 'None' string, so this is the only way I found to actually set namespace to None which is what we want.

Perhaps it's an idea to instead just add a property "repo.fullname", which includes the namespace, rather than reproduce this every time?

They are all keyword arguments, so the order doesn't really mater...

Even more inconsistent.. Now you've got RUN, URN, and NRU :sob:

Fullname includes the prefix forks/ for forks, I'm not sure it's ideal

Rather than passing it here explicitly.
So my idea was to just make this init use the allowed_prefixes code to determine the list itself rather than having it be passed in.

Well it's not just what is in the configuration file and I think I'd rather keep the logic out of the forms

1 new commit added

  • Adjust the order of the arguments in the links and some functions
8 years ago

Ack. I still find the wtforms thing strange, but if you say that it's okay...
:thumbsup:

2 new commits added

  • Fix the ProjectForm to be allowed to return None, not just unicode objects
  • Specify the allowed namespaces when creating a project via the API
8 years ago

That looks a lot nicer. :thumbsup: :)

Thanks, let's merge then :)

Thanks for the reviews @puiterwijk and @vivekanand1101 I know this wasn't a small one!

Pull-Request has been merged by pingou

8 years ago
Changes Summary 68
+61
file added
alembic/versions/350efb3f6baf_add_namespace_to_project.py
+1 -1
file changed
alembic/versions/36116bb7a69b_add_the_url_field_to_project.py
+5 -1
file changed
pagure-ci/pagure_ci_server.py
+14 -15
file changed
pagure/__init__.py
+11 -5
file changed
pagure/api/ci/jenkins.py
+57 -12
file changed
pagure/api/fork.py
+60 -15
file changed
pagure/api/issue.py
+28 -4
file changed
pagure/api/project.py
+24 -2
file changed
pagure/forms.py
+4 -1
file changed
pagure/hooks/files/fedmsg_hook.py
+9 -6
file changed
pagure/hooks/files/pagure_force_commit_hook.py
+2 -0
file changed
pagure/hooks/files/pagure_hook.py
+3 -1
file changed
pagure/hooks/files/pagure_hook_requests.py
+3 -1
file changed
pagure/hooks/files/pagure_hook_tickets.py
+6 -3
file changed
pagure/hooks/files/rtd_hook.py
+34 -14
file changed
pagure/lib/__init__.py
+35 -11
file changed
pagure/lib/git.py
+4 -3
file changed
pagure/lib/link.py
+4 -0
file changed
pagure/lib/model.py
+5 -2
file changed
pagure/templates/_formhelper.html
+35 -17
file changed
pagure/templates/_render_repo.html
+2 -1
file changed
pagure/templates/activity.html
+6 -3
file changed
pagure/templates/add_group_project.html
+2 -1
file changed
pagure/templates/add_token.html
+4 -2
file changed
pagure/templates/add_user.html
+2 -2
file changed
pagure/templates/comment_update.html
+55 -24
file changed
pagure/templates/commit.html
+33 -12
file changed
pagure/templates/commits.html
+9 -4
file changed
pagure/templates/docs.html
+25 -10
file changed
pagure/templates/edit_file.html
+6 -2
file changed
pagure/templates/edit_tag.html
+56 -22
file changed
pagure/templates/file.html
+10 -4
file changed
pagure/templates/forks.html
+46 -23
file changed
pagure/templates/index_auth.html
+69 -23
file changed
pagure/templates/issue.html
+90 -44
file changed
pagure/templates/issues.html
+24 -9
file changed
pagure/templates/new_issue.html
+1 -0
file changed
pagure/templates/new_project.html
+4 -2
file changed
pagure/templates/new_release.html
+6 -3
file changed
pagure/templates/plugin.html
+115 -42
file changed
pagure/templates/pull_request.html
+4 -1
file changed
pagure/templates/pull_request_comment.html
+10 -4
file changed
pagure/templates/pull_request_title.html
+10 -4
file changed
pagure/templates/releases.html
+12 -4
file changed
pagure/templates/remote_pull_request.html
+21 -6
file changed
pagure/templates/repo_info.html
+91 -34
file changed
pagure/templates/repo_master.html
+62 -21
file changed
pagure/templates/requests.html
+49 -17
file changed
pagure/templates/roadmap.html
+94 -27
file changed
pagure/templates/settings.html
+4 -4
file changed
pagure/templates/user_list.html
+9 -3
file changed
pagure/templates/user_requests.html
+17 -5
file changed
pagure/ui/app.py
+199 -85
file changed
pagure/ui/fork.py
+143 -62
file changed
pagure/ui/issues.py
+28 -8
file changed
pagure/ui/plugins.py
+338 -231
file changed
pagure/ui/repo.py
+4 -0
file changed
tests/test_pagure_flask_api_fork.py
+4 -0
file changed
tests/test_pagure_flask_api_project.py
+1 -0
file changed
tests/test_pagure_flask_dump_load_ticket.py
+5 -5
file changed
tests/test_pagure_flask_ui_fork.py
+18 -16
file changed
tests/test_pagure_flask_ui_repo.py
+8 -4
file changed
tests/test_pagure_flask_ui_repo_slash_name.py
+2 -1
file changed
tests/test_pagure_lib.py
+49 -4
file changed
tests/test_pagure_lib_git.py
+55 -24
file changed
tests/test_pagure_lib_link.py
+10 -10
file changed
tests/test_zzz_pagure_flask_ui_old_commit.py
+5 -1
file changed
webhook-server/pagure-webhook-server.py