Index: trac/versioncontrol/api.py =================================================================== --- trac/versioncontrol/api.py (revision 4673) +++ trac/versioncontrol/api.py (working copy) @@ -178,6 +178,10 @@ """ raise NotImplementedError + def get_revision(self, path, rev=None): + """Retrieve a Revision object of the node at path and rev.""" + raise NotImplementedError + def get_oldest_rev(self): """Return the oldest revision stored in the repository.""" raise NotImplementedError @@ -258,7 +262,37 @@ """ raise NotImplementedError +class Revision(object): + """Represents a revision from a repository.""" + + def __init__(self, base_path, rev_str, message, author, date): + self.base_path = base_path + self.rev_str = rev_str + self.message = message + self.author = author + self.date = date + def get_node(self, path): + """Retrieve a Node at the given path and this revision. + + A Node represents a directory or a file at a given revision in the + repository. + """ + raise NotImplementedError + + def get_changeset(self, path): + """Retrieve a Changeset corresponding to the this revision and possibly + restricted to the given path.""" + raise NotImplementedError + + def get_properties(self): + """Returns the properties (meta-data) of the node, as a dictionary. + + The set of properties depends on the version control system. + """ + raise NotImplementedError + + class Node(object): """Represents a directory or file in the repository at a given revision.""" Index: trac/versioncontrol/web_ui/browser.py =================================================================== --- trac/versioncontrol/web_ui/browser.py (revision 4673) +++ trac/versioncontrol/web_ui/browser.py (working copy) @@ -93,12 +93,7 @@ # Find node for the requested path/rev repos = self.env.get_repository(req.authname) - if rev: - rev = repos.normalize_rev(rev) - # If `rev` is `None`, we'll try to reuse `None` consistently, - # as a special shortcut to the latest revision. - rev_or_latest = rev or repos.youngest_rev - node = get_existing_node(req, repos, path, rev_or_latest) + node = get_existing_node(req, repos, path, rev) # Rendered list of node properties hidden_properties = self.hidden_properties @@ -117,7 +112,7 @@ 'href': req.href.browser(path, rev=rev), 'log_href': req.href.log(path, rev=rev), 'restr_changeset_href': req.href.changeset(node.rev, - node.created_path), + node.path), 'anydiff_href': req.href.anydiff(), } @@ -142,6 +137,7 @@ # Entries metadata info = [] + revisions = {} for entry in node.get_entries(): info.append({ 'name': entry.name, @@ -153,7 +149,10 @@ 'log_href': req.href.log(entry.path, rev=rev), 'browser_href': req.href.browser(entry.path, rev=rev) }) - changes = get_changes(self.env, repos, [i['rev'] for i in info]) + # May not work correctly in root because two branches may have the same rev: + if not revisions.has_key(entry.rev): + revisions[entry.rev] = entry.get_revision() + changes = get_revisions_properties(self.env, repos, revisions.values()) # Ordering of entries order = req.args.get('order', 'name').lower() Index: trac/versioncontrol/web_ui/log.py =================================================================== --- trac/versioncontrol/web_ui/log.py (revision 4673) +++ trac/versioncontrol/web_ui/log.py (working copy) @@ -72,12 +72,11 @@ limit = LOG_LIMIT repos = self.env.get_repository(req.authname) - normpath = repos.normalize_path(path) - rev = unicode(repos.normalize_rev(rev)) + node = repos.get_node(path, rev) + rev = node.rev + node_history = node.get_history(limit+1, stop_rev) if stop_rev: - stop_rev = unicode(repos.normalize_rev(stop_rev)) - if repos.rev_older_than(rev, stop_rev): - rev, stop_rev = stop_rev, rev + stop_rev = node_history[-1].rev req.hdf['title'] = path + ' (log)' req.hdf['log'] = { @@ -96,42 +95,31 @@ if path_links: add_link(req, 'up', path_links[-1]['href'], 'Parent directory') - # The `history()` method depends on the mode: - # * for ''stop on copy'' and ''follow copies'', it's `Node.history()` - # * for ''show only add, delete'' it's`Repository.get_path_history()` - if mode == 'path_history': - def history(limit): - for h in repos.get_path_history(path, rev, limit): - yield h - else: - history = get_existing_node(req, repos, path, rev).get_history - # -- retrieve history, asking for limit+1 results info = [] - previous_path = repos.normalize_path(path) - for old_path, old_rev, old_chg in history(limit+1): - if stop_rev and repos.rev_older_than(old_rev, stop_rev): - break - old_path = repos.normalize_path(old_path) + revisions = {} + previous_path = node.path + for node in node_history: + old_chg = 'modified' #\todo item = { - 'rev': str(old_rev), - 'path': old_path, - 'log_href': req.href.log(old_path, rev=old_rev), - 'browser_href': req.href.browser(old_path, rev=old_rev), - 'changeset_href': req.href.changeset(old_rev), - 'restricted_href': req.href.changeset(old_rev, new_path=old_path), + 'rev': node.rev, + 'path': node.path, + 'log_href': req.href.log(node.path, rev=node.rev), + 'browser_href': req.href.browser(node.path, rev=node.rev), + 'changeset_href': req.href.changeset(node.rev, node.get_revision().base_path), + 'restricted_href': req.href.changeset(node.rev, new_path=node.path), 'change': old_chg } if not (mode == 'path_history' and old_chg == Changeset.EDIT): info.append(item) - if old_path and old_path != previous_path \ - and not (mode == 'path_history' and old_path == normpath): - item['copyfrom_path'] = old_path + if node.path and node.path != previous_path \ + and not (mode == 'path_history' and old_path == normpath): #this maybe is never avaluated + item['copyfrom_path'] = node.rev if mode == 'stop_on_copy': break - if len(info) > limit: # we want limit+1 entries - break - previous_path = old_path + previous_path = node.path + if not revisions.has_key(node.rev): + revisions[node.rev] = node.get_revision() if info == []: # FIXME: we should send a 404 error here raise TracError("The file or directory '%s' doesn't exist " @@ -159,8 +147,7 @@ req.hdf['log.items'] = info - revs = [i['rev'] for i in info] - changes = get_changes(self.env, repos, revs, verbose, req, format) + changes = get_revisions_properties(self.env, repos, revisions.values(), verbose, req, format) if format == 'rss': # Get the email addresses of all known users email_map = {} Index: trac/versioncontrol/web_ui/util.py =================================================================== --- trac/versioncontrol/web_ui/util.py (revision 4673) +++ trac/versioncontrol/web_ui/util.py (working copy) @@ -26,21 +26,17 @@ from trac.versioncontrol.api import NoSuchNode, NoSuchChangeset from trac.wiki import wiki_to_html, wiki_to_oneliner -__all__ = ['get_changes', 'get_path_links', 'get_path_rev_line', +__all__ = ['get_revisions_properties', 'get_path_links', 'get_path_rev_line', 'get_existing_node', 'render_node_property'] -def get_changes(env, repos, revs, full=None, req=None, format=None): +def get_revisions_properties(env, repos, revisions, full=None, req=None, format=None): db = env.get_db_cnx() - changes = {} - for rev in revs: - try: - changeset = repos.get_changeset(rev) - except NoSuchChangeset: - changes[rev] = {} - continue - + properties = {} + for revision in revisions: + if not revision: + continue # \todo don't let Nones here wiki_format = env.config['changeset'].getbool('wiki_format_messages') - message = changeset.message or '--' + message = revision.message or '--' absurls = (format == 'rss') if wiki_format: shortlog = wiki_to_oneliner(message, env, db, @@ -62,14 +58,14 @@ shortlog = shortlog.plaintext(keeplinebreaks=False) message = unicode(message) - changes[rev] = { - 'date_seconds': changeset.date, - 'date': format_datetime(changeset.date), - 'age': pretty_timedelta(changeset.date), - 'author': changeset.author or 'anonymous', + properties[revision.rev_str] = { + 'date_seconds': revision.date, + 'date': format_datetime(revision.date), + 'age': pretty_timedelta(revision.date), + 'author': revision.author or 'anonymous', 'message': message, 'shortlog': shortlog, } - return changes + return properties def get_path_links(href, fullpath, rev): links = [{'name': 'root', 'href': href.browser(rev=rev)}] @@ -95,7 +91,7 @@ def get_existing_node(req, repos, path, rev): try: - return repos.get_node(path, rev) + return repos.get_node(path, rev) except NoSuchNode, e: raise TracError(Markup('%s

You can search ' 'in the repository history to see if that path '