Index: trac/config.py
===================================================================
--- trac/config.py	(revision 3147)
+++ trac/config.py	(working copy)
@@ -65,7 +65,6 @@
     """
     def __init__(self, filename):
         self._sections = {}
-        self._defaults = {}
         self.filename = filename
         self.parser = ConfigParser()
         self._lastmtime = 0
@@ -149,28 +148,41 @@
 
     def sections(self):
         """Return a list of section names."""
-        return self.parser.sections()
+        sections = self.site_parser.sections()
+        site_sections = [s.lower() for s in sections]
+        sections.extend([s for s in self.parser.sections() 
+                         if s not in site_sections])
+        return sections
 
     def save(self):
         """Write the configuration options to the primary file."""
         if not self.filename:
             return
         fileobj = file(self.filename, 'w')
+        # Only save options that differ from the defaults
+        clean_config = ConfigParser()
+        for section in self.sections():
+            for option in self[section]:
+                default = self.site_parser.has_option(section, option) and \
+                          self.site_parser.get(section, option) or None
+                current = self.parser.has_option(section, option) and \
+                          self.parser.get(section, option) or None
+                if current is not None and default != current:
+                    if not clean_config.has_section(section):
+                        clean_config.add_section(section)
+                    clean_config.set(section, option, current)
+
         try:
-            self.parser.write(fileobj)
+            clean_config.write(fileobj)
         finally:
             fileobj.close()
 
     def parse_if_needed(self):
-        # Merge global configuration option into _defaults
+        # Load global configuration
         if os.path.isfile(self.site_filename):
             modtime = os.path.getmtime(self.site_filename)
             if modtime > self._lastsitemtime:
                 self.site_parser.read(self.site_filename)
-                for section in self.site_parser.sections():
-                    for option in self.site_parser.options(section):
-                        value = self.site_parser.get(section, option)
-                        self._defaults[(section, option)] = value
                 self._lastsitemtime = modtime
 
         if not self.filename or not os.path.isfile(self.filename):
@@ -193,25 +205,29 @@
         self.name = name
 
     def __contains__(self, name):
-        return self.config.parser.has_option(self.name, name)
+        return self.config.parser.has_option(self.name, name) or \
+               self.config.site_parser.has_option(self.name, name)
+            
 
     def __iter__(self):
         options = []
         if self.config.parser.has_section(self.name):
             for option in self.config.parser.options(self.name):
-                options.append(option)
+                options.append(option.lower())
                 yield option
-        for section, option in self.config._defaults:
-            if section == self.name and option not in options:
-                yield option
+        if self.config.site_parser.has_section(self.name):
+            for option in self.config.site_parser.options(self.name):
+                if option.lower() not in options:
+                    yield option
 
     def get(self, name, default=None):
         """Return the value of the specified option."""
-        if not name in self:
-            if default is None:
-                return self.config._defaults.get((self.name, name), '')
-            return default
-        return to_unicode(self.config.parser.get(self.name, name))
+        if self.config.parser.has_option(self.name, name):
+            return to_unicode(self.config.parser.get(self.name, name))
+        elif self.config.site_parser.has_option(self.name, name):
+            return to_unicode(self.config.site_parser.get(self.name, name))
+        else:
+            return default or ''
 
     def getbool(self, name, default=None):
         """Return the value of the specified option as boolean.
@@ -258,8 +274,10 @@
 
     def setdefault(self, name, value):
         """Set the default value of a specific option."""
-        if (self.name, name) not in self.config._defaults:
-            self.config._defaults[(self.name, name)] = value
+        if not self.config.site_parser.has_option(self.name, name):
+            if not self.config.site_parser.has_section(self.name):
+                self.config.site_parser.add_section(self.name)
+            self.config.site_parser.set(self.name, name, value.encode('utf-8'))
 
     def set(self, name, value):
         """Change a configuration value.
Index: trac/tests/config.py
===================================================================
--- trac/tests/config.py	(revision 3147)
+++ trac/tests/config.py	(working copy)
@@ -116,6 +116,8 @@
     def test_sections(self):
         self._write(['[a]', 'option = x', '[b]', 'option = y'])
         config = Configuration(self.filename)
+        from ConfigParser import ConfigParser
+        config.site_parser = ConfigParser()
         self.assertEquals(['a', 'b'], config.sections())
 
     def test_options(self):

