Alien-SVN
view release on metacpan or search on metacpan
src/subversion/tools/dev/mergegraph/mergegraph.py view on Meta::CPAN
#!/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.
# ====================================================================
# Config file format:
example = """
[graph]
filename = merge-sync-1.png
title = Sync Merge: CC vs SVN
# Branches: (branch name, branched from node, first rev, last rev).
branches = [
('A', 'O0', 1, 4),
('O', None, 0, 0),
('B', 'O0', 1, 5)
]
# Changes: nodes in which a change was committed; merge targets need not
# be listed here.
changes = [
'A1', 'A2', 'A3', 'A4',
'B1', 'B2', 'B3', 'B4', 'B5'
]
# Merges: (base node, source-right node, target node, label).
# Base is also known as source-left.
merges = [
('O0', 'A:1', 'B3', 'sync'),
('A2', 'A:3', 'B5', 'sync'),
]
# Annotations for nodes: (node, annotation text).
annotations = [
('A2', 'cc:YCA')
]
"""
# Notes about different kinds of merge.
#
# A basic 3-way merge is ...
#
# The ClearCase style of merge is a 3-way merge.
#
# The Subversion style of merge (that is, one phase of a Subversion merge)
# is a three-way merge with its base (typically the YCA) on the source branch.
import sys
import pydot
from pydot import Node, Edge
def mergeinfo_to_node_list(mi):
"""Convert a mergeinfo string such as '/foo:1,3-5*' into a list of
node names such as ['foo1', 'foo3', 'foo4', 'foo5'].
"""
### Doesn't yet strip the leading slash.
l = []
if mi:
for mi_str in mi.split(' '):
path, ranges = mi_str.split(':')
for r in ranges.split(','):
if r.endswith('*'):
# TODO: store & use this 'non-inheritable' flag
# Remove the flag
r = r[:-1]
rlist = r.split('-')
r1 = int(rlist[0])
if len(rlist) == 2:
r2 = int(rlist[1])
else:
r2 = r1
src/subversion/tools/dev/mergegraph/mergegraph.py view on Meta::CPAN
'merges': '[]',
'annotations': '[]' })
files_read = config.read(config_filename)
if len(files_read) == 0:
print >> sys.stderr, 'graph: unable to read graph config from "' + config_filename + '"'
sys.exit(1)
graph.basename = config.get('graph', 'basename')
graph.title = config.get('graph', 'title')
graph.branches = eval(config.get('graph', 'branches'))
graph.changes = eval(config.get('graph', 'changes'))
graph.merges = eval(config.get('graph', 'merges'))
graph.annotations = eval(config.get('graph', 'annotations'))
def construct(graph):
""""""
# Origin nodes (done first, in an attempt to set the order)
for br, orig, r1, head in graph.branches:
name = br + '0'
if r1 > 0:
graph.mk_origin_node(name, br)
else:
graph.mk_node(name, label=br)
# Edges and target nodes for merges
for merge in graph.merges:
# Emphasize the last merge, as it's the important one
important = (merge == graph.merges[-1])
graph.add_merge(merge, important)
# Parallel edges for basic lines of descent
for br, orig, r1, head in graph.branches:
sub_g = MergeSubgraph(ordering='out')
for i in range(1, head + 1):
prev_n = br + str(i - 1)
this_n = br + str(i)
# Normal edges and nodes
if i < r1:
graph.mk_invis_node(this_n)
else:
graph.mk_node(this_n)
if i <= r1:
graph.mk_invis_edge(prev_n, this_n)
else:
graph.mk_edge(prev_n, this_n)
# Branch creation edges
if orig:
sub_g.mk_br_edge(orig, br + str(r1))
graph.add_subgraph(sub_g)
# Annotations
for node, label in graph.annotations:
graph.add_annotation(node, label)
# A title for the graph (added last so it goes at the top)
if graph.title:
graph.add_node(Node('title', shape='plaintext', label='"' + graph.title + '"'))
def save(graph, format='png', filename=None):
"""Save this merge graph to the given file format. If filename is None,
construct a filename from the basename of the original file (as passed
to the constructor and then stored in graph.basename) and the suffix
according to the given format.
"""
if not filename:
filename = graph.basename + '.' + format
if format == 'sh':
import save_as_sh
save_as_sh.write_sh_file(graph, filename)
else:
pydot.Dot.write(graph, filename, format=format)
( run in 1.875 second using v1.01-cache-2.11-cpan-df04353d9ac )