[Pkg-bazaar-commits] ./bzr/unstable r580: - Use explicit lock methods on a branch, rather than doing it

Martin Pool mbp at sourcefrog.net
Fri Apr 10 08:19:41 UTC 2009


------------------------------------------------------------
revno: 580
committer: Martin Pool <mbp at sourcefrog.net>
timestamp: Mon 2005-05-30 11:37:52 +1000
message:
  - Use explicit lock methods on a branch, rather than doing it
    implicitly from the Branch constructor and relying on destroying the
    branch to release the lock.
  
  - New with_readlock, _with_writelock decorators for branch methods.
  
  - Branch locks can now be taken several times by a single caller, but
    they forbid upgrading or downgrading.
  
  - Don't need assertions about whether the branch is locked anymore.
modified:
  bzrlib/branch.py
  bzrlib/commands.py
  bzrlib/commit.py
  bzrlib/remotebranch.py
  bzrlib/status.py
-------------- next part --------------
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py	2005-05-27 05:23:57 +0000
+++ b/bzrlib/branch.py	2005-05-30 01:37:52 +0000
@@ -43,6 +43,29 @@
         return remotebranch.RemoteBranch(f, **args)
     else:
         return Branch(f, **args)
+
+
+
+def with_writelock(method):
+    """Method decorator for functions run with the branch locked."""
+    def d(self, *a, **k):
+        # called with self set to the branch
+        self.lock('w')
+        try:
+            return method(self, *a, **k)
+        finally:
+            self.unlock()
+    return d
+
+
+def with_readlock(method):
+    def d(self, *a, **k):
+        self.lock('r')
+        try:
+            return method(self, *a, **k)
+        finally:
+            self.unlock()
+    return d
         
 
 def find_branch_root(f=None):
@@ -87,16 +110,20 @@
         Base directory of the branch.
 
     _lock_mode
-        None, or a duple with 'r' or 'w' for the first element and a positive
-        count for the second.
+        None, or 'r' or 'w'
+
+    _lock_count
+        If _lock_mode is true, a positive count of the number of times the
+        lock has been taken.
 
     _lockfile
         Open file used for locking.
     """
     base = None
     _lock_mode = None
+    _lock_count = None
     
-    def __init__(self, base, init=False, find_root=True, lock_mode='w'):
+    def __init__(self, base, init=False, find_root=True):
         """Create new branch object at a particular location.
 
         base -- Base directory for the branch.
@@ -125,7 +152,6 @@
                                       'current bzr can only operate from top-of-tree'])
         self._check_format()
         self._lockfile = self.controlfile('branch-lock', 'wb')
-        self.lock(lock_mode)
 
         self.text_store = ImmutableStore(self.controlfilename('text-store'))
         self.revision_store = ImmutableStore(self.controlfilename('revision-store'))
@@ -148,36 +174,36 @@
 
     def lock(self, mode):
         if self._lock_mode:
-            raise BzrError('branch %r is already locked: %r' % (self, self._lock_mode))
-
-        from bzrlib.lock import lock, LOCK_SH, LOCK_EX
-        if mode == 'r':
-            m = LOCK_SH
-        elif mode == 'w':
-            m = LOCK_EX
+            if mode == 'w' and cur_lm == 'r':
+                raise BzrError("can't upgrade to a write lock")
+            
+            assert self._lock_count >= 1
+            self._lock_count += 1
         else:
-            raise ValueError('invalid lock mode %r' % mode)
-        
-        lock(self._lockfile, m)
-        self._lock_mode = (mode, 1)
+            from bzrlib.lock import lock, LOCK_SH, LOCK_EX
+            if mode == 'r':
+                m = LOCK_SH
+            elif mode == 'w':
+                m = LOCK_EX
+            else:
+                raise ValueError('invalid lock mode %r' % mode)
+
+            lock(self._lockfile, m)
+            self._lock_mode = mode
+            self._lock_count = 1
 
 
     def unlock(self):
         if not self._lock_mode:
             raise BzrError('branch %r is not locked' % (self))
-        from bzrlib.lock import unlock
-        unlock(self._lockfile)
-        self._lock_mode = None
-
-
-    def _need_readlock(self):
-        if not self._lock_mode:
-            raise BzrError('need read lock on branch, only have %r' % self._lockmode)
-
-
-    def _need_writelock(self):
-        if (self._lock_mode == None) or (self._lock_mode[0] != 'w'):
-            raise BzrError('need write lock on branch, only have %r' % self._lockmode)
+
+        if self._lock_count > 1:
+            self._lock_count -= 1
+        else:
+            assert self._lock_count == 1
+            from bzrlib.lock import unlock
+            unlock(self._lockfile)
+            self._lock_mode = self._lock_count = None
 
 
     def abspath(self, name):
@@ -268,9 +294,10 @@
                             'or remove the .bzr directory and "bzr init" again'])
 
 
+
+    @with_readlock
     def read_working_inventory(self):
         """Read the working inventory."""
-        self._need_readlock()
         before = time.time()
         # ElementTree does its own conversion from UTF-8, so open in
         # binary.
@@ -278,7 +305,7 @@
         mutter("loaded inventory of %d items in %f"
                % (len(inv), time.time() - before))
         return inv
-
+            
 
     def _write_inventory(self, inv):
         """Update the working inventory.
@@ -286,7 +313,6 @@
         That is to say, the inventory describing changes underway, that
         will be committed to the next revision.
         """
-        self._need_writelock()
         ## TODO: factor out to atomicfile?  is rename safe on windows?
         ## TODO: Maybe some kind of clean/dirty marker on inventory?
         tmpfname = self.controlfilename('inventory.tmp')
@@ -298,12 +324,13 @@
             os.remove(inv_fname)
         os.rename(tmpfname, inv_fname)
         mutter('wrote working inventory')
-
+            
 
     inventory = property(read_working_inventory, _write_inventory, None,
                          """Inventory for the working copy.""")
 
 
+    @with_writelock
     def add(self, files, verbose=False, ids=None):
         """Make files versioned.
 
@@ -324,8 +351,6 @@
                add all non-ignored children.  Perhaps do that in a
                higher-level method.
         """
-        self._need_writelock()
-
         # TODO: Re-adding a file that is removed in the working copy
         # should probably put it back with the previous ID.
         if isinstance(files, types.StringTypes):
@@ -338,7 +363,7 @@
             ids = [None] * len(files)
         else:
             assert(len(ids) == len(files))
-        
+
         inv = self.read_working_inventory()
         for f,file_id in zip(files, ids):
             if is_control_file(f):
@@ -348,7 +373,7 @@
 
             if len(fp) == 0:
                 raise BzrError("cannot add top-level %r" % f)
-                
+
             fullpath = os.path.normpath(self.abspath(f))
 
             try:
@@ -356,7 +381,7 @@
             except OSError:
                 # maybe something better?
                 raise BzrError('cannot add: not a regular file or directory: %s' % quotefn(f))
-            
+
             if kind != 'file' and kind != 'directory':
                 raise BzrError('cannot add: not a regular file or directory: %s' % quotefn(f))
 
@@ -366,23 +391,23 @@
 
             if verbose:
                 show_status('A', kind, quotefn(f))
-                
+
             mutter("add file %s file_id:{%s} kind=%r" % (f, file_id, kind))
+
+        self._write_inventory(inv)
             
-        self._write_inventory(inv)
-
 
     def print_file(self, file, revno):
         """Print `file` to stdout."""
-        self._need_readlock()
         tree = self.revision_tree(self.lookup_revision(revno))
         # use inventory as it was in that revision
         file_id = tree.inventory.path2id(file)
         if not file_id:
             raise BzrError("%r is not present in revision %d" % (file, revno))
         tree.print_file(file_id)
-        
-
+
+
+    @with_writelock
     def remove(self, files, verbose=False):
         """Mark nominated files for removal from the inventory.
 
@@ -399,11 +424,9 @@
         """
         ## TODO: Normalize names
         ## TODO: Remove nested loops; better scalability
-        self._need_writelock()
-
         if isinstance(files, types.StringTypes):
             files = [files]
-        
+
         tree = self.working_tree()
         inv = tree.inventory
 
@@ -424,6 +447,7 @@
 
         self._write_inventory(inv)
 
+
     def set_inventory(self, new_inventory_list):
         inv = Inventory()
         for path, file_id, parent, kind in new_inventory_list:
@@ -474,7 +498,6 @@
 
     def get_revision(self, revision_id):
         """Return the Revision object for a named revision"""
-        self._need_readlock()
         r = Revision.read_xml(self.revision_store[revision_id])
         assert r.revision_id == revision_id
         return r
@@ -486,27 +509,25 @@
         TODO: Perhaps for this and similar methods, take a revision
                parameter which can be either an integer revno or a
                string hash."""
-        self._need_readlock()
         i = Inventory.read_xml(self.inventory_store[inventory_id])
         return i
 
 
     def get_revision_inventory(self, revision_id):
         """Return inventory of a past revision."""
-        self._need_readlock()
         if revision_id == None:
             return Inventory()
         else:
             return self.get_inventory(self.get_revision(revision_id).inventory_id)
 
 
+    @with_readlock
     def revision_history(self):
         """Return sequence of revision hashes on to this branch.
 
         >>> ScratchBranch().revision_history()
         []
         """
-        self._need_readlock()
         return [l.rstrip('\r\n') for l in self.controlfile('revision-history', 'r').readlines()]
 
 
@@ -576,7 +597,6 @@
         an `EmptyTree` is returned."""
         # TODO: refactor this to use an existing revision object
         # so we don't need to read it in twice.
-        self._need_readlock()
         if revision_id == None:
             return EmptyTree()
         else:
@@ -603,19 +623,19 @@
 
 
 
+    @with_writelock
     def rename_one(self, from_rel, to_rel):
         """Rename one file.
 
         This can change the directory or the filename or both.
         """
-        self._need_writelock()
         tree = self.working_tree()
         inv = tree.inventory
         if not tree.has_filename(from_rel):
             raise BzrError("can't rename: old working file %r does not exist" % from_rel)
         if tree.has_filename(to_rel):
             raise BzrError("can't rename: new working file %r already exists" % to_rel)
-            
+
         file_id = inv.path2id(from_rel)
         if file_id == None:
             raise BzrError("can't rename: old name %r is not versioned" % from_rel)
@@ -634,11 +654,11 @@
         mutter("  to_rel     %r" % to_rel)
         mutter("  to_dir     %r" % to_dir)
         mutter("  to_dir_id  {%s}" % to_dir_id)
-            
+
         inv.rename(file_id, to_dir_id, to_tail)
 
         print "%s => %s" % (from_rel, to_rel)
-        
+
         from_abs = self.abspath(from_rel)
         to_abs = self.abspath(to_rel)
         try:
@@ -649,9 +669,10 @@
                     ["rename rolled back"])
 
         self._write_inventory(inv)
-            
-
-
+
+
+
+    @with_writelock
     def move(self, from_paths, to_name):
         """Rename files.
 
@@ -663,7 +684,6 @@
         Note that to_name is only the last component of the new name;
         this doesn't change the directory.
         """
-        self._need_writelock()
         ## TODO: Option to move IDs only
         assert not isinstance(from_paths, basestring)
         tree = self.working_tree()

=== modified file 'bzrlib/commands.py'
--- a/bzrlib/commands.py	2005-05-27 04:08:47 +0000
+++ b/bzrlib/commands.py	2005-05-30 01:37:52 +0000
@@ -263,14 +263,14 @@
     
     def run(self, all=False, show_ids=False, file_list=None):
         if file_list:
-            b = Branch(file_list[0], lock_mode='r')
+            b = Branch(file_list[0])
             file_list = [b.relpath(x) for x in file_list]
             # special case: only one path was given and it's the root
             # of the branch
             if file_list == ['']:
                 file_list = None
         else:
-            b = Branch('.', lock_mode='r')
+            b = Branch('.')
         import status
         status.show_status(b, show_unchanged=all, show_ids=show_ids,
                            specific_files=file_list)
@@ -531,13 +531,13 @@
         from bzrlib import find_branch
 
         if file_list:
-            b = find_branch(file_list[0], lock_mode='r')
+            b = find_branch(file_list[0])
             file_list = [b.relpath(f) for f in file_list]
             if file_list == ['']:
                 # just pointing to top-of-tree
                 file_list = None
         else:
-            b = Branch('.', lock_mode='r')
+            b = Branch('.')
     
         show_diff(b, revision, specific_files=file_list,
                   external_diff_options=diff_options)
@@ -652,14 +652,14 @@
         direction = (forward and 'forward') or 'reverse'
         
         if filename:
-            b = find_branch(filename, lock_mode='r')
+            b = find_branch(filename)
             fp = b.relpath(filename)
             if fp:
                 file_id = b.read_working_inventory().path2id(fp)
             else:
                 file_id = None  # points to branch root
         else:
-            b = find_branch('.', lock_mode='r')
+            b = find_branch('.')
             file_id = None
 
         if revision == None:
@@ -693,7 +693,7 @@
     hidden = True
     takes_args = ["filename"]
     def run(self, filename):
-        b = Branch(filename, lock_mode='r')
+        b = Branch(filename)
         inv = b.read_working_inventory()
         file_id = inv.path2id(b.relpath(filename))
         for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):

=== modified file 'bzrlib/commit.py'
--- a/bzrlib/commit.py	2005-05-17 06:51:31 +0000
+++ b/bzrlib/commit.py	2005-05-30 01:37:52 +0000
@@ -64,166 +64,169 @@
     from revision import Revision
     from trace import mutter, note
 
-    branch._need_writelock()
-
-    # First walk over the working inventory; and both update that
-    # and also build a new revision inventory.  The revision
-    # inventory needs to hold the text-id, sha1 and size of the
-    # actual file versions committed in the revision.  (These are
-    # not present in the working inventory.)  We also need to
-    # detect missing/deleted files, and remove them from the
-    # working inventory.
-
-    work_tree = branch.working_tree()
-    work_inv = work_tree.inventory
-    inv = Inventory()
-    basis = branch.basis_tree()
-    basis_inv = basis.inventory
-    missing_ids = []
-
-    if verbose:
-        note('looking for changes...')
-        
-    for path, entry in work_inv.iter_entries():
-        ## TODO: Check that the file kind has not changed from the previous
-        ## revision of this file (if any).
-
-        entry = entry.copy()
-
-        p = branch.abspath(path)
-        file_id = entry.file_id
-        mutter('commit prep file %s, id %r ' % (p, file_id))
-
-        if specific_files and not is_inside_any(specific_files, path):
+    branch.lock('w')
+
+    try:
+        # First walk over the working inventory; and both update that
+        # and also build a new revision inventory.  The revision
+        # inventory needs to hold the text-id, sha1 and size of the
+        # actual file versions committed in the revision.  (These are
+        # not present in the working inventory.)  We also need to
+        # detect missing/deleted files, and remove them from the
+        # working inventory.
+
+        work_tree = branch.working_tree()
+        work_inv = work_tree.inventory
+        inv = Inventory()
+        basis = branch.basis_tree()
+        basis_inv = basis.inventory
+        missing_ids = []
+
+        if verbose:
+            note('looking for changes...')
+
+        for path, entry in work_inv.iter_entries():
+            ## TODO: Check that the file kind has not changed from the previous
+            ## revision of this file (if any).
+
+            entry = entry.copy()
+
+            p = branch.abspath(path)
+            file_id = entry.file_id
+            mutter('commit prep file %s, id %r ' % (p, file_id))
+
+            if specific_files and not is_inside_any(specific_files, path):
+                if basis_inv.has_id(file_id):
+                    # carry over with previous state
+                    inv.add(basis_inv[file_id].copy())
+                else:
+                    # omit this from committed inventory
+                    pass
+                continue
+
+            if not work_tree.has_id(file_id):
+                if verbose:
+                    print('deleted %s%s' % (path, kind_marker(entry.kind)))
+                mutter("    file is missing, removing from inventory")
+                missing_ids.append(file_id)
+                continue
+
+            inv.add(entry)
+
             if basis_inv.has_id(file_id):
-                # carry over with previous state
-                inv.add(basis_inv[file_id].copy())
-            else:
-                # omit this from committed inventory
-                pass
-            continue
-
-        if not work_tree.has_id(file_id):
-            if verbose:
-                print('deleted %s%s' % (path, kind_marker(entry.kind)))
-            mutter("    file is missing, removing from inventory")
-            missing_ids.append(file_id)
-            continue
-
-        inv.add(entry)
-
-        if basis_inv.has_id(file_id):
-            old_kind = basis_inv[file_id].kind
-            if old_kind != entry.kind:
-                raise BzrError("entry %r changed kind from %r to %r"
-                        % (file_id, old_kind, entry.kind))
-
-        if entry.kind == 'directory':
-            if not isdir(p):
-                raise BzrError("%s is entered as directory but not a directory"
-                               % quotefn(p))
-        elif entry.kind == 'file':
-            if not isfile(p):
-                raise BzrError("%s is entered as file but is not a file" % quotefn(p))
-
-            new_sha1 = work_tree.get_file_sha1(file_id)
-
-            old_ie = basis_inv.has_id(file_id) and basis_inv[file_id]
-            if (old_ie
-                and old_ie.text_sha1 == new_sha1):
-                ## assert content == basis.get_file(file_id).read()
-                entry.text_id = old_ie.text_id
-                entry.text_sha1 = new_sha1
-                entry.text_size = old_ie.text_size
-                mutter('    unchanged from previous text_id {%s}' %
-                       entry.text_id)
-            else:
-                content = file(p, 'rb').read()
-
-                # calculate the sha again, just in case the file contents
-                # changed since we updated the cache
-                entry.text_sha1 = sha_string(content)
-                entry.text_size = len(content)
-
-                entry.text_id = gen_file_id(entry.name)
-                branch.text_store.add(content, entry.text_id)
-                mutter('    stored with text_id {%s}' % entry.text_id)
-                if verbose:
-                    if not old_ie:
-                        print('added %s' % path)
-                    elif (old_ie.name == entry.name
-                          and old_ie.parent_id == entry.parent_id):
-                        print('modified %s' % path)
-                    else:
-                        print('renamed %s' % path)
-
-
-    for file_id in missing_ids:
-        # Any files that have been deleted are now removed from the
-        # working inventory.  Files that were not selected for commit
-        # are left as they were in the working inventory and ommitted
-        # from the revision inventory.
-        
-        # have to do this later so we don't mess up the iterator.
-        # since parents may be removed before their children we
-        # have to test.
-
-        # FIXME: There's probably a better way to do this; perhaps
-        # the workingtree should know how to filter itbranch.
-        if work_inv.has_id(file_id):
-            del work_inv[file_id]
-
-
-    if rev_id is None:
-        rev_id = _gen_revision_id(time.time())
-    inv_id = rev_id
-
-    inv_tmp = tempfile.TemporaryFile()
-    inv.write_xml(inv_tmp)
-    inv_tmp.seek(0)
-    branch.inventory_store.add(inv_tmp, inv_id)
-    mutter('new inventory_id is {%s}' % inv_id)
-
-    branch._write_inventory(work_inv)
-
-    if timestamp == None:
-        timestamp = time.time()
-
-    if committer == None:
-        committer = username()
-
-    if timezone == None:
-        timezone = local_time_offset()
-
-    mutter("building commit log message")
-    rev = Revision(timestamp=timestamp,
-                   timezone=timezone,
-                   committer=committer,
-                   precursor = branch.last_patch(),
-                   message = message,
-                   inventory_id=inv_id,
-                   revision_id=rev_id)
-
-    rev_tmp = tempfile.TemporaryFile()
-    rev.write_xml(rev_tmp)
-    rev_tmp.seek(0)
-    branch.revision_store.add(rev_tmp, rev_id)
-    mutter("new revision_id is {%s}" % rev_id)
-
-    ## XXX: Everything up to here can simply be orphaned if we abort
-    ## the commit; it will leave junk files behind but that doesn't
-    ## matter.
-
-    ## TODO: Read back the just-generated changeset, and make sure it
-    ## applies and recreates the right state.
-
-    ## TODO: Also calculate and store the inventory SHA1
-    mutter("committing patch r%d" % (branch.revno() + 1))
-
-    branch.append_revision(rev_id)
-
-    if verbose:
-        note("commited r%d" % branch.revno())
+                old_kind = basis_inv[file_id].kind
+                if old_kind != entry.kind:
+                    raise BzrError("entry %r changed kind from %r to %r"
+                            % (file_id, old_kind, entry.kind))
+
+            if entry.kind == 'directory':
+                if not isdir(p):
+                    raise BzrError("%s is entered as directory but not a directory"
+                                   % quotefn(p))
+            elif entry.kind == 'file':
+                if not isfile(p):
+                    raise BzrError("%s is entered as file but is not a file" % quotefn(p))
+
+                new_sha1 = work_tree.get_file_sha1(file_id)
+
+                old_ie = basis_inv.has_id(file_id) and basis_inv[file_id]
+                if (old_ie
+                    and old_ie.text_sha1 == new_sha1):
+                    ## assert content == basis.get_file(file_id).read()
+                    entry.text_id = old_ie.text_id
+                    entry.text_sha1 = new_sha1
+                    entry.text_size = old_ie.text_size
+                    mutter('    unchanged from previous text_id {%s}' %
+                           entry.text_id)
+                else:
+                    content = file(p, 'rb').read()
+
+                    # calculate the sha again, just in case the file contents
+                    # changed since we updated the cache
+                    entry.text_sha1 = sha_string(content)
+                    entry.text_size = len(content)
+
+                    entry.text_id = gen_file_id(entry.name)
+                    branch.text_store.add(content, entry.text_id)
+                    mutter('    stored with text_id {%s}' % entry.text_id)
+                    if verbose:
+                        if not old_ie:
+                            print('added %s' % path)
+                        elif (old_ie.name == entry.name
+                              and old_ie.parent_id == entry.parent_id):
+                            print('modified %s' % path)
+                        else:
+                            print('renamed %s' % path)
+
+
+        for file_id in missing_ids:
+            # Any files that have been deleted are now removed from the
+            # working inventory.  Files that were not selected for commit
+            # are left as they were in the working inventory and ommitted
+            # from the revision inventory.
+
+            # have to do this later so we don't mess up the iterator.
+            # since parents may be removed before their children we
+            # have to test.
+
+            # FIXME: There's probably a better way to do this; perhaps
+            # the workingtree should know how to filter itbranch.
+            if work_inv.has_id(file_id):
+                del work_inv[file_id]
+
+
+        if rev_id is None:
+            rev_id = _gen_revision_id(time.time())
+        inv_id = rev_id
+
+        inv_tmp = tempfile.TemporaryFile()
+        inv.write_xml(inv_tmp)
+        inv_tmp.seek(0)
+        branch.inventory_store.add(inv_tmp, inv_id)
+        mutter('new inventory_id is {%s}' % inv_id)
+
+        branch._write_inventory(work_inv)
+
+        if timestamp == None:
+            timestamp = time.time()
+
+        if committer == None:
+            committer = username()
+
+        if timezone == None:
+            timezone = local_time_offset()
+
+        mutter("building commit log message")
+        rev = Revision(timestamp=timestamp,
+                       timezone=timezone,
+                       committer=committer,
+                       precursor = branch.last_patch(),
+                       message = message,
+                       inventory_id=inv_id,
+                       revision_id=rev_id)
+
+        rev_tmp = tempfile.TemporaryFile()
+        rev.write_xml(rev_tmp)
+        rev_tmp.seek(0)
+        branch.revision_store.add(rev_tmp, rev_id)
+        mutter("new revision_id is {%s}" % rev_id)
+
+        ## XXX: Everything up to here can simply be orphaned if we abort
+        ## the commit; it will leave junk files behind but that doesn't
+        ## matter.
+
+        ## TODO: Read back the just-generated changeset, and make sure it
+        ## applies and recreates the right state.
+
+        ## TODO: Also calculate and store the inventory SHA1
+        mutter("committing patch r%d" % (branch.revno() + 1))
+
+        branch.append_revision(rev_id)
+
+        if verbose:
+            note("commited r%d" % branch.revno())
+    finally:
+        branch.unlock()
 
 
 

=== modified file 'bzrlib/remotebranch.py'
--- a/bzrlib/remotebranch.py	2005-05-26 02:13:57 +0000
+++ b/bzrlib/remotebranch.py	2005-05-30 01:37:52 +0000
@@ -99,7 +99,7 @@
 
 
 class RemoteBranch(Branch):
-    def __init__(self, baseurl, find_root=True, lock_mode='r'):
+    def __init__(self, baseurl, find_root=True):
         """Create new proxy for a remote branch."""
         if lock_mode not in ('', 'r'):
             raise BzrError('lock mode %r is not supported for remote branches'
@@ -124,12 +124,14 @@
             raise BzrError("file mode %r not supported for remote branches" % mode)
         return get_url(self.baseurl + '/.bzr/' + filename, False)
 
-    def _need_readlock(self):
-        # remote branch always safe for read
+
+    def lock(self, mode):
+        if mode != 'r':
+            raise BzrError('lock mode %r not supported for remote branch %r' % (mode, self))
+
+    def unlock(self):
         pass
-
-    def _need_writelock(self):
-        raise BzrError("cannot get write lock on HTTP remote branch")
+    
 
     def relpath(self, path):
         if not path.startswith(self.baseurl):

=== modified file 'bzrlib/status.py'
--- a/bzrlib/status.py	2005-05-11 08:11:37 +0000
+++ b/bzrlib/status.py	2005-05-30 01:37:52 +0000
@@ -28,28 +28,32 @@
         If set, only show the status of files in this list.
     """
     import sys
-    import diff
-    
-    branch._need_readlock()
-    
-    old = branch.basis_tree()
-    new = branch.working_tree()
-
-    delta = diff.compare_trees(old, new, want_unchanged=show_unchanged,
-                               specific_files=specific_files)
-
-    delta.show(sys.stdout, show_ids=show_ids,
-               show_unchanged=show_unchanged)
-
-    unknowns = new.unknowns()
-    done_header = False
-    for path in unknowns:
-        # FIXME: Should also match if the unknown file is within a
-        # specified directory.
-        if specific_files:
-            if path not in specific_files:
-                continue
-        if not done_header:
-            print 'unknown:'
-            done_header = True
-        print ' ', path
+    from bzrlib.diff import compare_trees
+    
+    branch.lock('r')
+    try:
+
+        old = branch.basis_tree()
+        new = branch.working_tree()
+
+        delta = compare_trees(old, new, want_unchanged=show_unchanged,
+                              specific_files=specific_files)
+
+        delta.show(sys.stdout, show_ids=show_ids,
+                   show_unchanged=show_unchanged)
+
+        unknowns = new.unknowns()
+        done_header = False
+        for path in unknowns:
+            # FIXME: Should also match if the unknown file is within a
+            # specified directory.
+            if specific_files:
+                if path not in specific_files:
+                    continue
+            if not done_header:
+                print 'unknown:'
+                done_header = True
+            print ' ', path
+    finally:
+        branch.unlock()
+        



More information about the Pkg-bazaar-commits mailing list