chiark / gitweb /
Refactor output handling to break circular dependency
[stgit] / stgit / config.py
... / ...
CommitLineData
1"""Handles the Stacked GIT configuration files
2"""
3
4__copyright__ = """
5Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License version 2 as
9published by the Free Software Foundation.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19"""
20
21import os, re
22from stgit import basedir
23
24class GitConfigException(Exception):
25 pass
26
27class GitConfig:
28 __defaults={
29 'stgit.autoresolved': 'no',
30 'stgit.smtpserver': 'localhost:25',
31 'stgit.smtpdelay': '5',
32 'stgit.pullcmd': 'git-pull',
33 'stgit.fetchcmd': 'git-fetch',
34 'stgit.pull-policy': 'pull',
35 'stgit.merger': 'diff3 -L current -L ancestor -L patched -m -E ' \
36 '"%(branch1)s" "%(ancestor)s" "%(branch2)s" > "%(output)s"',
37 'stgit.autoimerge': 'no',
38 'stgit.keeporig': 'yes',
39 'stgit.keepoptimized': 'no',
40 'stgit.extensions': '.ancestor .current .patched',
41 'stgit.shortnr': '5'
42 }
43
44 __cache={}
45
46 def __run(self, cmd, args=None):
47 """__run: runs cmd using spawnvp.
48
49 Runs cmd using spawnvp. The shell is avoided so it won't mess up
50 our arguments. If args is very large, the command is run multiple
51 times; args is split xargs style: cmd is passed on each
52 invocation. Unlike xargs, returns immediately if any non-zero
53 return code is received.
54 """
55
56 args_l=cmd.split()
57 if args is None:
58 args = []
59 for i in range(0, len(args)+1, 100):
60 r=os.spawnvp(os.P_WAIT, args_l[0], args_l + args[i:min(i+100, len(args))])
61 if r:
62 return r
63 return 0
64
65 def get(self, name):
66 if self.__cache.has_key(name):
67 return self.__cache[name]
68
69 stream = os.popen('git repo-config --get %s' % name, 'r')
70 value = stream.readline().strip()
71 stream.close()
72 if len(value) > 0:
73 pass
74 elif (self.__defaults.has_key(name)):
75 value = self.__defaults[name]
76 else:
77 value = None
78
79 self.__cache[name] = value
80 return value
81
82 def getall(self, name):
83 if self.__cache.has_key(name):
84 return self.__cache[name]
85
86 stream = os.popen('git repo-config --get-all %s' % name, 'r')
87 values = [line.strip() for line in stream]
88 stream.close()
89
90 self.__cache[name] = values
91 return values
92
93 def getint(self, name):
94 value = self.get(name)
95 if value.isdigit():
96 return int(value)
97 else:
98 raise GitConfigException, 'Value for "%s" is not an integer: "%s"' % (name, value)
99
100 def rename_section(self, from_name, to_name):
101 self.__run('git-repo-config --rename-section', [from_name, to_name])
102 self.__cache.clear()
103
104 def set(self, name, value):
105 self.__run('git-repo-config', [name, value])
106 self.__cache[name] = value
107
108 def unset(self, name):
109 self.__run('git-repo-config --unset', [name])
110 self.__cache[name] = None
111
112 def sections_matching(self, regexp):
113 """Takes a regexp with a single group, matches it against all
114 config variables, and returns a list whose members are the
115 group contents, for all variable names matching the regexp.
116 """
117 result = []
118 stream = os.popen('git repo-config --get-regexp "^%s$"' % regexp, 'r')
119 for line in stream:
120 m = re.match('^%s ' % regexp, line)
121 if m:
122 result.append(m.group(1))
123 stream.close()
124 return result
125
126config=GitConfig()
127
128def config_setup():
129 global config
130
131 # Set the PAGER environment to the config value (if any)
132 pager = config.get('stgit.pager')
133 if pager:
134 os.environ['PAGER'] = pager
135 # FIXME: handle EDITOR the same way ?
136
137class ConfigOption:
138 """Delayed cached reading of a configuration option.
139 """
140 def __init__(self, section, option):
141 self.__section = section
142 self.__option = option
143 self.__value = None
144
145 def __str__(self):
146 if not self.__value:
147 self.__value = config.get(self.__section + '.' + self.__option)
148 return self.__value
149
150
151# cached extensions
152__extensions = None
153
154def file_extensions():
155 """Returns a dictionary with the conflict file extensions
156 """
157 global __extensions
158
159 if not __extensions:
160 cfg_ext = config.get('stgit.extensions').split()
161 if len(cfg_ext) != 3:
162 raise CmdException, '"extensions" configuration error'
163
164 __extensions = { 'ancestor': cfg_ext[0],
165 'current': cfg_ext[1],
166 'patched': cfg_ext[2] }
167
168 return __extensions