actions.py
来自「linux subdivision ying gai ke yi le ba」· Python 代码 · 共 789 行 · 第 1/2 页
PY
789 行
#!/usr/bin/env python
#
# actions.py: routines that actually run the svn client.
#
# Subversion is a tool for revision control.
# See http://subversion.tigris.org for more information.
#
# ====================================================================
# Copyright (c) 2000-2004 CollabNet. All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://subversion.tigris.org/license-1.html.
# If newer versions of this license are posted there, you may use a
# newer version instead, at your option.
#
######################################################################
import os.path, shutil, string, re, sys
import main, tree, wc # general svntest routines in this module.
from svntest import Failure, SVNAnyOutput
class SVNUnexpectedOutput(Failure):
"""Exception raised if an invocation of svn results in unexpected
output of any kind."""
pass
class SVNUnexpectedStdout(SVNUnexpectedOutput):
"""Exception raised if an invocation of svn results in unexpected
output on STDOUT."""
pass
class SVNUnexpectedStderr(SVNUnexpectedOutput):
"""Exception raised if an invocation of svn results in unexpected
output on STDERR."""
pass
class SVNExpectedStdout(SVNUnexpectedOutput):
"""Exception raised if an invocation of svn results in no output on
STDOUT when output was expected."""
pass
class SVNExpectedStderr(SVNUnexpectedOutput):
"""Exception raised if an invocation of svn results in no output on
STDERR when output was expected."""
pass
class SVNIncorrectDatatype(SVNUnexpectedOutput):
"""Exception raised if invalid input is passed to the
run_and_verify_* API"""
pass
######################################################################
# Used by every test, so that they can run independently of
# one another. The first time it's run, it executes 'svnadmin' to
# create a repository and then 'svn imports' the greek tree.
# Thereafter, every time this routine is called, it recursively copies
# the `pristine repos' to a new location.
def guarantee_greek_repository(path):
"""Guarantee that a local svn repository exists at PATH, containing
nothing but the greek-tree at revision 1."""
if path == main.pristine_dir:
print "ERROR: attempt to overwrite the pristine repos! Aborting."
sys.exit(1)
# If there's no pristine repos, create one.
if not os.path.exists(main.pristine_dir):
main.create_repos(main.pristine_dir)
# dump the greek tree to disk.
main.greek_state.write_to_disk(main.greek_dump_dir)
# build a URL for doing an import.
url = main.test_area_url + '/' + main.pristine_dir
if main.windows == 1:
url = string.replace(url, '\\', '/')
# import the greek tree, using l:foo/p:bar
### todo: svn should not be prompting for auth info when using
### repositories with no auth/auth requirements
output, errput = main.run_svn(None, 'import',
'--username', main.wc_author,
'--password', main.wc_passwd,
'-m', 'Log message for revision 1.',
main.greek_dump_dir, url)
# check for any errors from the import
if len(errput):
display_lines("Errors during initial 'svn import':",
'STDERR', None, errput)
sys.exit(1)
# verify the printed output of 'svn import'.
lastline = string.strip(output.pop())
cm = re.compile ("(Committed|Imported) revision [0-9]+.")
match = cm.search (lastline)
if not match:
print "ERROR: import did not succeed, while creating greek repos."
print "The final line from 'svn import' was:"
print lastline
sys.exit(1)
output_tree = tree.build_tree_from_commit(output)
### due to path normalization in the .old_tree() method, we cannot
### prepend the necessary '.' directory. thus, let's construct an old
### tree manually from the greek_state.
output_list = []
for greek_path in main.greek_state.desc.keys():
output_list.append([ os.path.join(main.greek_dump_dir, greek_path),
None, {}, {'verb' : 'Adding'}])
expected_output_tree = tree.build_generic_tree(output_list)
try:
tree.compare_trees(output_tree, expected_output_tree)
except tree.SVNTreeUnequal:
display_trees("ERROR: output of import command is unexpected.",
'OUTPUT TREE', expected_output_tree, output_tree)
sys.exit(1)
# Now that the pristine repos exists, copy it to PATH.
main.safe_rmtree(path)
if main.copy_repos(main.pristine_dir, path, 1):
print "ERROR: copying repository failed."
sys.exit(1)
# make the repos world-writeable, for mod_dav_svn's sake.
main.chmod_tree(path, 0666, 0666)
def run_and_verify_svnversion(message, wc_dir, repo_url,
expected_stdout, expected_stderr):
"Run svnversion command and check its output"
out, err = main.run_svnversion(wc_dir, repo_url)
if type(expected_stdout) is type([]):
compare_and_display_lines(message, 'STDOUT', expected_stdout, out)
elif expected_stdout == SVNAnyOutput:
if len(out) == 0:
if message is not None: print message
raise SVNExpectedStdout
elif expected_stdout is not None:
raise SVNIncorrectDatatype("Unexpected specification for stdout data")
if type(expected_stderr) is type([]):
compare_and_display_lines(message, 'STDERR', expected_stderr, err)
elif expected_stderr == SVNAnyOutput:
if len(err) == 0:
if message is not None: print message
raise SVNExpectedStderr
elif expected_stderr is not None:
raise SVNIncorrectDatatype("Unexpected specification for stderr data")
return out, err
def run_and_verify_svn(message, expected_stdout, expected_stderr, *varargs):
"""Invokes main.run_svn with *VARARGS. If EXPECTED_STDOUT or
EXPECTED_STDERR is not 'None', invokes compare_and_display_lines
with MESSAGE and the expected output. If the comparison fails,
compare_and_display_lines will raise."""
### TODO catch and throw particular exceptions from above
want_err = None
if expected_stderr is not None and expected_stderr is not []:
want_err = 1
out, err = main.run_svn(want_err, *varargs)
if type(expected_stdout) is type([]):
compare_and_display_lines(message, 'STDOUT', expected_stdout, out)
elif expected_stdout == SVNAnyOutput:
if len(out) == 0:
if message is not None: print message
raise SVNExpectedStdout
elif expected_stdout is not None:
raise SVNIncorrectDatatype("Unexpected specification for stdout data")
if type(expected_stderr) is type([]):
compare_and_display_lines(message, 'STDERR', expected_stderr, err)
elif expected_stderr == SVNAnyOutput:
if len(err) == 0:
if message is not None: print message
raise SVNExpectedStderr
elif expected_stderr is not None:
raise SVNIncorrectDatatype("Unexpected specification for stderr data")
return out, err
######################################################################
# Subversion Actions
#
# These are all routines that invoke 'svn' in particular ways, and
# then verify the results by comparing expected trees with actual
# trees.
#
# For all the functions below, the OUTPUT_TREE and DISK_TREE args need
# to be created by feeding carefully constructed lists to
# tree.build_generic_tree(). A STATUS_TREE can be built by
# hand, or by editing the tree returned by get_virginal_state().
def run_and_verify_checkout(URL, wc_dir_name, output_tree, disk_tree,
singleton_handler_a = None,
a_baton = None,
singleton_handler_b = None,
b_baton = None):
"""Checkout the URL into a new directory WC_DIR_NAME.
The subcommand output will be verified against OUTPUT_TREE,
and the working copy itself will be verified against DISK_TREE.
SINGLETON_HANDLER_A and SINGLETON_HANDLER_B will be passed to
tree.compare_trees - see that function's doc string for more details.
Returns if successful and raise on failure."""
if isinstance(output_tree, wc.State):
output_tree = output_tree.old_tree()
if isinstance(disk_tree, wc.State):
disk_tree = disk_tree.old_tree()
# Remove dir if it's already there.
main.safe_rmtree(wc_dir_name)
# Checkout and make a tree of the output, using l:foo/p:bar
### todo: svn should not be prompting for auth info when using
### repositories with no auth/auth requirements
output, errput = main.run_svn (None, 'co',
'--username', main.wc_author,
'--password', main.wc_passwd,
URL, wc_dir_name)
mytree = tree.build_tree_from_checkout (output)
# Verify actual output against expected output.
tree.compare_trees (mytree, output_tree)
# Create a tree by scanning the working copy
mytree = tree.build_tree_from_wc (wc_dir_name)
# Verify expected disk against actual disk.
tree.compare_trees (mytree, disk_tree,
singleton_handler_a, a_baton,
singleton_handler_b, b_baton)
def run_and_verify_export(URL, export_dir_name, output_tree, disk_tree,
singleton_handler_a = None,
a_baton = None,
singleton_handler_b = None,
b_baton = None,
*args):
"""Export the URL into a new directory WC_DIR_NAME.
The subcommand output will be verified against OUTPUT_TREE,
and the exported copy itself will be verified against DISK_TREE.
SINGLETON_HANDLER_A and SINGLETON_HANDLER_B will be passed to
tree.compare_trees - see that function's doc string for more details.
Returns if successful and raise on failure."""
if isinstance(output_tree, wc.State):
output_tree = output_tree.old_tree()
if isinstance(disk_tree, wc.State):
disk_tree = disk_tree.old_tree()
# Export and make a tree of the output, using l:foo/p:bar
### todo: svn should not be prompting for auth info when using
### repositories with no auth/auth requirements
output, errput = main.run_svn (None, 'export',
'--username', main.wc_author,
'--password', main.wc_passwd,
URL, export_dir_name, *args)
mytree = tree.build_tree_from_checkout (output)
# Verify actual output against expected output.
tree.compare_trees (mytree, output_tree)
# Create a tree by scanning the working copy. Don't ignore
# the .svn directories so that we generate an error if they
# happen to show up.
mytree = tree.build_tree_from_wc (export_dir_name, ignore_svn=0)
# Verify expected disk against actual disk.
tree.compare_trees (mytree, disk_tree,
singleton_handler_a, a_baton,
singleton_handler_b, b_baton)
def verify_update(actual_output, wc_dir_name,
output_tree, disk_tree, status_tree,
singleton_handler_a, a_baton,
singleton_handler_b, b_baton,
check_props):
"""Verify update of WC_DIR_NAME.
The subcommand output (found in ACTUAL_OUTPUT) will be verified
against OUTPUT_TREE, and the working copy itself will be verified
against DISK_TREE. If optional STATUS_OUTPUT_TREE is given, then
'svn status' output will be compared. (This is a good way to check
that revision numbers were bumped.) SINGLETON_HANDLER_A and
SINGLETON_HANDLER_B will be passed to tree.compare_trees - see that
function's doc string for more details. If CHECK_PROPS is set, then
disk comparison will examine props. Returns if successful, raises
on failure."""
# Verify actual output against expected output.
tree.compare_trees (actual_output, output_tree)
# Create a tree by scanning the working copy
mytree = tree.build_tree_from_wc (wc_dir_name, check_props)
# Verify expected disk against actual disk.
tree.compare_trees (mytree, disk_tree,
singleton_handler_a, a_baton,
singleton_handler_b, b_baton)
# Verify via 'status' command too, if possible.
if status_tree:
run_and_verify_status(wc_dir_name, status_tree)
def run_and_verify_update(wc_dir_name,
output_tree, disk_tree, status_tree,
error_re_string = None,
singleton_handler_a = None,
a_baton = None,
singleton_handler_b = None,
b_baton = None,
check_props = 0,
*args):
"""Update WC_DIR_NAME. *ARGS are any extra optional args to the
update subcommand. NOTE: If *ARGS is specified at all, explicit
target paths must be passed in *ARGS as well (or a default `.' will
be chosen by the 'svn' binary). This allows the caller to update
many items in a single working copy dir, but still verify the entire
working copy dir.
If ERROR_RE_STRING, the update must exit with error, and the error
message must match regular expression ERROR_RE_STRING.
Else if ERROR_RE_STRING is None, then:
The subcommand output will be verified against OUTPUT_TREE, and the
working copy itself will be verified against DISK_TREE. If optional
STATUS_TREE is given, then 'svn status' output will be compared.
(This is a good way to check that revision numbers were bumped.)
SINGLETON_HANDLER_A and SINGLETON_HANDLER_B will be passed to
tree.compare_trees - see that function's doc string for more
details.
If CHECK_PROPS is set, then disk comparison will examine props.
Returns if successful, raises on failure."""
if isinstance(output_tree, wc.State):
output_tree = output_tree.old_tree()
if isinstance(disk_tree, wc.State):
disk_tree = disk_tree.old_tree()
if isinstance(status_tree, wc.State):
status_tree = status_tree.old_tree()
# Update and make a tree of the output.
if len(args):
output, errput = main.run_svn (error_re_string, 'up', *args)
else:
output, errput = main.run_svn (error_re_string, 'up', wc_dir_name, *args)
if (error_re_string):
rm = re.compile(error_re_string)
for line in errput:
match = rm.search(line)
if match:
return
raise main.SVNUnmatchedError
mytree = tree.build_tree_from_checkout (output)
verify_update (mytree, wc_dir_name,
output_tree, disk_tree, status_tree,
singleton_handler_a, a_baton,
singleton_handler_b, b_baton,
check_props)
def run_and_verify_merge(dir, rev1, rev2, url,
output_tree, disk_tree, status_tree, skip_tree,
error_re_string = None,
singleton_handler_a = None,
a_baton = None,
singleton_handler_b = None,
b_baton = None,
check_props = 0,
dry_run = 1,
*args):
"""Run 'svn merge -rREV1:REV2 URL DIR'
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?