/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.62.1 by Jelmer Vernooij
Lazy load plugin.
1
# Copyright (C) 2006-2011 Canonical Ltd
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
6656.2.1 by Jelmer Vernooij
Integrate bisect command into core.
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0.62.1 by Jelmer Vernooij
Lazy load plugin.
16
17
"""bisect command implementations."""
18
6625.4.4 by Jelmer Vernooij
Drop meta file.
19
from __future__ import absolute_import
20
0.62.1 by Jelmer Vernooij
Lazy load plugin.
21
import sys
6656.2.3 by Jelmer Vernooij
Merge trunk.
22
from .controldir import ControlDir
6656.2.1 by Jelmer Vernooij
Integrate bisect command into core.
23
from . import revision as _mod_revision
24
from .commands import Command
25
from .errors import BzrCommandError
26
from .option import Option
27
from .trace import note
0.62.1 by Jelmer Vernooij
Lazy load plugin.
28
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
29
BISECT_INFO_PATH = "bisect"
30
BISECT_REV_PATH = "bisect_revid"
0.62.1 by Jelmer Vernooij
Lazy load plugin.
31
32
33
class BisectCurrent(object):
34
    """Bisect class for managing the current revision."""
35
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
36
    def __init__(self, controldir, filename=BISECT_REV_PATH):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
37
        self._filename = filename
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
38
        self._controldir = controldir
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
39
        self._branch = self._controldir.open_branch()
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
40
        if self._controldir.control_transport.has(filename):
41
            self._revid = self._controldir.control_transport.get_bytes(
42
                filename).strip()
0.62.1 by Jelmer Vernooij
Lazy load plugin.
43
        else:
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
44
            self._revid = self._branch.last_revision()
0.62.1 by Jelmer Vernooij
Lazy load plugin.
45
46
    def _save(self):
47
        """Save the current revision."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
48
        self._controldir.control_transport.put_bytes(
49
            self._filename, self._revid + "\n")
0.62.1 by Jelmer Vernooij
Lazy load plugin.
50
51
    def get_current_revid(self):
52
        """Return the current revision id."""
53
        return self._revid
54
55
    def get_current_revno(self):
56
        """Return the current revision number as a tuple."""
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
57
        revdict = self._branch.get_revision_id_to_revno_map()
0.62.1 by Jelmer Vernooij
Lazy load plugin.
58
        return revdict[self.get_current_revid()]
59
60
    def get_parent_revids(self):
61
        """Return the IDs of the current revision's predecessors."""
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
62
        repo = self._branch.repository
0.62.1 by Jelmer Vernooij
Lazy load plugin.
63
        repo.lock_read()
64
        retval = repo.get_parent_map([self._revid]).get(self._revid, None)
65
        repo.unlock()
66
        return retval
67
68
    def is_merge_point(self):
69
        """Is the current revision a merge point?"""
70
        return len(self.get_parent_revids()) > 1
71
72
    def show_rev_log(self, out = sys.stdout):
73
        """Write the current revision's log entry to a file."""
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
74
        rev = self._branch.repository.get_revision(self._revid)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
75
        revno = ".".join([str(x) for x in self.get_current_revno()])
76
        out.write("On revision %s (%s):\n%s\n" % (revno, rev.revision_id,
77
                                                  rev.message))
78
79
    def switch(self, revid):
80
        """Switch the current revision to the given revid."""
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
81
        working = self._controldir.open_workingtree()
0.62.1 by Jelmer Vernooij
Lazy load plugin.
82
        if isinstance(revid, int):
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
83
            revid = self._branch.get_rev_id(revid)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
84
        elif isinstance(revid, list):
85
            revid = revid[0].in_history(working.branch).rev_id
86
        working.revert(None, working.branch.repository.revision_tree(revid),
87
                       False)
88
        self._revid = revid
89
        self._save()
90
91
    def reset(self):
92
        """Revert bisection, setting the working tree to normal."""
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
93
        working = self._controldir.open_workingtree()
0.62.1 by Jelmer Vernooij
Lazy load plugin.
94
        last_rev = working.branch.last_revision()
95
        rev_tree = working.branch.repository.revision_tree(last_rev)
96
        working.revert(None, rev_tree, False)
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
97
        if self._controldir.control_transport.has(BISECT_REV_PATH):
98
            self._controldir.control_transport.delete(BISECT_REV_PATH)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
99
100
101
class BisectLog(object):
102
    """Bisect log file handler."""
103
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
104
    def __init__(self, controldir, filename=BISECT_INFO_PATH):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
105
        self._items = []
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
106
        self._current = BisectCurrent(controldir)
107
        self._controldir = controldir
108
        self._branch = None
0.62.1 by Jelmer Vernooij
Lazy load plugin.
109
        self._high_revid = None
110
        self._low_revid = None
111
        self._middle_revid = None
112
        self._filename = filename
113
        self.load()
114
115
    def _open_for_read(self):
116
        """Open log file for reading."""
117
        if self._filename:
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
118
            return self._controldir.control_transport.get(self._filename)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
119
        else:
120
            return sys.stdin
121
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
122
    def _load_tree(self):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
123
        """Load bzr information."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
124
        if not self._branch:
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
125
            self._branch = self._controldir.open_branch()
0.62.1 by Jelmer Vernooij
Lazy load plugin.
126
127
    def _find_range_and_middle(self, branch_last_rev = None):
128
        """Find the current revision range, and the midpoint."""
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
129
        self._load_tree()
0.62.1 by Jelmer Vernooij
Lazy load plugin.
130
        self._middle_revid = None
131
132
        if not branch_last_rev:
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
133
            last_revid = self._branch.last_revision()
0.62.1 by Jelmer Vernooij
Lazy load plugin.
134
        else:
135
            last_revid = branch_last_rev
136
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
137
        repo = self._branch.repository
0.62.1 by Jelmer Vernooij
Lazy load plugin.
138
        repo.lock_read()
139
        try:
0.63.1 by Thomi Richards
Use graph.iter_lefthand_ancestry instead of repo.iter_reverse_revision_history.
140
            graph = repo.get_graph()
141
            rev_sequence = graph.iter_lefthand_ancestry(last_revid,
142
                (_mod_revision.NULL_REVISION,))
0.62.1 by Jelmer Vernooij
Lazy load plugin.
143
            high_revid = None
144
            low_revid = None
145
            between_revs = []
146
            for revision in rev_sequence:
147
                between_revs.insert(0, revision)
148
                matches = [x[1] for x in self._items
149
                           if x[0] == revision and x[1] in ('yes', 'no')]
150
                if not matches:
151
                    continue
152
                if len(matches) > 1:
153
                    raise RuntimeError("revision %s duplicated" % revision)
154
                if matches[0] == "yes":
155
                    high_revid = revision
156
                    between_revs = []
157
                elif matches[0] == "no":
158
                    low_revid = revision
159
                    del between_revs[0]
160
                    break
161
162
            if not high_revid:
163
                high_revid = last_revid
164
            if not low_revid:
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
165
                low_revid = self._branch.get_rev_id(1)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
166
        finally:
167
            repo.unlock()
168
169
        # The spread must include the high revision, to bias
170
        # odd numbers of intervening revisions towards the high
171
        # side.
172
173
        spread = len(between_revs) + 1
174
        if spread < 2:
175
            middle_index = 0
176
        else:
177
            middle_index = (spread / 2) - 1
178
179
        if len(between_revs) > 0:
180
            self._middle_revid = between_revs[middle_index]
181
        else:
182
            self._middle_revid = high_revid
183
184
        self._high_revid = high_revid
185
        self._low_revid = low_revid
186
187
    def _switch_wc_to_revno(self, revno, outf):
188
        """Move the working tree to the given revno."""
189
        self._current.switch(revno)
190
        self._current.show_rev_log(out=outf)
191
192
    def _set_status(self, revid, status):
193
        """Set the bisect status for the given revid."""
194
        if not self.is_done():
0.63.1 by Thomi Richards
Use graph.iter_lefthand_ancestry instead of repo.iter_reverse_revision_history.
195
            if status != "done" and revid in [x[0] for x in self._items
0.62.1 by Jelmer Vernooij
Lazy load plugin.
196
                                              if x[1] in ['yes', 'no']]:
197
                raise RuntimeError("attempting to add revid %s twice" % revid)
198
            self._items.append((revid, status))
199
200
    def change_file_name(self, filename):
201
        """Switch log files."""
202
        self._filename = filename
203
204
    def load(self):
205
        """Load the bisection log."""
206
        self._items = []
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
207
        if self._controldir.control_transport.has(self._filename):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
208
            revlog = self._open_for_read()
209
            for line in revlog:
210
                (revid, status) = line.split()
211
                self._items.append((revid, status))
212
213
    def save(self):
214
        """Save the bisection log."""
6681.2.8 by Jelmer Vernooij
Remove incorrect b''.
215
        contents = ''.join(
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
216
            ("%s %s\n" % (revid, status))
217
            for (revid, status) in self._items)
218
        if self._filename:
219
            self._controldir.control_transport.put_bytes(
220
                self._filename, contents)
221
        else:
222
            sys.stdout.write(contents)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
223
224
    def is_done(self):
225
        """Report whether we've found the right revision."""
226
        return len(self._items) > 0 and self._items[-1][1] == "done"
227
228
    def set_status_from_revspec(self, revspec, status):
229
        """Set the bisection status for the revision in revspec."""
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
230
        self._load_tree()
231
        revid = revspec[0].in_history(self._branch).rev_id
0.62.1 by Jelmer Vernooij
Lazy load plugin.
232
        self._set_status(revid, status)
233
234
    def set_current(self, status):
235
        """Set the current revision to the given bisection status."""
236
        self._set_status(self._current.get_current_revid(), status)
237
238
    def is_merge_point(self, revid):
239
        return len(self.get_parent_revids(revid)) > 1
240
241
    def get_parent_revids(self, revid):
6681.2.1 by Jelmer Vernooij
Rename more uses of bzrdir to controldir.
242
        repo = self._branch.repository
0.62.1 by Jelmer Vernooij
Lazy load plugin.
243
        repo.lock_read()
244
        try:
245
            retval = repo.get_parent_map([revid]).get(revid, None)
246
        finally:
247
            repo.unlock()
248
        return retval
249
250
    def bisect(self, outf):
251
        """Using the current revision's status, do a bisection."""
252
        self._find_range_and_middle()
253
        # If we've found the "final" revision, check for a
254
        # merge point.
255
        while ((self._middle_revid == self._high_revid
256
                or self._middle_revid == self._low_revid)
257
                and self.is_merge_point(self._middle_revid)):
258
            for parent in self.get_parent_revids(self._middle_revid):
259
                if parent == self._low_revid:
260
                    continue
261
                else:
262
                    self._find_range_and_middle(parent)
263
                    break
264
        self._switch_wc_to_revno(self._middle_revid, outf)
265
        if self._middle_revid == self._high_revid or \
266
           self._middle_revid == self._low_revid:
267
            self.set_current("done")
268
269
270
class cmd_bisect(Command):
271
    """Find an interesting commit using a binary search.
272
273
    Bisecting, in a nutshell, is a way to find the commit at which
274
    some testable change was made, such as the introduction of a bug
275
    or feature.  By identifying a version which did not have the
276
    interesting change and a later version which did, a developer
277
    can test for the presence of the change at various points in
278
    the history, eventually ending up at the precise commit when
279
    the change was first introduced.
280
281
    This command uses subcommands to implement the search, each
282
    of which changes the state of the bisection.  The
283
    subcommands are:
284
6656.2.1 by Jelmer Vernooij
Integrate bisect command into core.
285
    brz bisect start
0.62.1 by Jelmer Vernooij
Lazy load plugin.
286
        Start a bisect, possibly clearing out a previous bisect.
287
6656.2.1 by Jelmer Vernooij
Integrate bisect command into core.
288
    brz bisect yes [-r rev]
0.62.1 by Jelmer Vernooij
Lazy load plugin.
289
        The specified revision (or the current revision, if not given)
290
        has the characteristic we're looking for,
291
6656.2.1 by Jelmer Vernooij
Integrate bisect command into core.
292
    brz bisect no [-r rev]
0.62.1 by Jelmer Vernooij
Lazy load plugin.
293
        The specified revision (or the current revision, if not given)
294
        does not have the characteristic we're looking for,
295
6656.2.1 by Jelmer Vernooij
Integrate bisect command into core.
296
    brz bisect move -r rev
0.62.1 by Jelmer Vernooij
Lazy load plugin.
297
        Switch to a different revision manually.  Use if the bisect
298
        algorithm chooses a revision that is not suitable.  Try to
299
        move as little as possible.
300
6656.2.1 by Jelmer Vernooij
Integrate bisect command into core.
301
    brz bisect reset
0.62.1 by Jelmer Vernooij
Lazy load plugin.
302
        Clear out a bisection in progress.
303
6656.2.1 by Jelmer Vernooij
Integrate bisect command into core.
304
    brz bisect log [-o file]
0.62.1 by Jelmer Vernooij
Lazy load plugin.
305
        Output a log of the current bisection to standard output, or
306
        to the specified file.
307
6656.2.1 by Jelmer Vernooij
Integrate bisect command into core.
308
    brz bisect replay <logfile>
0.62.1 by Jelmer Vernooij
Lazy load plugin.
309
        Replay a previously-saved bisect log, forgetting any bisection
310
        that might be in progress.
311
6656.2.1 by Jelmer Vernooij
Integrate bisect command into core.
312
    brz bisect run <script>
0.62.1 by Jelmer Vernooij
Lazy load plugin.
313
        Bisect automatically using <script> to determine 'yes' or 'no'.
314
        <script> should exit with:
315
           0 for yes
316
           125 for unknown (like build failed so we could not test)
317
           anything else for no
318
    """
319
320
    takes_args = ['subcommand', 'args*']
321
    takes_options = [Option('output', short_name='o',
322
                            help='Write log to this file.', type=unicode),
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
323
                     'revision', 'directory']
0.62.1 by Jelmer Vernooij
Lazy load plugin.
324
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
325
    def _check(self, controldir):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
326
        """Check preconditions for most operations to work."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
327
        if not controldir.control_transport.has(BISECT_INFO_PATH):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
328
            raise BzrCommandError("No bisection in progress.")
329
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
330
    def _set_state(self, controldir, revspec, state):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
331
        """Set the state of the given revspec and bisecting.
332
333
        Returns boolean indicating if bisection is done."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
334
        bisect_log = BisectLog(controldir)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
335
        if bisect_log.is_done():
336
            note("No further bisection is possible.\n")
337
            bisect_log._current.show_rev_log(self.outf)
338
            return True
339
340
        if revspec:
341
            bisect_log.set_status_from_revspec(revspec, state)
342
        else:
343
            bisect_log.set_current(state)
344
        bisect_log.bisect(self.outf)
345
        bisect_log.save()
346
        return False
347
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
348
    def run(self, subcommand, args_list, directory='.', revision=None, output=None):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
349
        """Handle the bisect command."""
350
351
        log_fn = None
352
        if subcommand in ('yes', 'no', 'move') and revision:
353
            pass
354
        elif subcommand in ('replay', ) and args_list and len(args_list) == 1:
355
            log_fn = args_list[0]
356
        elif subcommand in ('move', ) and not revision:
357
            raise BzrCommandError(
358
                "The 'bisect move' command requires a revision.")
359
        elif subcommand in ('run', ):
360
            run_script = args_list[0]
361
        elif args_list or revision:
362
            raise BzrCommandError(
363
                "Improper arguments to bisect " + subcommand)
364
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
365
        controldir, _ = ControlDir.open_containing(directory)
366
0.62.1 by Jelmer Vernooij
Lazy load plugin.
367
        # Dispatch.
368
        if subcommand == "start":
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
369
            self.start(controldir)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
370
        elif subcommand == "yes":
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
371
            self.yes(controldir, revision)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
372
        elif subcommand == "no":
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
373
            self.no(controldir, revision)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
374
        elif subcommand == "move":
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
375
            self.move(controldir, revision)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
376
        elif subcommand == "reset":
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
377
            self.reset(controldir)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
378
        elif subcommand == "log":
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
379
            self.log(controldir, output)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
380
        elif subcommand == "replay":
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
381
            self.replay(controldir, log_fn)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
382
        elif subcommand == "run":
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
383
            self.run_bisect(controldir, run_script)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
384
        else:
385
            raise BzrCommandError(
386
                "Unknown bisect command: " + subcommand)
387
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
388
    def reset(self, controldir):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
389
        """Reset the bisect state to no state."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
390
        self._check(controldir)
391
        BisectCurrent(controldir).reset()
392
        controldir.control_transport.delete(BISECT_INFO_PATH)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
393
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
394
    def start(self, controldir):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
395
        """Reset the bisect state, then prepare for a new bisection."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
396
        if controldir.control_transport.has(BISECT_INFO_PATH):
397
            BisectCurrent(controldir).reset()
398
            controldir.control_transport.delete(BISECT_INFO_PATH)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
399
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
400
        bisect_log = BisectLog(controldir)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
401
        bisect_log.set_current("start")
402
        bisect_log.save()
403
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
404
    def yes(self, controldir, revspec):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
405
        """Mark that a given revision has the state we're looking for."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
406
        self._set_state(controldir, revspec, "yes")
0.62.1 by Jelmer Vernooij
Lazy load plugin.
407
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
408
    def no(self, controldir, revspec):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
409
        """Mark that a given revision does not have the state we're looking for."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
410
        self._set_state(controldir, revspec, "no")
0.62.1 by Jelmer Vernooij
Lazy load plugin.
411
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
412
    def move(self, controldir, revspec):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
413
        """Move to a different revision manually."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
414
        current = BisectCurrent(controldir)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
415
        current.switch(revspec)
416
        current.show_rev_log(out=self.outf)
417
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
418
    def log(self, controldir, filename):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
419
        """Write the current bisect log to a file."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
420
        self._check(controldir)
421
        bisect_log = BisectLog(controldir)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
422
        bisect_log.change_file_name(filename)
423
        bisect_log.save()
424
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
425
    def replay(self, controldir, filename):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
426
        """Apply the given log file to a clean state, so the state is
427
        exactly as it was when the log was saved."""
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
428
        if controldir.control_transport.has(BISECT_INFO_PATH):
429
            BisectCurrent(controldir).reset()
430
            controldir.control_transport.delete(BISECT_INFO_PATH)
431
        bisect_log = BisectLog(controldir, filename)
432
        bisect_log.change_file_name(BISECT_INFO_PATH)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
433
        bisect_log.save()
434
435
        bisect_log.bisect(self.outf)
436
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
437
    def run_bisect(self, controldir, script):
0.62.1 by Jelmer Vernooij
Lazy load plugin.
438
        import subprocess
439
        note("Starting bisect.")
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
440
        self.start(controldir)
0.62.1 by Jelmer Vernooij
Lazy load plugin.
441
        while True:
442
            try:
443
                process = subprocess.Popen(script, shell=True)
444
                process.wait()
445
                retcode = process.returncode
446
                if retcode == 0:
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
447
                    done = self._set_state(controldir, None, 'yes')
0.62.1 by Jelmer Vernooij
Lazy load plugin.
448
                elif retcode == 125:
449
                    break
450
                else:
6681.2.2 by Jelmer Vernooij
Use controldir API in bisect.
451
                    done = self._set_state(controldir, None, 'no')
0.62.1 by Jelmer Vernooij
Lazy load plugin.
452
                if done:
453
                    break
454
            except RuntimeError:
455
                break