From c1c8a17aadc84a3df1acd2e3023263a5248a0f01 Mon Sep 17 00:00:00 2001 From: Magnus Hagander Date: Sat, 1 Aug 2009 17:07:17 +0200 Subject: [PATCH] Add support for subdirectories in repository paths, per request from Peter E. --- gitadmin/adm/views.py | 2 +- gitdump.py | 60 +++++++++++++++++++++++++++++++++---------- reposync.py | 3 +++ 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/gitadmin/adm/views.py b/gitadmin/adm/views.py index 2d2ac0e..29c8c75 100644 --- a/gitadmin/adm/views.py +++ b/gitadmin/adm/views.py @@ -144,7 +144,7 @@ def newrepo(request): if request.method != "POST": raise Exception("Must be posted!") newname = request.POST['reponame'] - r = re.compile(r'^[a-z0-9-_]{5,64}$') + r = re.compile(r'^[a-z0-9-_/]{5,64}$') if not r.match(newname): raise Exception("Format of project name is invalid!") diff --git a/gitdump.py b/gitdump.py index 1af12cf..6f7a3eb 100644 --- a/gitdump.py +++ b/gitdump.py @@ -56,15 +56,24 @@ FROM repositories AS r WHERE approved ORDER BY name""") f = open("%s.tmp" % self.conf.get("paths", "gitweblist"), "w") for name, anon, web, description, initialclone, owner, remoterepo in curs: allrepos[name] = 1 + repopath = "%s/repos/%s.git" % (self.conf.get("paths", "githome"), name) + # If this is a remote repository, don't try to create it if it's not there - # this is handled by the repository importer. - if remoterepo and not os.path.isdir("%s/repos/%s.git" % (self.conf.get("paths", "githome"), name)): + if remoterepo and not os.path.isdir(repopath): continue # Check if this repository exists at all - if not os.path.isdir("%s/repos/%s.git" % (self.conf.get("paths", "githome"), name)): + if not os.path.isdir(repopath): # Does not exist, let's initialize a new one - os.environ['GIT_DIR'] = "%s/repos/%s.git"% (self.conf.get("paths", "githome"), name) + + # Does the parent directory exist? Needed for things like /user/foo/repo.git + parentpath = os.path.normpath(os.path.join(repopath, os.pardir)) + if not os.path.isdir(parentpath): + # Parent does not exist, create it + os.makedirs(parentpath) + + os.environ['GIT_DIR'] = repopath if initialclone: print "Initializing git into %s (cloned repo %s)" % (name, initialclone) if initialclone.startswith('git://'): @@ -87,12 +96,12 @@ FROM repositories AS r WHERE approved ORDER BY name""") # Check for publishing options here if web: f.write("%s.git %s\n" % (urllib.quote_plus(name), urllib.quote_plus(owner))) - df = open("%s/repos/%s.git/description" % (self.conf.get("paths", "githome"), name), "w") + df = open("%s/description" % repopath, "w") df.write(description) df.close() - anonfile = "%s/repos/%s.git/git-daemon-export-ok" % (self.conf.get("paths", "githome"), name) - htafile = "%s/repos/%s.git/.htaccess" % (self.conf.get("paths", "githome"), name) + anonfile = "%s/git-daemon-export-ok" % repopath + htafile = "%s/.htaccess" % repopath if anon: if not os.path.isfile(anonfile): open(anonfile, "w").close() @@ -111,17 +120,40 @@ FROM repositories AS r WHERE approved ORDER BY name""") os.rename("%s.tmp" % self.conf.get("paths", "gitweblist"), self.conf.get("paths", "gitweblist")) # Now remove any repositories that have been deleted - for d in os.listdir("%s/repos/" % self.conf.get("paths", "githome")): + self._removerepos("%s/repos/" % self.conf.get("paths", "githome"), '/', allrepos) + + def _removerepos(self, rootpath, relativepath, allrepos): + dl = os.listdir(rootpath) + if not dl: + # Nothing in there, perhaps we need to remove it? + if relativepath != '/': + print "Removing container directory %s" % rootpath + try: + os.rmdir("%s" % rootpath) + except Exception,e: + print "FAIL: unable to remove container directory: %s" % e + return + + for d in dl: if d.startswith('.'): continue - if d.endswith('.git'): + if not d.endswith('.git'): + # If it doesn't end in '.git', that means it's a repository container + # and not actually a repository. So we have to recurse. + self._removerepos(os.path.join(rootpath, d), + os.path.join(relativepath, d), + allrepos) + else: + # Ends with '.git', meaning it's a repository. Let's figure out if it should + # be here. d = d[:-4] - if not allrepos.has_key(d): - print "Removing repository %s" % d - try: - shutil.rmtree("%s/repos/%s.git" % (self.conf.get("paths", "githome"), d)) - except Exception,e: - print "FAIL: unable to remove directory: %s" % e + if not allrepos.has_key(os.path.join(relativepath, d)[1:]): + print "Removing repository %s" % os.path.join(relativepath, d) + try: + shutil.rmtree("%s.git" % os.path.join(rootpath, d)) + except Exception,e: + print "FAIL: unable to remove directory: %s" % e + if __name__ == "__main__": c = ConfigParser.ConfigParser() diff --git a/reposync.py b/reposync.py index ece98c8..28f38f2 100755 --- a/reposync.py +++ b/reposync.py @@ -30,6 +30,9 @@ INNER JOIN remoterepositories ON repositories.remoterepository_id=remotereposito WHERE approved ORDER BY name """) for id,name,repotype,remoteurl,remotemodule,lastsynced in curs: + if name.find('/')>0: + print "Subdirectories not supported when synchronizing" + continue s = SyncMethod.get(repotype) s.init(self.conf, name,remoteurl,remotemodule) s.sync() -- 2.39.5