##// END OF EJS Templates
Fix hg showconfig traceback with values that aren't strings
Alexis S. L. Carvalho -
r4085:719488a9 default
parent child Browse files
Show More
@@ -1,456 +1,456 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from i18n import _
8 from i18n import _
9 import errno, getpass, os, re, socket, sys, tempfile
9 import errno, getpass, os, re, socket, sys, tempfile
10 import ConfigParser, traceback, util
10 import ConfigParser, traceback, util
11
11
12 def dupconfig(orig):
12 def dupconfig(orig):
13 new = util.configparser(orig.defaults())
13 new = util.configparser(orig.defaults())
14 updateconfig(orig, new)
14 updateconfig(orig, new)
15 return new
15 return new
16
16
17 def updateconfig(source, dest, sections=None):
17 def updateconfig(source, dest, sections=None):
18 if not sections:
18 if not sections:
19 sections = source.sections()
19 sections = source.sections()
20 for section in sections:
20 for section in sections:
21 if not dest.has_section(section):
21 if not dest.has_section(section):
22 dest.add_section(section)
22 dest.add_section(section)
23 for name, value in source.items(section, raw=True):
23 for name, value in source.items(section, raw=True):
24 dest.set(section, name, value)
24 dest.set(section, name, value)
25
25
26 class ui(object):
26 class ui(object):
27 def __init__(self, verbose=False, debug=False, quiet=False,
27 def __init__(self, verbose=False, debug=False, quiet=False,
28 interactive=True, traceback=False, report_untrusted=True,
28 interactive=True, traceback=False, report_untrusted=True,
29 parentui=None):
29 parentui=None):
30 self.overlay = None
30 self.overlay = None
31 self.buffers = []
31 self.buffers = []
32 if parentui is None:
32 if parentui is None:
33 # this is the parent of all ui children
33 # this is the parent of all ui children
34 self.parentui = None
34 self.parentui = None
35 self.readhooks = []
35 self.readhooks = []
36 self.quiet = quiet
36 self.quiet = quiet
37 self.verbose = verbose
37 self.verbose = verbose
38 self.debugflag = debug
38 self.debugflag = debug
39 self.interactive = interactive
39 self.interactive = interactive
40 self.traceback = traceback
40 self.traceback = traceback
41 self.report_untrusted = report_untrusted
41 self.report_untrusted = report_untrusted
42 self.trusted_users = {}
42 self.trusted_users = {}
43 self.trusted_groups = {}
43 self.trusted_groups = {}
44 # if ucdata is not None, its keys must be a superset of cdata's
44 # if ucdata is not None, its keys must be a superset of cdata's
45 self.cdata = util.configparser()
45 self.cdata = util.configparser()
46 self.ucdata = None
46 self.ucdata = None
47 # we always trust global config files
47 # we always trust global config files
48 self.check_trusted = False
48 self.check_trusted = False
49 self.readconfig(util.rcpath())
49 self.readconfig(util.rcpath())
50 self.check_trusted = True
50 self.check_trusted = True
51 self.updateopts(verbose, debug, quiet, interactive)
51 self.updateopts(verbose, debug, quiet, interactive)
52 else:
52 else:
53 # parentui may point to an ui object which is already a child
53 # parentui may point to an ui object which is already a child
54 self.parentui = parentui.parentui or parentui
54 self.parentui = parentui.parentui or parentui
55 self.readhooks = self.parentui.readhooks[:]
55 self.readhooks = self.parentui.readhooks[:]
56 self.trusted_users = parentui.trusted_users.copy()
56 self.trusted_users = parentui.trusted_users.copy()
57 self.trusted_groups = parentui.trusted_groups.copy()
57 self.trusted_groups = parentui.trusted_groups.copy()
58 self.cdata = dupconfig(self.parentui.cdata)
58 self.cdata = dupconfig(self.parentui.cdata)
59 if self.parentui.ucdata:
59 if self.parentui.ucdata:
60 self.ucdata = dupconfig(self.parentui.ucdata)
60 self.ucdata = dupconfig(self.parentui.ucdata)
61 if self.parentui.overlay:
61 if self.parentui.overlay:
62 self.overlay = dupconfig(self.parentui.overlay)
62 self.overlay = dupconfig(self.parentui.overlay)
63
63
64 def __getattr__(self, key):
64 def __getattr__(self, key):
65 return getattr(self.parentui, key)
65 return getattr(self.parentui, key)
66
66
67 def updateopts(self, verbose=False, debug=False, quiet=False,
67 def updateopts(self, verbose=False, debug=False, quiet=False,
68 interactive=True, traceback=False, config=[]):
68 interactive=True, traceback=False, config=[]):
69 for section, name, value in config:
69 for section, name, value in config:
70 self.setconfig(section, name, value)
70 self.setconfig(section, name, value)
71
71
72 if quiet or verbose or debug:
72 if quiet or verbose or debug:
73 self.setconfig('ui', 'quiet', str(bool(quiet)))
73 self.setconfig('ui', 'quiet', str(bool(quiet)))
74 self.setconfig('ui', 'verbose', str(bool(verbose)))
74 self.setconfig('ui', 'verbose', str(bool(verbose)))
75 self.setconfig('ui', 'debug', str(bool(debug)))
75 self.setconfig('ui', 'debug', str(bool(debug)))
76
76
77 self.verbosity_constraints()
77 self.verbosity_constraints()
78
78
79 if not interactive:
79 if not interactive:
80 self.setconfig('ui', 'interactive', 'False')
80 self.setconfig('ui', 'interactive', 'False')
81 self.interactive = False
81 self.interactive = False
82
82
83 self.traceback = self.traceback or traceback
83 self.traceback = self.traceback or traceback
84
84
85 def verbosity_constraints(self):
85 def verbosity_constraints(self):
86 self.quiet = self.configbool('ui', 'quiet')
86 self.quiet = self.configbool('ui', 'quiet')
87 self.verbose = self.configbool('ui', 'verbose')
87 self.verbose = self.configbool('ui', 'verbose')
88 self.debugflag = self.configbool('ui', 'debug')
88 self.debugflag = self.configbool('ui', 'debug')
89
89
90 if self.debugflag:
90 if self.debugflag:
91 self.verbose = True
91 self.verbose = True
92 self.quiet = False
92 self.quiet = False
93 elif self.verbose and self.quiet:
93 elif self.verbose and self.quiet:
94 self.quiet = self.verbose = False
94 self.quiet = self.verbose = False
95
95
96 def _is_trusted(self, fp, f, warn=True):
96 def _is_trusted(self, fp, f, warn=True):
97 if not self.check_trusted:
97 if not self.check_trusted:
98 return True
98 return True
99 st = util.fstat(fp)
99 st = util.fstat(fp)
100 if util.isowner(fp, st):
100 if util.isowner(fp, st):
101 return True
101 return True
102 tusers = self.trusted_users
102 tusers = self.trusted_users
103 tgroups = self.trusted_groups
103 tgroups = self.trusted_groups
104 if not tusers:
104 if not tusers:
105 user = util.username()
105 user = util.username()
106 if user is not None:
106 if user is not None:
107 self.trusted_users[user] = 1
107 self.trusted_users[user] = 1
108 self.fixconfig(section='trusted')
108 self.fixconfig(section='trusted')
109 if (tusers or tgroups) and '*' not in tusers and '*' not in tgroups:
109 if (tusers or tgroups) and '*' not in tusers and '*' not in tgroups:
110 user = util.username(st.st_uid)
110 user = util.username(st.st_uid)
111 group = util.groupname(st.st_gid)
111 group = util.groupname(st.st_gid)
112 if user not in tusers and group not in tgroups:
112 if user not in tusers and group not in tgroups:
113 if warn and self.report_untrusted:
113 if warn and self.report_untrusted:
114 self.warn(_('Not trusting file %s from untrusted '
114 self.warn(_('Not trusting file %s from untrusted '
115 'user %s, group %s\n') % (f, user, group))
115 'user %s, group %s\n') % (f, user, group))
116 return False
116 return False
117 return True
117 return True
118
118
119 def readconfig(self, fn, root=None):
119 def readconfig(self, fn, root=None):
120 if isinstance(fn, basestring):
120 if isinstance(fn, basestring):
121 fn = [fn]
121 fn = [fn]
122 for f in fn:
122 for f in fn:
123 try:
123 try:
124 fp = open(f)
124 fp = open(f)
125 except IOError:
125 except IOError:
126 continue
126 continue
127 cdata = self.cdata
127 cdata = self.cdata
128 trusted = self._is_trusted(fp, f)
128 trusted = self._is_trusted(fp, f)
129 if not trusted:
129 if not trusted:
130 if self.ucdata is None:
130 if self.ucdata is None:
131 self.ucdata = dupconfig(self.cdata)
131 self.ucdata = dupconfig(self.cdata)
132 cdata = self.ucdata
132 cdata = self.ucdata
133 elif self.ucdata is not None:
133 elif self.ucdata is not None:
134 # use a separate configparser, so that we don't accidentally
134 # use a separate configparser, so that we don't accidentally
135 # override ucdata settings later on.
135 # override ucdata settings later on.
136 cdata = util.configparser()
136 cdata = util.configparser()
137
137
138 try:
138 try:
139 cdata.readfp(fp, f)
139 cdata.readfp(fp, f)
140 except ConfigParser.ParsingError, inst:
140 except ConfigParser.ParsingError, inst:
141 msg = _("Failed to parse %s\n%s") % (f, inst)
141 msg = _("Failed to parse %s\n%s") % (f, inst)
142 if trusted:
142 if trusted:
143 raise util.Abort(msg)
143 raise util.Abort(msg)
144 self.warn(_("Ignored: %s\n") % msg)
144 self.warn(_("Ignored: %s\n") % msg)
145
145
146 if trusted:
146 if trusted:
147 if cdata != self.cdata:
147 if cdata != self.cdata:
148 updateconfig(cdata, self.cdata)
148 updateconfig(cdata, self.cdata)
149 if self.ucdata is not None:
149 if self.ucdata is not None:
150 updateconfig(cdata, self.ucdata)
150 updateconfig(cdata, self.ucdata)
151 # override data from config files with data set with ui.setconfig
151 # override data from config files with data set with ui.setconfig
152 if self.overlay:
152 if self.overlay:
153 updateconfig(self.overlay, self.cdata)
153 updateconfig(self.overlay, self.cdata)
154 if root is None:
154 if root is None:
155 root = os.path.expanduser('~')
155 root = os.path.expanduser('~')
156 self.fixconfig(root=root)
156 self.fixconfig(root=root)
157 for hook in self.readhooks:
157 for hook in self.readhooks:
158 hook(self)
158 hook(self)
159
159
160 def addreadhook(self, hook):
160 def addreadhook(self, hook):
161 self.readhooks.append(hook)
161 self.readhooks.append(hook)
162
162
163 def readsections(self, filename, *sections):
163 def readsections(self, filename, *sections):
164 """Read filename and add only the specified sections to the config data
164 """Read filename and add only the specified sections to the config data
165
165
166 The settings are added to the trusted config data.
166 The settings are added to the trusted config data.
167 """
167 """
168 if not sections:
168 if not sections:
169 return
169 return
170
170
171 cdata = util.configparser()
171 cdata = util.configparser()
172 try:
172 try:
173 cdata.read(filename)
173 cdata.read(filename)
174 except ConfigParser.ParsingError, inst:
174 except ConfigParser.ParsingError, inst:
175 raise util.Abort(_("failed to parse %s\n%s") % (filename,
175 raise util.Abort(_("failed to parse %s\n%s") % (filename,
176 inst))
176 inst))
177
177
178 for section in sections:
178 for section in sections:
179 if not cdata.has_section(section):
179 if not cdata.has_section(section):
180 cdata.add_section(section)
180 cdata.add_section(section)
181
181
182 updateconfig(cdata, self.cdata, sections)
182 updateconfig(cdata, self.cdata, sections)
183 if self.ucdata:
183 if self.ucdata:
184 updateconfig(cdata, self.ucdata, sections)
184 updateconfig(cdata, self.ucdata, sections)
185
185
186 def fixconfig(self, section=None, name=None, value=None, root=None):
186 def fixconfig(self, section=None, name=None, value=None, root=None):
187 # translate paths relative to root (or home) into absolute paths
187 # translate paths relative to root (or home) into absolute paths
188 if section is None or section == 'paths':
188 if section is None or section == 'paths':
189 if root is None:
189 if root is None:
190 root = os.getcwd()
190 root = os.getcwd()
191 items = section and [(name, value)] or []
191 items = section and [(name, value)] or []
192 for cdata in self.cdata, self.ucdata, self.overlay:
192 for cdata in self.cdata, self.ucdata, self.overlay:
193 if not cdata: continue
193 if not cdata: continue
194 if not items and cdata.has_section('paths'):
194 if not items and cdata.has_section('paths'):
195 pathsitems = cdata.items('paths')
195 pathsitems = cdata.items('paths')
196 else:
196 else:
197 pathsitems = items
197 pathsitems = items
198 for n, path in pathsitems:
198 for n, path in pathsitems:
199 if path and "://" not in path and not os.path.isabs(path):
199 if path and "://" not in path and not os.path.isabs(path):
200 cdata.set("paths", n, os.path.join(root, path))
200 cdata.set("paths", n, os.path.join(root, path))
201
201
202 # update quiet/verbose/debug and interactive status
202 # update quiet/verbose/debug and interactive status
203 if section is None or section == 'ui':
203 if section is None or section == 'ui':
204 if name is None or name in ('quiet', 'verbose', 'debug'):
204 if name is None or name in ('quiet', 'verbose', 'debug'):
205 self.verbosity_constraints()
205 self.verbosity_constraints()
206
206
207 if name is None or name == 'interactive':
207 if name is None or name == 'interactive':
208 self.interactive = self.configbool("ui", "interactive", True)
208 self.interactive = self.configbool("ui", "interactive", True)
209
209
210 # update trust information
210 # update trust information
211 if (section is None or section == 'trusted') and self.trusted_users:
211 if (section is None or section == 'trusted') and self.trusted_users:
212 for user in self.configlist('trusted', 'users'):
212 for user in self.configlist('trusted', 'users'):
213 self.trusted_users[user] = 1
213 self.trusted_users[user] = 1
214 for group in self.configlist('trusted', 'groups'):
214 for group in self.configlist('trusted', 'groups'):
215 self.trusted_groups[group] = 1
215 self.trusted_groups[group] = 1
216
216
217 def setconfig(self, section, name, value):
217 def setconfig(self, section, name, value):
218 if not self.overlay:
218 if not self.overlay:
219 self.overlay = util.configparser()
219 self.overlay = util.configparser()
220 for cdata in (self.overlay, self.cdata, self.ucdata):
220 for cdata in (self.overlay, self.cdata, self.ucdata):
221 if not cdata: continue
221 if not cdata: continue
222 if not cdata.has_section(section):
222 if not cdata.has_section(section):
223 cdata.add_section(section)
223 cdata.add_section(section)
224 cdata.set(section, name, value)
224 cdata.set(section, name, value)
225 self.fixconfig(section, name, value)
225 self.fixconfig(section, name, value)
226
226
227 def _get_cdata(self, untrusted):
227 def _get_cdata(self, untrusted):
228 if untrusted and self.ucdata:
228 if untrusted and self.ucdata:
229 return self.ucdata
229 return self.ucdata
230 return self.cdata
230 return self.cdata
231
231
232 def _config(self, section, name, default, funcname, untrusted, abort):
232 def _config(self, section, name, default, funcname, untrusted, abort):
233 cdata = self._get_cdata(untrusted)
233 cdata = self._get_cdata(untrusted)
234 if cdata.has_option(section, name):
234 if cdata.has_option(section, name):
235 try:
235 try:
236 func = getattr(cdata, funcname)
236 func = getattr(cdata, funcname)
237 return func(section, name)
237 return func(section, name)
238 except ConfigParser.InterpolationError, inst:
238 except ConfigParser.InterpolationError, inst:
239 msg = _("Error in configuration section [%s] "
239 msg = _("Error in configuration section [%s] "
240 "parameter '%s':\n%s") % (section, name, inst)
240 "parameter '%s':\n%s") % (section, name, inst)
241 if abort:
241 if abort:
242 raise util.Abort(msg)
242 raise util.Abort(msg)
243 self.warn(_("Ignored: %s\n") % msg)
243 self.warn(_("Ignored: %s\n") % msg)
244 return default
244 return default
245
245
246 def _configcommon(self, section, name, default, funcname, untrusted):
246 def _configcommon(self, section, name, default, funcname, untrusted):
247 value = self._config(section, name, default, funcname,
247 value = self._config(section, name, default, funcname,
248 untrusted, abort=True)
248 untrusted, abort=True)
249 if self.debugflag and not untrusted and self.ucdata:
249 if self.debugflag and not untrusted and self.ucdata:
250 uvalue = self._config(section, name, None, funcname,
250 uvalue = self._config(section, name, None, funcname,
251 untrusted=True, abort=False)
251 untrusted=True, abort=False)
252 if uvalue is not None and uvalue != value:
252 if uvalue is not None and uvalue != value:
253 self.warn(_("Ignoring untrusted configuration option "
253 self.warn(_("Ignoring untrusted configuration option "
254 "%s.%s = %s\n") % (section, name, uvalue))
254 "%s.%s = %s\n") % (section, name, uvalue))
255 return value
255 return value
256
256
257 def config(self, section, name, default=None, untrusted=False):
257 def config(self, section, name, default=None, untrusted=False):
258 return self._configcommon(section, name, default, 'get', untrusted)
258 return self._configcommon(section, name, default, 'get', untrusted)
259
259
260 def configbool(self, section, name, default=False, untrusted=False):
260 def configbool(self, section, name, default=False, untrusted=False):
261 return self._configcommon(section, name, default, 'getboolean',
261 return self._configcommon(section, name, default, 'getboolean',
262 untrusted)
262 untrusted)
263
263
264 def configlist(self, section, name, default=None, untrusted=False):
264 def configlist(self, section, name, default=None, untrusted=False):
265 """Return a list of comma/space separated strings"""
265 """Return a list of comma/space separated strings"""
266 result = self.config(section, name, untrusted=untrusted)
266 result = self.config(section, name, untrusted=untrusted)
267 if result is None:
267 if result is None:
268 result = default or []
268 result = default or []
269 if isinstance(result, basestring):
269 if isinstance(result, basestring):
270 result = result.replace(",", " ").split()
270 result = result.replace(",", " ").split()
271 return result
271 return result
272
272
273 def has_config(self, section, untrusted=False):
273 def has_config(self, section, untrusted=False):
274 '''tell whether section exists in config.'''
274 '''tell whether section exists in config.'''
275 cdata = self._get_cdata(untrusted)
275 cdata = self._get_cdata(untrusted)
276 return cdata.has_section(section)
276 return cdata.has_section(section)
277
277
278 def _configitems(self, section, untrusted, abort):
278 def _configitems(self, section, untrusted, abort):
279 items = {}
279 items = {}
280 cdata = self._get_cdata(untrusted)
280 cdata = self._get_cdata(untrusted)
281 if cdata.has_section(section):
281 if cdata.has_section(section):
282 try:
282 try:
283 items.update(dict(cdata.items(section)))
283 items.update(dict(cdata.items(section)))
284 except ConfigParser.InterpolationError, inst:
284 except ConfigParser.InterpolationError, inst:
285 msg = _("Error in configuration section [%s]:\n"
285 msg = _("Error in configuration section [%s]:\n"
286 "%s") % (section, inst)
286 "%s") % (section, inst)
287 if abort:
287 if abort:
288 raise util.Abort(msg)
288 raise util.Abort(msg)
289 self.warn(_("Ignored: %s\n") % msg)
289 self.warn(_("Ignored: %s\n") % msg)
290 return items
290 return items
291
291
292 def configitems(self, section, untrusted=False):
292 def configitems(self, section, untrusted=False):
293 items = self._configitems(section, untrusted=untrusted, abort=True)
293 items = self._configitems(section, untrusted=untrusted, abort=True)
294 if self.debugflag and not untrusted and self.ucdata:
294 if self.debugflag and not untrusted and self.ucdata:
295 uitems = self._configitems(section, untrusted=True, abort=False)
295 uitems = self._configitems(section, untrusted=True, abort=False)
296 keys = uitems.keys()
296 keys = uitems.keys()
297 keys.sort()
297 keys.sort()
298 for k in keys:
298 for k in keys:
299 if uitems[k] != items.get(k):
299 if uitems[k] != items.get(k):
300 self.warn(_("Ignoring untrusted configuration option "
300 self.warn(_("Ignoring untrusted configuration option "
301 "%s.%s = %s\n") % (section, k, uitems[k]))
301 "%s.%s = %s\n") % (section, k, uitems[k]))
302 x = items.items()
302 x = items.items()
303 x.sort()
303 x.sort()
304 return x
304 return x
305
305
306 def walkconfig(self, untrusted=False):
306 def walkconfig(self, untrusted=False):
307 cdata = self._get_cdata(untrusted)
307 cdata = self._get_cdata(untrusted)
308 sections = cdata.sections()
308 sections = cdata.sections()
309 sections.sort()
309 sections.sort()
310 for section in sections:
310 for section in sections:
311 for name, value in self.configitems(section, untrusted):
311 for name, value in self.configitems(section, untrusted):
312 yield section, name, value.replace('\n', '\\n')
312 yield section, name, str(value).replace('\n', '\\n')
313
313
314 def extensions(self):
314 def extensions(self):
315 result = self.configitems("extensions")
315 result = self.configitems("extensions")
316 for i, (key, value) in enumerate(result):
316 for i, (key, value) in enumerate(result):
317 if value:
317 if value:
318 result[i] = (key, os.path.expanduser(value))
318 result[i] = (key, os.path.expanduser(value))
319 return result
319 return result
320
320
321 def hgignorefiles(self):
321 def hgignorefiles(self):
322 result = []
322 result = []
323 for key, value in self.configitems("ui"):
323 for key, value in self.configitems("ui"):
324 if key == 'ignore' or key.startswith('ignore.'):
324 if key == 'ignore' or key.startswith('ignore.'):
325 result.append(os.path.expanduser(value))
325 result.append(os.path.expanduser(value))
326 return result
326 return result
327
327
328 def configrevlog(self):
328 def configrevlog(self):
329 result = {}
329 result = {}
330 for key, value in self.configitems("revlog"):
330 for key, value in self.configitems("revlog"):
331 result[key.lower()] = value
331 result[key.lower()] = value
332 return result
332 return result
333
333
334 def username(self):
334 def username(self):
335 """Return default username to be used in commits.
335 """Return default username to be used in commits.
336
336
337 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
337 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
338 and stop searching if one of these is set.
338 and stop searching if one of these is set.
339 If not found, use ($LOGNAME or $USER or $LNAME or
339 If not found, use ($LOGNAME or $USER or $LNAME or
340 $USERNAME) +"@full.hostname".
340 $USERNAME) +"@full.hostname".
341 """
341 """
342 user = os.environ.get("HGUSER")
342 user = os.environ.get("HGUSER")
343 if user is None:
343 if user is None:
344 user = self.config("ui", "username")
344 user = self.config("ui", "username")
345 if user is None:
345 if user is None:
346 user = os.environ.get("EMAIL")
346 user = os.environ.get("EMAIL")
347 if user is None:
347 if user is None:
348 try:
348 try:
349 user = '%s@%s' % (util.getuser(), socket.getfqdn())
349 user = '%s@%s' % (util.getuser(), socket.getfqdn())
350 self.warn(_("No username found, using '%s' instead\n") % user)
350 self.warn(_("No username found, using '%s' instead\n") % user)
351 except KeyError:
351 except KeyError:
352 pass
352 pass
353 if not user:
353 if not user:
354 raise util.Abort(_("Please specify a username."))
354 raise util.Abort(_("Please specify a username."))
355 return user
355 return user
356
356
357 def shortuser(self, user):
357 def shortuser(self, user):
358 """Return a short representation of a user name or email address."""
358 """Return a short representation of a user name or email address."""
359 if not self.verbose: user = util.shortuser(user)
359 if not self.verbose: user = util.shortuser(user)
360 return user
360 return user
361
361
362 def expandpath(self, loc, default=None):
362 def expandpath(self, loc, default=None):
363 """Return repository location relative to cwd or from [paths]"""
363 """Return repository location relative to cwd or from [paths]"""
364 if "://" in loc or os.path.isdir(loc):
364 if "://" in loc or os.path.isdir(loc):
365 return loc
365 return loc
366
366
367 path = self.config("paths", loc)
367 path = self.config("paths", loc)
368 if not path and default is not None:
368 if not path and default is not None:
369 path = self.config("paths", default)
369 path = self.config("paths", default)
370 return path or loc
370 return path or loc
371
371
372 def pushbuffer(self):
372 def pushbuffer(self):
373 self.buffers.append([])
373 self.buffers.append([])
374
374
375 def popbuffer(self):
375 def popbuffer(self):
376 return "".join(self.buffers.pop())
376 return "".join(self.buffers.pop())
377
377
378 def write(self, *args):
378 def write(self, *args):
379 if self.buffers:
379 if self.buffers:
380 self.buffers[-1].extend([str(a) for a in args])
380 self.buffers[-1].extend([str(a) for a in args])
381 else:
381 else:
382 for a in args:
382 for a in args:
383 sys.stdout.write(str(a))
383 sys.stdout.write(str(a))
384
384
385 def write_err(self, *args):
385 def write_err(self, *args):
386 try:
386 try:
387 if not sys.stdout.closed: sys.stdout.flush()
387 if not sys.stdout.closed: sys.stdout.flush()
388 for a in args:
388 for a in args:
389 sys.stderr.write(str(a))
389 sys.stderr.write(str(a))
390 # stderr may be buffered under win32 when redirected to files,
390 # stderr may be buffered under win32 when redirected to files,
391 # including stdout.
391 # including stdout.
392 if not sys.stderr.closed: sys.stderr.flush()
392 if not sys.stderr.closed: sys.stderr.flush()
393 except IOError, inst:
393 except IOError, inst:
394 if inst.errno != errno.EPIPE:
394 if inst.errno != errno.EPIPE:
395 raise
395 raise
396
396
397 def flush(self):
397 def flush(self):
398 try: sys.stdout.flush()
398 try: sys.stdout.flush()
399 except: pass
399 except: pass
400 try: sys.stderr.flush()
400 try: sys.stderr.flush()
401 except: pass
401 except: pass
402
402
403 def readline(self):
403 def readline(self):
404 return sys.stdin.readline()[:-1]
404 return sys.stdin.readline()[:-1]
405 def prompt(self, msg, pat=None, default="y"):
405 def prompt(self, msg, pat=None, default="y"):
406 if not self.interactive: return default
406 if not self.interactive: return default
407 while 1:
407 while 1:
408 self.write(msg, " ")
408 self.write(msg, " ")
409 r = self.readline()
409 r = self.readline()
410 if not pat or re.match(pat, r):
410 if not pat or re.match(pat, r):
411 return r
411 return r
412 else:
412 else:
413 self.write(_("unrecognized response\n"))
413 self.write(_("unrecognized response\n"))
414 def getpass(self, prompt=None, default=None):
414 def getpass(self, prompt=None, default=None):
415 if not self.interactive: return default
415 if not self.interactive: return default
416 return getpass.getpass(prompt or _('password: '))
416 return getpass.getpass(prompt or _('password: '))
417 def status(self, *msg):
417 def status(self, *msg):
418 if not self.quiet: self.write(*msg)
418 if not self.quiet: self.write(*msg)
419 def warn(self, *msg):
419 def warn(self, *msg):
420 self.write_err(*msg)
420 self.write_err(*msg)
421 def note(self, *msg):
421 def note(self, *msg):
422 if self.verbose: self.write(*msg)
422 if self.verbose: self.write(*msg)
423 def debug(self, *msg):
423 def debug(self, *msg):
424 if self.debugflag: self.write(*msg)
424 if self.debugflag: self.write(*msg)
425 def edit(self, text, user):
425 def edit(self, text, user):
426 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
426 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
427 text=True)
427 text=True)
428 try:
428 try:
429 f = os.fdopen(fd, "w")
429 f = os.fdopen(fd, "w")
430 f.write(text)
430 f.write(text)
431 f.close()
431 f.close()
432
432
433 editor = (os.environ.get("HGEDITOR") or
433 editor = (os.environ.get("HGEDITOR") or
434 self.config("ui", "editor") or
434 self.config("ui", "editor") or
435 os.environ.get("EDITOR", "vi"))
435 os.environ.get("EDITOR", "vi"))
436
436
437 util.system("%s \"%s\"" % (editor, name),
437 util.system("%s \"%s\"" % (editor, name),
438 environ={'HGUSER': user},
438 environ={'HGUSER': user},
439 onerr=util.Abort, errprefix=_("edit failed"))
439 onerr=util.Abort, errprefix=_("edit failed"))
440
440
441 f = open(name)
441 f = open(name)
442 t = f.read()
442 t = f.read()
443 f.close()
443 f.close()
444 t = re.sub("(?m)^HG:.*\n", "", t)
444 t = re.sub("(?m)^HG:.*\n", "", t)
445 finally:
445 finally:
446 os.unlink(name)
446 os.unlink(name)
447
447
448 return t
448 return t
449
449
450 def print_exc(self):
450 def print_exc(self):
451 '''print exception traceback if traceback printing enabled.
451 '''print exception traceback if traceback printing enabled.
452 only to call in exception handler. returns true if traceback
452 only to call in exception handler. returns true if traceback
453 printed.'''
453 printed.'''
454 if self.traceback:
454 if self.traceback:
455 traceback.print_exc()
455 traceback.print_exc()
456 return self.traceback
456 return self.traceback
@@ -1,206 +1,208 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 # commit hooks can see env vars
3 # commit hooks can see env vars
4 hg init a
4 hg init a
5 cd a
5 cd a
6 echo "[hooks]" > .hg/hgrc
6 echo "[hooks]" > .hg/hgrc
7 echo 'commit = echo commit hook: n=$HG_NODE p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc
7 echo 'commit = echo commit hook: n=$HG_NODE p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc
8 echo 'commit.b = echo commit hook b' >> .hg/hgrc
8 echo 'commit.b = echo commit hook b' >> .hg/hgrc
9 echo 'precommit = echo precommit hook: p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc
9 echo 'precommit = echo precommit hook: p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc
10 echo 'pretxncommit = echo pretxncommit hook: n=$HG_NODE p1=$HG_PARENT1 p2=$HG_PARENT2; hg -q tip' >> .hg/hgrc
10 echo 'pretxncommit = echo pretxncommit hook: n=$HG_NODE p1=$HG_PARENT1 p2=$HG_PARENT2; hg -q tip' >> .hg/hgrc
11 echo a > a
11 echo a > a
12 hg add a
12 hg add a
13 hg commit -m a -d "1000000 0"
13 hg commit -m a -d "1000000 0"
14
14
15 hg clone . ../b
15 hg clone . ../b
16 cd ../b
16 cd ../b
17
17
18 # changegroup hooks can see env vars
18 # changegroup hooks can see env vars
19 echo '[hooks]' > .hg/hgrc
19 echo '[hooks]' > .hg/hgrc
20 echo 'prechangegroup = echo prechangegroup hook: u=`echo $HG_URL | sed s,file:.*,file:,`' >> .hg/hgrc
20 echo 'prechangegroup = echo prechangegroup hook: u=`echo $HG_URL | sed s,file:.*,file:,`' >> .hg/hgrc
21 echo 'changegroup = echo changegroup hook: n=$HG_NODE u=`echo $HG_URL | sed s,file:.*,file:,`' >> .hg/hgrc
21 echo 'changegroup = echo changegroup hook: n=$HG_NODE u=`echo $HG_URL | sed s,file:.*,file:,`' >> .hg/hgrc
22 echo 'incoming = echo incoming hook: n=$HG_NODE u=`echo $HG_URL | sed s,file:.*,file:,`' >> .hg/hgrc
22 echo 'incoming = echo incoming hook: n=$HG_NODE u=`echo $HG_URL | sed s,file:.*,file:,`' >> .hg/hgrc
23
23
24 # pretxncommit and commit hooks can see both parents of merge
24 # pretxncommit and commit hooks can see both parents of merge
25 cd ../a
25 cd ../a
26 echo b >> a
26 echo b >> a
27 hg commit -m a1 -d "1 0"
27 hg commit -m a1 -d "1 0"
28 hg update -C 0
28 hg update -C 0
29 echo b > b
29 echo b > b
30 hg add b
30 hg add b
31 hg commit -m b -d '1 0'
31 hg commit -m b -d '1 0'
32 hg merge 1
32 hg merge 1
33 hg commit -m merge -d '2 0'
33 hg commit -m merge -d '2 0'
34
34
35 cd ../b
35 cd ../b
36 hg pull ../a
36 hg pull ../a
37
37
38 # tag hooks can see env vars
38 # tag hooks can see env vars
39 cd ../a
39 cd ../a
40 echo 'pretag = echo pretag hook: t=$HG_TAG n=$HG_NODE l=$HG_LOCAL' >> .hg/hgrc
40 echo 'pretag = echo pretag hook: t=$HG_TAG n=$HG_NODE l=$HG_LOCAL' >> .hg/hgrc
41 echo 'tag = echo tag hook: t=$HG_TAG n=$HG_NODE l=$HG_LOCAL' >> .hg/hgrc
41 echo 'tag = echo tag hook: t=$HG_TAG n=$HG_NODE l=$HG_LOCAL' >> .hg/hgrc
42 hg tag -d '3 0' a
42 hg tag -d '3 0' a
43 hg tag -l la
43 hg tag -l la
44
44
45 # pretag hook can forbid tagging
45 # pretag hook can forbid tagging
46 echo 'pretag.forbid = echo pretag.forbid hook; exit 1' >> .hg/hgrc
46 echo 'pretag.forbid = echo pretag.forbid hook; exit 1' >> .hg/hgrc
47 hg tag -d '4 0' fa
47 hg tag -d '4 0' fa
48 hg tag -l fla
48 hg tag -l fla
49
49
50 # pretxncommit hook can see changeset, can roll back txn, changeset
50 # pretxncommit hook can see changeset, can roll back txn, changeset
51 # no more there after
51 # no more there after
52 echo 'pretxncommit.forbid = echo pretxncommit.forbid hook: tip=`hg -q tip`; exit 1' >> .hg/hgrc
52 echo 'pretxncommit.forbid = echo pretxncommit.forbid hook: tip=`hg -q tip`; exit 1' >> .hg/hgrc
53 echo z > z
53 echo z > z
54 hg add z
54 hg add z
55 hg -q tip
55 hg -q tip
56 hg commit -m 'fail' -d '4 0'
56 hg commit -m 'fail' -d '4 0'
57 hg -q tip
57 hg -q tip
58
58
59 # precommit hook can prevent commit
59 # precommit hook can prevent commit
60 echo 'precommit.forbid = echo precommit.forbid hook; exit 1' >> .hg/hgrc
60 echo 'precommit.forbid = echo precommit.forbid hook; exit 1' >> .hg/hgrc
61 hg commit -m 'fail' -d '4 0'
61 hg commit -m 'fail' -d '4 0'
62 hg -q tip
62 hg -q tip
63
63
64 # preupdate hook can prevent update
64 # preupdate hook can prevent update
65 echo 'preupdate = echo preupdate hook: p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc
65 echo 'preupdate = echo preupdate hook: p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc
66 hg update 1
66 hg update 1
67
67
68 # update hook
68 # update hook
69 echo 'update = echo update hook: p1=$HG_PARENT1 p2=$HG_PARENT2 err=$HG_ERROR' >> .hg/hgrc
69 echo 'update = echo update hook: p1=$HG_PARENT1 p2=$HG_PARENT2 err=$HG_ERROR' >> .hg/hgrc
70 hg update
70 hg update
71
71
72 # prechangegroup hook can prevent incoming changes
72 # prechangegroup hook can prevent incoming changes
73 cd ../b
73 cd ../b
74 hg -q tip
74 hg -q tip
75 echo '[hooks]' > .hg/hgrc
75 echo '[hooks]' > .hg/hgrc
76 echo 'prechangegroup.forbid = echo prechangegroup.forbid hook; exit 1' >> .hg/hgrc
76 echo 'prechangegroup.forbid = echo prechangegroup.forbid hook; exit 1' >> .hg/hgrc
77 hg pull ../a
77 hg pull ../a
78
78
79 # pretxnchangegroup hook can see incoming changes, can roll back txn,
79 # pretxnchangegroup hook can see incoming changes, can roll back txn,
80 # incoming changes no longer there after
80 # incoming changes no longer there after
81 echo '[hooks]' > .hg/hgrc
81 echo '[hooks]' > .hg/hgrc
82 echo 'pretxnchangegroup.forbid = echo pretxnchangegroup.forbid hook: tip=`hg -q tip`; exit 1' >> .hg/hgrc
82 echo 'pretxnchangegroup.forbid = echo pretxnchangegroup.forbid hook: tip=`hg -q tip`; exit 1' >> .hg/hgrc
83 hg pull ../a
83 hg pull ../a
84 hg -q tip
84 hg -q tip
85
85
86 # outgoing hooks can see env vars
86 # outgoing hooks can see env vars
87 rm .hg/hgrc
87 rm .hg/hgrc
88 echo '[hooks]' > ../a/.hg/hgrc
88 echo '[hooks]' > ../a/.hg/hgrc
89 echo 'preoutgoing = echo preoutgoing hook: s=$HG_SOURCE' >> ../a/.hg/hgrc
89 echo 'preoutgoing = echo preoutgoing hook: s=$HG_SOURCE' >> ../a/.hg/hgrc
90 echo 'outgoing = echo outgoing hook: n=$HG_NODE s=$HG_SOURCE' >> ../a/.hg/hgrc
90 echo 'outgoing = echo outgoing hook: n=$HG_NODE s=$HG_SOURCE' >> ../a/.hg/hgrc
91 hg pull ../a
91 hg pull ../a
92 hg rollback
92 hg rollback
93
93
94 # preoutgoing hook can prevent outgoing changes
94 # preoutgoing hook can prevent outgoing changes
95 echo 'preoutgoing.forbid = echo preoutgoing.forbid hook; exit 1' >> ../a/.hg/hgrc
95 echo 'preoutgoing.forbid = echo preoutgoing.forbid hook; exit 1' >> ../a/.hg/hgrc
96 hg pull ../a
96 hg pull ../a
97
97
98 cat > hooktests.py <<EOF
98 cat > hooktests.py <<EOF
99 from mercurial import util
99 from mercurial import util
100
100
101 uncallable = 0
101 uncallable = 0
102
102
103 def printargs(args):
103 def printargs(args):
104 args.pop('ui', None)
104 args.pop('ui', None)
105 args.pop('repo', None)
105 args.pop('repo', None)
106 a = list(args.items())
106 a = list(args.items())
107 a.sort()
107 a.sort()
108 print 'hook args:'
108 print 'hook args:'
109 for k, v in a:
109 for k, v in a:
110 print ' ', k, v
110 print ' ', k, v
111
111
112 def passhook(**args):
112 def passhook(**args):
113 printargs(args)
113 printargs(args)
114
114
115 def failhook(**args):
115 def failhook(**args):
116 printargs(args)
116 printargs(args)
117 return True
117 return True
118
118
119 class LocalException(Exception):
119 class LocalException(Exception):
120 pass
120 pass
121
121
122 def raisehook(**args):
122 def raisehook(**args):
123 raise LocalException('exception from hook')
123 raise LocalException('exception from hook')
124
124
125 def aborthook(**args):
125 def aborthook(**args):
126 raise util.Abort('raise abort from hook')
126 raise util.Abort('raise abort from hook')
127
127
128 def brokenhook(**args):
128 def brokenhook(**args):
129 return 1 + {}
129 return 1 + {}
130
130
131 class container:
131 class container:
132 unreachable = 1
132 unreachable = 1
133 EOF
133 EOF
134
134
135 echo '# test python hooks'
135 echo '# test python hooks'
136 PYTHONPATH="`pwd`:$PYTHONPATH"
136 PYTHONPATH="`pwd`:$PYTHONPATH"
137 export PYTHONPATH
137 export PYTHONPATH
138
138
139 echo '[hooks]' > ../a/.hg/hgrc
139 echo '[hooks]' > ../a/.hg/hgrc
140 echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc
140 echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc
141 hg pull ../a 2>&1 | grep 'raised an exception'
141 hg pull ../a 2>&1 | grep 'raised an exception'
142
142
143 echo '[hooks]' > ../a/.hg/hgrc
143 echo '[hooks]' > ../a/.hg/hgrc
144 echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc
144 echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc
145 hg pull ../a 2>&1 | grep 'raised an exception'
145 hg pull ../a 2>&1 | grep 'raised an exception'
146
146
147 echo '[hooks]' > ../a/.hg/hgrc
147 echo '[hooks]' > ../a/.hg/hgrc
148 echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc
148 echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc
149 hg pull ../a
149 hg pull ../a
150
150
151 echo '[hooks]' > ../a/.hg/hgrc
151 echo '[hooks]' > ../a/.hg/hgrc
152 echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc
152 echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc
153 hg pull ../a
153 hg pull ../a
154
154
155 echo '[hooks]' > ../a/.hg/hgrc
155 echo '[hooks]' > ../a/.hg/hgrc
156 echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc
156 echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc
157 hg pull ../a
157 hg pull ../a
158
158
159 echo '[hooks]' > ../a/.hg/hgrc
159 echo '[hooks]' > ../a/.hg/hgrc
160 echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc
160 echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc
161 hg pull ../a
161 hg pull ../a
162
162
163 echo '[hooks]' > ../a/.hg/hgrc
163 echo '[hooks]' > ../a/.hg/hgrc
164 echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc
164 echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc
165 hg pull ../a
165 hg pull ../a
166
166
167 echo '[hooks]' > ../a/.hg/hgrc
167 echo '[hooks]' > ../a/.hg/hgrc
168 echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc
168 echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc
169 hg pull ../a
169 hg pull ../a
170
170
171 echo '[hooks]' > ../a/.hg/hgrc
171 echo '[hooks]' > ../a/.hg/hgrc
172 echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc
172 echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc
173 hg pull ../a
173 hg pull ../a
174
174
175 echo '[hooks]' > ../a/.hg/hgrc
175 echo '[hooks]' > ../a/.hg/hgrc
176 echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc
176 echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc
177 hg pull ../a
177 hg pull ../a
178
178
179 echo '# make sure --traceback works'
179 echo '# make sure --traceback works'
180 echo '[hooks]' > .hg/hgrc
180 echo '[hooks]' > .hg/hgrc
181 echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc
181 echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc
182
182
183 echo a >> a
183 echo a >> a
184 hg --traceback commit -A -m a 2>&1 | grep '^Traceback'
184 hg --traceback commit -A -m a 2>&1 | grep '^Traceback'
185
185
186 cd ..
186 cd ..
187 hg init c
187 hg init c
188 cd c
188 cd c
189
189
190 cat > hookext.py <<EOF
190 cat > hookext.py <<EOF
191 def autohook(**args):
191 def autohook(**args):
192 print "Automatically installed hook"
192 print "Automatically installed hook"
193
193
194 def reposetup(ui, repo):
194 def reposetup(ui, repo):
195 repo.ui.setconfig("hooks", "commit.auto", autohook)
195 repo.ui.setconfig("hooks", "commit.auto", autohook)
196 EOF
196 EOF
197 echo '[extensions]' >> .hg/hgrc
197 echo '[extensions]' >> .hg/hgrc
198 echo 'hookext = hookext.py' >> .hg/hgrc
198 echo 'hookext = hookext.py' >> .hg/hgrc
199
199
200 touch foo
200 touch foo
201 hg add foo
201 hg add foo
202 hg ci -m 'add foo'
202 hg ci -m 'add foo'
203 echo >> foo
203 echo >> foo
204 hg ci --debug -m 'change foo' | sed -e 's/ at .*>/>/'
204 hg ci --debug -m 'change foo' | sed -e 's/ at .*>/>/'
205
205
206 hg showconfig hooks | sed -e 's/ at .*>/>/'
207
206 exit 0
208 exit 0
@@ -1,144 +1,145 b''
1 precommit hook: p1=0000000000000000000000000000000000000000 p2=
1 precommit hook: p1=0000000000000000000000000000000000000000 p2=
2 pretxncommit hook: n=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p1=0000000000000000000000000000000000000000 p2=
2 pretxncommit hook: n=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p1=0000000000000000000000000000000000000000 p2=
3 0:29b62aeb769f
3 0:29b62aeb769f
4 commit hook: n=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p1=0000000000000000000000000000000000000000 p2=
4 commit hook: n=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p1=0000000000000000000000000000000000000000 p2=
5 commit hook b
5 commit hook b
6 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
6 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
7 precommit hook: p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
7 precommit hook: p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
8 pretxncommit hook: n=b702efe9688826e3a91283852b328b84dbf37bc2 p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
8 pretxncommit hook: n=b702efe9688826e3a91283852b328b84dbf37bc2 p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
9 1:b702efe96888
9 1:b702efe96888
10 commit hook: n=b702efe9688826e3a91283852b328b84dbf37bc2 p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
10 commit hook: n=b702efe9688826e3a91283852b328b84dbf37bc2 p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
11 commit hook b
11 commit hook b
12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 precommit hook: p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
13 precommit hook: p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
14 pretxncommit hook: n=1324a5531bac09b329c3845d35ae6a7526874edb p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
14 pretxncommit hook: n=1324a5531bac09b329c3845d35ae6a7526874edb p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
15 2:1324a5531bac
15 2:1324a5531bac
16 commit hook: n=1324a5531bac09b329c3845d35ae6a7526874edb p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
16 commit hook: n=1324a5531bac09b329c3845d35ae6a7526874edb p1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b p2=
17 commit hook b
17 commit hook b
18 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
18 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
19 (branch merge, don't forget to commit)
19 (branch merge, don't forget to commit)
20 precommit hook: p1=1324a5531bac09b329c3845d35ae6a7526874edb p2=b702efe9688826e3a91283852b328b84dbf37bc2
20 precommit hook: p1=1324a5531bac09b329c3845d35ae6a7526874edb p2=b702efe9688826e3a91283852b328b84dbf37bc2
21 pretxncommit hook: n=4c52fb2e402287dd5dc052090682536c8406c321 p1=1324a5531bac09b329c3845d35ae6a7526874edb p2=b702efe9688826e3a91283852b328b84dbf37bc2
21 pretxncommit hook: n=4c52fb2e402287dd5dc052090682536c8406c321 p1=1324a5531bac09b329c3845d35ae6a7526874edb p2=b702efe9688826e3a91283852b328b84dbf37bc2
22 3:4c52fb2e4022
22 3:4c52fb2e4022
23 commit hook: n=4c52fb2e402287dd5dc052090682536c8406c321 p1=1324a5531bac09b329c3845d35ae6a7526874edb p2=b702efe9688826e3a91283852b328b84dbf37bc2
23 commit hook: n=4c52fb2e402287dd5dc052090682536c8406c321 p1=1324a5531bac09b329c3845d35ae6a7526874edb p2=b702efe9688826e3a91283852b328b84dbf37bc2
24 commit hook b
24 commit hook b
25 prechangegroup hook: u=file:
25 prechangegroup hook: u=file:
26 changegroup hook: n=b702efe9688826e3a91283852b328b84dbf37bc2 u=file:
26 changegroup hook: n=b702efe9688826e3a91283852b328b84dbf37bc2 u=file:
27 incoming hook: n=b702efe9688826e3a91283852b328b84dbf37bc2 u=file:
27 incoming hook: n=b702efe9688826e3a91283852b328b84dbf37bc2 u=file:
28 incoming hook: n=1324a5531bac09b329c3845d35ae6a7526874edb u=file:
28 incoming hook: n=1324a5531bac09b329c3845d35ae6a7526874edb u=file:
29 incoming hook: n=4c52fb2e402287dd5dc052090682536c8406c321 u=file:
29 incoming hook: n=4c52fb2e402287dd5dc052090682536c8406c321 u=file:
30 pulling from ../a
30 pulling from ../a
31 searching for changes
31 searching for changes
32 adding changesets
32 adding changesets
33 adding manifests
33 adding manifests
34 adding file changes
34 adding file changes
35 added 3 changesets with 2 changes to 2 files
35 added 3 changesets with 2 changes to 2 files
36 (run 'hg update' to get a working copy)
36 (run 'hg update' to get a working copy)
37 pretag hook: t=a n=4c52fb2e402287dd5dc052090682536c8406c321 l=0
37 pretag hook: t=a n=4c52fb2e402287dd5dc052090682536c8406c321 l=0
38 precommit hook: p1=4c52fb2e402287dd5dc052090682536c8406c321 p2=
38 precommit hook: p1=4c52fb2e402287dd5dc052090682536c8406c321 p2=
39 pretxncommit hook: n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 p1=4c52fb2e402287dd5dc052090682536c8406c321 p2=
39 pretxncommit hook: n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 p1=4c52fb2e402287dd5dc052090682536c8406c321 p2=
40 4:8ea2ef7ad3e8
40 4:8ea2ef7ad3e8
41 commit hook: n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 p1=4c52fb2e402287dd5dc052090682536c8406c321 p2=
41 commit hook: n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 p1=4c52fb2e402287dd5dc052090682536c8406c321 p2=
42 commit hook b
42 commit hook b
43 tag hook: t=a n=4c52fb2e402287dd5dc052090682536c8406c321 l=0
43 tag hook: t=a n=4c52fb2e402287dd5dc052090682536c8406c321 l=0
44 pretag hook: t=la n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 l=1
44 pretag hook: t=la n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 l=1
45 tag hook: t=la n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 l=1
45 tag hook: t=la n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 l=1
46 pretag hook: t=fa n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 l=0
46 pretag hook: t=fa n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 l=0
47 pretag.forbid hook
47 pretag.forbid hook
48 abort: pretag.forbid hook exited with status 1
48 abort: pretag.forbid hook exited with status 1
49 pretag hook: t=fla n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 l=1
49 pretag hook: t=fla n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 l=1
50 pretag.forbid hook
50 pretag.forbid hook
51 abort: pretag.forbid hook exited with status 1
51 abort: pretag.forbid hook exited with status 1
52 4:8ea2ef7ad3e8
52 4:8ea2ef7ad3e8
53 precommit hook: p1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 p2=
53 precommit hook: p1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 p2=
54 pretxncommit hook: n=fad284daf8c032148abaffcd745dafeceefceb61 p1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 p2=
54 pretxncommit hook: n=fad284daf8c032148abaffcd745dafeceefceb61 p1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 p2=
55 5:fad284daf8c0
55 5:fad284daf8c0
56 pretxncommit.forbid hook: tip=5:fad284daf8c0
56 pretxncommit.forbid hook: tip=5:fad284daf8c0
57 abort: pretxncommit.forbid hook exited with status 1
57 abort: pretxncommit.forbid hook exited with status 1
58 transaction abort!
58 transaction abort!
59 rollback completed
59 rollback completed
60 4:8ea2ef7ad3e8
60 4:8ea2ef7ad3e8
61 precommit hook: p1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 p2=
61 precommit hook: p1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 p2=
62 precommit.forbid hook
62 precommit.forbid hook
63 abort: precommit.forbid hook exited with status 1
63 abort: precommit.forbid hook exited with status 1
64 4:8ea2ef7ad3e8
64 4:8ea2ef7ad3e8
65 preupdate hook: p1=b702efe96888 p2=
65 preupdate hook: p1=b702efe96888 p2=
66 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
66 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
67 preupdate hook: p1=8ea2ef7ad3e8 p2=
67 preupdate hook: p1=8ea2ef7ad3e8 p2=
68 update hook: p1=8ea2ef7ad3e8 p2= err=0
68 update hook: p1=8ea2ef7ad3e8 p2= err=0
69 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 3:4c52fb2e4022
70 3:4c52fb2e4022
71 prechangegroup.forbid hook
71 prechangegroup.forbid hook
72 pulling from ../a
72 pulling from ../a
73 searching for changes
73 searching for changes
74 abort: prechangegroup.forbid hook exited with status 1
74 abort: prechangegroup.forbid hook exited with status 1
75 pretxnchangegroup.forbid hook: tip=4:8ea2ef7ad3e8
75 pretxnchangegroup.forbid hook: tip=4:8ea2ef7ad3e8
76 pulling from ../a
76 pulling from ../a
77 searching for changes
77 searching for changes
78 adding changesets
78 adding changesets
79 adding manifests
79 adding manifests
80 adding file changes
80 adding file changes
81 added 1 changesets with 1 changes to 1 files
81 added 1 changesets with 1 changes to 1 files
82 abort: pretxnchangegroup.forbid hook exited with status 1
82 abort: pretxnchangegroup.forbid hook exited with status 1
83 transaction abort!
83 transaction abort!
84 rollback completed
84 rollback completed
85 3:4c52fb2e4022
85 3:4c52fb2e4022
86 preoutgoing hook: s=pull
86 preoutgoing hook: s=pull
87 outgoing hook: n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 s=pull
87 outgoing hook: n=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 s=pull
88 pulling from ../a
88 pulling from ../a
89 searching for changes
89 searching for changes
90 adding changesets
90 adding changesets
91 adding manifests
91 adding manifests
92 adding file changes
92 adding file changes
93 added 1 changesets with 1 changes to 1 files
93 added 1 changesets with 1 changes to 1 files
94 (run 'hg update' to get a working copy)
94 (run 'hg update' to get a working copy)
95 rolling back last transaction
95 rolling back last transaction
96 preoutgoing hook: s=pull
96 preoutgoing hook: s=pull
97 preoutgoing.forbid hook
97 preoutgoing.forbid hook
98 pulling from ../a
98 pulling from ../a
99 searching for changes
99 searching for changes
100 abort: preoutgoing.forbid hook exited with status 1
100 abort: preoutgoing.forbid hook exited with status 1
101 # test python hooks
101 # test python hooks
102 error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
102 error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
103 error: preoutgoing.raise hook raised an exception: exception from hook
103 error: preoutgoing.raise hook raised an exception: exception from hook
104 pulling from ../a
104 pulling from ../a
105 searching for changes
105 searching for changes
106 error: preoutgoing.abort hook failed: raise abort from hook
106 error: preoutgoing.abort hook failed: raise abort from hook
107 abort: raise abort from hook
107 abort: raise abort from hook
108 pulling from ../a
108 pulling from ../a
109 searching for changes
109 searching for changes
110 hook args:
110 hook args:
111 hooktype preoutgoing
111 hooktype preoutgoing
112 source pull
112 source pull
113 abort: preoutgoing.fail hook failed
113 abort: preoutgoing.fail hook failed
114 pulling from ../a
114 pulling from ../a
115 searching for changes
115 searching for changes
116 abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
116 abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
117 pulling from ../a
117 pulling from ../a
118 searching for changes
118 searching for changes
119 abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
119 abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
120 pulling from ../a
120 pulling from ../a
121 searching for changes
121 searching for changes
122 abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
122 abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
123 pulling from ../a
123 pulling from ../a
124 searching for changes
124 searching for changes
125 abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
125 abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
126 pulling from ../a
126 pulling from ../a
127 searching for changes
127 searching for changes
128 abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
128 abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
129 pulling from ../a
129 pulling from ../a
130 searching for changes
130 searching for changes
131 hook args:
131 hook args:
132 hooktype preoutgoing
132 hooktype preoutgoing
133 source pull
133 source pull
134 adding changesets
134 adding changesets
135 adding manifests
135 adding manifests
136 adding file changes
136 adding file changes
137 added 1 changesets with 1 changes to 1 files
137 added 1 changesets with 1 changes to 1 files
138 (run 'hg update' to get a working copy)
138 (run 'hg update' to get a working copy)
139 # make sure --traceback works
139 # make sure --traceback works
140 Traceback (most recent call last):
140 Traceback (most recent call last):
141 Automatically installed hook
141 Automatically installed hook
142 foo
142 foo
143 calling hook commit.auto: <function autohook>
143 calling hook commit.auto: <function autohook>
144 Automatically installed hook
144 Automatically installed hook
145 hooks.commit.auto=<function autohook>
General Comments 0
You need to be logged in to leave comments. Login now