
* tools/dev/merge-graph.py

--This line, and those below, will be ignored--

Index: tools/dev/merge-graph.py
===================================================================
--- tools/dev/merge-graph.py	(revision 1343819)
+++ tools/dev/merge-graph.py	(working copy)
@@ -29,6 +29,87 @@ import getopt
 from mergegraph import MergeDot
 
 
+def svn(subcmd, *args):
+  """Run svn with the given subcommand and arguments"""
+  print 'svn', subcmd, ' '.join(args)
+
+def write_recipe(graph):
+  """Write out a sequence of svn commands that will execute the branching
+     and merging shown in GRAPH."""
+  revs = {}  # keyed by revnum
+
+  def node_branch(node_name):
+    """Extract branch name from a node name.
+       ### TODO: multi-char names."""
+    return node_name[:1]
+
+  def node_url(node_name):
+    """Extract the URL (in command-line repo-relative URL syntax) from a
+       node name."""
+    return '^/' + node_branch(node_name)
+
+  def node_rev(node_name):
+    """Extract revnum (as an integer) from a node name.
+       ### TODO: multi-char names."""
+    return int(node_name[1:]) + 1
+
+  def add(node_name, action, *args):
+    """Add the tuple (ACTION, (ARGS)) to the list REVS[REVNUM]."""
+    revnum = node_rev(node_name)
+    if not revnum in revs:
+      revs[revnum] = []
+    revs[revnum].append((action, args))
+
+  for br, orig, r1, head in graph.branches:
+    if orig:
+      add(br + str(r1), 'copy', orig, br)
+    else:
+      add(br + str(r1), 'mkproj', br)
+
+  for base_node, src_node, tgt_node, kind in graph.merges:
+    add(tgt_node, 'merge', src_node, tgt_node, kind)
+
+  for node_name in graph.changes:
+    # Originally the 'changes' list could have entries that overlapped with
+    # merges. We must either disallow that or filter out such changes here.
+    #if not node_name in revs:
+    add(node_name, 'modify', node_name)
+
+  # Execute the actions for each revision in turn.
+  for r in sorted(revs.keys()):
+    print '# start r' + str(r)
+    for action, params in revs[r]:
+      print '# (', action, params, ')'
+      if action == 'mkproj':
+        (br,) = params
+        svn('mkdir', br, br + '/created_in_' + br)
+      elif action == 'copy':
+        (orig, br) = params
+        svn('copy', '-r' + str(node_rev(orig)), node_branch(orig), br)
+      elif action == 'modify':
+        (node_name,) = params
+        svn('mkdir', node_branch(node_name) + '/new_in_' + node_name)
+      elif action == 'merge':
+        (src_node, tgt_node, kind) = params
+        assert node_rev(tgt_node) == r
+        svn('update')
+        if kind == 'cherry':
+          svn('merge',
+              '-c' + str(node_rev(src_node)), node_url(src_node),
+              node_branch(tgt_node))
+        elif kind.startswith('reint'):
+          svn('merge', '--reintegrate',
+              node_url(src_node) + '@' + str(node_rev(src_node)),
+              node_branch(tgt_node))
+        else:
+          svn('merge',
+              node_url(src_node) + '@' + str(node_rev(src_node)),
+              node_branch(tgt_node))
+      else:
+        raise 'unknown action: %s' % action
+    svn('commit', '-m', 'r' + str(r))
+
+
 # If run as a program, process each input filename as a graph config file.
 if __name__ == '__main__':
   optlist, args = getopt.getopt(sys.argv[1:], 'f:', ['format'])
@@ -56,3 +137,6 @@ if __name__ == '__main__':
       print "writing '%s'" % filename,
       graph.save(format=format, filename=filename)
     print
+
+    write_recipe(graph)
+
