Rev 6502: Stop using _CompatibleStack now that local config files can be in file:///home/vila/src/bzr/bugs/832042-shared-stores/

Vincent Ladeuil v.ladeuil+lp at free.fr
Tue Jul 31 09:22:02 UTC 2012


At file:///home/vila/src/bzr/bugs/832042-shared-stores/

------------------------------------------------------------
revno: 6502
revision-id: v.ladeuil+lp at free.fr-20120731092202-qh9fs6q4p7y4qqmy
parent: v.ladeuil+lp at free.fr-20120731091807-tft1lk8zw84rp1nj
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: 832042-shared-stores
timestamp: Tue 2012-07-31 11:22:02 +0200
message:
  Stop using _CompatibleStack now that local config files can be
  shared. Save changes when library state goes out of scope or, as a
  fallback, when the process ends.
-------------- next part --------------
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py	2012-03-08 18:30:33 +0000
+++ b/bzrlib/config.py	2012-07-31 09:22:02 +0000
@@ -3278,6 +3278,7 @@
         # anyway.
         return 'In-Process Store, no URL'
 
+
 class TransportIniFileStore(IniFileStore):
     """IniFileStore that loads files from a transport.
 
@@ -3408,6 +3409,44 @@
         self.id = 'control'
 
 
+# FIXME: _shared_stores should be an attribute of a library state once a
+# library_state object is always available.
+_shared_stores = {}
+_once = True
+def get_shared_store(store, state=None):
+    """Get a known shared store.
+
+    Store urls uniquely identify them and are used to ensure a single copy is
+    shared across all users.
+
+    :param store: The store known to the caller.
+
+    :param state: The library state where the known stores are kept.
+
+    :returns: The store received if it's not a known one, an already known
+        otherwise.
+    """
+    if state is None:
+        global _once
+        stores = _shared_stores
+        def save_config_changes():
+            for k, store in stores.iteritems():
+                store.save_changes()
+        if _once:
+            # FIXME: Ugly hack waiting for library_state to always be available.
+            import atexit
+            atexit.register(save_config_changes)
+            _once = False
+    else:
+        stores = states.config_stores
+    url = store.external_url()
+    try:
+        return stores[url]
+    except KeyError:
+        stores[url] = store
+        return store
+
+
 class SectionMatcher(object):
     """Select sections into a given Store.
 
@@ -3797,7 +3836,7 @@
         return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
 
     def _get_overrides(self):
-        # Hack around library_state.initialize never called
+        # FIXME: Hack around library_state.initialize never called
         if bzrlib.global_state is not None:
             return bzrlib.global_state.cmdline_overrides.get_sections()
         return []
@@ -3857,7 +3896,7 @@
         self.store.save()
 
 
-class GlobalStack(_CompatibleStack):
+class GlobalStack(Stack):
     """Global options only stack.
 
     The following sections are queried:
@@ -3871,14 +3910,14 @@
     """
 
     def __init__(self):
-        gstore = GlobalStore()
+        gstore = get_shared_store(GlobalStore())
         super(GlobalStack, self).__init__(
             [self._get_overrides,
              NameMatcher(gstore, 'DEFAULT').get_sections],
             gstore, mutable_section_id='DEFAULT')
 
 
-class LocationStack(_CompatibleStack):
+class LocationStack(Stack):
     """Per-location options falling back to global options stack.
 
 
@@ -3900,10 +3939,11 @@
         """Make a new stack for a location and global configuration.
 
         :param location: A URL prefix to """
-        lstore = LocationStore()
+        # FIXME: self._get_shared_store ?
+        lstore = get_shared_store(LocationStore())
         if location.startswith('file://'):
             location = urlutils.local_path_from_url(location)
-        gstore = GlobalStore()
+        gstore = get_shared_store(GlobalStore())
         super(LocationStack, self).__init__(
             [self._get_overrides,
              LocationMatcher(lstore, location).get_sections,
@@ -3931,9 +3971,9 @@
     """
 
     def __init__(self, branch):
-        lstore = LocationStore()
+        lstore = get_shared_store(LocationStore())
         bstore = branch._get_config_store()
-        gstore = GlobalStore()
+        gstore = get_shared_store(GlobalStore())
         super(BranchStack, self).__init__(
             [self._get_overrides,
              LocationMatcher(lstore, branch.base).get_sections,
@@ -3961,7 +4001,7 @@
         # unlock saves all the changes.
 
 
-class RemoteControlStack(_CompatibleStack):
+class RemoteControlStack(Stack):
     """Remote control-only options stack."""
 
     # FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion

=== modified file 'bzrlib/library_state.py'
--- a/bzrlib/library_state.py	2011-12-19 13:23:58 +0000
+++ b/bzrlib/library_state.py	2012-07-31 09:22:02 +0000
@@ -76,6 +76,8 @@
         # There is no overrides by default, they are set later when the command
         # arguments are parsed.
         self.cmdline_overrides = config.CommandLineStore()
+        # No config stores are cached to start with
+        self.config_stores = {} # By url
         self.started = False
 
     def __enter__(self):
@@ -106,6 +108,10 @@
         self.started = True
 
     def __exit__(self, exc_type, exc_val, exc_tb):
+        if exc_type is None:
+            # Save config changes
+            for k, store in self.config_stores.iteritems():
+                store.save_changes()
         self.cleanups.cleanup_now()
         trace._flush_stdout_stderr()
         trace._flush_trace()



More information about the bazaar-commits mailing list