svn+wiki
Я чего-то не совсем понял что ты хочешь, но DokuWiki, например, хранит свои странички в тексте и их теоретически можно менять на файловой системе. Единственное - могут быть проблемы с историей и, возможно, с кешем (2-е точно не помню).
Мне все это мешает (и я не понимаю какому разработчику удобно пользоваться wiki я хочу чтоб wiki подстраивалась под мой проект, а не наоборот.
У разработчика должно быть как можно меньше черновой организационной работы, ему должно быть удобно.
Удобно: редактируя в текстовом редакторе текст программы, открыть рядом файлик и в него этим же редактором дописать кусок документации к изменениям в коде. Закоммитить оба файла. И все.
Удобно: читать документацию в текстовом редакторе, переключаясь между кодом и документацией для разъяснения.
Только когда документация лежит рядом с кодом она будет с ним синхронизирована.
При коммите у разработчика куча дел:
— проверить изменения (svn up && svn status -q && svn diff)
— разрешить конфликты и закоммитить
— написать в лог svn осмысленное сообщение (с номером талончика)
— закрыть талончик, написав как проверить талончик (с номером ревизии svn)
— написать на вики в документации что изменилось в поведении модуля
— написать в отдельный changelog (в особо запущенных случаях он отдельный)
Хочется количество пунктов уменьшить.
Ненормально дублировать одну и ту же информацию в 5 местах, ненормально переключаться между редактором и браузером, это все отвлекает.
В этой схеме человек, который будет смотреть на код после меня, не должен обладать тайным знанием о местонахождении вики и странички (страничек!) в ней которые описывают текущее положение дел.
Ему все должно быть видно в svn.
Ага, теперь кажется понял чего ты хочешь. Тебе надо браузер svn, но, чтобы документация, хранящаяся в svn отображалась с учётом маркировки, ссылками и пр.
Возможно тебе тогда подойдёт что-то вроде ikiwiki. Можно, например, при коммите документации перегенерировать странички. Там ещё вроде даже историю можно прикрутить плагинами.
Тебе надо браузер svn, но, чтобы документация, хранящаяся в svn отображалась с учётом маркировки, ссылками и пр.
Ну да, единственное что я вижу полезного в вики по сравнению с простым текстом под svn — удобный переход по ссылкам (так как там html).
Уведомления об изменениях я от svn по почте получаю. Историю практически никто никогда не смотрит, правами доступа пусть занимается ОС.
То есть как раз прикручивать фичи — это "права доступа, история, diff и проч" — теоретически это все приятно видеть, но на практике я этими штуками пользовался 2 раза в жизни — когда промазал по кнопке.
В качестве wiki compiler я уже использовал python-markdown, такая же штука.
Интересно почему никто так не делает как я предлагаю. Если бы велосипед был уже изобретен, можно было бы радоваться этим самым фичам (которые в общем не нужны но забавны)
В качестве wiki compiler я уже использовал python-markdown, такая же штука.Ну да, я понял уже что ты хотел (надеюсь). Сначала просто затупил не в ту сторону.
Интересно почему никто так не делает как я предлагаю. Если бы велосипед был уже изобретен, можно было бы радоваться этим самым фичам (которые в общем не нужны но забавны)
Думаю, ikiwiki - как раз то, что тебе нужно. Там можно разные разметки использовать, разные штучки прикручивать и прочее.
$ cat swinki.py
from __future__ import with_statement
import cgi, os
from pysvn import Client
from markdown import markdown
REPOSITORY = '/home/fvv/projects/svn'
ROOT = '/'
MAIN_PAGE = 'README'
def swinki(env, start_response):
query = cgi.parse_qs(env['QUERY_STRING'])
if env['PATH_INFO'] == ROOT:
if 'css' in query:
start_response('200 Ok', [('Content-Type', 'text/css; charset=utf-8')])
return CSS
elif 'js' in query:
start_response('200 Ok', [('Content-Type', 'text/javascript; charset=utf-8')])
return JS
else:
start_response('301 Moved Permanently', [('Content-Type', 'text/html' ('Location', ROOT + MAIN_PAGE)])
return ''
elif 'action' in query:
action = query['action'][0]
if action == 'edit':
if is_post_request(env):
content = get_post_form(env)['content'].value.decode('utf8')
preview = markdown(content)
else:
path = os.path.abspath(REPOSITORY + env['PATH_INFO'])
assert path.startswith(REPOSITORY)
content = open(path).read.decode('utf8')
preview = ''
start_response('200 Ok', [('Content-Type', 'text/html; charset=utf-8')])
return (EDIT % {'path': env['PATH_INFO'],
'content': content,
'preview': preview,
'repository': REPOSITORY,
'main': ROOT}).encode('utf8')
elif action == 'update':
Client.update(REPOSITORY + env['PATH_INFO'])
start_response('307 Temporary Redirect', [('Location', env['PATH_INFO'])])
return ''
else:
path = os.path.abspath(REPOSITORY + env['PATH_INFO'])
assert path.startswith(REPOSITORY)
if is_post_request(env):
content = get_post_form(env)['content'].value.decode('utf8')
with open(path,'w') as out:
out.write(content.encode('utf8'
Client.checkin(path, 'changed by swinki')
start_response('200 Ok', [('Content-Type', 'text/html; charset=utf-8')])
info = Client.list(path)[0][0]
return (PAGE % {'path': env['PATH_INFO'],
'content': markdown(Client.cat(path).decode('utf8'
'repository': REPOSITORY,
'revision': info.created_rev.number,
'author': info.last_author,
'main': ROOT}).encode('utf8')
def is_post_request(environ):
if environ['REQUEST_METHOD'].upper != 'POST':
return False
content_type = environ.get('CONTENT_TYPE', 'application/x-www-form-urlencoded')
return (content_type.startswith('application/x-www-form-urlencoded'
or content_type.startswith('multipart/form-data'
def get_post_form(environ):
assert is_post_request(environ)
input = environ['wsgi.input']
post_form = environ.get('wsgi.post_form')
if (post_form is not None
and post_form[0] is input):
return post_form[2]
# This must be done to avoid a bug in cgi.FieldStorage
environ.setdefault('QUERY_STRING', '')
fs = cgi.FieldStorage(fp=input,
environ=environ,
keep_blank_values=1)
new_input = InputProcessed
post_form = (new_input, input, fs)
environ['wsgi.post_form'] = post_form
environ['wsgi.input'] = new_input
return fs
class InputProcessed(object):
def read(self, *args):
raise EOFError('The wsgi.input stream has already been consumed')
readline = readlines = __iter__ = read
# --------Templates---------------
# There is no need in Cheetah/Django yet
PAGE = u"""
<html>
<head>
<title>sWInKI: Page -- %(repository)s</title>
<script src="%(main)s?js=swinki&" type="text/javascript"></script>
<link href="%(main)s?css=swinki&" rel="stylesheet" type="text/css" />
</head>
<body>
<h3>%(path)s @ %(revision)s by %(author)s</h3>
<span class="header">
<a href="%(main)s">Home</a>
<a href="?action=edit">Edit</a>
<a href="%(path)s?action=update">Update</a></span>
<div class="main">
<div class="markdown">%(content)s</div>
</div>
</body>
</html>
"""
EDIT = u"""
<html>
<head>
<title>sWInKI: Edit -- %(repository)s</title>
<script src="%(main)s?js=swinki&" type="text/javascript"></script>
<link href="%(main)s?css=swinki&" rel="stylesheet" type="text/css" />
</head>
<body>
<h3>%(path)s</h3>
<span class="header"><a href="%(main)s">Home</a><a href="%(path)s">Back</a></span>
<div class="main">
<div class="markdown">%(preview)s</div>
<form method="post" action="%(path)s" enctype="application/x-www-form-urlencoded" name="form">
<textarea name="content" cols="80" rows="30">%(content)s</textarea>
<div class="footer">
<input type="button" onclick="document.form.action += '?action=edit'; document.form.submit;" value="Preview"/>
<input type="button" onclick="document.form.submit;" value="Save"/>
</div>
</form>
</div>
</body>
</html>
"""
CSS = """
span.header a, span.footer a { padding: 5px; margin: 3px; border: 1px solid #9999FF; background-color: #FAFAFA;}
div.main { padding: 5px; background-color: #FAFAFA; border: 1px solid #9999FF;}
div.markdown h1, div.markdown h2 { font-size: medium;}
"""
JS = ''
# ---------------------------------
if __name__ == '__main__':
from optparse import OptionParser
parser = OptionParser
parser.add_option('-p', '--port', dest = 'port',
help = 'port',
default = '8080')
options, args = parser.parse_args
from wsgiref.simple_server import make_server
make_server('', int(options.port swinki).serve_forever
Оставить комментарий
pilot
Сколько не видел разных wiki, всегда информация в них рассинхронизируется с состоянием исходного кода [под svn].Вопрос: есть ли тулза/плагин к вики или что-то еще, что встраивает вики в svn таким образом:
Есть репозиторий:
И тп.
В README пишем используя markdown (например):
Для Trac такого не нашел + разметка Trac'а нечитабельна.
Написал простенький скриптик который делает то что мне нужно. Сразу же появились желания дописать туда фич, чтоб было удобнее. Но изобретать велосипед не хочется.
Посоветуйте штуку которая делает нечто похожее?