1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Django form for configuring Gitweb.
"""
import re
from urllib.parse import urlparse
from django import forms
from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
from django.utils.translation import gettext_lazy as _
from plinth.modules import gitweb
from . import privileged
def _get_branches(repo):
"""Get all the branches in the repository."""
branch_data = privileged.get_branches(repo)
default_branch = branch_data['default_branch']
branches = branch_data['branches']
if default_branch not in branches:
branches.insert(0, default_branch)
return [(branch, branch) for branch in branches]
def get_name_from_url(url):
"""Get a repository name from URL"""
return urlparse(url).path.split('/')[-1]
def is_repo_url(url):
"""Check if URL is valid."""
try:
RepositoryValidator(input_should_be='url')(url)
except ValidationError:
return False
return True
class RepositoryValidator:
input_should_be = 'name'
def __init__(self, input_should_be=None):
if input_should_be is not None:
self.input_should_be = input_should_be
def __call__(self, value):
"""Validate that the input is a correct repository name or URL"""
if self.input_should_be in ('url', 'url_or_name'):
try:
URLValidator(schemes=['http', 'https'],
message=_('Invalid repository URL.'))(value)
except ValidationError:
if self.input_should_be == 'url':
raise
else:
value = get_name_from_url(value)
if (not re.match(r'^[a-zA-Z0-9-._]+$', value)) \
or value.startswith(('-', '.')) \
or value.endswith('.git.git'):
raise ValidationError(_('Invalid repository name.'), 'invalid')
class CreateRepoForm(forms.Form):
"""Form to create and edit a new repository."""
name = forms.CharField(
label=_(
'Name of a new repository or URL to import an existing repository.'
), strip=True,
validators=[RepositoryValidator(input_should_be='url_or_name')],
widget=forms.TextInput(attrs={'autocomplete': 'off'}))
description = forms.CharField(
label=_('Description of the repository'), strip=True, required=False,
help_text=_('Optional, for displaying on Gitweb.'))
owner = forms.CharField(label=_('Repository\'s owner name'), strip=True,
required=False,
help_text=_('Optional, for displaying on Gitweb.'))
is_private = forms.BooleanField(
label=_('Private repository'), required=False,
help_text=_('Allow only authorized users to access this repository.'))
def __init__(self, *args, **kwargs):
"""Initialize the form with extra request argument."""
super().__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update({'autofocus': 'autofocus'})
def clean_name(self):
"""Check if the name is valid."""
name = self.cleaned_data['name']
repo_name = name
if is_repo_url(name):
repo_name = get_name_from_url(name)
if repo_name.endswith('.git'):
repo_name = repo_name[:-4]
for repo in gitweb.get_repo_list():
if repo_name == repo['name']:
raise ValidationError(
_('A repository with this name already exists.'))
if is_repo_url(name):
if not privileged.repo_exists(name):
raise ValidationError('Remote repository is not available.')
return name
class EditRepoForm(CreateRepoForm):
"""Form to create and edit a new repository."""
name = forms.CharField(
label=_('Name of the repository'),
strip=True,
validators=[RepositoryValidator()],
help_text=_(
'An alpha-numeric string that uniquely identifies a repository.'),
)
default_branch = forms.ChoiceField(
label=_('Default branch'),
help_text=_('Gitweb displays this as a default branch.'))
def __init__(self, *args, **kwargs):
"""Initialize the form with extra request argument."""
super().__init__(*args, **kwargs)
branches = _get_branches(self.initial['name'])
self.fields['default_branch'].choices = branches
def clean_name(self):
"""Check if the name is valid."""
name = self.cleaned_data['name']
if 'name' in self.initial and name == self.initial['name']:
return name
if name.endswith('.git'):
name = name[:-4]
for repo in gitweb.get_repo_list():
if name == repo['name']:
raise ValidationError(
_('A repository with this name already exists.'))
return name
|