~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lockdir.py

  • Committer: Martin Pool
  • Date: 2010-09-15 05:18:54 UTC
  • mfrom: (5425 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5452.
  • Revision ID: mbp@sourcefrog.net-20100915051854-fv6x062f38qo82l1
resolveĀ againstĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
120
120
        LockBreakMismatch,
121
121
        LockBroken,
122
122
        LockContention,
 
123
        LockCorrupt,
123
124
        LockFailed,
124
125
        LockNotHeld,
125
126
        NoSuchFile,
350
351
        :returns: LockResult for the broken lock.
351
352
        """
352
353
        self._check_not_locked()
353
 
        holder_info = self.peek()
 
354
        try:
 
355
            holder_info = self.peek()
 
356
        except LockCorrupt, e:
 
357
            # The lock info is corrupt.
 
358
            if bzrlib.ui.ui_factory.get_boolean("Break (corrupt %r)" % (self,)):
 
359
                self.force_break_corrupt(e.file_data)
 
360
            return
354
361
        if holder_info is not None:
355
362
            lock_info = '\n'.join(self._format_lock_info(holder_info))
356
363
            if bzrlib.ui.ui_factory.confirm_action(
404
411
            hook(result)
405
412
        return result
406
413
 
 
414
    def force_break_corrupt(self, corrupt_info_lines):
 
415
        """Release a lock that has been corrupted.
 
416
        
 
417
        This is very similar to force_break, it except it doesn't assume that
 
418
        self.peek() can work.
 
419
        
 
420
        :param corrupt_info_lines: the lines of the corrupted info file, used
 
421
            to check that the lock hasn't changed between reading the (corrupt)
 
422
            info file and calling force_break_corrupt.
 
423
        """
 
424
        # XXX: this copes with unparseable info files, but what about missing
 
425
        # info files?  Or missing lock dirs?
 
426
        self._check_not_locked()
 
427
        tmpname = '%s/broken.%s.tmp' % (self.path, rand_chars(20))
 
428
        self.transport.rename(self._held_dir, tmpname)
 
429
        # check that we actually broke the right lock, not someone else;
 
430
        # there's a small race window between checking it and doing the
 
431
        # rename.
 
432
        broken_info_path = tmpname + self.__INFO_NAME
 
433
        f = self.transport.get(broken_info_path)
 
434
        broken_lines = f.readlines()
 
435
        if broken_lines != corrupt_info_lines:
 
436
            raise LockBreakMismatch(self, broken_lines, corrupt_info_lines)
 
437
        self.transport.delete(broken_info_path)
 
438
        self.transport.rmdir(tmpname)
 
439
        result = lock.LockResult(self.transport.abspath(self.path))
 
440
        for hook in self.hooks['lock_broken']:
 
441
            hook(result)
 
442
 
407
443
    def _check_not_locked(self):
408
444
        """If the lock is held by this instance, raise an error."""
409
445
        if self._lock_held:
468
504
        return s.to_string()
469
505
 
470
506
    def _parse_info(self, info_bytes):
471
 
        stanza = rio.read_stanza(osutils.split_lines(info_bytes))
 
507
        lines = osutils.split_lines(info_bytes)
 
508
        try:
 
509
            stanza = rio.read_stanza(lines)
 
510
        except ValueError, e:
 
511
            mutter('Corrupt lock info file: %r', lines)
 
512
            raise LockCorrupt("could not parse lock info file: " + str(e),
 
513
                              lines)
472
514
        if stanza is None:
473
515
            # see bug 185013; we fairly often end up with the info file being
474
516
            # empty after an interruption; we could log a message here but