~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 10:40:51 UTC
  • mfrom: (5425 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5426.
  • Revision ID: mbp@sourcefrog.net-20100915104051-pkjmuc2bc27buysp
merge 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,
348
349
        it possibly being still active.
349
350
        """
350
351
        self._check_not_locked()
351
 
        holder_info = self.peek()
 
352
        try:
 
353
            holder_info = self.peek()
 
354
        except LockCorrupt, e:
 
355
            # The lock info is corrupt.
 
356
            if bzrlib.ui.ui_factory.get_boolean("Break (corrupt %r)" % (self,)):
 
357
                self.force_break_corrupt(e.file_data)
 
358
            return
352
359
        if holder_info is not None:
353
360
            lock_info = '\n'.join(self._format_lock_info(holder_info))
354
361
            if bzrlib.ui.ui_factory.confirm_action(
397
404
        for hook in self.hooks['lock_broken']:
398
405
            hook(result)
399
406
 
 
407
    def force_break_corrupt(self, corrupt_info_lines):
 
408
        """Release a lock that has been corrupted.
 
409
        
 
410
        This is very similar to force_break, it except it doesn't assume that
 
411
        self.peek() can work.
 
412
        
 
413
        :param corrupt_info_lines: the lines of the corrupted info file, used
 
414
            to check that the lock hasn't changed between reading the (corrupt)
 
415
            info file and calling force_break_corrupt.
 
416
        """
 
417
        # XXX: this copes with unparseable info files, but what about missing
 
418
        # info files?  Or missing lock dirs?
 
419
        self._check_not_locked()
 
420
        tmpname = '%s/broken.%s.tmp' % (self.path, rand_chars(20))
 
421
        self.transport.rename(self._held_dir, tmpname)
 
422
        # check that we actually broke the right lock, not someone else;
 
423
        # there's a small race window between checking it and doing the
 
424
        # rename.
 
425
        broken_info_path = tmpname + self.__INFO_NAME
 
426
        f = self.transport.get(broken_info_path)
 
427
        broken_lines = f.readlines()
 
428
        if broken_lines != corrupt_info_lines:
 
429
            raise LockBreakMismatch(self, broken_lines, corrupt_info_lines)
 
430
        self.transport.delete(broken_info_path)
 
431
        self.transport.rmdir(tmpname)
 
432
        result = lock.LockResult(self.transport.abspath(self.path))
 
433
        for hook in self.hooks['lock_broken']:
 
434
            hook(result)
 
435
 
400
436
    def _check_not_locked(self):
401
437
        """If the lock is held by this instance, raise an error."""
402
438
        if self._lock_held:
461
497
        return s.to_string()
462
498
 
463
499
    def _parse_info(self, info_bytes):
464
 
        stanza = rio.read_stanza(osutils.split_lines(info_bytes))
 
500
        lines = osutils.split_lines(info_bytes)
 
501
        try:
 
502
            stanza = rio.read_stanza(lines)
 
503
        except ValueError, e:
 
504
            mutter('Corrupt lock info file: %r', lines)
 
505
            raise LockCorrupt("could not parse lock info file: " + str(e),
 
506
                              lines)
465
507
        if stanza is None:
466
508
            # see bug 185013; we fairly often end up with the info file being
467
509
            # empty after an interruption; we could log a message here but