Initial attempt to support cloning of repositories when creating
authorMagnus Hagander <magnus@hagander.net>
Thu, 12 Feb 2009 14:27:24 +0000 (15:27 +0100)
committerMagnus Hagander <magnus@hagander.net>
Thu, 12 Feb 2009 14:27:24 +0000 (15:27 +0100)
a new one. Not tested at all yet.

gitadmin/adm/forms.py
gitadmin/adm/models.py
gitadmin/adm/templates/base.html
gitadmin/adm/templates/repoview.html
gitadmin/adm/views.py
gitdump.py

index 386d0fcb211949db11618fb2e912ec9311a25995..3f1c9ba2bb1a96756c60605205651878936e07c5 100644 (file)
@@ -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='<a href="javascript:popupRepoList()">Select repository</a>')
+               help_text='Input a valid local repository name or git:// URL')
+
        class Meta:
                model = Repository
                exclude = ('repoid','name', )
index 6185d9c86c1733f428ee176de80be42ff6cacf32..965ff3d377fc3703bf3352fa2ce293366d53824a 100644 (file)
@@ -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:
index b668b4ce63f748e865b6a98ec3d79c6bb5e2303a..195758c4bfcb013cb48aa703a85645e54c70cbdb 100644 (file)
@@ -6,6 +6,7 @@
   <meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8" />
   <link rel="shortcut icon" href="/favicon.ico" />
   <style type="text/css" media="screen" title="Normal Text">@import url("/static/pggit.css");</style>
+  <script language="javascript" src="/static/pggit.js"></script>
  </head>
  <body>
   <div id="pggitWrap">
index 02753e0bc5ffc43e39cb6870d630d7bc386c00cb..31a4fc3aff9cee49659883bc6a539152fb571148 100644 (file)
@@ -5,11 +5,15 @@
 {% if not repo.approved %}
 <p><strong>This repository has not yet been approved.</strong> 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.</p>
+when the repository is approved. Until approval you can also set it up to clone another repository
+automatically upon creation.</p>
 {%endif%}
 {% if form_saved_at %}
 <p>Your changes were successfully saved at {{form_saved_at|date:"Y-m-d H:i:s"}}.</p>
 {%endif%}
+{% if form.errors %}
+<p><b>Error:</b> The submitted form contains errors and could not be saved.</p>
+{%endif%}
 <form method="POST" action=".">
 <table class="leftalign">
 {{form}}
index 52d312fa5bacc863963bd3b1ba3f470eab928532..7a6dafc3eb845bebbcba16c4fc120e7d5f7656a5 100644 (file)
@@ -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()
index 6f21ae12d370f91ed8c2555dfb9b415658c52662..34d4301d51116fe50b118a79c1c20e3ba3887618 100644 (file)
@@ -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