#!/usr/bin/python # -*- mode: python; coding: utf-8 -*- # Copyright © 2008 Jeffrey C. Ollie # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see # . """Make convenience symlinks for public git repositories. This will make urls to get repositories on fedorapeople.org more convenient: git://fedorapeople.org/git/$user/$repo.git instead of: git://fedorapeople.org/home/fedora/$user/public_git/$repo.git For safety this should be run as a non-root user. """ import os import pwd import sys import genshi.template class Repo: pass if os.getuid() == 0: sys.stderr.write('Do not run this as root!') sys.exit(1) symlink_dir = '/git' existing_symlinks = {} blocked_symlinks = set() for filename in os.listdir(symlink_dir): dst = os.path.join(symlink_dir, filename) if not os.path.islink(dst): print "oops: %s is not a symlink" % dst blocked_symlinks.add(dst) else: existing_symlinks[dst] = os.readlink(dst) unneeded_symlinks = existing_symlinks.copy() needed_symlinks = {} git_users = [] for (username, uid, gid, passwd, gecos, homedir, shell) in pwd.getpwall(): if uid < 100000: continue src = os.path.join(homedir, 'public_git') if not os.path.exists(src): continue git_users.append((username, gecos, src)) dst = os.path.join(symlink_dir, username) needed_symlinks[dst] = src try: del unneeded_symlinks[dst] except KeyError: pass for dst, src in needed_symlinks.iteritems(): if dst in blocked_symlinks: sys.stderr.write("oops: %s is blocked!\n" % dst) continue if dst in existing_symlinks: # make sure that symlink points to right place if src != existing_symlinks[dst]: sys.stderr.write("updating symlink %s: %s -> %s\n" % (dst, existing_symlinks[dst], src)) os.unlink(dst) os.symlink(src, dst) else: # create symlinks that don't already exist sys.stderr.write("new symlink: %s -> %s\n" % (dst, src)) os.symlink(src, dst) # get rid of any symlinks we no longer need for dst, src in unneeded_symlinks.iteritems(): sys.stdout.write("deleting symlink %s -> %s\n" % (dst, src)) os.unlink(dst) git_users.sort(lambda a, b: cmp(a[0], b[0])) repos = [] for username, gecos, src in git_users: gecos = gecos.decode('utf-8', 'replace') username = username.decode('utf-8', 'replace') group_repos = [] filenames = os.listdir(src) filenames.sort() for filename in filenames: if not filename.endswith('.git'): continue path = os.path.join(src, filename) if not os.path.isdir(path): continue repo = Repo() repo.url = u'%s/%s' % (username, filename.decode('utf-8', 'replace')) repo.path = path repo.owner = gecos try: repo.desc = file(os.path.join(path, 'description')).readline().decode('utf-8', 'replace').strip() if repo.desc == '' or repo.desc == u'Unnamed repository; edit this file to name it for gitweb.': repo.desc = None except IOError: repo.desc = None group_repos.append(repo) repos.append((gecos, group_repos)) loader = genshi.template.TemplateLoader(search_path = ['.'], default_class = genshi.template.NewTextTemplate) template = loader.load('cgitrc.txt') stream = template.generate(repos = repos) file('cgitrc', 'wb').write(stream.render())