#!/usr/bin/env python

# ====================================================================
#    Licensed to the Apache Software Foundation (ASF) under one
#    or more contributor license agreements.  See the NOTICE file
#    distributed with this work for additional information
#    regarding copyright ownership.  The ASF licenses this file
#    to you under the Apache License, Version 2.0 (the
#    "License"); you may not use this file except in compliance
#    with the License.  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing,
#    software distributed under the License is distributed on an
#    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#    KIND, either express or implied.  See the License for the
#    specific language governing permissions and limitations
#    under the License.
# ====================================================================


# This module writes a sequence of 'svn' commands to a file, that when
# run will perform the branching and merging described by a given MergeDot
# graph description object.


def shebang_line(out):
  print >> out, '#!/bin/sh'

def command(out, cmd, *args):
  """Write the shell command CMD with the arguments ARGS to the file-like
     object OUT.
  """
  print >> out, ' '.join((cmd,) + args)

def svn(out, subcmd, *args):
  """Write an svn command with the given subcommand and arguments.  Write
     to the file-like object OUT.
  """
  command(out, 'svn', subcmd, *args)

def comment(out, text):
  """Write the comment TEXT to the file-like object OUT.
  """
  print >> out, '#', text

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(revs, 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))

def write_recipe(graph, out):
  """Write out a sequence of svn commands that will execute the branching
     and merging shown in GRAPH.  Write to the file-like object OUT.
  """
  revs = {}  # keyed by revnum

  for br, orig, r1, head in graph.branches:
    if orig:
      add(revs, br + str(r1), 'copy', orig, br)
    else:
      add(revs, br + str(r1), 'mkproj', br)

  for base_node, src_node, tgt_node, kind in graph.merges:
    add(revs, 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(revs, node_name, 'modify', node_name)

  # Execute the actions for each revision in turn.
  for r in sorted(revs.keys()):
    comment(out, 'start r' + str(r))
    for action, params in revs[r]:
      #comment(out, '(' + action + ' ' + params + ')')
      if action == 'mkproj':
        (br,) = params
        svn(out, 'mkdir', br, br + '/created_in_' + br)
      elif action == 'copy':
        (orig, br) = params
        svn(out, 'copy', '-r' + str(node_rev(orig)), node_branch(orig), br)
      elif action == 'modify':
        (node_name,) = params
        svn(out, '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(out, 'update')
        if kind == 'cherry':
          svn(out, 'merge',
              '-c' + str(node_rev(src_node)), node_url(src_node),
              node_branch(tgt_node))
        elif kind.startswith('reint'):
          svn(out, 'merge', '--reintegrate',
              node_url(src_node) + '@' + str(node_rev(src_node)),
              node_branch(tgt_node))
        else:
          svn(out, 'merge',
              node_url(src_node) + '@' + str(node_rev(src_node)),
              node_branch(tgt_node))
      else:
        raise Exception('unknown action: %s' % action)
    svn(out, 'commit', '-m', 'r' + str(r))

def write_sh_file(graph, filename):
  """Write a file containing a sequence of 'svn' commands that when run will
     perform the branching and merging described by the MergeDot object
     GRAPH.  Write to a new file named FILENAME.
  """
  out_stream = open(filename, 'w')
  shebang_line(out_stream)
  write_recipe(graph, out_stream)
  out_stream.close()
