blob: c5124cae8f7212c3df00549d4558e31a33e5d7ee [file] [log] [blame]
#!/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):
out.write('#!/bin/sh\n')
def command(out, cmd, *args):
"""Write the shell command CMD with the arguments ARGS to the file-like
object OUT.
"""
out.write(' '.join((cmd,) + args) + "\n")
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.
"""
out.write('# %s\n' % 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()