2 Initialize a user account for use with gitosis.
10 from pkg_resources import resource_filename
11 from cStringIO import StringIO
12 from ConfigParser import RawConfigParser
14 from gitosis import repository
15 from gitosis import run_hook
16 from gitosis import ssh
17 from gitosis import util
18 from gitosis import app
20 log = logging.getLogger('gitosis.init')
22 def read_ssh_pubkey(fp=None):
28 class InsecureSSHKeyUsername(Exception):
29 """Username contains not allowed characters"""
32 return '%s: %s' % (self.__doc__, ': '.join(self.args))
34 def ssh_extract_user(pubkey):
35 _, user = pubkey.rsplit(None, 1)
36 if ssh.isSafeUsername(user):
39 raise InsecureSSHKeyUsername(repr(user))
41 def initial_commit(git_dir, cfg, pubkey, user):
42 repository.fast_import(
44 commit_msg='Automatic creation of gitosis repository.',
45 committer='Gitosis Admin <%s>' % user,
47 ('keydir/%s.pub' % user, pubkey),
48 ('gitosis.conf', cfg),
52 def symlink_config(git_dir):
53 dst = os.path.expanduser('~/.gitosis.conf')
54 tmp = '%s.%d.tmp' % (dst, os.getpid())
58 if e.errno == errno.ENOENT:
63 os.path.join(git_dir, 'gitosis.conf'),
68 def init_admin_repository(
75 template=resource_filename('gitosis.templates', 'admin')
80 if not repository.has_initial_commit(git_dir):
81 log.info('Making initial commit...')
82 # ConfigParser does not guarantee order, so jump through hoops
83 # to make sure [gitosis] is first
85 print >>cfg_file, '[gitosis]'
87 cfg = RawConfigParser()
88 cfg.add_section('group gitosis-admin')
89 cfg.set('group gitosis-admin', 'members', user)
90 cfg.set('group gitosis-admin', 'writable', 'gitosis-admin')
94 cfg=cfg_file.getvalue(),
100 def create_parser(self):
101 parser = super(Main, self).create_parser()
102 parser.set_usage('%prog [OPTS]')
103 parser.set_description(
104 'Initialize a user account for use with gitosis')
107 def read_config(self, *a, **kw):
108 # ignore errors that result from non-existent config file
110 super(Main, self).read_config(*a, **kw)
111 except app.ConfigFileDoesNotExistError:
114 def handle_args(self, parser, cfg, options, args):
115 super(Main, self).handle_args(parser, cfg, options, args)
119 log.info('Reading SSH public key...')
120 pubkey = read_ssh_pubkey()
121 user = ssh_extract_user(pubkey)
123 log.error('Cannot parse user from SSH public key.')
125 log.info('Admin user is %r', user)
126 log.info('Creating generated files directory...')
127 generated = util.getGeneratedFilesDir(config=cfg)
128 util.mkdir(generated)
129 log.info('Creating repository structure...')
130 repositories = util.getRepositoryDir(cfg)
131 util.mkdir(repositories)
132 admin_repository = os.path.join(repositories, 'gitosis-admin.git')
133 init_admin_repository(
134 git_dir=admin_repository,
138 log.info('Running post-update hook...')
139 util.mkdir(os.path.expanduser('~/.ssh'), 0700)
140 run_hook.post_update(cfg=cfg, git_dir=admin_repository)
141 log.info('Symlinking ~/.gitosis.conf to repository...')
142 symlink_config(git_dir=admin_repository)