/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.436.2 by Jelmer Vernooij
Add stubs for testsuite, rebase-continue and rebase-abort commands.
1
# Copyright (C) 2006-2007 by Jelmer Vernooij
2
# 
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0.436.16 by Jelmer Vernooij
Some more work on maptree.
16
"""Rebase."""
0.436.3 by Jelmer Vernooij
Fill in commands.
17
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
18
from bzrlib.config import Config
0.436.16 by Jelmer Vernooij
Some more work on maptree.
19
from bzrlib.errors import BzrError, NoSuchFile, UnknownFormatError
0.436.4 by Jelmer Vernooij
Add some tests.
20
from bzrlib.generate_ids import gen_revision_id
0.436.10 by Jelmer Vernooij
Add more agressive version of revert.
21
from bzrlib import osutils
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
22
from bzrlib.revision import NULL_REVISION
0.436.4 by Jelmer Vernooij
Add some tests.
23
from bzrlib.trace import mutter
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
24
import bzrlib.ui as ui
0.436.4 by Jelmer Vernooij
Add some tests.
25
0.436.17 by Jelmer Vernooij
Move maptree code to separate files.
26
from maptree import MapTree, map_file_ids
27
0.436.3 by Jelmer Vernooij
Fill in commands.
28
REBASE_PLAN_FILENAME = 'rebase-plan'
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
29
REBASE_CURRENT_REVID_FILENAME = 'rebase-current'
0.436.4 by Jelmer Vernooij
Add some tests.
30
REBASE_PLAN_VERSION = 1
0.436.3 by Jelmer Vernooij
Fill in commands.
31
32
def rebase_plan_exists(wt):
33
    """Check whether there is a rebase plan present.
34
35
    :param wt: Working tree for which to check.
36
    :return: boolean
37
    """
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
38
    try:
39
        return wt._control_files.get(REBASE_PLAN_FILENAME).read() != ''
40
    except NoSuchFile:
41
        return False
0.436.3 by Jelmer Vernooij
Fill in commands.
42
43
44
def read_rebase_plan(wt):
45
    """Read a rebase plan file.
46
47
    :param wt: Working Tree for which to write the plan.
0.436.4 by Jelmer Vernooij
Add some tests.
48
    :return: Tuple with last revision info and replace map.
0.436.3 by Jelmer Vernooij
Fill in commands.
49
    """
50
    text = wt._control_files.get(REBASE_PLAN_FILENAME).read()
51
    if text == '':
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
52
        raise NoSuchFile(REBASE_PLAN_FILENAME)
0.436.4 by Jelmer Vernooij
Add some tests.
53
    return unmarshall_rebase_plan(text)
54
55
56
def write_rebase_plan(wt, replace_map):
0.436.3 by Jelmer Vernooij
Fill in commands.
57
    """Write a rebase plan file.
58
59
    :param wt: Working Tree for which to write the plan.
0.436.4 by Jelmer Vernooij
Add some tests.
60
    :param replace_map: Replace map (old revid -> (new revid, new parents))
0.436.3 by Jelmer Vernooij
Fill in commands.
61
    """
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
62
    wt._control_files.put_utf8(REBASE_PLAN_FILENAME, 
63
            marshall_rebase_plan(wt.branch.last_revision_info(), replace_map))
0.436.3 by Jelmer Vernooij
Fill in commands.
64
65
66
def remove_rebase_plan(wt):
67
    """Remove a rebase plan file.
68
69
    :param wt: Working Tree for which to remove the plan.
70
    """
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
71
    wt._control_files.put_utf8(REBASE_PLAN_FILENAME, '')
0.436.3 by Jelmer Vernooij
Fill in commands.
72
73
0.436.4 by Jelmer Vernooij
Add some tests.
74
def marshall_rebase_plan(last_rev_info, replace_map):
0.436.3 by Jelmer Vernooij
Fill in commands.
75
    """Marshall a rebase plan.
76
77
    :param last_rev_info: Last revision info tuple.
0.436.4 by Jelmer Vernooij
Add some tests.
78
    :param replace_map: Replace map (old revid -> (new revid, new parents))
0.436.3 by Jelmer Vernooij
Fill in commands.
79
    :return: string
80
    """
0.436.4 by Jelmer Vernooij
Add some tests.
81
    ret = "# Bazaar rebase plan %d\n" % REBASE_PLAN_VERSION
82
    ret += "%d %s\n" % last_rev_info
83
    for oldrev in replace_map:
84
        (newrev, newparents) = replace_map[oldrev]
85
        ret += "%s %s" % (oldrev, newrev) + \
86
            "".join([" %s" % p for p in newparents]) + "\n"
87
    return ret
88
89
90
def unmarshall_rebase_plan(text):
0.436.3 by Jelmer Vernooij
Fill in commands.
91
    """Unmarshall a rebase plan.
92
93
    :param text: Text to parse
0.436.4 by Jelmer Vernooij
Add some tests.
94
    :return: Tuple with last revision info, replace map.
0.436.3 by Jelmer Vernooij
Fill in commands.
95
    """
0.436.4 by Jelmer Vernooij
Add some tests.
96
    lines = text.split('\n')
97
    # Make sure header is there
98
    if lines[0] != "# Bazaar rebase plan %d" % REBASE_PLAN_VERSION:
99
        raise UnknownFormatError(lines[0])
100
101
    pts = lines[1].split(" ", 1)
102
    last_revision_info = (int(pts[0]), pts[1])
103
    replace_map = {}
104
    for l in lines[2:]:
105
        if l == "":
106
            # Skip empty lines
107
            continue
108
        pts = l.split(" ")
109
        replace_map[pts[0]] = (pts[1], pts[2:])
110
    return (last_revision_info, replace_map)
111
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
112
113
def regenerate_default_revid(rev):
114
    return gen_revision_id(rev.committer, rev.timestamp)
115
116
117
def generate_simple_plan(repository, history, start_revid, onto_revid, 
118
                         generate_revid=regenerate_default_revid):
0.436.3 by Jelmer Vernooij
Fill in commands.
119
    """Create a simple rebase plan that replays history based 
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
120
    on one revision being replayed on top of another.
0.436.3 by Jelmer Vernooij
Fill in commands.
121
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
122
    :param repository: Repository
123
    :param history: Revision history
124
    :param start_revid: Id of revision at which to start replaying
125
    :param onto_revid: Id of revision on top of which to replay
126
    :param generate_revid: Function for generating new revision ids
0.436.3 by Jelmer Vernooij
Fill in commands.
127
0.436.4 by Jelmer Vernooij
Add some tests.
128
    :return: replace map
0.436.3 by Jelmer Vernooij
Fill in commands.
129
    """
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
130
    assert start_revid in history
131
    assert repository.has_revision(start_revid)
132
    assert repository.has_revision(onto_revid)
133
    replace_map = {}
134
    i = history.index(start_revid)
135
    new_parent = onto_revid
136
    for oldrevid in history[i:]: 
137
        rev = repository.get_revision(oldrevid)
138
        parents = rev.parent_ids
139
        assert len(parents) == 0 or \
140
                parents[0] == history[history.index(oldrevid)-1]
141
        parents[0] = new_parent
142
        newrevid = generate_revid(rev)
143
        assert newrevid != oldrevid
144
        replace_map[oldrevid] = (newrevid, parents)
145
        new_parent = newrevid
146
    return replace_map
147
148
149
def generate_transpose_plan(repository, graph, renames, 
150
        generate_revid=regenerate_default_revid):
151
    """Create a rebase plan that replaces the bottom of 
152
    a revision graph.
153
154
    :param repository: Repository
155
    :param graph: Revision graph in which to operate
156
    :param renames: Renames of revision
157
    :param generate_revid: Function for creating new revision ids
158
    """
159
    replace_map = {}
160
    todo = []
161
    for r in renames:
162
        replace_map[r] = (renames[r], 
163
                          repository.revision_parents(renames[r]))
164
        todo.append(r)
0.436.13 by Jelmer Vernooij
Add progress bar, some optimizations. Make merge type configurable.
165
    
166
    children = {}
167
    for r in graph:
168
        if not children.has_key(r):
169
            children[r] = []
170
        for p in graph[r]:
171
            if not children.has_key(p):
172
                children[p] = []
173
            children[p].append(r)
174
175
    total = len(todo)
176
    processed = set()
177
    i = 0
178
    pb = ui.ui_factory.nested_progress_bar()
179
    try:
180
        while len(todo) > 0:
181
            r = todo.pop()
182
            i += 1
183
            pb.update('determining dependencies', i, total)
184
            # Add entry for them in replace_map
185
            for c in children[r]:
186
                if c in renames:
187
                    continue
188
                rev = repository.get_revision(c)
189
                if replace_map.has_key(c):
190
                    parents = replace_map[c][1]
191
                else:
192
                    parents = rev.parent_ids
193
                # replace r in parents with replace_map[r][0]
194
                if not replace_map[r][0] in parents:
195
                    parents[parents.index(r)] = replace_map[r][0]
196
                replace_map[c] = (generate_revid(rev), parents)
197
                assert replace_map[c][0] != rev.revision_id
198
            processed.add(r)
199
            # Add them to todo[]
0.436.15 by Jelmer Vernooij
Fix inverse bug - needs tests.
200
            todo.extend(filter(lambda x: not x in processed, children[r]))
0.436.13 by Jelmer Vernooij
Add progress bar, some optimizations. Make merge type configurable.
201
    finally:
202
        pb.finished()
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
203
204
    return replace_map
205
206
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
207
def rebase_todo(repository, replace_map):
208
    """Figure out what revisions still need to be rebased.
209
210
    :param repository: Repository that contains the revisions
211
    :param replace_map: Replace map
212
    """
213
    for revid in replace_map:
214
        if not repository.has_revision(replace_map[revid][0]):
215
            yield revid
216
217
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
218
def rebase(repository, replace_map, replay_fn):
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
219
    """Rebase a working tree according to the specified map.
220
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
221
    :param repository: Repository that contains the revisions
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
222
    :param replace_map: Dictionary with revisions to (optionally) rewrite
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
223
    :param merge_fn: Function for replaying a revision
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
224
    """
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
225
    todo = list(rebase_todo(repository, replace_map))
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
226
    dependencies = {}
227
228
    # Figure out the dependencies
229
    for revid in todo:
230
        for p in replace_map[revid][1]:
231
            if repository.has_revision(p):
232
                continue
233
            if not dependencies.has_key(p):
234
                dependencies[p] = []
235
            dependencies[p].append(revid)
236
237
    pb = ui.ui_factory.nested_progress_bar()
0.436.22 by Jelmer Vernooij
Try to improve the progress bar a bit.
238
    total = len(todo)
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
239
    i = 0
240
    try:
241
        while len(todo) > 0:
0.436.22 by Jelmer Vernooij
Try to improve the progress bar a bit.
242
            pb.update('rebase revisions', i, total)
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
243
            i += 1
244
            revid = todo.pop()
245
            (newrevid, newparents) = replace_map[revid]
0.436.19 by Jelmer Vernooij
- Add blackbox tests
246
            if filter(repository.has_revision, newparents) != newparents:
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
247
                # Not all parents present yet, avoid for now
248
                continue
249
            if repository.has_revision(newrevid):
250
                # Was already converted, no need to worry about it again
251
                continue
252
            replay_fn(repository, revid, newrevid, newparents)
253
            assert repository.has_revision(newrevid)
254
            assert repository.revision_parents(newrevid) == newparents
255
            if dependencies.has_key(newrevid):
256
                todo.extend(dependencies[newrevid])
257
                del dependencies[newrevid]
258
    finally:
259
        pb.finished()
260
        
0.436.19 by Jelmer Vernooij
- Add blackbox tests
261
    #assert all(map(repository.has_revision, 
262
    #           [replace_map[r][0] for r in replace_map]))
0.436.16 by Jelmer Vernooij
Some more work on maptree.
263
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
264
def replay_snapshot(repository, oldrevid, newrevid, new_parents):
265
    """Replay a commit by simply commiting the same snapshot with different parents.
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
266
267
    :param repository: Repository in which the revision is present.
268
    :param oldrevid: Revision id of the revision to copy.
269
    :param newrevid: Revision id of the revision to create.
270
    :param new_parents: Revision ids of the new parent revisions.
271
    """
272
    assert isinstance(new_parents, list)
0.436.16 by Jelmer Vernooij
Some more work on maptree.
273
    mutter('creating copy %r of %r with new parents %r' % 
274
                               (newrevid, oldrevid, new_parents))
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
275
    oldrev = repository.get_revision(oldrevid)
276
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
277
    revprops = dict(oldrev.properties)
278
    revprops['rebase-of'] = oldrevid
279
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
280
    builder = repository.get_commit_builder(branch=None, parents=new_parents, 
281
                                  config=Config(),
282
                                  committer=oldrev.committer,
283
                                  timestamp=oldrev.timestamp,
284
                                  timezone=oldrev.timezone,
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
285
                                  revprops=revprops,
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
286
                                  revision_id=newrevid)
287
288
    # Check what new_ie.file_id should be
289
    # use old and new parent inventories to generate new_id map
0.436.16 by Jelmer Vernooij
Some more work on maptree.
290
    fileid_map = map_file_ids(repository, oldrev.parent_ids, new_parents)
291
    oldtree = MapTree(repository.revision_tree(oldrevid), fileid_map)
292
    total = len(oldtree.inventory)
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
293
    pb = ui.ui_factory.nested_progress_bar()
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
294
    i = 0
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
295
    try:
0.436.14 by Jelmer Vernooij
More speed optimizations, deal with already created revisions.
296
        parent_invs = map(repository.get_revision_inventory, new_parents)
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
297
        transact = repository.get_transaction()
0.436.16 by Jelmer Vernooij
Some more work on maptree.
298
        for path, ie in oldtree.inventory.iter_entries():
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
299
            pb.update('upgrading file', i, total)
300
            i += 1
0.436.16 by Jelmer Vernooij
Some more work on maptree.
301
            builder.record_entry_contents(ie, 
0.436.14 by Jelmer Vernooij
More speed optimizations, deal with already created revisions.
302
                    parent_invs,
0.436.5 by Jelmer Vernooij
Import change_revision_parent from bzr-svn.
303
                   path, oldtree)
304
    finally:
305
        pb.finished()
306
307
    builder.finish_inventory()
308
    return builder.commit(oldrev.message)
309
310
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
311
def commit_rebase(wt, oldrev, newrevid):
312
    """Commit a rebase.
313
    
314
    :param wt: Mutable tree with the changes.
315
    :param oldrev: Revision info of new revision to commit.
316
    :param newrevid: New revision id."""
317
    assert oldrev.revision_id != newrevid
318
    revprops = dict(oldrev.properties)
319
    revprops['rebase-of'] = oldrev.revision_id
320
    wt.commit(message=oldrev.message, timestamp=oldrev.timestamp, timezone=oldrev.timezone,
321
              revprops=revprops, rev_id=newrevid)
322
    write_active_rebase_revid(wt, None)
323
324
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
325
def replay_delta_workingtree(wt, oldrevid, newrevid, newparents, map_ids=False,
326
        merge_type=None):
327
    """Replay a commit in a working tree, with a different base.
328
329
    :param wt: Working tree in which to do the replays.
330
    :param oldrevid: Old revision id
331
    :param newrevid: New revision id
332
    :param newparents: New parent revision ids
333
    :param map_ids: Whether to map file ids from the rebased revision using 
334
        the old and new parent tree file ids.
335
    """
336
    repository = wt.branch.repository
337
    if merge_type is None:
338
        from bzrlib.merge import Merge3Merger
339
        merge_type = Merge3Merger
340
    oldrev = wt.branch.repository.get_revision(oldrevid)
341
    # Make sure there are no conflicts or pending merges/changes 
342
    # in the working tree
343
    if wt.changes_from(wt.basis_tree()).has_changed():
344
        raise BzrError("Working tree has uncommitted changes.")
0.436.10 by Jelmer Vernooij
Add more agressive version of revert.
345
    complete_revert(wt, newparents)
0.436.8 by Jelmer Vernooij
Couple more minor fixes.
346
    assert not wt.changes_from(wt.basis_tree()).has_changed()
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
347
348
    oldtree = repository.revision_tree(oldrevid)
349
    basetree = repository.revision_tree(oldrev.parent_ids[0])
350
    if map_ids:
0.436.16 by Jelmer Vernooij
Some more work on maptree.
351
        fileid_map = map_file_ids(repository, oldrev.parent_ids, new_parents)
352
        oldtree = MapTree(repository, oldtree, fileid_map)
353
        basetree = MapTree(repository, basetree, fileid_map)
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
354
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
355
    write_active_rebase_revid(wt, oldrevid)
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
356
    merge = merge_type(working_tree=wt, this_tree=wt, 
357
            base_tree=basetree,
358
            other_tree=oldtree)
359
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
360
    commit_rebase(wt, oldrev, newrevid)
0.436.8 by Jelmer Vernooij
Couple more minor fixes.
361
0.436.10 by Jelmer Vernooij
Add more agressive version of revert.
362
0.436.13 by Jelmer Vernooij
Add progress bar, some optimizations. Make merge type configurable.
363
def workingtree_replay(wt, map_ids=False, merge_type=None):
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
364
    """Returns a function that can replay revisions in wt.
365
366
    :param wt: Working tree in which to do the replays.
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
367
    :param map_ids: Whether to try to map between file ids (False for path-based merge)
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
368
    """
369
    def replay(repository, oldrevid, newrevid, newparents):
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
370
        assert wt.branch.repository == repository
0.436.16 by Jelmer Vernooij
Some more work on maptree.
371
        return replay_delta_workingtree(wt, oldrevid, newrevid, newparents, 
372
                                        merge_type=merge_type)
0.436.6 by Jelmer Vernooij
Add somewhat more complex plan generation function, rebase implementation.
373
    return replay
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
374
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
375
376
def write_active_rebase_revid(wt, revid):
0.436.16 by Jelmer Vernooij
Some more work on maptree.
377
    """Write the id of the revision that is currently being rebased. 
378
379
    :param wt: Working Tree that is being used for the rebase.
380
    :param revid: Revision id to write
381
    """
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
382
    if revid is None:
383
        revid = NULL_REVISION
384
    wt._control_files.put_utf8(REBASE_CURRENT_REVID_FILENAME, revid)
385
0.436.10 by Jelmer Vernooij
Add more agressive version of revert.
386
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
387
def read_active_rebase_revid(wt):
0.436.16 by Jelmer Vernooij
Some more work on maptree.
388
    """Read the id of the revision that is currently being rebased.
389
390
    :param wt: Working Tree that is being used for the rebase.
391
    :return: Id of the revision that is being rebased.
392
    """
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
393
    try:
394
        text = wt._control_files.get(REBASE_CURRENT_REVID_FILENAME).read().rstrip("\n")
395
        if text == NULL_REVISION:
396
            return None
397
        return text
398
    except NoSuchFile:
399
        return None
0.436.10 by Jelmer Vernooij
Add more agressive version of revert.
400
401
402
def complete_revert(wt, newparents):
0.436.16 by Jelmer Vernooij
Some more work on maptree.
403
    """Simple helper that reverts to specified new parents and makes sure none 
404
    of the extra files are left around.
405
406
    :param wt: Working tree to use for rebase
407
    :param newparents: New parents of the working tree
0.436.10 by Jelmer Vernooij
Add more agressive version of revert.
408
    """
409
    newtree = wt.branch.repository.revision_tree(newparents[0])
410
    delta = wt.changes_from(newtree)
411
    wt.branch.generate_revision_history(newparents[0])
412
    wt.set_parent_ids(newparents)
413
    for (f, _, _) in delta.added:
414
        abs_path = wt.abspath(f)
415
        if osutils.lexists(abs_path):
416
            osutils.delete_any(abs_path)
417
    wt.revert([], old_tree=newtree, backups=False)