From b2bc3390413f7fdfdd2baabd2c244576fa31fc58 Mon Sep 17 00:00:00 2001 From: David Leen Date: Tue, 17 Jun 2014 21:42:55 -0700 Subject: [PATCH] Add a class for interacting with git config This commit adds the GitConfigStore class. This allows us to easily get and set keys and values in git config. Tests pass. --- git-imerge | 81 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 15 deletions(-) diff --git a/git-imerge b/git-imerge index 897a48b..eb8b459 100755 --- a/git-imerge +++ b/git-imerge @@ -580,6 +580,67 @@ class AutomaticMergeFailed(Exception): self.commit1, self.commit2 = commit1, commit2 +class GitConfigError(Exception): + def __init__(self, returncode, output): + Exception.__init__( + self, 'Git config failed with exit code %s: %s' % (returncode, output,) + ) + + +def memo(obj): + cache = {} + @functools.wraps(obj) + def wrap(*args, **kwds): + if args not in cache: + cache[args] = obj(*args, **kwds) + return cache[args] + return wrap + + +@memo +class GitConfigStore(object): + def __init__(self, name, config_prefix='imerge'): + self.config_prefix = config_prefix + self.config = self._get_all_keys() + + def _get_all_keys(self): + d = {} + try: + items_with_prefix = check_output( + ['git', 'config', '--get-regex', self.config_prefix] + ).rstrip().split('\n') + for row in items_with_prefix: + k, v = row.split() + d[k[len(self.config_prefix + '.'):]] = v + return d + except CalledProcessError: + return {} + + def get(self, key): + return self.config.get(key) + + def set(self, key, value): + self.config[key] = value + config_key = '.'.join([self.config_prefix, key]) + try: + check_call(['git', 'config', config_key, value]) + except CalledProcessError as e: + raise GitConfigError(e.returncode, e.output) + + def unset(self, key): + if key in self.config: + del self.config[key] + config_key = '.'.join([self.config_prefix, key]) + try: + check_call(['git', 'config', '--unset', config_key]) + except CalledProcessError as e: + if e.returncode == 5: + # Value was not set + pass + else: + raise GitConfigError(e.returncode, e.output) + + def automerge(commit1, commit2, msg=None): """Attempt an automatic merge of commit1 and commit2. @@ -1865,27 +1926,17 @@ class MergeState(Block): """Set the default merge to the specified one. name can be None to cause the default to be cleared.""" - + gcs = GitConfigStore(name) if name is None: - try: - check_call(['git', 'config', '--unset', 'imerge.default']) - except CalledProcessError as e: - if e.returncode == 5: - # Value was not set - pass - else: - raise + gcs.unset("default") else: - check_call(['git', 'config', 'imerge.default', name]) + gcs.set("default", name) @staticmethod def get_default_name(): """Get the name of the default merge, or None if none is currently set.""" - - try: - return check_output(['git', 'config', 'imerge.default']).rstrip() - except CalledProcessError: - return None + gcs = GitConfigStore(None) + return gcs.get("default") @staticmethod def _check_no_merges(commits):