90
93
class TreeTransformBase(object):
91
94
"""The base class for TreeTransform and its kin."""
93
def __init__(self, tree, pb=None,
96
def __init__(self, tree, pb=None, case_sensitive=True):
97
99
:param tree: The tree that will be transformed, but not necessarily
132
134
# The trans_id that will be used as the tree root
133
135
root_id = tree.get_root_id()
134
136
if root_id is not None:
135
self._new_root = self.trans_id_tree_file_id(root_id)
137
self._new_root = self.trans_id_tree_path('')
137
139
self._new_root = None
138
140
# Indicator of whether the transform has been applied
216
218
# the physical root needs a new transaction id
217
219
self._tree_path_ids.pop("")
218
220
self._tree_id_paths.pop(old_root)
219
self._new_root = self.trans_id_tree_file_id(self._tree.get_root_id())
221
self._new_root = self.trans_id_tree_path('')
220
222
if parent == old_root:
221
223
parent = self._new_root
222
224
self.adjust_path(name, parent, old_root)
285
287
del self._new_parent[old_new_root]
286
288
del self._new_name[old_new_root]
288
def trans_id_tree_file_id(self, inventory_id):
289
"""Determine the transaction id of a working tree file.
291
This reflects only files that already exist, not ones that will be
292
added by transactions.
294
if inventory_id is None:
295
raise ValueError('None is not a valid file id')
296
path = self._tree.id2path(inventory_id)
297
return self.trans_id_tree_path(path)
299
290
def trans_id_file_id(self, file_id):
300
291
"""Determine or set the transaction id associated with a file ID.
301
292
A new id is only created for file_ids that were never present. If
308
299
return self._r_new_id[file_id]
311
next(self._tree.iter_entries_by_dir([file_id]))
312
except StopIteration:
302
path = self._tree.id2path(file_id)
303
except errors.NoSuchId:
313
304
if file_id in self._non_present_ids:
314
305
return self._non_present_ids[file_id]
317
308
self._non_present_ids[file_id] = trans_id
320
return self.trans_id_tree_file_id(file_id)
311
return self.trans_id_tree_path(path)
322
313
def trans_id_tree_path(self, path):
323
314
"""Determine (and maybe set) the transaction ID for a tree path."""
455
446
return self.tree_kind(trans_id)
448
def tree_path(self, trans_id):
449
"""Determine the tree path associated with the trans_id."""
450
return self._tree_id_paths.get(trans_id)
457
452
def tree_file_id(self, trans_id):
458
453
"""Determine the file id associated with the trans_id in the tree"""
460
path = self._tree_id_paths[trans_id]
462
# the file is a new, unversioned file, or invalid trans_id
454
path = self.tree_path(trans_id)
464
457
# the file is old; the old id is still valid
465
458
if self._new_root == trans_id:
567
560
parents.extend([t for t in self._removed_contents if
568
561
self.tree_kind(t) == 'directory'])
569
562
for trans_id in self._removed_id:
570
file_id = self.tree_file_id(trans_id)
571
path = self._tree.id2path(file_id)
572
if file_id is not None:
573
if self._tree.stored_kind(path, file_id) == 'directory':
563
path = self.tree_path(trans_id)
565
if self._tree.stored_kind(path) == 'directory':
574
566
parents.append(trans_id)
575
567
elif self.tree_kind(trans_id) == 'directory':
576
568
parents.append(trans_id)
735
727
active_tree_ids = all_ids.difference(removed_tree_ids)
736
728
for trans_id, file_id in viewitems(self._new_id):
737
729
if file_id in active_tree_ids:
738
old_trans_id = self.trans_id_tree_file_id(file_id)
730
path = self._tree.id2path(file_id)
731
old_trans_id = self.trans_id_tree_path(path)
739
732
conflicts.append(('duplicate id', old_trans_id, trans_id))
901
894
to_trans_ids[to_file_id] = trans_id
902
895
return from_trans_ids, to_trans_ids
904
def _from_file_data(self, from_trans_id, from_versioned, file_id):
897
def _from_file_data(self, from_trans_id, from_versioned, from_path):
905
898
"""Get data about a file in the from (tree) state
907
900
Return a (name, parent, kind, executable) tuple
909
902
from_path = self._tree_id_paths.get(from_trans_id)
910
903
if from_versioned:
911
904
# get data from working tree if versioned
912
from_entry = next(self._tree.iter_entries_by_dir([file_id]))[1]
905
from_entry = next(self._tree.iter_entries_by_dir(
906
specific_files=[from_path]))[1]
913
907
from_name = from_entry.name
914
908
from_parent = from_entry.parent_id
979
973
to_versioned = True
981
from_name, from_parent, from_kind, from_executable = \
982
self._from_file_data(from_trans_id, from_versioned, file_id)
984
to_name, to_parent, to_kind, to_executable = \
985
self._to_file_data(to_trans_id, from_trans_id, from_executable)
987
975
if not from_versioned:
994
982
to_path = final_paths.get_path(to_trans_id)
984
from_name, from_parent, from_kind, from_executable = \
985
self._from_file_data(from_trans_id, from_versioned, from_path)
987
to_name, to_parent, to_kind, to_executable = \
988
self._to_file_data(to_trans_id, from_trans_id, from_executable)
995
990
if from_kind != to_kind:
997
992
elif to_kind in ('file', 'symlink') and (
1077
1072
return revision_id
1079
1074
def _text_parent(self, trans_id):
1080
file_id = self.tree_file_id(trans_id)
1075
path = self.tree_path(trans_id)
1082
if (file_id is None or
1083
self._tree.kind(self._tree.id2path(file_id), file_id) != 'file'):
1077
if path is None or self._tree.kind(path) != 'file':
1085
1079
except errors.NoSuchFile:
1089
1083
def _get_parents_texts(self, trans_id):
1090
1084
"""Get texts for compression parents of this file."""
1091
file_id = self._text_parent(trans_id)
1085
path = self._text_parent(trans_id)
1094
return (self._tree.get_file_text(self._tree.id2path(file_id), file_id),)
1088
return (self._tree.get_file_text(path),)
1096
1090
def _get_parents_lines(self, trans_id):
1097
1091
"""Get lines for compression parents of this file."""
1098
file_id = self._text_parent(trans_id)
1092
path = self._text_parent(trans_id)
1101
return (self._tree.get_file_lines(self._tree.id2path(file_id), file_id),)
1095
return (self._tree.get_file_lines(path),)
1103
1097
def serialize(self, serializer):
1104
1098
"""Serialize this TreeTransform.
1408
1402
def new_orphan(self, trans_id, parent_id):
1409
1403
conf = self._tree.get_config_stack()
1410
handle_orphan = conf.get('bzr.transform.orphan_policy')
1404
handle_orphan = conf.get('transform.orphan_policy')
1411
1405
handle_orphan(self, trans_id, parent_id)
1479
1473
opt_transform_orphan = _mod_config.RegistryOption(
1480
'bzr.transform.orphan_policy', orphaning_registry,
1474
'transform.orphan_policy', orphaning_registry,
1481
1475
help='Policy for orphaned files during transform operations.',
1482
1476
invalid='warning')
1721
1715
hook(self._tree, self)
1722
1716
if not no_conflicts:
1723
1717
self._check_malformed()
1724
child_pb = ui.ui_factory.nested_progress_bar()
1718
with ui.ui_factory.nested_progress_bar() as child_pb:
1726
1719
if precomputed_delta is None:
1727
1720
child_pb.update(gettext('Apply phase'), 0, 2)
1728
1721
inventory_delta = self._generate_inventory_delta()
1757
1748
def _generate_inventory_delta(self):
1758
1749
"""Generate an inventory delta for the current transform."""
1759
1750
inventory_delta = []
1760
child_pb = ui.ui_factory.nested_progress_bar()
1761
1751
new_paths = self._inventory_altered()
1762
1752
total_entries = len(new_paths) + len(self._removed_id)
1753
with ui.ui_factory.nested_progress_bar() as child_pb:
1764
1754
for num, trans_id in enumerate(self._removed_id):
1765
1755
if (num % 10) == 0:
1766
1756
child_pb.update(gettext('removing file'), num, total_entries)
1775
1765
inventory_delta.append((path, None, file_id, None))
1776
1766
new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in
1778
entries = self._tree.iter_entries_by_dir(
1779
viewvalues(new_path_file_ids))
1780
old_paths = dict((e.file_id, p) for p, e in entries)
1781
1768
final_kinds = {}
1782
1769
for num, (path, trans_id) in enumerate(new_paths):
1783
1770
if (num % 10) == 0:
1805
1792
new_entry = inventory.make_entry(kind,
1806
1793
self.final_name(trans_id),
1807
1794
parent_file_id, file_id)
1808
old_path = old_paths.get(new_entry.file_id)
1796
old_path = self._tree.id2path(new_entry.file_id)
1797
except errors.NoSuchId:
1809
1799
new_executability = self._new_executability.get(trans_id)
1810
1800
if new_executability is not None:
1811
1801
new_entry.executable = new_executability
1812
1802
inventory_delta.append(
1813
1803
(old_path, path, new_entry.file_id, new_entry))
1816
1804
return inventory_delta
1818
1806
def _apply_removals(self, mover):
1825
1813
If inventory_delta is None, no inventory delta generation is performed.
1827
1815
tree_paths = sorted(viewitems(self._tree_path_ids), reverse=True)
1828
child_pb = ui.ui_factory.nested_progress_bar()
1816
with ui.ui_factory.nested_progress_bar() as child_pb:
1830
1817
for num, (path, trans_id) in enumerate(tree_paths):
1831
1818
# do not attempt to move root into a subdirectory of itself.
1862
1847
modified_paths = []
1863
1848
new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in
1865
child_pb = ui.ui_factory.nested_progress_bar()
1850
with ui.ui_factory.nested_progress_bar() as child_pb:
1867
1851
for num, (path, trans_id) in enumerate(new_paths):
1868
1852
if (num % 10) == 0:
1869
1853
child_pb.update(gettext('adding file'), num, len(new_paths))
1890
1874
o_sha1, o_st_val = self._observed_sha1s[trans_id]
1891
1875
st = osutils.lstat(full_path)
1892
1876
self._observed_sha1s[trans_id] = (o_sha1, st)
1895
1877
for path, trans_id in new_paths:
1896
1878
# new_paths includes stuff like workingtree conflicts. Only the
1897
1879
# stuff in new_contents actually comes from limbo.
1964
1946
path = self._tree_id_paths[parent_id]
1965
1947
except KeyError:
1967
file_id = self.tree_file_id(parent_id)
1970
entry = next(self._tree.iter_entries_by_dir([file_id]))[1]
1949
entry = next(self._tree.iter_entries_by_dir(
1950
specific_files=[path]))[1]
1971
1951
children = getattr(entry, 'children', {})
1972
1952
for child in children:
1973
1953
childpath = joinpath(path, child)
2023
2003
vf.fallback_versionedfiles.append(base_vf)
2024
2004
return tree_revision
2026
def _stat_limbo_file(self, file_id=None, trans_id=None):
2027
if trans_id is None:
2028
trans_id = self._transform.trans_id_file_id(file_id)
2006
def _stat_limbo_file(self, trans_id):
2029
2007
name = self._transform._limbo_name(trans_id)
2030
2008
return os.lstat(name)
2135
2113
self._all_children_cache[trans_id] = children
2136
2114
return children
2138
def iter_children(self, file_id):
2116
def _iter_children(self, file_id):
2139
2117
trans_id = self._transform.trans_id_file_id(file_id)
2140
2118
for child_trans_id in self._all_children(trans_id):
2141
2119
yield self._transform.final_file_id(child_trans_id)
2149
2127
if self._transform.final_file_id(trans_id) is None:
2150
2128
yield self._final_paths._determine_path(trans_id)
2152
def _make_inv_entries(self, ordered_entries, specific_file_ids=None,
2130
def _make_inv_entries(self, ordered_entries, specific_files=None,
2153
2131
yield_parents=False):
2154
2132
for trans_id, parent_file_id in ordered_entries:
2155
2133
file_id = self._transform.final_file_id(trans_id)
2156
2134
if file_id is None:
2158
if (specific_file_ids is not None
2159
and file_id not in specific_file_ids):
2136
if (specific_files is not None and
2137
unicode(self._final_paths.get_path(trans_id)) not in specific_files):
2161
2139
kind = self._transform.final_kind(trans_id)
2162
2140
if kind is None:
2184
2162
return ordered_ids
2186
2164
def iter_child_entries(self, path, file_id=None):
2188
file_id = self.path2id(path)
2165
trans_id = self._path2trans_id(path)
2166
if trans_id is None:
2190
2167
raise errors.NoSuchFile(path)
2191
trans_id = self._transform.trans_id_file_id(file_id)
2192
2168
todo = [(child_trans_id, trans_id) for child_trans_id in
2193
2169
self._all_children(trans_id)]
2194
2170
for entry, trans_id in self._make_inv_entries(todo):
2197
def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
2173
def iter_entries_by_dir(self, specific_files=None, yield_parents=False):
2198
2174
# This may not be a maximally efficient implementation, but it is
2199
2175
# reasonably straightforward. An implementation that grafts the
2200
2176
# TreeTransform changes onto the tree's iter_entries_by_dir results
2203
2179
ordered_ids = self._list_files_by_dir()
2204
2180
for entry, trans_id in self._make_inv_entries(ordered_ids,
2205
specific_file_ids, yield_parents=yield_parents):
2181
specific_files, yield_parents=yield_parents):
2206
2182
yield unicode(self._final_paths.get_path(trans_id)), entry
2208
2184
def _iter_entries_for_dir(self, dir_path):
2209
2185
"""Return path, entry for items in a directory without recursing down."""
2210
dir_file_id = self.path2id(dir_path)
2211
2186
ordered_ids = []
2212
for file_id in self.iter_children(dir_file_id):
2213
trans_id = self._transform.trans_id_file_id(file_id)
2214
ordered_ids.append((trans_id, file_id))
2187
dir_trans_id = self._path2trans_id(dir_path)
2188
dir_id = self._transform.final_file_id(dir_trans_id)
2189
for child_trans_id in self._all_children(dir_trans_id):
2190
ordered_ids.append((child_trans_id, dir_id))
2215
2191
for entry, trans_id in self._make_inv_entries(ordered_ids):
2216
2192
yield unicode(self._final_paths.get_path(trans_id)), entry
2242
2218
yield path, 'V', entry.kind, entry.file_id, entry
2244
2220
def kind(self, path, file_id=None):
2246
file_id = self.path2id(path)
2247
trans_id = self._transform.trans_id_file_id(file_id)
2221
trans_id = self._path2trans_id(path)
2222
if trans_id is None:
2223
raise errors.NoSuchFile(path)
2248
2224
return self._transform.final_kind(trans_id)
2250
2226
def stored_kind(self, path, file_id=None):
2252
file_id = self.path2id(path)
2253
trans_id = self._transform.trans_id_file_id(file_id)
2227
trans_id = self._path2trans_id(path)
2228
if trans_id is None:
2229
raise errors.NoSuchFile(path)
2255
2231
return self._transform._new_contents[trans_id]
2256
2232
except KeyError:
2265
2241
if not self._content_change(file_id):
2266
2242
return self._transform._tree.get_file_mtime(
2267
2243
self._transform._tree.id2path(file_id), file_id)
2268
return self._stat_limbo_file(file_id).st_mtime
2270
def _file_size(self, entry, stat_value):
2271
path = self.id2path(entry.file_id)
2272
return self.get_file_size(path, entry.file_id)
2244
trans_id = self._path2trans_id(path)
2245
return self._stat_limbo_file(trans_id).st_mtime
2274
2247
def get_file_size(self, path, file_id=None):
2275
2248
"""See Tree.get_file_size"""
2277
file_id = self.path2id(path)
2278
trans_id = self._transform.trans_id_file_id(file_id)
2249
trans_id = self._path2trans_id(path)
2250
if trans_id is None:
2251
raise errors.NoSuchFile(path)
2279
2252
kind = self._transform.final_kind(trans_id)
2280
2253
if kind != 'file':
2282
2255
if trans_id in self._transform._new_contents:
2283
return self._stat_limbo_file(trans_id=trans_id).st_size
2256
return self._stat_limbo_file(trans_id).st_size
2284
2257
if self.kind(path, file_id) == 'file':
2285
2258
return self._transform._tree.get_file_size(path, file_id)
2289
2262
def get_file_verifier(self, path, file_id=None, stat_value=None):
2291
file_id = self.path2id(path)
2292
trans_id = self._transform.trans_id_file_id(file_id)
2263
trans_id = self._path2trans_id(path)
2264
if trans_id is None:
2265
raise errors.NoSuchFile(path)
2293
2266
kind = self._transform._new_contents.get(trans_id)
2294
2267
if kind is None:
2295
2268
return self._transform._tree.get_file_verifier(path, file_id)
2301
2274
fileobj.close()
2303
2276
def get_file_sha1(self, path, file_id=None, stat_value=None):
2305
file_id = self.path2id(path)
2306
trans_id = self._transform.trans_id_file_id(file_id)
2277
trans_id = self._path2trans_id(path)
2278
if trans_id is None:
2279
raise errors.NoSuchFile(path)
2307
2280
kind = self._transform._new_contents.get(trans_id)
2308
2281
if kind is None:
2309
2282
return self._transform._tree.get_file_sha1(path, file_id)
2315
2288
fileobj.close()
2317
2290
def is_executable(self, path, file_id=None):
2319
file_id = self.path2id(path)
2291
trans_id = self._path2trans_id(path)
2292
if trans_id is None:
2322
trans_id = self._transform.trans_id_file_id(file_id)
2324
2295
return self._transform._new_executability[trans_id]
2325
2296
except KeyError:
2398
2369
file_id = self.path2id(path)
2399
2370
if not self._content_change(file_id):
2400
2371
return self._transform._tree.get_file(path, file_id)
2401
trans_id = self._transform.trans_id_file_id(file_id)
2372
trans_id = self._path2trans_id(path)
2402
2373
name = self._transform._limbo_name(trans_id)
2403
2374
return open(name, 'rb')
2444
2415
file_id = self.path2id(path)
2445
2416
if not self._content_change(file_id):
2446
2417
return self._transform._tree.get_symlink_target(path)
2447
trans_id = self._transform.trans_id_file_id(file_id)
2418
trans_id = self._path2trans_id(path)
2448
2419
name = self._transform._limbo_name(trans_id)
2449
2420
return osutils.readlink(name)
2598
2569
pp.next_phase()
2599
file_trans_id[wt.get_root_id()] = \
2600
tt.trans_id_tree_file_id(wt.get_root_id())
2601
pb = ui.ui_factory.nested_progress_bar()
2570
file_trans_id[wt.get_root_id()] = tt.trans_id_tree_path('')
2571
with ui.ui_factory.nested_progress_bar() as pb:
2603
2572
deferred_contents = []
2605
2574
total = len(tree.all_versioned_paths())
2637
2606
divert.add(file_id)
2638
2607
if (file_id not in divert and
2639
_content_match(tree, entry, file_id, kind,
2608
_content_match(tree, entry, tree_path, file_id, kind,
2641
2610
tt.delete_contents(tt.trans_id_tree_path(tree_path))
2642
2611
if kind == 'directory':
2651
2620
executable = tree.is_executable(tree_path, file_id)
2653
2622
tt.set_executability(executable, trans_id)
2654
trans_data = (trans_id, tree_path, entry.text_sha1)
2655
deferred_contents.append((file_id, trans_data))
2623
trans_data = (trans_id, file_id, tree_path, entry.text_sha1)
2624
deferred_contents.append((tree_path, trans_data))
2657
2626
file_trans_id[file_id] = new_by_entry(
2658
2627
tree_path, tt, entry, parent_id, tree)
2663
2632
offset = num + 1 - len(deferred_contents)
2664
2633
_create_files(tt, tree, deferred_contents, pb, offset,
2665
2634
accelerator_tree, hardlink)
2668
2635
pp.next_phase()
2669
2636
divert_trans = set(file_trans_id[f] for f in divert)
2670
2637
resolver = lambda t, c: resolve_checkout(t, c, divert_trans)
2694
2661
new_desired_files = desired_files
2696
2663
iter = accelerator_tree.iter_changes(tree, include_unchanged=True)
2697
unchanged = [(f, p[1]) for (f, p, c, v, d, n, k, e)
2664
unchanged = [(p[0], p[1]) for (f, p, c, v, d, n, k, e)
2698
2665
in iter if not (c or e[0] != e[1])]
2699
2666
if accelerator_tree.supports_content_filtering():
2700
unchanged = [(f, p) for (f, p) in unchanged
2701
if not next(accelerator_tree.iter_search_rules([p]))]
2667
unchanged = [(tp, ap) for (tp, ap) in unchanged
2668
if not next(accelerator_tree.iter_search_rules([ap]))]
2702
2669
unchanged = dict(unchanged)
2703
2670
new_desired_files = []
2705
for file_id, (trans_id, tree_path, text_sha1) in desired_files:
2706
accelerator_path = unchanged.get(file_id)
2672
for unused_tree_path, (trans_id, file_id, tree_path, text_sha1) in desired_files:
2673
accelerator_path = unchanged.get(tree_path)
2707
2674
if accelerator_path is None:
2708
new_desired_files.append((file_id,
2709
(trans_id, tree_path, text_sha1)))
2675
new_desired_files.append((tree_path,
2676
(trans_id, file_id, tree_path, text_sha1)))
2711
2678
pb.update(gettext('Adding file contents'), count + offset, total)
2730
2697
offset += count
2731
for count, ((trans_id, tree_path, text_sha1), contents) in enumerate(
2698
for count, ((trans_id, file_id, tree_path, text_sha1), contents) in enumerate(
2732
2699
tree.iter_files_bytes(new_desired_files)):
2733
2700
if wt.supports_content_filtering():
2734
2701
filters = wt._content_filter_stack(tree_path)
2750
2717
return by_parent[old_parent]
2753
def _content_match(tree, entry, file_id, kind, target_path):
2720
def _content_match(tree, entry, tree_path, file_id, kind, target_path):
2754
2721
if entry.kind != kind:
2756
2723
if entry.kind == "directory":
2758
path = tree.id2path(file_id)
2759
2725
if entry.kind == "file":
2760
2726
f = file(target_path, 'rb')
2762
if tree.get_file_text(path, file_id) == f.read():
2728
if tree.get_file_text(tree_path, file_id) == f.read():
2766
2732
elif entry.kind == "symlink":
2767
if tree.get_symlink_target(path, file_id) == os.readlink(target_path):
2733
if tree.get_symlink_target(tree_path, file_id) == os.readlink(target_path):
2885
2852
def _prepare_revert_transform(working_tree, target_tree, tt, filenames,
2886
2853
backups, pp, basis_tree=None,
2887
2854
merge_modified=None):
2888
child_pb = ui.ui_factory.nested_progress_bar()
2855
with ui.ui_factory.nested_progress_bar() as child_pb:
2890
2856
if merge_modified is None:
2891
2857
merge_modified = working_tree.merge_modified()
2892
2858
merge_modified = _alter_files(working_tree, target_tree, tt,
2893
2859
child_pb, filenames, backups,
2894
2860
merge_modified, basis_tree)
2897
child_pb = ui.ui_factory.nested_progress_bar()
2861
with ui.ui_factory.nested_progress_bar() as child_pb:
2899
2862
raw_conflicts = resolve_conflicts(tt, child_pb,
2900
2863
lambda t, c: conflict_pass(t, c, target_tree))
2903
2864
conflicts = cook_conflicts(raw_conflicts, tt)
2904
2865
return conflicts, merge_modified
2943
2904
if basis_tree is None:
2944
2905
basis_tree = working_tree.basis_tree()
2945
2906
basis_tree.lock_read()
2947
basis_path = basis_tree.id2path(file_id)
2948
except errors.NoSuchId:
2907
basis_path = find_previous_path(working_tree, basis_tree, wt_path)
2908
if basis_path is None:
2949
2909
if target_kind is None and not target_versioned:
2950
2910
keep_content = True
2977
2937
tt.create_symlink(target_tree.get_symlink_target(
2978
2938
target_path, file_id), trans_id)
2979
2939
elif target_kind == 'file':
2980
deferred_files.append((file_id, (trans_id, mode_id)))
2940
deferred_files.append((target_path, (trans_id, mode_id, file_id)))
2981
2941
if basis_tree is None:
2982
2942
basis_tree = working_tree.basis_tree()
2983
2943
basis_tree.lock_read()
2984
2944
new_sha1 = target_tree.get_file_sha1(target_path, file_id)
2986
basis_path = basis_tree.id2path(file_id)
2987
except errors.NoSuchId:
2945
basis_path = find_previous_path(target_tree, basis_tree, target_path)
2989
2946
if (basis_path is not None and
2990
2947
new_sha1 == basis_tree.get_file_sha1(basis_path, file_id)):
2991
2948
if file_id in merge_modified:
3015
2972
if wt_executable != target_executable and target_kind == "file":
3016
2973
tt.set_executability(target_executable, trans_id)
3017
2974
if working_tree.supports_content_filtering():
3018
for index, ((trans_id, mode_id), bytes) in enumerate(
2975
for (trans_id, mode_id, file_id), bytes in (
3019
2976
target_tree.iter_files_bytes(deferred_files)):
3020
file_id = deferred_files[index][0]
3021
2977
# We're reverting a tree to the target tree so using the
3022
2978
# target tree to find the file path seems the best choice
3023
2979
# here IMO - Ian C 27/Oct/2009
3027
2983
ContentFilterContext(filter_tree_path, working_tree))
3028
2984
tt.create_file(bytes, trans_id, mode_id)
3030
for (trans_id, mode_id), bytes in target_tree.iter_files_bytes(
2986
for (trans_id, mode_id, file_id), bytes in target_tree.iter_files_bytes(
3031
2987
deferred_files):
3032
2988
tt.create_file(bytes, trans_id, mode_id)
3033
2989
tt.fixup_new_roots()
3042
2998
if pass_func is None:
3043
2999
pass_func = conflict_pass
3044
3000
new_conflicts = set()
3045
pb = ui.ui_factory.nested_progress_bar()
3001
with ui.ui_factory.nested_progress_bar() as pb:
3047
3002
for n in range(10):
3048
3003
pb.update(gettext('Resolution pass'), n+1, 10)
3049
3004
conflicts = tt.find_conflicts()
3051
3006
return new_conflicts
3052
3007
new_conflicts.update(pass_func(tt, conflicts))
3053
3008
raise MalformedTransform(conflicts=conflicts)
3058
3011
def conflict_pass(tt, conflicts, path_tree=None):
3123
3076
if file_id is None:
3124
3077
file_id = tt.inactive_file_id(trans_id)
3125
3078
_, entry = next(path_tree.iter_entries_by_dir(
3079
specific_files=[path_tree.id2path(file_id)]))
3127
3080
# special-case the other tree root (move its
3128
3081
# children to current root)
3129
3082
if entry.parent_id is None:
3144
3097
elif c_type == 'unversioned parent':
3145
3098
file_id = tt.inactive_file_id(conflict[1])
3146
3099
# special-case the other tree root (move its children instead)
3147
if path_tree and path_tree.has_id(file_id):
3148
if path_tree.path2id('') == file_id:
3100
if path_tree and path_tree.path2id('') == file_id:
3149
3101
# This is the root entry, skip it
3151
3103
tt.version_file(file_id, conflict[1])
3260
3212
if executable[0] != executable[1]:
3262
trans_id = tt.trans_id_tree_file_id(file_id)
3214
trans_id = tt.trans_id_tree_path(paths[1])
3263
3215
tt.delete_contents(trans_id)
3264
tt.create_hardlink(source_tree.id2abspath(file_id), trans_id)
3216
tt.create_hardlink(source_tree.abspath(paths[0]), trans_id)