summaryrefslogtreecommitdiff
path: root/lib/git
diff options
context:
space:
mode:
Diffstat (limited to 'lib/git')
-rw-r--r--lib/git/__init__.py1
-rw-r--r--lib/git/config.py100
-rw-r--r--lib/git/repo.py53
3 files changed, 153 insertions, 1 deletions
diff --git a/lib/git/__init__.py b/lib/git/__init__.py
index e2adac62..041d69f7 100644
--- a/lib/git/__init__.py
+++ b/lib/git/__init__.py
@@ -9,6 +9,7 @@ import inspect
__version__ = 'git'
+from git.config import GitConfigParser
from git.objects import *
from git.refs import *
from git.actor import Actor
diff --git a/lib/git/config.py b/lib/git/config.py
new file mode 100644
index 00000000..c7f2c398
--- /dev/null
+++ b/lib/git/config.py
@@ -0,0 +1,100 @@
+# config.py
+# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
+#
+# This module is part of GitPython and is released under
+# the BSD License: http://www.opensource.org/licenses/bsd-license.php
+"""
+Module containing module parser implementation able to properly read and write
+configuration files
+"""
+
+import re
+from ConfigParser import RawConfigParser
+
+class _MetaParserBuilder(type):
+ """
+ Utlity class wrapping methods into decorators that assure read-only properties
+ """
+
+def _needs_values(func):
+ """Returns method assuring we read values (on demand) before we try to access them"""
+ return func
+
+def _ensure_writable(non_const_func):
+ """Return method that checks whether given non constant function may be called.
+ If so, the instance will be set dirty"""
+
+
+
+class GitConfigParser(RawConfigParser, object):
+ """
+ Implements specifics required to read git style configuration files.
+
+ This variation behaves much like the git.config command such that the configuration
+ will be read on demand based on the filepath given during initialization.
+
+ The changes will automatically be written once the instance goes out of scope, but
+ can be triggered manually as well.
+
+ The configuration file will be locked if you intend to change values preventing other
+ instances to write concurrently.
+ """
+ __metaclass__ = _MetaParserBuilder
+
+ OPTCRE = re.compile(
+ r'\s?(?P<option>[^:=\s][^:=]*)' # very permissive, incuding leading whitespace
+ r'\s*(?P<vi>[:=])\s*' # any number of space/tab,
+ # followed by separator
+ # (either : or =), followed
+ # by any # space/tab
+ r'(?P<value>.*)$' # everything up to eol
+ )
+
+ # list of RawConfigParser methods able to change the instance
+ _mutating_methods_ = tuple()
+
+
+ def __init__(self, file_or_files, read_only=True):
+ """
+ Initialize a configuration reader to read the given file_or_files and to
+ possibly allow changes to it by setting read_only False
+ """
+ self._file_or_files = file_or_files
+ self._read_only = read_only
+ self._is_initialized = False
+ self._is_dirty = False
+
+ def __del__(self):
+ """
+ Write pending changes if required and release locks
+ """
+
+ def read(self):
+ """
+ Read configuration information from our file or files
+ """
+ if self._is_initialized:
+ return
+
+ self._is_initialized = True
+
+ @_ensure_writable
+ def write(self):
+ """
+ Write our changes to our file
+
+ Raise
+ AssertionError if this is a read-only writer instance
+ """
+ if not self._is_dirty:
+ return
+
+ self._is_dirty = False
+
+ @property
+ def read_only(self):
+ """
+ Returns
+ True if this instance may change the configuration file
+ """
+ return self._read_only
diff --git a/lib/git/repo.py b/lib/git/repo.py
index cc4a6c6b..c53a4d9b 100644
--- a/lib/git/repo.py
+++ b/lib/git/repo.py
@@ -5,6 +5,7 @@
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import os
+import sys
import re
import gzip
import StringIO
@@ -15,7 +16,7 @@ from cmd import Git
from actor import Actor
from refs import *
from objects import *
-
+from config import GitConfigParser
class Repo(object):
"""
@@ -30,6 +31,10 @@ class Repo(object):
re_hexsha_only = re.compile('^[0-9A-Fa-f]{40}$')
re_author_committer_start = re.compile(r'^(author|committer)')
re_tab_full_line = re.compile(r'^\t(.*)$')
+
+ # invariants
+ # represents the configuration level of a configuration file
+ config_level = ("system", "global", "repository")
def __init__(self, path=None):
"""
@@ -125,6 +130,52 @@ class Repo(object):
"""
return Tag.list_items(self)
+ def _get_config_path(self, config_level ):
+ # we do not support an absolute path of the gitconfig on windows ,
+ # use the global config instead
+ if sys.platform == "win32" and config_level == "system":
+ config_level = "global"
+
+ if config_level == "system":
+ return "/etc/gitconfig"
+ elif config_level == "global":
+ return os.path.expanduser("~/.gitconfig")
+ elif config_level == "repository":
+ return "%s/config" % self.git.git_dir
+
+ raise ValueError( "Invalid configuration level: %r" % config_level )
+
+ @property
+ def config_reader(self):
+ """
+ Returns
+ GitConfigParser allowing to read the full git configuration, but not to write it
+
+ The configuration will include values from the system, user and repository
+ configuration files.
+
+ NOTE: On windows, system configuration cannot currently be read as the path is
+ unknown, instead the global path will be used.
+ """
+ files = [ self._get_config_path(f) for f in self.config_level ]
+ return GitConfigParser(files, read_only=True)
+
+ def config_writer(self, config_level="repository"):
+ """
+ Returns
+ GitConfigParser allowing to write values of the specified configuration file level.
+ Config writers should be retrieved, used to change the configuration ,and written
+ right away as they will lock the configuration file in question and prevent other's
+ to write it.
+
+ ``config_level``
+ One of the following values
+ system = sytem wide configuration file
+ global = user level configuration file
+ repository = configuration file for this repostory only
+ """
+ return GitConfigParser(self._get_config_path(config_level), read_only = False)
+
def commit(self, rev=None):
"""
The Commit object for the specified revision