886
888
:param universal_newlines: Convert CRLF => LF
888
890
env_changes = kwargs.get('env_changes', {})
891
process = self.start_bzr_subprocess(args, env_changes=env_changes)
892
# We distinguish between retcode=None and retcode not passed.
893
supplied_retcode = kwargs.get('retcode', 0)
894
return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
895
universal_newlines=kwargs.get('universal_newlines', False),
898
def start_bzr_subprocess(self, process_args, env_changes=None,
899
skip_if_plan_to_signal=False):
900
"""Start bzr in a subprocess for testing.
902
This starts a new Python interpreter and runs bzr in there.
903
This should only be used for tests that have a justifiable need for
904
this isolation: e.g. they are testing startup time, or signal
905
handling, or early startup code, etc. Subprocess code can't be
906
profiled or debugged so easily.
908
:param process_args: a list of arguments to pass to the bzr executable,
909
for example `['--version']`.
910
:param env_changes: A dictionary which lists changes to environment
911
variables. A value of None will unset the env variable.
912
The values must be strings. The change will only occur in the
913
child, so you don't need to fix the environment after running.
914
:param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
917
:returns: Popen object for the started process.
919
if skip_if_plan_to_signal:
920
if not getattr(os, 'kill', None):
921
raise TestSkipped("os.kill not available.")
923
if env_changes is None:
892
927
def cleanup_environment():
898
933
osutils.set_or_unset_env(env_var, value)
900
935
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
936
if not os.path.isfile(bzr_path):
937
# We are probably installed. Assume sys.argv is the right file
938
bzr_path = sys.argv[0]
904
941
# win32 subprocess doesn't support preexec_fn
905
942
# so we will avoid using it on all platforms, just to
906
943
# make sure the code path is used, and we don't break on win32
907
944
cleanup_environment()
908
process = Popen([sys.executable, bzr_path]+args,
909
stdout=PIPE, stderr=PIPE)
945
process = Popen([sys.executable, bzr_path] + list(process_args),
946
stdin=PIPE, stdout=PIPE, stderr=PIPE)
911
948
restore_environment()
913
out = process.stdout.read()
914
err = process.stderr.read()
916
if kwargs.get('universal_newlines', False):
951
def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
952
universal_newlines=False, process_args=None):
953
"""Finish the execution of process.
955
:param process: the Popen object returned from start_bzr_subprocess.
956
:param retcode: The status code that is expected. Defaults to 0. If
957
None is supplied, the status code is not checked.
958
:param send_signal: an optional signal to send to the process.
959
:param universal_newlines: Convert CRLF => LF
960
:returns: (stdout, stderr)
962
if send_signal is not None:
963
os.kill(process.pid, send_signal)
964
out, err = process.communicate()
966
if universal_newlines:
917
967
out = out.replace('\r\n', '\n')
918
968
err = err.replace('\r\n', '\n')
920
retcode = process.wait()
921
supplied_retcode = kwargs.get('retcode', 0)
922
if supplied_retcode is not None:
923
assert supplied_retcode == retcode
970
if retcode is not None and retcode != process.returncode:
971
if process_args is None:
972
process_args = "(unknown args)"
973
mutter('Output of bzr %s:\n%s', process_args, out)
974
mutter('Error for bzr %s:\n%s', process_args, err)
975
self.fail('Command bzr %s failed with retcode %s != %s'
976
% (process_args, retcode, process.returncode))
924
977
return [out, err]
926
979
def check_inventory_shape(self, inv, shape):
1213
1266
if relpath is not None and relpath != '.':
1214
1267
if not base.endswith('/'):
1215
1268
base = base + '/'
1216
base = base + urlutils.escape(relpath)
1269
# XXX: Really base should be a url; we did after all call
1270
# get_url()! But sometimes it's just a path (from
1271
# LocalAbspathServer), and it'd be wrong to append urlescaped data
1272
# to a non-escaped local path.
1273
if base.startswith('./') or base.startswith('/'):
1276
base += urlutils.escape(relpath)
1219
1279
def get_transport(self):
1240
1300
def make_bzrdir(self, relpath, format=None):
1242
url = self.get_url(relpath)
1243
mutter('relpath %r => url %r', relpath, url)
1244
segments = url.split('/')
1245
if segments and segments[-1] not in ('', '.'):
1246
parent = '/'.join(segments[:-1])
1247
t = get_transport(parent)
1302
# might be a relative or absolute path
1303
maybe_a_url = self.get_url(relpath)
1304
segments = maybe_a_url.rsplit('/', 1)
1305
t = get_transport(maybe_a_url)
1306
if len(segments) > 1 and segments[-1] not in ('', '.'):
1249
t.mkdir(segments[-1])
1250
1309
except errors.FileExists:
1252
1311
if format is None:
1253
format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
1254
# FIXME: make this use a single transport someday. RBC 20060418
1255
return format.initialize_on_transport(get_transport(relpath))
1312
format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
1313
return format.initialize_on_transport(t)
1256
1314
except errors.UninitializableFormat:
1257
1315
raise TestSkipped("Format %s is not initializable." % format)
1261
1319
made_control = self.make_bzrdir(relpath, format=format)
1262
1320
return made_control.create_repository(shared=shared)
1322
def make_branch_and_memory_tree(self, relpath):
1323
"""Create a branch on the default transport and a MemoryTree for it."""
1324
b = self.make_branch(relpath)
1325
return memorytree.MemoryTree.create_on_branch(b)
1264
1327
def make_branch_and_tree(self, relpath, format=None):
1265
1328
"""Create a branch on the transport and a tree locally.
1330
If the transport is not a LocalTransport, the Tree can't be created on
1331
the transport. In that case the working tree is created in the local
1332
directory, and the returned tree's branch and repository will also be
1335
This will fail if the original default transport for this test
1336
case wasn't backed by the working directory, as the branch won't
1337
be on disk for us to open it.
1339
:param format: The BzrDirFormat.
1340
:returns: the WorkingTree.
1269
1342
# TODO: always use the local disk path for the working tree,
1270
1343
# this obviously requires a format that supports branch references
1275
1348
return b.bzrdir.create_workingtree()
1276
1349
except errors.NotLocalUrl:
1277
# new formats - catch No tree error and create
1278
# a branch reference and a checkout.
1279
# old formats at that point - raise TestSkipped.
1280
# TODO: rbc 20060208
1281
return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
1350
# We can only make working trees locally at the moment. If the
1351
# transport can't support them, then reopen the branch on a local
1352
# transport, and create the working tree there.
1354
# Possibly we should instead keep
1355
# the non-disk-backed branch and create a local checkout?
1356
bd = bzrdir.BzrDir.open(relpath)
1357
return bd.create_workingtree()
1283
1359
def assertIsDirectory(self, relpath, transport):
1284
1360
"""Assert that relpath within transport is a directory.
1405
1481
'bzrlib.tests.test_errors',
1406
1482
'bzrlib.tests.test_escaped_store',
1407
1483
'bzrlib.tests.test_fetch',
1484
'bzrlib.tests.test_ftp_transport',
1408
1485
'bzrlib.tests.test_gpg',
1409
1486
'bzrlib.tests.test_graph',
1410
1487
'bzrlib.tests.test_hashcache',
1414
1491
'bzrlib.tests.test_ignores',
1415
1492
'bzrlib.tests.test_inv',
1416
1493
'bzrlib.tests.test_knit',
1494
'bzrlib.tests.test_lazy_import',
1417
1495
'bzrlib.tests.test_lockdir',
1418
1496
'bzrlib.tests.test_lockable_files',
1419
1497
'bzrlib.tests.test_log',
1498
'bzrlib.tests.test_memorytree',
1420
1499
'bzrlib.tests.test_merge',
1421
1500
'bzrlib.tests.test_merge3',
1422
1501
'bzrlib.tests.test_merge_core',
1441
1520
'bzrlib.tests.test_selftest',
1442
1521
'bzrlib.tests.test_setup',
1443
1522
'bzrlib.tests.test_sftp_transport',
1444
'bzrlib.tests.test_ftp_transport',
1445
1523
'bzrlib.tests.test_smart_add',
1524
'bzrlib.tests.test_smart_transport',
1446
1525
'bzrlib.tests.test_source',
1447
1526
'bzrlib.tests.test_status',
1448
1527
'bzrlib.tests.test_store',
1455
1534
'bzrlib.tests.test_transform',
1456
1535
'bzrlib.tests.test_transport',
1457
1536
'bzrlib.tests.test_tree',
1537
'bzrlib.tests.test_treebuilder',
1458
1538
'bzrlib.tests.test_tsort',
1459
1539
'bzrlib.tests.test_tuned_gzip',
1460
1540
'bzrlib.tests.test_ui',