diff options
Diffstat (limited to 'Tools/faqwiz/faqwiz.py')
-rw-r--r-- | Tools/faqwiz/faqwiz.py | 1186 |
1 files changed, 593 insertions, 593 deletions
diff --git a/Tools/faqwiz/faqwiz.py b/Tools/faqwiz/faqwiz.py index 29712eb..f604fd2 100644 --- a/Tools/faqwiz/faqwiz.py +++ b/Tools/faqwiz/faqwiz.py @@ -12,25 +12,25 @@ The actual script to place in cgi-bin is faqw.py. """ import sys, string, time, os, stat, re, cgi, faqconf -from faqconf import * # This imports all uppercase names +from faqconf import * # This imports all uppercase names now = time.time() class FileError: def __init__(self, file): - self.file = file + self.file = file class InvalidFile(FileError): pass class NoSuchSection(FileError): def __init__(self, section): - FileError.__init__(self, NEWFILENAME %(section, 1)) - self.section = section + FileError.__init__(self, NEWFILENAME %(section, 1)) + self.section = section class NoSuchFile(FileError): def __init__(self, file, why=None): - FileError.__init__(self, file) - self.why = why + FileError.__init__(self, file) + self.why = why def escape(s): s = string.replace(s, '&', '&') @@ -45,9 +45,9 @@ def escapeq(s): def _interpolate(format, args, kw): try: - quote = kw['_quote'] + quote = kw['_quote'] except KeyError: - quote = 1 + quote = 1 d = (kw,) + args + (faqconf.__dict__,) m = MagicDict(d, quote) return format % m @@ -57,9 +57,9 @@ def interpolate(format, *args, **kw): def emit(format, *args, **kw): try: - f = kw['_file'] + f = kw['_file'] except KeyError: - f = sys.stdout + f = sys.stdout f.write(_interpolate(format, args, kw)) translate_prog = None @@ -67,32 +67,32 @@ translate_prog = None def translate(text, pre=0): global translate_prog if not translate_prog: - translate_prog = prog = re.compile( - r'\b(http|ftp|https)://\S+(\b|/)|\b[-.\w]+@[-.\w]+') + translate_prog = prog = re.compile( + r'\b(http|ftp|https)://\S+(\b|/)|\b[-.\w]+@[-.\w]+') else: - prog = translate_prog + prog = translate_prog i = 0 list = [] while 1: - m = prog.search(text, i) - if not m: - break - j = m.start() - list.append(escape(text[i:j])) - i = j - url = m.group(0) - while url[-1] in '();:,.?\'"<>': - url = url[:-1] - i = i + len(url) - url = escape(url) - if not pre or (pre and PROCESS_PREFORMAT): - if ':' in url: - repl = '<A HREF="%s">%s</A>' % (url, url) - else: - repl = '<A HREF="mailto:%s"><%s></A>' % (url, url) - else: - repl = url - list.append(repl) + m = prog.search(text, i) + if not m: + break + j = m.start() + list.append(escape(text[i:j])) + i = j + url = m.group(0) + while url[-1] in '();:,.?\'"<>': + url = url[:-1] + i = i + len(url) + url = escape(url) + if not pre or (pre and PROCESS_PREFORMAT): + if ':' in url: + repl = '<A HREF="%s">%s</A>' % (url, url) + else: + repl = '<A HREF="mailto:%s"><%s></A>' % (url, url) + else: + repl = url + list.append(repl) j = len(text) list.append(escape(text[i:j])) return string.join(list, '') @@ -105,43 +105,43 @@ revparse_prog = None def revparse(rev): global revparse_prog if not revparse_prog: - revparse_prog = re.compile(r'^(\d{1,3})\.(\d{1-4})$') + revparse_prog = re.compile(r'^(\d{1,3})\.(\d{1-4})$') m = revparse_prog.match(rev) if not m: - return None + return None [major, minor] = map(string.atoi, m.group(1, 2)) return major, minor def load_cookies(): if not os.environ.has_key('HTTP_COOKIE'): - return {} + return {} raw = os.environ['HTTP_COOKIE'] words = map(string.strip, string.split(raw, ';')) cookies = {} for word in words: - i = string.find(word, '=') - if i >= 0: - key, value = word[:i], word[i+1:] - cookies[key] = value + i = string.find(word, '=') + if i >= 0: + key, value = word[:i], word[i+1:] + cookies[key] = value return cookies def load_my_cookie(): cookies = load_cookies() try: - value = cookies[COOKIE_NAME] + value = cookies[COOKIE_NAME] except KeyError: - return {} + return {} import urllib value = urllib.unquote(value) words = string.split(value, '/') while len(words) < 3: - words.append('') + words.append('') author = string.join(words[:-2], '/') email = words[-2] password = words[-1] return {'author': author, - 'email': email, - 'password': password} + 'email': email, + 'password': password} def send_my_cookie(ui): name = COOKIE_NAME @@ -156,147 +156,147 @@ def send_my_cookie(ui): class MagicDict: def __init__(self, d, quote): - self.__d = d - self.__quote = quote + self.__d = d + self.__quote = quote def __getitem__(self, key): - for d in self.__d: - try: - value = d[key] - if value: - value = str(value) - if self.__quote: - value = escapeq(value) - return value - except KeyError: - pass - return '' + for d in self.__d: + try: + value = d[key] + if value: + value = str(value) + if self.__quote: + value = escapeq(value) + return value + except KeyError: + pass + return '' class UserInput: def __init__(self): - self.__form = cgi.FieldStorage() + self.__form = cgi.FieldStorage() def __getattr__(self, name): - if name[0] == '_': - raise AttributeError - try: - value = self.__form[name].value - except (TypeError, KeyError): - value = '' - else: - value = string.strip(value) - setattr(self, name, value) - return value + if name[0] == '_': + raise AttributeError + try: + value = self.__form[name].value + except (TypeError, KeyError): + value = '' + else: + value = string.strip(value) + setattr(self, name, value) + return value def __getitem__(self, key): - return getattr(self, key) + return getattr(self, key) class FaqEntry: def __init__(self, fp, file, sec_num): - self.file = file - self.sec, self.num = sec_num - if fp: - import rfc822 - self.__headers = rfc822.Message(fp) - self.body = string.strip(fp.read()) - else: - self.__headers = {'title': "%d.%d. " % sec_num} - self.body = '' + self.file = file + self.sec, self.num = sec_num + if fp: + import rfc822 + self.__headers = rfc822.Message(fp) + self.body = string.strip(fp.read()) + else: + self.__headers = {'title': "%d.%d. " % sec_num} + self.body = '' def __getattr__(self, name): - if name[0] == '_': - raise AttributeError - key = string.join(string.split(name, '_'), '-') - try: - value = self.__headers[key] - except KeyError: - value = '' - setattr(self, name, value) - return value + if name[0] == '_': + raise AttributeError + key = string.join(string.split(name, '_'), '-') + try: + value = self.__headers[key] + except KeyError: + value = '' + setattr(self, name, value) + return value def __getitem__(self, key): - return getattr(self, key) + return getattr(self, key) def load_version(self): - command = interpolate(SH_RLOG_H, self) - p = os.popen(command) - version = '' - while 1: - line = p.readline() - if not line: - break - if line[:5] == 'head:': - version = string.strip(line[5:]) - p.close() - self.version = version + command = interpolate(SH_RLOG_H, self) + p = os.popen(command) + version = '' + while 1: + line = p.readline() + if not line: + break + if line[:5] == 'head:': + version = string.strip(line[5:]) + p.close() + self.version = version def getmtime(self): - if not self.last_changed_date: - return 0 - try: - return os.stat(self.file)[stat.ST_MTIME] - except os.error: - return 0 + if not self.last_changed_date: + return 0 + try: + return os.stat(self.file)[stat.ST_MTIME] + except os.error: + return 0 def emit_marks(self): - mtime = self.getmtime() - if mtime >= now - DT_VERY_RECENT: - emit(MARK_VERY_RECENT, self) - elif mtime >= now - DT_RECENT: - emit(MARK_RECENT, self) + mtime = self.getmtime() + if mtime >= now - DT_VERY_RECENT: + emit(MARK_VERY_RECENT, self) + elif mtime >= now - DT_RECENT: + emit(MARK_RECENT, self) def show(self, edit=1): - emit(ENTRY_HEADER1, self) - self.emit_marks() - emit(ENTRY_HEADER2, self) - pre = 0 - raw = 0 - for line in string.split(self.body, '\n'): - # Allow the user to insert raw html into a FAQ answer - # (Skip Montanaro, with changes by Guido) - tag = string.lower(string.rstrip(line)) - if tag == '<html>': - raw = 1 - continue - if tag == '</html>': - raw = 0 - continue - if raw: - print line - continue - if not string.strip(line): - if pre: - print '</PRE>' - pre = 0 - else: - print '<P>' - else: - if line[0] not in string.whitespace: - if pre: - print '</PRE>' - pre = 0 - else: - if not pre: - print '<PRE>' - pre = 1 - if '/' in line or '@' in line: - line = translate(line, pre) - elif '<' in line or '&' in line: - line = escape(line) - if not pre and '*' in line: - line = emphasize(line) - print line - if pre: - print '</PRE>' - pre = 0 - if edit: - print '<P>' - emit(ENTRY_FOOTER, self) - if self.last_changed_date: - emit(ENTRY_LOGINFO, self) - print '<P>' + emit(ENTRY_HEADER1, self) + self.emit_marks() + emit(ENTRY_HEADER2, self) + pre = 0 + raw = 0 + for line in string.split(self.body, '\n'): + # Allow the user to insert raw html into a FAQ answer + # (Skip Montanaro, with changes by Guido) + tag = string.lower(string.rstrip(line)) + if tag == '<html>': + raw = 1 + continue + if tag == '</html>': + raw = 0 + continue + if raw: + print line + continue + if not string.strip(line): + if pre: + print '</PRE>' + pre = 0 + else: + print '<P>' + else: + if line[0] not in string.whitespace: + if pre: + print '</PRE>' + pre = 0 + else: + if not pre: + print '<PRE>' + pre = 1 + if '/' in line or '@' in line: + line = translate(line, pre) + elif '<' in line or '&' in line: + line = escape(line) + if not pre and '*' in line: + line = emphasize(line) + print line + if pre: + print '</PRE>' + pre = 0 + if edit: + print '<P>' + emit(ENTRY_FOOTER, self) + if self.last_changed_date: + emit(ENTRY_LOGINFO, self) + print '<P>' class FaqDir: @@ -305,517 +305,517 @@ class FaqDir: __okprog = re.compile(OKFILENAME) def __init__(self, dir=os.curdir): - self.__dir = dir - self.__files = None + self.__dir = dir + self.__files = None def __fill(self): - if self.__files is not None: - return - self.__files = files = [] - okprog = self.__okprog - for file in os.listdir(self.__dir): - if self.__okprog.match(file): - files.append(file) - files.sort() + if self.__files is not None: + return + self.__files = files = [] + okprog = self.__okprog + for file in os.listdir(self.__dir): + if self.__okprog.match(file): + files.append(file) + files.sort() def good(self, file): - return self.__okprog.match(file) + return self.__okprog.match(file) def parse(self, file): - m = self.good(file) - if not m: - return None - sec, num = m.group(1, 2) - return string.atoi(sec), string.atoi(num) + m = self.good(file) + if not m: + return None + sec, num = m.group(1, 2) + return string.atoi(sec), string.atoi(num) def list(self): - # XXX Caller shouldn't modify result - self.__fill() - return self.__files + # XXX Caller shouldn't modify result + self.__fill() + return self.__files def open(self, file): - sec_num = self.parse(file) - if not sec_num: - raise InvalidFile(file) - try: - fp = open(file) - except IOError, msg: - raise NoSuchFile(file, msg) - try: - return self.entryclass(fp, file, sec_num) - finally: - fp.close() + sec_num = self.parse(file) + if not sec_num: + raise InvalidFile(file) + try: + fp = open(file) + except IOError, msg: + raise NoSuchFile(file, msg) + try: + return self.entryclass(fp, file, sec_num) + finally: + fp.close() def show(self, file, edit=1): - self.open(file).show(edit=edit) + self.open(file).show(edit=edit) def new(self, section): - if not SECTION_TITLES.has_key(section): - raise NoSuchSection(section) - maxnum = 0 - for file in self.list(): - sec, num = self.parse(file) - if sec == section: - maxnum = max(maxnum, num) - sec_num = (section, maxnum+1) - file = NEWFILENAME % sec_num - return self.entryclass(None, file, sec_num) + if not SECTION_TITLES.has_key(section): + raise NoSuchSection(section) + maxnum = 0 + for file in self.list(): + sec, num = self.parse(file) + if sec == section: + maxnum = max(maxnum, num) + sec_num = (section, maxnum+1) + file = NEWFILENAME % sec_num + return self.entryclass(None, file, sec_num) class FaqWizard: def __init__(self): - self.ui = UserInput() - self.dir = FaqDir() + self.ui = UserInput() + self.dir = FaqDir() def go(self): - print 'Content-type: text/html' - req = self.ui.req or 'home' - mname = 'do_%s' % req - try: - meth = getattr(self, mname) - except AttributeError: - self.error("Bad request type %s." % `req`) - else: - try: - meth() - except InvalidFile, exc: - self.error("Invalid entry file name %s" % exc.file) - except NoSuchFile, exc: - self.error("No entry with file name %s" % exc.file) - except NoSuchSection, exc: - self.error("No section number %s" % exc.section) - self.epilogue() + print 'Content-type: text/html' + req = self.ui.req or 'home' + mname = 'do_%s' % req + try: + meth = getattr(self, mname) + except AttributeError: + self.error("Bad request type %s." % `req`) + else: + try: + meth() + except InvalidFile, exc: + self.error("Invalid entry file name %s" % exc.file) + except NoSuchFile, exc: + self.error("No entry with file name %s" % exc.file) + except NoSuchSection, exc: + self.error("No section number %s" % exc.section) + self.epilogue() def error(self, message, **kw): - self.prologue(T_ERROR) - emit(message, kw) + self.prologue(T_ERROR) + emit(message, kw) def prologue(self, title, entry=None, **kw): - emit(PROLOGUE, entry, kwdict=kw, title=escape(title)) + emit(PROLOGUE, entry, kwdict=kw, title=escape(title)) def epilogue(self): - emit(EPILOGUE) + emit(EPILOGUE) def do_home(self): - self.prologue(T_HOME) - emit(HOME) + self.prologue(T_HOME) + emit(HOME) def do_debug(self): - self.prologue("FAQ Wizard Debugging") - form = cgi.FieldStorage() - cgi.print_form(form) + self.prologue("FAQ Wizard Debugging") + form = cgi.FieldStorage() + cgi.print_form(form) cgi.print_environ(os.environ) - cgi.print_directory() - cgi.print_arguments() + cgi.print_directory() + cgi.print_arguments() def do_search(self): - query = self.ui.query - if not query: - self.error("Empty query string!") - return - if self.ui.querytype == 'simple': - query = re.escape(query) - queries = [query] - elif self.ui.querytype in ('anykeywords', 'allkeywords'): - words = filter(None, re.split('\W+', query)) - if not words: - self.error("No keywords specified!") - return - words = map(lambda w: r'\b%s\b' % w, words) - if self.ui.querytype[:3] == 'any': - queries = [string.join(words, '|')] - else: - # Each of the individual queries must match - queries = words - else: - # Default to regular expression - queries = [query] - self.prologue(T_SEARCH) - progs = [] - for query in queries: - if self.ui.casefold == 'no': - p = re.compile(query) - else: - p = re.compile(query, re.IGNORECASE) - progs.append(p) - hits = [] - for file in self.dir.list(): - try: - entry = self.dir.open(file) - except FileError: - constants - for p in progs: - if not p.search(entry.title) and not p.search(entry.body): - break - else: - hits.append(file) - if not hits: - emit(NO_HITS, self.ui, count=0) - elif len(hits) <= MAXHITS: - if len(hits) == 1: - emit(ONE_HIT, count=1) - else: - emit(FEW_HITS, count=len(hits)) - self.format_all(hits, headers=0) - else: - emit(MANY_HITS, count=len(hits)) - self.format_index(hits) + query = self.ui.query + if not query: + self.error("Empty query string!") + return + if self.ui.querytype == 'simple': + query = re.escape(query) + queries = [query] + elif self.ui.querytype in ('anykeywords', 'allkeywords'): + words = filter(None, re.split('\W+', query)) + if not words: + self.error("No keywords specified!") + return + words = map(lambda w: r'\b%s\b' % w, words) + if self.ui.querytype[:3] == 'any': + queries = [string.join(words, '|')] + else: + # Each of the individual queries must match + queries = words + else: + # Default to regular expression + queries = [query] + self.prologue(T_SEARCH) + progs = [] + for query in queries: + if self.ui.casefold == 'no': + p = re.compile(query) + else: + p = re.compile(query, re.IGNORECASE) + progs.append(p) + hits = [] + for file in self.dir.list(): + try: + entry = self.dir.open(file) + except FileError: + constants + for p in progs: + if not p.search(entry.title) and not p.search(entry.body): + break + else: + hits.append(file) + if not hits: + emit(NO_HITS, self.ui, count=0) + elif len(hits) <= MAXHITS: + if len(hits) == 1: + emit(ONE_HIT, count=1) + else: + emit(FEW_HITS, count=len(hits)) + self.format_all(hits, headers=0) + else: + emit(MANY_HITS, count=len(hits)) + self.format_index(hits) def do_all(self): - self.prologue(T_ALL) - files = self.dir.list() - self.last_changed(files) - self.format_index(files, localrefs=1) - self.format_all(files) + self.prologue(T_ALL) + files = self.dir.list() + self.last_changed(files) + self.format_index(files, localrefs=1) + self.format_all(files) def do_compat(self): - files = self.dir.list() - emit(COMPAT) - self.last_changed(files) - self.format_index(files, localrefs=1) - self.format_all(files, edit=0) - sys.exit(0) # XXX Hack to suppress epilogue + files = self.dir.list() + emit(COMPAT) + self.last_changed(files) + self.format_index(files, localrefs=1) + self.format_all(files, edit=0) + sys.exit(0) # XXX Hack to suppress epilogue def last_changed(self, files): - latest = 0 - for file in files: - entry = self.dir.open(file) - if entry: - mtime = mtime = entry.getmtime() - if mtime > latest: - latest = mtime - print time.strftime(LAST_CHANGED, time.localtime(latest)) - emit(EXPLAIN_MARKS) + latest = 0 + for file in files: + entry = self.dir.open(file) + if entry: + mtime = mtime = entry.getmtime() + if mtime > latest: + latest = mtime + print time.strftime(LAST_CHANGED, time.localtime(latest)) + emit(EXPLAIN_MARKS) def format_all(self, files, edit=1, headers=1): - sec = 0 - for file in files: - try: - entry = self.dir.open(file) - except NoSuchFile: - continue - if headers and entry.sec != sec: - sec = entry.sec - try: - title = SECTION_TITLES[sec] - except KeyError: - title = "Untitled" - emit("\n<HR>\n<H1>%(sec)s. %(title)s</H1>\n", - sec=sec, title=title) - entry.show(edit=edit) + sec = 0 + for file in files: + try: + entry = self.dir.open(file) + except NoSuchFile: + continue + if headers and entry.sec != sec: + sec = entry.sec + try: + title = SECTION_TITLES[sec] + except KeyError: + title = "Untitled" + emit("\n<HR>\n<H1>%(sec)s. %(title)s</H1>\n", + sec=sec, title=title) + entry.show(edit=edit) def do_index(self): - self.prologue(T_INDEX) - files = self.dir.list() - self.last_changed(files) - self.format_index(files, add=1) + self.prologue(T_INDEX) + files = self.dir.list() + self.last_changed(files) + self.format_index(files, add=1) def format_index(self, files, add=0, localrefs=0): - sec = 0 - for file in files: - try: - entry = self.dir.open(file) - except NoSuchFile: - continue - if entry.sec != sec: - if sec: - if add: - emit(INDEX_ADDSECTION, sec=sec) - emit(INDEX_ENDSECTION, sec=sec) - sec = entry.sec - try: - title = SECTION_TITLES[sec] - except KeyError: - title = "Untitled" - emit(INDEX_SECTION, sec=sec, title=title) - if localrefs: - emit(LOCAL_ENTRY, entry) - else: - emit(INDEX_ENTRY, entry) - entry.emit_marks() - if sec: - if add: - emit(INDEX_ADDSECTION, sec=sec) - emit(INDEX_ENDSECTION, sec=sec) + sec = 0 + for file in files: + try: + entry = self.dir.open(file) + except NoSuchFile: + continue + if entry.sec != sec: + if sec: + if add: + emit(INDEX_ADDSECTION, sec=sec) + emit(INDEX_ENDSECTION, sec=sec) + sec = entry.sec + try: + title = SECTION_TITLES[sec] + except KeyError: + title = "Untitled" + emit(INDEX_SECTION, sec=sec, title=title) + if localrefs: + emit(LOCAL_ENTRY, entry) + else: + emit(INDEX_ENTRY, entry) + entry.emit_marks() + if sec: + if add: + emit(INDEX_ADDSECTION, sec=sec) + emit(INDEX_ENDSECTION, sec=sec) def do_recent(self): - if not self.ui.days: - days = 1 - else: - days = string.atof(self.ui.days) - try: - cutoff = now - days * 24 * 3600 - except OverflowError: - cutoff = 0 - list = [] - for file in self.dir.list(): - entry = self.dir.open(file) - if not entry: - continue - mtime = entry.getmtime() - if mtime >= cutoff: - list.append((mtime, file)) - list.sort() - list.reverse() - self.prologue(T_RECENT) - if days <= 1: - period = "%.2g hours" % (days*24) - else: - period = "%.6g days" % days - if not list: - emit(NO_RECENT, period=period) - elif len(list) == 1: - emit(ONE_RECENT, period=period) - else: - emit(SOME_RECENT, period=period, count=len(list)) - self.format_all(map(lambda (mtime, file): file, list), headers=0) - emit(TAIL_RECENT) + if not self.ui.days: + days = 1 + else: + days = string.atof(self.ui.days) + try: + cutoff = now - days * 24 * 3600 + except OverflowError: + cutoff = 0 + list = [] + for file in self.dir.list(): + entry = self.dir.open(file) + if not entry: + continue + mtime = entry.getmtime() + if mtime >= cutoff: + list.append((mtime, file)) + list.sort() + list.reverse() + self.prologue(T_RECENT) + if days <= 1: + period = "%.2g hours" % (days*24) + else: + period = "%.6g days" % days + if not list: + emit(NO_RECENT, period=period) + elif len(list) == 1: + emit(ONE_RECENT, period=period) + else: + emit(SOME_RECENT, period=period, count=len(list)) + self.format_all(map(lambda (mtime, file): file, list), headers=0) + emit(TAIL_RECENT) def do_roulette(self): - import whrandom - files = self.dir.list() - if not files: - self.error("No entries.") - return - file = whrandom.choice(files) - self.prologue(T_ROULETTE) - emit(ROULETTE) - self.dir.show(file) + import whrandom + files = self.dir.list() + if not files: + self.error("No entries.") + return + file = whrandom.choice(files) + self.prologue(T_ROULETTE) + emit(ROULETTE) + self.dir.show(file) def do_help(self): - self.prologue(T_HELP) - emit(HELP) + self.prologue(T_HELP) + emit(HELP) def do_show(self): - entry = self.dir.open(self.ui.file) - self.prologue(T_SHOW) - entry.show() + entry = self.dir.open(self.ui.file) + self.prologue(T_SHOW) + entry.show() def do_add(self): - self.prologue(T_ADD) - emit(ADD_HEAD) - sections = SECTION_TITLES.items() - sections.sort() - for section, title in sections: - emit(ADD_SECTION, section=section, title=title) - emit(ADD_TAIL) + self.prologue(T_ADD) + emit(ADD_HEAD) + sections = SECTION_TITLES.items() + sections.sort() + for section, title in sections: + emit(ADD_SECTION, section=section, title=title) + emit(ADD_TAIL) def do_delete(self): - self.prologue(T_DELETE) - emit(DELETE) + self.prologue(T_DELETE) + emit(DELETE) def do_log(self): - entry = self.dir.open(self.ui.file) - self.prologue(T_LOG, entry) - emit(LOG, entry) - self.rlog(interpolate(SH_RLOG, entry), entry) + entry = self.dir.open(self.ui.file) + self.prologue(T_LOG, entry) + emit(LOG, entry) + self.rlog(interpolate(SH_RLOG, entry), entry) def rlog(self, command, entry=None): - output = os.popen(command).read() - sys.stdout.write('<PRE>') - athead = 0 - lines = string.split(output, '\n') - while lines and not lines[-1]: - del lines[-1] - if lines: - line = lines[-1] - if line[:1] == '=' and len(line) >= 40 and \ - line == line[0]*len(line): - del lines[-1] - headrev = None - for line in lines: - if entry and athead and line[:9] == 'revision ': - rev = string.strip(line[9:]) - mami = revparse(rev) - if not mami: - print line - else: - emit(REVISIONLINK, entry, rev=rev, line=line) - if mami[1] > 1: - prev = "%d.%d" % (mami[0], mami[1]-1) - emit(DIFFLINK, entry, prev=prev, rev=rev) - if headrev: - emit(DIFFLINK, entry, prev=rev, rev=headrev) - else: - headrev = rev - print - athead = 0 - else: - athead = 0 - if line[:1] == '-' and len(line) >= 20 and \ - line == len(line) * line[0]: - athead = 1 - sys.stdout.write('<HR>') - else: - print line - print '</PRE>' + output = os.popen(command).read() + sys.stdout.write('<PRE>') + athead = 0 + lines = string.split(output, '\n') + while lines and not lines[-1]: + del lines[-1] + if lines: + line = lines[-1] + if line[:1] == '=' and len(line) >= 40 and \ + line == line[0]*len(line): + del lines[-1] + headrev = None + for line in lines: + if entry and athead and line[:9] == 'revision ': + rev = string.strip(line[9:]) + mami = revparse(rev) + if not mami: + print line + else: + emit(REVISIONLINK, entry, rev=rev, line=line) + if mami[1] > 1: + prev = "%d.%d" % (mami[0], mami[1]-1) + emit(DIFFLINK, entry, prev=prev, rev=rev) + if headrev: + emit(DIFFLINK, entry, prev=rev, rev=headrev) + else: + headrev = rev + print + athead = 0 + else: + athead = 0 + if line[:1] == '-' and len(line) >= 20 and \ + line == len(line) * line[0]: + athead = 1 + sys.stdout.write('<HR>') + else: + print line + print '</PRE>' def do_revision(self): - entry = self.dir.open(self.ui.file) - rev = self.ui.rev - mami = revparse(rev) - if not mami: - self.error("Invalid revision number: %s." % `rev`) - self.prologue(T_REVISION, entry) - self.shell(interpolate(SH_REVISION, entry, rev=rev)) + entry = self.dir.open(self.ui.file) + rev = self.ui.rev + mami = revparse(rev) + if not mami: + self.error("Invalid revision number: %s." % `rev`) + self.prologue(T_REVISION, entry) + self.shell(interpolate(SH_REVISION, entry, rev=rev)) def do_diff(self): - entry = self.dir.open(self.ui.file) - prev = self.ui.prev - rev = self.ui.rev - mami = revparse(rev) - if not mami: - self.error("Invalid revision number: %s." % `rev`) - if prev: - if not revparse(prev): - self.error("Invalid previous revision number: %s." % `prev`) - else: - prev = '%d.%d' % (mami[0], mami[1]) - self.prologue(T_DIFF, entry) - self.shell(interpolate(SH_RDIFF, entry, rev=rev, prev=prev)) + entry = self.dir.open(self.ui.file) + prev = self.ui.prev + rev = self.ui.rev + mami = revparse(rev) + if not mami: + self.error("Invalid revision number: %s." % `rev`) + if prev: + if not revparse(prev): + self.error("Invalid previous revision number: %s." % `prev`) + else: + prev = '%d.%d' % (mami[0], mami[1]) + self.prologue(T_DIFF, entry) + self.shell(interpolate(SH_RDIFF, entry, rev=rev, prev=prev)) def shell(self, command): - output = os.popen(command).read() - sys.stdout.write('<PRE>') - print escape(output) - print '</PRE>' + output = os.popen(command).read() + sys.stdout.write('<PRE>') + print escape(output) + print '</PRE>' def do_new(self): - entry = self.dir.new(section=string.atoi(self.ui.section)) - entry.version = '*new*' - self.prologue(T_EDIT) - emit(EDITHEAD) - emit(EDITFORM1, entry, editversion=entry.version) - emit(EDITFORM2, entry, load_my_cookie()) - emit(EDITFORM3) - entry.show(edit=0) + entry = self.dir.new(section=string.atoi(self.ui.section)) + entry.version = '*new*' + self.prologue(T_EDIT) + emit(EDITHEAD) + emit(EDITFORM1, entry, editversion=entry.version) + emit(EDITFORM2, entry, load_my_cookie()) + emit(EDITFORM3) + entry.show(edit=0) def do_edit(self): - entry = self.dir.open(self.ui.file) - entry.load_version() - self.prologue(T_EDIT) - emit(EDITHEAD) - emit(EDITFORM1, entry, editversion=entry.version) - emit(EDITFORM2, entry, load_my_cookie()) - emit(EDITFORM3) - entry.show(edit=0) + entry = self.dir.open(self.ui.file) + entry.load_version() + self.prologue(T_EDIT) + emit(EDITHEAD) + emit(EDITFORM1, entry, editversion=entry.version) + emit(EDITFORM2, entry, load_my_cookie()) + emit(EDITFORM3) + entry.show(edit=0) def do_review(self): - send_my_cookie(self.ui) - if self.ui.editversion == '*new*': - sec, num = self.dir.parse(self.ui.file) - entry = self.dir.new(section=sec) - entry.version = "*new*" - if entry.file != self.ui.file: - self.error("Commit version conflict!") - emit(NEWCONFLICT, self.ui, sec=sec, num=num) - return - else: - entry = self.dir.open(self.ui.file) - entry.load_version() - # Check that the FAQ entry number didn't change - if string.split(self.ui.title)[:1] != string.split(entry.title)[:1]: - self.error("Don't change the entry number please!") - return - # Check that the edited version is the current version - if entry.version != self.ui.editversion: - self.error("Commit version conflict!") - emit(VERSIONCONFLICT, entry, self.ui) - return - commit_ok = ((not PASSWORD - or self.ui.password == PASSWORD) - and self.ui.author - and '@' in self.ui.email - and self.ui.log) - if self.ui.commit: - if not commit_ok: - self.cantcommit() - else: - self.commit(entry) - return - self.prologue(T_REVIEW) - emit(REVIEWHEAD) - entry.body = self.ui.body - entry.title = self.ui.title - entry.show(edit=0) - emit(EDITFORM1, self.ui, entry) - if commit_ok: - emit(COMMIT) - else: - emit(NOCOMMIT) - emit(EDITFORM2, self.ui, entry, load_my_cookie()) - emit(EDITFORM3) + send_my_cookie(self.ui) + if self.ui.editversion == '*new*': + sec, num = self.dir.parse(self.ui.file) + entry = self.dir.new(section=sec) + entry.version = "*new*" + if entry.file != self.ui.file: + self.error("Commit version conflict!") + emit(NEWCONFLICT, self.ui, sec=sec, num=num) + return + else: + entry = self.dir.open(self.ui.file) + entry.load_version() + # Check that the FAQ entry number didn't change + if string.split(self.ui.title)[:1] != string.split(entry.title)[:1]: + self.error("Don't change the entry number please!") + return + # Check that the edited version is the current version + if entry.version != self.ui.editversion: + self.error("Commit version conflict!") + emit(VERSIONCONFLICT, entry, self.ui) + return + commit_ok = ((not PASSWORD + or self.ui.password == PASSWORD) + and self.ui.author + and '@' in self.ui.email + and self.ui.log) + if self.ui.commit: + if not commit_ok: + self.cantcommit() + else: + self.commit(entry) + return + self.prologue(T_REVIEW) + emit(REVIEWHEAD) + entry.body = self.ui.body + entry.title = self.ui.title + entry.show(edit=0) + emit(EDITFORM1, self.ui, entry) + if commit_ok: + emit(COMMIT) + else: + emit(NOCOMMIT) + emit(EDITFORM2, self.ui, entry, load_my_cookie()) + emit(EDITFORM3) def cantcommit(self): - self.prologue(T_CANTCOMMIT) - print CANTCOMMIT_HEAD - if not self.ui.passwd: - emit(NEED_PASSWD) - if not self.ui.log: - emit(NEED_LOG) - if not self.ui.author: - emit(NEED_AUTHOR) - if not self.ui.email: - emit(NEED_EMAIL) - print CANTCOMMIT_TAIL + self.prologue(T_CANTCOMMIT) + print CANTCOMMIT_HEAD + if not self.ui.passwd: + emit(NEED_PASSWD) + if not self.ui.log: + emit(NEED_LOG) + if not self.ui.author: + emit(NEED_AUTHOR) + if not self.ui.email: + emit(NEED_EMAIL) + print CANTCOMMIT_TAIL def commit(self, entry): - file = entry.file - # Normalize line endings in body - if '\r' in self.ui.body: - self.ui.body = re.sub('\r\n?', '\n', self.ui.body) - # Normalize whitespace in title - self.ui.title = string.join(string.split(self.ui.title)) - # Check that there were any changes - if self.ui.body == entry.body and self.ui.title == entry.title: - self.error("You didn't make any changes!") - return - # XXX Should lock here - try: - os.unlink(file) - except os.error: - pass - try: - f = open(file, 'w') - except IOError, why: - self.error(CANTWRITE, file=file, why=why) - return - date = time.ctime(now) - emit(FILEHEADER, self.ui, os.environ, date=date, _file=f, _quote=0) - f.write('\n') - f.write(self.ui.body) - f.write('\n') - f.close() - - import tempfile - tfn = tempfile.mktemp() - f = open(tfn, 'w') - emit(LOGHEADER, self.ui, os.environ, date=date, _file=f) - f.close() - - command = interpolate( - SH_LOCK + '\n' + SH_CHECKIN, - file=file, tfn=tfn) - - p = os.popen(command) - output = p.read() - sts = p.close() - # XXX Should unlock here - if not sts: - self.prologue(T_COMMITTED) - emit(COMMITTED) - else: - self.error(T_COMMITFAILED) - emit(COMMITFAILED, sts=sts) - print '<PRE>%s</PRE>' % escape(output) - - try: - os.unlink(tfn) - except os.error: - pass - - entry = self.dir.open(file) - entry.show() + file = entry.file + # Normalize line endings in body + if '\r' in self.ui.body: + self.ui.body = re.sub('\r\n?', '\n', self.ui.body) + # Normalize whitespace in title + self.ui.title = string.join(string.split(self.ui.title)) + # Check that there were any changes + if self.ui.body == entry.body and self.ui.title == entry.title: + self.error("You didn't make any changes!") + return + # XXX Should lock here + try: + os.unlink(file) + except os.error: + pass + try: + f = open(file, 'w') + except IOError, why: + self.error(CANTWRITE, file=file, why=why) + return + date = time.ctime(now) + emit(FILEHEADER, self.ui, os.environ, date=date, _file=f, _quote=0) + f.write('\n') + f.write(self.ui.body) + f.write('\n') + f.close() + + import tempfile + tfn = tempfile.mktemp() + f = open(tfn, 'w') + emit(LOGHEADER, self.ui, os.environ, date=date, _file=f) + f.close() + + command = interpolate( + SH_LOCK + '\n' + SH_CHECKIN, + file=file, tfn=tfn) + + p = os.popen(command) + output = p.read() + sts = p.close() + # XXX Should unlock here + if not sts: + self.prologue(T_COMMITTED) + emit(COMMITTED) + else: + self.error(T_COMMITFAILED) + emit(COMMITFAILED, sts=sts) + print '<PRE>%s</PRE>' % escape(output) + + try: + os.unlink(tfn) + except os.error: + pass + + entry = self.dir.open(file) + entry.show() wiz = FaqWizard() wiz.go() |