Kaynağa Gözat

Allow to force the creation of a git tag

Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
Pierre-Yves Chibon 4 yıl önce
ebeveyn
işleme
28bce03ba3

+ 8 - 0
pagure/api/project.py

@@ -396,6 +396,13 @@ def api_new_git_tags(repo, username=None, namespace=None):
     |                 |          |               |   tags found in the repo |
     |                 |          |               |   in the data returned   |
     +-----------------+----------+---------------+--------------------------+
+    | ``force``       | boolean  | Optional      | | If a similar git tag   |
+    |                 |          |               |   already exists, remove |
+    |                 |          |               |   it from the repo and   |
+    |                 |          |               |   create the specified   |
+    |                 |          |               |   one, thus forcing it   |
+    +-----------------+----------+---------------+--------------------------+
+
 
     Sample response
     ^^^^^^^^^^^^^^^
@@ -439,6 +446,7 @@ def api_new_git_tags(repo, username=None, namespace=None):
                 target=form.commit_hash.data,
                 user=user_obj,
                 message=form.message.data,
+                force=form.force.data,
             )
             created = True
         except AlreadyExistsError:

+ 5 - 0
pagure/forms.py

@@ -946,3 +946,8 @@ class AddGitTagForm(PagureForm):
     message = wtforms.TextAreaField(
         "Annotation message", [wtforms.validators.Optional()]
     )
+    force = wtforms.BooleanField(
+        "Force the creation of the git tag",
+        [wtforms.validators.optional()],
+        false_values=FALSE_VALUES,
+    )

+ 9 - 1
pagure/lib/git.py

@@ -2352,7 +2352,7 @@ def get_git_tags(project, with_commits=False):
     return tags
 
 
-def new_git_tag(project, tagname, target, user, message=None):
+def new_git_tag(project, tagname, target, user, message=None, force=False):
     """ Create a new git tag in the git repositorie of the specified project.
 
     :arg project: the project in which we want to create a git tag
@@ -2363,6 +2363,9 @@ def new_git_tag(project, tagname, target, user, message=None):
     :type user: pagure.lib.model.User
     :kwarg message: the message to include in the annotation of the tag
     :type message: str or None
+    :kwarg force: a boolean specifying wether to force the creation of
+        the git tag or not
+    :type message: bool
     """
     repopath = pagure.utils.get_repo_path(project)
     repo_obj = PagureRepo(repopath)
@@ -2371,6 +2374,11 @@ def new_git_tag(project, tagname, target, user, message=None):
     if not target_obj:
         raise pygit2.GitError("Unknown target: %s" % target)
 
+    if force:
+        existing_tag = repo_obj.lookup_reference("refs/tags/%s" % tagname)
+        if existing_tag:
+            existing_tag.delete()
+
     tag = repo_obj.create_tag(
         tagname,
         target,

+ 57 - 0
tests/test_pagure_flask_api_project_git_tags.py

@@ -306,3 +306,60 @@ class PagureFlaskApiProjectGitTagstests(tests.Modeltests):
         self.assertEqual(data["tags"], ["test-tag-no-message"])
         self.assertEqual(data["total_tags"], 1)
         self.assertEqual(data["tag_created"], True)
+
+    def test_api_new_git_tag_forced(self):
+        """ Test the api_new_git_tags function.  """
+
+        # Before
+        output = self.app.get("/api/0/test/git/tags")
+        self.assertEqual(output.status_code, 200)
+        data = json.loads(output.get_data(as_text=True))
+        self.assertEqual(sorted(data.keys()), ["tags", "total_tags"])
+        self.assertEqual(data["tags"], [])
+        self.assertEqual(data["total_tags"], 0)
+
+        # Add a tag so that we can list it
+        repo = pygit2.Repository(os.path.join(self.path, "repos", "test.git"))
+        latest_commit = repo.revparse_single("HEAD")
+        prev_commit = latest_commit.parents[0].oid.hex
+        data = {
+            "tagname": "test-tag-no-message",
+            "commit_hash": prev_commit,
+            "message": "This is a long annotation\nover multiple lines\n for testing",
+            "with_commits": True,
+        }
+
+        output = self.app.post(
+            "/api/0/test/git/tags", headers=self.headers, data=data
+        )
+        self.assertEqual(output.status_code, 200)
+        data = json.loads(output.get_data(as_text=True))
+        self.assertEqual(
+            sorted(data.keys()), ["tag_created", "tags", "total_tags"]
+        )
+        self.assertEqual(data["tags"], {"test-tag-no-message": prev_commit})
+        self.assertEqual(data["total_tags"], 1)
+        self.assertEqual(data["tag_created"], True)
+
+        # Submit the same request/tag a second time to the same commit
+        data = {
+            "tagname": "test-tag-no-message",
+            "commit_hash": latest_commit.oid.hex,
+            "message": "This is a long annotation\nover multiple lines\n for testing",
+            "with_commits": True,
+            "force": True,
+        }
+
+        output = self.app.post(
+            "/api/0/test/git/tags", headers=self.headers, data=data
+        )
+        self.assertEqual(output.status_code, 200)
+        data = json.loads(output.get_data(as_text=True))
+        self.assertEqual(
+            sorted(data.keys()), ["tag_created", "tags", "total_tags"]
+        )
+        self.assertEqual(
+            data["tags"], {"test-tag-no-message": latest_commit.oid.hex}
+        )
+        self.assertEqual(data["total_tags"], 1)
+        self.assertEqual(data["tag_created"], True)