Add `gitosis-gitweb
`, for writing gitweb project lists.
Takes the list of repositories to publish from the gitosis config file.
This commit is contained in:
parent
67940f4b28
commit
418c5c3cfc
5 changed files with 223 additions and 1 deletions
5
TODO.rst
5
TODO.rst
|
@ -3,3 +3,8 @@
|
|||
===========
|
||||
|
||||
- guard against *.pub files named -foo.pub or foo;bar.pub
|
||||
|
||||
- gitweb doesn't understand mappings, just visible/no,
|
||||
physical and logical path are always the same
|
||||
|
||||
- maybe remove the whole mapping feature for good?
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
[gitosis]
|
||||
repositories = repo
|
||||
gitweb = no
|
||||
# daemon-ok = no
|
||||
|
||||
[group quux]
|
||||
members = jdoe wsmith @anothergroup
|
||||
|
@ -8,8 +10,10 @@ readonly = xyzzy
|
|||
map writable visiblename1 = actualname1
|
||||
map readonly visiblename2 = actualname2
|
||||
|
||||
# [repo foo]
|
||||
[repo foo]
|
||||
# description = blah blah
|
||||
gitweb = yes
|
||||
owner = John Doe
|
||||
# daemon-ok = no
|
||||
|
||||
# [gitweb]
|
||||
|
|
115
gitosis/gitweb.py
Normal file
115
gitosis/gitweb.py
Normal file
|
@ -0,0 +1,115 @@
|
|||
"""
|
||||
Generate ``gitweb`` project list based on ``gitosis.conf``.
|
||||
|
||||
To plug this into ``gitweb``, you have two choices.
|
||||
|
||||
- The global way, edit ``/etc/gitweb.conf`` to say::
|
||||
|
||||
$projects_list = "/path/to/your/projects.list";
|
||||
|
||||
Note that there can be only one such use of gitweb.
|
||||
|
||||
- The local way, create a new config file::
|
||||
|
||||
do "/etc/gitweb.conf" if -e "/etc/gitweb.conf";
|
||||
$projects_list = "/path/to/your/projects.list";
|
||||
# see ``repositories`` in the ``gitosis`` section
|
||||
# of ``~/.gitosis.conf``; usually ``~/repos``
|
||||
# but you need to expand the tilde here
|
||||
$projectroot = "/path/to/your/repos";
|
||||
|
||||
Then in your web server, set environment variable ``GITWEB_CONFIG``
|
||||
to point to this file.
|
||||
|
||||
This way allows you have multiple separate uses of ``gitweb``, and
|
||||
isolates the changes a bit more nicely. Recommended.
|
||||
"""
|
||||
|
||||
import os, urllib
|
||||
|
||||
from ConfigParser import RawConfigParser, NoSectionError, NoOptionError
|
||||
|
||||
def _escape_filename(s):
|
||||
s = s.replace('\\', '\\\\')
|
||||
s = s.replace('$', '\\$')
|
||||
s = s.replace('"', '\\"')
|
||||
return s
|
||||
|
||||
def generate(config, fp):
|
||||
"""
|
||||
Generate a config file and projects list for ``gitweb``.
|
||||
|
||||
:param config: configuration to read projects from
|
||||
:type config: RawConfigParser
|
||||
|
||||
:param fp: writable for ``projects.list``
|
||||
:type fp: (file-like, anything with ``.write(data)``)
|
||||
"""
|
||||
try:
|
||||
global_enable = config.getboolean('gitosis', 'gitweb')
|
||||
except (NoSectionError, NoOptionError):
|
||||
global_enable = False
|
||||
|
||||
for section in config.sections():
|
||||
l = section.split(None, 1)
|
||||
type_ = l.pop(0)
|
||||
if type_ != 'repo':
|
||||
continue
|
||||
if not l:
|
||||
continue
|
||||
|
||||
try:
|
||||
enable = config.getboolean(section, 'gitweb')
|
||||
except (NoSectionError, NoOptionError):
|
||||
enable = global_enable
|
||||
|
||||
if not enable:
|
||||
continue
|
||||
|
||||
name, = l
|
||||
response = [name]
|
||||
try:
|
||||
owner = config.get(section, 'owner')
|
||||
except (NoSectionError, NoOptionError):
|
||||
pass
|
||||
else:
|
||||
response.append(owner)
|
||||
|
||||
line = ' '.join([urllib.quote_plus(s) for s in response])
|
||||
print >>fp, line
|
||||
|
||||
def _getParser():
|
||||
import optparse
|
||||
parser = optparse.OptionParser(
|
||||
usage="%prog [--config=FILE] PROJECTSLIST")
|
||||
parser.set_defaults(
|
||||
config=os.path.expanduser('~/.gitosis.conf'),
|
||||
)
|
||||
parser.add_option('--config',
|
||||
metavar='FILE',
|
||||
help='read config from FILE (default %s)'
|
||||
% parser.defaults['config'],
|
||||
)
|
||||
return parser
|
||||
|
||||
def main():
|
||||
parser = _getParser()
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if len(args) != 1:
|
||||
parser.error('Expected one command line argument.')
|
||||
|
||||
path, = args
|
||||
|
||||
cfg = RawConfigParser()
|
||||
cfg.read(options.config)
|
||||
|
||||
tmp = '%s.%d.tmp' % (path, os.getpid())
|
||||
|
||||
f = file(tmp, 'w')
|
||||
try:
|
||||
generate(config=cfg, fp=f)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
os.rename(tmp, path)
|
97
gitosis/test/test_gitweb.py
Normal file
97
gitosis/test/test_gitweb.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
from nose.tools import eq_ as eq
|
||||
|
||||
from ConfigParser import RawConfigParser
|
||||
from cStringIO import StringIO
|
||||
|
||||
from gitosis import gitweb
|
||||
|
||||
def test_empty():
|
||||
cfg = RawConfigParser()
|
||||
got = StringIO()
|
||||
gitweb.generate(
|
||||
config=cfg,
|
||||
fp=got)
|
||||
eq(got.getvalue(), '''\
|
||||
''')
|
||||
|
||||
def test_trickyFilenames():
|
||||
cfg = RawConfigParser()
|
||||
got = StringIO()
|
||||
gitweb.generate(
|
||||
config=cfg,
|
||||
fp=got)
|
||||
eq(got.getvalue(), '''\
|
||||
''')
|
||||
|
||||
def test_projectsList_repoDenied():
|
||||
cfg = RawConfigParser()
|
||||
cfg.add_section('repo foo/bar')
|
||||
got = StringIO()
|
||||
gitweb.generate(
|
||||
config=cfg,
|
||||
fp=got)
|
||||
eq(got.getvalue(), '''\
|
||||
''')
|
||||
|
||||
def test_projectsList_noOwner():
|
||||
cfg = RawConfigParser()
|
||||
cfg.add_section('repo foo/bar')
|
||||
cfg.set('repo foo/bar', 'gitweb', 'yes')
|
||||
got = StringIO()
|
||||
gitweb.generate(
|
||||
config=cfg,
|
||||
fp=got)
|
||||
eq(got.getvalue(), '''\
|
||||
foo%2Fbar
|
||||
''')
|
||||
|
||||
def test_projectsList_haveOwner():
|
||||
cfg = RawConfigParser()
|
||||
cfg.add_section('repo foo/bar')
|
||||
cfg.set('repo foo/bar', 'gitweb', 'yes')
|
||||
cfg.set('repo foo/bar', 'owner', 'John Doe')
|
||||
got = StringIO()
|
||||
gitweb.generate(
|
||||
config=cfg,
|
||||
fp=got)
|
||||
eq(got.getvalue(), '''\
|
||||
foo%2Fbar John+Doe
|
||||
''')
|
||||
|
||||
def test_projectsList_multiple():
|
||||
cfg = RawConfigParser()
|
||||
cfg.add_section('gitosis')
|
||||
cfg.add_section('repo foo/bar')
|
||||
cfg.set('repo foo/bar', 'owner', 'John Doe')
|
||||
cfg.set('repo foo/bar', 'gitweb', 'yes')
|
||||
cfg.add_section('repo quux')
|
||||
cfg.set('repo quux', 'gitweb', 'yes')
|
||||
got = StringIO()
|
||||
gitweb.generate(
|
||||
config=cfg,
|
||||
fp=got)
|
||||
eq(got.getvalue(), '''\
|
||||
quux
|
||||
foo%2Fbar John+Doe
|
||||
''')
|
||||
|
||||
def test_projectsList_multiple_globalGitwebYes():
|
||||
cfg = RawConfigParser()
|
||||
cfg.add_section('gitosis')
|
||||
cfg.set('gitosis', 'gitweb', 'yes')
|
||||
cfg.add_section('repo foo/bar')
|
||||
cfg.set('repo foo/bar', 'owner', 'John Doe')
|
||||
cfg.add_section('repo quux')
|
||||
# same as default, no effect
|
||||
cfg.set('repo quux', 'gitweb', 'yes')
|
||||
cfg.add_section('repo thud')
|
||||
# this is still hidden
|
||||
cfg.set('repo thud', 'gitweb', 'no')
|
||||
got = StringIO()
|
||||
gitweb.generate(
|
||||
config=cfg,
|
||||
fp=got)
|
||||
eq(got.getvalue(), '''\
|
||||
quux
|
||||
foo%2Fbar John+Doe
|
||||
''')
|
1
setup.py
1
setup.py
|
@ -16,6 +16,7 @@ setup(
|
|||
'console_scripts': [
|
||||
'gitosis-ssh = gitosis.ssh:main',
|
||||
'gitosis-serve = gitosis.serve:main',
|
||||
'gitosis-gitweb = gitosis.gitweb:main',
|
||||
],
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue