diff --git a/changelog/ChangeLogMacro.py b/changelog/ChangeLogMacro.py --- a/changelog/ChangeLogMacro.py +++ b/changelog/ChangeLogMacro.py @@ -1,1 +1,3 @@ +import re + from trac.core import * @@ -1,4 +3,5 @@ from trac.core import * +from trac.mimeview import * from trac.util import escape, Markup from trac.wiki.api import parse_args from trac.wiki.macros import WikiMacroBase @@ -2,8 +5,8 @@ from trac.util import escape, Markup from trac.wiki.api import parse_args from trac.wiki.macros import WikiMacroBase -from trac.wiki.formatter import wiki_to_html +from trac.wiki.formatter import format_to_html, wiki_to_oneliner from trac.util import format_datetime from StringIO import StringIO class ChangeLogMacro(WikiMacroBase): @@ -6,6 +9,6 @@ from trac.util import format_datetime from StringIO import StringIO class ChangeLogMacro(WikiMacroBase): - """ Provides the macro + """Write repository change log to output. @@ -11,2 +14,4 @@ + The !ChangeLog macro writes a log of the last changes of a repository at a + given path. Following variants are possible to use: {{{ @@ -12,4 +17,8 @@ {{{ - [[ChangeLog(path[,limit[,rev]])]] + 1. [[ChangeLog([reponame:]path)]] + 2. [[ChangeLog([reponame:]path@rev)]] + 3. [[ChangeLog([reponame:]path@rev, limit)]] + 4. [[ChangeLog([reponame:]path@from-to)]] + 5. [[ChangeLog([reponame:]path@rev, limit, rev)]] }}} @@ -14,5 +23,39 @@ }}} - which dumps the change log for path of revision rev, back - limit revisions. "rev" can be 0 for the latest revision. + 1. Default repository is used if reponame is left out. To show the last + five changes of the default repository: + {{{ + [[ChangeLog(/)]] + }}} + To show the last five changes of the trunk folder in a named repo: + {{{ + [[ChangeLog(otherrepo:/trunk)]] + }}} + 2. The ending revision can be set. + To show the last five changes up to revision 99: + {{{ + [[ChangeLog(otherrepo:/trunk@99)]] + }}} + 3. The limit can be set by an optional parameter. To show the last + 10 changes, up to revision 99: + {{{ + [[ChangeLog(otherrepo:/trunk@99, 10)]] + }}} + 4. A range of revisions can be logged. + {{{ + [[ChangeLog(otherrepo:/trunk@90-99)]] + }}} + To lists all changes: + {{{ + [[ChangeLog(otherrepo:/trunk@1-HEAD)]] + }}} + HEAD can be left out: + {{{ + [[ChangeLog(otherrepo:/trunk@1-)]] + }}} + 5. For backwards compatibility, revision can be stated as a second + parameter instead: + {{{ + [[ChangeLog(otherrepo:/trunk, 10, 99)]] + }}} @@ -18,6 +61,9 @@ - limit and rev may be keyword arguments + limit and rev may be keyword arguments. + {{{ + [[ChangeLog(otherrepo:/trunk, limit=10, rev=99)]] + }}} """ def expand_macro(self, formatter, name, content): req = formatter.req @@ -20,9 +66,14 @@ """ def expand_macro(self, formatter, name, content): req = formatter.req + + if 'CHANGESET_VIEW' not in req.perm: + return Markup('Changelog not available') + + context = Context.from_request(req) args, kwargs = parse_args(content) args += [None, None] path, limit, rev = args[:3] limit = kwargs.pop('limit', limit) rev = kwargs.pop('rev', rev) @@ -24,14 +75,33 @@ args, kwargs = parse_args(content) args += [None, None] path, limit, rev = args[:3] limit = kwargs.pop('limit', limit) rev = kwargs.pop('rev', rev) - - if 'CHANGESET_VIEW' not in req.perm: - return Markup('Changelog not available') - - repo = self.env.get_repository() + if ':' in path: + reponame, path = path.split(':', 2) + else: + reponame = '' + if '@' in path: + path, rev = path.split('@', 2) + repo = self.env.get_repository(reponame) + path = repo.normalize_path(path) + revstart = 0 + if rev is not None: + for d in [':', '-']: + if d in rev: + revstart, revstop = rev.split(d, 2) + if not revstop or revstop.lower() in ['head', '0']: + revstart = int(revstart) + rev = repo.get_youngest_rev() + limit = rev - revstart + 1 + else: + revstart, revstop = int(revstart), int(revstop) + if revstart > revstop: + revstart, revstop = revstop, revstart + limit = revstop - revstart + 1 + rev = revstop or None + break if rev is None: rev = repo.get_youngest_rev() rev = repo.normalize_rev(rev) @@ -34,11 +104,10 @@ if rev is None: rev = repo.get_youngest_rev() rev = repo.normalize_rev(rev) - path = repo.normalize_path(path) if limit is None: limit = 5 else: limit = int(limit) node = repo.get_node(path, rev) out = StringIO() @@ -39,8 +108,9 @@ if limit is None: limit = 5 else: limit = int(limit) node = repo.get_node(path, rev) out = StringIO() - out.write('
') # re-open surrounding paragraph return out.getvalue() @@ -53,1 +135,14 @@ return out.getvalue() + +# Utilities + +REMOVE_P = '^\s*
(.*?)
\s*$' +REMOVE_P_RE = re.compile(REMOVE_P, re.DOTALL) + +def _remove_p(html): + f = REMOVE_P_RE.findall(html) + if f: + return f[0] + else: + return html +