~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lock.py

(igc) Improve paths are not versioned reporting (Benoît PIERRE)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 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
37
37
import errno
38
38
import os
39
39
import sys
40
 
import warnings
41
40
 
42
41
from bzrlib import (
43
 
    debug,
44
42
    errors,
45
43
    osutils,
46
44
    trace,
84
82
        return self.lock_url == other.lock_url and self.details == other.details
85
83
 
86
84
    def __repr__(self):
87
 
        return '%s(%s, %s)' % (self.__class__.__name__,
 
85
        return '%s(%s%s)' % (self.__class__.__name__,
88
86
                             self.lock_url, self.details)
89
87
 
90
88
 
91
 
def cant_unlock_not_held(locked_object):
92
 
    """An attempt to unlock failed because the object was not locked.
93
 
 
94
 
    This provides a policy point from which we can generate either a warning 
95
 
    or an exception.
96
 
    """
97
 
    # This is typically masking some other error and called from a finally
98
 
    # block, so it's useful to have the option not to generate a new error
99
 
    # here.  You can use -Werror to make it fatal.  It should possibly also
100
 
    # raise LockNotHeld.
101
 
    if 'unlock' in debug.debug_flags:
102
 
        warnings.warn("%r is already unlocked" % (locked_object,),
103
 
            stacklevel=3)
104
 
    else:
105
 
        raise errors.LockNotHeld(locked_object)
106
 
 
107
 
 
108
89
try:
109
90
    import fcntl
110
91
    have_fcntl = True
190
171
            if self.filename in _fcntl_WriteLock._open_locks:
191
172
                self._clear_f()
192
173
                raise errors.LockContention(self.filename)
193
 
            if self.filename in _fcntl_ReadLock._open_locks:
194
 
                if 'strict_locks' in debug.debug_flags:
195
 
                    self._clear_f()
196
 
                    raise errors.LockContention(self.filename)
197
 
                else:
198
 
                    trace.mutter('Write lock taken w/ an open read lock on: %s'
199
 
                                 % (self.filename,))
200
174
 
201
175
            self._open(self.filename, 'rb+')
202
176
            # reserve a slot for this lock - even if the lockf call fails,
203
 
            # at this point unlock() will be called, because self.f is set.
 
177
            # at thisi point unlock() will be called, because self.f is set.
204
178
            # TODO: make this fully threadsafe, if we decide we care.
205
179
            _fcntl_WriteLock._open_locks.add(self.filename)
206
180
            try:
227
201
        def __init__(self, filename):
228
202
            super(_fcntl_ReadLock, self).__init__()
229
203
            self.filename = osutils.realpath(filename)
230
 
            if self.filename in _fcntl_WriteLock._open_locks:
231
 
                if 'strict_locks' in debug.debug_flags:
232
 
                    # We raise before calling _open so we don't need to
233
 
                    # _clear_f
234
 
                    raise errors.LockContention(self.filename)
235
 
                else:
236
 
                    trace.mutter('Read lock taken w/ an open write lock on: %s'
237
 
                                 % (self.filename,))
238
204
            _fcntl_ReadLock._open_locks.setdefault(self.filename, 0)
239
205
            _fcntl_ReadLock._open_locks[self.filename] += 1
240
206
            self._open(filename, 'rb')
335
301
 
336
302
 
337
303
if have_pywin32 and sys.platform == 'win32':
338
 
    if os.path.supports_unicode_filenames:
339
 
        # for Windows NT/2K/XP/etc
340
 
        win32file_CreateFile = win32file.CreateFileW
341
 
    else:
342
 
        # for Windows 98
343
 
        win32file_CreateFile = win32file.CreateFile
344
304
 
345
305
    class _w32c_FileLock(_OSLock):
346
306
 
347
307
        def _open(self, filename, access, share, cflags, pymode):
348
308
            self.filename = osutils.realpath(filename)
349
309
            try:
350
 
                self._handle = win32file_CreateFile(filename, access, share,
 
310
                self._handle = win32file.CreateFile(filename, access, share,
351
311
                    None, win32file.OPEN_ALWAYS,
352
312
                    win32file.FILE_ATTRIBUTE_NORMAL, None)
353
313
            except pywintypes.error, e:
433
393
            DWORD,                 # dwFlagsAndAttributes
434
394
            HANDLE                 # hTemplateFile
435
395
        )((_function_name, ctypes.windll.kernel32))
436
 
 
 
396
    
437
397
    INVALID_HANDLE_VALUE = -1
438
 
 
 
398
    
439
399
    GENERIC_READ = 0x80000000
440
400
    GENERIC_WRITE = 0x40000000
441
401
    FILE_SHARE_READ = 1
442
402
    OPEN_ALWAYS = 4
443
403
    FILE_ATTRIBUTE_NORMAL = 128
444
 
 
 
404
    
445
405
    ERROR_ACCESS_DENIED = 5
446
406
    ERROR_SHARING_VIOLATION = 32
447
407
 
518
478
# We default to using the first available lock class.
519
479
_lock_type, WriteLock, ReadLock = _lock_classes[0]
520
480
 
521
 
 
522
 
class _RelockDebugMixin(object):
523
 
    """Mixin support for -Drelock flag.
524
 
 
525
 
    Add this as a base class then call self._note_lock with 'r' or 'w' when
526
 
    acquiring a read- or write-lock.  If this object was previously locked (and
527
 
    locked the same way), and -Drelock is set, then this will trace.note a
528
 
    message about it.
529
 
    """
530
 
    
531
 
    _prev_lock = None
532
 
 
533
 
    def _note_lock(self, lock_type):
534
 
        if 'relock' in debug.debug_flags and self._prev_lock == lock_type:
535
 
            if lock_type == 'r':
536
 
                type_name = 'read'
537
 
            else:
538
 
                type_name = 'write'
539
 
            trace.note('%r was %s locked again', self, type_name)
540
 
        self._prev_lock = lock_type
541