##// END OF EJS Templates
ui: replace obsolete default-push with default:pushurl (issue5485)...
Rishabh Madan -
r31064:4431add9 stable
parent child Browse files
Show More
@@ -1,1431 +1,1431 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import contextlib
10 import contextlib
11 import errno
11 import errno
12 import getpass
12 import getpass
13 import inspect
13 import inspect
14 import os
14 import os
15 import re
15 import re
16 import socket
16 import socket
17 import sys
17 import sys
18 import tempfile
18 import tempfile
19 import traceback
19 import traceback
20
20
21 from .i18n import _
21 from .i18n import _
22 from .node import hex
22 from .node import hex
23
23
24 from . import (
24 from . import (
25 config,
25 config,
26 encoding,
26 encoding,
27 error,
27 error,
28 formatter,
28 formatter,
29 progress,
29 progress,
30 pycompat,
30 pycompat,
31 scmutil,
31 scmutil,
32 util,
32 util,
33 )
33 )
34
34
35 urlreq = util.urlreq
35 urlreq = util.urlreq
36
36
37 samplehgrcs = {
37 samplehgrcs = {
38 'user':
38 'user':
39 """# example user config (see 'hg help config' for more info)
39 """# example user config (see 'hg help config' for more info)
40 [ui]
40 [ui]
41 # name and email, e.g.
41 # name and email, e.g.
42 # username = Jane Doe <jdoe@example.com>
42 # username = Jane Doe <jdoe@example.com>
43 username =
43 username =
44
44
45 [extensions]
45 [extensions]
46 # uncomment these lines to enable some popular extensions
46 # uncomment these lines to enable some popular extensions
47 # (see 'hg help extensions' for more info)
47 # (see 'hg help extensions' for more info)
48 #
48 #
49 # pager =
49 # pager =
50 # color =""",
50 # color =""",
51
51
52 'cloned':
52 'cloned':
53 """# example repository config (see 'hg help config' for more info)
53 """# example repository config (see 'hg help config' for more info)
54 [paths]
54 [paths]
55 default = %s
55 default = %s
56
56
57 # path aliases to other clones of this repo in URLs or filesystem paths
57 # path aliases to other clones of this repo in URLs or filesystem paths
58 # (see 'hg help config.paths' for more info)
58 # (see 'hg help config.paths' for more info)
59 #
59 #
60 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
60 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
61 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
61 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
62 # my-clone = /home/jdoe/jdoes-clone
62 # my-clone = /home/jdoe/jdoes-clone
63
63
64 [ui]
64 [ui]
65 # name and email (local to this repository, optional), e.g.
65 # name and email (local to this repository, optional), e.g.
66 # username = Jane Doe <jdoe@example.com>
66 # username = Jane Doe <jdoe@example.com>
67 """,
67 """,
68
68
69 'local':
69 'local':
70 """# example repository config (see 'hg help config' for more info)
70 """# example repository config (see 'hg help config' for more info)
71 [paths]
71 [paths]
72 # path aliases to other clones of this repo in URLs or filesystem paths
72 # path aliases to other clones of this repo in URLs or filesystem paths
73 # (see 'hg help config.paths' for more info)
73 # (see 'hg help config.paths' for more info)
74 #
74 #
75 # default = http://example.com/hg/example-repo
75 # default = http://example.com/hg/example-repo
76 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
76 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
77 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
77 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
78 # my-clone = /home/jdoe/jdoes-clone
78 # my-clone = /home/jdoe/jdoes-clone
79
79
80 [ui]
80 [ui]
81 # name and email (local to this repository, optional), e.g.
81 # name and email (local to this repository, optional), e.g.
82 # username = Jane Doe <jdoe@example.com>
82 # username = Jane Doe <jdoe@example.com>
83 """,
83 """,
84
84
85 'global':
85 'global':
86 """# example system-wide hg config (see 'hg help config' for more info)
86 """# example system-wide hg config (see 'hg help config' for more info)
87
87
88 [extensions]
88 [extensions]
89 # uncomment these lines to enable some popular extensions
89 # uncomment these lines to enable some popular extensions
90 # (see 'hg help extensions' for more info)
90 # (see 'hg help extensions' for more info)
91 #
91 #
92 # blackbox =
92 # blackbox =
93 # color =
93 # color =
94 # pager =""",
94 # pager =""",
95 }
95 }
96
96
97 class ui(object):
97 class ui(object):
98 def __init__(self, src=None):
98 def __init__(self, src=None):
99 """Create a fresh new ui object if no src given
99 """Create a fresh new ui object if no src given
100
100
101 Use uimod.ui.load() to create a ui which knows global and user configs.
101 Use uimod.ui.load() to create a ui which knows global and user configs.
102 In most cases, you should use ui.copy() to create a copy of an existing
102 In most cases, you should use ui.copy() to create a copy of an existing
103 ui object.
103 ui object.
104 """
104 """
105 # _buffers: used for temporary capture of output
105 # _buffers: used for temporary capture of output
106 self._buffers = []
106 self._buffers = []
107 # 3-tuple describing how each buffer in the stack behaves.
107 # 3-tuple describing how each buffer in the stack behaves.
108 # Values are (capture stderr, capture subprocesses, apply labels).
108 # Values are (capture stderr, capture subprocesses, apply labels).
109 self._bufferstates = []
109 self._bufferstates = []
110 # When a buffer is active, defines whether we are expanding labels.
110 # When a buffer is active, defines whether we are expanding labels.
111 # This exists to prevent an extra list lookup.
111 # This exists to prevent an extra list lookup.
112 self._bufferapplylabels = None
112 self._bufferapplylabels = None
113 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
113 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
114 self._reportuntrusted = True
114 self._reportuntrusted = True
115 self._ocfg = config.config() # overlay
115 self._ocfg = config.config() # overlay
116 self._tcfg = config.config() # trusted
116 self._tcfg = config.config() # trusted
117 self._ucfg = config.config() # untrusted
117 self._ucfg = config.config() # untrusted
118 self._trustusers = set()
118 self._trustusers = set()
119 self._trustgroups = set()
119 self._trustgroups = set()
120 self.callhooks = True
120 self.callhooks = True
121 # Insecure server connections requested.
121 # Insecure server connections requested.
122 self.insecureconnections = False
122 self.insecureconnections = False
123
123
124 if src:
124 if src:
125 self.fout = src.fout
125 self.fout = src.fout
126 self.ferr = src.ferr
126 self.ferr = src.ferr
127 self.fin = src.fin
127 self.fin = src.fin
128
128
129 self._tcfg = src._tcfg.copy()
129 self._tcfg = src._tcfg.copy()
130 self._ucfg = src._ucfg.copy()
130 self._ucfg = src._ucfg.copy()
131 self._ocfg = src._ocfg.copy()
131 self._ocfg = src._ocfg.copy()
132 self._trustusers = src._trustusers.copy()
132 self._trustusers = src._trustusers.copy()
133 self._trustgroups = src._trustgroups.copy()
133 self._trustgroups = src._trustgroups.copy()
134 self.environ = src.environ
134 self.environ = src.environ
135 self.callhooks = src.callhooks
135 self.callhooks = src.callhooks
136 self.insecureconnections = src.insecureconnections
136 self.insecureconnections = src.insecureconnections
137 self.fixconfig()
137 self.fixconfig()
138
138
139 self.httppasswordmgrdb = src.httppasswordmgrdb
139 self.httppasswordmgrdb = src.httppasswordmgrdb
140 else:
140 else:
141 self.fout = util.stdout
141 self.fout = util.stdout
142 self.ferr = util.stderr
142 self.ferr = util.stderr
143 self.fin = util.stdin
143 self.fin = util.stdin
144
144
145 # shared read-only environment
145 # shared read-only environment
146 self.environ = encoding.environ
146 self.environ = encoding.environ
147
147
148 self.httppasswordmgrdb = urlreq.httppasswordmgrwithdefaultrealm()
148 self.httppasswordmgrdb = urlreq.httppasswordmgrwithdefaultrealm()
149
149
150 allowed = self.configlist('experimental', 'exportableenviron')
150 allowed = self.configlist('experimental', 'exportableenviron')
151 if '*' in allowed:
151 if '*' in allowed:
152 self._exportableenviron = self.environ
152 self._exportableenviron = self.environ
153 else:
153 else:
154 self._exportableenviron = {}
154 self._exportableenviron = {}
155 for k in allowed:
155 for k in allowed:
156 if k in self.environ:
156 if k in self.environ:
157 self._exportableenviron[k] = self.environ[k]
157 self._exportableenviron[k] = self.environ[k]
158
158
159 @classmethod
159 @classmethod
160 def load(cls):
160 def load(cls):
161 """Create a ui and load global and user configs"""
161 """Create a ui and load global and user configs"""
162 u = cls()
162 u = cls()
163 # we always trust global config files
163 # we always trust global config files
164 for f in scmutil.rcpath():
164 for f in scmutil.rcpath():
165 u.readconfig(f, trust=True)
165 u.readconfig(f, trust=True)
166 return u
166 return u
167
167
168 def copy(self):
168 def copy(self):
169 return self.__class__(self)
169 return self.__class__(self)
170
170
171 def resetstate(self):
171 def resetstate(self):
172 """Clear internal state that shouldn't persist across commands"""
172 """Clear internal state that shouldn't persist across commands"""
173 if self._progbar:
173 if self._progbar:
174 self._progbar.resetstate() # reset last-print time of progress bar
174 self._progbar.resetstate() # reset last-print time of progress bar
175 self.httppasswordmgrdb = urlreq.httppasswordmgrwithdefaultrealm()
175 self.httppasswordmgrdb = urlreq.httppasswordmgrwithdefaultrealm()
176
176
177 def formatter(self, topic, opts):
177 def formatter(self, topic, opts):
178 return formatter.formatter(self, topic, opts)
178 return formatter.formatter(self, topic, opts)
179
179
180 def _trusted(self, fp, f):
180 def _trusted(self, fp, f):
181 st = util.fstat(fp)
181 st = util.fstat(fp)
182 if util.isowner(st):
182 if util.isowner(st):
183 return True
183 return True
184
184
185 tusers, tgroups = self._trustusers, self._trustgroups
185 tusers, tgroups = self._trustusers, self._trustgroups
186 if '*' in tusers or '*' in tgroups:
186 if '*' in tusers or '*' in tgroups:
187 return True
187 return True
188
188
189 user = util.username(st.st_uid)
189 user = util.username(st.st_uid)
190 group = util.groupname(st.st_gid)
190 group = util.groupname(st.st_gid)
191 if user in tusers or group in tgroups or user == util.username():
191 if user in tusers or group in tgroups or user == util.username():
192 return True
192 return True
193
193
194 if self._reportuntrusted:
194 if self._reportuntrusted:
195 self.warn(_('not trusting file %s from untrusted '
195 self.warn(_('not trusting file %s from untrusted '
196 'user %s, group %s\n') % (f, user, group))
196 'user %s, group %s\n') % (f, user, group))
197 return False
197 return False
198
198
199 def readconfig(self, filename, root=None, trust=False,
199 def readconfig(self, filename, root=None, trust=False,
200 sections=None, remap=None):
200 sections=None, remap=None):
201 try:
201 try:
202 fp = open(filename, u'rb')
202 fp = open(filename, u'rb')
203 except IOError:
203 except IOError:
204 if not sections: # ignore unless we were looking for something
204 if not sections: # ignore unless we were looking for something
205 return
205 return
206 raise
206 raise
207
207
208 cfg = config.config()
208 cfg = config.config()
209 trusted = sections or trust or self._trusted(fp, filename)
209 trusted = sections or trust or self._trusted(fp, filename)
210
210
211 try:
211 try:
212 cfg.read(filename, fp, sections=sections, remap=remap)
212 cfg.read(filename, fp, sections=sections, remap=remap)
213 fp.close()
213 fp.close()
214 except error.ConfigError as inst:
214 except error.ConfigError as inst:
215 if trusted:
215 if trusted:
216 raise
216 raise
217 self.warn(_("ignored: %s\n") % str(inst))
217 self.warn(_("ignored: %s\n") % str(inst))
218
218
219 if self.plain():
219 if self.plain():
220 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
220 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
221 'logtemplate', 'statuscopies', 'style',
221 'logtemplate', 'statuscopies', 'style',
222 'traceback', 'verbose'):
222 'traceback', 'verbose'):
223 if k in cfg['ui']:
223 if k in cfg['ui']:
224 del cfg['ui'][k]
224 del cfg['ui'][k]
225 for k, v in cfg.items('defaults'):
225 for k, v in cfg.items('defaults'):
226 del cfg['defaults'][k]
226 del cfg['defaults'][k]
227 # Don't remove aliases from the configuration if in the exceptionlist
227 # Don't remove aliases from the configuration if in the exceptionlist
228 if self.plain('alias'):
228 if self.plain('alias'):
229 for k, v in cfg.items('alias'):
229 for k, v in cfg.items('alias'):
230 del cfg['alias'][k]
230 del cfg['alias'][k]
231 if self.plain('revsetalias'):
231 if self.plain('revsetalias'):
232 for k, v in cfg.items('revsetalias'):
232 for k, v in cfg.items('revsetalias'):
233 del cfg['revsetalias'][k]
233 del cfg['revsetalias'][k]
234 if self.plain('templatealias'):
234 if self.plain('templatealias'):
235 for k, v in cfg.items('templatealias'):
235 for k, v in cfg.items('templatealias'):
236 del cfg['templatealias'][k]
236 del cfg['templatealias'][k]
237
237
238 if trusted:
238 if trusted:
239 self._tcfg.update(cfg)
239 self._tcfg.update(cfg)
240 self._tcfg.update(self._ocfg)
240 self._tcfg.update(self._ocfg)
241 self._ucfg.update(cfg)
241 self._ucfg.update(cfg)
242 self._ucfg.update(self._ocfg)
242 self._ucfg.update(self._ocfg)
243
243
244 if root is None:
244 if root is None:
245 root = os.path.expanduser('~')
245 root = os.path.expanduser('~')
246 self.fixconfig(root=root)
246 self.fixconfig(root=root)
247
247
248 def fixconfig(self, root=None, section=None):
248 def fixconfig(self, root=None, section=None):
249 if section in (None, 'paths'):
249 if section in (None, 'paths'):
250 # expand vars and ~
250 # expand vars and ~
251 # translate paths relative to root (or home) into absolute paths
251 # translate paths relative to root (or home) into absolute paths
252 root = root or pycompat.getcwd()
252 root = root or pycompat.getcwd()
253 for c in self._tcfg, self._ucfg, self._ocfg:
253 for c in self._tcfg, self._ucfg, self._ocfg:
254 for n, p in c.items('paths'):
254 for n, p in c.items('paths'):
255 # Ignore sub-options.
255 # Ignore sub-options.
256 if ':' in n:
256 if ':' in n:
257 continue
257 continue
258 if not p:
258 if not p:
259 continue
259 continue
260 if '%%' in p:
260 if '%%' in p:
261 s = self.configsource('paths', n) or 'none'
261 s = self.configsource('paths', n) or 'none'
262 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
262 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
263 % (n, p, s))
263 % (n, p, s))
264 p = p.replace('%%', '%')
264 p = p.replace('%%', '%')
265 p = util.expandpath(p)
265 p = util.expandpath(p)
266 if not util.hasscheme(p) and not os.path.isabs(p):
266 if not util.hasscheme(p) and not os.path.isabs(p):
267 p = os.path.normpath(os.path.join(root, p))
267 p = os.path.normpath(os.path.join(root, p))
268 c.set("paths", n, p)
268 c.set("paths", n, p)
269
269
270 if section in (None, 'ui'):
270 if section in (None, 'ui'):
271 # update ui options
271 # update ui options
272 self.debugflag = self.configbool('ui', 'debug')
272 self.debugflag = self.configbool('ui', 'debug')
273 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
273 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
274 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
274 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
275 if self.verbose and self.quiet:
275 if self.verbose and self.quiet:
276 self.quiet = self.verbose = False
276 self.quiet = self.verbose = False
277 self._reportuntrusted = self.debugflag or self.configbool("ui",
277 self._reportuntrusted = self.debugflag or self.configbool("ui",
278 "report_untrusted", True)
278 "report_untrusted", True)
279 self.tracebackflag = self.configbool('ui', 'traceback', False)
279 self.tracebackflag = self.configbool('ui', 'traceback', False)
280
280
281 if section in (None, 'trusted'):
281 if section in (None, 'trusted'):
282 # update trust information
282 # update trust information
283 self._trustusers.update(self.configlist('trusted', 'users'))
283 self._trustusers.update(self.configlist('trusted', 'users'))
284 self._trustgroups.update(self.configlist('trusted', 'groups'))
284 self._trustgroups.update(self.configlist('trusted', 'groups'))
285
285
286 def backupconfig(self, section, item):
286 def backupconfig(self, section, item):
287 return (self._ocfg.backup(section, item),
287 return (self._ocfg.backup(section, item),
288 self._tcfg.backup(section, item),
288 self._tcfg.backup(section, item),
289 self._ucfg.backup(section, item),)
289 self._ucfg.backup(section, item),)
290 def restoreconfig(self, data):
290 def restoreconfig(self, data):
291 self._ocfg.restore(data[0])
291 self._ocfg.restore(data[0])
292 self._tcfg.restore(data[1])
292 self._tcfg.restore(data[1])
293 self._ucfg.restore(data[2])
293 self._ucfg.restore(data[2])
294
294
295 def setconfig(self, section, name, value, source=''):
295 def setconfig(self, section, name, value, source=''):
296 for cfg in (self._ocfg, self._tcfg, self._ucfg):
296 for cfg in (self._ocfg, self._tcfg, self._ucfg):
297 cfg.set(section, name, value, source)
297 cfg.set(section, name, value, source)
298 self.fixconfig(section=section)
298 self.fixconfig(section=section)
299
299
300 def _data(self, untrusted):
300 def _data(self, untrusted):
301 return untrusted and self._ucfg or self._tcfg
301 return untrusted and self._ucfg or self._tcfg
302
302
303 def configsource(self, section, name, untrusted=False):
303 def configsource(self, section, name, untrusted=False):
304 return self._data(untrusted).source(section, name)
304 return self._data(untrusted).source(section, name)
305
305
306 def config(self, section, name, default=None, untrusted=False):
306 def config(self, section, name, default=None, untrusted=False):
307 if isinstance(name, list):
307 if isinstance(name, list):
308 alternates = name
308 alternates = name
309 else:
309 else:
310 alternates = [name]
310 alternates = [name]
311
311
312 for n in alternates:
312 for n in alternates:
313 value = self._data(untrusted).get(section, n, None)
313 value = self._data(untrusted).get(section, n, None)
314 if value is not None:
314 if value is not None:
315 name = n
315 name = n
316 break
316 break
317 else:
317 else:
318 value = default
318 value = default
319
319
320 if self.debugflag and not untrusted and self._reportuntrusted:
320 if self.debugflag and not untrusted and self._reportuntrusted:
321 for n in alternates:
321 for n in alternates:
322 uvalue = self._ucfg.get(section, n)
322 uvalue = self._ucfg.get(section, n)
323 if uvalue is not None and uvalue != value:
323 if uvalue is not None and uvalue != value:
324 self.debug("ignoring untrusted configuration option "
324 self.debug("ignoring untrusted configuration option "
325 "%s.%s = %s\n" % (section, n, uvalue))
325 "%s.%s = %s\n" % (section, n, uvalue))
326 return value
326 return value
327
327
328 def configsuboptions(self, section, name, default=None, untrusted=False):
328 def configsuboptions(self, section, name, default=None, untrusted=False):
329 """Get a config option and all sub-options.
329 """Get a config option and all sub-options.
330
330
331 Some config options have sub-options that are declared with the
331 Some config options have sub-options that are declared with the
332 format "key:opt = value". This method is used to return the main
332 format "key:opt = value". This method is used to return the main
333 option and all its declared sub-options.
333 option and all its declared sub-options.
334
334
335 Returns a 2-tuple of ``(option, sub-options)``, where `sub-options``
335 Returns a 2-tuple of ``(option, sub-options)``, where `sub-options``
336 is a dict of defined sub-options where keys and values are strings.
336 is a dict of defined sub-options where keys and values are strings.
337 """
337 """
338 data = self._data(untrusted)
338 data = self._data(untrusted)
339 main = data.get(section, name, default)
339 main = data.get(section, name, default)
340 if self.debugflag and not untrusted and self._reportuntrusted:
340 if self.debugflag and not untrusted and self._reportuntrusted:
341 uvalue = self._ucfg.get(section, name)
341 uvalue = self._ucfg.get(section, name)
342 if uvalue is not None and uvalue != main:
342 if uvalue is not None and uvalue != main:
343 self.debug('ignoring untrusted configuration option '
343 self.debug('ignoring untrusted configuration option '
344 '%s.%s = %s\n' % (section, name, uvalue))
344 '%s.%s = %s\n' % (section, name, uvalue))
345
345
346 sub = {}
346 sub = {}
347 prefix = '%s:' % name
347 prefix = '%s:' % name
348 for k, v in data.items(section):
348 for k, v in data.items(section):
349 if k.startswith(prefix):
349 if k.startswith(prefix):
350 sub[k[len(prefix):]] = v
350 sub[k[len(prefix):]] = v
351
351
352 if self.debugflag and not untrusted and self._reportuntrusted:
352 if self.debugflag and not untrusted and self._reportuntrusted:
353 for k, v in sub.items():
353 for k, v in sub.items():
354 uvalue = self._ucfg.get(section, '%s:%s' % (name, k))
354 uvalue = self._ucfg.get(section, '%s:%s' % (name, k))
355 if uvalue is not None and uvalue != v:
355 if uvalue is not None and uvalue != v:
356 self.debug('ignoring untrusted configuration option '
356 self.debug('ignoring untrusted configuration option '
357 '%s:%s.%s = %s\n' % (section, name, k, uvalue))
357 '%s:%s.%s = %s\n' % (section, name, k, uvalue))
358
358
359 return main, sub
359 return main, sub
360
360
361 def configpath(self, section, name, default=None, untrusted=False):
361 def configpath(self, section, name, default=None, untrusted=False):
362 'get a path config item, expanded relative to repo root or config file'
362 'get a path config item, expanded relative to repo root or config file'
363 v = self.config(section, name, default, untrusted)
363 v = self.config(section, name, default, untrusted)
364 if v is None:
364 if v is None:
365 return None
365 return None
366 if not os.path.isabs(v) or "://" not in v:
366 if not os.path.isabs(v) or "://" not in v:
367 src = self.configsource(section, name, untrusted)
367 src = self.configsource(section, name, untrusted)
368 if ':' in src:
368 if ':' in src:
369 base = os.path.dirname(src.rsplit(':')[0])
369 base = os.path.dirname(src.rsplit(':')[0])
370 v = os.path.join(base, os.path.expanduser(v))
370 v = os.path.join(base, os.path.expanduser(v))
371 return v
371 return v
372
372
373 def configbool(self, section, name, default=False, untrusted=False):
373 def configbool(self, section, name, default=False, untrusted=False):
374 """parse a configuration element as a boolean
374 """parse a configuration element as a boolean
375
375
376 >>> u = ui(); s = 'foo'
376 >>> u = ui(); s = 'foo'
377 >>> u.setconfig(s, 'true', 'yes')
377 >>> u.setconfig(s, 'true', 'yes')
378 >>> u.configbool(s, 'true')
378 >>> u.configbool(s, 'true')
379 True
379 True
380 >>> u.setconfig(s, 'false', 'no')
380 >>> u.setconfig(s, 'false', 'no')
381 >>> u.configbool(s, 'false')
381 >>> u.configbool(s, 'false')
382 False
382 False
383 >>> u.configbool(s, 'unknown')
383 >>> u.configbool(s, 'unknown')
384 False
384 False
385 >>> u.configbool(s, 'unknown', True)
385 >>> u.configbool(s, 'unknown', True)
386 True
386 True
387 >>> u.setconfig(s, 'invalid', 'somevalue')
387 >>> u.setconfig(s, 'invalid', 'somevalue')
388 >>> u.configbool(s, 'invalid')
388 >>> u.configbool(s, 'invalid')
389 Traceback (most recent call last):
389 Traceback (most recent call last):
390 ...
390 ...
391 ConfigError: foo.invalid is not a boolean ('somevalue')
391 ConfigError: foo.invalid is not a boolean ('somevalue')
392 """
392 """
393
393
394 v = self.config(section, name, None, untrusted)
394 v = self.config(section, name, None, untrusted)
395 if v is None:
395 if v is None:
396 return default
396 return default
397 if isinstance(v, bool):
397 if isinstance(v, bool):
398 return v
398 return v
399 b = util.parsebool(v)
399 b = util.parsebool(v)
400 if b is None:
400 if b is None:
401 raise error.ConfigError(_("%s.%s is not a boolean ('%s')")
401 raise error.ConfigError(_("%s.%s is not a boolean ('%s')")
402 % (section, name, v))
402 % (section, name, v))
403 return b
403 return b
404
404
405 def configint(self, section, name, default=None, untrusted=False):
405 def configint(self, section, name, default=None, untrusted=False):
406 """parse a configuration element as an integer
406 """parse a configuration element as an integer
407
407
408 >>> u = ui(); s = 'foo'
408 >>> u = ui(); s = 'foo'
409 >>> u.setconfig(s, 'int1', '42')
409 >>> u.setconfig(s, 'int1', '42')
410 >>> u.configint(s, 'int1')
410 >>> u.configint(s, 'int1')
411 42
411 42
412 >>> u.setconfig(s, 'int2', '-42')
412 >>> u.setconfig(s, 'int2', '-42')
413 >>> u.configint(s, 'int2')
413 >>> u.configint(s, 'int2')
414 -42
414 -42
415 >>> u.configint(s, 'unknown', 7)
415 >>> u.configint(s, 'unknown', 7)
416 7
416 7
417 >>> u.setconfig(s, 'invalid', 'somevalue')
417 >>> u.setconfig(s, 'invalid', 'somevalue')
418 >>> u.configint(s, 'invalid')
418 >>> u.configint(s, 'invalid')
419 Traceback (most recent call last):
419 Traceback (most recent call last):
420 ...
420 ...
421 ConfigError: foo.invalid is not an integer ('somevalue')
421 ConfigError: foo.invalid is not an integer ('somevalue')
422 """
422 """
423
423
424 v = self.config(section, name, None, untrusted)
424 v = self.config(section, name, None, untrusted)
425 if v is None:
425 if v is None:
426 return default
426 return default
427 try:
427 try:
428 return int(v)
428 return int(v)
429 except ValueError:
429 except ValueError:
430 raise error.ConfigError(_("%s.%s is not an integer ('%s')")
430 raise error.ConfigError(_("%s.%s is not an integer ('%s')")
431 % (section, name, v))
431 % (section, name, v))
432
432
433 def configbytes(self, section, name, default=0, untrusted=False):
433 def configbytes(self, section, name, default=0, untrusted=False):
434 """parse a configuration element as a quantity in bytes
434 """parse a configuration element as a quantity in bytes
435
435
436 Units can be specified as b (bytes), k or kb (kilobytes), m or
436 Units can be specified as b (bytes), k or kb (kilobytes), m or
437 mb (megabytes), g or gb (gigabytes).
437 mb (megabytes), g or gb (gigabytes).
438
438
439 >>> u = ui(); s = 'foo'
439 >>> u = ui(); s = 'foo'
440 >>> u.setconfig(s, 'val1', '42')
440 >>> u.setconfig(s, 'val1', '42')
441 >>> u.configbytes(s, 'val1')
441 >>> u.configbytes(s, 'val1')
442 42
442 42
443 >>> u.setconfig(s, 'val2', '42.5 kb')
443 >>> u.setconfig(s, 'val2', '42.5 kb')
444 >>> u.configbytes(s, 'val2')
444 >>> u.configbytes(s, 'val2')
445 43520
445 43520
446 >>> u.configbytes(s, 'unknown', '7 MB')
446 >>> u.configbytes(s, 'unknown', '7 MB')
447 7340032
447 7340032
448 >>> u.setconfig(s, 'invalid', 'somevalue')
448 >>> u.setconfig(s, 'invalid', 'somevalue')
449 >>> u.configbytes(s, 'invalid')
449 >>> u.configbytes(s, 'invalid')
450 Traceback (most recent call last):
450 Traceback (most recent call last):
451 ...
451 ...
452 ConfigError: foo.invalid is not a byte quantity ('somevalue')
452 ConfigError: foo.invalid is not a byte quantity ('somevalue')
453 """
453 """
454
454
455 value = self.config(section, name)
455 value = self.config(section, name)
456 if value is None:
456 if value is None:
457 if not isinstance(default, str):
457 if not isinstance(default, str):
458 return default
458 return default
459 value = default
459 value = default
460 try:
460 try:
461 return util.sizetoint(value)
461 return util.sizetoint(value)
462 except error.ParseError:
462 except error.ParseError:
463 raise error.ConfigError(_("%s.%s is not a byte quantity ('%s')")
463 raise error.ConfigError(_("%s.%s is not a byte quantity ('%s')")
464 % (section, name, value))
464 % (section, name, value))
465
465
466 def configlist(self, section, name, default=None, untrusted=False):
466 def configlist(self, section, name, default=None, untrusted=False):
467 """parse a configuration element as a list of comma/space separated
467 """parse a configuration element as a list of comma/space separated
468 strings
468 strings
469
469
470 >>> u = ui(); s = 'foo'
470 >>> u = ui(); s = 'foo'
471 >>> u.setconfig(s, 'list1', 'this,is "a small" ,test')
471 >>> u.setconfig(s, 'list1', 'this,is "a small" ,test')
472 >>> u.configlist(s, 'list1')
472 >>> u.configlist(s, 'list1')
473 ['this', 'is', 'a small', 'test']
473 ['this', 'is', 'a small', 'test']
474 """
474 """
475
475
476 def _parse_plain(parts, s, offset):
476 def _parse_plain(parts, s, offset):
477 whitespace = False
477 whitespace = False
478 while offset < len(s) and (s[offset].isspace() or s[offset] == ','):
478 while offset < len(s) and (s[offset].isspace() or s[offset] == ','):
479 whitespace = True
479 whitespace = True
480 offset += 1
480 offset += 1
481 if offset >= len(s):
481 if offset >= len(s):
482 return None, parts, offset
482 return None, parts, offset
483 if whitespace:
483 if whitespace:
484 parts.append('')
484 parts.append('')
485 if s[offset] == '"' and not parts[-1]:
485 if s[offset] == '"' and not parts[-1]:
486 return _parse_quote, parts, offset + 1
486 return _parse_quote, parts, offset + 1
487 elif s[offset] == '"' and parts[-1][-1] == '\\':
487 elif s[offset] == '"' and parts[-1][-1] == '\\':
488 parts[-1] = parts[-1][:-1] + s[offset]
488 parts[-1] = parts[-1][:-1] + s[offset]
489 return _parse_plain, parts, offset + 1
489 return _parse_plain, parts, offset + 1
490 parts[-1] += s[offset]
490 parts[-1] += s[offset]
491 return _parse_plain, parts, offset + 1
491 return _parse_plain, parts, offset + 1
492
492
493 def _parse_quote(parts, s, offset):
493 def _parse_quote(parts, s, offset):
494 if offset < len(s) and s[offset] == '"': # ""
494 if offset < len(s) and s[offset] == '"': # ""
495 parts.append('')
495 parts.append('')
496 offset += 1
496 offset += 1
497 while offset < len(s) and (s[offset].isspace() or
497 while offset < len(s) and (s[offset].isspace() or
498 s[offset] == ','):
498 s[offset] == ','):
499 offset += 1
499 offset += 1
500 return _parse_plain, parts, offset
500 return _parse_plain, parts, offset
501
501
502 while offset < len(s) and s[offset] != '"':
502 while offset < len(s) and s[offset] != '"':
503 if (s[offset] == '\\' and offset + 1 < len(s)
503 if (s[offset] == '\\' and offset + 1 < len(s)
504 and s[offset + 1] == '"'):
504 and s[offset + 1] == '"'):
505 offset += 1
505 offset += 1
506 parts[-1] += '"'
506 parts[-1] += '"'
507 else:
507 else:
508 parts[-1] += s[offset]
508 parts[-1] += s[offset]
509 offset += 1
509 offset += 1
510
510
511 if offset >= len(s):
511 if offset >= len(s):
512 real_parts = _configlist(parts[-1])
512 real_parts = _configlist(parts[-1])
513 if not real_parts:
513 if not real_parts:
514 parts[-1] = '"'
514 parts[-1] = '"'
515 else:
515 else:
516 real_parts[0] = '"' + real_parts[0]
516 real_parts[0] = '"' + real_parts[0]
517 parts = parts[:-1]
517 parts = parts[:-1]
518 parts.extend(real_parts)
518 parts.extend(real_parts)
519 return None, parts, offset
519 return None, parts, offset
520
520
521 offset += 1
521 offset += 1
522 while offset < len(s) and s[offset] in [' ', ',']:
522 while offset < len(s) and s[offset] in [' ', ',']:
523 offset += 1
523 offset += 1
524
524
525 if offset < len(s):
525 if offset < len(s):
526 if offset + 1 == len(s) and s[offset] == '"':
526 if offset + 1 == len(s) and s[offset] == '"':
527 parts[-1] += '"'
527 parts[-1] += '"'
528 offset += 1
528 offset += 1
529 else:
529 else:
530 parts.append('')
530 parts.append('')
531 else:
531 else:
532 return None, parts, offset
532 return None, parts, offset
533
533
534 return _parse_plain, parts, offset
534 return _parse_plain, parts, offset
535
535
536 def _configlist(s):
536 def _configlist(s):
537 s = s.rstrip(' ,')
537 s = s.rstrip(' ,')
538 if not s:
538 if not s:
539 return []
539 return []
540 parser, parts, offset = _parse_plain, [''], 0
540 parser, parts, offset = _parse_plain, [''], 0
541 while parser:
541 while parser:
542 parser, parts, offset = parser(parts, s, offset)
542 parser, parts, offset = parser(parts, s, offset)
543 return parts
543 return parts
544
544
545 result = self.config(section, name, untrusted=untrusted)
545 result = self.config(section, name, untrusted=untrusted)
546 if result is None:
546 if result is None:
547 result = default or []
547 result = default or []
548 if isinstance(result, bytes):
548 if isinstance(result, bytes):
549 result = _configlist(result.lstrip(' ,\n'))
549 result = _configlist(result.lstrip(' ,\n'))
550 if result is None:
550 if result is None:
551 result = default or []
551 result = default or []
552 return result
552 return result
553
553
554 def hasconfig(self, section, name, untrusted=False):
554 def hasconfig(self, section, name, untrusted=False):
555 return self._data(untrusted).hasitem(section, name)
555 return self._data(untrusted).hasitem(section, name)
556
556
557 def has_section(self, section, untrusted=False):
557 def has_section(self, section, untrusted=False):
558 '''tell whether section exists in config.'''
558 '''tell whether section exists in config.'''
559 return section in self._data(untrusted)
559 return section in self._data(untrusted)
560
560
561 def configitems(self, section, untrusted=False, ignoresub=False):
561 def configitems(self, section, untrusted=False, ignoresub=False):
562 items = self._data(untrusted).items(section)
562 items = self._data(untrusted).items(section)
563 if ignoresub:
563 if ignoresub:
564 newitems = {}
564 newitems = {}
565 for k, v in items:
565 for k, v in items:
566 if ':' not in k:
566 if ':' not in k:
567 newitems[k] = v
567 newitems[k] = v
568 items = newitems.items()
568 items = newitems.items()
569 if self.debugflag and not untrusted and self._reportuntrusted:
569 if self.debugflag and not untrusted and self._reportuntrusted:
570 for k, v in self._ucfg.items(section):
570 for k, v in self._ucfg.items(section):
571 if self._tcfg.get(section, k) != v:
571 if self._tcfg.get(section, k) != v:
572 self.debug("ignoring untrusted configuration option "
572 self.debug("ignoring untrusted configuration option "
573 "%s.%s = %s\n" % (section, k, v))
573 "%s.%s = %s\n" % (section, k, v))
574 return items
574 return items
575
575
576 def walkconfig(self, untrusted=False):
576 def walkconfig(self, untrusted=False):
577 cfg = self._data(untrusted)
577 cfg = self._data(untrusted)
578 for section in cfg.sections():
578 for section in cfg.sections():
579 for name, value in self.configitems(section, untrusted):
579 for name, value in self.configitems(section, untrusted):
580 yield section, name, value
580 yield section, name, value
581
581
582 def plain(self, feature=None):
582 def plain(self, feature=None):
583 '''is plain mode active?
583 '''is plain mode active?
584
584
585 Plain mode means that all configuration variables which affect
585 Plain mode means that all configuration variables which affect
586 the behavior and output of Mercurial should be
586 the behavior and output of Mercurial should be
587 ignored. Additionally, the output should be stable,
587 ignored. Additionally, the output should be stable,
588 reproducible and suitable for use in scripts or applications.
588 reproducible and suitable for use in scripts or applications.
589
589
590 The only way to trigger plain mode is by setting either the
590 The only way to trigger plain mode is by setting either the
591 `HGPLAIN' or `HGPLAINEXCEPT' environment variables.
591 `HGPLAIN' or `HGPLAINEXCEPT' environment variables.
592
592
593 The return value can either be
593 The return value can either be
594 - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT
594 - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT
595 - True otherwise
595 - True otherwise
596 '''
596 '''
597 if ('HGPLAIN' not in encoding.environ and
597 if ('HGPLAIN' not in encoding.environ and
598 'HGPLAINEXCEPT' not in encoding.environ):
598 'HGPLAINEXCEPT' not in encoding.environ):
599 return False
599 return False
600 exceptions = encoding.environ.get('HGPLAINEXCEPT',
600 exceptions = encoding.environ.get('HGPLAINEXCEPT',
601 '').strip().split(',')
601 '').strip().split(',')
602 if feature and exceptions:
602 if feature and exceptions:
603 return feature not in exceptions
603 return feature not in exceptions
604 return True
604 return True
605
605
606 def username(self):
606 def username(self):
607 """Return default username to be used in commits.
607 """Return default username to be used in commits.
608
608
609 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
609 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
610 and stop searching if one of these is set.
610 and stop searching if one of these is set.
611 If not found and ui.askusername is True, ask the user, else use
611 If not found and ui.askusername is True, ask the user, else use
612 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
612 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
613 """
613 """
614 user = encoding.environ.get("HGUSER")
614 user = encoding.environ.get("HGUSER")
615 if user is None:
615 if user is None:
616 user = self.config("ui", ["username", "user"])
616 user = self.config("ui", ["username", "user"])
617 if user is not None:
617 if user is not None:
618 user = os.path.expandvars(user)
618 user = os.path.expandvars(user)
619 if user is None:
619 if user is None:
620 user = encoding.environ.get("EMAIL")
620 user = encoding.environ.get("EMAIL")
621 if user is None and self.configbool("ui", "askusername"):
621 if user is None and self.configbool("ui", "askusername"):
622 user = self.prompt(_("enter a commit username:"), default=None)
622 user = self.prompt(_("enter a commit username:"), default=None)
623 if user is None and not self.interactive():
623 if user is None and not self.interactive():
624 try:
624 try:
625 user = '%s@%s' % (util.getuser(), socket.getfqdn())
625 user = '%s@%s' % (util.getuser(), socket.getfqdn())
626 self.warn(_("no username found, using '%s' instead\n") % user)
626 self.warn(_("no username found, using '%s' instead\n") % user)
627 except KeyError:
627 except KeyError:
628 pass
628 pass
629 if not user:
629 if not user:
630 raise error.Abort(_('no username supplied'),
630 raise error.Abort(_('no username supplied'),
631 hint=_("use 'hg config --edit' "
631 hint=_("use 'hg config --edit' "
632 'to set your username'))
632 'to set your username'))
633 if "\n" in user:
633 if "\n" in user:
634 raise error.Abort(_("username %s contains a newline\n")
634 raise error.Abort(_("username %s contains a newline\n")
635 % repr(user))
635 % repr(user))
636 return user
636 return user
637
637
638 def shortuser(self, user):
638 def shortuser(self, user):
639 """Return a short representation of a user name or email address."""
639 """Return a short representation of a user name or email address."""
640 if not self.verbose:
640 if not self.verbose:
641 user = util.shortuser(user)
641 user = util.shortuser(user)
642 return user
642 return user
643
643
644 def expandpath(self, loc, default=None):
644 def expandpath(self, loc, default=None):
645 """Return repository location relative to cwd or from [paths]"""
645 """Return repository location relative to cwd or from [paths]"""
646 try:
646 try:
647 p = self.paths.getpath(loc)
647 p = self.paths.getpath(loc)
648 if p:
648 if p:
649 return p.rawloc
649 return p.rawloc
650 except error.RepoError:
650 except error.RepoError:
651 pass
651 pass
652
652
653 if default:
653 if default:
654 try:
654 try:
655 p = self.paths.getpath(default)
655 p = self.paths.getpath(default)
656 if p:
656 if p:
657 return p.rawloc
657 return p.rawloc
658 except error.RepoError:
658 except error.RepoError:
659 pass
659 pass
660
660
661 return loc
661 return loc
662
662
663 @util.propertycache
663 @util.propertycache
664 def paths(self):
664 def paths(self):
665 return paths(self)
665 return paths(self)
666
666
667 def pushbuffer(self, error=False, subproc=False, labeled=False):
667 def pushbuffer(self, error=False, subproc=False, labeled=False):
668 """install a buffer to capture standard output of the ui object
668 """install a buffer to capture standard output of the ui object
669
669
670 If error is True, the error output will be captured too.
670 If error is True, the error output will be captured too.
671
671
672 If subproc is True, output from subprocesses (typically hooks) will be
672 If subproc is True, output from subprocesses (typically hooks) will be
673 captured too.
673 captured too.
674
674
675 If labeled is True, any labels associated with buffered
675 If labeled is True, any labels associated with buffered
676 output will be handled. By default, this has no effect
676 output will be handled. By default, this has no effect
677 on the output returned, but extensions and GUI tools may
677 on the output returned, but extensions and GUI tools may
678 handle this argument and returned styled output. If output
678 handle this argument and returned styled output. If output
679 is being buffered so it can be captured and parsed or
679 is being buffered so it can be captured and parsed or
680 processed, labeled should not be set to True.
680 processed, labeled should not be set to True.
681 """
681 """
682 self._buffers.append([])
682 self._buffers.append([])
683 self._bufferstates.append((error, subproc, labeled))
683 self._bufferstates.append((error, subproc, labeled))
684 self._bufferapplylabels = labeled
684 self._bufferapplylabels = labeled
685
685
686 def popbuffer(self):
686 def popbuffer(self):
687 '''pop the last buffer and return the buffered output'''
687 '''pop the last buffer and return the buffered output'''
688 self._bufferstates.pop()
688 self._bufferstates.pop()
689 if self._bufferstates:
689 if self._bufferstates:
690 self._bufferapplylabels = self._bufferstates[-1][2]
690 self._bufferapplylabels = self._bufferstates[-1][2]
691 else:
691 else:
692 self._bufferapplylabels = None
692 self._bufferapplylabels = None
693
693
694 return "".join(self._buffers.pop())
694 return "".join(self._buffers.pop())
695
695
696 def write(self, *args, **opts):
696 def write(self, *args, **opts):
697 '''write args to output
697 '''write args to output
698
698
699 By default, this method simply writes to the buffer or stdout,
699 By default, this method simply writes to the buffer or stdout,
700 but extensions or GUI tools may override this method,
700 but extensions or GUI tools may override this method,
701 write_err(), popbuffer(), and label() to style output from
701 write_err(), popbuffer(), and label() to style output from
702 various parts of hg.
702 various parts of hg.
703
703
704 An optional keyword argument, "label", can be passed in.
704 An optional keyword argument, "label", can be passed in.
705 This should be a string containing label names separated by
705 This should be a string containing label names separated by
706 space. Label names take the form of "topic.type". For example,
706 space. Label names take the form of "topic.type". For example,
707 ui.debug() issues a label of "ui.debug".
707 ui.debug() issues a label of "ui.debug".
708
708
709 When labeling output for a specific command, a label of
709 When labeling output for a specific command, a label of
710 "cmdname.type" is recommended. For example, status issues
710 "cmdname.type" is recommended. For example, status issues
711 a label of "status.modified" for modified files.
711 a label of "status.modified" for modified files.
712 '''
712 '''
713 if self._buffers and not opts.get('prompt', False):
713 if self._buffers and not opts.get('prompt', False):
714 self._buffers[-1].extend(a for a in args)
714 self._buffers[-1].extend(a for a in args)
715 else:
715 else:
716 self._progclear()
716 self._progclear()
717 for a in args:
717 for a in args:
718 self.fout.write(a)
718 self.fout.write(a)
719
719
720 def write_err(self, *args, **opts):
720 def write_err(self, *args, **opts):
721 self._progclear()
721 self._progclear()
722 try:
722 try:
723 if self._bufferstates and self._bufferstates[-1][0]:
723 if self._bufferstates and self._bufferstates[-1][0]:
724 return self.write(*args, **opts)
724 return self.write(*args, **opts)
725 if not getattr(self.fout, 'closed', False):
725 if not getattr(self.fout, 'closed', False):
726 self.fout.flush()
726 self.fout.flush()
727 for a in args:
727 for a in args:
728 self.ferr.write(a)
728 self.ferr.write(a)
729 # stderr may be buffered under win32 when redirected to files,
729 # stderr may be buffered under win32 when redirected to files,
730 # including stdout.
730 # including stdout.
731 if not getattr(self.ferr, 'closed', False):
731 if not getattr(self.ferr, 'closed', False):
732 self.ferr.flush()
732 self.ferr.flush()
733 except IOError as inst:
733 except IOError as inst:
734 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
734 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
735 raise
735 raise
736
736
737 def flush(self):
737 def flush(self):
738 try: self.fout.flush()
738 try: self.fout.flush()
739 except (IOError, ValueError): pass
739 except (IOError, ValueError): pass
740 try: self.ferr.flush()
740 try: self.ferr.flush()
741 except (IOError, ValueError): pass
741 except (IOError, ValueError): pass
742
742
743 def _isatty(self, fh):
743 def _isatty(self, fh):
744 if self.configbool('ui', 'nontty', False):
744 if self.configbool('ui', 'nontty', False):
745 return False
745 return False
746 return util.isatty(fh)
746 return util.isatty(fh)
747
747
748 def interface(self, feature):
748 def interface(self, feature):
749 """what interface to use for interactive console features?
749 """what interface to use for interactive console features?
750
750
751 The interface is controlled by the value of `ui.interface` but also by
751 The interface is controlled by the value of `ui.interface` but also by
752 the value of feature-specific configuration. For example:
752 the value of feature-specific configuration. For example:
753
753
754 ui.interface.histedit = text
754 ui.interface.histedit = text
755 ui.interface.chunkselector = curses
755 ui.interface.chunkselector = curses
756
756
757 Here the features are "histedit" and "chunkselector".
757 Here the features are "histedit" and "chunkselector".
758
758
759 The configuration above means that the default interfaces for commands
759 The configuration above means that the default interfaces for commands
760 is curses, the interface for histedit is text and the interface for
760 is curses, the interface for histedit is text and the interface for
761 selecting chunk is crecord (the best curses interface available).
761 selecting chunk is crecord (the best curses interface available).
762
762
763 Consider the following example:
763 Consider the following example:
764 ui.interface = curses
764 ui.interface = curses
765 ui.interface.histedit = text
765 ui.interface.histedit = text
766
766
767 Then histedit will use the text interface and chunkselector will use
767 Then histedit will use the text interface and chunkselector will use
768 the default curses interface (crecord at the moment).
768 the default curses interface (crecord at the moment).
769 """
769 """
770 alldefaults = frozenset(["text", "curses"])
770 alldefaults = frozenset(["text", "curses"])
771
771
772 featureinterfaces = {
772 featureinterfaces = {
773 "chunkselector": [
773 "chunkselector": [
774 "text",
774 "text",
775 "curses",
775 "curses",
776 ]
776 ]
777 }
777 }
778
778
779 # Feature-specific interface
779 # Feature-specific interface
780 if feature not in featureinterfaces.keys():
780 if feature not in featureinterfaces.keys():
781 # Programming error, not user error
781 # Programming error, not user error
782 raise ValueError("Unknown feature requested %s" % feature)
782 raise ValueError("Unknown feature requested %s" % feature)
783
783
784 availableinterfaces = frozenset(featureinterfaces[feature])
784 availableinterfaces = frozenset(featureinterfaces[feature])
785 if alldefaults > availableinterfaces:
785 if alldefaults > availableinterfaces:
786 # Programming error, not user error. We need a use case to
786 # Programming error, not user error. We need a use case to
787 # define the right thing to do here.
787 # define the right thing to do here.
788 raise ValueError(
788 raise ValueError(
789 "Feature %s does not handle all default interfaces" %
789 "Feature %s does not handle all default interfaces" %
790 feature)
790 feature)
791
791
792 if self.plain():
792 if self.plain():
793 return "text"
793 return "text"
794
794
795 # Default interface for all the features
795 # Default interface for all the features
796 defaultinterface = "text"
796 defaultinterface = "text"
797 i = self.config("ui", "interface", None)
797 i = self.config("ui", "interface", None)
798 if i in alldefaults:
798 if i in alldefaults:
799 defaultinterface = i
799 defaultinterface = i
800
800
801 choseninterface = defaultinterface
801 choseninterface = defaultinterface
802 f = self.config("ui", "interface.%s" % feature, None)
802 f = self.config("ui", "interface.%s" % feature, None)
803 if f in availableinterfaces:
803 if f in availableinterfaces:
804 choseninterface = f
804 choseninterface = f
805
805
806 if i is not None and defaultinterface != i:
806 if i is not None and defaultinterface != i:
807 if f is not None:
807 if f is not None:
808 self.warn(_("invalid value for ui.interface: %s\n") %
808 self.warn(_("invalid value for ui.interface: %s\n") %
809 (i,))
809 (i,))
810 else:
810 else:
811 self.warn(_("invalid value for ui.interface: %s (using %s)\n") %
811 self.warn(_("invalid value for ui.interface: %s (using %s)\n") %
812 (i, choseninterface))
812 (i, choseninterface))
813 if f is not None and choseninterface != f:
813 if f is not None and choseninterface != f:
814 self.warn(_("invalid value for ui.interface.%s: %s (using %s)\n") %
814 self.warn(_("invalid value for ui.interface.%s: %s (using %s)\n") %
815 (feature, f, choseninterface))
815 (feature, f, choseninterface))
816
816
817 return choseninterface
817 return choseninterface
818
818
819 def interactive(self):
819 def interactive(self):
820 '''is interactive input allowed?
820 '''is interactive input allowed?
821
821
822 An interactive session is a session where input can be reasonably read
822 An interactive session is a session where input can be reasonably read
823 from `sys.stdin'. If this function returns false, any attempt to read
823 from `sys.stdin'. If this function returns false, any attempt to read
824 from stdin should fail with an error, unless a sensible default has been
824 from stdin should fail with an error, unless a sensible default has been
825 specified.
825 specified.
826
826
827 Interactiveness is triggered by the value of the `ui.interactive'
827 Interactiveness is triggered by the value of the `ui.interactive'
828 configuration variable or - if it is unset - when `sys.stdin' points
828 configuration variable or - if it is unset - when `sys.stdin' points
829 to a terminal device.
829 to a terminal device.
830
830
831 This function refers to input only; for output, see `ui.formatted()'.
831 This function refers to input only; for output, see `ui.formatted()'.
832 '''
832 '''
833 i = self.configbool("ui", "interactive", None)
833 i = self.configbool("ui", "interactive", None)
834 if i is None:
834 if i is None:
835 # some environments replace stdin without implementing isatty
835 # some environments replace stdin without implementing isatty
836 # usually those are non-interactive
836 # usually those are non-interactive
837 return self._isatty(self.fin)
837 return self._isatty(self.fin)
838
838
839 return i
839 return i
840
840
841 def termwidth(self):
841 def termwidth(self):
842 '''how wide is the terminal in columns?
842 '''how wide is the terminal in columns?
843 '''
843 '''
844 if 'COLUMNS' in encoding.environ:
844 if 'COLUMNS' in encoding.environ:
845 try:
845 try:
846 return int(encoding.environ['COLUMNS'])
846 return int(encoding.environ['COLUMNS'])
847 except ValueError:
847 except ValueError:
848 pass
848 pass
849 return scmutil.termsize(self)[0]
849 return scmutil.termsize(self)[0]
850
850
851 def formatted(self):
851 def formatted(self):
852 '''should formatted output be used?
852 '''should formatted output be used?
853
853
854 It is often desirable to format the output to suite the output medium.
854 It is often desirable to format the output to suite the output medium.
855 Examples of this are truncating long lines or colorizing messages.
855 Examples of this are truncating long lines or colorizing messages.
856 However, this is not often not desirable when piping output into other
856 However, this is not often not desirable when piping output into other
857 utilities, e.g. `grep'.
857 utilities, e.g. `grep'.
858
858
859 Formatted output is triggered by the value of the `ui.formatted'
859 Formatted output is triggered by the value of the `ui.formatted'
860 configuration variable or - if it is unset - when `sys.stdout' points
860 configuration variable or - if it is unset - when `sys.stdout' points
861 to a terminal device. Please note that `ui.formatted' should be
861 to a terminal device. Please note that `ui.formatted' should be
862 considered an implementation detail; it is not intended for use outside
862 considered an implementation detail; it is not intended for use outside
863 Mercurial or its extensions.
863 Mercurial or its extensions.
864
864
865 This function refers to output only; for input, see `ui.interactive()'.
865 This function refers to output only; for input, see `ui.interactive()'.
866 This function always returns false when in plain mode, see `ui.plain()'.
866 This function always returns false when in plain mode, see `ui.plain()'.
867 '''
867 '''
868 if self.plain():
868 if self.plain():
869 return False
869 return False
870
870
871 i = self.configbool("ui", "formatted", None)
871 i = self.configbool("ui", "formatted", None)
872 if i is None:
872 if i is None:
873 # some environments replace stdout without implementing isatty
873 # some environments replace stdout without implementing isatty
874 # usually those are non-interactive
874 # usually those are non-interactive
875 return self._isatty(self.fout)
875 return self._isatty(self.fout)
876
876
877 return i
877 return i
878
878
879 def _readline(self, prompt=''):
879 def _readline(self, prompt=''):
880 if self._isatty(self.fin):
880 if self._isatty(self.fin):
881 try:
881 try:
882 # magically add command line editing support, where
882 # magically add command line editing support, where
883 # available
883 # available
884 import readline
884 import readline
885 # force demandimport to really load the module
885 # force demandimport to really load the module
886 readline.read_history_file
886 readline.read_history_file
887 # windows sometimes raises something other than ImportError
887 # windows sometimes raises something other than ImportError
888 except Exception:
888 except Exception:
889 pass
889 pass
890
890
891 # call write() so output goes through subclassed implementation
891 # call write() so output goes through subclassed implementation
892 # e.g. color extension on Windows
892 # e.g. color extension on Windows
893 self.write(prompt, prompt=True)
893 self.write(prompt, prompt=True)
894
894
895 # instead of trying to emulate raw_input, swap (self.fin,
895 # instead of trying to emulate raw_input, swap (self.fin,
896 # self.fout) with (sys.stdin, sys.stdout)
896 # self.fout) with (sys.stdin, sys.stdout)
897 oldin = sys.stdin
897 oldin = sys.stdin
898 oldout = sys.stdout
898 oldout = sys.stdout
899 sys.stdin = self.fin
899 sys.stdin = self.fin
900 sys.stdout = self.fout
900 sys.stdout = self.fout
901 # prompt ' ' must exist; otherwise readline may delete entire line
901 # prompt ' ' must exist; otherwise readline may delete entire line
902 # - http://bugs.python.org/issue12833
902 # - http://bugs.python.org/issue12833
903 line = raw_input(' ')
903 line = raw_input(' ')
904 sys.stdin = oldin
904 sys.stdin = oldin
905 sys.stdout = oldout
905 sys.stdout = oldout
906
906
907 # When stdin is in binary mode on Windows, it can cause
907 # When stdin is in binary mode on Windows, it can cause
908 # raw_input() to emit an extra trailing carriage return
908 # raw_input() to emit an extra trailing carriage return
909 if os.linesep == '\r\n' and line and line[-1] == '\r':
909 if os.linesep == '\r\n' and line and line[-1] == '\r':
910 line = line[:-1]
910 line = line[:-1]
911 return line
911 return line
912
912
913 def prompt(self, msg, default="y"):
913 def prompt(self, msg, default="y"):
914 """Prompt user with msg, read response.
914 """Prompt user with msg, read response.
915 If ui is not interactive, the default is returned.
915 If ui is not interactive, the default is returned.
916 """
916 """
917 if not self.interactive():
917 if not self.interactive():
918 self.write(msg, ' ', default or '', "\n")
918 self.write(msg, ' ', default or '', "\n")
919 return default
919 return default
920 try:
920 try:
921 r = self._readline(self.label(msg, 'ui.prompt'))
921 r = self._readline(self.label(msg, 'ui.prompt'))
922 if not r:
922 if not r:
923 r = default
923 r = default
924 if self.configbool('ui', 'promptecho'):
924 if self.configbool('ui', 'promptecho'):
925 self.write(r, "\n")
925 self.write(r, "\n")
926 return r
926 return r
927 except EOFError:
927 except EOFError:
928 raise error.ResponseExpected()
928 raise error.ResponseExpected()
929
929
930 @staticmethod
930 @staticmethod
931 def extractchoices(prompt):
931 def extractchoices(prompt):
932 """Extract prompt message and list of choices from specified prompt.
932 """Extract prompt message and list of choices from specified prompt.
933
933
934 This returns tuple "(message, choices)", and "choices" is the
934 This returns tuple "(message, choices)", and "choices" is the
935 list of tuple "(response character, text without &)".
935 list of tuple "(response character, text without &)".
936
936
937 >>> ui.extractchoices("awake? $$ &Yes $$ &No")
937 >>> ui.extractchoices("awake? $$ &Yes $$ &No")
938 ('awake? ', [('y', 'Yes'), ('n', 'No')])
938 ('awake? ', [('y', 'Yes'), ('n', 'No')])
939 >>> ui.extractchoices("line\\nbreak? $$ &Yes $$ &No")
939 >>> ui.extractchoices("line\\nbreak? $$ &Yes $$ &No")
940 ('line\\nbreak? ', [('y', 'Yes'), ('n', 'No')])
940 ('line\\nbreak? ', [('y', 'Yes'), ('n', 'No')])
941 >>> ui.extractchoices("want lots of $$money$$?$$Ye&s$$N&o")
941 >>> ui.extractchoices("want lots of $$money$$?$$Ye&s$$N&o")
942 ('want lots of $$money$$?', [('s', 'Yes'), ('o', 'No')])
942 ('want lots of $$money$$?', [('s', 'Yes'), ('o', 'No')])
943 """
943 """
944
944
945 # Sadly, the prompt string may have been built with a filename
945 # Sadly, the prompt string may have been built with a filename
946 # containing "$$" so let's try to find the first valid-looking
946 # containing "$$" so let's try to find the first valid-looking
947 # prompt to start parsing. Sadly, we also can't rely on
947 # prompt to start parsing. Sadly, we also can't rely on
948 # choices containing spaces, ASCII, or basically anything
948 # choices containing spaces, ASCII, or basically anything
949 # except an ampersand followed by a character.
949 # except an ampersand followed by a character.
950 m = re.match(r'(?s)(.+?)\$\$([^\$]*&[^ \$].*)', prompt)
950 m = re.match(r'(?s)(.+?)\$\$([^\$]*&[^ \$].*)', prompt)
951 msg = m.group(1)
951 msg = m.group(1)
952 choices = [p.strip(' ') for p in m.group(2).split('$$')]
952 choices = [p.strip(' ') for p in m.group(2).split('$$')]
953 return (msg,
953 return (msg,
954 [(s[s.index('&') + 1].lower(), s.replace('&', '', 1))
954 [(s[s.index('&') + 1].lower(), s.replace('&', '', 1))
955 for s in choices])
955 for s in choices])
956
956
957 def promptchoice(self, prompt, default=0):
957 def promptchoice(self, prompt, default=0):
958 """Prompt user with a message, read response, and ensure it matches
958 """Prompt user with a message, read response, and ensure it matches
959 one of the provided choices. The prompt is formatted as follows:
959 one of the provided choices. The prompt is formatted as follows:
960
960
961 "would you like fries with that (Yn)? $$ &Yes $$ &No"
961 "would you like fries with that (Yn)? $$ &Yes $$ &No"
962
962
963 The index of the choice is returned. Responses are case
963 The index of the choice is returned. Responses are case
964 insensitive. If ui is not interactive, the default is
964 insensitive. If ui is not interactive, the default is
965 returned.
965 returned.
966 """
966 """
967
967
968 msg, choices = self.extractchoices(prompt)
968 msg, choices = self.extractchoices(prompt)
969 resps = [r for r, t in choices]
969 resps = [r for r, t in choices]
970 while True:
970 while True:
971 r = self.prompt(msg, resps[default])
971 r = self.prompt(msg, resps[default])
972 if r.lower() in resps:
972 if r.lower() in resps:
973 return resps.index(r.lower())
973 return resps.index(r.lower())
974 self.write(_("unrecognized response\n"))
974 self.write(_("unrecognized response\n"))
975
975
976 def getpass(self, prompt=None, default=None):
976 def getpass(self, prompt=None, default=None):
977 if not self.interactive():
977 if not self.interactive():
978 return default
978 return default
979 try:
979 try:
980 self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
980 self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
981 # disable getpass() only if explicitly specified. it's still valid
981 # disable getpass() only if explicitly specified. it's still valid
982 # to interact with tty even if fin is not a tty.
982 # to interact with tty even if fin is not a tty.
983 if self.configbool('ui', 'nontty'):
983 if self.configbool('ui', 'nontty'):
984 l = self.fin.readline()
984 l = self.fin.readline()
985 if not l:
985 if not l:
986 raise EOFError
986 raise EOFError
987 return l.rstrip('\n')
987 return l.rstrip('\n')
988 else:
988 else:
989 return getpass.getpass('')
989 return getpass.getpass('')
990 except EOFError:
990 except EOFError:
991 raise error.ResponseExpected()
991 raise error.ResponseExpected()
992 def status(self, *msg, **opts):
992 def status(self, *msg, **opts):
993 '''write status message to output (if ui.quiet is False)
993 '''write status message to output (if ui.quiet is False)
994
994
995 This adds an output label of "ui.status".
995 This adds an output label of "ui.status".
996 '''
996 '''
997 if not self.quiet:
997 if not self.quiet:
998 opts['label'] = opts.get('label', '') + ' ui.status'
998 opts['label'] = opts.get('label', '') + ' ui.status'
999 self.write(*msg, **opts)
999 self.write(*msg, **opts)
1000 def warn(self, *msg, **opts):
1000 def warn(self, *msg, **opts):
1001 '''write warning message to output (stderr)
1001 '''write warning message to output (stderr)
1002
1002
1003 This adds an output label of "ui.warning".
1003 This adds an output label of "ui.warning".
1004 '''
1004 '''
1005 opts['label'] = opts.get('label', '') + ' ui.warning'
1005 opts['label'] = opts.get('label', '') + ' ui.warning'
1006 self.write_err(*msg, **opts)
1006 self.write_err(*msg, **opts)
1007 def note(self, *msg, **opts):
1007 def note(self, *msg, **opts):
1008 '''write note to output (if ui.verbose is True)
1008 '''write note to output (if ui.verbose is True)
1009
1009
1010 This adds an output label of "ui.note".
1010 This adds an output label of "ui.note".
1011 '''
1011 '''
1012 if self.verbose:
1012 if self.verbose:
1013 opts['label'] = opts.get('label', '') + ' ui.note'
1013 opts['label'] = opts.get('label', '') + ' ui.note'
1014 self.write(*msg, **opts)
1014 self.write(*msg, **opts)
1015 def debug(self, *msg, **opts):
1015 def debug(self, *msg, **opts):
1016 '''write debug message to output (if ui.debugflag is True)
1016 '''write debug message to output (if ui.debugflag is True)
1017
1017
1018 This adds an output label of "ui.debug".
1018 This adds an output label of "ui.debug".
1019 '''
1019 '''
1020 if self.debugflag:
1020 if self.debugflag:
1021 opts['label'] = opts.get('label', '') + ' ui.debug'
1021 opts['label'] = opts.get('label', '') + ' ui.debug'
1022 self.write(*msg, **opts)
1022 self.write(*msg, **opts)
1023
1023
1024 def edit(self, text, user, extra=None, editform=None, pending=None,
1024 def edit(self, text, user, extra=None, editform=None, pending=None,
1025 repopath=None):
1025 repopath=None):
1026 extra_defaults = {
1026 extra_defaults = {
1027 'prefix': 'editor',
1027 'prefix': 'editor',
1028 'suffix': '.txt',
1028 'suffix': '.txt',
1029 }
1029 }
1030 if extra is not None:
1030 if extra is not None:
1031 extra_defaults.update(extra)
1031 extra_defaults.update(extra)
1032 extra = extra_defaults
1032 extra = extra_defaults
1033
1033
1034 rdir = None
1034 rdir = None
1035 if self.configbool('experimental', 'editortmpinhg'):
1035 if self.configbool('experimental', 'editortmpinhg'):
1036 rdir = repopath
1036 rdir = repopath
1037 (fd, name) = tempfile.mkstemp(prefix='hg-' + extra['prefix'] + '-',
1037 (fd, name) = tempfile.mkstemp(prefix='hg-' + extra['prefix'] + '-',
1038 suffix=extra['suffix'], text=True,
1038 suffix=extra['suffix'], text=True,
1039 dir=rdir)
1039 dir=rdir)
1040 try:
1040 try:
1041 f = os.fdopen(fd, "w")
1041 f = os.fdopen(fd, "w")
1042 f.write(text)
1042 f.write(text)
1043 f.close()
1043 f.close()
1044
1044
1045 environ = {'HGUSER': user}
1045 environ = {'HGUSER': user}
1046 if 'transplant_source' in extra:
1046 if 'transplant_source' in extra:
1047 environ.update({'HGREVISION': hex(extra['transplant_source'])})
1047 environ.update({'HGREVISION': hex(extra['transplant_source'])})
1048 for label in ('intermediate-source', 'source', 'rebase_source'):
1048 for label in ('intermediate-source', 'source', 'rebase_source'):
1049 if label in extra:
1049 if label in extra:
1050 environ.update({'HGREVISION': extra[label]})
1050 environ.update({'HGREVISION': extra[label]})
1051 break
1051 break
1052 if editform:
1052 if editform:
1053 environ.update({'HGEDITFORM': editform})
1053 environ.update({'HGEDITFORM': editform})
1054 if pending:
1054 if pending:
1055 environ.update({'HG_PENDING': pending})
1055 environ.update({'HG_PENDING': pending})
1056
1056
1057 editor = self.geteditor()
1057 editor = self.geteditor()
1058
1058
1059 self.system("%s \"%s\"" % (editor, name),
1059 self.system("%s \"%s\"" % (editor, name),
1060 environ=environ,
1060 environ=environ,
1061 onerr=error.Abort, errprefix=_("edit failed"))
1061 onerr=error.Abort, errprefix=_("edit failed"))
1062
1062
1063 f = open(name)
1063 f = open(name)
1064 t = f.read()
1064 t = f.read()
1065 f.close()
1065 f.close()
1066 finally:
1066 finally:
1067 os.unlink(name)
1067 os.unlink(name)
1068
1068
1069 return t
1069 return t
1070
1070
1071 def system(self, cmd, environ=None, cwd=None, onerr=None, errprefix=None):
1071 def system(self, cmd, environ=None, cwd=None, onerr=None, errprefix=None):
1072 '''execute shell command with appropriate output stream. command
1072 '''execute shell command with appropriate output stream. command
1073 output will be redirected if fout is not stdout.
1073 output will be redirected if fout is not stdout.
1074 '''
1074 '''
1075 out = self.fout
1075 out = self.fout
1076 if any(s[1] for s in self._bufferstates):
1076 if any(s[1] for s in self._bufferstates):
1077 out = self
1077 out = self
1078 return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
1078 return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
1079 errprefix=errprefix, out=out)
1079 errprefix=errprefix, out=out)
1080
1080
1081 def traceback(self, exc=None, force=False):
1081 def traceback(self, exc=None, force=False):
1082 '''print exception traceback if traceback printing enabled or forced.
1082 '''print exception traceback if traceback printing enabled or forced.
1083 only to call in exception handler. returns true if traceback
1083 only to call in exception handler. returns true if traceback
1084 printed.'''
1084 printed.'''
1085 if self.tracebackflag or force:
1085 if self.tracebackflag or force:
1086 if exc is None:
1086 if exc is None:
1087 exc = sys.exc_info()
1087 exc = sys.exc_info()
1088 cause = getattr(exc[1], 'cause', None)
1088 cause = getattr(exc[1], 'cause', None)
1089
1089
1090 if cause is not None:
1090 if cause is not None:
1091 causetb = traceback.format_tb(cause[2])
1091 causetb = traceback.format_tb(cause[2])
1092 exctb = traceback.format_tb(exc[2])
1092 exctb = traceback.format_tb(exc[2])
1093 exconly = traceback.format_exception_only(cause[0], cause[1])
1093 exconly = traceback.format_exception_only(cause[0], cause[1])
1094
1094
1095 # exclude frame where 'exc' was chained and rethrown from exctb
1095 # exclude frame where 'exc' was chained and rethrown from exctb
1096 self.write_err('Traceback (most recent call last):\n',
1096 self.write_err('Traceback (most recent call last):\n',
1097 ''.join(exctb[:-1]),
1097 ''.join(exctb[:-1]),
1098 ''.join(causetb),
1098 ''.join(causetb),
1099 ''.join(exconly))
1099 ''.join(exconly))
1100 else:
1100 else:
1101 output = traceback.format_exception(exc[0], exc[1], exc[2])
1101 output = traceback.format_exception(exc[0], exc[1], exc[2])
1102 self.write_err(''.join(output))
1102 self.write_err(''.join(output))
1103 return self.tracebackflag or force
1103 return self.tracebackflag or force
1104
1104
1105 def geteditor(self):
1105 def geteditor(self):
1106 '''return editor to use'''
1106 '''return editor to use'''
1107 if pycompat.sysplatform == 'plan9':
1107 if pycompat.sysplatform == 'plan9':
1108 # vi is the MIPS instruction simulator on Plan 9. We
1108 # vi is the MIPS instruction simulator on Plan 9. We
1109 # instead default to E to plumb commit messages to
1109 # instead default to E to plumb commit messages to
1110 # avoid confusion.
1110 # avoid confusion.
1111 editor = 'E'
1111 editor = 'E'
1112 else:
1112 else:
1113 editor = 'vi'
1113 editor = 'vi'
1114 return (encoding.environ.get("HGEDITOR") or
1114 return (encoding.environ.get("HGEDITOR") or
1115 self.config("ui", "editor") or
1115 self.config("ui", "editor") or
1116 encoding.environ.get("VISUAL") or
1116 encoding.environ.get("VISUAL") or
1117 encoding.environ.get("EDITOR", editor))
1117 encoding.environ.get("EDITOR", editor))
1118
1118
1119 @util.propertycache
1119 @util.propertycache
1120 def _progbar(self):
1120 def _progbar(self):
1121 """setup the progbar singleton to the ui object"""
1121 """setup the progbar singleton to the ui object"""
1122 if (self.quiet or self.debugflag
1122 if (self.quiet or self.debugflag
1123 or self.configbool('progress', 'disable', False)
1123 or self.configbool('progress', 'disable', False)
1124 or not progress.shouldprint(self)):
1124 or not progress.shouldprint(self)):
1125 return None
1125 return None
1126 return getprogbar(self)
1126 return getprogbar(self)
1127
1127
1128 def _progclear(self):
1128 def _progclear(self):
1129 """clear progress bar output if any. use it before any output"""
1129 """clear progress bar output if any. use it before any output"""
1130 if '_progbar' not in vars(self): # nothing loaded yet
1130 if '_progbar' not in vars(self): # nothing loaded yet
1131 return
1131 return
1132 if self._progbar is not None and self._progbar.printed:
1132 if self._progbar is not None and self._progbar.printed:
1133 self._progbar.clear()
1133 self._progbar.clear()
1134
1134
1135 def progress(self, topic, pos, item="", unit="", total=None):
1135 def progress(self, topic, pos, item="", unit="", total=None):
1136 '''show a progress message
1136 '''show a progress message
1137
1137
1138 By default a textual progress bar will be displayed if an operation
1138 By default a textual progress bar will be displayed if an operation
1139 takes too long. 'topic' is the current operation, 'item' is a
1139 takes too long. 'topic' is the current operation, 'item' is a
1140 non-numeric marker of the current position (i.e. the currently
1140 non-numeric marker of the current position (i.e. the currently
1141 in-process file), 'pos' is the current numeric position (i.e.
1141 in-process file), 'pos' is the current numeric position (i.e.
1142 revision, bytes, etc.), unit is a corresponding unit label,
1142 revision, bytes, etc.), unit is a corresponding unit label,
1143 and total is the highest expected pos.
1143 and total is the highest expected pos.
1144
1144
1145 Multiple nested topics may be active at a time.
1145 Multiple nested topics may be active at a time.
1146
1146
1147 All topics should be marked closed by setting pos to None at
1147 All topics should be marked closed by setting pos to None at
1148 termination.
1148 termination.
1149 '''
1149 '''
1150 if self._progbar is not None:
1150 if self._progbar is not None:
1151 self._progbar.progress(topic, pos, item=item, unit=unit,
1151 self._progbar.progress(topic, pos, item=item, unit=unit,
1152 total=total)
1152 total=total)
1153 if pos is None or not self.configbool('progress', 'debug'):
1153 if pos is None or not self.configbool('progress', 'debug'):
1154 return
1154 return
1155
1155
1156 if unit:
1156 if unit:
1157 unit = ' ' + unit
1157 unit = ' ' + unit
1158 if item:
1158 if item:
1159 item = ' ' + item
1159 item = ' ' + item
1160
1160
1161 if total:
1161 if total:
1162 pct = 100.0 * pos / total
1162 pct = 100.0 * pos / total
1163 self.debug('%s:%s %s/%s%s (%4.2f%%)\n'
1163 self.debug('%s:%s %s/%s%s (%4.2f%%)\n'
1164 % (topic, item, pos, total, unit, pct))
1164 % (topic, item, pos, total, unit, pct))
1165 else:
1165 else:
1166 self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
1166 self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
1167
1167
1168 def log(self, service, *msg, **opts):
1168 def log(self, service, *msg, **opts):
1169 '''hook for logging facility extensions
1169 '''hook for logging facility extensions
1170
1170
1171 service should be a readily-identifiable subsystem, which will
1171 service should be a readily-identifiable subsystem, which will
1172 allow filtering.
1172 allow filtering.
1173
1173
1174 *msg should be a newline-terminated format string to log, and
1174 *msg should be a newline-terminated format string to log, and
1175 then any values to %-format into that format string.
1175 then any values to %-format into that format string.
1176
1176
1177 **opts currently has no defined meanings.
1177 **opts currently has no defined meanings.
1178 '''
1178 '''
1179
1179
1180 def label(self, msg, label):
1180 def label(self, msg, label):
1181 '''style msg based on supplied label
1181 '''style msg based on supplied label
1182
1182
1183 Like ui.write(), this just returns msg unchanged, but extensions
1183 Like ui.write(), this just returns msg unchanged, but extensions
1184 and GUI tools can override it to allow styling output without
1184 and GUI tools can override it to allow styling output without
1185 writing it.
1185 writing it.
1186
1186
1187 ui.write(s, 'label') is equivalent to
1187 ui.write(s, 'label') is equivalent to
1188 ui.write(ui.label(s, 'label')).
1188 ui.write(ui.label(s, 'label')).
1189 '''
1189 '''
1190 return msg
1190 return msg
1191
1191
1192 def develwarn(self, msg, stacklevel=1, config=None):
1192 def develwarn(self, msg, stacklevel=1, config=None):
1193 """issue a developer warning message
1193 """issue a developer warning message
1194
1194
1195 Use 'stacklevel' to report the offender some layers further up in the
1195 Use 'stacklevel' to report the offender some layers further up in the
1196 stack.
1196 stack.
1197 """
1197 """
1198 if not self.configbool('devel', 'all-warnings'):
1198 if not self.configbool('devel', 'all-warnings'):
1199 if config is not None and not self.configbool('devel', config):
1199 if config is not None and not self.configbool('devel', config):
1200 return
1200 return
1201 msg = 'devel-warn: ' + msg
1201 msg = 'devel-warn: ' + msg
1202 stacklevel += 1 # get in develwarn
1202 stacklevel += 1 # get in develwarn
1203 if self.tracebackflag:
1203 if self.tracebackflag:
1204 util.debugstacktrace(msg, stacklevel, self.ferr, self.fout)
1204 util.debugstacktrace(msg, stacklevel, self.ferr, self.fout)
1205 self.log('develwarn', '%s at:\n%s' %
1205 self.log('develwarn', '%s at:\n%s' %
1206 (msg, ''.join(util.getstackframes(stacklevel))))
1206 (msg, ''.join(util.getstackframes(stacklevel))))
1207 else:
1207 else:
1208 curframe = inspect.currentframe()
1208 curframe = inspect.currentframe()
1209 calframe = inspect.getouterframes(curframe, 2)
1209 calframe = inspect.getouterframes(curframe, 2)
1210 self.write_err('%s at: %s:%s (%s)\n'
1210 self.write_err('%s at: %s:%s (%s)\n'
1211 % ((msg,) + calframe[stacklevel][1:4]))
1211 % ((msg,) + calframe[stacklevel][1:4]))
1212 self.log('develwarn', '%s at: %s:%s (%s)\n',
1212 self.log('develwarn', '%s at: %s:%s (%s)\n',
1213 msg, *calframe[stacklevel][1:4])
1213 msg, *calframe[stacklevel][1:4])
1214 curframe = calframe = None # avoid cycles
1214 curframe = calframe = None # avoid cycles
1215
1215
1216 def deprecwarn(self, msg, version):
1216 def deprecwarn(self, msg, version):
1217 """issue a deprecation warning
1217 """issue a deprecation warning
1218
1218
1219 - msg: message explaining what is deprecated and how to upgrade,
1219 - msg: message explaining what is deprecated and how to upgrade,
1220 - version: last version where the API will be supported,
1220 - version: last version where the API will be supported,
1221 """
1221 """
1222 if not (self.configbool('devel', 'all-warnings')
1222 if not (self.configbool('devel', 'all-warnings')
1223 or self.configbool('devel', 'deprec-warn')):
1223 or self.configbool('devel', 'deprec-warn')):
1224 return
1224 return
1225 msg += ("\n(compatibility will be dropped after Mercurial-%s,"
1225 msg += ("\n(compatibility will be dropped after Mercurial-%s,"
1226 " update your code.)") % version
1226 " update your code.)") % version
1227 self.develwarn(msg, stacklevel=2, config='deprec-warn')
1227 self.develwarn(msg, stacklevel=2, config='deprec-warn')
1228
1228
1229 def exportableenviron(self):
1229 def exportableenviron(self):
1230 """The environment variables that are safe to export, e.g. through
1230 """The environment variables that are safe to export, e.g. through
1231 hgweb.
1231 hgweb.
1232 """
1232 """
1233 return self._exportableenviron
1233 return self._exportableenviron
1234
1234
1235 @contextlib.contextmanager
1235 @contextlib.contextmanager
1236 def configoverride(self, overrides, source=""):
1236 def configoverride(self, overrides, source=""):
1237 """Context manager for temporary config overrides
1237 """Context manager for temporary config overrides
1238 `overrides` must be a dict of the following structure:
1238 `overrides` must be a dict of the following structure:
1239 {(section, name) : value}"""
1239 {(section, name) : value}"""
1240 backups = {}
1240 backups = {}
1241 try:
1241 try:
1242 for (section, name), value in overrides.items():
1242 for (section, name), value in overrides.items():
1243 backups[(section, name)] = self.backupconfig(section, name)
1243 backups[(section, name)] = self.backupconfig(section, name)
1244 self.setconfig(section, name, value, source)
1244 self.setconfig(section, name, value, source)
1245 yield
1245 yield
1246 finally:
1246 finally:
1247 for __, backup in backups.items():
1247 for __, backup in backups.items():
1248 self.restoreconfig(backup)
1248 self.restoreconfig(backup)
1249 # just restoring ui.quiet config to the previous value is not enough
1249 # just restoring ui.quiet config to the previous value is not enough
1250 # as it does not update ui.quiet class member
1250 # as it does not update ui.quiet class member
1251 if ('ui', 'quiet') in overrides:
1251 if ('ui', 'quiet') in overrides:
1252 self.fixconfig(section='ui')
1252 self.fixconfig(section='ui')
1253
1253
1254 class paths(dict):
1254 class paths(dict):
1255 """Represents a collection of paths and their configs.
1255 """Represents a collection of paths and their configs.
1256
1256
1257 Data is initially derived from ui instances and the config files they have
1257 Data is initially derived from ui instances and the config files they have
1258 loaded.
1258 loaded.
1259 """
1259 """
1260 def __init__(self, ui):
1260 def __init__(self, ui):
1261 dict.__init__(self)
1261 dict.__init__(self)
1262
1262
1263 for name, loc in ui.configitems('paths', ignoresub=True):
1263 for name, loc in ui.configitems('paths', ignoresub=True):
1264 # No location is the same as not existing.
1264 # No location is the same as not existing.
1265 if not loc:
1265 if not loc:
1266 continue
1266 continue
1267 loc, sub = ui.configsuboptions('paths', name)
1267 loc, sub = ui.configsuboptions('paths', name)
1268 self[name] = path(ui, name, rawloc=loc, suboptions=sub)
1268 self[name] = path(ui, name, rawloc=loc, suboptions=sub)
1269
1269
1270 def getpath(self, name, default=None):
1270 def getpath(self, name, default=None):
1271 """Return a ``path`` from a string, falling back to default.
1271 """Return a ``path`` from a string, falling back to default.
1272
1272
1273 ``name`` can be a named path or locations. Locations are filesystem
1273 ``name`` can be a named path or locations. Locations are filesystem
1274 paths or URIs.
1274 paths or URIs.
1275
1275
1276 Returns None if ``name`` is not a registered path, a URI, or a local
1276 Returns None if ``name`` is not a registered path, a URI, or a local
1277 path to a repo.
1277 path to a repo.
1278 """
1278 """
1279 # Only fall back to default if no path was requested.
1279 # Only fall back to default if no path was requested.
1280 if name is None:
1280 if name is None:
1281 if not default:
1281 if not default:
1282 default = ()
1282 default = ()
1283 elif not isinstance(default, (tuple, list)):
1283 elif not isinstance(default, (tuple, list)):
1284 default = (default,)
1284 default = (default,)
1285 for k in default:
1285 for k in default:
1286 try:
1286 try:
1287 return self[k]
1287 return self[k]
1288 except KeyError:
1288 except KeyError:
1289 continue
1289 continue
1290 return None
1290 return None
1291
1291
1292 # Most likely empty string.
1292 # Most likely empty string.
1293 # This may need to raise in the future.
1293 # This may need to raise in the future.
1294 if not name:
1294 if not name:
1295 return None
1295 return None
1296
1296
1297 try:
1297 try:
1298 return self[name]
1298 return self[name]
1299 except KeyError:
1299 except KeyError:
1300 # Try to resolve as a local path or URI.
1300 # Try to resolve as a local path or URI.
1301 try:
1301 try:
1302 # We don't pass sub-options in, so no need to pass ui instance.
1302 # We don't pass sub-options in, so no need to pass ui instance.
1303 return path(None, None, rawloc=name)
1303 return path(None, None, rawloc=name)
1304 except ValueError:
1304 except ValueError:
1305 raise error.RepoError(_('repository %s does not exist') %
1305 raise error.RepoError(_('repository %s does not exist') %
1306 name)
1306 name)
1307
1307
1308 _pathsuboptions = {}
1308 _pathsuboptions = {}
1309
1309
1310 def pathsuboption(option, attr):
1310 def pathsuboption(option, attr):
1311 """Decorator used to declare a path sub-option.
1311 """Decorator used to declare a path sub-option.
1312
1312
1313 Arguments are the sub-option name and the attribute it should set on
1313 Arguments are the sub-option name and the attribute it should set on
1314 ``path`` instances.
1314 ``path`` instances.
1315
1315
1316 The decorated function will receive as arguments a ``ui`` instance,
1316 The decorated function will receive as arguments a ``ui`` instance,
1317 ``path`` instance, and the string value of this option from the config.
1317 ``path`` instance, and the string value of this option from the config.
1318 The function should return the value that will be set on the ``path``
1318 The function should return the value that will be set on the ``path``
1319 instance.
1319 instance.
1320
1320
1321 This decorator can be used to perform additional verification of
1321 This decorator can be used to perform additional verification of
1322 sub-options and to change the type of sub-options.
1322 sub-options and to change the type of sub-options.
1323 """
1323 """
1324 def register(func):
1324 def register(func):
1325 _pathsuboptions[option] = (attr, func)
1325 _pathsuboptions[option] = (attr, func)
1326 return func
1326 return func
1327 return register
1327 return register
1328
1328
1329 @pathsuboption('pushurl', 'pushloc')
1329 @pathsuboption('pushurl', 'pushloc')
1330 def pushurlpathoption(ui, path, value):
1330 def pushurlpathoption(ui, path, value):
1331 u = util.url(value)
1331 u = util.url(value)
1332 # Actually require a URL.
1332 # Actually require a URL.
1333 if not u.scheme:
1333 if not u.scheme:
1334 ui.warn(_('(paths.%s:pushurl not a URL; ignoring)\n') % path.name)
1334 ui.warn(_('(paths.%s:pushurl not a URL; ignoring)\n') % path.name)
1335 return None
1335 return None
1336
1336
1337 # Don't support the #foo syntax in the push URL to declare branch to
1337 # Don't support the #foo syntax in the push URL to declare branch to
1338 # push.
1338 # push.
1339 if u.fragment:
1339 if u.fragment:
1340 ui.warn(_('("#fragment" in paths.%s:pushurl not supported; '
1340 ui.warn(_('("#fragment" in paths.%s:pushurl not supported; '
1341 'ignoring)\n') % path.name)
1341 'ignoring)\n') % path.name)
1342 u.fragment = None
1342 u.fragment = None
1343
1343
1344 return str(u)
1344 return str(u)
1345
1345
1346 @pathsuboption('pushrev', 'pushrev')
1346 @pathsuboption('pushrev', 'pushrev')
1347 def pushrevpathoption(ui, path, value):
1347 def pushrevpathoption(ui, path, value):
1348 return value
1348 return value
1349
1349
1350 class path(object):
1350 class path(object):
1351 """Represents an individual path and its configuration."""
1351 """Represents an individual path and its configuration."""
1352
1352
1353 def __init__(self, ui, name, rawloc=None, suboptions=None):
1353 def __init__(self, ui, name, rawloc=None, suboptions=None):
1354 """Construct a path from its config options.
1354 """Construct a path from its config options.
1355
1355
1356 ``ui`` is the ``ui`` instance the path is coming from.
1356 ``ui`` is the ``ui`` instance the path is coming from.
1357 ``name`` is the symbolic name of the path.
1357 ``name`` is the symbolic name of the path.
1358 ``rawloc`` is the raw location, as defined in the config.
1358 ``rawloc`` is the raw location, as defined in the config.
1359 ``pushloc`` is the raw locations pushes should be made to.
1359 ``pushloc`` is the raw locations pushes should be made to.
1360
1360
1361 If ``name`` is not defined, we require that the location be a) a local
1361 If ``name`` is not defined, we require that the location be a) a local
1362 filesystem path with a .hg directory or b) a URL. If not,
1362 filesystem path with a .hg directory or b) a URL. If not,
1363 ``ValueError`` is raised.
1363 ``ValueError`` is raised.
1364 """
1364 """
1365 if not rawloc:
1365 if not rawloc:
1366 raise ValueError('rawloc must be defined')
1366 raise ValueError('rawloc must be defined')
1367
1367
1368 # Locations may define branches via syntax <base>#<branch>.
1368 # Locations may define branches via syntax <base>#<branch>.
1369 u = util.url(rawloc)
1369 u = util.url(rawloc)
1370 branch = None
1370 branch = None
1371 if u.fragment:
1371 if u.fragment:
1372 branch = u.fragment
1372 branch = u.fragment
1373 u.fragment = None
1373 u.fragment = None
1374
1374
1375 self.url = u
1375 self.url = u
1376 self.branch = branch
1376 self.branch = branch
1377
1377
1378 self.name = name
1378 self.name = name
1379 self.rawloc = rawloc
1379 self.rawloc = rawloc
1380 self.loc = str(u)
1380 self.loc = str(u)
1381
1381
1382 # When given a raw location but not a symbolic name, validate the
1382 # When given a raw location but not a symbolic name, validate the
1383 # location is valid.
1383 # location is valid.
1384 if not name and not u.scheme and not self._isvalidlocalpath(self.loc):
1384 if not name and not u.scheme and not self._isvalidlocalpath(self.loc):
1385 raise ValueError('location is not a URL or path to a local '
1385 raise ValueError('location is not a URL or path to a local '
1386 'repo: %s' % rawloc)
1386 'repo: %s' % rawloc)
1387
1387
1388 suboptions = suboptions or {}
1388 suboptions = suboptions or {}
1389
1389
1390 # Now process the sub-options. If a sub-option is registered, its
1390 # Now process the sub-options. If a sub-option is registered, its
1391 # attribute will always be present. The value will be None if there
1391 # attribute will always be present. The value will be None if there
1392 # was no valid sub-option.
1392 # was no valid sub-option.
1393 for suboption, (attr, func) in _pathsuboptions.iteritems():
1393 for suboption, (attr, func) in _pathsuboptions.iteritems():
1394 if suboption not in suboptions:
1394 if suboption not in suboptions:
1395 setattr(self, attr, None)
1395 setattr(self, attr, None)
1396 continue
1396 continue
1397
1397
1398 value = func(ui, self, suboptions[suboption])
1398 value = func(ui, self, suboptions[suboption])
1399 setattr(self, attr, value)
1399 setattr(self, attr, value)
1400
1400
1401 def _isvalidlocalpath(self, path):
1401 def _isvalidlocalpath(self, path):
1402 """Returns True if the given path is a potentially valid repository.
1402 """Returns True if the given path is a potentially valid repository.
1403 This is its own function so that extensions can change the definition of
1403 This is its own function so that extensions can change the definition of
1404 'valid' in this case (like when pulling from a git repo into a hg
1404 'valid' in this case (like when pulling from a git repo into a hg
1405 one)."""
1405 one)."""
1406 return os.path.isdir(os.path.join(path, '.hg'))
1406 return os.path.isdir(os.path.join(path, '.hg'))
1407
1407
1408 @property
1408 @property
1409 def suboptions(self):
1409 def suboptions(self):
1410 """Return sub-options and their values for this path.
1410 """Return sub-options and their values for this path.
1411
1411
1412 This is intended to be used for presentation purposes.
1412 This is intended to be used for presentation purposes.
1413 """
1413 """
1414 d = {}
1414 d = {}
1415 for subopt, (attr, _func) in _pathsuboptions.iteritems():
1415 for subopt, (attr, _func) in _pathsuboptions.iteritems():
1416 value = getattr(self, attr)
1416 value = getattr(self, attr)
1417 if value is not None:
1417 if value is not None:
1418 d[subopt] = value
1418 d[subopt] = value
1419 return d
1419 return d
1420
1420
1421 # we instantiate one globally shared progress bar to avoid
1421 # we instantiate one globally shared progress bar to avoid
1422 # competing progress bars when multiple UI objects get created
1422 # competing progress bars when multiple UI objects get created
1423 _progresssingleton = None
1423 _progresssingleton = None
1424
1424
1425 def getprogbar(ui):
1425 def getprogbar(ui):
1426 global _progresssingleton
1426 global _progresssingleton
1427 if _progresssingleton is None:
1427 if _progresssingleton is None:
1428 # passing 'ui' object to the singleton is fishy,
1428 # passing 'ui' object to the singleton is fishy,
1429 # this is how the extension used to work but feel free to rework it.
1429 # this is how the extension used to work but feel free to rework it.
1430 _progresssingleton = progress.progbar(ui)
1430 _progresssingleton = progress.progbar(ui)
1431 return _progresssingleton
1431 return _progresssingleton
@@ -1,231 +1,231 b''
1 hide outer repo
1 hide outer repo
2 $ hg init
2 $ hg init
3
3
4 Use hgrc within $TESTTMP
4 Use hgrc within $TESTTMP
5
5
6 $ HGRCPATH=`pwd`/hgrc
6 $ HGRCPATH=`pwd`/hgrc
7 $ export HGRCPATH
7 $ export HGRCPATH
8
8
9 Use an alternate var for scribbling on hgrc to keep check-code from
9 Use an alternate var for scribbling on hgrc to keep check-code from
10 complaining about the important settings we may be overwriting:
10 complaining about the important settings we may be overwriting:
11
11
12 $ HGRC=`pwd`/hgrc
12 $ HGRC=`pwd`/hgrc
13 $ export HGRC
13 $ export HGRC
14
14
15 Basic syntax error
15 Basic syntax error
16
16
17 $ echo "invalid" > $HGRC
17 $ echo "invalid" > $HGRC
18 $ hg version
18 $ hg version
19 hg: parse error at $TESTTMP/hgrc:1: invalid
19 hg: parse error at $TESTTMP/hgrc:1: invalid
20 [255]
20 [255]
21 $ echo "" > $HGRC
21 $ echo "" > $HGRC
22
22
23 Issue1199: Can't use '%' in hgrc (eg url encoded username)
23 Issue1199: Can't use '%' in hgrc (eg url encoded username)
24
24
25 $ hg init "foo%bar"
25 $ hg init "foo%bar"
26 $ hg clone "foo%bar" foobar
26 $ hg clone "foo%bar" foobar
27 updating to branch default
27 updating to branch default
28 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 $ cd foobar
29 $ cd foobar
30 $ cat .hg/hgrc
30 $ cat .hg/hgrc
31 # example repository config (see 'hg help config' for more info)
31 # example repository config (see 'hg help config' for more info)
32 [paths]
32 [paths]
33 default = $TESTTMP/foo%bar (glob)
33 default = $TESTTMP/foo%bar (glob)
34
34
35 # path aliases to other clones of this repo in URLs or filesystem paths
35 # path aliases to other clones of this repo in URLs or filesystem paths
36 # (see 'hg help config.paths' for more info)
36 # (see 'hg help config.paths' for more info)
37 #
37 #
38 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
38 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
39 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
39 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
40 # my-clone = /home/jdoe/jdoes-clone
40 # my-clone = /home/jdoe/jdoes-clone
41
41
42 [ui]
42 [ui]
43 # name and email (local to this repository, optional), e.g.
43 # name and email (local to this repository, optional), e.g.
44 # username = Jane Doe <jdoe@example.com>
44 # username = Jane Doe <jdoe@example.com>
45 $ hg paths
45 $ hg paths
46 default = $TESTTMP/foo%bar (glob)
46 default = $TESTTMP/foo%bar (glob)
47 $ hg showconfig
47 $ hg showconfig
48 bundle.mainreporoot=$TESTTMP/foobar (glob)
48 bundle.mainreporoot=$TESTTMP/foobar (glob)
49 paths.default=$TESTTMP/foo%bar (glob)
49 paths.default=$TESTTMP/foo%bar (glob)
50 $ cd ..
50 $ cd ..
51
51
52 issue1829: wrong indentation
52 issue1829: wrong indentation
53
53
54 $ echo '[foo]' > $HGRC
54 $ echo '[foo]' > $HGRC
55 $ echo ' x = y' >> $HGRC
55 $ echo ' x = y' >> $HGRC
56 $ hg version
56 $ hg version
57 hg: parse error at $TESTTMP/hgrc:2: x = y
57 hg: parse error at $TESTTMP/hgrc:2: x = y
58 unexpected leading whitespace
58 unexpected leading whitespace
59 [255]
59 [255]
60
60
61 $ $PYTHON -c "print '[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n'" \
61 $ $PYTHON -c "print '[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n'" \
62 > > $HGRC
62 > > $HGRC
63 $ hg showconfig foo
63 $ hg showconfig foo
64 foo.bar=a\nb\nc\nde\nfg
64 foo.bar=a\nb\nc\nde\nfg
65 foo.baz=bif cb
65 foo.baz=bif cb
66
66
67 $ FAKEPATH=/path/to/nowhere
67 $ FAKEPATH=/path/to/nowhere
68 $ export FAKEPATH
68 $ export FAKEPATH
69 $ echo '%include $FAKEPATH/no-such-file' > $HGRC
69 $ echo '%include $FAKEPATH/no-such-file' > $HGRC
70 $ hg version
70 $ hg version
71 Mercurial Distributed SCM (version *) (glob)
71 Mercurial Distributed SCM (version *) (glob)
72 (see https://mercurial-scm.org for more information)
72 (see https://mercurial-scm.org for more information)
73
73
74 Copyright (C) 2005-* Matt Mackall and others (glob)
74 Copyright (C) 2005-* Matt Mackall and others (glob)
75 This is free software; see the source for copying conditions. There is NO
75 This is free software; see the source for copying conditions. There is NO
76 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
76 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
77 $ unset FAKEPATH
77 $ unset FAKEPATH
78
78
79 make sure global options given on the cmdline take precedence
79 make sure global options given on the cmdline take precedence
80
80
81 $ hg showconfig --config ui.verbose=True --quiet
81 $ hg showconfig --config ui.verbose=True --quiet
82 bundle.mainreporoot=$TESTTMP
82 bundle.mainreporoot=$TESTTMP
83 ui.verbose=False
83 ui.verbose=False
84 ui.debug=False
84 ui.debug=False
85 ui.quiet=True
85 ui.quiet=True
86
86
87 $ touch foobar/untracked
87 $ touch foobar/untracked
88 $ cat >> foobar/.hg/hgrc <<EOF
88 $ cat >> foobar/.hg/hgrc <<EOF
89 > [ui]
89 > [ui]
90 > verbose=True
90 > verbose=True
91 > EOF
91 > EOF
92 $ hg -R foobar st -q
92 $ hg -R foobar st -q
93
93
94 username expansion
94 username expansion
95
95
96 $ olduser=$HGUSER
96 $ olduser=$HGUSER
97 $ unset HGUSER
97 $ unset HGUSER
98
98
99 $ FAKEUSER='John Doe'
99 $ FAKEUSER='John Doe'
100 $ export FAKEUSER
100 $ export FAKEUSER
101 $ echo '[ui]' > $HGRC
101 $ echo '[ui]' > $HGRC
102 $ echo 'username = $FAKEUSER' >> $HGRC
102 $ echo 'username = $FAKEUSER' >> $HGRC
103
103
104 $ hg init usertest
104 $ hg init usertest
105 $ cd usertest
105 $ cd usertest
106 $ touch bar
106 $ touch bar
107 $ hg commit --addremove --quiet -m "added bar"
107 $ hg commit --addremove --quiet -m "added bar"
108 $ hg log --template "{author}\n"
108 $ hg log --template "{author}\n"
109 John Doe
109 John Doe
110 $ cd ..
110 $ cd ..
111
111
112 $ hg showconfig
112 $ hg showconfig
113 bundle.mainreporoot=$TESTTMP
113 bundle.mainreporoot=$TESTTMP
114 ui.username=$FAKEUSER
114 ui.username=$FAKEUSER
115
115
116 $ unset FAKEUSER
116 $ unset FAKEUSER
117 $ HGUSER=$olduser
117 $ HGUSER=$olduser
118 $ export HGUSER
118 $ export HGUSER
119
119
120 showconfig with multiple arguments
120 showconfig with multiple arguments
121
121
122 $ echo "[alias]" > $HGRC
122 $ echo "[alias]" > $HGRC
123 $ echo "log = log -g" >> $HGRC
123 $ echo "log = log -g" >> $HGRC
124 $ echo "[defaults]" >> $HGRC
124 $ echo "[defaults]" >> $HGRC
125 $ echo "identify = -n" >> $HGRC
125 $ echo "identify = -n" >> $HGRC
126 $ hg showconfig alias defaults
126 $ hg showconfig alias defaults
127 alias.log=log -g
127 alias.log=log -g
128 defaults.identify=-n
128 defaults.identify=-n
129 $ hg showconfig alias defaults.identify
129 $ hg showconfig alias defaults.identify
130 abort: only one config item permitted
130 abort: only one config item permitted
131 [255]
131 [255]
132 $ hg showconfig alias.log defaults.identify
132 $ hg showconfig alias.log defaults.identify
133 abort: only one config item permitted
133 abort: only one config item permitted
134 [255]
134 [255]
135
135
136 HGPLAIN
136 HGPLAIN
137
137
138 $ echo "[ui]" > $HGRC
138 $ echo "[ui]" > $HGRC
139 $ echo "debug=true" >> $HGRC
139 $ echo "debug=true" >> $HGRC
140 $ echo "fallbackencoding=ASCII" >> $HGRC
140 $ echo "fallbackencoding=ASCII" >> $HGRC
141 $ echo "quiet=true" >> $HGRC
141 $ echo "quiet=true" >> $HGRC
142 $ echo "slash=true" >> $HGRC
142 $ echo "slash=true" >> $HGRC
143 $ echo "traceback=true" >> $HGRC
143 $ echo "traceback=true" >> $HGRC
144 $ echo "verbose=true" >> $HGRC
144 $ echo "verbose=true" >> $HGRC
145 $ echo "style=~/.hgstyle" >> $HGRC
145 $ echo "style=~/.hgstyle" >> $HGRC
146 $ echo "logtemplate={node}" >> $HGRC
146 $ echo "logtemplate={node}" >> $HGRC
147 $ echo "[defaults]" >> $HGRC
147 $ echo "[defaults]" >> $HGRC
148 $ echo "identify=-n" >> $HGRC
148 $ echo "identify=-n" >> $HGRC
149 $ echo "[alias]" >> $HGRC
149 $ echo "[alias]" >> $HGRC
150 $ echo "log=log -g" >> $HGRC
150 $ echo "log=log -g" >> $HGRC
151
151
152 customized hgrc
152 customized hgrc
153
153
154 $ hg showconfig
154 $ hg showconfig
155 read config from: $TESTTMP/hgrc
155 read config from: $TESTTMP/hgrc
156 $TESTTMP/hgrc:13: alias.log=log -g
156 $TESTTMP/hgrc:13: alias.log=log -g
157 repo: bundle.mainreporoot=$TESTTMP
157 repo: bundle.mainreporoot=$TESTTMP
158 $TESTTMP/hgrc:11: defaults.identify=-n
158 $TESTTMP/hgrc:11: defaults.identify=-n
159 $TESTTMP/hgrc:2: ui.debug=true
159 $TESTTMP/hgrc:2: ui.debug=true
160 $TESTTMP/hgrc:3: ui.fallbackencoding=ASCII
160 $TESTTMP/hgrc:3: ui.fallbackencoding=ASCII
161 $TESTTMP/hgrc:4: ui.quiet=true
161 $TESTTMP/hgrc:4: ui.quiet=true
162 $TESTTMP/hgrc:5: ui.slash=true
162 $TESTTMP/hgrc:5: ui.slash=true
163 $TESTTMP/hgrc:6: ui.traceback=true
163 $TESTTMP/hgrc:6: ui.traceback=true
164 $TESTTMP/hgrc:7: ui.verbose=true
164 $TESTTMP/hgrc:7: ui.verbose=true
165 $TESTTMP/hgrc:8: ui.style=~/.hgstyle
165 $TESTTMP/hgrc:8: ui.style=~/.hgstyle
166 $TESTTMP/hgrc:9: ui.logtemplate={node}
166 $TESTTMP/hgrc:9: ui.logtemplate={node}
167
167
168 plain hgrc
168 plain hgrc
169
169
170 $ HGPLAIN=; export HGPLAIN
170 $ HGPLAIN=; export HGPLAIN
171 $ hg showconfig --config ui.traceback=True --debug
171 $ hg showconfig --config ui.traceback=True --debug
172 read config from: $TESTTMP/hgrc
172 read config from: $TESTTMP/hgrc
173 repo: bundle.mainreporoot=$TESTTMP
173 repo: bundle.mainreporoot=$TESTTMP
174 --config: ui.traceback=True
174 --config: ui.traceback=True
175 --verbose: ui.verbose=False
175 --verbose: ui.verbose=False
176 --debug: ui.debug=True
176 --debug: ui.debug=True
177 --quiet: ui.quiet=False
177 --quiet: ui.quiet=False
178
178
179 plain mode with exceptions
179 plain mode with exceptions
180
180
181 $ cat > plain.py <<EOF
181 $ cat > plain.py <<EOF
182 > from mercurial import commands, extensions
182 > from mercurial import commands, extensions
183 > def _config(orig, ui, repo, *values, **opts):
183 > def _config(orig, ui, repo, *values, **opts):
184 > ui.write('plain: %r\n' % ui.plain())
184 > ui.write('plain: %r\n' % ui.plain())
185 > return orig(ui, repo, *values, **opts)
185 > return orig(ui, repo, *values, **opts)
186 > def uisetup(ui):
186 > def uisetup(ui):
187 > extensions.wrapcommand(commands.table, 'config', _config)
187 > extensions.wrapcommand(commands.table, 'config', _config)
188 > EOF
188 > EOF
189 $ echo "[extensions]" >> $HGRC
189 $ echo "[extensions]" >> $HGRC
190 $ echo "plain=./plain.py" >> $HGRC
190 $ echo "plain=./plain.py" >> $HGRC
191 $ HGPLAINEXCEPT=; export HGPLAINEXCEPT
191 $ HGPLAINEXCEPT=; export HGPLAINEXCEPT
192 $ hg showconfig --config ui.traceback=True --debug
192 $ hg showconfig --config ui.traceback=True --debug
193 plain: True
193 plain: True
194 read config from: $TESTTMP/hgrc
194 read config from: $TESTTMP/hgrc
195 repo: bundle.mainreporoot=$TESTTMP
195 repo: bundle.mainreporoot=$TESTTMP
196 $TESTTMP/hgrc:15: extensions.plain=./plain.py
196 $TESTTMP/hgrc:15: extensions.plain=./plain.py
197 --config: ui.traceback=True
197 --config: ui.traceback=True
198 --verbose: ui.verbose=False
198 --verbose: ui.verbose=False
199 --debug: ui.debug=True
199 --debug: ui.debug=True
200 --quiet: ui.quiet=False
200 --quiet: ui.quiet=False
201 $ unset HGPLAIN
201 $ unset HGPLAIN
202 $ hg showconfig --config ui.traceback=True --debug
202 $ hg showconfig --config ui.traceback=True --debug
203 plain: True
203 plain: True
204 read config from: $TESTTMP/hgrc
204 read config from: $TESTTMP/hgrc
205 repo: bundle.mainreporoot=$TESTTMP
205 repo: bundle.mainreporoot=$TESTTMP
206 $TESTTMP/hgrc:15: extensions.plain=./plain.py
206 $TESTTMP/hgrc:15: extensions.plain=./plain.py
207 --config: ui.traceback=True
207 --config: ui.traceback=True
208 --verbose: ui.verbose=False
208 --verbose: ui.verbose=False
209 --debug: ui.debug=True
209 --debug: ui.debug=True
210 --quiet: ui.quiet=False
210 --quiet: ui.quiet=False
211 $ HGPLAINEXCEPT=i18n; export HGPLAINEXCEPT
211 $ HGPLAINEXCEPT=i18n; export HGPLAINEXCEPT
212 $ hg showconfig --config ui.traceback=True --debug
212 $ hg showconfig --config ui.traceback=True --debug
213 plain: True
213 plain: True
214 read config from: $TESTTMP/hgrc
214 read config from: $TESTTMP/hgrc
215 repo: bundle.mainreporoot=$TESTTMP
215 repo: bundle.mainreporoot=$TESTTMP
216 $TESTTMP/hgrc:15: extensions.plain=./plain.py
216 $TESTTMP/hgrc:15: extensions.plain=./plain.py
217 --config: ui.traceback=True
217 --config: ui.traceback=True
218 --verbose: ui.verbose=False
218 --verbose: ui.verbose=False
219 --debug: ui.debug=True
219 --debug: ui.debug=True
220 --quiet: ui.quiet=False
220 --quiet: ui.quiet=False
221
221
222 source of paths is not mangled
222 source of paths is not mangled
223
223
224 $ cat >> $HGRCPATH <<EOF
224 $ cat >> $HGRCPATH <<EOF
225 > [paths]
225 > [paths]
226 > foo = bar
226 > foo = bar
227 > EOF
227 > EOF
228 $ hg showconfig --debug paths
228 $ hg showconfig --debug paths
229 plain: True
229 plain: True
230 read config from: $TESTTMP/hgrc
230 read config from: $TESTTMP/hgrc
231 $TESTTMP/hgrc:17: paths.foo=$TESTTMP/bar (glob)
231 $TESTTMP/hgrc:17: paths.foo=$TESTTMP/bar (glob)
@@ -1,80 +1,80 b''
1 #require killdaemons
1 #require killdaemons
2
2
3 $ hg init test
3 $ hg init test
4 $ cd test
4 $ cd test
5 $ echo a > a
5 $ echo a > a
6 $ hg ci -Ama
6 $ hg ci -Ama
7 adding a
7 adding a
8 $ cd ..
8 $ cd ..
9 $ hg clone test test2
9 $ hg clone test test2
10 updating to branch default
10 updating to branch default
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 $ cd test2
12 $ cd test2
13 $ echo a >> a
13 $ echo a >> a
14 $ hg ci -mb
14 $ hg ci -mb
15
15
16 Cloning with a password in the URL should not save the password in .hg/hgrc:
16 Cloning with a password in the URL should not save the password in .hg/hgrc:
17
17
18 $ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
18 $ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
19 $ cat hg.pid >> $DAEMON_PIDS
19 $ cat hg.pid >> $DAEMON_PIDS
20 $ hg clone http://foo:xyzzy@localhost:$HGPORT/ test3
20 $ hg clone http://foo:xyzzy@localhost:$HGPORT/ test3
21 requesting all changes
21 requesting all changes
22 adding changesets
22 adding changesets
23 adding manifests
23 adding manifests
24 adding file changes
24 adding file changes
25 added 2 changesets with 2 changes to 1 files
25 added 2 changesets with 2 changes to 1 files
26 updating to branch default
26 updating to branch default
27 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
27 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 $ cat test3/.hg/hgrc
28 $ cat test3/.hg/hgrc
29 # example repository config (see 'hg help config' for more info)
29 # example repository config (see 'hg help config' for more info)
30 [paths]
30 [paths]
31 default = http://foo@localhost:$HGPORT/
31 default = http://foo@localhost:$HGPORT/
32
32
33 # path aliases to other clones of this repo in URLs or filesystem paths
33 # path aliases to other clones of this repo in URLs or filesystem paths
34 # (see 'hg help config.paths' for more info)
34 # (see 'hg help config.paths' for more info)
35 #
35 #
36 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
36 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
37 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
37 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
38 # my-clone = /home/jdoe/jdoes-clone
38 # my-clone = /home/jdoe/jdoes-clone
39
39
40 [ui]
40 [ui]
41 # name and email (local to this repository, optional), e.g.
41 # name and email (local to this repository, optional), e.g.
42 # username = Jane Doe <jdoe@example.com>
42 # username = Jane Doe <jdoe@example.com>
43 $ killdaemons.py
43 $ killdaemons.py
44
44
45 expect error, cloning not allowed
45 expect error, cloning not allowed
46
46
47 $ echo '[web]' > .hg/hgrc
47 $ echo '[web]' > .hg/hgrc
48 $ echo 'allowpull = false' >> .hg/hgrc
48 $ echo 'allowpull = false' >> .hg/hgrc
49 $ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
49 $ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
50 $ cat hg.pid >> $DAEMON_PIDS
50 $ cat hg.pid >> $DAEMON_PIDS
51 $ hg clone http://localhost:$HGPORT/ test4 # bundle2+
51 $ hg clone http://localhost:$HGPORT/ test4 # bundle2+
52 requesting all changes
52 requesting all changes
53 abort: authorization failed
53 abort: authorization failed
54 [255]
54 [255]
55 $ hg clone http://localhost:$HGPORT/ test4 --config devel.legacy.exchange=bundle1
55 $ hg clone http://localhost:$HGPORT/ test4 --config devel.legacy.exchange=bundle1
56 abort: authorization failed
56 abort: authorization failed
57 [255]
57 [255]
58 $ killdaemons.py
58 $ killdaemons.py
59
59
60 serve errors
60 serve errors
61
61
62 $ cat errors.log
62 $ cat errors.log
63 $ req() {
63 $ req() {
64 > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
64 > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
65 > cat hg.pid >> $DAEMON_PIDS
65 > cat hg.pid >> $DAEMON_PIDS
66 > hg --cwd ../test pull http://localhost:$HGPORT/
66 > hg --cwd ../test pull http://localhost:$HGPORT/
67 > killdaemons.py hg.pid
67 > killdaemons.py hg.pid
68 > echo % serve errors
68 > echo % serve errors
69 > cat errors.log
69 > cat errors.log
70 > }
70 > }
71
71
72 expect error, pulling not allowed
72 expect error, pulling not allowed
73
73
74 $ req
74 $ req
75 pulling from http://localhost:$HGPORT/
75 pulling from http://localhost:$HGPORT/
76 searching for changes
76 searching for changes
77 abort: authorization failed
77 abort: authorization failed
78 % serve errors
78 % serve errors
79
79
80 $ cd ..
80 $ cd ..
@@ -1,116 +1,116 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [alias]
2 > [alias]
3 > tlog = log --template "{rev}:{node|short}: '{desc}' {branches}\n"
3 > tlog = log --template "{rev}:{node|short}: '{desc}' {branches}\n"
4 > tglog = tlog -G
4 > tglog = tlog -G
5 > tout = out --template "{rev}:{node|short}: '{desc}' {branches}\n"
5 > tout = out --template "{rev}:{node|short}: '{desc}' {branches}\n"
6 > EOF
6 > EOF
7
7
8 $ hg init a
8 $ hg init a
9 $ cd a
9 $ cd a
10
10
11 $ echo a > a
11 $ echo a > a
12 $ hg ci -Aqm0
12 $ hg ci -Aqm0
13
13
14 $ echo foo >> a
14 $ echo foo >> a
15 $ hg ci -Aqm1
15 $ hg ci -Aqm1
16
16
17 $ hg up -q 0
17 $ hg up -q 0
18
18
19 $ hg branch stable
19 $ hg branch stable
20 marked working directory as branch stable
20 marked working directory as branch stable
21 (branches are permanent and global, did you want a bookmark?)
21 (branches are permanent and global, did you want a bookmark?)
22 $ echo bar >> a
22 $ echo bar >> a
23 $ hg ci -qm2
23 $ hg ci -qm2
24
24
25 $ hg tglog
25 $ hg tglog
26 @ 2:7bee6c3bea3a: '2' stable
26 @ 2:7bee6c3bea3a: '2' stable
27 |
27 |
28 | o 1:3560197d8331: '1'
28 | o 1:3560197d8331: '1'
29 |/
29 |/
30 o 0:f7b1eb17ad24: '0'
30 o 0:f7b1eb17ad24: '0'
31
31
32
32
33 $ cd ..
33 $ cd ..
34
34
35 $ hg clone -q a#stable b
35 $ hg clone -q a#stable b
36
36
37 $ cd b
37 $ cd b
38 $ cat .hg/hgrc
38 $ cat .hg/hgrc
39 # example repository config (see 'hg help config' for more info)
39 # example repository config (see 'hg help config' for more info)
40 [paths]
40 [paths]
41 default = $TESTTMP/a#stable (glob)
41 default = $TESTTMP/a#stable (glob)
42
42
43 # path aliases to other clones of this repo in URLs or filesystem paths
43 # path aliases to other clones of this repo in URLs or filesystem paths
44 # (see 'hg help config.paths' for more info)
44 # (see 'hg help config.paths' for more info)
45 #
45 #
46 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
46 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
47 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
47 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
48 # my-clone = /home/jdoe/jdoes-clone
48 # my-clone = /home/jdoe/jdoes-clone
49
49
50 [ui]
50 [ui]
51 # name and email (local to this repository, optional), e.g.
51 # name and email (local to this repository, optional), e.g.
52 # username = Jane Doe <jdoe@example.com>
52 # username = Jane Doe <jdoe@example.com>
53
53
54 $ echo red >> a
54 $ echo red >> a
55 $ hg ci -qm3
55 $ hg ci -qm3
56
56
57 $ hg up -q default
57 $ hg up -q default
58
58
59 $ echo blue >> a
59 $ echo blue >> a
60 $ hg ci -qm4
60 $ hg ci -qm4
61
61
62 $ hg tglog
62 $ hg tglog
63 @ 3:f0461977a3db: '4'
63 @ 3:f0461977a3db: '4'
64 |
64 |
65 | o 2:1d4099801a4e: '3' stable
65 | o 2:1d4099801a4e: '3' stable
66 | |
66 | |
67 | o 1:7bee6c3bea3a: '2' stable
67 | o 1:7bee6c3bea3a: '2' stable
68 |/
68 |/
69 o 0:f7b1eb17ad24: '0'
69 o 0:f7b1eb17ad24: '0'
70
70
71
71
72 $ hg tout
72 $ hg tout
73 comparing with $TESTTMP/a (glob)
73 comparing with $TESTTMP/a (glob)
74 searching for changes
74 searching for changes
75 2:1d4099801a4e: '3' stable
75 2:1d4099801a4e: '3' stable
76
76
77 $ hg tlog -r 'outgoing()'
77 $ hg tlog -r 'outgoing()'
78 2:1d4099801a4e: '3' stable
78 2:1d4099801a4e: '3' stable
79
79
80 $ hg tout ../a#default
80 $ hg tout ../a#default
81 comparing with ../a
81 comparing with ../a
82 searching for changes
82 searching for changes
83 3:f0461977a3db: '4'
83 3:f0461977a3db: '4'
84
84
85 $ hg tlog -r 'outgoing("../a#default")'
85 $ hg tlog -r 'outgoing("../a#default")'
86 3:f0461977a3db: '4'
86 3:f0461977a3db: '4'
87
87
88 $ echo "green = ../a#default" >> .hg/hgrc
88 $ echo "green = ../a#default" >> .hg/hgrc
89
89
90 $ cat .hg/hgrc
90 $ cat .hg/hgrc
91 # example repository config (see 'hg help config' for more info)
91 # example repository config (see 'hg help config' for more info)
92 [paths]
92 [paths]
93 default = $TESTTMP/a#stable (glob)
93 default = $TESTTMP/a#stable (glob)
94
94
95 # path aliases to other clones of this repo in URLs or filesystem paths
95 # path aliases to other clones of this repo in URLs or filesystem paths
96 # (see 'hg help config.paths' for more info)
96 # (see 'hg help config.paths' for more info)
97 #
97 #
98 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
98 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
99 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
99 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
100 # my-clone = /home/jdoe/jdoes-clone
100 # my-clone = /home/jdoe/jdoes-clone
101
101
102 [ui]
102 [ui]
103 # name and email (local to this repository, optional), e.g.
103 # name and email (local to this repository, optional), e.g.
104 # username = Jane Doe <jdoe@example.com>
104 # username = Jane Doe <jdoe@example.com>
105 green = ../a#default
105 green = ../a#default
106
106
107 $ hg tout green
107 $ hg tout green
108 comparing with green
108 comparing with green
109 abort: repository green not found!
109 abort: repository green not found!
110 [255]
110 [255]
111
111
112 $ hg tlog -r 'outgoing("green")'
112 $ hg tlog -r 'outgoing("green")'
113 abort: repository green not found!
113 abort: repository green not found!
114 [255]
114 [255]
115
115
116 $ cd ..
116 $ cd ..
@@ -1,1097 +1,1097 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extdiff]
2 > [extdiff]
3 > # for portability:
3 > # for portability:
4 > pdiff = sh "$RUNTESTDIR/pdiff"
4 > pdiff = sh "$RUNTESTDIR/pdiff"
5 > [progress]
5 > [progress]
6 > disable=False
6 > disable=False
7 > assume-tty = 1
7 > assume-tty = 1
8 > delay = 0
8 > delay = 0
9 > # set changedelay really large so we don't see nested topics
9 > # set changedelay really large so we don't see nested topics
10 > changedelay = 30000
10 > changedelay = 30000
11 > format = topic bar number
11 > format = topic bar number
12 > refresh = 0
12 > refresh = 0
13 > width = 60
13 > width = 60
14 > EOF
14 > EOF
15
15
16 Preparing the subrepository 'sub2'
16 Preparing the subrepository 'sub2'
17
17
18 $ hg init sub2
18 $ hg init sub2
19 $ echo sub2 > sub2/sub2
19 $ echo sub2 > sub2/sub2
20 $ hg add -R sub2
20 $ hg add -R sub2
21 adding sub2/sub2 (glob)
21 adding sub2/sub2 (glob)
22 $ hg commit -R sub2 -m "sub2 import"
22 $ hg commit -R sub2 -m "sub2 import"
23
23
24 Preparing the 'sub1' repo which depends on the subrepo 'sub2'
24 Preparing the 'sub1' repo which depends on the subrepo 'sub2'
25
25
26 $ hg init sub1
26 $ hg init sub1
27 $ echo sub1 > sub1/sub1
27 $ echo sub1 > sub1/sub1
28 $ echo "sub2 = ../sub2" > sub1/.hgsub
28 $ echo "sub2 = ../sub2" > sub1/.hgsub
29 $ hg clone sub2 sub1/sub2
29 $ hg clone sub2 sub1/sub2
30 \r (no-eol) (esc)
30 \r (no-eol) (esc)
31 linking [ <=> ] 1\r (no-eol) (esc)
31 linking [ <=> ] 1\r (no-eol) (esc)
32 linking [ <=> ] 2\r (no-eol) (esc)
32 linking [ <=> ] 2\r (no-eol) (esc)
33 linking [ <=> ] 3\r (no-eol) (esc)
33 linking [ <=> ] 3\r (no-eol) (esc)
34 linking [ <=> ] 4\r (no-eol) (esc)
34 linking [ <=> ] 4\r (no-eol) (esc)
35 linking [ <=> ] 5\r (no-eol) (esc)
35 linking [ <=> ] 5\r (no-eol) (esc)
36 linking [ <=> ] 6\r (no-eol) (esc)
36 linking [ <=> ] 6\r (no-eol) (esc)
37 \r (no-eol) (esc)
37 \r (no-eol) (esc)
38 \r (no-eol) (esc)
38 \r (no-eol) (esc)
39 updating [===========================================>] 1/1\r (no-eol) (esc)
39 updating [===========================================>] 1/1\r (no-eol) (esc)
40 \r (no-eol) (esc)
40 \r (no-eol) (esc)
41 updating to branch default
41 updating to branch default
42 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 $ hg add -R sub1
43 $ hg add -R sub1
44 adding sub1/.hgsub (glob)
44 adding sub1/.hgsub (glob)
45 adding sub1/sub1 (glob)
45 adding sub1/sub1 (glob)
46 $ hg commit -R sub1 -m "sub1 import"
46 $ hg commit -R sub1 -m "sub1 import"
47
47
48 Preparing the 'main' repo which depends on the subrepo 'sub1'
48 Preparing the 'main' repo which depends on the subrepo 'sub1'
49
49
50 $ hg init main
50 $ hg init main
51 $ echo main > main/main
51 $ echo main > main/main
52 $ echo "sub1 = ../sub1" > main/.hgsub
52 $ echo "sub1 = ../sub1" > main/.hgsub
53 $ hg clone sub1 main/sub1
53 $ hg clone sub1 main/sub1
54 \r (no-eol) (esc)
54 \r (no-eol) (esc)
55 linking [ <=> ] 1\r (no-eol) (esc)
55 linking [ <=> ] 1\r (no-eol) (esc)
56 linking [ <=> ] 2\r (no-eol) (esc)
56 linking [ <=> ] 2\r (no-eol) (esc)
57 linking [ <=> ] 3\r (no-eol) (esc)
57 linking [ <=> ] 3\r (no-eol) (esc)
58 linking [ <=> ] 4\r (no-eol) (esc)
58 linking [ <=> ] 4\r (no-eol) (esc)
59 linking [ <=> ] 5\r (no-eol) (esc)
59 linking [ <=> ] 5\r (no-eol) (esc)
60 linking [ <=> ] 6\r (no-eol) (esc)
60 linking [ <=> ] 6\r (no-eol) (esc)
61 linking [ <=> ] 7\r (no-eol) (esc)
61 linking [ <=> ] 7\r (no-eol) (esc)
62 linking [ <=> ] 8\r (no-eol) (esc)
62 linking [ <=> ] 8\r (no-eol) (esc)
63 \r (no-eol) (esc)
63 \r (no-eol) (esc)
64 \r (no-eol) (esc)
64 \r (no-eol) (esc)
65 updating [===========================================>] 3/3\r (no-eol) (esc)
65 updating [===========================================>] 3/3\r (no-eol) (esc)
66 updating [===========================================>] 1/1\r (no-eol) (esc)
66 updating [===========================================>] 1/1\r (no-eol) (esc)
67 \r (no-eol) (esc)
67 \r (no-eol) (esc)
68 updating to branch default
68 updating to branch default
69 cloning subrepo sub2 from $TESTTMP/sub2
69 cloning subrepo sub2 from $TESTTMP/sub2
70 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
71 $ hg add -R main
71 $ hg add -R main
72 adding main/.hgsub (glob)
72 adding main/.hgsub (glob)
73 adding main/main (glob)
73 adding main/main (glob)
74 $ hg commit -R main -m "main import"
74 $ hg commit -R main -m "main import"
75
75
76 Cleaning both repositories, just as a clone -U
76 Cleaning both repositories, just as a clone -U
77
77
78 $ hg up -C -R sub2 null
78 $ hg up -C -R sub2 null
79 \r (no-eol) (esc)
79 \r (no-eol) (esc)
80 updating [===========================================>] 1/1\r (no-eol) (esc)
80 updating [===========================================>] 1/1\r (no-eol) (esc)
81 \r (no-eol) (esc)
81 \r (no-eol) (esc)
82 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
82 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
83 $ hg up -C -R sub1 null
83 $ hg up -C -R sub1 null
84 \r (no-eol) (esc)
84 \r (no-eol) (esc)
85 updating [===========================================>] 1/1\r (no-eol) (esc)
85 updating [===========================================>] 1/1\r (no-eol) (esc)
86 \r (no-eol) (esc)
86 \r (no-eol) (esc)
87 \r (no-eol) (esc)
87 \r (no-eol) (esc)
88 updating [===========================================>] 3/3\r (no-eol) (esc)
88 updating [===========================================>] 3/3\r (no-eol) (esc)
89 \r (no-eol) (esc)
89 \r (no-eol) (esc)
90 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
90 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
91 $ hg up -C -R main null
91 $ hg up -C -R main null
92 \r (no-eol) (esc)
92 \r (no-eol) (esc)
93 updating [===========================================>] 1/1\r (no-eol) (esc)
93 updating [===========================================>] 1/1\r (no-eol) (esc)
94 \r (no-eol) (esc)
94 \r (no-eol) (esc)
95 \r (no-eol) (esc)
95 \r (no-eol) (esc)
96 updating [===========================================>] 3/3\r (no-eol) (esc)
96 updating [===========================================>] 3/3\r (no-eol) (esc)
97 \r (no-eol) (esc)
97 \r (no-eol) (esc)
98 \r (no-eol) (esc)
98 \r (no-eol) (esc)
99 updating [===========================================>] 3/3\r (no-eol) (esc)
99 updating [===========================================>] 3/3\r (no-eol) (esc)
100 \r (no-eol) (esc)
100 \r (no-eol) (esc)
101 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
101 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
102 $ rm -rf main/sub1
102 $ rm -rf main/sub1
103 $ rm -rf sub1/sub2
103 $ rm -rf sub1/sub2
104
104
105 Clone main
105 Clone main
106
106
107 $ hg --config extensions.largefiles= clone main cloned
107 $ hg --config extensions.largefiles= clone main cloned
108 \r (no-eol) (esc)
108 \r (no-eol) (esc)
109 linking [ <=> ] 1\r (no-eol) (esc)
109 linking [ <=> ] 1\r (no-eol) (esc)
110 linking [ <=> ] 2\r (no-eol) (esc)
110 linking [ <=> ] 2\r (no-eol) (esc)
111 linking [ <=> ] 3\r (no-eol) (esc)
111 linking [ <=> ] 3\r (no-eol) (esc)
112 linking [ <=> ] 4\r (no-eol) (esc)
112 linking [ <=> ] 4\r (no-eol) (esc)
113 linking [ <=> ] 5\r (no-eol) (esc)
113 linking [ <=> ] 5\r (no-eol) (esc)
114 linking [ <=> ] 6\r (no-eol) (esc)
114 linking [ <=> ] 6\r (no-eol) (esc)
115 linking [ <=> ] 7\r (no-eol) (esc)
115 linking [ <=> ] 7\r (no-eol) (esc)
116 linking [ <=> ] 8\r (no-eol) (esc)
116 linking [ <=> ] 8\r (no-eol) (esc)
117 \r (no-eol) (esc)
117 \r (no-eol) (esc)
118 \r (no-eol) (esc)
118 \r (no-eol) (esc)
119 updating [===========================================>] 3/3\r (no-eol) (esc)
119 updating [===========================================>] 3/3\r (no-eol) (esc)
120 updating [===========================================>] 3/3\r (no-eol) (esc)
120 updating [===========================================>] 3/3\r (no-eol) (esc)
121 updating [===========================================>] 1/1\r (no-eol) (esc)
121 updating [===========================================>] 1/1\r (no-eol) (esc)
122 \r (no-eol) (esc)
122 \r (no-eol) (esc)
123 updating to branch default
123 updating to branch default
124 cloning subrepo sub1 from $TESTTMP/sub1
124 cloning subrepo sub1 from $TESTTMP/sub1
125 cloning subrepo sub1/sub2 from $TESTTMP/sub2 (glob)
125 cloning subrepo sub1/sub2 from $TESTTMP/sub2 (glob)
126 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
127
127
128 Largefiles is NOT enabled in the clone if the source repo doesn't require it
128 Largefiles is NOT enabled in the clone if the source repo doesn't require it
129 $ cat cloned/.hg/hgrc
129 $ cat cloned/.hg/hgrc
130 # example repository config (see 'hg help config' for more info)
130 # example repository config (see 'hg help config' for more info)
131 [paths]
131 [paths]
132 default = $TESTTMP/main (glob)
132 default = $TESTTMP/main (glob)
133
133
134 # path aliases to other clones of this repo in URLs or filesystem paths
134 # path aliases to other clones of this repo in URLs or filesystem paths
135 # (see 'hg help config.paths' for more info)
135 # (see 'hg help config.paths' for more info)
136 #
136 #
137 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
137 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
138 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
138 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
139 # my-clone = /home/jdoe/jdoes-clone
139 # my-clone = /home/jdoe/jdoes-clone
140
140
141 [ui]
141 [ui]
142 # name and email (local to this repository, optional), e.g.
142 # name and email (local to this repository, optional), e.g.
143 # username = Jane Doe <jdoe@example.com>
143 # username = Jane Doe <jdoe@example.com>
144
144
145 Checking cloned repo ids
145 Checking cloned repo ids
146
146
147 $ printf "cloned " ; hg id -R cloned
147 $ printf "cloned " ; hg id -R cloned
148 cloned 7f491f53a367 tip
148 cloned 7f491f53a367 tip
149 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
149 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
150 cloned/sub1 fc3b4ce2696f tip
150 cloned/sub1 fc3b4ce2696f tip
151 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
151 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
152 cloned/sub1/sub2 c57a0840e3ba tip
152 cloned/sub1/sub2 c57a0840e3ba tip
153
153
154 debugsub output for main and sub1
154 debugsub output for main and sub1
155
155
156 $ hg debugsub -R cloned
156 $ hg debugsub -R cloned
157 path sub1
157 path sub1
158 source ../sub1
158 source ../sub1
159 revision fc3b4ce2696f7741438c79207583768f2ce6b0dd
159 revision fc3b4ce2696f7741438c79207583768f2ce6b0dd
160 $ hg debugsub -R cloned/sub1
160 $ hg debugsub -R cloned/sub1
161 path sub2
161 path sub2
162 source ../sub2
162 source ../sub2
163 revision c57a0840e3badd667ef3c3ef65471609acb2ba3c
163 revision c57a0840e3badd667ef3c3ef65471609acb2ba3c
164
164
165 Modifying deeply nested 'sub2'
165 Modifying deeply nested 'sub2'
166
166
167 $ echo modified > cloned/sub1/sub2/sub2
167 $ echo modified > cloned/sub1/sub2/sub2
168 $ hg commit --subrepos -m "deep nested modif should trigger a commit" -R cloned
168 $ hg commit --subrepos -m "deep nested modif should trigger a commit" -R cloned
169 committing subrepository sub1
169 committing subrepository sub1
170 committing subrepository sub1/sub2 (glob)
170 committing subrepository sub1/sub2 (glob)
171
171
172 Checking modified node ids
172 Checking modified node ids
173
173
174 $ printf "cloned " ; hg id -R cloned
174 $ printf "cloned " ; hg id -R cloned
175 cloned ffe6649062fe tip
175 cloned ffe6649062fe tip
176 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
176 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
177 cloned/sub1 2ecb03bf44a9 tip
177 cloned/sub1 2ecb03bf44a9 tip
178 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
178 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
179 cloned/sub1/sub2 53dd3430bcaf tip
179 cloned/sub1/sub2 53dd3430bcaf tip
180
180
181 debugsub output for main and sub1
181 debugsub output for main and sub1
182
182
183 $ hg debugsub -R cloned
183 $ hg debugsub -R cloned
184 path sub1
184 path sub1
185 source ../sub1
185 source ../sub1
186 revision 2ecb03bf44a94e749e8669481dd9069526ce7cb9
186 revision 2ecb03bf44a94e749e8669481dd9069526ce7cb9
187 $ hg debugsub -R cloned/sub1
187 $ hg debugsub -R cloned/sub1
188 path sub2
188 path sub2
189 source ../sub2
189 source ../sub2
190 revision 53dd3430bcaf5ab4a7c48262bcad6d441f510487
190 revision 53dd3430bcaf5ab4a7c48262bcad6d441f510487
191
191
192 Check that deep archiving works
192 Check that deep archiving works
193
193
194 $ cd cloned
194 $ cd cloned
195 $ echo 'test' > sub1/sub2/test.txt
195 $ echo 'test' > sub1/sub2/test.txt
196 $ hg --config extensions.largefiles=! add sub1/sub2/test.txt
196 $ hg --config extensions.largefiles=! add sub1/sub2/test.txt
197 $ mkdir sub1/sub2/folder
197 $ mkdir sub1/sub2/folder
198 $ echo 'subfolder' > sub1/sub2/folder/test.txt
198 $ echo 'subfolder' > sub1/sub2/folder/test.txt
199 $ hg ci -ASm "add test.txt"
199 $ hg ci -ASm "add test.txt"
200 adding sub1/sub2/folder/test.txt
200 adding sub1/sub2/folder/test.txt
201 committing subrepository sub1
201 committing subrepository sub1
202 committing subrepository sub1/sub2 (glob)
202 committing subrepository sub1/sub2 (glob)
203
203
204 .. but first take a detour through some deep removal testing
204 .. but first take a detour through some deep removal testing
205
205
206 $ hg remove -S -I 're:.*.txt' .
206 $ hg remove -S -I 're:.*.txt' .
207 \r (no-eol) (esc)
207 \r (no-eol) (esc)
208 searching [==========================================>] 1/1\r (no-eol) (esc)
208 searching [==========================================>] 1/1\r (no-eol) (esc)
209 searching [==========================================>] 1/1\r (no-eol) (esc)
209 searching [==========================================>] 1/1\r (no-eol) (esc)
210 \r (no-eol) (esc)
210 \r (no-eol) (esc)
211 \r (no-eol) (esc)
211 \r (no-eol) (esc)
212 deleting [=====================> ] 1/2\r (no-eol) (esc)
212 deleting [=====================> ] 1/2\r (no-eol) (esc)
213 \r (no-eol) (esc)
213 \r (no-eol) (esc)
214 \r (no-eol) (esc)
214 \r (no-eol) (esc)
215 deleting [===========================================>] 2/2\r (no-eol) (esc)
215 deleting [===========================================>] 2/2\r (no-eol) (esc)
216 \r (no-eol) (esc)
216 \r (no-eol) (esc)
217 removing sub1/sub2/folder/test.txt (glob)
217 removing sub1/sub2/folder/test.txt (glob)
218 removing sub1/sub2/test.txt (glob)
218 removing sub1/sub2/test.txt (glob)
219 $ hg status -S
219 $ hg status -S
220 R sub1/sub2/folder/test.txt
220 R sub1/sub2/folder/test.txt
221 R sub1/sub2/test.txt
221 R sub1/sub2/test.txt
222 $ hg update -Cq
222 $ hg update -Cq
223 $ hg remove -I 're:.*.txt' sub1
223 $ hg remove -I 're:.*.txt' sub1
224 \r (no-eol) (esc)
224 \r (no-eol) (esc)
225 searching [==========================================>] 1/1\r (no-eol) (esc)
225 searching [==========================================>] 1/1\r (no-eol) (esc)
226 \r (no-eol) (esc)
226 \r (no-eol) (esc)
227 \r (no-eol) (esc)
227 \r (no-eol) (esc)
228 deleting [===========================================>] 1/1\r (no-eol) (esc)
228 deleting [===========================================>] 1/1\r (no-eol) (esc)
229 \r (no-eol) (esc)
229 \r (no-eol) (esc)
230 $ hg status -S
230 $ hg status -S
231 $ hg remove sub1/sub2/folder/test.txt
231 $ hg remove sub1/sub2/folder/test.txt
232 \r (no-eol) (esc)
232 \r (no-eol) (esc)
233 searching [==========================================>] 1/1\r (no-eol) (esc)
233 searching [==========================================>] 1/1\r (no-eol) (esc)
234 searching [==========================================>] 1/1\r (no-eol) (esc)
234 searching [==========================================>] 1/1\r (no-eol) (esc)
235 \r (no-eol) (esc)
235 \r (no-eol) (esc)
236 \r (no-eol) (esc)
236 \r (no-eol) (esc)
237 deleting [===========================================>] 1/1\r (no-eol) (esc)
237 deleting [===========================================>] 1/1\r (no-eol) (esc)
238 \r (no-eol) (esc)
238 \r (no-eol) (esc)
239 \r (no-eol) (esc)
239 \r (no-eol) (esc)
240 deleting [===========================================>] 1/1\r (no-eol) (esc)
240 deleting [===========================================>] 1/1\r (no-eol) (esc)
241 \r (no-eol) (esc)
241 \r (no-eol) (esc)
242 \r (no-eol) (esc)
242 \r (no-eol) (esc)
243 deleting [===========================================>] 1/1\r (no-eol) (esc)
243 deleting [===========================================>] 1/1\r (no-eol) (esc)
244 \r (no-eol) (esc)
244 \r (no-eol) (esc)
245 $ hg remove sub1/.hgsubstate
245 $ hg remove sub1/.hgsubstate
246 \r (no-eol) (esc)
246 \r (no-eol) (esc)
247 searching [==========================================>] 1/1\r (no-eol) (esc)
247 searching [==========================================>] 1/1\r (no-eol) (esc)
248 \r (no-eol) (esc)
248 \r (no-eol) (esc)
249 \r (no-eol) (esc)
249 \r (no-eol) (esc)
250 deleting [===========================================>] 1/1\r (no-eol) (esc)
250 deleting [===========================================>] 1/1\r (no-eol) (esc)
251 \r (no-eol) (esc)
251 \r (no-eol) (esc)
252 \r (no-eol) (esc)
252 \r (no-eol) (esc)
253 deleting [===========================================>] 1/1\r (no-eol) (esc)
253 deleting [===========================================>] 1/1\r (no-eol) (esc)
254 \r (no-eol) (esc)
254 \r (no-eol) (esc)
255 $ mv sub1/.hgsub sub1/x.hgsub
255 $ mv sub1/.hgsub sub1/x.hgsub
256 $ hg status -S
256 $ hg status -S
257 warning: subrepo spec file 'sub1/.hgsub' not found
257 warning: subrepo spec file 'sub1/.hgsub' not found
258 R sub1/.hgsubstate
258 R sub1/.hgsubstate
259 R sub1/sub2/folder/test.txt
259 R sub1/sub2/folder/test.txt
260 ! sub1/.hgsub
260 ! sub1/.hgsub
261 ? sub1/x.hgsub
261 ? sub1/x.hgsub
262 $ mv sub1/x.hgsub sub1/.hgsub
262 $ mv sub1/x.hgsub sub1/.hgsub
263 $ hg update -Cq
263 $ hg update -Cq
264 $ touch sub1/foo
264 $ touch sub1/foo
265 $ hg forget sub1/sub2/folder/test.txt
265 $ hg forget sub1/sub2/folder/test.txt
266 $ rm sub1/sub2/test.txt
266 $ rm sub1/sub2/test.txt
267
267
268 Test relative path printing + subrepos
268 Test relative path printing + subrepos
269 $ mkdir -p foo/bar
269 $ mkdir -p foo/bar
270 $ cd foo
270 $ cd foo
271 $ touch bar/abc
271 $ touch bar/abc
272 $ hg addremove -S ..
272 $ hg addremove -S ..
273 \r (no-eol) (esc)
273 \r (no-eol) (esc)
274 searching for exact renames [ ] 0/1\r (no-eol) (esc)
274 searching for exact renames [ ] 0/1\r (no-eol) (esc)
275 \r (no-eol) (esc)
275 \r (no-eol) (esc)
276 adding ../sub1/sub2/folder/test.txt (glob)
276 adding ../sub1/sub2/folder/test.txt (glob)
277 removing ../sub1/sub2/test.txt (glob)
277 removing ../sub1/sub2/test.txt (glob)
278 adding ../sub1/foo (glob)
278 adding ../sub1/foo (glob)
279 adding bar/abc (glob)
279 adding bar/abc (glob)
280 $ cd ..
280 $ cd ..
281 $ hg status -S
281 $ hg status -S
282 A foo/bar/abc
282 A foo/bar/abc
283 A sub1/foo
283 A sub1/foo
284 R sub1/sub2/test.txt
284 R sub1/sub2/test.txt
285
285
286 Archive wdir() with subrepos
286 Archive wdir() with subrepos
287 $ hg rm main
287 $ hg rm main
288 \r (no-eol) (esc)
288 \r (no-eol) (esc)
289 deleting [===========================================>] 1/1\r (no-eol) (esc)
289 deleting [===========================================>] 1/1\r (no-eol) (esc)
290 \r (no-eol) (esc)
290 \r (no-eol) (esc)
291 $ hg archive -S -r 'wdir()' ../wdir
291 $ hg archive -S -r 'wdir()' ../wdir
292 \r (no-eol) (esc)
292 \r (no-eol) (esc)
293 archiving [ ] 0/3\r (no-eol) (esc)
293 archiving [ ] 0/3\r (no-eol) (esc)
294 archiving [=============> ] 1/3\r (no-eol) (esc)
294 archiving [=============> ] 1/3\r (no-eol) (esc)
295 archiving [===========================> ] 2/3\r (no-eol) (esc)
295 archiving [===========================> ] 2/3\r (no-eol) (esc)
296 archiving [==========================================>] 3/3\r (no-eol) (esc)
296 archiving [==========================================>] 3/3\r (no-eol) (esc)
297 \r (no-eol) (esc)
297 \r (no-eol) (esc)
298 \r (no-eol) (esc)
298 \r (no-eol) (esc)
299 archiving (sub1) [ ] 0/4\r (no-eol) (esc)
299 archiving (sub1) [ ] 0/4\r (no-eol) (esc)
300 archiving (sub1) [========> ] 1/4\r (no-eol) (esc)
300 archiving (sub1) [========> ] 1/4\r (no-eol) (esc)
301 archiving (sub1) [=================> ] 2/4\r (no-eol) (esc)
301 archiving (sub1) [=================> ] 2/4\r (no-eol) (esc)
302 archiving (sub1) [==========================> ] 3/4\r (no-eol) (esc)
302 archiving (sub1) [==========================> ] 3/4\r (no-eol) (esc)
303 archiving (sub1) [===================================>] 4/4\r (no-eol) (esc)
303 archiving (sub1) [===================================>] 4/4\r (no-eol) (esc)
304 \r (no-eol) (esc)
304 \r (no-eol) (esc)
305 \r (no-eol) (esc)
305 \r (no-eol) (esc)
306 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (glob) (esc)
306 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (glob) (esc)
307 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (glob) (esc)
307 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (glob) (esc)
308 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (glob) (esc)
308 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (glob) (esc)
309 \r (no-eol) (esc)
309 \r (no-eol) (esc)
310 $ diff -r . ../wdir | egrep -v '\.hg$|^Common subdirectories:'
310 $ diff -r . ../wdir | egrep -v '\.hg$|^Common subdirectories:'
311 Only in ../wdir: .hg_archival.txt
311 Only in ../wdir: .hg_archival.txt
312
312
313 $ find ../wdir -type f | sort
313 $ find ../wdir -type f | sort
314 ../wdir/.hg_archival.txt
314 ../wdir/.hg_archival.txt
315 ../wdir/.hgsub
315 ../wdir/.hgsub
316 ../wdir/.hgsubstate
316 ../wdir/.hgsubstate
317 ../wdir/foo/bar/abc
317 ../wdir/foo/bar/abc
318 ../wdir/sub1/.hgsub
318 ../wdir/sub1/.hgsub
319 ../wdir/sub1/.hgsubstate
319 ../wdir/sub1/.hgsubstate
320 ../wdir/sub1/foo
320 ../wdir/sub1/foo
321 ../wdir/sub1/sub1
321 ../wdir/sub1/sub1
322 ../wdir/sub1/sub2/folder/test.txt
322 ../wdir/sub1/sub2/folder/test.txt
323 ../wdir/sub1/sub2/sub2
323 ../wdir/sub1/sub2/sub2
324
324
325 $ cat ../wdir/.hg_archival.txt
325 $ cat ../wdir/.hg_archival.txt
326 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
326 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
327 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
327 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
328 branch: default
328 branch: default
329 latesttag: null
329 latesttag: null
330 latesttagdistance: 4
330 latesttagdistance: 4
331 changessincelatesttag: 4
331 changessincelatesttag: 4
332
332
333 Attempting to archive 'wdir()' with a missing file is handled gracefully
333 Attempting to archive 'wdir()' with a missing file is handled gracefully
334 $ rm sub1/sub1
334 $ rm sub1/sub1
335 $ rm -r ../wdir
335 $ rm -r ../wdir
336 $ hg archive -v -S -r 'wdir()' ../wdir
336 $ hg archive -v -S -r 'wdir()' ../wdir
337 \r (no-eol) (esc)
337 \r (no-eol) (esc)
338 archiving [ ] 0/3\r (no-eol) (esc)
338 archiving [ ] 0/3\r (no-eol) (esc)
339 archiving [=============> ] 1/3\r (no-eol) (esc)
339 archiving [=============> ] 1/3\r (no-eol) (esc)
340 archiving [===========================> ] 2/3\r (no-eol) (esc)
340 archiving [===========================> ] 2/3\r (no-eol) (esc)
341 archiving [==========================================>] 3/3\r (no-eol) (esc)
341 archiving [==========================================>] 3/3\r (no-eol) (esc)
342 \r (no-eol) (esc)
342 \r (no-eol) (esc)
343 \r (no-eol) (esc)
343 \r (no-eol) (esc)
344 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
344 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
345 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
345 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
346 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
346 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
347 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
347 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
348 \r (no-eol) (esc)
348 \r (no-eol) (esc)
349 \r (no-eol) (esc)
349 \r (no-eol) (esc)
350 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (glob) (esc)
350 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (glob) (esc)
351 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (glob) (esc)
351 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (glob) (esc)
352 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (glob) (esc)
352 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (glob) (esc)
353 \r (no-eol) (esc)
353 \r (no-eol) (esc)
354 $ find ../wdir -type f | sort
354 $ find ../wdir -type f | sort
355 ../wdir/.hg_archival.txt
355 ../wdir/.hg_archival.txt
356 ../wdir/.hgsub
356 ../wdir/.hgsub
357 ../wdir/.hgsubstate
357 ../wdir/.hgsubstate
358 ../wdir/foo/bar/abc
358 ../wdir/foo/bar/abc
359 ../wdir/sub1/.hgsub
359 ../wdir/sub1/.hgsub
360 ../wdir/sub1/.hgsubstate
360 ../wdir/sub1/.hgsubstate
361 ../wdir/sub1/foo
361 ../wdir/sub1/foo
362 ../wdir/sub1/sub2/folder/test.txt
362 ../wdir/sub1/sub2/folder/test.txt
363 ../wdir/sub1/sub2/sub2
363 ../wdir/sub1/sub2/sub2
364
364
365 Continue relative path printing + subrepos
365 Continue relative path printing + subrepos
366 $ hg update -Cq
366 $ hg update -Cq
367 $ rm -r ../wdir
367 $ rm -r ../wdir
368 $ hg archive -S -r 'wdir()' ../wdir
368 $ hg archive -S -r 'wdir()' ../wdir
369 \r (no-eol) (esc)
369 \r (no-eol) (esc)
370 archiving [ ] 0/3\r (no-eol) (esc)
370 archiving [ ] 0/3\r (no-eol) (esc)
371 archiving [=============> ] 1/3\r (no-eol) (esc)
371 archiving [=============> ] 1/3\r (no-eol) (esc)
372 archiving [===========================> ] 2/3\r (no-eol) (esc)
372 archiving [===========================> ] 2/3\r (no-eol) (esc)
373 archiving [==========================================>] 3/3\r (no-eol) (esc)
373 archiving [==========================================>] 3/3\r (no-eol) (esc)
374 \r (no-eol) (esc)
374 \r (no-eol) (esc)
375 \r (no-eol) (esc)
375 \r (no-eol) (esc)
376 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
376 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
377 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
377 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
378 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
378 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
379 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
379 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
380 \r (no-eol) (esc)
380 \r (no-eol) (esc)
381 \r (no-eol) (esc)
381 \r (no-eol) (esc)
382 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (glob) (esc)
382 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (glob) (esc)
383 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (glob) (esc)
383 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (glob) (esc)
384 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (glob) (esc)
384 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (glob) (esc)
385 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (glob) (esc)
385 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (glob) (esc)
386 \r (no-eol) (esc)
386 \r (no-eol) (esc)
387 $ cat ../wdir/.hg_archival.txt
387 $ cat ../wdir/.hg_archival.txt
388 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
388 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
389 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd
389 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd
390 branch: default
390 branch: default
391 latesttag: null
391 latesttag: null
392 latesttagdistance: 4
392 latesttagdistance: 4
393 changessincelatesttag: 4
393 changessincelatesttag: 4
394
394
395 $ touch sub1/sub2/folder/bar
395 $ touch sub1/sub2/folder/bar
396 $ hg addremove sub1/sub2
396 $ hg addremove sub1/sub2
397 adding sub1/sub2/folder/bar (glob)
397 adding sub1/sub2/folder/bar (glob)
398 $ hg status -S
398 $ hg status -S
399 A sub1/sub2/folder/bar
399 A sub1/sub2/folder/bar
400 ? foo/bar/abc
400 ? foo/bar/abc
401 ? sub1/foo
401 ? sub1/foo
402 $ hg update -Cq
402 $ hg update -Cq
403 $ hg addremove sub1
403 $ hg addremove sub1
404 adding sub1/sub2/folder/bar (glob)
404 adding sub1/sub2/folder/bar (glob)
405 adding sub1/foo (glob)
405 adding sub1/foo (glob)
406 $ hg update -Cq
406 $ hg update -Cq
407 $ rm sub1/sub2/folder/test.txt
407 $ rm sub1/sub2/folder/test.txt
408 $ rm sub1/sub2/test.txt
408 $ rm sub1/sub2/test.txt
409 $ hg ci -ASm "remove test.txt"
409 $ hg ci -ASm "remove test.txt"
410 adding sub1/sub2/folder/bar
410 adding sub1/sub2/folder/bar
411 removing sub1/sub2/folder/test.txt
411 removing sub1/sub2/folder/test.txt
412 removing sub1/sub2/test.txt
412 removing sub1/sub2/test.txt
413 adding sub1/foo
413 adding sub1/foo
414 adding foo/bar/abc
414 adding foo/bar/abc
415 committing subrepository sub1
415 committing subrepository sub1
416 committing subrepository sub1/sub2 (glob)
416 committing subrepository sub1/sub2 (glob)
417
417
418 $ hg forget sub1/sub2/sub2
418 $ hg forget sub1/sub2/sub2
419 $ echo x > sub1/sub2/x.txt
419 $ echo x > sub1/sub2/x.txt
420 $ hg add sub1/sub2/x.txt
420 $ hg add sub1/sub2/x.txt
421
421
422 Files sees uncommitted adds and removes in subrepos
422 Files sees uncommitted adds and removes in subrepos
423 $ hg files -S
423 $ hg files -S
424 .hgsub
424 .hgsub
425 .hgsubstate
425 .hgsubstate
426 foo/bar/abc (glob)
426 foo/bar/abc (glob)
427 main
427 main
428 sub1/.hgsub (glob)
428 sub1/.hgsub (glob)
429 sub1/.hgsubstate (glob)
429 sub1/.hgsubstate (glob)
430 sub1/foo (glob)
430 sub1/foo (glob)
431 sub1/sub1 (glob)
431 sub1/sub1 (glob)
432 sub1/sub2/folder/bar (glob)
432 sub1/sub2/folder/bar (glob)
433 sub1/sub2/x.txt (glob)
433 sub1/sub2/x.txt (glob)
434
434
435 $ hg files -S "set:eol('dos') or eol('unix') or size('<= 0')"
435 $ hg files -S "set:eol('dos') or eol('unix') or size('<= 0')"
436 .hgsub
436 .hgsub
437 .hgsubstate
437 .hgsubstate
438 foo/bar/abc (glob)
438 foo/bar/abc (glob)
439 main
439 main
440 sub1/.hgsub (glob)
440 sub1/.hgsub (glob)
441 sub1/.hgsubstate (glob)
441 sub1/.hgsubstate (glob)
442 sub1/foo (glob)
442 sub1/foo (glob)
443 sub1/sub1 (glob)
443 sub1/sub1 (glob)
444 sub1/sub2/folder/bar (glob)
444 sub1/sub2/folder/bar (glob)
445 sub1/sub2/x.txt (glob)
445 sub1/sub2/x.txt (glob)
446
446
447 $ hg files -r '.^' -S "set:eol('dos') or eol('unix')"
447 $ hg files -r '.^' -S "set:eol('dos') or eol('unix')"
448 .hgsub
448 .hgsub
449 .hgsubstate
449 .hgsubstate
450 main
450 main
451 sub1/.hgsub (glob)
451 sub1/.hgsub (glob)
452 sub1/.hgsubstate (glob)
452 sub1/.hgsubstate (glob)
453 sub1/sub1 (glob)
453 sub1/sub1 (glob)
454 sub1/sub2/folder/test.txt (glob)
454 sub1/sub2/folder/test.txt (glob)
455 sub1/sub2/sub2 (glob)
455 sub1/sub2/sub2 (glob)
456 sub1/sub2/test.txt (glob)
456 sub1/sub2/test.txt (glob)
457
457
458 $ hg files sub1
458 $ hg files sub1
459 sub1/.hgsub (glob)
459 sub1/.hgsub (glob)
460 sub1/.hgsubstate (glob)
460 sub1/.hgsubstate (glob)
461 sub1/foo (glob)
461 sub1/foo (glob)
462 sub1/sub1 (glob)
462 sub1/sub1 (glob)
463 sub1/sub2/folder/bar (glob)
463 sub1/sub2/folder/bar (glob)
464 sub1/sub2/x.txt (glob)
464 sub1/sub2/x.txt (glob)
465
465
466 $ hg files sub1/sub2
466 $ hg files sub1/sub2
467 sub1/sub2/folder/bar (glob)
467 sub1/sub2/folder/bar (glob)
468 sub1/sub2/x.txt (glob)
468 sub1/sub2/x.txt (glob)
469
469
470 $ hg files
470 $ hg files
471 .hgsub
471 .hgsub
472 .hgsubstate
472 .hgsubstate
473 foo/bar/abc (glob)
473 foo/bar/abc (glob)
474 main
474 main
475
475
476 $ hg files -S -r '.^' sub1/sub2/folder
476 $ hg files -S -r '.^' sub1/sub2/folder
477 sub1/sub2/folder/test.txt (glob)
477 sub1/sub2/folder/test.txt (glob)
478
478
479 $ hg files -S -r '.^' sub1/sub2/missing
479 $ hg files -S -r '.^' sub1/sub2/missing
480 sub1/sub2/missing: no such file in rev 78026e779ea6 (glob)
480 sub1/sub2/missing: no such file in rev 78026e779ea6 (glob)
481 [1]
481 [1]
482
482
483 $ hg files -r '.^' sub1/
483 $ hg files -r '.^' sub1/
484 sub1/.hgsub (glob)
484 sub1/.hgsub (glob)
485 sub1/.hgsubstate (glob)
485 sub1/.hgsubstate (glob)
486 sub1/sub1 (glob)
486 sub1/sub1 (glob)
487 sub1/sub2/folder/test.txt (glob)
487 sub1/sub2/folder/test.txt (glob)
488 sub1/sub2/sub2 (glob)
488 sub1/sub2/sub2 (glob)
489 sub1/sub2/test.txt (glob)
489 sub1/sub2/test.txt (glob)
490
490
491 $ hg files -r '.^' sub1/sub2
491 $ hg files -r '.^' sub1/sub2
492 sub1/sub2/folder/test.txt (glob)
492 sub1/sub2/folder/test.txt (glob)
493 sub1/sub2/sub2 (glob)
493 sub1/sub2/sub2 (glob)
494 sub1/sub2/test.txt (glob)
494 sub1/sub2/test.txt (glob)
495
495
496 $ hg rollback -q
496 $ hg rollback -q
497 $ hg up -Cq
497 $ hg up -Cq
498
498
499 $ hg --config extensions.largefiles=! archive -S ../archive_all
499 $ hg --config extensions.largefiles=! archive -S ../archive_all
500 \r (no-eol) (esc)
500 \r (no-eol) (esc)
501 archiving [ ] 0/3\r (no-eol) (esc)
501 archiving [ ] 0/3\r (no-eol) (esc)
502 archiving [=============> ] 1/3\r (no-eol) (esc)
502 archiving [=============> ] 1/3\r (no-eol) (esc)
503 archiving [===========================> ] 2/3\r (no-eol) (esc)
503 archiving [===========================> ] 2/3\r (no-eol) (esc)
504 archiving [==========================================>] 3/3\r (no-eol) (esc)
504 archiving [==========================================>] 3/3\r (no-eol) (esc)
505 \r (no-eol) (esc)
505 \r (no-eol) (esc)
506 \r (no-eol) (esc)
506 \r (no-eol) (esc)
507 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
507 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
508 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
508 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
509 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
509 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
510 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
510 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
511 \r (no-eol) (esc)
511 \r (no-eol) (esc)
512 \r (no-eol) (esc)
512 \r (no-eol) (esc)
513 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (glob) (esc)
513 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (glob) (esc)
514 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (glob) (esc)
514 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (glob) (esc)
515 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (glob) (esc)
515 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (glob) (esc)
516 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (glob) (esc)
516 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (glob) (esc)
517 \r (no-eol) (esc)
517 \r (no-eol) (esc)
518 $ find ../archive_all | sort
518 $ find ../archive_all | sort
519 ../archive_all
519 ../archive_all
520 ../archive_all/.hg_archival.txt
520 ../archive_all/.hg_archival.txt
521 ../archive_all/.hgsub
521 ../archive_all/.hgsub
522 ../archive_all/.hgsubstate
522 ../archive_all/.hgsubstate
523 ../archive_all/main
523 ../archive_all/main
524 ../archive_all/sub1
524 ../archive_all/sub1
525 ../archive_all/sub1/.hgsub
525 ../archive_all/sub1/.hgsub
526 ../archive_all/sub1/.hgsubstate
526 ../archive_all/sub1/.hgsubstate
527 ../archive_all/sub1/sub1
527 ../archive_all/sub1/sub1
528 ../archive_all/sub1/sub2
528 ../archive_all/sub1/sub2
529 ../archive_all/sub1/sub2/folder
529 ../archive_all/sub1/sub2/folder
530 ../archive_all/sub1/sub2/folder/test.txt
530 ../archive_all/sub1/sub2/folder/test.txt
531 ../archive_all/sub1/sub2/sub2
531 ../archive_all/sub1/sub2/sub2
532 ../archive_all/sub1/sub2/test.txt
532 ../archive_all/sub1/sub2/test.txt
533
533
534 Check that archive -X works in deep subrepos
534 Check that archive -X works in deep subrepos
535
535
536 $ hg --config extensions.largefiles=! archive -S -X '**test*' ../archive_exclude
536 $ hg --config extensions.largefiles=! archive -S -X '**test*' ../archive_exclude
537 \r (no-eol) (esc)
537 \r (no-eol) (esc)
538 archiving [ ] 0/3\r (no-eol) (esc)
538 archiving [ ] 0/3\r (no-eol) (esc)
539 archiving [=============> ] 1/3\r (no-eol) (esc)
539 archiving [=============> ] 1/3\r (no-eol) (esc)
540 archiving [===========================> ] 2/3\r (no-eol) (esc)
540 archiving [===========================> ] 2/3\r (no-eol) (esc)
541 archiving [==========================================>] 3/3\r (no-eol) (esc)
541 archiving [==========================================>] 3/3\r (no-eol) (esc)
542 \r (no-eol) (esc)
542 \r (no-eol) (esc)
543 \r (no-eol) (esc)
543 \r (no-eol) (esc)
544 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
544 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
545 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
545 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
546 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
546 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
547 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
547 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
548 \r (no-eol) (esc)
548 \r (no-eol) (esc)
549 \r (no-eol) (esc)
549 \r (no-eol) (esc)
550 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (glob) (esc)
550 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (glob) (esc)
551 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (glob) (esc)
551 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (glob) (esc)
552 \r (no-eol) (esc)
552 \r (no-eol) (esc)
553 $ find ../archive_exclude | sort
553 $ find ../archive_exclude | sort
554 ../archive_exclude
554 ../archive_exclude
555 ../archive_exclude/.hg_archival.txt
555 ../archive_exclude/.hg_archival.txt
556 ../archive_exclude/.hgsub
556 ../archive_exclude/.hgsub
557 ../archive_exclude/.hgsubstate
557 ../archive_exclude/.hgsubstate
558 ../archive_exclude/main
558 ../archive_exclude/main
559 ../archive_exclude/sub1
559 ../archive_exclude/sub1
560 ../archive_exclude/sub1/.hgsub
560 ../archive_exclude/sub1/.hgsub
561 ../archive_exclude/sub1/.hgsubstate
561 ../archive_exclude/sub1/.hgsubstate
562 ../archive_exclude/sub1/sub1
562 ../archive_exclude/sub1/sub1
563 ../archive_exclude/sub1/sub2
563 ../archive_exclude/sub1/sub2
564 ../archive_exclude/sub1/sub2/sub2
564 ../archive_exclude/sub1/sub2/sub2
565
565
566 $ hg --config extensions.largefiles=! archive -S -I '**test*' ../archive_include
566 $ hg --config extensions.largefiles=! archive -S -I '**test*' ../archive_include
567 \r (no-eol) (esc)
567 \r (no-eol) (esc)
568 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
568 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
569 \r (no-eol) (esc)
569 \r (no-eol) (esc)
570 \r (no-eol) (esc)
570 \r (no-eol) (esc)
571 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (glob) (esc)
571 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (glob) (esc)
572 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (glob) (esc)
572 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (glob) (esc)
573 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (glob) (esc)
573 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (glob) (esc)
574 \r (no-eol) (esc)
574 \r (no-eol) (esc)
575 $ find ../archive_include | sort
575 $ find ../archive_include | sort
576 ../archive_include
576 ../archive_include
577 ../archive_include/sub1
577 ../archive_include/sub1
578 ../archive_include/sub1/sub2
578 ../archive_include/sub1/sub2
579 ../archive_include/sub1/sub2/folder
579 ../archive_include/sub1/sub2/folder
580 ../archive_include/sub1/sub2/folder/test.txt
580 ../archive_include/sub1/sub2/folder/test.txt
581 ../archive_include/sub1/sub2/test.txt
581 ../archive_include/sub1/sub2/test.txt
582
582
583 Check that deep archive works with largefiles (which overrides hgsubrepo impl)
583 Check that deep archive works with largefiles (which overrides hgsubrepo impl)
584 This also tests the repo.ui regression in 43fb170a23bd, and that lf subrepo
584 This also tests the repo.ui regression in 43fb170a23bd, and that lf subrepo
585 subrepos are archived properly.
585 subrepos are archived properly.
586 Note that add --large through a subrepo currently adds the file as a normal file
586 Note that add --large through a subrepo currently adds the file as a normal file
587
587
588 $ echo "large" > sub1/sub2/large.bin
588 $ echo "large" > sub1/sub2/large.bin
589 $ hg --config extensions.largefiles= add --large -R sub1/sub2 sub1/sub2/large.bin
589 $ hg --config extensions.largefiles= add --large -R sub1/sub2 sub1/sub2/large.bin
590 $ echo "large" > large.bin
590 $ echo "large" > large.bin
591 $ hg --config extensions.largefiles= add --large large.bin
591 $ hg --config extensions.largefiles= add --large large.bin
592 $ hg --config extensions.largefiles= ci -S -m "add large files"
592 $ hg --config extensions.largefiles= ci -S -m "add large files"
593 committing subrepository sub1
593 committing subrepository sub1
594 committing subrepository sub1/sub2 (glob)
594 committing subrepository sub1/sub2 (glob)
595
595
596 $ hg --config extensions.largefiles= archive -S ../archive_lf
596 $ hg --config extensions.largefiles= archive -S ../archive_lf
597 $ find ../archive_lf | sort
597 $ find ../archive_lf | sort
598 ../archive_lf
598 ../archive_lf
599 ../archive_lf/.hg_archival.txt
599 ../archive_lf/.hg_archival.txt
600 ../archive_lf/.hgsub
600 ../archive_lf/.hgsub
601 ../archive_lf/.hgsubstate
601 ../archive_lf/.hgsubstate
602 ../archive_lf/large.bin
602 ../archive_lf/large.bin
603 ../archive_lf/main
603 ../archive_lf/main
604 ../archive_lf/sub1
604 ../archive_lf/sub1
605 ../archive_lf/sub1/.hgsub
605 ../archive_lf/sub1/.hgsub
606 ../archive_lf/sub1/.hgsubstate
606 ../archive_lf/sub1/.hgsubstate
607 ../archive_lf/sub1/sub1
607 ../archive_lf/sub1/sub1
608 ../archive_lf/sub1/sub2
608 ../archive_lf/sub1/sub2
609 ../archive_lf/sub1/sub2/folder
609 ../archive_lf/sub1/sub2/folder
610 ../archive_lf/sub1/sub2/folder/test.txt
610 ../archive_lf/sub1/sub2/folder/test.txt
611 ../archive_lf/sub1/sub2/large.bin
611 ../archive_lf/sub1/sub2/large.bin
612 ../archive_lf/sub1/sub2/sub2
612 ../archive_lf/sub1/sub2/sub2
613 ../archive_lf/sub1/sub2/test.txt
613 ../archive_lf/sub1/sub2/test.txt
614 $ rm -rf ../archive_lf
614 $ rm -rf ../archive_lf
615
615
616 Exclude large files from main and sub-sub repo
616 Exclude large files from main and sub-sub repo
617
617
618 $ hg --config extensions.largefiles= archive -S -X '**.bin' ../archive_lf
618 $ hg --config extensions.largefiles= archive -S -X '**.bin' ../archive_lf
619 $ find ../archive_lf | sort
619 $ find ../archive_lf | sort
620 ../archive_lf
620 ../archive_lf
621 ../archive_lf/.hg_archival.txt
621 ../archive_lf/.hg_archival.txt
622 ../archive_lf/.hgsub
622 ../archive_lf/.hgsub
623 ../archive_lf/.hgsubstate
623 ../archive_lf/.hgsubstate
624 ../archive_lf/main
624 ../archive_lf/main
625 ../archive_lf/sub1
625 ../archive_lf/sub1
626 ../archive_lf/sub1/.hgsub
626 ../archive_lf/sub1/.hgsub
627 ../archive_lf/sub1/.hgsubstate
627 ../archive_lf/sub1/.hgsubstate
628 ../archive_lf/sub1/sub1
628 ../archive_lf/sub1/sub1
629 ../archive_lf/sub1/sub2
629 ../archive_lf/sub1/sub2
630 ../archive_lf/sub1/sub2/folder
630 ../archive_lf/sub1/sub2/folder
631 ../archive_lf/sub1/sub2/folder/test.txt
631 ../archive_lf/sub1/sub2/folder/test.txt
632 ../archive_lf/sub1/sub2/sub2
632 ../archive_lf/sub1/sub2/sub2
633 ../archive_lf/sub1/sub2/test.txt
633 ../archive_lf/sub1/sub2/test.txt
634 $ rm -rf ../archive_lf
634 $ rm -rf ../archive_lf
635
635
636 Exclude normal files from main and sub-sub repo
636 Exclude normal files from main and sub-sub repo
637
637
638 $ hg --config extensions.largefiles= archive -S -X '**.txt' -p '.' ../archive_lf.tgz
638 $ hg --config extensions.largefiles= archive -S -X '**.txt' -p '.' ../archive_lf.tgz
639 $ tar -tzf ../archive_lf.tgz | sort
639 $ tar -tzf ../archive_lf.tgz | sort
640 .hgsub
640 .hgsub
641 .hgsubstate
641 .hgsubstate
642 large.bin
642 large.bin
643 main
643 main
644 sub1/.hgsub
644 sub1/.hgsub
645 sub1/.hgsubstate
645 sub1/.hgsubstate
646 sub1/sub1
646 sub1/sub1
647 sub1/sub2/large.bin
647 sub1/sub2/large.bin
648 sub1/sub2/sub2
648 sub1/sub2/sub2
649
649
650 Include normal files from within a largefiles subrepo
650 Include normal files from within a largefiles subrepo
651
651
652 $ hg --config extensions.largefiles= archive -S -I '**.txt' ../archive_lf
652 $ hg --config extensions.largefiles= archive -S -I '**.txt' ../archive_lf
653 $ find ../archive_lf | sort
653 $ find ../archive_lf | sort
654 ../archive_lf
654 ../archive_lf
655 ../archive_lf/.hg_archival.txt
655 ../archive_lf/.hg_archival.txt
656 ../archive_lf/sub1
656 ../archive_lf/sub1
657 ../archive_lf/sub1/sub2
657 ../archive_lf/sub1/sub2
658 ../archive_lf/sub1/sub2/folder
658 ../archive_lf/sub1/sub2/folder
659 ../archive_lf/sub1/sub2/folder/test.txt
659 ../archive_lf/sub1/sub2/folder/test.txt
660 ../archive_lf/sub1/sub2/test.txt
660 ../archive_lf/sub1/sub2/test.txt
661 $ rm -rf ../archive_lf
661 $ rm -rf ../archive_lf
662
662
663 Include large files from within a largefiles subrepo
663 Include large files from within a largefiles subrepo
664
664
665 $ hg --config extensions.largefiles= archive -S -I '**.bin' ../archive_lf
665 $ hg --config extensions.largefiles= archive -S -I '**.bin' ../archive_lf
666 $ find ../archive_lf | sort
666 $ find ../archive_lf | sort
667 ../archive_lf
667 ../archive_lf
668 ../archive_lf/large.bin
668 ../archive_lf/large.bin
669 ../archive_lf/sub1
669 ../archive_lf/sub1
670 ../archive_lf/sub1/sub2
670 ../archive_lf/sub1/sub2
671 ../archive_lf/sub1/sub2/large.bin
671 ../archive_lf/sub1/sub2/large.bin
672 $ rm -rf ../archive_lf
672 $ rm -rf ../archive_lf
673
673
674 Find an exact largefile match in a largefiles subrepo
674 Find an exact largefile match in a largefiles subrepo
675
675
676 $ hg --config extensions.largefiles= archive -S -I 'sub1/sub2/large.bin' ../archive_lf
676 $ hg --config extensions.largefiles= archive -S -I 'sub1/sub2/large.bin' ../archive_lf
677 $ find ../archive_lf | sort
677 $ find ../archive_lf | sort
678 ../archive_lf
678 ../archive_lf
679 ../archive_lf/sub1
679 ../archive_lf/sub1
680 ../archive_lf/sub1/sub2
680 ../archive_lf/sub1/sub2
681 ../archive_lf/sub1/sub2/large.bin
681 ../archive_lf/sub1/sub2/large.bin
682 $ rm -rf ../archive_lf
682 $ rm -rf ../archive_lf
683
683
684 The local repo enables largefiles if a largefiles repo is cloned
684 The local repo enables largefiles if a largefiles repo is cloned
685 $ hg showconfig extensions
685 $ hg showconfig extensions
686 abort: repository requires features unknown to this Mercurial: largefiles!
686 abort: repository requires features unknown to this Mercurial: largefiles!
687 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
687 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
688 [255]
688 [255]
689 $ hg --config extensions.largefiles= clone -qU . ../lfclone
689 $ hg --config extensions.largefiles= clone -qU . ../lfclone
690 $ cat ../lfclone/.hg/hgrc
690 $ cat ../lfclone/.hg/hgrc
691 # example repository config (see 'hg help config' for more info)
691 # example repository config (see 'hg help config' for more info)
692 [paths]
692 [paths]
693 default = $TESTTMP/cloned (glob)
693 default = $TESTTMP/cloned (glob)
694
694
695 # path aliases to other clones of this repo in URLs or filesystem paths
695 # path aliases to other clones of this repo in URLs or filesystem paths
696 # (see 'hg help config.paths' for more info)
696 # (see 'hg help config.paths' for more info)
697 #
697 #
698 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
698 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
699 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
699 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
700 # my-clone = /home/jdoe/jdoes-clone
700 # my-clone = /home/jdoe/jdoes-clone
701
701
702 [ui]
702 [ui]
703 # name and email (local to this repository, optional), e.g.
703 # name and email (local to this repository, optional), e.g.
704 # username = Jane Doe <jdoe@example.com>
704 # username = Jane Doe <jdoe@example.com>
705
705
706 [extensions]
706 [extensions]
707 largefiles=
707 largefiles=
708
708
709 Find an exact match to a standin (should archive nothing)
709 Find an exact match to a standin (should archive nothing)
710 $ hg --config extensions.largefiles= archive -S -I 'sub/sub2/.hglf/large.bin' ../archive_lf
710 $ hg --config extensions.largefiles= archive -S -I 'sub/sub2/.hglf/large.bin' ../archive_lf
711 $ find ../archive_lf 2> /dev/null | sort
711 $ find ../archive_lf 2> /dev/null | sort
712
712
713 $ cat >> $HGRCPATH <<EOF
713 $ cat >> $HGRCPATH <<EOF
714 > [extensions]
714 > [extensions]
715 > largefiles=
715 > largefiles=
716 > [largefiles]
716 > [largefiles]
717 > patterns=glob:**.dat
717 > patterns=glob:**.dat
718 > EOF
718 > EOF
719
719
720 Test forget through a deep subrepo with the largefiles extension, both a
720 Test forget through a deep subrepo with the largefiles extension, both a
721 largefile and a normal file. Then a largefile that hasn't been committed yet.
721 largefile and a normal file. Then a largefile that hasn't been committed yet.
722 $ touch sub1/sub2/untracked.txt
722 $ touch sub1/sub2/untracked.txt
723 $ touch sub1/sub2/large.dat
723 $ touch sub1/sub2/large.dat
724 $ hg forget sub1/sub2/large.bin sub1/sub2/test.txt sub1/sub2/untracked.txt
724 $ hg forget sub1/sub2/large.bin sub1/sub2/test.txt sub1/sub2/untracked.txt
725 not removing sub1/sub2/untracked.txt: file is already untracked (glob)
725 not removing sub1/sub2/untracked.txt: file is already untracked (glob)
726 [1]
726 [1]
727 $ hg add --large --dry-run -v sub1/sub2/untracked.txt
727 $ hg add --large --dry-run -v sub1/sub2/untracked.txt
728 adding sub1/sub2/untracked.txt as a largefile (glob)
728 adding sub1/sub2/untracked.txt as a largefile (glob)
729 $ hg add --large -v sub1/sub2/untracked.txt
729 $ hg add --large -v sub1/sub2/untracked.txt
730 adding sub1/sub2/untracked.txt as a largefile (glob)
730 adding sub1/sub2/untracked.txt as a largefile (glob)
731 $ hg add --normal -v sub1/sub2/large.dat
731 $ hg add --normal -v sub1/sub2/large.dat
732 adding sub1/sub2/large.dat (glob)
732 adding sub1/sub2/large.dat (glob)
733 $ hg forget -v sub1/sub2/untracked.txt
733 $ hg forget -v sub1/sub2/untracked.txt
734 removing sub1/sub2/untracked.txt (glob)
734 removing sub1/sub2/untracked.txt (glob)
735 $ hg status -S
735 $ hg status -S
736 A sub1/sub2/large.dat
736 A sub1/sub2/large.dat
737 R sub1/sub2/large.bin
737 R sub1/sub2/large.bin
738 R sub1/sub2/test.txt
738 R sub1/sub2/test.txt
739 ? foo/bar/abc
739 ? foo/bar/abc
740 ? sub1/sub2/untracked.txt
740 ? sub1/sub2/untracked.txt
741 ? sub1/sub2/x.txt
741 ? sub1/sub2/x.txt
742 $ hg add sub1/sub2
742 $ hg add sub1/sub2
743
743
744 $ hg archive -S -r 'wdir()' ../wdir2
744 $ hg archive -S -r 'wdir()' ../wdir2
745 $ diff -r . ../wdir2 | egrep -v '\.hg$|^Common subdirectories:'
745 $ diff -r . ../wdir2 | egrep -v '\.hg$|^Common subdirectories:'
746 Only in ../wdir2: .hg_archival.txt
746 Only in ../wdir2: .hg_archival.txt
747 Only in .: .hglf
747 Only in .: .hglf
748 Only in .: foo
748 Only in .: foo
749 Only in ./sub1/sub2: large.bin
749 Only in ./sub1/sub2: large.bin
750 Only in ./sub1/sub2: test.txt
750 Only in ./sub1/sub2: test.txt
751 Only in ./sub1/sub2: untracked.txt
751 Only in ./sub1/sub2: untracked.txt
752 Only in ./sub1/sub2: x.txt
752 Only in ./sub1/sub2: x.txt
753 $ find ../wdir2 -type f | sort
753 $ find ../wdir2 -type f | sort
754 ../wdir2/.hg_archival.txt
754 ../wdir2/.hg_archival.txt
755 ../wdir2/.hgsub
755 ../wdir2/.hgsub
756 ../wdir2/.hgsubstate
756 ../wdir2/.hgsubstate
757 ../wdir2/large.bin
757 ../wdir2/large.bin
758 ../wdir2/main
758 ../wdir2/main
759 ../wdir2/sub1/.hgsub
759 ../wdir2/sub1/.hgsub
760 ../wdir2/sub1/.hgsubstate
760 ../wdir2/sub1/.hgsubstate
761 ../wdir2/sub1/sub1
761 ../wdir2/sub1/sub1
762 ../wdir2/sub1/sub2/folder/test.txt
762 ../wdir2/sub1/sub2/folder/test.txt
763 ../wdir2/sub1/sub2/large.dat
763 ../wdir2/sub1/sub2/large.dat
764 ../wdir2/sub1/sub2/sub2
764 ../wdir2/sub1/sub2/sub2
765 $ hg status -S -mac -n | sort
765 $ hg status -S -mac -n | sort
766 .hgsub
766 .hgsub
767 .hgsubstate
767 .hgsubstate
768 large.bin
768 large.bin
769 main
769 main
770 sub1/.hgsub
770 sub1/.hgsub
771 sub1/.hgsubstate
771 sub1/.hgsubstate
772 sub1/sub1
772 sub1/sub1
773 sub1/sub2/folder/test.txt
773 sub1/sub2/folder/test.txt
774 sub1/sub2/large.dat
774 sub1/sub2/large.dat
775 sub1/sub2/sub2
775 sub1/sub2/sub2
776
776
777 $ hg ci -Sqm 'forget testing'
777 $ hg ci -Sqm 'forget testing'
778
778
779 Test 'wdir()' modified file archiving with largefiles
779 Test 'wdir()' modified file archiving with largefiles
780 $ echo 'mod' > main
780 $ echo 'mod' > main
781 $ echo 'mod' > large.bin
781 $ echo 'mod' > large.bin
782 $ echo 'mod' > sub1/sub2/large.dat
782 $ echo 'mod' > sub1/sub2/large.dat
783 $ hg archive -S -r 'wdir()' ../wdir3
783 $ hg archive -S -r 'wdir()' ../wdir3
784 $ diff -r . ../wdir3 | egrep -v '\.hg$|^Common subdirectories'
784 $ diff -r . ../wdir3 | egrep -v '\.hg$|^Common subdirectories'
785 Only in ../wdir3: .hg_archival.txt
785 Only in ../wdir3: .hg_archival.txt
786 Only in .: .hglf
786 Only in .: .hglf
787 Only in .: foo
787 Only in .: foo
788 Only in ./sub1/sub2: large.bin
788 Only in ./sub1/sub2: large.bin
789 Only in ./sub1/sub2: test.txt
789 Only in ./sub1/sub2: test.txt
790 Only in ./sub1/sub2: untracked.txt
790 Only in ./sub1/sub2: untracked.txt
791 Only in ./sub1/sub2: x.txt
791 Only in ./sub1/sub2: x.txt
792 $ find ../wdir3 -type f | sort
792 $ find ../wdir3 -type f | sort
793 ../wdir3/.hg_archival.txt
793 ../wdir3/.hg_archival.txt
794 ../wdir3/.hgsub
794 ../wdir3/.hgsub
795 ../wdir3/.hgsubstate
795 ../wdir3/.hgsubstate
796 ../wdir3/large.bin
796 ../wdir3/large.bin
797 ../wdir3/main
797 ../wdir3/main
798 ../wdir3/sub1/.hgsub
798 ../wdir3/sub1/.hgsub
799 ../wdir3/sub1/.hgsubstate
799 ../wdir3/sub1/.hgsubstate
800 ../wdir3/sub1/sub1
800 ../wdir3/sub1/sub1
801 ../wdir3/sub1/sub2/folder/test.txt
801 ../wdir3/sub1/sub2/folder/test.txt
802 ../wdir3/sub1/sub2/large.dat
802 ../wdir3/sub1/sub2/large.dat
803 ../wdir3/sub1/sub2/sub2
803 ../wdir3/sub1/sub2/sub2
804 $ hg up -Cq
804 $ hg up -Cq
805
805
806 Test issue4330: commit a directory where only normal files have changed
806 Test issue4330: commit a directory where only normal files have changed
807 $ touch foo/bar/large.dat
807 $ touch foo/bar/large.dat
808 $ hg add --large foo/bar/large.dat
808 $ hg add --large foo/bar/large.dat
809 $ hg ci -m 'add foo/bar/large.dat'
809 $ hg ci -m 'add foo/bar/large.dat'
810 $ touch a.txt
810 $ touch a.txt
811 $ touch a.dat
811 $ touch a.dat
812 $ hg add -v foo/bar/abc a.txt a.dat
812 $ hg add -v foo/bar/abc a.txt a.dat
813 adding a.dat as a largefile
813 adding a.dat as a largefile
814 adding a.txt
814 adding a.txt
815 adding foo/bar/abc (glob)
815 adding foo/bar/abc (glob)
816 $ hg ci -m 'dir commit with only normal file deltas' foo/bar
816 $ hg ci -m 'dir commit with only normal file deltas' foo/bar
817 $ hg status
817 $ hg status
818 A a.dat
818 A a.dat
819 A a.txt
819 A a.txt
820
820
821 Test a directory commit with a changed largefile and a changed normal file
821 Test a directory commit with a changed largefile and a changed normal file
822 $ echo changed > foo/bar/large.dat
822 $ echo changed > foo/bar/large.dat
823 $ echo changed > foo/bar/abc
823 $ echo changed > foo/bar/abc
824 $ hg ci -m 'dir commit with normal and lf file deltas' foo
824 $ hg ci -m 'dir commit with normal and lf file deltas' foo
825 $ hg status
825 $ hg status
826 A a.dat
826 A a.dat
827 A a.txt
827 A a.txt
828
828
829 $ hg ci -m "add a.*"
829 $ hg ci -m "add a.*"
830 $ hg mv a.dat b.dat
830 $ hg mv a.dat b.dat
831 $ hg mv foo/bar/abc foo/bar/def
831 $ hg mv foo/bar/abc foo/bar/def
832 $ hg status -C
832 $ hg status -C
833 A b.dat
833 A b.dat
834 a.dat
834 a.dat
835 A foo/bar/def
835 A foo/bar/def
836 foo/bar/abc
836 foo/bar/abc
837 R a.dat
837 R a.dat
838 R foo/bar/abc
838 R foo/bar/abc
839
839
840 $ hg ci -m "move large and normal"
840 $ hg ci -m "move large and normal"
841 $ hg status -C --rev '.^' --rev .
841 $ hg status -C --rev '.^' --rev .
842 A b.dat
842 A b.dat
843 a.dat
843 a.dat
844 A foo/bar/def
844 A foo/bar/def
845 foo/bar/abc
845 foo/bar/abc
846 R a.dat
846 R a.dat
847 R foo/bar/abc
847 R foo/bar/abc
848
848
849
849
850 $ echo foo > main
850 $ echo foo > main
851 $ hg ci -m "mod parent only"
851 $ hg ci -m "mod parent only"
852 $ hg init sub3
852 $ hg init sub3
853 $ echo "sub3 = sub3" >> .hgsub
853 $ echo "sub3 = sub3" >> .hgsub
854 $ echo xyz > sub3/a.txt
854 $ echo xyz > sub3/a.txt
855 $ hg add sub3/a.txt
855 $ hg add sub3/a.txt
856 $ hg ci -Sm "add sub3"
856 $ hg ci -Sm "add sub3"
857 committing subrepository sub3
857 committing subrepository sub3
858 $ cat .hgsub | grep -v sub3 > .hgsub1
858 $ cat .hgsub | grep -v sub3 > .hgsub1
859 $ mv .hgsub1 .hgsub
859 $ mv .hgsub1 .hgsub
860 $ hg ci -m "remove sub3"
860 $ hg ci -m "remove sub3"
861
861
862 $ hg log -r "subrepo()" --style compact
862 $ hg log -r "subrepo()" --style compact
863 0 7f491f53a367 1970-01-01 00:00 +0000 test
863 0 7f491f53a367 1970-01-01 00:00 +0000 test
864 main import
864 main import
865
865
866 1 ffe6649062fe 1970-01-01 00:00 +0000 test
866 1 ffe6649062fe 1970-01-01 00:00 +0000 test
867 deep nested modif should trigger a commit
867 deep nested modif should trigger a commit
868
868
869 2 9bb10eebee29 1970-01-01 00:00 +0000 test
869 2 9bb10eebee29 1970-01-01 00:00 +0000 test
870 add test.txt
870 add test.txt
871
871
872 3 7c64f035294f 1970-01-01 00:00 +0000 test
872 3 7c64f035294f 1970-01-01 00:00 +0000 test
873 add large files
873 add large files
874
874
875 4 f734a59e2e35 1970-01-01 00:00 +0000 test
875 4 f734a59e2e35 1970-01-01 00:00 +0000 test
876 forget testing
876 forget testing
877
877
878 11 9685a22af5db 1970-01-01 00:00 +0000 test
878 11 9685a22af5db 1970-01-01 00:00 +0000 test
879 add sub3
879 add sub3
880
880
881 12[tip] 2e0485b475b9 1970-01-01 00:00 +0000 test
881 12[tip] 2e0485b475b9 1970-01-01 00:00 +0000 test
882 remove sub3
882 remove sub3
883
883
884 $ hg log -r "subrepo('sub3')" --style compact
884 $ hg log -r "subrepo('sub3')" --style compact
885 11 9685a22af5db 1970-01-01 00:00 +0000 test
885 11 9685a22af5db 1970-01-01 00:00 +0000 test
886 add sub3
886 add sub3
887
887
888 12[tip] 2e0485b475b9 1970-01-01 00:00 +0000 test
888 12[tip] 2e0485b475b9 1970-01-01 00:00 +0000 test
889 remove sub3
889 remove sub3
890
890
891 $ hg log -r "subrepo('bogus')" --style compact
891 $ hg log -r "subrepo('bogus')" --style compact
892
892
893
893
894 Test .hgsubstate in the R state
894 Test .hgsubstate in the R state
895
895
896 $ hg rm .hgsub .hgsubstate
896 $ hg rm .hgsub .hgsubstate
897 \r (no-eol) (esc)
897 \r (no-eol) (esc)
898 deleting [=====================> ] 1/2\r (no-eol) (esc)
898 deleting [=====================> ] 1/2\r (no-eol) (esc)
899 deleting [===========================================>] 2/2\r (no-eol) (esc)
899 deleting [===========================================>] 2/2\r (no-eol) (esc)
900 \r (no-eol) (esc)
900 \r (no-eol) (esc)
901 $ hg ci -m 'trash subrepo tracking'
901 $ hg ci -m 'trash subrepo tracking'
902
902
903 $ hg log -r "subrepo('re:sub\d+')" --style compact
903 $ hg log -r "subrepo('re:sub\d+')" --style compact
904 0 7f491f53a367 1970-01-01 00:00 +0000 test
904 0 7f491f53a367 1970-01-01 00:00 +0000 test
905 main import
905 main import
906
906
907 1 ffe6649062fe 1970-01-01 00:00 +0000 test
907 1 ffe6649062fe 1970-01-01 00:00 +0000 test
908 deep nested modif should trigger a commit
908 deep nested modif should trigger a commit
909
909
910 2 9bb10eebee29 1970-01-01 00:00 +0000 test
910 2 9bb10eebee29 1970-01-01 00:00 +0000 test
911 add test.txt
911 add test.txt
912
912
913 3 7c64f035294f 1970-01-01 00:00 +0000 test
913 3 7c64f035294f 1970-01-01 00:00 +0000 test
914 add large files
914 add large files
915
915
916 4 f734a59e2e35 1970-01-01 00:00 +0000 test
916 4 f734a59e2e35 1970-01-01 00:00 +0000 test
917 forget testing
917 forget testing
918
918
919 11 9685a22af5db 1970-01-01 00:00 +0000 test
919 11 9685a22af5db 1970-01-01 00:00 +0000 test
920 add sub3
920 add sub3
921
921
922 12 2e0485b475b9 1970-01-01 00:00 +0000 test
922 12 2e0485b475b9 1970-01-01 00:00 +0000 test
923 remove sub3
923 remove sub3
924
924
925 13[tip] a68b2c361653 1970-01-01 00:00 +0000 test
925 13[tip] a68b2c361653 1970-01-01 00:00 +0000 test
926 trash subrepo tracking
926 trash subrepo tracking
927
927
928
928
929 Restore the trashed subrepo tracking
929 Restore the trashed subrepo tracking
930
930
931 $ hg rollback -q
931 $ hg rollback -q
932 $ hg update -Cq .
932 $ hg update -Cq .
933
933
934 Interaction with extdiff, largefiles and subrepos
934 Interaction with extdiff, largefiles and subrepos
935
935
936 $ hg --config extensions.extdiff= pdiff -S
936 $ hg --config extensions.extdiff= pdiff -S
937
937
938 $ hg --config extensions.extdiff= pdiff -r '.^' -S
938 $ hg --config extensions.extdiff= pdiff -r '.^' -S
939 \r (no-eol) (esc)
939 \r (no-eol) (esc)
940 archiving [ ] 0/2\r (no-eol) (esc)
940 archiving [ ] 0/2\r (no-eol) (esc)
941 archiving [====================> ] 1/2\r (no-eol) (esc)
941 archiving [====================> ] 1/2\r (no-eol) (esc)
942 archiving [==========================================>] 2/2\r (no-eol) (esc)
942 archiving [==========================================>] 2/2\r (no-eol) (esc)
943 \r (no-eol) (esc)
943 \r (no-eol) (esc)
944 \r (no-eol) (esc)
944 \r (no-eol) (esc)
945 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
945 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
946 \r (no-eol) (esc)
946 \r (no-eol) (esc)
947 \r (no-eol) (esc)
947 \r (no-eol) (esc)
948 archiving (sub1/sub2) [ <=> ] 0\r (no-eol) (glob) (esc)
948 archiving (sub1/sub2) [ <=> ] 0\r (no-eol) (glob) (esc)
949 \r (no-eol) (esc)
949 \r (no-eol) (esc)
950 \r (no-eol) (esc)
950 \r (no-eol) (esc)
951 archiving (sub3) [ <=> ] 0\r (no-eol) (esc)
951 archiving (sub3) [ <=> ] 0\r (no-eol) (esc)
952 \r (no-eol) (esc)
952 \r (no-eol) (esc)
953 \r (no-eol) (esc)
953 \r (no-eol) (esc)
954 archiving [ ] 0/2\r (no-eol) (esc)
954 archiving [ ] 0/2\r (no-eol) (esc)
955 archiving [====================> ] 1/2\r (no-eol) (esc)
955 archiving [====================> ] 1/2\r (no-eol) (esc)
956 archiving [==========================================>] 2/2\r (no-eol) (esc)
956 archiving [==========================================>] 2/2\r (no-eol) (esc)
957 \r (no-eol) (esc)
957 \r (no-eol) (esc)
958 \r (no-eol) (esc)
958 \r (no-eol) (esc)
959 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
959 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
960 \r (no-eol) (esc)
960 \r (no-eol) (esc)
961 \r (no-eol) (esc)
961 \r (no-eol) (esc)
962 archiving (sub1/sub2) [ <=> ] 0\r (no-eol) (glob) (esc)
962 archiving (sub1/sub2) [ <=> ] 0\r (no-eol) (glob) (esc)
963 \r (no-eol) (esc)
963 \r (no-eol) (esc)
964 diff -Nru cloned.*/.hgsub cloned/.hgsub (glob)
964 diff -Nru cloned.*/.hgsub cloned/.hgsub (glob)
965 --- cloned.*/.hgsub * (glob)
965 --- cloned.*/.hgsub * (glob)
966 +++ cloned/.hgsub * (glob)
966 +++ cloned/.hgsub * (glob)
967 @@ -1,2 +1* @@ (glob)
967 @@ -1,2 +1* @@ (glob)
968 sub1 = ../sub1
968 sub1 = ../sub1
969 -sub3 = sub3
969 -sub3 = sub3
970 diff -Nru cloned.*/.hgsubstate cloned/.hgsubstate (glob)
970 diff -Nru cloned.*/.hgsubstate cloned/.hgsubstate (glob)
971 --- cloned.*/.hgsubstate * (glob)
971 --- cloned.*/.hgsubstate * (glob)
972 +++ cloned/.hgsubstate * (glob)
972 +++ cloned/.hgsubstate * (glob)
973 @@ -1,2 +1* @@ (glob)
973 @@ -1,2 +1* @@ (glob)
974 7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
974 7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
975 -b1a26de6f2a045a9f079323693614ee322f1ff7e sub3
975 -b1a26de6f2a045a9f079323693614ee322f1ff7e sub3
976 [1]
976 [1]
977
977
978 $ hg --config extensions.extdiff= pdiff -r 0 -r '.^' -S
978 $ hg --config extensions.extdiff= pdiff -r 0 -r '.^' -S
979 \r (no-eol) (esc)
979 \r (no-eol) (esc)
980 archiving [ ] 0/3\r (no-eol) (esc)
980 archiving [ ] 0/3\r (no-eol) (esc)
981 archiving [=============> ] 1/3\r (no-eol) (esc)
981 archiving [=============> ] 1/3\r (no-eol) (esc)
982 archiving [===========================> ] 2/3\r (no-eol) (esc)
982 archiving [===========================> ] 2/3\r (no-eol) (esc)
983 archiving [==========================================>] 3/3\r (no-eol) (esc)
983 archiving [==========================================>] 3/3\r (no-eol) (esc)
984 \r (no-eol) (esc)
984 \r (no-eol) (esc)
985 \r (no-eol) (esc)
985 \r (no-eol) (esc)
986 archiving (sub1) [ ] 0/1\r (no-eol) (esc)
986 archiving (sub1) [ ] 0/1\r (no-eol) (esc)
987 archiving (sub1) [===================================>] 1/1\r (no-eol) (esc)
987 archiving (sub1) [===================================>] 1/1\r (no-eol) (esc)
988 \r (no-eol) (esc)
988 \r (no-eol) (esc)
989 \r (no-eol) (esc)
989 \r (no-eol) (esc)
990 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (glob) (esc)
990 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (glob) (esc)
991 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (glob) (esc)
991 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (glob) (esc)
992 \r (no-eol) (esc)
992 \r (no-eol) (esc)
993 \r (no-eol) (esc)
993 \r (no-eol) (esc)
994 archiving [ ] 0/8\r (no-eol) (esc)
994 archiving [ ] 0/8\r (no-eol) (esc)
995 archiving [====> ] 1/8\r (no-eol) (esc)
995 archiving [====> ] 1/8\r (no-eol) (esc)
996 archiving [=========> ] 2/8\r (no-eol) (esc)
996 archiving [=========> ] 2/8\r (no-eol) (esc)
997 archiving [===============> ] 3/8\r (no-eol) (esc)
997 archiving [===============> ] 3/8\r (no-eol) (esc)
998 archiving [====================> ] 4/8\r (no-eol) (esc)
998 archiving [====================> ] 4/8\r (no-eol) (esc)
999 archiving [=========================> ] 5/8\r (no-eol) (esc)
999 archiving [=========================> ] 5/8\r (no-eol) (esc)
1000 archiving [===============================> ] 6/8\r (no-eol) (esc)
1000 archiving [===============================> ] 6/8\r (no-eol) (esc)
1001 archiving [====================================> ] 7/8\r (no-eol) (esc)
1001 archiving [====================================> ] 7/8\r (no-eol) (esc)
1002 archiving [==========================================>] 8/8\r (no-eol) (esc)
1002 archiving [==========================================>] 8/8\r (no-eol) (esc)
1003 \r (no-eol) (esc)
1003 \r (no-eol) (esc)
1004 \r (no-eol) (esc)
1004 \r (no-eol) (esc)
1005 archiving (sub1) [ ] 0/1\r (no-eol) (esc)
1005 archiving (sub1) [ ] 0/1\r (no-eol) (esc)
1006 archiving (sub1) [===================================>] 1/1\r (no-eol) (esc)
1006 archiving (sub1) [===================================>] 1/1\r (no-eol) (esc)
1007 \r (no-eol) (esc)
1007 \r (no-eol) (esc)
1008 \r (no-eol) (esc)
1008 \r (no-eol) (esc)
1009 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (glob) (esc)
1009 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (glob) (esc)
1010 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (glob) (esc)
1010 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (glob) (esc)
1011 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (glob) (esc)
1011 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (glob) (esc)
1012 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (glob) (esc)
1012 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (glob) (esc)
1013 \r (no-eol) (esc)
1013 \r (no-eol) (esc)
1014 \r (no-eol) (esc)
1014 \r (no-eol) (esc)
1015 archiving (sub3) [ ] 0/1\r (no-eol) (esc)
1015 archiving (sub3) [ ] 0/1\r (no-eol) (esc)
1016 archiving (sub3) [===================================>] 1/1\r (no-eol) (esc)
1016 archiving (sub3) [===================================>] 1/1\r (no-eol) (esc)
1017 \r (no-eol) (esc)
1017 \r (no-eol) (esc)
1018 diff -Nru cloned.*/.hglf/b.dat cloned.*/.hglf/b.dat (glob)
1018 diff -Nru cloned.*/.hglf/b.dat cloned.*/.hglf/b.dat (glob)
1019 --- cloned.*/.hglf/b.dat * (glob)
1019 --- cloned.*/.hglf/b.dat * (glob)
1020 +++ cloned.*/.hglf/b.dat * (glob)
1020 +++ cloned.*/.hglf/b.dat * (glob)
1021 @@ -*,0 +1* @@ (glob)
1021 @@ -*,0 +1* @@ (glob)
1022 +da39a3ee5e6b4b0d3255bfef95601890afd80709
1022 +da39a3ee5e6b4b0d3255bfef95601890afd80709
1023 diff -Nru cloned.*/.hglf/foo/bar/large.dat cloned.*/.hglf/foo/bar/large.dat (glob)
1023 diff -Nru cloned.*/.hglf/foo/bar/large.dat cloned.*/.hglf/foo/bar/large.dat (glob)
1024 --- cloned.*/.hglf/foo/bar/large.dat * (glob)
1024 --- cloned.*/.hglf/foo/bar/large.dat * (glob)
1025 +++ cloned.*/.hglf/foo/bar/large.dat * (glob)
1025 +++ cloned.*/.hglf/foo/bar/large.dat * (glob)
1026 @@ -*,0 +1* @@ (glob)
1026 @@ -*,0 +1* @@ (glob)
1027 +2f6933b5ee0f5fdd823d9717d8729f3c2523811b
1027 +2f6933b5ee0f5fdd823d9717d8729f3c2523811b
1028 diff -Nru cloned.*/.hglf/large.bin cloned.*/.hglf/large.bin (glob)
1028 diff -Nru cloned.*/.hglf/large.bin cloned.*/.hglf/large.bin (glob)
1029 --- cloned.*/.hglf/large.bin * (glob)
1029 --- cloned.*/.hglf/large.bin * (glob)
1030 +++ cloned.*/.hglf/large.bin * (glob)
1030 +++ cloned.*/.hglf/large.bin * (glob)
1031 @@ -*,0 +1* @@ (glob)
1031 @@ -*,0 +1* @@ (glob)
1032 +7f7097b041ccf68cc5561e9600da4655d21c6d18
1032 +7f7097b041ccf68cc5561e9600da4655d21c6d18
1033 diff -Nru cloned.*/.hgsub cloned.*/.hgsub (glob)
1033 diff -Nru cloned.*/.hgsub cloned.*/.hgsub (glob)
1034 --- cloned.*/.hgsub * (glob)
1034 --- cloned.*/.hgsub * (glob)
1035 +++ cloned.*/.hgsub * (glob)
1035 +++ cloned.*/.hgsub * (glob)
1036 @@ -1* +1,2 @@ (glob)
1036 @@ -1* +1,2 @@ (glob)
1037 sub1 = ../sub1
1037 sub1 = ../sub1
1038 +sub3 = sub3
1038 +sub3 = sub3
1039 diff -Nru cloned.*/.hgsubstate cloned.*/.hgsubstate (glob)
1039 diff -Nru cloned.*/.hgsubstate cloned.*/.hgsubstate (glob)
1040 --- cloned.*/.hgsubstate * (glob)
1040 --- cloned.*/.hgsubstate * (glob)
1041 +++ cloned.*/.hgsubstate * (glob)
1041 +++ cloned.*/.hgsubstate * (glob)
1042 @@ -1* +1,2 @@ (glob)
1042 @@ -1* +1,2 @@ (glob)
1043 -fc3b4ce2696f7741438c79207583768f2ce6b0dd sub1
1043 -fc3b4ce2696f7741438c79207583768f2ce6b0dd sub1
1044 +7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
1044 +7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
1045 +b1a26de6f2a045a9f079323693614ee322f1ff7e sub3
1045 +b1a26de6f2a045a9f079323693614ee322f1ff7e sub3
1046 diff -Nru cloned.*/foo/bar/def cloned.*/foo/bar/def (glob)
1046 diff -Nru cloned.*/foo/bar/def cloned.*/foo/bar/def (glob)
1047 --- cloned.*/foo/bar/def * (glob)
1047 --- cloned.*/foo/bar/def * (glob)
1048 +++ cloned.*/foo/bar/def * (glob)
1048 +++ cloned.*/foo/bar/def * (glob)
1049 @@ -*,0 +1* @@ (glob)
1049 @@ -*,0 +1* @@ (glob)
1050 +changed
1050 +changed
1051 diff -Nru cloned.*/main cloned.*/main (glob)
1051 diff -Nru cloned.*/main cloned.*/main (glob)
1052 --- cloned.*/main * (glob)
1052 --- cloned.*/main * (glob)
1053 +++ cloned.*/main * (glob)
1053 +++ cloned.*/main * (glob)
1054 @@ -1* +1* @@ (glob)
1054 @@ -1* +1* @@ (glob)
1055 -main
1055 -main
1056 +foo
1056 +foo
1057 diff -Nru cloned.*/sub1/.hgsubstate cloned.*/sub1/.hgsubstate (glob)
1057 diff -Nru cloned.*/sub1/.hgsubstate cloned.*/sub1/.hgsubstate (glob)
1058 --- cloned.*/sub1/.hgsubstate * (glob)
1058 --- cloned.*/sub1/.hgsubstate * (glob)
1059 +++ cloned.*/sub1/.hgsubstate * (glob)
1059 +++ cloned.*/sub1/.hgsubstate * (glob)
1060 @@ -1* +1* @@ (glob)
1060 @@ -1* +1* @@ (glob)
1061 -c57a0840e3badd667ef3c3ef65471609acb2ba3c sub2
1061 -c57a0840e3badd667ef3c3ef65471609acb2ba3c sub2
1062 +c77908c81ccea3794a896c79e98b0e004aee2e9e sub2
1062 +c77908c81ccea3794a896c79e98b0e004aee2e9e sub2
1063 diff -Nru cloned.*/sub1/sub2/folder/test.txt cloned.*/sub1/sub2/folder/test.txt (glob)
1063 diff -Nru cloned.*/sub1/sub2/folder/test.txt cloned.*/sub1/sub2/folder/test.txt (glob)
1064 --- cloned.*/sub1/sub2/folder/test.txt * (glob)
1064 --- cloned.*/sub1/sub2/folder/test.txt * (glob)
1065 +++ cloned.*/sub1/sub2/folder/test.txt * (glob)
1065 +++ cloned.*/sub1/sub2/folder/test.txt * (glob)
1066 @@ -*,0 +1* @@ (glob)
1066 @@ -*,0 +1* @@ (glob)
1067 +subfolder
1067 +subfolder
1068 diff -Nru cloned.*/sub1/sub2/sub2 cloned.*/sub1/sub2/sub2 (glob)
1068 diff -Nru cloned.*/sub1/sub2/sub2 cloned.*/sub1/sub2/sub2 (glob)
1069 --- cloned.*/sub1/sub2/sub2 * (glob)
1069 --- cloned.*/sub1/sub2/sub2 * (glob)
1070 +++ cloned.*/sub1/sub2/sub2 * (glob)
1070 +++ cloned.*/sub1/sub2/sub2 * (glob)
1071 @@ -1* +1* @@ (glob)
1071 @@ -1* +1* @@ (glob)
1072 -sub2
1072 -sub2
1073 +modified
1073 +modified
1074 diff -Nru cloned.*/sub3/a.txt cloned.*/sub3/a.txt (glob)
1074 diff -Nru cloned.*/sub3/a.txt cloned.*/sub3/a.txt (glob)
1075 --- cloned.*/sub3/a.txt * (glob)
1075 --- cloned.*/sub3/a.txt * (glob)
1076 +++ cloned.*/sub3/a.txt * (glob)
1076 +++ cloned.*/sub3/a.txt * (glob)
1077 @@ -*,0 +1* @@ (glob)
1077 @@ -*,0 +1* @@ (glob)
1078 +xyz
1078 +xyz
1079 [1]
1079 [1]
1080
1080
1081 $ echo mod > sub1/sub2/sub2
1081 $ echo mod > sub1/sub2/sub2
1082 $ hg --config extensions.extdiff= pdiff -S
1082 $ hg --config extensions.extdiff= pdiff -S
1083 \r (no-eol) (esc)
1083 \r (no-eol) (esc)
1084 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1084 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1085 \r (no-eol) (esc)
1085 \r (no-eol) (esc)
1086 \r (no-eol) (esc)
1086 \r (no-eol) (esc)
1087 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (glob) (esc)
1087 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (glob) (esc)
1088 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (glob) (esc)
1088 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (glob) (esc)
1089 \r (no-eol) (esc)
1089 \r (no-eol) (esc)
1090 --- */cloned.*/sub1/sub2/sub2 * (glob)
1090 --- */cloned.*/sub1/sub2/sub2 * (glob)
1091 +++ */cloned/sub1/sub2/sub2 * (glob)
1091 +++ */cloned/sub1/sub2/sub2 * (glob)
1092 @@ -1* +1* @@ (glob)
1092 @@ -1* +1* @@ (glob)
1093 -modified
1093 -modified
1094 +mod
1094 +mod
1095 [1]
1095 [1]
1096
1096
1097 $ cd ..
1097 $ cd ..
@@ -1,331 +1,331 b''
1 Test basic functionality of url#rev syntax
1 Test basic functionality of url#rev syntax
2
2
3 $ hg init repo
3 $ hg init repo
4 $ cd repo
4 $ cd repo
5 $ echo a > a
5 $ echo a > a
6 $ hg ci -qAm 'add a'
6 $ hg ci -qAm 'add a'
7 $ hg branch foo
7 $ hg branch foo
8 marked working directory as branch foo
8 marked working directory as branch foo
9 (branches are permanent and global, did you want a bookmark?)
9 (branches are permanent and global, did you want a bookmark?)
10 $ echo >> a
10 $ echo >> a
11 $ hg ci -m 'change a'
11 $ hg ci -m 'change a'
12 $ cd ..
12 $ cd ..
13
13
14 $ hg clone 'repo#foo' clone
14 $ hg clone 'repo#foo' clone
15 adding changesets
15 adding changesets
16 adding manifests
16 adding manifests
17 adding file changes
17 adding file changes
18 added 2 changesets with 2 changes to 1 files
18 added 2 changesets with 2 changes to 1 files
19 updating to branch foo
19 updating to branch foo
20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21
21
22 $ hg --cwd clone heads
22 $ hg --cwd clone heads
23 changeset: 1:cd2a86ecc814
23 changeset: 1:cd2a86ecc814
24 branch: foo
24 branch: foo
25 tag: tip
25 tag: tip
26 user: test
26 user: test
27 date: Thu Jan 01 00:00:00 1970 +0000
27 date: Thu Jan 01 00:00:00 1970 +0000
28 summary: change a
28 summary: change a
29
29
30 changeset: 0:1f0dee641bb7
30 changeset: 0:1f0dee641bb7
31 user: test
31 user: test
32 date: Thu Jan 01 00:00:00 1970 +0000
32 date: Thu Jan 01 00:00:00 1970 +0000
33 summary: add a
33 summary: add a
34
34
35 $ hg --cwd clone parents
35 $ hg --cwd clone parents
36 changeset: 1:cd2a86ecc814
36 changeset: 1:cd2a86ecc814
37 branch: foo
37 branch: foo
38 tag: tip
38 tag: tip
39 user: test
39 user: test
40 date: Thu Jan 01 00:00:00 1970 +0000
40 date: Thu Jan 01 00:00:00 1970 +0000
41 summary: change a
41 summary: change a
42
42
43 $ cat clone/.hg/hgrc
43 $ cat clone/.hg/hgrc
44 # example repository config (see 'hg help config' for more info)
44 # example repository config (see 'hg help config' for more info)
45 [paths]
45 [paths]
46 default = $TESTTMP/repo#foo (glob)
46 default = $TESTTMP/repo#foo (glob)
47
47
48 # path aliases to other clones of this repo in URLs or filesystem paths
48 # path aliases to other clones of this repo in URLs or filesystem paths
49 # (see 'hg help config.paths' for more info)
49 # (see 'hg help config.paths' for more info)
50 #
50 #
51 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
51 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
52 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
52 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
53 # my-clone = /home/jdoe/jdoes-clone
53 # my-clone = /home/jdoe/jdoes-clone
54
54
55 [ui]
55 [ui]
56 # name and email (local to this repository, optional), e.g.
56 # name and email (local to this repository, optional), e.g.
57 # username = Jane Doe <jdoe@example.com>
57 # username = Jane Doe <jdoe@example.com>
58
58
59 Changing original repo:
59 Changing original repo:
60
60
61 $ cd repo
61 $ cd repo
62
62
63 $ echo >> a
63 $ echo >> a
64 $ hg ci -m 'new head of branch foo'
64 $ hg ci -m 'new head of branch foo'
65
65
66 $ hg up -qC default
66 $ hg up -qC default
67 $ echo bar > bar
67 $ echo bar > bar
68 $ hg ci -qAm 'add bar'
68 $ hg ci -qAm 'add bar'
69
69
70 $ hg log
70 $ hg log
71 changeset: 3:4cd725637392
71 changeset: 3:4cd725637392
72 tag: tip
72 tag: tip
73 parent: 0:1f0dee641bb7
73 parent: 0:1f0dee641bb7
74 user: test
74 user: test
75 date: Thu Jan 01 00:00:00 1970 +0000
75 date: Thu Jan 01 00:00:00 1970 +0000
76 summary: add bar
76 summary: add bar
77
77
78 changeset: 2:faba9097cad4
78 changeset: 2:faba9097cad4
79 branch: foo
79 branch: foo
80 user: test
80 user: test
81 date: Thu Jan 01 00:00:00 1970 +0000
81 date: Thu Jan 01 00:00:00 1970 +0000
82 summary: new head of branch foo
82 summary: new head of branch foo
83
83
84 changeset: 1:cd2a86ecc814
84 changeset: 1:cd2a86ecc814
85 branch: foo
85 branch: foo
86 user: test
86 user: test
87 date: Thu Jan 01 00:00:00 1970 +0000
87 date: Thu Jan 01 00:00:00 1970 +0000
88 summary: change a
88 summary: change a
89
89
90 changeset: 0:1f0dee641bb7
90 changeset: 0:1f0dee641bb7
91 user: test
91 user: test
92 date: Thu Jan 01 00:00:00 1970 +0000
92 date: Thu Jan 01 00:00:00 1970 +0000
93 summary: add a
93 summary: add a
94
94
95 $ hg -q outgoing '../clone'
95 $ hg -q outgoing '../clone'
96 2:faba9097cad4
96 2:faba9097cad4
97 3:4cd725637392
97 3:4cd725637392
98 $ hg summary --remote --config paths.default='../clone'
98 $ hg summary --remote --config paths.default='../clone'
99 parent: 3:4cd725637392 tip
99 parent: 3:4cd725637392 tip
100 add bar
100 add bar
101 branch: default
101 branch: default
102 commit: (clean)
102 commit: (clean)
103 update: (current)
103 update: (current)
104 phases: 4 draft
104 phases: 4 draft
105 remote: 2 outgoing
105 remote: 2 outgoing
106 $ hg -q outgoing '../clone#foo'
106 $ hg -q outgoing '../clone#foo'
107 2:faba9097cad4
107 2:faba9097cad4
108 $ hg summary --remote --config paths.default='../clone#foo'
108 $ hg summary --remote --config paths.default='../clone#foo'
109 parent: 3:4cd725637392 tip
109 parent: 3:4cd725637392 tip
110 add bar
110 add bar
111 branch: default
111 branch: default
112 commit: (clean)
112 commit: (clean)
113 update: (current)
113 update: (current)
114 phases: 4 draft
114 phases: 4 draft
115 remote: 1 outgoing
115 remote: 1 outgoing
116
116
117 $ hg -q --cwd ../clone incoming '../repo#foo'
117 $ hg -q --cwd ../clone incoming '../repo#foo'
118 2:faba9097cad4
118 2:faba9097cad4
119 $ hg --cwd ../clone summary --remote --config paths.default='../repo#foo'
119 $ hg --cwd ../clone summary --remote --config paths.default='../repo#foo'
120 parent: 1:cd2a86ecc814 tip
120 parent: 1:cd2a86ecc814 tip
121 change a
121 change a
122 branch: foo
122 branch: foo
123 commit: (clean)
123 commit: (clean)
124 update: (current)
124 update: (current)
125 remote: 1 or more incoming
125 remote: 1 or more incoming
126
126
127 $ hg -q push '../clone#foo'
127 $ hg -q push '../clone#foo'
128
128
129 $ hg --cwd ../clone heads
129 $ hg --cwd ../clone heads
130 changeset: 2:faba9097cad4
130 changeset: 2:faba9097cad4
131 branch: foo
131 branch: foo
132 tag: tip
132 tag: tip
133 user: test
133 user: test
134 date: Thu Jan 01 00:00:00 1970 +0000
134 date: Thu Jan 01 00:00:00 1970 +0000
135 summary: new head of branch foo
135 summary: new head of branch foo
136
136
137 changeset: 0:1f0dee641bb7
137 changeset: 0:1f0dee641bb7
138 user: test
138 user: test
139 date: Thu Jan 01 00:00:00 1970 +0000
139 date: Thu Jan 01 00:00:00 1970 +0000
140 summary: add a
140 summary: add a
141
141
142 $ hg -q --cwd ../clone incoming '../repo#foo'
142 $ hg -q --cwd ../clone incoming '../repo#foo'
143 [1]
143 [1]
144 $ hg --cwd ../clone summary --remote --config paths.default='../repo#foo'
144 $ hg --cwd ../clone summary --remote --config paths.default='../repo#foo'
145 parent: 1:cd2a86ecc814
145 parent: 1:cd2a86ecc814
146 change a
146 change a
147 branch: foo
147 branch: foo
148 commit: (clean)
148 commit: (clean)
149 update: 1 new changesets (update)
149 update: 1 new changesets (update)
150 remote: (synced)
150 remote: (synced)
151
151
152 $ cd ..
152 $ cd ..
153
153
154 $ cd clone
154 $ cd clone
155 $ hg rollback
155 $ hg rollback
156 repository tip rolled back to revision 1 (undo push)
156 repository tip rolled back to revision 1 (undo push)
157
157
158 $ hg -q incoming
158 $ hg -q incoming
159 2:faba9097cad4
159 2:faba9097cad4
160
160
161 $ hg -q pull
161 $ hg -q pull
162
162
163 $ hg heads
163 $ hg heads
164 changeset: 2:faba9097cad4
164 changeset: 2:faba9097cad4
165 branch: foo
165 branch: foo
166 tag: tip
166 tag: tip
167 user: test
167 user: test
168 date: Thu Jan 01 00:00:00 1970 +0000
168 date: Thu Jan 01 00:00:00 1970 +0000
169 summary: new head of branch foo
169 summary: new head of branch foo
170
170
171 changeset: 0:1f0dee641bb7
171 changeset: 0:1f0dee641bb7
172 user: test
172 user: test
173 date: Thu Jan 01 00:00:00 1970 +0000
173 date: Thu Jan 01 00:00:00 1970 +0000
174 summary: add a
174 summary: add a
175
175
176 Pull should not have updated:
176 Pull should not have updated:
177
177
178 $ hg parents -q
178 $ hg parents -q
179 1:cd2a86ecc814
179 1:cd2a86ecc814
180
180
181 Going back to the default branch:
181 Going back to the default branch:
182
182
183 $ hg up -C 0
183 $ hg up -C 0
184 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
184 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
185
185
186 $ hg parents
186 $ hg parents
187 changeset: 0:1f0dee641bb7
187 changeset: 0:1f0dee641bb7
188 user: test
188 user: test
189 date: Thu Jan 01 00:00:00 1970 +0000
189 date: Thu Jan 01 00:00:00 1970 +0000
190 summary: add a
190 summary: add a
191
191
192 No new revs, no update:
192 No new revs, no update:
193
193
194 $ hg pull -qu
194 $ hg pull -qu
195
195
196 $ hg parents -q
196 $ hg parents -q
197 0:1f0dee641bb7
197 0:1f0dee641bb7
198
198
199 $ hg rollback
199 $ hg rollback
200 repository tip rolled back to revision 1 (undo pull)
200 repository tip rolled back to revision 1 (undo pull)
201
201
202 $ hg parents -q
202 $ hg parents -q
203 0:1f0dee641bb7
203 0:1f0dee641bb7
204
204
205 Pull -u takes us back to branch foo:
205 Pull -u takes us back to branch foo:
206
206
207 $ hg pull -qu
207 $ hg pull -qu
208
208
209 $ hg parents
209 $ hg parents
210 changeset: 2:faba9097cad4
210 changeset: 2:faba9097cad4
211 branch: foo
211 branch: foo
212 tag: tip
212 tag: tip
213 user: test
213 user: test
214 date: Thu Jan 01 00:00:00 1970 +0000
214 date: Thu Jan 01 00:00:00 1970 +0000
215 summary: new head of branch foo
215 summary: new head of branch foo
216
216
217 $ hg rollback
217 $ hg rollback
218 repository tip rolled back to revision 1 (undo pull)
218 repository tip rolled back to revision 1 (undo pull)
219 working directory now based on revision 0
219 working directory now based on revision 0
220
220
221 $ hg up -C 0
221 $ hg up -C 0
222 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
222 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
223
223
224 $ hg parents -q
224 $ hg parents -q
225 0:1f0dee641bb7
225 0:1f0dee641bb7
226
226
227 $ hg heads -q
227 $ hg heads -q
228 1:cd2a86ecc814
228 1:cd2a86ecc814
229 0:1f0dee641bb7
229 0:1f0dee641bb7
230
230
231 $ hg pull -qur default default
231 $ hg pull -qur default default
232
232
233 $ hg parents
233 $ hg parents
234 changeset: 3:4cd725637392
234 changeset: 3:4cd725637392
235 tag: tip
235 tag: tip
236 parent: 0:1f0dee641bb7
236 parent: 0:1f0dee641bb7
237 user: test
237 user: test
238 date: Thu Jan 01 00:00:00 1970 +0000
238 date: Thu Jan 01 00:00:00 1970 +0000
239 summary: add bar
239 summary: add bar
240
240
241 $ hg heads
241 $ hg heads
242 changeset: 3:4cd725637392
242 changeset: 3:4cd725637392
243 tag: tip
243 tag: tip
244 parent: 0:1f0dee641bb7
244 parent: 0:1f0dee641bb7
245 user: test
245 user: test
246 date: Thu Jan 01 00:00:00 1970 +0000
246 date: Thu Jan 01 00:00:00 1970 +0000
247 summary: add bar
247 summary: add bar
248
248
249 changeset: 2:faba9097cad4
249 changeset: 2:faba9097cad4
250 branch: foo
250 branch: foo
251 user: test
251 user: test
252 date: Thu Jan 01 00:00:00 1970 +0000
252 date: Thu Jan 01 00:00:00 1970 +0000
253 summary: new head of branch foo
253 summary: new head of branch foo
254
254
255 Test handling of invalid urls
255 Test handling of invalid urls
256
256
257 $ hg id http://foo/?bar
257 $ hg id http://foo/?bar
258 abort: unsupported URL component: "bar"
258 abort: unsupported URL component: "bar"
259 [255]
259 [255]
260
260
261 $ cd ..
261 $ cd ..
262
262
263 Test handling common incoming revisions between "default" and
263 Test handling common incoming revisions between "default" and
264 "default-push"
264 "default-push"
265
265
266 $ hg -R clone rollback
266 $ hg -R clone rollback
267 repository tip rolled back to revision 1 (undo pull)
267 repository tip rolled back to revision 1 (undo pull)
268 working directory now based on revision 0
268 working directory now based on revision 0
269
269
270 $ cd repo
270 $ cd repo
271
271
272 $ hg update -q -C default
272 $ hg update -q -C default
273 $ echo modified >> bar
273 $ echo modified >> bar
274 $ hg commit -m "new head to push current default head"
274 $ hg commit -m "new head to push current default head"
275 $ hg -q push -r ".^1" '../clone'
275 $ hg -q push -r ".^1" '../clone'
276
276
277 $ hg -q outgoing '../clone'
277 $ hg -q outgoing '../clone'
278 2:faba9097cad4
278 2:faba9097cad4
279 4:d515801a8f3d
279 4:d515801a8f3d
280
280
281 $ hg summary --remote --config paths.default='../clone#default' --config paths.default-push='../clone#foo'
281 $ hg summary --remote --config paths.default='../clone#default' --config paths.default-push='../clone#foo'
282 parent: 4:d515801a8f3d tip
282 parent: 4:d515801a8f3d tip
283 new head to push current default head
283 new head to push current default head
284 branch: default
284 branch: default
285 commit: (clean)
285 commit: (clean)
286 update: (current)
286 update: (current)
287 phases: 1 draft
287 phases: 1 draft
288 remote: 1 outgoing
288 remote: 1 outgoing
289
289
290 $ hg summary --remote --config paths.default='../clone#foo' --config paths.default-push='../clone'
290 $ hg summary --remote --config paths.default='../clone#foo' --config paths.default-push='../clone'
291 parent: 4:d515801a8f3d tip
291 parent: 4:d515801a8f3d tip
292 new head to push current default head
292 new head to push current default head
293 branch: default
293 branch: default
294 commit: (clean)
294 commit: (clean)
295 update: (current)
295 update: (current)
296 phases: 1 draft
296 phases: 1 draft
297 remote: 2 outgoing
297 remote: 2 outgoing
298
298
299 $ hg summary --remote --config paths.default='../clone' --config paths.default-push='../clone#foo'
299 $ hg summary --remote --config paths.default='../clone' --config paths.default-push='../clone#foo'
300 parent: 4:d515801a8f3d tip
300 parent: 4:d515801a8f3d tip
301 new head to push current default head
301 new head to push current default head
302 branch: default
302 branch: default
303 commit: (clean)
303 commit: (clean)
304 update: (current)
304 update: (current)
305 phases: 1 draft
305 phases: 1 draft
306 remote: 1 outgoing
306 remote: 1 outgoing
307
307
308 $ hg clone -q -r 0 . ../another
308 $ hg clone -q -r 0 . ../another
309 $ hg -q outgoing '../another#default'
309 $ hg -q outgoing '../another#default'
310 3:4cd725637392
310 3:4cd725637392
311 4:d515801a8f3d
311 4:d515801a8f3d
312
312
313 $ hg summary --remote --config paths.default='../another#default' --config paths.default-push='../clone#default'
313 $ hg summary --remote --config paths.default='../another#default' --config paths.default-push='../clone#default'
314 parent: 4:d515801a8f3d tip
314 parent: 4:d515801a8f3d tip
315 new head to push current default head
315 new head to push current default head
316 branch: default
316 branch: default
317 commit: (clean)
317 commit: (clean)
318 update: (current)
318 update: (current)
319 phases: 1 draft
319 phases: 1 draft
320 remote: 1 outgoing
320 remote: 1 outgoing
321
321
322 $ cd ..
322 $ cd ..
323
323
324 Test url#rev syntax of local destination path, which should be taken as
324 Test url#rev syntax of local destination path, which should be taken as
325 a 'url#rev' path
325 a 'url#rev' path
326
326
327 $ hg clone repo '#foo'
327 $ hg clone repo '#foo'
328 updating to branch default
328 updating to branch default
329 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
330 $ hg root -R '#foo'
330 $ hg root -R '#foo'
331 $TESTTMP/#foo (glob)
331 $TESTTMP/#foo (glob)
General Comments 0
You need to be logged in to leave comments. Login now