#NEWLINE# def make_log_graph( repos , revs ) : #NEWLINE# #INDENT# 'Generate graph information for the given revisions.\n\n    Returns a tuple `(threads, vertices, columns)`, where:\n\n     * `threads`: List of paint command lists `[(type, column, line)]`, where\n       `type` is either 0 for "move to" or 1 for "line to", and `column` and\n       `line` are coordinates.\n     * `vertices`: List of `(column, thread_index)` tuples, where the `i`th\n       item specifies the column in which to draw the dot in line `i` and the\n       corresponding thread.\n     * `columns`: Maximum width of the graph.\n    ' #NEWLINE# threads = [ ] #NEWLINE# vertices = [ ] #NEWLINE# columns = 0 #NEWLINE# revs = iter ( revs ) #NEWLINE# def add_edge( thread , column , line ) : #NEWLINE# #INDENT# if ( thread and ( thread [ ( - 1 ) ] [ : 2 ] == [ 1 , column ] ) and ( thread [ ( - 2 ) ] [ 1 ] == column ) ) : #NEWLINE# #INDENT# thread [ ( - 1 ) ] [ 2 ] = line #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# thread . append ( [ 1 , column , line ] ) #NEWLINE# #UNINDENT# #UNINDENT# try : #NEWLINE# #INDENT# next_rev = revs . next ( ) #NEWLINE# line = 0 #NEWLINE# active = [ ] #NEWLINE# active_thread = [ ] #NEWLINE# while True : #NEWLINE# #INDENT# rev = next_rev #NEWLINE# if ( rev not in active ) : #NEWLINE# #INDENT# threads . append ( [ [ 0 , len ( active ) , line ] ] ) #NEWLINE# active_thread . append ( threads [ ( - 1 ) ] ) #NEWLINE# active . append ( rev ) #NEWLINE# #UNINDENT# columns = max ( columns , len ( active ) ) #NEWLINE# column = active . index ( rev ) #NEWLINE# vertices . append ( ( column , threads . index ( active_thread [ column ] ) ) ) #NEWLINE# next_rev = revs . next ( ) #NEWLINE# next = active [ : ] #NEWLINE# parents = list ( repos . parent_revs ( rev ) ) #NEWLINE# new_parents = [ p for p in parents if ( p not in active ) ] #NEWLINE# next [ column : ( column + 1 ) ] = new_parents #NEWLINE# for ( col , ( r , thread ) ) in enumerate ( izip ( active , active_thread ) ) : #NEWLINE# #INDENT# if ( r in next ) : #NEWLINE# #INDENT# add_edge ( thread , next . index ( r ) , ( line + 1 ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( r == rev ) : #NEWLINE# #INDENT# if new_parents : #NEWLINE# #INDENT# parents . remove ( new_parents [ 0 ] ) #NEWLINE# parents . append ( new_parents [ 0 ] ) #NEWLINE# #UNINDENT# for parent in parents : #NEWLINE# #INDENT# if ( parent != parents [ 0 ] ) : #NEWLINE# #INDENT# thread . append ( [ 0 , col , line ] ) #NEWLINE# #UNINDENT# add_edge ( thread , next . index ( parent ) , ( line + 1 ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# if ( not new_parents ) : #NEWLINE# #INDENT# del active_thread [ column ] #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# base = len ( threads ) #NEWLINE# threads . extend ( ( [ [ 0 , ( ( column + 1 ) + i ) , ( line + 1 ) ] ] for i in xrange ( ( len ( new_parents ) - 1 ) ) ) ) #NEWLINE# active_thread [ ( column + 1 ) : ( column + 1 ) ] = threads [ base : ] #NEWLINE# #UNINDENT# active = next #NEWLINE# line += 1 #NEWLINE# #UNINDENT# #UNINDENT# except StopIteration : #NEWLINE# #INDENT# pass #NEWLINE# #UNINDENT# return ( threads , vertices , columns )