39
|
1 # -*- coding: utf-8 -*-
|
|
2 #
|
|
3 # Copyright (C) 2003-2006 Edgewall Software
|
|
4 # Copyright (C) 2003-2005 Jonas Borgström <jonas@edgewall.com>
|
|
5 # Copyright (C) 2005-2006 Christian Boos <cboos@neuf.fr>
|
|
6 # All rights reserved.
|
|
7 #
|
|
8 # This software is licensed as described in the file COPYING, which
|
|
9 # you should have received as part of this distribution. The terms
|
|
10 # are also available at http://trac.edgewall.com/license.html.
|
|
11 #
|
|
12 # This software consists of voluntary contributions made by many
|
|
13 # individuals. For the exact contribution history, see the revision
|
|
14 # history and logs, available at http://projects.edgewall.com/trac/.
|
|
15 #
|
|
16 # Author: Jonas Borgström <jonas@edgewall.com>
|
|
17 # Christian Boos <cboos@neuf.fr>
|
|
18
|
|
19 import re
|
|
20 import urllib
|
|
21
|
|
22 from trac.core import TracError
|
|
23 from trac.util.datefmt import format_datetime, pretty_timedelta
|
|
24 from trac.util.text import shorten_line
|
|
25 from trac.util.markup import escape, html, Markup
|
|
26 from trac.versioncontrol.api import NoSuchNode, NoSuchChangeset
|
|
27 from trac.wiki import wiki_to_html, wiki_to_oneliner
|
|
28
|
|
29 __all__ = ['get_changes', 'get_path_links', 'get_path_rev_line',
|
|
30 'get_existing_node', 'render_node_property']
|
|
31
|
|
32 def get_changes(env, repos, revs, full=None, req=None, format=None):
|
|
33 db = env.get_db_cnx()
|
|
34 changes = {}
|
|
35 for rev in revs:
|
|
36 try:
|
|
37 changeset = repos.get_changeset(rev)
|
|
38 except NoSuchChangeset:
|
|
39 changes[rev] = {}
|
|
40 continue
|
|
41
|
|
42 wiki_format = env.config['changeset'].getbool('wiki_format_messages')
|
|
43 message = changeset.message or '--'
|
|
44 absurls = (format == 'rss')
|
|
45 if wiki_format:
|
|
46 shortlog = wiki_to_oneliner(message, env, db,
|
|
47 shorten=True, absurls=absurls)
|
|
48 else:
|
|
49 shortlog = Markup.escape(shorten_line(message))
|
|
50
|
|
51 if full:
|
|
52 if wiki_format:
|
|
53 message = wiki_to_html(message, env, req, db,
|
|
54 absurls=absurls, escape_newlines=True)
|
|
55 else:
|
|
56 message = html.PRE(message)
|
|
57 else:
|
|
58 message = shortlog
|
|
59
|
|
60 if format == 'rss':
|
|
61 if isinstance(shortlog, Markup):
|
|
62 shortlog = shortlog.plaintext(keeplinebreaks=False)
|
|
63 message = unicode(message)
|
|
64
|
|
65 changes[rev] = {
|
|
66 'date_seconds': changeset.date,
|
|
67 'date': format_datetime(changeset.date),
|
|
68 'age': pretty_timedelta(changeset.date),
|
|
69 'author': changeset.author or 'anonymous',
|
|
70 'message': message, 'shortlog': shortlog,
|
|
71 }
|
|
72 return changes
|
|
73
|
|
74 def get_path_links(href, path, rev):
|
|
75 links = []
|
|
76 parts = path.split('/')
|
|
77 if not parts[-1]:
|
|
78 parts.pop()
|
|
79 path = '/'
|
|
80 for part in parts:
|
|
81 path = path + part + '/'
|
|
82 links.append({
|
|
83 'name': part or 'root',
|
|
84 'href': href.browser(path, rev=rev)
|
|
85 })
|
|
86 return links
|
|
87
|
|
88 rev_re = re.compile(r"([^@#:]*)[@#:]([^#]+)(?:#L(\d+))?")
|
|
89
|
|
90 def get_path_rev_line(path):
|
|
91 rev = None
|
|
92 line = None
|
|
93 match = rev_re.search(path)
|
|
94 if match:
|
|
95 path = match.group(1)
|
|
96 rev = match.group(2)
|
|
97 if match.group(3):
|
|
98 line = int(match.group(3))
|
|
99 path = urllib.unquote(path)
|
|
100 return path, rev, line
|
|
101
|
|
102 def get_existing_node(req, repos, path, rev):
|
|
103 try:
|
|
104 return repos.get_node(path, rev)
|
|
105 except NoSuchNode, e:
|
|
106 raise TracError(Markup('%s<br><p>You can <a href="%s">search</a> '
|
|
107 'in the repository history to see if that path '
|
|
108 'existed but was later removed.</p>', e.message,
|
|
109 req.href.log(path, rev=rev,
|
|
110 mode='path_history')))
|
|
111
|
|
112 def render_node_property(env, name, value):
|
|
113 """Renders a node property value to HTML.
|
|
114
|
|
115 Currently only handle multi-line properties. See also #1601.
|
|
116 """
|
|
117 if value and '\n' in value:
|
|
118 value = Markup(''.join(['<br />%s' % escape(v)
|
|
119 for v in value.split('\n')]))
|
|
120 return value
|