1158
1158
def get_backup_name(entry, by_parent, parent_trans_id, tt):
1159
return _get_backup_name(entry.name, by_parent, parent_trans_id, tt)
1162
def _get_backup_name(name, by_parent, parent_trans_id, tt):
1159
1163
"""Produce a backup-style name that appears to be available"""
1160
1164
def name_gen():
1163
yield "%s.~%d~" % (entry.name, counter)
1167
yield "%s.~%d~" % (name, counter)
1165
for name in name_gen():
1166
if not tt.has_named_child(by_parent, parent_trans_id, name):
1169
for new_name in name_gen():
1170
if not tt.has_named_child(by_parent, parent_trans_id, new_name):
1169
1174
def _entry_changes(file_id, entry, working_tree):
1170
1175
"""Determine in which ways the inventory entry has changed.
1197
1202
pb=DummyProgress()):
1198
1203
"""Revert a working tree's contents to those of a target tree."""
1199
1204
interesting_ids = find_interesting(working_tree, target_tree, filenames)
1200
def interesting(file_id):
1201
return interesting_ids is None or (file_id in interesting_ids)
1203
1205
tt = TreeTransform(working_tree, pb)
1205
merge_modified = working_tree.merge_modified()
1207
def trans_id_file_id(file_id):
1209
return trans_id[file_id]
1211
return tt.trans_id_tree_file_id(file_id)
1213
pp = ProgressPhase("Revert phase", 4, pb)
1215
sorted_interesting = [i for i in topology_sorted_ids(target_tree) if
1217
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1219
by_parent = tt.by_parent()
1220
for id_num, file_id in enumerate(sorted_interesting):
1221
child_pb.update("Reverting file", id_num+1,
1222
len(sorted_interesting))
1223
if file_id not in working_tree.inventory:
1224
entry = target_tree.inventory[file_id]
1225
parent_id = trans_id_file_id(entry.parent_id)
1226
e_trans_id = new_by_entry(tt, entry, parent_id, target_tree)
1227
trans_id[file_id] = e_trans_id
1229
backup_this = backups
1230
if file_id in merge_modified:
1232
del merge_modified[file_id]
1233
change_entry(tt, file_id, working_tree, target_tree,
1234
trans_id_file_id, backup_this, trans_id,
1239
wt_interesting = [i for i in working_tree.inventory if interesting(i)]
1240
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1243
for id_num, file_id in enumerate(wt_interesting):
1244
if (working_tree.inventory.is_root(file_id) and
1245
len(target_tree.inventory) == 0):
1247
child_pb.update("New file check", id_num+1,
1248
len(sorted_interesting))
1249
if file_id not in target_tree:
1250
trans_id = tt.trans_id_tree_file_id(file_id)
1251
tt.unversion_file(trans_id)
1253
file_kind = working_tree.kind(file_id)
1256
delete_merge_modified = (file_id in merge_modified)
1257
if file_kind != 'file' and file_kind is not None:
1258
keep_contents = False
1260
if basis_tree is None:
1261
basis_tree = working_tree.basis_tree()
1262
wt_sha1 = working_tree.get_file_sha1(file_id)
1263
if (file_id in merge_modified and
1264
merge_modified[file_id] == wt_sha1):
1265
keep_contents = False
1266
elif (file_id in basis_tree and
1267
basis_tree.get_file_sha1(file_id) == wt_sha1):
1268
keep_contents = False
1270
keep_contents = True
1271
if not keep_contents:
1272
tt.delete_contents(trans_id)
1273
if delete_merge_modified:
1274
del merge_modified[file_id]
1207
pp = ProgressPhase("Revert phase", 3, pb)
1209
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1211
_alter_files(working_tree, target_tree, tt, child_pb,
1212
interesting_ids, backups)
1276
1214
child_pb.finished()
1277
1215
pp.next_phase()
1292
1230
return conflicts
1233
def _alter_files(working_tree, target_tree, tt, pb, interesting_ids, backups):
1234
merge_modified = working_tree.merge_modified()
1235
iterator = target_tree._iter_changes(working_tree,
1236
specific_file_ids=interesting_ids,
1238
if target_tree.inventory.root is None:
1243
for id_num, (file_id, path, changed_content, versioned, parent, name, kind,
1244
executable) in enumerate(iterator):
1245
if skip_root and file_id[0] is not None and parent[0] is None:
1247
trans_id = tt.trans_id_file_id(file_id)
1250
keep_content = False
1251
if kind[0] == 'file' and (backups or kind[1] is None):
1252
wt_sha1 = working_tree.get_file_sha1(file_id)
1253
if merge_modified.get(file_id) != wt_sha1:
1254
if basis_tree is None:
1255
basis_tree = working_tree.basis_tree()
1256
if file_id in basis_tree:
1257
if wt_sha1 != basis_tree.get_file_sha1(file_id):
1259
elif kind[1] is None and not versioned[1]:
1261
if kind[0] is not None:
1262
if not keep_content:
1263
tt.delete_contents(trans_id)
1264
elif kind[1] is not None:
1265
parent_trans_id = tt.trans_id_file_id(parent[0])
1266
by_parent = tt.by_parent()
1267
backup_name = _get_backup_name(name[0], by_parent,
1268
parent_trans_id, tt)
1269
tt.adjust_path(backup_name, parent_trans_id, trans_id)
1270
new_trans_id = tt.create_path(name[0], parent_trans_id)
1271
if versioned == (True, True):
1272
tt.unversion_file(trans_id)
1273
tt.version_file(file_id, new_trans_id)
1274
# New contents should have the same unix perms as old
1277
trans_id = new_trans_id
1278
if kind[1] == 'directory':
1279
tt.create_directory(trans_id)
1280
elif kind[1] == 'symlink':
1281
tt.create_symlink(target_tree.get_symlink_target(file_id),
1283
elif kind[1] == 'file':
1284
tt.create_file(target_tree.get_file_lines(file_id),
1286
# preserve the execute bit when backing up
1287
if keep_content and executable[0] == executable[1]:
1288
tt.set_executability(executable[1], trans_id)
1290
assert kind[1] is None
1291
if versioned == (False, True):
1292
tt.version_file(file_id, trans_id)
1293
if versioned == (True, False):
1294
tt.unversion_file(trans_id)
1295
if (name[1] is not None and
1296
(name[0] != name[1] or parent[0] != parent[1])):
1297
tt.adjust_path(name[1], tt.trans_id_file_id(parent[1]), trans_id)
1298
if executable[0] != executable[1] and kind[1] == "file":
1299
tt.set_executability(executable[1], trans_id)
1295
1302
def resolve_conflicts(tt, pb=DummyProgress(), pass_func=None):
1296
1303
"""Make many conflict-resolution attempts, but die if they fail"""
1297
1304
if pass_func is None: