Skip to content

Commit

Permalink
Add support for renaming plugin name (#302)
Browse files Browse the repository at this point in the history
* Plugin rename management

* Fix lint error for rename plugin

* Add test for plugin renaming

* Allow uploading new version without changing name
  • Loading branch information
Xpirix authored Nov 20, 2023
1 parent c625132 commit 694b2e1
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 3 deletions.
5 changes: 3 additions & 2 deletions qgis-app/plugins/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,16 @@ def clean(self):
self.cleaned_data.get("version")
)
self.instance.server = self.cleaned_data.get("server")
# Check plugin name

# Check plugin folder name
if (
self.cleaned_data.get("package_name")
and self.cleaned_data.get("package_name")
!= self.instance.plugin.package_name
):
raise ValidationError(
_(
"Plugin name mismatch: the plugin main folder name in the compressed file (%s) is different from the original plugin package name (%s)."
"Plugin folder name mismatch: the plugin main folder name in the compressed file (%s) is different from the original plugin package name (%s)."
)
% (
self.cleaned_data.get("package_name"),
Expand Down
18 changes: 18 additions & 0 deletions qgis-app/plugins/migrations/0003_plugin_allow_update_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.25 on 2023-11-07 03:04

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('plugins', '0002_pluginversiondownload'),
]

operations = [
migrations.AddField(
model_name='plugin',
name='allow_update_name',
field=models.BooleanField(default=False, help_text='Allow name in metadata.txt to update the plugin name', verbose_name='Allow update name'),
),
]
7 changes: 7 additions & 0 deletions qgis-app/plugins/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,13 @@ class Plugin(models.Model):
name = models.CharField(
_("Name"), help_text=_("Must be unique"), max_length=256, unique=True
)

allow_update_name = models.BooleanField(
_("Allow update name"),
help_text=_("Allow name in metadata.txt to update the plugin name"),
default=False
)

description = models.TextField(_("Description"))
about = models.TextField(_("About"), blank=False, null=True)

Expand Down
111 changes: 111 additions & 0 deletions qgis-app/plugins/tests/test_rename_plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import os
from unittest.mock import patch

from django.urls import reverse
from django.test import Client, TestCase, override_settings
from django.contrib.auth.models import User
from django.core.files.uploadedfile import SimpleUploadedFile
from plugins.models import Plugin, PluginVersion
from plugins.forms import PluginVersionForm

def do_nothing(*args, **kwargs):
pass

TESTFILE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "testfiles"))

class PluginRenameTestCase(TestCase):
fixtures = [
"fixtures/styles.json",
"fixtures/auth.json",
"fixtures/simplemenu.json",
]

@override_settings(MEDIA_ROOT="api/tests")
def setUp(self):
self.client = Client()
self.url_upload = reverse('plugin_upload')

# Create a test user
self.user = User.objects.create_user(
username='testuser',
password='testpassword',
email='[email protected]'
)

# Log in the test user
self.client.login(username='testuser', password='testpassword')

# Upload a plugin for renaming test.
# This process is already tested in test_plugin_upload
valid_plugin = os.path.join(TESTFILE_DIR, "valid_plugin.zip_")
with open(valid_plugin, "rb") as file:
uploaded_file = SimpleUploadedFile(
"valid_plugin.zip_", file.read(),
content_type="application/zip")

self.client.post(self.url_upload, {
'package': uploaded_file,
})

self.plugin = Plugin.objects.get(name='Test Plugin')
self.plugin.name = "New name Test Plugin"
self.plugin.save()

@patch("plugins.tasks.generate_plugins_xml.delay", new=do_nothing)
@patch("plugins.validator._check_url_link", new=do_nothing)
def test_plugin_rename(self):
"""
Test rename from a new plugin version
"""
package_name = self.plugin.package_name
self.url_add_version = reverse('version_create', args=[package_name])
# Test GET request
response = self.client.get(self.url_add_version)
self.assertEqual(response.status_code, 200)
self.assertIsInstance(response.context['form'], PluginVersionForm)

# Test POST request with invalid form data
response = self.client.post(self.url_add_version, {})
self.assertEqual(response.status_code, 200)
self.assertFalse(response.context['form'].is_valid())

# Test POST request without allowing name from metadata
valid_plugin = os.path.join(TESTFILE_DIR, "valid_plugin_0.0.2.zip_")
with open(valid_plugin, "rb") as file:
uploaded_file = SimpleUploadedFile(
"valid_plugin_0.0.2.zip_", file.read(),
content_type="application/zip_")

response = self.client.post(self.url_add_version, {
'package': uploaded_file,
'experimental': False,
'changelog': ''
})
self.assertEqual(response.status_code, 302)
self.assertTrue(PluginVersion.objects.filter(
plugin__name='New name Test Plugin',
version='0.0.2').exists()
)

# Test POST request with allowing name from metadata
self.plugin.allow_update_name = True
self.plugin.save()

valid_plugin = os.path.join(TESTFILE_DIR, "valid_plugin_0.0.3.zip_")
with open(valid_plugin, "rb") as file:
uploaded_file = SimpleUploadedFile(
"valid_plugin_0.0.3.zip_", file.read(),
content_type="application/zip_")
response = self.client.post(self.url_add_version, {
'package': uploaded_file,
'experimental': False,
'changelog': ''
})
self.assertEqual(response.status_code, 302)
self.assertTrue(PluginVersion.objects.filter(
plugin__name='Test Plugin',
version='0.0.3').exists()
)

def tearDown(self):
self.client.logout()
Binary file not shown.
Binary file not shown.
7 changes: 6 additions & 1 deletion qgis-app/plugins/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -879,8 +879,13 @@ def _main_plugin_update(request, plugin, form):
"""
Updates the main plugin object from version metadata
"""
# Check if update name from metadata is allowed
metadata_fields = ["author", "email", "description", "about", "homepage", "tracker"]
if plugin.allow_update_name:
metadata_fields.insert(0, "name")

# Update plugin from metadata
for f in ["name", "author", "email", "description", "about", "homepage", "tracker"]:
for f in metadata_fields:
if form.cleaned_data.get(f):
setattr(plugin, f, form.cleaned_data.get(f))

Expand Down

0 comments on commit 694b2e1

Please sign in to comment.