~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lockdir.py

  • Committer: John Arbash Meinel
  • Date: 2011-05-11 11:35:28 UTC
  • mto: This revision was merged to the branch mainline in revision 5851.
  • Revision ID: john@arbash-meinel.com-20110511113528-qepibuwxicjrbb2h
Break compatibility with python <2.6.

This includes auditing the code for places where we were doing
explicit 'sys.version' checks and removing them as appropriate.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
120
120
        LockBreakMismatch,
121
121
        LockBroken,
122
122
        LockContention,
 
123
        LockCorrupt,
123
124
        LockFailed,
124
125
        LockNotHeld,
125
126
        NoSuchFile,
346
347
        This is a UI centric function: it uses the bzrlib.ui.ui_factory to
347
348
        prompt for input if a lock is detected and there is any doubt about
348
349
        it possibly being still active.
 
350
 
 
351
        :returns: LockResult for the broken lock.
349
352
        """
350
353
        self._check_not_locked()
351
 
        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
352
361
        if holder_info is not None:
353
362
            lock_info = '\n'.join(self._format_lock_info(holder_info))
354
 
            if bzrlib.ui.ui_factory.get_boolean("Break %s" % lock_info):
355
 
                self.force_break(holder_info)
 
363
            if bzrlib.ui.ui_factory.confirm_action(
 
364
                "Break %(lock_info)s", 'bzrlib.lockdir.break', 
 
365
                dict(lock_info=lock_info)):
 
366
                result = self.force_break(holder_info)
 
367
                bzrlib.ui.ui_factory.show_message(
 
368
                    "Broke lock %s" % result.lock_url)
356
369
 
357
370
    def force_break(self, dead_holder_info):
358
371
        """Release a lock held by another process.
369
382
        After the lock is broken it will not be held by any process.
370
383
        It is possible that another process may sneak in and take the
371
384
        lock before the breaking process acquires it.
 
385
 
 
386
        :returns: LockResult for the broken lock.
372
387
        """
373
388
        if not isinstance(dead_holder_info, dict):
374
389
            raise ValueError("dead_holder_info: %r" % dead_holder_info)
394
409
                                 current_info.get('nonce'))
395
410
        for hook in self.hooks['lock_broken']:
396
411
            hook(result)
 
412
        return result
 
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
        broken_content = self.transport.get_bytes(broken_info_path)
 
434
        broken_lines = osutils.split_lines(broken_content)
 
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)
397
442
 
398
443
    def _check_not_locked(self):
399
444
        """If the lock is held by this instance, raise an error."""
459
504
        return s.to_string()
460
505
 
461
506
    def _parse_info(self, info_bytes):
462
 
        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)
463
514
        if stanza is None:
464
515
            # see bug 185013; we fairly often end up with the info file being
465
516
            # empty after an interruption; we could log a message here but
486
537
            hook(hook_result)
487
538
        return result
488
539
 
 
540
    def lock_url_for_display(self):
 
541
        """Give a nicely-printable representation of the URL of this lock."""
 
542
        # As local lock urls are correct we display them.
 
543
        # We avoid displaying remote lock urls.
 
544
        lock_url = self.transport.abspath(self.path)
 
545
        if lock_url.startswith('file://'):
 
546
            lock_url = lock_url.split('.bzr/')[0]
 
547
        else:
 
548
            lock_url = ''
 
549
        return lock_url
 
550
 
489
551
    def wait_lock(self, timeout=None, poll=None, max_attempts=None):
490
552
        """Wait a certain period for a lock.
491
553
 
515
577
        deadline_str = None
516
578
        last_info = None
517
579
        attempt_count = 0
 
580
        lock_url = self.lock_url_for_display()
518
581
        while True:
519
582
            attempt_count += 1
520
583
            try:
539
602
                if deadline_str is None:
540
603
                    deadline_str = time.strftime('%H:%M:%S',
541
604
                                                 time.localtime(deadline))
542
 
                # As local lock urls are correct we display them.
543
 
                # We avoid displaying remote lock urls.
544
 
                lock_url = self.transport.abspath(self.path)
545
 
                if lock_url.startswith('file://'):
546
 
                    lock_url = lock_url.split('.bzr/')[0]
547
 
                else:
548
 
                    lock_url = ''
549
605
                user, hostname, pid, time_ago = formatted_info
550
606
                msg = ('%s lock %s '        # lock_url
551
607
                    'held by '              # start