~bzr/bzr-bisect/trunk

« back to all changes in this revision

Viewing changes to __init__.py

  • Committer: Jelmer Vernooij
  • Date: 2010-11-05 12:19:42 UTC
  • mfrom: (77.1.4 539937-subtree)
  • Revision ID: jelmer@samba.org-20101105121942-cn4vx7rxgj9018t7
Merge several improvements from Gustaf:

* Several testcases for running a test script.
* Fix up doc string format to be the same as other bzr plugins and core.
* Avoid deprecated bzrlib.trace.info.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
"Support for git-style bisection."
 
17
"""Support for git-style bisection."""
18
18
 
19
19
import sys
20
20
import os
22
22
from bzrlib.commands import Command, register_command
23
23
from bzrlib.errors import BzrCommandError
24
24
from bzrlib.option import Option
25
 
from bzrlib.trace import info
 
25
from bzrlib.trace import note
26
26
 
27
27
from meta import *
28
28
 
31
31
 
32
32
 
33
33
class BisectCurrent(object):
34
 
    "Bisect class for managing the current revision."
 
34
    """Bisect class for managing the current revision."""
35
35
 
36
36
    def __init__(self, filename = bisect_rev_path):
37
37
        self._filename = filename
45
45
            self._revid = self._bzrbranch.last_revision()
46
46
 
47
47
    def _save(self):
48
 
        "Save the current revision."
 
48
        """Save the current revision."""
49
49
 
50
50
        revid_file = open(self._filename, "w")
51
51
        revid_file.write(self._revid + "\n")
52
52
        revid_file.close()
53
53
 
54
54
    def get_current_revid(self):
55
 
        "Return the current revision id."
 
55
        """Return the current revision id."""
56
56
        return self._revid
57
57
 
58
58
    def get_current_revno(self):
59
 
        "Return the current revision number as a tuple."
 
59
        """Return the current revision number as a tuple."""
60
60
        revdict = self._bzrbranch.get_revision_id_to_revno_map()
61
61
        return revdict[self.get_current_revid()]
62
62
 
63
63
    def get_parent_revids(self):
64
 
        "Return the IDs of the current revision's predecessors."
 
64
        """Return the IDs of the current revision's predecessors."""
65
65
        repo = self._bzrbranch.repository
66
66
        repo.lock_read()
67
67
        retval = repo.get_parent_map([self._revid]).get(self._revid, None)
69
69
        return retval
70
70
 
71
71
    def is_merge_point(self):
72
 
        "Is the current revision a merge point?"
 
72
        """Is the current revision a merge point?"""
73
73
        return len(self.get_parent_revids()) > 1
74
74
 
75
75
    def show_rev_log(self, out = sys.stdout):
76
 
        "Write the current revision's log entry to a file."
 
76
        """Write the current revision's log entry to a file."""
77
77
        rev = self._bzrbranch.repository.get_revision(self._revid)
78
78
        revno = ".".join([str(x) for x in self.get_current_revno()])
79
79
        out.write("On revision %s (%s):\n%s\n" % (revno, rev.revision_id,
80
80
                                                  rev.message))
81
81
 
82
82
    def switch(self, revid):
83
 
        "Switch the current revision to the given revid."
 
83
        """Switch the current revision to the given revid."""
84
84
        working = self._bzrdir.open_workingtree()
85
85
        if isinstance(revid, int):
86
86
            revid = self._bzrbranch.get_rev_id(revid)
92
92
        self._save()
93
93
 
94
94
    def reset(self):
95
 
        "Revert bisection, setting the working tree to normal."
 
95
        """Revert bisection, setting the working tree to normal."""
96
96
        working = self._bzrdir.open_workingtree()
97
97
        last_rev = working.branch.last_revision()
98
98
        rev_tree = working.branch.repository.revision_tree(last_rev)
102
102
 
103
103
 
104
104
class BisectLog(object):
105
 
    "Bisect log file handler."
 
105
    """Bisect log file handler."""
106
106
 
107
107
    def __init__(self, filename = bisect_info_path):
108
108
        self._items = []
115
115
        self.load()
116
116
 
117
117
    def _open_for_read(self):
118
 
        "Open log file for reading."
 
118
        """Open log file for reading."""
119
119
        if self._filename:
120
120
            return open(self._filename)
121
121
        else:
122
122
            return sys.stdin
123
123
 
124
124
    def _open_for_write(self):
125
 
        "Open log file for writing."
 
125
        """Open log file for writing."""
126
126
        if self._filename:
127
127
            return open(self._filename, "w")
128
128
        else:
129
129
            return sys.stdout
130
130
 
131
131
    def _load_bzr_tree(self):
132
 
        "Load bzr information."
 
132
        """Load bzr information."""
133
133
        if not self._bzrdir:
134
134
            self._bzrdir = bzrlib.bzrdir.BzrDir.open_containing('.')[0]
135
135
            self._bzrbranch = self._bzrdir.open_branch()
136
136
 
137
137
    def _find_range_and_middle(self, branch_last_rev = None):
138
 
        "Find the current revision range, and the midpoint."
 
138
        """Find the current revision range, and the midpoint."""
139
139
        self._load_bzr_tree()
140
140
        self._middle_revid = None
141
141
 
193
193
        self._low_revid = low_revid
194
194
 
195
195
    def _switch_wc_to_revno(self, revno, outf):
196
 
        "Move the working tree to the given revno."
 
196
        """Move the working tree to the given revno."""
197
197
        self._current.switch(revno)
198
198
        self._current.show_rev_log(out=outf)
199
199
 
200
200
    def _set_status(self, revid, status):
201
 
        "Set the bisect status for the given revid."
 
201
        """Set the bisect status for the given revid."""
202
202
        if not self.is_done():
203
203
            if status != "done" and revid in [x[0] for x in self._items 
204
204
                                              if x[1] in ['yes', 'no']]:
206
206
            self._items.append((revid, status))
207
207
 
208
208
    def change_file_name(self, filename):
209
 
        "Switch log files."
 
209
        """Switch log files."""
210
210
        self._filename = filename
211
211
 
212
212
    def load(self):
213
 
        "Load the bisection log."
 
213
        """Load the bisection log."""
214
214
        self._items = []
215
215
        if os.path.exists(self._filename):
216
216
            revlog = self._open_for_read()
219
219
                self._items.append((revid, status))
220
220
 
221
221
    def save(self):
222
 
        "Save the bisection log."
 
222
        """Save the bisection log."""
223
223
        revlog = self._open_for_write()
224
224
        for (revid, status) in self._items:
225
225
            revlog.write("%s %s\n" % (revid, status))
226
226
 
227
227
    def is_done(self):
228
 
        "Report whether we've found the right revision."
 
228
        """Report whether we've found the right revision."""
229
229
        return len(self._items) > 0 and self._items[-1][1] == "done"
230
230
 
231
231
    def set_status_from_revspec(self, revspec, status):
232
 
        "Set the bisection status for the revision in revspec."
 
232
        """Set the bisection status for the revision in revspec."""
233
233
        self._load_bzr_tree()
234
234
        revid = revspec[0].in_history(self._bzrbranch).rev_id
235
235
        self._set_status(revid, status)
236
236
 
237
237
    def set_current(self, status):
238
 
        "Set the current revision to the given bisection status."
 
238
        """Set the current revision to the given bisection status."""
239
239
        self._set_status(self._current.get_current_revid(), status)
240
240
 
241
241
    def is_merge_point(self, revid):
251
251
        return retval
252
252
 
253
253
    def bisect(self, outf):
254
 
        "Using the current revision's status, do a bisection."
 
254
        """Using the current revision's status, do a bisection."""
255
255
        self._find_range_and_middle()
256
256
        # If we've found the "final" revision, check for a
257
257
        # merge point.
322
322
                     'revision']
323
323
 
324
324
    def _check(self):
325
 
        "Check preconditions for most operations to work."
 
325
        """Check preconditions for most operations to work."""
326
326
        if not os.path.exists(bisect_info_path):
327
327
            raise BzrCommandError("No bisection in progress.")
328
328
 
332
332
        Returns boolean indicating if bisection is done."""
333
333
        bisect_log = BisectLog()
334
334
        if bisect_log.is_done():
335
 
            info("No further bisection is possible.\n")
 
335
            note("No further bisection is possible.\n")
336
336
            bisect_log._current.show_rev_log(self.outf)
337
337
            return True
338
338
 
345
345
        return False
346
346
 
347
347
    def run(self, subcommand, args_list, revision=None, output=None):
348
 
        "Handle the bisect command."
 
348
        """Handle the bisect command."""
349
349
 
350
350
        log_fn = None
351
351
        if subcommand in ('yes', 'no', 'move') and revision:
384
384
                "Unknown bisect command: " + subcommand)
385
385
 
386
386
    def reset(self):
387
 
        "Reset the bisect state to no state."
 
387
        """Reset the bisect state to no state."""
388
388
        self._check()
389
389
        BisectCurrent().reset()
390
390
        os.unlink(bisect_info_path)
391
391
 
392
392
    def start(self):
393
 
        "Reset the bisect state, then prepare for a new bisection."
 
393
        """Reset the bisect state, then prepare for a new bisection."""
394
394
        if os.path.exists(bisect_info_path):
395
395
            BisectCurrent().reset()
396
396
            os.unlink(bisect_info_path)
400
400
        bisect_log.save()
401
401
 
402
402
    def yes(self, revspec):
403
 
        "Mark that a given revision has the state we're looking for."
 
403
        """Mark that a given revision has the state we're looking for."""
404
404
        self._set_state(revspec, "yes")
405
405
 
406
406
    def no(self, revspec):
407
 
        "Mark that a given revision does not have the state we're looking for."
 
407
        """Mark that a given revision does not have the state we're looking for."""
408
408
        self._set_state(revspec, "no")
409
409
 
410
410
    def move(self, revspec):
411
 
        "Move to a different revision manually."
 
411
        """Move to a different revision manually."""
412
412
        current = BisectCurrent()
413
413
        current.switch(revspec)
414
414
        current.show_rev_log(out=self.outf)
415
415
 
416
416
    def log(self, filename):
417
 
        "Write the current bisect log to a file."
 
417
        """Write the current bisect log to a file."""
418
418
        self._check()
419
419
        bisect_log = BisectLog()
420
420
        bisect_log.change_file_name(filename)
434
434
 
435
435
    def run_bisect(self, script):
436
436
        import subprocess
437
 
        info("Starting bisect.")
 
437
        note("Starting bisect.")
438
438
        self.start()
439
439
        while True:
440
440
            try: