From: Magnus Hagander Date: Thu, 12 Feb 2009 14:27:24 +0000 (+0100) Subject: Initial attempt to support cloning of repositories when creating X-Git-Url: http://git.postgresql.org/gitweb/static/%7B%7Bpgdulink%28?a=commitdiff_plain;h=96ead414507cede0e7a60c6f6d90132e78c6d373;p=pggit.git Initial attempt to support cloning of repositories when creating a new one. Not tested at all yet. --- diff --git a/gitadmin/adm/forms.py b/gitadmin/adm/forms.py index 386d0fc..3f1c9ba 100644 --- a/gitadmin/adm/forms.py +++ b/gitadmin/adm/forms.py @@ -5,6 +5,11 @@ from django.db import models from gitadmin.adm.models import Repository class RepositoryForm(ModelForm): + initialclone = forms.RegexField(r'^(git://.+/.+|[^:]+)$',max_length=256,required=False, + label="Initial clone", +# help_text='Select repository') + help_text='Input a valid local repository name or git:// URL') + class Meta: model = Repository exclude = ('repoid','name', ) diff --git a/gitadmin/adm/models.py b/gitadmin/adm/models.py index 6185d9c..965ff3d 100644 --- a/gitadmin/adm/models.py +++ b/gitadmin/adm/models.py @@ -13,6 +13,7 @@ class Repository(models.Model): anonymous = models.BooleanField(blank=False,verbose_name='Enable anonymous access') web = models.BooleanField(blank=False,verbose_name='Enable gitweb access') approved = models.BooleanField(blank=False) + initialclone = models.TextField(max_length=256, blank=False, null=True) def ValidateOwnerPermissions(self, user): if user.is_superuser: diff --git a/gitadmin/adm/templates/base.html b/gitadmin/adm/templates/base.html index b668b4c..195758c 100644 --- a/gitadmin/adm/templates/base.html +++ b/gitadmin/adm/templates/base.html @@ -6,6 +6,7 @@ +
diff --git a/gitadmin/adm/templates/repoview.html b/gitadmin/adm/templates/repoview.html index 02753e0..31a4fc3 100644 --- a/gitadmin/adm/templates/repoview.html +++ b/gitadmin/adm/templates/repoview.html @@ -5,11 +5,15 @@ {% if not repo.approved %}

This repository has not yet been approved. This means you cannot access it through git or web yet. You can still update the description and set permissions - they will all start working automatically -when the repository is approved.

+when the repository is approved. Until approval you can also set it up to clone another repository +automatically upon creation.

{%endif%} {% if form_saved_at %}

Your changes were successfully saved at {{form_saved_at|date:"Y-m-d H:i:s"}}.

{%endif%} +{% if form.errors %} +

Error: The submitted form contains errors and could not be saved.

+{%endif%}
{{form}} diff --git a/gitadmin/adm/views.py b/gitadmin/adm/views.py index 52d312f..7a6dafc 100644 --- a/gitadmin/adm/views.py +++ b/gitadmin/adm/views.py @@ -1,3 +1,4 @@ +# vim: ai ts=4 sts=4 sw=4 import re from django.http import HttpResponse, HttpResponseRedirect @@ -12,6 +13,10 @@ import datetime from gitadmin.adm.models import * from gitadmin.adm.forms import * +# Utility classes +class FormIsNotValid(Exception): + pass + # Utility functions def _MissingSshkey(user): @@ -53,6 +58,7 @@ def editrepo(request, repoid): repo = get_object_or_404(Repository, repoid=repoid) repo.ValidateOwnerPermissions(request.user) savedat = None + form = None formfactory = inlineformset_factory(Repository, RepositoryPermission, extra=1) @@ -61,17 +67,41 @@ def editrepo(request, repoid): formset = formfactory(data=request.POST, instance=repo) if not request.user.is_superuser: del form.fields['approved'] + if repo.approved: + del form.fields['initialclone'] if form.is_valid() and formset.is_valid(): - form.save() - formset.save() - savedat = datetime.datetime.now() - # Get a new copy of the repository to make sure it refreshes! - repo = get_object_or_404(Repository, repoid=repoid) - - form = RepositoryForm(instance=repo) - if not request.user.is_superuser: - del form.fields['approved'] + try: + # Manually validate the repository entered if there is one to clone + if form.cleaned_data['initialclone']: + if form.cleaned_data['initialclone'].startswith('git://'): + # Validate hostnames and stuff? + pass + else: + # Assume local + try: + r = Repository.objects.get(name=form.cleaned_data['initialclone']) + except Repository.DoesNotExist: + form._errors['initialclone'] = form._errors.get('initialclone', []) + form._errors['initialclone'].append('Specified repository does not exist') + raise FormIsNotValid() + + form.save() + formset.save() + savedat = datetime.datetime.now() + # Get a new copy of the repository to make sure it refreshes! + repo = get_object_or_404(Repository, repoid=repoid) + except FormIsNotValid: + # Just continue as if the form wasn't valid, expect the caller + # to have set the required error fields + pass + + if not form or not form.errors: + form = RepositoryForm(instance=repo) + if not request.user.is_superuser: + del form.fields['approved'] + if repo.approved: + del form.fields['initialclone'] formset = formfactory(instance=repo) perm = repo.repositorypermission_set.all() diff --git a/gitdump.py b/gitdump.py index 6f21ae1..34d4301 100644 --- a/gitdump.py +++ b/gitdump.py @@ -40,15 +40,30 @@ class AuthorizedKeysDumper(object): def dumprepos(self): # FIXME: use a trigger to indicate if *anything at all* has changed curs = self.db.cursor() - curs.execute("SELECT name,anonymous,web,description,(SELECT min(first_name) FROM repository_permissions AS rp LEFT JOIN auth_user AS au ON au.username=rp.userid WHERE rp.level=2 AND rp.repository=r.repoid) FROM repositories AS r WHERE approved ORDER BY name") + curs.execute("SELECT name,anonymous,web,description,initialclone,(SELECT min(first_name) FROM repository_permissions AS rp LEFT JOIN auth_user AS au ON au.username=rp.userid WHERE rp.level=2 AND rp.repository=r.repoid) FROM repositories AS r WHERE approved ORDER BY name") f = open("%s.tmp" % self.conf.get("paths", "gitweblist"), "w") - for name, anon, web, description, owner in curs: + for name, anon, web, description, initialclone, owner in curs: # Check if this repository exists at all if not os.path.isdir("%s/repos/%s" % (self.conf.get("paths", "githome"), name)): # Does not exist, let's initialize a new one - print "Initializing new git repository %s" % name os.environ['GIT_DIR'] = "%s/repos/%s"% (self.conf.get("paths", "githome"), name) - os.system("git init --bare --shared") + if initialclone: + print "Initializing git into %s (cloned repo %s)" % (name, initialclone) + if initialclone.startswith('git://'): + # Just use the raw URL, expect approver to have validated it + oldrepo = initialclone + else: + # This is a local reference, so rewrite it based on our root + oldrepo = "%s/repos/%s" % (self.conf.get("paths", "githome"), initialclone) + os.system("git clone --bare %s %s/repos/%s" % ( + # Old repo + oldrepo, + # New repo + self.conf.get("paths", "githome"), name, + )) + else: + print "Initializing new git repository %s" % name + os.system("git init --bare --shared") del os.environ['GIT_DIR'] # Check for publishing options here