#5062 Add support for git aliases
Merged 3 years ago by pingou. Opened 3 years ago by pingou.

file modified
+7 -1
@@ -161,7 +161,13 @@ 

  

  

  def get_request_data():

-     return flask.request.form or flask.request.get_json() or {}

+     # Check if it's JSON or form data

+     if flask.request.headers.get("Content-Type") == "application/json":

+         # Set force to True to ignore the mimetype. Set silent so that None is

+         # returned if it's invalid JSON.

+         return flask.request.get_json(force=True, silent=True) or {}

+     else:

+         return flask.request.form or flask.request.get_json() or {}

  

  

  def api_login_required(acls=None, optional=False):

file modified
+227 -24
@@ -1627,15 +1627,8 @@ 

          )

  

      valid_keys = ["main_admin", "retain_access"]

-     # Check if it's JSON or form data

-     if flask.request.headers.get("Content-Type") == "application/json":

-         # Set force to True to ignore the mimetype. Set silent so that None is

-         # returned if it's invalid JSON.

-         args = flask.request.get_json(force=True, silent=True) or {}

-         retain_access = args.get("retain_access", False)

-     else:

-         args = get_request_data()

-         retain_access = args.get("retain_access", "").lower() in ["true", "1"]

+     args = get_request_data()

+     retain_access = args.get("retain_access", "").lower() in ["true", "1"]

  

      if not args:

          raise pagure.exceptions.APIError(400, error_code=APIERROR.EINVALIDREQ)
@@ -1847,14 +1840,7 @@ 

      project = _get_repo(repo, username, namespace)

      _check_token(project, project_token=False)

  

-     # Check if it's JSON or form data

-     if flask.request.headers.get("Content-Type") == "application/json":

-         # Set force to True to ignore the mimetype. Set silent so that None is

-         # returned if it's invalid JSON.

-         json = flask.request.get_json(force=True, silent=True) or {}

-         wait = json.get("wait", False)

-     else:

-         wait = pagure.utils.is_true(get_request_data().get("wait"))

+     wait = pagure.utils.is_true(get_request_data().get("wait"))

  

      try:

          task = pagure.lib.git.generate_gitolite_acls(project=project)
@@ -1926,13 +1912,7 @@ 

      project = _get_repo(repo, username, namespace)

      _check_token(project, project_token=False)

  

-     # Check if it's JSON or form data

-     if flask.request.headers.get("Content-Type") == "application/json":

-         # Set force to True to ignore the mimetype. Set silent so that None is

-         # returned if it's invalid JSON.

-         args = flask.request.get_json(force=True, silent=True) or {}

-     else:

-         args = get_request_data()

+     args = get_request_data()

  

      branch = args.get("branch")

      from_branch = args.get("from_branch")
@@ -1969,6 +1949,229 @@ 

      return jsonout

  

  

+ @API.route("/<repo>/git/alias/drop", methods=["POST"])

+ @API.route("/<namespace>/<repo>/git/alias/drop", methods=["POST"])

+ @API.route("/fork/<username>/<repo>/git/alias/drop", methods=["POST"])

+ @API.route(

+     "/fork/<username>/<namespace>/<repo>/git/alias/drop", methods=["POST"]

+ )

+ @api_login_required(

+     acls=["delete_git_alias", "modify_git_alias", "modify_project"]

+ )

+ @api_method

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

+     """

+     Delete a git branch alias

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

+     Delete an existing git branch alias from a project.

+ 

+     ::

+ 

+         POST /api/0/rpms/python-requests/alias/drop

+ 

+ 

+     Input

+     ^^^^^

+ 

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

+     | Key              | Type    | Optionality  | Description                |

+     +==================+=========+==============+============================+

+     | ``alias_from``   | string  | Mandatory    | | The origin reference the |

+     |                  |         |              |   alias is for.            |

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

+     | ``alias_to``     | string  | Mandatory    | | The destination reference|

+     |                  |         |              |   of the alias (must be an |

+     |                  |         |              |   existing branch in the   |

+     |                  |         |              |   git repository).         |

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

+ 

+     Note: while the references are listed as ``refs/heads/...`` the alias_from

+         and alias_to need to be specified as the basic branch name that they

+         are (ie: ``refs/heads/main`` needs to be specified as ``main``).

+ 

+ 

+     Sample input

+     ^^^^^^^^^^^^

+ 

+     ::

+ 

+         {

+           'alias_from': 'master',

+           'alias_to': 'main'

+         }

+ 

+ 

+ 

+     Sample response

+     ^^^^^^^^^^^^^^^

+ 

+     ::

+ 

+         {

+             "refs/heads/rawhide": "refs/heads/main"

+         }

+ 

+     """

+     project = _get_repo(repo, username, namespace)

+     _check_token(project, project_token=False)

+ 

+     args = get_request_data()

+ 

+     alias_from = args.get("alias_from")

+     alias_to = args.get("alias_to")

+ 

+     if (

+         not alias_from

+         or (alias_from and not isinstance(alias_from, string_types))

+     ) or (

+         not alias_to or (alias_to and not isinstance(alias_to, string_types))

+     ):

+         raise pagure.exceptions.APIError(400, error_code=APIERROR.EINVALIDREQ)

+ 

+     try:

+         pagure.lib.git.drop_branch_aliases(project, alias_from, alias_to)

+     except KeyError:

+         raise pagure.exceptions.APIError(

+             400, error_code=APIERROR.EBRANCHNOTFOUND

+         )

+ 

+     return api_list_git_alias(repo, username, namespace)

+ 

+ 

+ @API.route("/<repo>/git/alias/new", methods=["POST"])

+ @API.route("/<namespace>/<repo>/git/alias/new", methods=["POST"])

+ @API.route("/fork/<username>/<repo>/git/alias/new", methods=["POST"])

+ @API.route(

+     "/fork/<username>/<namespace>/<repo>/git/alias/new", methods=["POST"]

+ )

+ @api_login_required(

+     acls=["create_git_alias", "modify_git_alias", "modify_project"]

+ )

+ @api_method

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

+     """

+     Create a git branch alias

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

+     Create a new git branch alias in a project.

+ 

+     ::

+ 

+         POST /api/0/rpms/python-requests/alias/new

+ 

+ 

+     Input

+     ^^^^^

+ 

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

+     | Key              | Type    | Optionality  | Description                |

+     +==================+=========+==============+============================+

+     | ``alias_from``   | string  | Mandatory    | | The origin reference the |

+     |                  |         |              |   alias is for.            |

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

+     | ``alias_to``     | string  | Mandatory    | | The destination reference|

+     |                  |         |              |   of the alias (must be an |

+     |                  |         |              |   existing branch in the   |

+     |                  |         |              |   git repository).         |

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

+ 

+     Note: while the references are listed as ``refs/heads/...`` the alias_from

+         and alias_to need to be specified as the basic branch name that they

+         are (ie: ``refs/heads/main`` needs to be specified as ``main``).

+ 

+ 

+     Sample input

+     ^^^^^^^^^^^^

+ 

+     ::

+ 

+         {

+           'alias_from': 'main',

+           'alias_to': 'rawhide'

+         }

+ 

+ 

+     Sample response

+     ^^^^^^^^^^^^^^^

+ 

+     ::

+ 

+         {

+             "refs/heads/main": "refs/heads/master"

+         }

+ 

+     """

+     project = _get_repo(repo, username, namespace)

+     _check_token(project, project_token=False)

+ 

+     args = get_request_data()

+ 

+     alias_from = args.get("alias_from")

+     alias_to = args.get("alias_to")

+ 

+     if (

+         not alias_from

+         or (alias_from and not isinstance(alias_from, string_types))

+     ) or (

+         not alias_to or (alias_to and not isinstance(alias_to, string_types))

+     ):

+         raise pagure.exceptions.APIError(

+             400,

+             error_code=APIERROR.EINVALIDREQ,

+             error="Invalid input for alias_from or alias_to",

+         )

+ 

+     try:

+         pagure.lib.git.set_branch_alias(project, alias_from, alias_to)

+     except KeyError:

+         raise pagure.exceptions.APIError(

+             400, error_code=APIERROR.EBRANCHNOTFOUND

+         )

+     except pagure.exceptions.PagureException as error:

+         raise pagure.exceptions.APIError(

+             400, error_code=APIERROR.ENOCODE, error=str(error)

+         )

+ 

+     return api_list_git_alias(repo, username, namespace)

+ 

+ 

+ @API.route("/<repo>/git/alias")

+ @API.route("/<namespace>/<repo>/git/alias")

+ @API.route("/fork/<username>/<repo>/git/alias")

+ @API.route("/fork/<username>/<namespace>/<repo>/git/alias")

+ @api_method

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

+     """

+     List git branch alias

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

+     List the existing git branch alias in a project.

+ 

+     ::

+ 

+         GET /api/0/rpms/python-requests/alias

+ 

+ 

+     Sample response

+     ^^^^^^^^^^^^^^^

+ 

+     ::

+ 

+         {

+             "refs/heads/main": "refs/heads/master"

+         }

+ 

+     """

+     project = _get_repo(repo, username, namespace)

+     _check_token(project, project_token=False)

+ 

+     try:

+         output = pagure.lib.git.get_branch_aliases(project)

+     except pygit2.GitError:  # pragma: no cover

+         raise pagure.exceptions.APIError(400, error_code=APIERROR.EGITERROR)

+ 

+     jsonout = flask.jsonify(output)

+     return jsonout

+ 

+ 

  @API.route("/<repo>/c/<commit_hash>/flag")

  @API.route("/<namespace>/<repo>/c/<commit_hash>/flag")

  @API.route("/fork/<username>/<repo>/c/<commit_hash>/flag")

@@ -358,6 +358,9 @@ 

      "pull_request_rebase": "Rebase a pull-request",

      "tag_project": "Allows adding git tags to a project",

      "commit": "Commit to a git repository via http(s)",

+     "modify_git_alias": "Modify git aliases (create or delete)",

+     "create_git_alias": "Create git aliases",

+     "delete_git_alias": "Delete git aliases",

  }

  

  # List of ACLs which a regular user is allowed to associate to an API token

file modified
+55
@@ -2670,6 +2670,61 @@ 

      repo_obj.set_head(reference.name)

  

  

+ def get_branch_aliases(project):

+     """ Iterates through the references of the provided git repo to extract all

+     of its aliases.

+     """

+     repo_path = pagure.utils.get_repo_path(project)

+     repo_obj = PagureRepo(repo_path)

+ 

+     output = {}

+     for ref in repo_obj.listall_reference_objects():

+         if "refs/heads/" in str(ref.target):

+             output[ref.name] = ref.target

+     return output

+ 

+ 

+ def set_branch_alias(project, source, dest):

+     """ Create a reference in the provided git repo from the source reference

+     to the dest one.

+     """

+     repo_path = pagure.utils.get_repo_path(project)

+     repo_obj = PagureRepo(repo_path)

+ 

+     # Check that the source reference exists

+     repo_obj.lookup_reference("refs/heads/{}".format(dest))

+ 

+     try:

+         repo_obj.create_reference(

+             "refs/heads/{}".format(source), "refs/heads/{}".format(dest),

+         )

+     except ValueError as err:

+         _log.debug(

+             "Failed to create alias from %s to %s -- %s", source, dest, err

+         )

+         raise pagure.exceptions.PagureException(

+             "Could not create alias from {0} to {1}. "

+             "Reference already existing?".format(source, dest)

+         )

+ 

+ 

+ def drop_branch_aliases(project, source, dest):

+     """ Delete a reference in the provided git repo from the source reference

+     to the dest one.

+     """

+     repo_path = pagure.utils.get_repo_path(project)

+     repo_obj = PagureRepo(repo_path)

+ 

+     ref = repo_obj.lookup_reference("refs/heads/{}".format(dest))

+     output = False

+     if ref.target == "refs/heads/{}".format(source):

+         ref_file = os.path.join(repo_obj.path, ref.name)

+         if os.path.exists(ref_file):

+             os.unlink(ref_file)

+             output = True

+     return output

+ 

+ 

  def delete_project_repos(project):

      """ Deletes the actual git repositories on disk or repoSpanner

  

@@ -19,8 +19,8 @@ 

            <h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>

            <a class="nav-item nav-link active" id="projectdetails" data-toggle="tab"

                  href="#projectdetails-tab" role="tab" aria-controls="projectdetails" aria-selected="true">Project Details</a>

-           <a class="nav-item nav-link" id="defaultbranch" data-toggle="tab"

-                 href="#defaultbranch-tab" role="tab" aria-controls="defaultbranch">Default Branch</a>

+           <a class="nav-item nav-link" id="gitbranch" data-toggle="tab"

+                 href="#gitbranch-tab" role="tab" aria-controls="gitbranch">Git Branches</a>

  

            {% if config.get('WEBHOOK', False) %}

            <a class="nav-item nav-link" id="privatewebhookkey" data-toggle="tab"
@@ -179,22 +179,9 @@ 

                </div>

              </div>

            </div>

-           <div class="tab-pane fade" id="defaultbranch-tab" role="tabpanel" aria-labelledby="defaultbranch-tab">

-             <h3 class="font-weight-bold mb-3">

-               Default Branch

-             </h3>

-             <div class="row">

-               <div class="col">

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

-                     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"/>

-                 </form>

-               </div>

-             </div>

+ 

+           <div class="tab-pane fade" id="gitbranch-tab" role="tabpanel" aria-labelledby="gitbranch-tab">

+               {% include 'settings_git_branches.html' %}

            </div>

  

            {% if config.get('WEBHOOK', False) %}

@@ -0,0 +1,195 @@ 

+ 

+ <h3 class="font-weight-bold mb-3">

+   Default Branch

+ </h3>

+ <div class="row">

+   <div class="col">

+     <form action="{{ url_for('ui_ns.change_ref_head',

+         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"/>

+     </form>

+   </div>

+ </div>

+ 

+ <div class="row p-t-1">

+   <div class="col-sm-12"></div>

+ </div>

+ 

+ <h3 class="font-weight-bold mb-3">

+   Git Branch Alias

+ </h3>

+ <div class="row">

+   <div class="col">

+     <div class="form-group">

+       <div class="row">

+         <div class="col-sm-5" >

+           Alias name

+         </div>

+ 

+         <div class="col-sm-5" >

+           Alias To (existing reference/branch)

+         </div>

+ 

+       </div>

+     </div>

+     <div class="form-group settings-field-rows" id="git-alias-list">

+       <form action="{{ url_for('api_ns.api_drop_git_alias',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace) }}" class="add-alias-form hidden blank-field" method="post">

+         <div class="row">

+           <div class="col-sm-5" >

+             <input type="text" name="alias_from" value="" class="form-control"/>

+           </div>

+           <div class="col-sm-5" >

+             <input type="text" name="alias_to" value="" class="form-control"/>

+           </div>

+ 

+           <div class="col-sm-1">

+             <a class="btn btn-outline-info create-field-row pointer create-alias"

+                 title="Create this alias"><i class="fa fa-check"></i></a>

+           </div>

+           <div class="col-sm-1">

+             <a class="btn btn-outline-danger remove-settings-field-row pointer drop-alias"

+                 title="Delete this alias"><i class="fa fa-trash"></i></a>

+           </div>

+         </div>

+       </form>

+       {% for alias in branch_aliases %}

+         <form action="{{ url_for('api_ns.api_drop_git_alias',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace) }}" class="add-alias-form" method="post">

+           <div class="row">

+             <div class="col-sm-5" >

+               <input type="text" name="alias_from" value="{{ alias | replace('refs/heads/', '') }}"

+                 class="form-control" readonly />

+             </div>

+             <div class="col-sm-5" >

+               <input type="text" name="alias_to" value="{{ branch_aliases[alias] | replace('refs/heads/', '') }}"

+                 class="form-control" readonly />

+             </div>

+ 

+             <div class="col-sm-1">

+             </div>

+             <div class="col-sm-1">

+               <a class="btn btn-outline-danger remove-settings-field-row pointer drop-alias"

+                 title="Delete this alias"><i class="fa fa-trash"></i></a>

+             </div>

+           </div>

+         </form>

+       {% endfor %}

+     </div>

+     <a class="btn btn-secondary pt-2 btn-sm btn-block add-alias" data-target="#git-alias-list">

+       <i class="fa fa-plus"></i> Add new alias

+     </a>

+   </div>

+ </div>

+ 

+ <script type="text/javascript" nonce="{{ g.nonce }}" src="{{

+       url_for('static', filename='vendor/jquery/jquery.min.js') }}?version={{ g.version}}"></script>

+ 

+ <script type="text/javascript" nonce="{{ g.nonce }}">

+ 

+ function set_up_drop_btn() {

+   $('.drop-alias').click(function(e) {

+     _form = $(this).closest('.add-alias-form');

+     data = $(_form).serializeArray();

+     output = {}

+     for (d = 0; d < data.length; d++ ) {

+       output[data[d]["name"]] = data[d]["value"];

+     }

+ 

+     $.ajax({

+         url: _form.prop('action') ,

+         type: 'POST',

+         contentType: 'application/json; charset=utf-8',

+         data: JSON.stringify(output),

+         dataType: 'json',

+         success: function(res) {

+           _form.hide()

+ 

+           var _html = '<div class="container pt-2">'

+             + '  <div class="alert alert-info border border-secondary bg-white alert-dismissible" role="alert">'

+             + '      <button type="button" class="close" data-dismiss="alert" aria-label="Close">'

+             + '      <span aria-hidden="true">×</span>'

+             + '      <span class="sr-only">Close</span>'

+             + '    </button>'

+             + '    <div class="text-info font-weight-bold">'

+             + '      <i class="fa fa-fw fa-info-circle"></i>Alias deleted'

+             + '    </div>'

+             + '  </div>'

+             + '</div>';

+           $('.bodycontent').prepend(_html)

+         },

+         error: function(res) {

+           console.log(res);

+           alert('Request failed: ' + res.responseJSON["error"]);

+         }

+     });

+     return false;

+   });

+ };

+ set_up_drop_btn();

+ 

+ 

+ function set_up_create_btn() {

+   $('.create-alias').click(function(e) {

+     _form = $(this).closest('.add-alias-form');

+     data = $(_form).serializeArray();

+     output = {}

+     for (d = 0; d < data.length; d++ ) {

+       output[data[d]["name"]] = data[d]["value"];

+     }

+ 

+     $.ajax({

+         url: "{{ url_for('api_ns.api_new_git_alias',

+             repo=repo.name,

+             username=username,

+             namespace=repo.namespace) }}",

+         type: 'POST',

+         contentType: 'application/json; charset=utf-8',

+         data: JSON.stringify(output),

+         dataType: 'json',

+         success: function(res) {

+           _form.find(".create-alias").hide()

+           _form.find("input").prop("readonly", true);

+ 

+           var _html = '<div class="container pt-2">'

+             + '  <div class="alert alert-info border border-secondary bg-white alert-dismissible" role="alert">'

+             + '      <button type="button" class="close" data-dismiss="alert" aria-label="Close">'

+             + '      <span aria-hidden="true">×</span>'

+             + '      <span class="sr-only">Close</span>'

+             + '    </button>'

+             + '    <div class="text-info font-weight-bold">'

+             + '      <i class="fa fa-fw fa-info-circle"></i>Alias created'

+             + '    </div>'

+             + '  </div>'

+             + '</div>';

+           $('.bodycontent').prepend(_html)

+ 

+         },

+         error: function(res) {

+           console.log(res);

+           alert('Request failed: ' + res.responseJSON["error"]);

+         }

+     });

+     return false;

+   });

+ };

+ 

+ $('.add-alias').click(function(e) {

+   let target = $(this).attr("data-target");

+   let row = $(target + ".settings-field-rows .blank-field").clone();

+   row.removeClass("hidden");

+   row.removeClass("blank-field");

+   $(target + ".settings-field-rows").append(row);

+   set_up_drop_btn();

+   set_up_create_btn();

+ });

+ 

+ </script>

file modified
+3
@@ -1292,6 +1292,8 @@ 

      )

      tags = pagure.lib.query.get_tags_of_project(flask.g.session, repo)

  

+     branch_aliases = pagure.lib.git.get_branch_aliases(repo)

+ 

      form = pagure.forms.ConfirmationForm()

      tag_form = pagure.forms.AddIssueTagForm()

  
@@ -1357,6 +1359,7 @@ 

          plugins=plugins,

          branchname=branchname,

          pagure_admin=pagure.utils.is_admin(),

+         branch_aliases=branch_aliases,

      )

  

  

@@ -2296,7 +2296,9 @@ 

                  "commit",

                  "commit_flag",

                  "create_branch",

+                 "create_git_alias",

                  "create_project",

+                 "delete_git_alias",

                  "fork_project",

                  "generate_acls_project",

                  "internal_access",
@@ -2308,6 +2310,7 @@ 

                  "issue_update",

                  "issue_update_custom_fields",

                  "issue_update_milestone",

+                 "modify_git_alias",

                  "modify_project",

                  "pull_request_assign",

                  "pull_request_close",
@@ -2344,7 +2347,9 @@ 

                  "commit",

                  "commit_flag",

                  "create_branch",

+                 "create_git_alias",

                  "create_project",

+                 "delete_git_alias",

                  "dummy_acls",

                  "fork_project",

                  "generate_acls_project",
@@ -2357,6 +2362,7 @@ 

                  "issue_update",

                  "issue_update_custom_fields",

                  "issue_update_milestone",

+                 "modify_git_alias",

                  "modify_project",

                  "pull_request_assign",

                  "pull_request_close",

@@ -0,0 +1,288 @@ 

+ # -*- coding: utf-8 -*-

+ 

+ """

+  (c) 2020 - Copyright Red Hat Inc

+ 

+  Authors:

+    Pierre-Yves Chibon <pingou@pingoured.fr>

+ 

+ """

+ 

+ from __future__ import unicode_literals, absolute_import

+ 

+ import unittest

+ import shutil

+ import sys

+ import os

+ 

+ import json

+ import pygit2

+ from mock import patch, MagicMock

+ 

+ sys.path.insert(

+     0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")

+ )

+ 

+ import pagure.api

+ import pagure.flask_app

+ import pagure.lib.query

+ import tests

+ 

+ 

+ def set_projects_up(self):

+     tests.create_projects(self.session)

+     tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)

+     tests.add_content_git_repo(os.path.join(self.path, "repos", "test.git"))

+     tests.create_tokens(self.session)

+     tests.create_tokens_acl(self.session)

+ 

+     self.session.commit()

+ 

+ 

+ def set_up_board(self):

+     headers = {

+         "Authorization": "token aaabbbcccddd",

+         "Content-Type": "application/json",

+     }

+ 

+     data = json.dumps({"dev": {"active": True, "tag": "dev"}})

+     output = self.app.post("/api/0/test/boards", headers=headers, data=data)

+     self.assertEqual(output.status_code, 200)

+     data = json.loads(output.get_data(as_text=True))

+     self.assertDictEqual(

+         data,

+         {

+             "boards": [

+                 {

+                     "active": True,

+                     "full_url": "http://localhost.localdomain/test/boards/dev",

+                     "name": "dev",

+                     "status": [],

+                     "tag": {

+                         "tag": "dev",

+                         "tag_color": "DeepBlueSky",

+                         "tag_description": "",

+                     },

+                 }

+             ]

+         },

+     )

+ 

+ 

+ class PagureFlaskApiProjectGitAliastests(tests.SimplePagureTest):

+     """ Tests for flask API for branch alias in pagure """

+ 

+     maxDiff = None

+ 

+     def setUp(self):

+         super(PagureFlaskApiProjectGitAliastests, self).setUp()

+ 

+         set_projects_up(self)

+         self.repo_obj = pygit2.Repository(

+             os.path.join(self.path, "repos", "test.git")

+         )

+ 

+     def test_api_git_alias_view_no_project(self):

+         output = self.app.get("/api/0/invalid/git/alias")

+         self.assertEqual(output.status_code, 404)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data, {"error": "Project not found", "error_code": "ENOPROJECT"}

+         )

+ 

+     def test_api_git_alias_view_empty(self):

+         output = self.app.get("/api/0/test/git/alias")

+         self.assertEqual(output.status_code, 200)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(data, {})

+ 

+     def test_api_new_git_alias_no_data(self):

+         data = "{}"

+         headers = {

+             "Authorization": "token aaabbbcccddd",

+             "Content-Type": "application/json",

+         }

+         output = self.app.post(

+             "/api/0/test/git/alias/new", headers=headers, data=data

+         )

+ 

+         self.assertEqual(output.status_code, 400)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data,

+             {

+                 "error": "Invalid or incomplete input submitted",

+                 "error_code": "EINVALIDREQ",

+             },

+         )

+ 

+     def test_api_new_git_alias_invalid_data(self):

+         data = json.dumps({"dev": "foobar"})

+         headers = {

+             "Authorization": "token aaabbbcccddd",

+             "Content-Type": "application/json",

+         }

+         output = self.app.post(

+             "/api/0/test/git/alias/new", headers=headers, data=data

+         )

+ 

+         self.assertEqual(output.status_code, 400)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data,

+             {

+                 "error": "Invalid or incomplete input submitted",

+                 "error_code": "EINVALIDREQ",

+             },

+         )

+ 

+     def test_api_new_git_alias_missing_data(self):

+         data = json.dumps({"alias_from": "mster"})

+         headers = {

+             "Authorization": "token aaabbbcccddd",

+             "Content-Type": "application/json",

+         }

+         output = self.app.post(

+             "/api/0/test/git/alias/new", headers=headers, data=data

+         )

+ 

+         self.assertEqual(output.status_code, 400)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data,

+             {

+                 "error": "Invalid or incomplete input submitted",

+                 "error_code": "EINVALIDREQ",

+             },

+         )

+ 

+     def test_api_new_git_alias_no_existant_branch(self):

+         data = json.dumps({"alias_from": "master", "alias_to": "main"})

+         headers = {

+             "Authorization": "token aaabbbcccddd",

+             "Content-Type": "application/json",

+         }

+         output = self.app.post(

+             "/api/0/test/git/alias/new", headers=headers, data=data

+         )

+ 

+         self.assertEqual(output.status_code, 400)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data,

+             {

+                 "error": "Branch not found in this git repository",

+                 "error_code": "EBRANCHNOTFOUND",

+             },

+         )

+ 

+     def test_api_new_git_alias(self):

+         data = json.dumps({"alias_from": "main", "alias_to": "master"})

+         headers = {

+             "Authorization": "token aaabbbcccddd",

+             "Content-Type": "application/json",

+         }

+         output = self.app.post(

+             "/api/0/test/git/alias/new", headers=headers, data=data

+         )

+ 

+         self.assertEqual(output.status_code, 200)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(data, {"refs/heads/main": "refs/heads/master"})

+ 

+     def test_api_drop_git_alias_no_data(self):

+         data = "{}"

+         headers = {

+             "Authorization": "token aaabbbcccddd",

+             "Content-Type": "application/json",

+         }

+         output = self.app.post(

+             "/api/0/test/git/alias/drop", headers=headers, data=data

+         )

+ 

+         self.assertEqual(output.status_code, 400)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data,

+             {

+                 "error": "Invalid or incomplete input submitted",

+                 "error_code": "EINVALIDREQ",

+             },

+         )

+ 

+     def test_api_drop_git_alias_invalid_data(self):

+         data = json.dumps({"dev": "foobar"})

+         headers = {

+             "Authorization": "token aaabbbcccddd",

+             "Content-Type": "application/json",

+         }

+         output = self.app.post(

+             "/api/0/test/git/alias/drop", headers=headers, data=data

+         )

+ 

+         self.assertEqual(output.status_code, 400)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data,

+             {

+                 "error": "Invalid or incomplete input submitted",

+                 "error_code": "EINVALIDREQ",

+             },

+         )

+ 

+     def test_api_drop_git_alias_missing_data(self):

+         data = json.dumps({"alias_from": "mster"})

+         headers = {

+             "Authorization": "token aaabbbcccddd",

+             "Content-Type": "application/json",

+         }

+         output = self.app.post(

+             "/api/0/test/git/alias/drop", headers=headers, data=data

+         )

+ 

+         self.assertEqual(output.status_code, 400)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data,

+             {

+                 "error": "Invalid or incomplete input submitted",

+                 "error_code": "EINVALIDREQ",

+             },

+         )

+ 

+     def test_api_drop_git_alias_no_existant_branch(self):

+         data = json.dumps({"alias_from": "master", "alias_to": "main"})

+         headers = {

+             "Authorization": "token aaabbbcccddd",

+             "Content-Type": "application/json",

+         }

+         output = self.app.post(

+             "/api/0/test/git/alias/drop", headers=headers, data=data

+         )

+ 

+         self.assertEqual(output.status_code, 400)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data,

+             {

+                 "error": "Branch not found in this git repository",

+                 "error_code": "EBRANCHNOTFOUND",

+             },

+         )

+ 

+     def test_api_drop_git_alias(self):

+         data = json.dumps({"alias_from": "main", "alias_to": "master"})

+         headers = {

+             "Authorization": "token aaabbbcccddd",

+             "Content-Type": "application/json",

+         }

+         output = self.app.post(

+             "/api/0/test/git/alias/drop", headers=headers, data=data

+         )

+         self.assertEqual(output.status_code, 200)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(data, {})

+ 

+ 

+ if __name__ == "__main__":

+     unittest.main(verbosity=2)

@@ -5667,7 +5667,9 @@ 

                  "commit",

                  "commit_flag",

                  "create_branch",

+                 "create_git_alias",

                  "create_project",

+                 "delete_git_alias",

                  "fork_project",

                  "generate_acls_project",

                  "internal_access",
@@ -5679,6 +5681,7 @@ 

                  "issue_update",

                  "issue_update_custom_fields",

                  "issue_update_milestone",

+                 "modify_git_alias",

                  "modify_project",

                  "pull_request_assign",

                  "pull_request_close",

Let's call this Git branch aliases, since we're restricting to branches.

2 new commits added

  • Add support for git branch aliases
  • Make get_request_data take into account the content-type header
3 years ago

2 new commits added

  • Add support for git branch aliases
  • Make get_request_data take into account the content-type header
3 years ago

2 new commits added

  • Add support for git branch aliases
  • Make get_request_data take into account the content-type header
3 years ago

Pull-Request has been merged by pingou

3 years ago