1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
132
132
self._format = _format
133
133
self.bzrdir = _bzrdir
134
assert isinstance(basedir, basestring), \
135
"base directory %r is not a string" % basedir
134
136
basedir = safe_unicode(basedir)
135
137
mutter("opening working tree %r", basedir)
136
138
self._branch = branch
139
assert isinstance(self.branch, bzrlib.branch.Branch), \
140
"branch %r is not a Branch" % self.branch
137
141
self.basedir = realpath(basedir)
138
142
# if branch is at our basedir and is a format 6 or less
139
143
# assume all other formats have their own control files.
144
assert isinstance(_control_files, LockableFiles), \
145
"_control_files must be a LockableFiles, not %r" % _control_files
140
146
self._control_files = _control_files
141
self._transport = self._control_files._transport
142
147
self._dirty = None
144
149
# during a read or write lock these objects are set, and are
313
316
state._read_dirblocks_if_needed()
314
317
root_key, current_entry = self._get_entry(path='')
315
318
current_id = root_key[2]
316
if not (current_entry[0][0] == 'd'): # directory
317
raise AssertionError(current_entry)
319
assert current_entry[0][0] == 'd' # directory
318
320
inv = Inventory(root_id=current_id)
319
321
# Turn some things into local variables
320
322
minikind_to_kind = dirstate.DirState._minikind_to_kind
353
355
# add this entry to the parent map.
354
356
parent_ies[(dirname + '/' + name).strip('/')] = inv_entry
355
357
elif kind == 'tree-reference':
356
if not self._repo_supports_tree_reference:
357
raise AssertionError(
359
"doesn't support tree references "
360
"required by entry %r"
358
assert self._repo_supports_tree_reference, \
359
"repository of %r " \
360
"doesn't support tree references " \
361
"required by entry %r" \
362
363
inv_entry.reference_revision = link_or_sha1 or None
363
364
elif kind != 'symlink':
364
365
raise AssertionError("unknown kind %r" % kind)
365
366
# These checks cost us around 40ms on a 55k entry tree
366
if file_id in inv_byid:
367
raise AssertionError('file_id %s already in'
368
' inventory as %s' % (file_id, inv_byid[file_id]))
369
if name_unicode in parent_ie.children:
370
raise AssertionError('name %r already in parent'
367
assert file_id not in inv_byid, ('file_id %s already in'
368
' inventory as %s' % (file_id, inv_byid[file_id]))
369
assert name_unicode not in parent_ie.children
372
370
inv_byid[file_id] = inv_entry
373
371
parent_ie.children[name_unicode] = inv_entry
374
372
self._inventory = inv
496
494
Note: The caller is expected to take a read-lock before calling this.
498
self._must_be_locked()
500
497
path = self.id2path(file_id)
501
498
mode = os.lstat(self.abspath(path)).st_mode
502
499
return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
504
def all_file_ids(self):
505
"""See Tree.iter_all_file_ids"""
506
self._must_be_locked()
508
for key, tree_details in self.current_dirstate()._iter_entries():
509
if tree_details[0][0] in ('a', 'r'): # relocated
515
502
def __iter__(self):
516
503
"""Iterate through file_ids for this tree.
529
516
return iter(result)
531
518
def iter_references(self):
532
if not self._repo_supports_tree_reference:
533
# When the repo doesn't support references, we will have nothing to
536
519
for key, tree_details in self.current_dirstate()._iter_entries():
537
520
if tree_details[0][0] in ('a', 'r'): # absent, relocated
538
521
# not relevant to the working tree
541
524
# the root is not a reference.
543
relpath = pathjoin(key[0].decode('utf8'), key[1].decode('utf8'))
526
path = pathjoin(self.basedir, key[0].decode('utf8'), key[1].decode('utf8'))
545
if self._kind(relpath) == 'tree-reference':
546
yield relpath, key[2]
528
if self._kind(path) == 'tree-reference':
547
530
except errors.NoSuchFile:
548
531
# path is missing on disk.
557
540
Note: The caller is expected to take a read-lock before calling this.
559
542
relpath = self.id2path(file_id)
561
raise AssertionError(
562
"path for id {%s} is None!" % file_id)
543
assert relpath != None, \
544
"path for id {%s} is None!" % file_id
563
545
return self._kind(relpath)
565
547
def _kind(self, relpath):
638
620
if not from_paths:
640
623
state = self.current_dirstate()
641
if isinstance(from_paths, basestring):
625
assert not isinstance(from_paths, basestring)
643
626
to_dir_utf8 = to_dir.encode('utf8')
644
627
to_entry_dirname, to_basename = os.path.split(to_dir_utf8)
645
628
id_index = state._get_id_index()
800
783
if minikind == 'd':
801
784
def update_dirblock(from_dir, to_key, to_dir_utf8):
802
785
"""Recursively update all entries in this dirblock."""
804
raise AssertionError("renaming root not supported")
786
assert from_dir != '', "renaming root not supported"
805
787
from_key = (from_dir, '')
806
788
from_block_idx, present = \
807
789
state._find_block_index_from_key(from_key)
821
803
# Grab a copy since move_one may update the list.
822
804
for entry in from_block[1][:]:
823
if not (entry[0][0] == from_dir):
824
raise AssertionError()
805
assert entry[0][0] == from_dir
825
806
cur_details = entry[1][0]
826
807
to_key = (to_dir_utf8, entry[0][1], entry[0][2])
827
808
from_path_utf8 = osutils.pathjoin(entry[0][0], entry[0][1])
1040
1021
"""Change the last revision in the working tree."""
1041
1022
parents = self.get_parent_ids()
1042
1023
if new_revision in (NULL_REVISION, None):
1043
if len(parents) >= 2:
1044
raise AssertionError(
1045
"setting the last parent to none with a pending merge is "
1024
assert len(parents) < 2, (
1025
"setting the last parent to none with a pending merge is "
1047
1027
self.set_parent_ids([])
1049
1029
self.set_parent_ids([new_revision] + parents[1:],
1090
1070
raise errors.GhostRevisionUnusableHere(parents_list[0][0])
1091
1071
real_trees = []
1094
parent_ids = [rev_id for rev_id, tree in parents_list]
1095
graph = self.branch.repository.get_graph()
1096
heads = graph.heads(parent_ids)
1097
accepted_revisions = set()
1099
1073
# convert absent trees to the null tree, which we convert back to
1100
1074
# missing on access.
1101
1075
for rev_id, tree in parents_list:
1102
if len(accepted_revisions) > 0:
1103
# we always accept the first tree
1104
if rev_id in accepted_revisions or rev_id not in heads:
1105
# We have already included either this tree, or its
1106
# descendent, so we skip it.
1108
1076
_mod_revision.check_not_reserved_id(rev_id)
1109
1077
if tree is not None:
1110
1078
real_trees.append((rev_id, tree))
1246
1213
for file_id in file_ids:
1247
1214
self._inventory.remove_recursive_id(file_id)
1249
@needs_tree_write_lock
1250
def rename_one(self, from_rel, to_rel, after=False):
1251
"""See WorkingTree.rename_one"""
1253
WorkingTree.rename_one(self, from_rel, to_rel, after)
1255
@needs_tree_write_lock
1256
def apply_inventory_delta(self, changes):
1257
"""See MutableTree.apply_inventory_delta"""
1258
state = self.current_dirstate()
1259
state.update_by_delta(changes)
1260
self._make_dirty(reset_inventory=True)
1262
1216
def update_basis_by_delta(self, new_revid, delta):
1263
1217
"""See MutableTree.update_basis_by_delta."""
1264
if self.last_revision() == new_revid:
1265
raise AssertionError()
1218
assert self.last_revision() != new_revid
1266
1219
self.current_dirstate().update_basis_by_delta(delta, new_revid)
1268
1221
@needs_read_lock
1272
1225
@needs_tree_write_lock
1273
1226
def _write_inventory(self, inv):
1274
1227
"""Write inventory as the current inventory."""
1276
raise AssertionError("attempting to write an inventory when the "
1277
"dirstate is dirty will lose pending changes")
1228
assert not self._dirty, ("attempting to write an inventory when the "
1229
"dirstate is dirty will cause data loss")
1278
1230
self.current_dirstate().set_state_from_inventory(inv)
1279
1231
self._make_dirty(reset_inventory=False)
1280
1232
if self._inventory is not None:
1306
1256
"""See WorkingTreeFormat.get_format_description()."""
1307
1257
return "Working tree format 4"
1309
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1310
accelerator_tree=None, hardlink=False):
1259
def initialize(self, a_bzrdir, revision_id=None, from_branch=None):
1311
1260
"""See WorkingTreeFormat.initialize().
1313
1262
:param revision_id: allows creating a working tree at a different
1314
1263
revision than the branch is at.
1315
:param accelerator_tree: A tree which can be used for retrieving file
1316
contents more quickly than the revision tree, i.e. a workingtree.
1317
The revision tree will be used for cases where accelerator_tree's
1318
content is different.
1319
:param hardlink: If true, hard-link files from accelerator_tree,
1322
1265
These trees get an initial random root id, if their repository supports
1323
1266
rich root data, TREE_ROOT otherwise.
1328
1271
control_files = self._open_control_files(a_bzrdir)
1329
1272
control_files.create_lock()
1330
1273
control_files.lock_write()
1331
transport.put_bytes('format', self.get_format_string(),
1332
mode=a_bzrdir._get_file_mode())
1274
control_files.put_utf8('format', self.get_format_string())
1333
1275
if from_branch is not None:
1334
1276
branch = from_branch
1350
1292
wt.lock_tree_write()
1352
self._init_custom_control_files(wt)
1353
1294
if revision_id in (None, NULL_REVISION):
1354
1295
if branch.repository.supports_rich_root():
1355
1296
wt._set_root_id(generate_ids.gen_root_id())
1357
1298
wt._set_root_id(ROOT_ID)
1360
# frequently, we will get here due to branching. The accelerator
1361
# tree will be the tree from the branch, so the desired basis
1362
# tree will often be a parent of the accelerator tree.
1363
if accelerator_tree is not None:
1365
basis = accelerator_tree.revision_tree(revision_id)
1366
except errors.NoSuchRevision:
1369
basis = branch.repository.revision_tree(revision_id)
1370
if revision_id == NULL_REVISION:
1373
parents_list = [(revision_id, basis)]
1300
wt.set_last_revision(revision_id)
1302
basis = wt.basis_tree()
1374
1303
basis.lock_read()
1376
wt.set_parent_trees(parents_list, allow_leftmost_as_ghost=True)
1304
# if the basis has a root id we have to use that; otherwise we use
1306
basis_root_id = basis.get_root_id()
1307
if basis_root_id is not None:
1308
wt._set_root_id(basis_root_id)
1378
# if the basis has a root id we have to use that; otherwise we
1379
# use a new random one
1380
basis_root_id = basis.get_root_id()
1381
if basis_root_id is not None:
1382
wt._set_root_id(basis_root_id)
1384
# delta_from_tree is safe even for DirStateRevisionTrees,
1385
# because wt4.apply_inventory_delta does not mutate the input
1386
# inventory entries.
1387
transform.build_tree(basis, wt, accelerator_tree,
1388
hardlink=hardlink, delta_from_tree=True)
1310
transform.build_tree(basis, wt)
1392
1313
control_files.unlock()
1396
def _init_custom_control_files(self, wt):
1397
"""Subclasses with custom control files should override this method.
1399
The working tree and control files are locked for writing when this
1402
:param wt: the WorkingTree object
1405
1317
def _open(self, a_bzrdir, control_files):
1406
1318
"""Open the tree itself.
1408
1320
:param a_bzrdir: the dir for the tree.
1409
1321
:param control_files: the control files for the tree.
1411
return self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
1323
return WorkingTree4(a_bzrdir.root_transport.local_abspath('.'),
1412
1324
branch=a_bzrdir.open_branch(),
1414
1326
_bzrdir=a_bzrdir,
1443
1352
def annotate_iter(self, file_id,
1444
1353
default_revision=_mod_revision.CURRENT_REVISION):
1445
1354
"""See Tree.annotate_iter"""
1446
text_key = (file_id, self.inventory[file_id].revision)
1447
annotations = self._repository.texts.annotate(text_key)
1448
return [(key[-1], line) for (key, line) in annotations]
1355
w = self._get_weave(file_id)
1356
return w.annotate_iter(self.inventory[file_id].revision)
1450
1358
def _get_ancestors(self, default_revision):
1451
1359
return set(self._repository.get_ancestry(self._revision_id,
1480
1388
path_utf8 = osutils.pathjoin(entry[0][0], entry[0][1])
1481
1389
return path_utf8.decode('utf8')
1483
def iter_references(self):
1484
if not self._repo_supports_tree_reference:
1485
# When the repo doesn't support references, we will have nothing to
1488
# Otherwise, fall back to the default implementation
1489
return super(DirStateRevisionTree, self).iter_references()
1491
1391
def _get_parent_index(self):
1492
1392
"""Return the index in the dirstate referenced by this tree."""
1493
1393
return self._dirstate.get_parent_ids().index(self._revision_id) + 1
1519
1419
This is relatively expensive: we have to walk the entire dirstate.
1521
if not self._locked:
1522
raise AssertionError(
1523
'cannot generate inventory of an unlocked '
1524
'dirstate revision tree')
1421
assert self._locked, 'cannot generate inventory of an unlocked '\
1422
'dirstate revision tree'
1525
1423
# separate call for profiling - makes it clear where the costs are.
1526
1424
self._dirstate._read_dirblocks_if_needed()
1527
if self._revision_id not in self._dirstate.get_parent_ids():
1528
raise AssertionError(
1529
'parent %s has disappeared from %s' % (
1530
self._revision_id, self._dirstate.get_parent_ids()))
1425
assert self._revision_id in self._dirstate.get_parent_ids(), \
1426
'parent %s has disappeared from %s' % (
1427
self._revision_id, self._dirstate.get_parent_ids())
1531
1428
parent_index = self._dirstate.get_parent_ids().index(self._revision_id) + 1
1532
1429
# This is identical now to the WorkingTree _generate_inventory except
1533
1430
# for the tree index use.
1534
1431
root_key, current_entry = self._dirstate._get_entry(parent_index, path_utf8='')
1535
1432
current_id = root_key[2]
1536
if current_entry[parent_index][0] != 'd':
1537
raise AssertionError()
1433
assert current_entry[parent_index][0] == 'd'
1538
1434
inv = Inventory(root_id=current_id, revision_id=self._revision_id)
1539
1435
inv.root.revision = current_entry[parent_index][4]
1540
1436
# Turn some things into local variables
1580
1476
raise AssertionError("cannot convert entry %r into an InventoryEntry"
1582
1478
# These checks cost us around 40ms on a 55k entry tree
1583
if file_id in inv_byid:
1584
raise AssertionError('file_id %s already in'
1585
' inventory as %s' % (file_id, inv_byid[file_id]))
1586
if name_unicode in parent_ie.children:
1587
raise AssertionError('name %r already in parent'
1479
assert file_id not in inv_byid
1480
assert name_unicode not in parent_ie.children
1589
1481
inv_byid[file_id] = inv_entry
1590
1482
parent_ie.children[name_unicode] = inv_entry
1591
1483
self._inventory = inv
1611
1503
return parent_details[1]
1506
@symbol_versioning.deprecated_method(symbol_versioning.zero_ninety)
1507
def get_weave(self, file_id):
1508
return self._get_weave(file_id)
1510
def _get_weave(self, file_id):
1511
return self._repository.weave_store.get_weave(file_id,
1512
self._repository.get_transaction())
1614
1514
def get_file(self, file_id, path=None):
1615
1515
return StringIO(self.get_file_text(file_id))
1617
1517
def get_file_lines(self, file_id):
1618
return osutils.split_lines(self.get_file_text(file_id))
1518
entry = self._get_entry(file_id=file_id)[1]
1520
raise errors.NoSuchId(tree=self, file_id=file_id)
1521
return self._get_weave(file_id).get_lines(entry[1][4])
1620
1523
def get_file_size(self, file_id):
1621
"""See Tree.get_file_size"""
1622
1524
return self.inventory[file_id].text_size
1624
1526
def get_file_text(self, file_id):
1625
return list(self.iter_files_bytes([(file_id, None)]))[0][1]
1527
return ''.join(self.get_file_lines(file_id))
1627
1529
def get_reference_revision(self, file_id, path=None):
1628
1530
return self.inventory[file_id].reference_revision
1676
1578
def kind(self, file_id):
1677
1579
entry = self._get_entry(file_id=file_id)[1]
1679
1581
raise errors.NoSuchId(tree=self, file_id=file_id)
1680
1582
return dirstate.DirState._minikind_to_kind[entry[1][0]]
1682
def stored_kind(self, file_id):
1683
"""See Tree.stored_kind"""
1684
return self.kind(file_id)
1686
1584
def path_content_summary(self, path):
1687
1585
"""See Tree.path_content_summary."""
1688
1586
id = self.inventory.path2id(path)
1747
1645
self._dirstate_locked = False
1748
1646
self._repository.unlock()
1751
def supports_tree_reference(self):
1752
return self._repo_supports_tree_reference
1754
1648
def walkdirs(self, prefix=""):
1755
1649
# TODO: jam 20070215 This is the lazy way by using the RevisionTree
1756
1650
# implementation based on an inventory.
1813
1707
_matching_to_tree_format = WorkingTreeFormat4()
1814
1708
_test_mutable_trees_to_test_trees = make_source_parent_tree
1816
def iter_changes(self, include_unchanged=False,
1710
def _iter_changes(self, include_unchanged=False,
1817
1711
specific_files=None, pb=None, extra_trees=[],
1818
1712
require_versioned=True, want_unversioned=False):
1819
1713
"""Return the changes from source to target.
1821
:return: An iterator that yields tuples. See InterTree.iter_changes
1715
:return: An iterator that yields tuples. See InterTree._iter_changes
1823
1717
:param specific_files: An optional list of file paths to restrict the
1824
1718
comparison to. When mapping filenames to ids, all matches in all
1841
1735
# NB: show_status depends on being able to pass in non-versioned files
1842
1736
# and report them as unknown
1843
1737
# TODO: handle extra trees in the dirstate.
1844
if (extra_trees or specific_files == []):
1738
# TODO: handle comparisons as an empty tree as a different special
1739
# case? mbp 20070226
1740
if (extra_trees or (self.source._revision_id == NULL_REVISION)
1741
or specific_files == []):
1845
1742
# we can't fast-path these cases (yet)
1846
for f in super(InterDirStateTree, self).iter_changes(
1743
for f in super(InterDirStateTree, self)._iter_changes(
1847
1744
include_unchanged, specific_files, pb, extra_trees,
1848
1745
require_versioned, want_unversioned=want_unversioned):
1851
1748
parent_ids = self.target.get_parent_ids()
1852
if not (self.source._revision_id in parent_ids
1853
or self.source._revision_id == NULL_REVISION):
1854
raise AssertionError(
1855
"revision {%s} is not stored in {%s}, but %s "
1856
"can only be used for trees stored in the dirstate"
1857
% (self.source._revision_id, self.target, self.iter_changes))
1749
assert (self.source._revision_id in parent_ids), \
1750
"revision {%s} is not stored in {%s}, but %s " \
1751
"can only be used for trees stored in the dirstate" \
1752
% (self.source._revision_id, self.target, self._iter_changes)
1858
1753
target_index = 0
1859
1754
if self.source._revision_id == NULL_REVISION:
1860
1755
source_index = None
1861
1756
indices = (target_index,)
1863
if not (self.source._revision_id in parent_ids):
1864
raise AssertionError(
1865
"Failure: source._revision_id: %s not in target.parent_ids(%s)" % (
1866
self.source._revision_id, parent_ids))
1758
assert (self.source._revision_id in parent_ids), \
1759
"Failure: source._revision_id: %s not in target.parent_ids(%s)" % (
1760
self.source._revision_id, parent_ids)
1867
1761
source_index = 1 + parent_ids.index(self.source._revision_id)
1868
indices = (source_index, target_index)
1762
indices = (source_index,target_index)
1869
1763
# -- make all specific_files utf8 --
1870
1764
if specific_files:
1871
1765
specific_files_utf8 = set()
2006
1901
target_details = entry[1][target_index]
2007
1902
target_minikind = target_details[0]
2008
1903
if path_info is not None and target_minikind in 'fdlt':
2009
if not (target_index == 0):
2010
raise AssertionError()
1904
assert target_index == 0
2011
1905
link_or_sha1 = state.update_entry(entry, abspath=path_info[4],
2012
1906
stat_value=path_info[3])
2013
1907
# The entry may have been modified by update_entry
2038
1932
path_utf8=old_path)
2039
1933
# update the source details variable to be the real
2041
if old_entry == (None, None):
2042
raise errors.CorruptDirstate(state._filename,
2043
"entry '%s/%s' is considered renamed from %r"
2044
" but source does not exist\n"
2045
"entry: %s" % (entry[0][0], entry[0][1], old_path, entry))
2046
1935
source_details = old_entry[1][source_index]
2047
1936
source_minikind = source_details[0]
2126
2015
# parent entry will be the same as the source entry.
2127
2016
target_parent_entry = state._get_entry(target_index,
2128
2017
path_utf8=new_dirname)
2129
if target_parent_entry == (None, None):
2130
raise AssertionError(
2131
"Could not find target parent in wt: %s\nparent of: %s"
2132
% (new_dirname, entry))
2018
assert target_parent_entry != (None, None), (
2019
"Could not find target parent in wt: %s\nparent of: %s"
2020
% (new_dirname, entry))
2133
2021
target_parent_id = target_parent_entry[0][2]
2134
2022
if target_parent_id == entry[0][2]:
2135
2023
# This is the root, so the parent is None
2168
2056
return uninteresting
2169
2057
elif source_minikind in 'a' and target_minikind in 'fdlt':
2170
2058
# looks like a new file
2171
path = pathjoin(entry[0][0], entry[0][1])
2172
# parent id is the entry for the path in the target tree
2173
# TODO: these are the same for an entire directory: cache em.
2174
parent_id = state._get_entry(target_index,
2175
path_utf8=entry[0][0])[0][2]
2176
if parent_id == entry[0][2]:
2178
2059
if path_info is not None:
2060
path = pathjoin(entry[0][0], entry[0][1])
2061
# parent id is the entry for the path in the target tree
2062
# TODO: these are the same for an entire directory: cache em.
2063
parent_id = state._get_entry(target_index,
2064
path_utf8=entry[0][0])[0][2]
2065
if parent_id == entry[0][2]:
2180
2067
if use_filesystem_for_exec:
2181
2068
# We need S_ISREG here, because we aren't sure if this
2182
2069
# is a file or not.
2194
2081
(None, path_info[2]),
2195
2082
(None, target_exec))
2197
# Its a missing file, report it as such.
2198
return (entry[0][2],
2199
(None, utf8_decode(path)[0]),
2203
(None, utf8_decode(entry[0][1])[0]),
2084
# but its not on disk: we deliberately treat this as just
2085
# never-present. (Why ?! - RBC 20070224)
2206
2087
elif source_minikind in 'fdlt' and target_minikind in 'a':
2207
2088
# unversioned, possibly, or possibly not deleted: we dont care.
2208
2089
# if its still on disk, *and* theres no other entry at this
2325
2206
if current_dir_info[0][0] == '':
2326
2207
# remove .bzr from iteration
2327
2208
bzr_index = bisect_left(current_dir_info[1], ('.bzr',))
2328
if current_dir_info[1][bzr_index][0] != '.bzr':
2329
raise AssertionError()
2209
assert current_dir_info[1][bzr_index][0] == '.bzr'
2330
2210
del current_dir_info[1][bzr_index]
2331
2211
# walk until both the directory listing and the versioned metadata
2332
2212
# are exhausted.
2478
2358
new_executable = bool(
2479
2359
stat.S_ISREG(current_path_info[3].st_mode)
2480
2360
and stat.S_IEXEC & current_path_info[3].st_mode)
2482
relpath_unicode = utf8_decode(current_path_info[0])[0]
2483
except UnicodeDecodeError:
2484
raise errors.BadFilenameEncoding(
2485
current_path_info[0], osutils._fs_enc)
2487
(None, relpath_unicode),
2362
(None, utf8_decode(current_path_info[0])[0]),
2489
2364
(False, False),
2588
2464
def update_format(self, tree):
2589
2465
"""Change the format marker."""
2590
tree._transport.put_bytes('format',
2591
self.target_format.get_format_string(),
2592
mode=tree.bzrdir._get_file_mode())
2466
tree._control_files.put_utf8('format',
2467
self.target_format.get_format_string())