chiark / gitweb /
Failed recursive merging can silently lose date in StGIT
[stgit] / stgit / config.py
CommitLineData
41a6d859
CM
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
c73e63b7 21import os, re
170f576b 22from stgit import basedir
41a6d859 23
c73e63b7
YD
24class GitConfigException(Exception):
25 pass
26
27class GitConfig:
28 __defaults={
29 'stgit.autoresolved': 'no',
30 'stgit.smtpserver': 'localhost:25',
31 'stgit.smtpdelay': '5',
3b3c26fa
YD
32 'stgit.pullcmd': 'git-pull',
33 'stgit.fetchcmd': 'git-fetch',
34 'stgit.pull-policy': 'pull',
c73e63b7
YD
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
9a4bf454
YD
44 __cache={}
45
c73e63b7
YD
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):
9a4bf454
YD
66 if self.__cache.has_key(name):
67 return self.__cache[name]
68
c73e63b7
YD
69 stream = os.popen('git repo-config --get %s' % name, 'r')
70 value = stream.readline().strip()
71 stream.close()
72 if len(value) > 0:
9a4bf454 73 pass
c73e63b7 74 elif (self.__defaults.has_key(name)):
9a4bf454 75 value = self.__defaults[name]
c73e63b7 76 else:
9a4bf454
YD
77 value = None
78
79 self.__cache[name] = value
80 return value
c73e63b7
YD
81
82 def getall(self, name):
9a4bf454
YD
83 if self.__cache.has_key(name):
84 return self.__cache[name]
85
c73e63b7
YD
86 stream = os.popen('git repo-config --get-all %s' % name, 'r')
87 values = [line.strip() for line in stream]
88 stream.close()
9a4bf454
YD
89
90 self.__cache[name] = values
c73e63b7
YD
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
cb5be4c3
PR
100 def rename_section(self, from_name, to_name):
101 self.__run('git-repo-config --rename-section', [from_name, to_name])
102
c73e63b7
YD
103 def set(self, name, value):
104 self.__run('git-repo-config', [name, value])
105
0aee23c2
YD
106 def unset(self, name):
107 self.__run('git-repo-config --unset', [name])
108
c73e63b7
YD
109 def sections_matching(self, regexp):
110 """Takes a regexp with a single group, matches it against all
111 config variables, and returns a list whose members are the
112 group contents, for all variable names matching the regexp.
113 """
114 result = []
115 stream = os.popen('git repo-config --get-regexp "^%s$"' % regexp, 'r')
116 for line in stream:
117 m = re.match('^%s ' % regexp, line)
118 if m:
119 result.append(m.group(1))
120 stream.close()
121 return result
122
123config=GitConfig()
abcc2620 124
eee7283e
CM
125def config_setup():
126 global config
127
eee7283e 128 # Set the PAGER environment to the config value (if any)
c73e63b7
YD
129 pager = config.get('stgit.pager')
130 if pager:
131 os.environ['PAGER'] = pager
132 # FIXME: handle EDITOR the same way ?
eee7283e
CM
133
134class ConfigOption:
135 """Delayed cached reading of a configuration option.
136 """
137 def __init__(self, section, option):
138 self.__section = section
139 self.__option = option
140 self.__value = None
141
142 def __str__(self):
143 if not self.__value:
c73e63b7 144 self.__value = config.get(self.__section + '.' + self.__option)
eee7283e 145 return self.__value
d7fade4b
CM
146
147
148# cached extensions
149__extensions = None
150
151def file_extensions():
152 """Returns a dictionary with the conflict file extensions
153 """
154 global __extensions
155
156 if not __extensions:
c73e63b7 157 cfg_ext = config.get('stgit.extensions').split()
d7fade4b
CM
158 if len(cfg_ext) != 3:
159 raise CmdException, '"extensions" configuration error'
160
161 __extensions = { 'ancestor': cfg_ext[0],
162 'current': cfg_ext[1],
163 'patched': cfg_ext[2] }
164
165 return __extensions