#!/usr/bin/env python
"""
A Mercurial extension that provides a recursive tree/listing of the files and
their last modified revision.
"""
# This should work with Mercurial 1.1.

# stdlib imports
import os
from operator import itemgetter
from os.path import *

# mercurial imports
from mercurial import hg, cmdutil


def treeify(filenames):
    """
    Create a tree of dictionaries corresponding to the hierarchy of the given
    list of filenames. Return a dictionary whose keys are the file or directory
    names and whose values are either None (for files), or another dictionary
    (for subdirectories).
    """
    root = {}
    for fn in filenames:
        comps = fn.split(os.sep)
        addnode(comps, root, fn)
    return root

def addnode(comps, dir, leaf):
    "Add a node from the components 'comps' to the directory dictionary."
    beg, rest = comps[0], comps[1:]
    if not rest:
        dir[beg] = leaf
    else:
        try:
            sd = dir[beg]
        except KeyError:
            sd = dir[beg] = {}
        # Recurse one component down.
        return addnode(comps[1:], sd, leaf)

def render_tree(root, rootname='.'):
    "Render a tree of dictionaries as outlined above in treeify."
    lines = [(None, rootname)]
    render_node(root, [], lines)
    return lines

def render_node(node, pre, lines):
    "Render a dictionary node (recursively)."
    for i, (name, sub) in enumerate(sorted(node.iteritems())):
        last = (i == len(node)-1)
        if last:
            patcont = '`-- '
        else:
            patcont = '|-- '
        if last:
            patpref = '    '
        else:
            patpref = '|   '
        isdir = isinstance(sub, dict)

        if not isdir:
            fn = sub
        else:
            fn = None
        lines.append( (fn, ''.join(pre) + patcont + name) )
        if isdir:
            render_node(sub, pre + [patpref], lines)



def do_tree(ui, repo, *pats, **opts):
    # The doc string below will show up in hg help
    """Display tree of files with information about last modified user/time."""

    # Find all of the matched files.
    matcher = cmdutil.match(repo, pats, opts)
    filenames = repo.walk(match=matcher)

    # Build a tree of nodes from the list of filenames.
    root = treeify(filenames)

    tlines = render_tree(root)
    width = max(len(ln) for fn, ln in tlines if ln is not None)
    fmt = '%%-%ds  %%s' % width

    #w = repo.workingctx()
    c = repo.changectx("tip")
    rev = c.rev()
    for fn, ln in tlines:
        if fn is not None:
            ## info = w.filectx(fn).rev()
            info = repo.file(fn).index[-2]
        else:
            info = ''
        print fmt % (ln, info)


cmdtable = {
    "tree": (do_tree, [],
             "hg tree [options] [node]")
}

