##// END OF EJS Templates
keyword: fix weeding of expansion candidates when recording...
Christian Ebert -
r12684:8348599c default
parent child Browse files
Show More
@@ -1,619 +1,620 b''
1 # keyword.py - $Keyword$ expansion for Mercurial
1 # keyword.py - $Keyword$ expansion for Mercurial
2 #
2 #
3 # Copyright 2007-2010 Christian Ebert <blacktrash@gmx.net>
3 # Copyright 2007-2010 Christian Ebert <blacktrash@gmx.net>
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 # $Id$
8 # $Id$
9 #
9 #
10 # Keyword expansion hack against the grain of a DSCM
10 # Keyword expansion hack against the grain of a DSCM
11 #
11 #
12 # There are many good reasons why this is not needed in a distributed
12 # There are many good reasons why this is not needed in a distributed
13 # SCM, still it may be useful in very small projects based on single
13 # SCM, still it may be useful in very small projects based on single
14 # files (like LaTeX packages), that are mostly addressed to an
14 # files (like LaTeX packages), that are mostly addressed to an
15 # audience not running a version control system.
15 # audience not running a version control system.
16 #
16 #
17 # For in-depth discussion refer to
17 # For in-depth discussion refer to
18 # <http://mercurial.selenic.com/wiki/KeywordPlan>.
18 # <http://mercurial.selenic.com/wiki/KeywordPlan>.
19 #
19 #
20 # Keyword expansion is based on Mercurial's changeset template mappings.
20 # Keyword expansion is based on Mercurial's changeset template mappings.
21 #
21 #
22 # Binary files are not touched.
22 # Binary files are not touched.
23 #
23 #
24 # Files to act upon/ignore are specified in the [keyword] section.
24 # Files to act upon/ignore are specified in the [keyword] section.
25 # Customized keyword template mappings in the [keywordmaps] section.
25 # Customized keyword template mappings in the [keywordmaps] section.
26 #
26 #
27 # Run "hg help keyword" and "hg kwdemo" to get info on configuration.
27 # Run "hg help keyword" and "hg kwdemo" to get info on configuration.
28
28
29 '''expand keywords in tracked files
29 '''expand keywords in tracked files
30
30
31 This extension expands RCS/CVS-like or self-customized $Keywords$ in
31 This extension expands RCS/CVS-like or self-customized $Keywords$ in
32 tracked text files selected by your configuration.
32 tracked text files selected by your configuration.
33
33
34 Keywords are only expanded in local repositories and not stored in the
34 Keywords are only expanded in local repositories and not stored in the
35 change history. The mechanism can be regarded as a convenience for the
35 change history. The mechanism can be regarded as a convenience for the
36 current user or for archive distribution.
36 current user or for archive distribution.
37
37
38 Keywords expand to the changeset data pertaining to the latest change
38 Keywords expand to the changeset data pertaining to the latest change
39 relative to the working directory parent of each file.
39 relative to the working directory parent of each file.
40
40
41 Configuration is done in the [keyword], [keywordset] and [keywordmaps]
41 Configuration is done in the [keyword], [keywordset] and [keywordmaps]
42 sections of hgrc files.
42 sections of hgrc files.
43
43
44 Example::
44 Example::
45
45
46 [keyword]
46 [keyword]
47 # expand keywords in every python file except those matching "x*"
47 # expand keywords in every python file except those matching "x*"
48 **.py =
48 **.py =
49 x* = ignore
49 x* = ignore
50
50
51 [keywordset]
51 [keywordset]
52 # prefer svn- over cvs-like default keywordmaps
52 # prefer svn- over cvs-like default keywordmaps
53 svn = True
53 svn = True
54
54
55 .. note::
55 .. note::
56 The more specific you are in your filename patterns the less you
56 The more specific you are in your filename patterns the less you
57 lose speed in huge repositories.
57 lose speed in huge repositories.
58
58
59 For [keywordmaps] template mapping and expansion demonstration and
59 For [keywordmaps] template mapping and expansion demonstration and
60 control run :hg:`kwdemo`. See :hg:`help templates` for a list of
60 control run :hg:`kwdemo`. See :hg:`help templates` for a list of
61 available templates and filters.
61 available templates and filters.
62
62
63 Three additional date template filters are provided::
63 Three additional date template filters are provided::
64
64
65 utcdate "2006/09/18 15:13:13"
65 utcdate "2006/09/18 15:13:13"
66 svnutcdate "2006-09-18 15:13:13Z"
66 svnutcdate "2006-09-18 15:13:13Z"
67 svnisodate "2006-09-18 08:13:13 -700 (Mon, 18 Sep 2006)"
67 svnisodate "2006-09-18 08:13:13 -700 (Mon, 18 Sep 2006)"
68
68
69 The default template mappings (view with :hg:`kwdemo -d`) can be
69 The default template mappings (view with :hg:`kwdemo -d`) can be
70 replaced with customized keywords and templates. Again, run
70 replaced with customized keywords and templates. Again, run
71 :hg:`kwdemo` to control the results of your config changes.
71 :hg:`kwdemo` to control the results of your config changes.
72
72
73 Before changing/disabling active keywords, run :hg:`kwshrink` to avoid
73 Before changing/disabling active keywords, run :hg:`kwshrink` to avoid
74 the risk of inadvertently storing expanded keywords in the change
74 the risk of inadvertently storing expanded keywords in the change
75 history.
75 history.
76
76
77 To force expansion after enabling it, or a configuration change, run
77 To force expansion after enabling it, or a configuration change, run
78 :hg:`kwexpand`.
78 :hg:`kwexpand`.
79
79
80 Expansions spanning more than one line and incremental expansions,
80 Expansions spanning more than one line and incremental expansions,
81 like CVS' $Log$, are not supported. A keyword template map "Log =
81 like CVS' $Log$, are not supported. A keyword template map "Log =
82 {desc}" expands to the first line of the changeset description.
82 {desc}" expands to the first line of the changeset description.
83 '''
83 '''
84
84
85 from mercurial import commands, cmdutil, dispatch, filelog, extensions
85 from mercurial import commands, cmdutil, dispatch, filelog, extensions
86 from mercurial import localrepo, match, patch, templatefilters, templater, util
86 from mercurial import localrepo, match, patch, templatefilters, templater, util
87 from mercurial.hgweb import webcommands
87 from mercurial.hgweb import webcommands
88 from mercurial.i18n import _
88 from mercurial.i18n import _
89 import re, shutil, tempfile
89 import re, shutil, tempfile
90
90
91 commands.optionalrepo += ' kwdemo'
91 commands.optionalrepo += ' kwdemo'
92
92
93 # hg commands that do not act on keywords
93 # hg commands that do not act on keywords
94 nokwcommands = ('add addremove annotate bundle export grep incoming init log'
94 nokwcommands = ('add addremove annotate bundle export grep incoming init log'
95 ' outgoing push tip verify convert email glog')
95 ' outgoing push tip verify convert email glog')
96
96
97 # hg commands that trigger expansion only when writing to working dir,
97 # hg commands that trigger expansion only when writing to working dir,
98 # not when reading filelog, and unexpand when reading from working dir
98 # not when reading filelog, and unexpand when reading from working dir
99 restricted = 'merge kwexpand kwshrink record qrecord resolve transplant'
99 restricted = 'merge kwexpand kwshrink record qrecord resolve transplant'
100
100
101 # names of extensions using dorecord
101 # names of extensions using dorecord
102 recordextensions = 'record'
102 recordextensions = 'record'
103
103
104 # date like in cvs' $Date
104 # date like in cvs' $Date
105 utcdate = lambda x: util.datestr((x[0], 0), '%Y/%m/%d %H:%M:%S')
105 utcdate = lambda x: util.datestr((x[0], 0), '%Y/%m/%d %H:%M:%S')
106 # date like in svn's $Date
106 # date like in svn's $Date
107 svnisodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
107 svnisodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
108 # date like in svn's $Id
108 # date like in svn's $Id
109 svnutcdate = lambda x: util.datestr((x[0], 0), '%Y-%m-%d %H:%M:%SZ')
109 svnutcdate = lambda x: util.datestr((x[0], 0), '%Y-%m-%d %H:%M:%SZ')
110
110
111 # make keyword tools accessible
111 # make keyword tools accessible
112 kwtools = {'templater': None, 'hgcmd': ''}
112 kwtools = {'templater': None, 'hgcmd': ''}
113
113
114
114
115 def _defaultkwmaps(ui):
115 def _defaultkwmaps(ui):
116 '''Returns default keywordmaps according to keywordset configuration.'''
116 '''Returns default keywordmaps according to keywordset configuration.'''
117 templates = {
117 templates = {
118 'Revision': '{node|short}',
118 'Revision': '{node|short}',
119 'Author': '{author|user}',
119 'Author': '{author|user}',
120 }
120 }
121 kwsets = ({
121 kwsets = ({
122 'Date': '{date|utcdate}',
122 'Date': '{date|utcdate}',
123 'RCSfile': '{file|basename},v',
123 'RCSfile': '{file|basename},v',
124 'RCSFile': '{file|basename},v', # kept for backwards compatibility
124 'RCSFile': '{file|basename},v', # kept for backwards compatibility
125 # with hg-keyword
125 # with hg-keyword
126 'Source': '{root}/{file},v',
126 'Source': '{root}/{file},v',
127 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
127 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
128 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
128 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
129 }, {
129 }, {
130 'Date': '{date|svnisodate}',
130 'Date': '{date|svnisodate}',
131 'Id': '{file|basename},v {node|short} {date|svnutcdate} {author|user}',
131 'Id': '{file|basename},v {node|short} {date|svnutcdate} {author|user}',
132 'LastChangedRevision': '{node|short}',
132 'LastChangedRevision': '{node|short}',
133 'LastChangedBy': '{author|user}',
133 'LastChangedBy': '{author|user}',
134 'LastChangedDate': '{date|svnisodate}',
134 'LastChangedDate': '{date|svnisodate}',
135 })
135 })
136 templates.update(kwsets[ui.configbool('keywordset', 'svn')])
136 templates.update(kwsets[ui.configbool('keywordset', 'svn')])
137 return templates
137 return templates
138
138
139 def _shrinktext(text, subfunc):
139 def _shrinktext(text, subfunc):
140 '''Helper for keyword expansion removal in text.
140 '''Helper for keyword expansion removal in text.
141 Depending on subfunc also returns number of substitutions.'''
141 Depending on subfunc also returns number of substitutions.'''
142 return subfunc(r'$\1$', text)
142 return subfunc(r'$\1$', text)
143
143
144
144
145 class kwtemplater(object):
145 class kwtemplater(object):
146 '''
146 '''
147 Sets up keyword templates, corresponding keyword regex, and
147 Sets up keyword templates, corresponding keyword regex, and
148 provides keyword substitution functions.
148 provides keyword substitution functions.
149 '''
149 '''
150
150
151 def __init__(self, ui, repo, inc, exc):
151 def __init__(self, ui, repo, inc, exc):
152 self.ui = ui
152 self.ui = ui
153 self.repo = repo
153 self.repo = repo
154 self.match = match.match(repo.root, '', [], inc, exc)
154 self.match = match.match(repo.root, '', [], inc, exc)
155 self.restrict = kwtools['hgcmd'] in restricted.split()
155 self.restrict = kwtools['hgcmd'] in restricted.split()
156 self.record = False
156 self.record = False
157
157
158 kwmaps = self.ui.configitems('keywordmaps')
158 kwmaps = self.ui.configitems('keywordmaps')
159 if kwmaps: # override default templates
159 if kwmaps: # override default templates
160 self.templates = dict((k, templater.parsestring(v, False))
160 self.templates = dict((k, templater.parsestring(v, False))
161 for k, v in kwmaps)
161 for k, v in kwmaps)
162 else:
162 else:
163 self.templates = _defaultkwmaps(self.ui)
163 self.templates = _defaultkwmaps(self.ui)
164 escaped = '|'.join(map(re.escape, self.templates.keys()))
164 escaped = '|'.join(map(re.escape, self.templates.keys()))
165 self.re_kw = re.compile(r'\$(%s)\$' % escaped)
165 self.re_kw = re.compile(r'\$(%s)\$' % escaped)
166 self.re_kwexp = re.compile(r'\$(%s): [^$\n\r]*? \$' % escaped)
166 self.re_kwexp = re.compile(r'\$(%s): [^$\n\r]*? \$' % escaped)
167
167
168 templatefilters.filters.update({'utcdate': utcdate,
168 templatefilters.filters.update({'utcdate': utcdate,
169 'svnisodate': svnisodate,
169 'svnisodate': svnisodate,
170 'svnutcdate': svnutcdate})
170 'svnutcdate': svnutcdate})
171
171
172 def substitute(self, data, path, ctx, subfunc):
172 def substitute(self, data, path, ctx, subfunc):
173 '''Replaces keywords in data with expanded template.'''
173 '''Replaces keywords in data with expanded template.'''
174 def kwsub(mobj):
174 def kwsub(mobj):
175 kw = mobj.group(1)
175 kw = mobj.group(1)
176 ct = cmdutil.changeset_templater(self.ui, self.repo,
176 ct = cmdutil.changeset_templater(self.ui, self.repo,
177 False, None, '', False)
177 False, None, '', False)
178 ct.use_template(self.templates[kw])
178 ct.use_template(self.templates[kw])
179 self.ui.pushbuffer()
179 self.ui.pushbuffer()
180 ct.show(ctx, root=self.repo.root, file=path)
180 ct.show(ctx, root=self.repo.root, file=path)
181 ekw = templatefilters.firstline(self.ui.popbuffer())
181 ekw = templatefilters.firstline(self.ui.popbuffer())
182 return '$%s: %s $' % (kw, ekw)
182 return '$%s: %s $' % (kw, ekw)
183 return subfunc(kwsub, data)
183 return subfunc(kwsub, data)
184
184
185 def expand(self, path, node, data):
185 def expand(self, path, node, data):
186 '''Returns data with keywords expanded.'''
186 '''Returns data with keywords expanded.'''
187 if not self.restrict and self.match(path) and not util.binary(data):
187 if not self.restrict and self.match(path) and not util.binary(data):
188 ctx = self.repo.filectx(path, fileid=node).changectx()
188 ctx = self.repo.filectx(path, fileid=node).changectx()
189 return self.substitute(data, path, ctx, self.re_kw.sub)
189 return self.substitute(data, path, ctx, self.re_kw.sub)
190 return data
190 return data
191
191
192 def iskwfile(self, cand, ctx):
192 def iskwfile(self, cand, ctx):
193 '''Returns subset of candidates which are configured for keyword
193 '''Returns subset of candidates which are configured for keyword
194 expansion are not symbolic links.'''
194 expansion are not symbolic links.'''
195 return [f for f in cand if self.match(f) and not 'l' in ctx.flags(f)]
195 return [f for f in cand if self.match(f) and not 'l' in ctx.flags(f)]
196
196
197 def overwrite(self, ctx, candidates, lookup, expand, recsubn=None):
197 def overwrite(self, ctx, candidates, lookup, expand, recsubn=None):
198 '''Overwrites selected files expanding/shrinking keywords.'''
198 '''Overwrites selected files expanding/shrinking keywords.'''
199 if self.restrict or lookup: # exclude kw_copy
199 if self.restrict or lookup: # exclude kw_copy
200 candidates = self.iskwfile(candidates, ctx)
200 candidates = self.iskwfile(candidates, ctx)
201 if not candidates:
201 if not candidates:
202 return
202 return
203 commit = self.restrict and not lookup
203 commit = self.restrict and not lookup
204 if self.restrict or expand and lookup:
204 if self.restrict or expand and lookup:
205 mf = ctx.manifest()
205 mf = ctx.manifest()
206 fctx = ctx
206 fctx = ctx
207 subn = (self.restrict and self.re_kw.subn or
207 subn = (self.restrict and self.re_kw.subn or
208 recsubn or self.re_kwexp.subn)
208 recsubn or self.re_kwexp.subn)
209 msg = (expand and _('overwriting %s expanding keywords\n')
209 msg = (expand and _('overwriting %s expanding keywords\n')
210 or _('overwriting %s shrinking keywords\n'))
210 or _('overwriting %s shrinking keywords\n'))
211 for f in candidates:
211 for f in candidates:
212 if self.restrict:
212 if self.restrict:
213 data = self.repo.file(f).read(mf[f])
213 data = self.repo.file(f).read(mf[f])
214 else:
214 else:
215 data = self.repo.wread(f)
215 data = self.repo.wread(f)
216 if util.binary(data):
216 if util.binary(data):
217 continue
217 continue
218 if expand:
218 if expand:
219 if lookup:
219 if lookup:
220 fctx = self.repo.filectx(f, fileid=mf[f]).changectx()
220 fctx = self.repo.filectx(f, fileid=mf[f]).changectx()
221 data, found = self.substitute(data, f, fctx, subn)
221 data, found = self.substitute(data, f, fctx, subn)
222 elif self.restrict:
222 elif self.restrict:
223 found = self.re_kw.search(data)
223 found = self.re_kw.search(data)
224 else:
224 else:
225 data, found = _shrinktext(data, subn)
225 data, found = _shrinktext(data, subn)
226 if found:
226 if found:
227 self.ui.note(msg % f)
227 self.ui.note(msg % f)
228 self.repo.wwrite(f, data, ctx.flags(f))
228 self.repo.wwrite(f, data, ctx.flags(f))
229 if commit:
229 if commit:
230 self.repo.dirstate.normal(f)
230 self.repo.dirstate.normal(f)
231 elif self.record:
231 elif self.record:
232 self.repo.dirstate.normallookup(f)
232 self.repo.dirstate.normallookup(f)
233
233
234 def shrink(self, fname, text):
234 def shrink(self, fname, text):
235 '''Returns text with all keyword substitutions removed.'''
235 '''Returns text with all keyword substitutions removed.'''
236 if self.match(fname) and not util.binary(text):
236 if self.match(fname) and not util.binary(text):
237 return _shrinktext(text, self.re_kwexp.sub)
237 return _shrinktext(text, self.re_kwexp.sub)
238 return text
238 return text
239
239
240 def shrinklines(self, fname, lines):
240 def shrinklines(self, fname, lines):
241 '''Returns lines with keyword substitutions removed.'''
241 '''Returns lines with keyword substitutions removed.'''
242 if self.match(fname):
242 if self.match(fname):
243 text = ''.join(lines)
243 text = ''.join(lines)
244 if not util.binary(text):
244 if not util.binary(text):
245 return _shrinktext(text, self.re_kwexp.sub).splitlines(True)
245 return _shrinktext(text, self.re_kwexp.sub).splitlines(True)
246 return lines
246 return lines
247
247
248 def wread(self, fname, data):
248 def wread(self, fname, data):
249 '''If in restricted mode returns data read from wdir with
249 '''If in restricted mode returns data read from wdir with
250 keyword substitutions removed.'''
250 keyword substitutions removed.'''
251 return self.restrict and self.shrink(fname, data) or data
251 return self.restrict and self.shrink(fname, data) or data
252
252
253 class kwfilelog(filelog.filelog):
253 class kwfilelog(filelog.filelog):
254 '''
254 '''
255 Subclass of filelog to hook into its read, add, cmp methods.
255 Subclass of filelog to hook into its read, add, cmp methods.
256 Keywords are "stored" unexpanded, and processed on reading.
256 Keywords are "stored" unexpanded, and processed on reading.
257 '''
257 '''
258 def __init__(self, opener, kwt, path):
258 def __init__(self, opener, kwt, path):
259 super(kwfilelog, self).__init__(opener, path)
259 super(kwfilelog, self).__init__(opener, path)
260 self.kwt = kwt
260 self.kwt = kwt
261 self.path = path
261 self.path = path
262
262
263 def read(self, node):
263 def read(self, node):
264 '''Expands keywords when reading filelog.'''
264 '''Expands keywords when reading filelog.'''
265 data = super(kwfilelog, self).read(node)
265 data = super(kwfilelog, self).read(node)
266 if self.renamed(node):
266 if self.renamed(node):
267 return data
267 return data
268 return self.kwt.expand(self.path, node, data)
268 return self.kwt.expand(self.path, node, data)
269
269
270 def add(self, text, meta, tr, link, p1=None, p2=None):
270 def add(self, text, meta, tr, link, p1=None, p2=None):
271 '''Removes keyword substitutions when adding to filelog.'''
271 '''Removes keyword substitutions when adding to filelog.'''
272 text = self.kwt.shrink(self.path, text)
272 text = self.kwt.shrink(self.path, text)
273 return super(kwfilelog, self).add(text, meta, tr, link, p1, p2)
273 return super(kwfilelog, self).add(text, meta, tr, link, p1, p2)
274
274
275 def cmp(self, node, text):
275 def cmp(self, node, text):
276 '''Removes keyword substitutions for comparison.'''
276 '''Removes keyword substitutions for comparison.'''
277 text = self.kwt.shrink(self.path, text)
277 text = self.kwt.shrink(self.path, text)
278 return super(kwfilelog, self).cmp(node, text)
278 return super(kwfilelog, self).cmp(node, text)
279
279
280 def _status(ui, repo, kwt, *pats, **opts):
280 def _status(ui, repo, kwt, *pats, **opts):
281 '''Bails out if [keyword] configuration is not active.
281 '''Bails out if [keyword] configuration is not active.
282 Returns status of working directory.'''
282 Returns status of working directory.'''
283 if kwt:
283 if kwt:
284 return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
284 return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
285 unknown=opts.get('unknown') or opts.get('all'))
285 unknown=opts.get('unknown') or opts.get('all'))
286 if ui.configitems('keyword'):
286 if ui.configitems('keyword'):
287 raise util.Abort(_('[keyword] patterns cannot match'))
287 raise util.Abort(_('[keyword] patterns cannot match'))
288 raise util.Abort(_('no [keyword] patterns configured'))
288 raise util.Abort(_('no [keyword] patterns configured'))
289
289
290 def _kwfwrite(ui, repo, expand, *pats, **opts):
290 def _kwfwrite(ui, repo, expand, *pats, **opts):
291 '''Selects files and passes them to kwtemplater.overwrite.'''
291 '''Selects files and passes them to kwtemplater.overwrite.'''
292 wctx = repo[None]
292 wctx = repo[None]
293 if len(wctx.parents()) > 1:
293 if len(wctx.parents()) > 1:
294 raise util.Abort(_('outstanding uncommitted merge'))
294 raise util.Abort(_('outstanding uncommitted merge'))
295 kwt = kwtools['templater']
295 kwt = kwtools['templater']
296 wlock = repo.wlock()
296 wlock = repo.wlock()
297 try:
297 try:
298 status = _status(ui, repo, kwt, *pats, **opts)
298 status = _status(ui, repo, kwt, *pats, **opts)
299 modified, added, removed, deleted, unknown, ignored, clean = status
299 modified, added, removed, deleted, unknown, ignored, clean = status
300 if modified or added or removed or deleted:
300 if modified or added or removed or deleted:
301 raise util.Abort(_('outstanding uncommitted changes'))
301 raise util.Abort(_('outstanding uncommitted changes'))
302 kwt.overwrite(wctx, clean, True, expand)
302 kwt.overwrite(wctx, clean, True, expand)
303 finally:
303 finally:
304 wlock.release()
304 wlock.release()
305
305
306 def demo(ui, repo, *args, **opts):
306 def demo(ui, repo, *args, **opts):
307 '''print [keywordmaps] configuration and an expansion example
307 '''print [keywordmaps] configuration and an expansion example
308
308
309 Show current, custom, or default keyword template maps and their
309 Show current, custom, or default keyword template maps and their
310 expansions.
310 expansions.
311
311
312 Extend the current configuration by specifying maps as arguments
312 Extend the current configuration by specifying maps as arguments
313 and using -f/--rcfile to source an external hgrc file.
313 and using -f/--rcfile to source an external hgrc file.
314
314
315 Use -d/--default to disable current configuration.
315 Use -d/--default to disable current configuration.
316
316
317 See :hg:`help templates` for information on templates and filters.
317 See :hg:`help templates` for information on templates and filters.
318 '''
318 '''
319 def demoitems(section, items):
319 def demoitems(section, items):
320 ui.write('[%s]\n' % section)
320 ui.write('[%s]\n' % section)
321 for k, v in sorted(items):
321 for k, v in sorted(items):
322 ui.write('%s = %s\n' % (k, v))
322 ui.write('%s = %s\n' % (k, v))
323
323
324 fn = 'demo.txt'
324 fn = 'demo.txt'
325 tmpdir = tempfile.mkdtemp('', 'kwdemo.')
325 tmpdir = tempfile.mkdtemp('', 'kwdemo.')
326 ui.note(_('creating temporary repository at %s\n') % tmpdir)
326 ui.note(_('creating temporary repository at %s\n') % tmpdir)
327 repo = localrepo.localrepository(ui, tmpdir, True)
327 repo = localrepo.localrepository(ui, tmpdir, True)
328 ui.setconfig('keyword', fn, '')
328 ui.setconfig('keyword', fn, '')
329
329
330 uikwmaps = ui.configitems('keywordmaps')
330 uikwmaps = ui.configitems('keywordmaps')
331 if args or opts.get('rcfile'):
331 if args or opts.get('rcfile'):
332 ui.status(_('\n\tconfiguration using custom keyword template maps\n'))
332 ui.status(_('\n\tconfiguration using custom keyword template maps\n'))
333 if uikwmaps:
333 if uikwmaps:
334 ui.status(_('\textending current template maps\n'))
334 ui.status(_('\textending current template maps\n'))
335 if opts.get('default') or not uikwmaps:
335 if opts.get('default') or not uikwmaps:
336 ui.status(_('\toverriding default template maps\n'))
336 ui.status(_('\toverriding default template maps\n'))
337 if opts.get('rcfile'):
337 if opts.get('rcfile'):
338 ui.readconfig(opts.get('rcfile'))
338 ui.readconfig(opts.get('rcfile'))
339 if args:
339 if args:
340 # simulate hgrc parsing
340 # simulate hgrc parsing
341 rcmaps = ['[keywordmaps]\n'] + [a + '\n' for a in args]
341 rcmaps = ['[keywordmaps]\n'] + [a + '\n' for a in args]
342 fp = repo.opener('hgrc', 'w')
342 fp = repo.opener('hgrc', 'w')
343 fp.writelines(rcmaps)
343 fp.writelines(rcmaps)
344 fp.close()
344 fp.close()
345 ui.readconfig(repo.join('hgrc'))
345 ui.readconfig(repo.join('hgrc'))
346 kwmaps = dict(ui.configitems('keywordmaps'))
346 kwmaps = dict(ui.configitems('keywordmaps'))
347 elif opts.get('default'):
347 elif opts.get('default'):
348 ui.status(_('\n\tconfiguration using default keyword template maps\n'))
348 ui.status(_('\n\tconfiguration using default keyword template maps\n'))
349 kwmaps = _defaultkwmaps(ui)
349 kwmaps = _defaultkwmaps(ui)
350 if uikwmaps:
350 if uikwmaps:
351 ui.status(_('\tdisabling current template maps\n'))
351 ui.status(_('\tdisabling current template maps\n'))
352 for k, v in kwmaps.iteritems():
352 for k, v in kwmaps.iteritems():
353 ui.setconfig('keywordmaps', k, v)
353 ui.setconfig('keywordmaps', k, v)
354 else:
354 else:
355 ui.status(_('\n\tconfiguration using current keyword template maps\n'))
355 ui.status(_('\n\tconfiguration using current keyword template maps\n'))
356 kwmaps = dict(uikwmaps) or _defaultkwmaps(ui)
356 kwmaps = dict(uikwmaps) or _defaultkwmaps(ui)
357
357
358 uisetup(ui)
358 uisetup(ui)
359 reposetup(ui, repo)
359 reposetup(ui, repo)
360 ui.write('[extensions]\nkeyword =\n')
360 ui.write('[extensions]\nkeyword =\n')
361 demoitems('keyword', ui.configitems('keyword'))
361 demoitems('keyword', ui.configitems('keyword'))
362 demoitems('keywordmaps', kwmaps.iteritems())
362 demoitems('keywordmaps', kwmaps.iteritems())
363 keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
363 keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
364 repo.wopener(fn, 'w').write(keywords)
364 repo.wopener(fn, 'w').write(keywords)
365 repo[None].add([fn])
365 repo[None].add([fn])
366 ui.note(_('\nkeywords written to %s:\n') % fn)
366 ui.note(_('\nkeywords written to %s:\n') % fn)
367 ui.note(keywords)
367 ui.note(keywords)
368 repo.dirstate.setbranch('demobranch')
368 repo.dirstate.setbranch('demobranch')
369 for name, cmd in ui.configitems('hooks'):
369 for name, cmd in ui.configitems('hooks'):
370 if name.split('.', 1)[0].find('commit') > -1:
370 if name.split('.', 1)[0].find('commit') > -1:
371 repo.ui.setconfig('hooks', name, '')
371 repo.ui.setconfig('hooks', name, '')
372 msg = _('hg keyword configuration and expansion example')
372 msg = _('hg keyword configuration and expansion example')
373 ui.note("hg ci -m '%s'\n" % msg)
373 ui.note("hg ci -m '%s'\n" % msg)
374 repo.commit(text=msg)
374 repo.commit(text=msg)
375 ui.status(_('\n\tkeywords expanded\n'))
375 ui.status(_('\n\tkeywords expanded\n'))
376 ui.write(repo.wread(fn))
376 ui.write(repo.wread(fn))
377 shutil.rmtree(tmpdir, ignore_errors=True)
377 shutil.rmtree(tmpdir, ignore_errors=True)
378
378
379 def expand(ui, repo, *pats, **opts):
379 def expand(ui, repo, *pats, **opts):
380 '''expand keywords in the working directory
380 '''expand keywords in the working directory
381
381
382 Run after (re)enabling keyword expansion.
382 Run after (re)enabling keyword expansion.
383
383
384 kwexpand refuses to run if given files contain local changes.
384 kwexpand refuses to run if given files contain local changes.
385 '''
385 '''
386 # 3rd argument sets expansion to True
386 # 3rd argument sets expansion to True
387 _kwfwrite(ui, repo, True, *pats, **opts)
387 _kwfwrite(ui, repo, True, *pats, **opts)
388
388
389 def files(ui, repo, *pats, **opts):
389 def files(ui, repo, *pats, **opts):
390 '''show files configured for keyword expansion
390 '''show files configured for keyword expansion
391
391
392 List which files in the working directory are matched by the
392 List which files in the working directory are matched by the
393 [keyword] configuration patterns.
393 [keyword] configuration patterns.
394
394
395 Useful to prevent inadvertent keyword expansion and to speed up
395 Useful to prevent inadvertent keyword expansion and to speed up
396 execution by including only files that are actual candidates for
396 execution by including only files that are actual candidates for
397 expansion.
397 expansion.
398
398
399 See :hg:`help keyword` on how to construct patterns both for
399 See :hg:`help keyword` on how to construct patterns both for
400 inclusion and exclusion of files.
400 inclusion and exclusion of files.
401
401
402 With -A/--all and -v/--verbose the codes used to show the status
402 With -A/--all and -v/--verbose the codes used to show the status
403 of files are::
403 of files are::
404
404
405 K = keyword expansion candidate
405 K = keyword expansion candidate
406 k = keyword expansion candidate (not tracked)
406 k = keyword expansion candidate (not tracked)
407 I = ignored
407 I = ignored
408 i = ignored (not tracked)
408 i = ignored (not tracked)
409 '''
409 '''
410 kwt = kwtools['templater']
410 kwt = kwtools['templater']
411 status = _status(ui, repo, kwt, *pats, **opts)
411 status = _status(ui, repo, kwt, *pats, **opts)
412 cwd = pats and repo.getcwd() or ''
412 cwd = pats and repo.getcwd() or ''
413 modified, added, removed, deleted, unknown, ignored, clean = status
413 modified, added, removed, deleted, unknown, ignored, clean = status
414 files = []
414 files = []
415 if not opts.get('unknown') or opts.get('all'):
415 if not opts.get('unknown') or opts.get('all'):
416 files = sorted(modified + added + clean)
416 files = sorted(modified + added + clean)
417 wctx = repo[None]
417 wctx = repo[None]
418 kwfiles = kwt.iskwfile(files, wctx)
418 kwfiles = kwt.iskwfile(files, wctx)
419 kwunknown = kwt.iskwfile(unknown, wctx)
419 kwunknown = kwt.iskwfile(unknown, wctx)
420 if not opts.get('ignore') or opts.get('all'):
420 if not opts.get('ignore') or opts.get('all'):
421 showfiles = kwfiles, kwunknown
421 showfiles = kwfiles, kwunknown
422 else:
422 else:
423 showfiles = [], []
423 showfiles = [], []
424 if opts.get('all') or opts.get('ignore'):
424 if opts.get('all') or opts.get('ignore'):
425 showfiles += ([f for f in files if f not in kwfiles],
425 showfiles += ([f for f in files if f not in kwfiles],
426 [f for f in unknown if f not in kwunknown])
426 [f for f in unknown if f not in kwunknown])
427 for char, filenames in zip('KkIi', showfiles):
427 for char, filenames in zip('KkIi', showfiles):
428 fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
428 fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
429 for f in filenames:
429 for f in filenames:
430 ui.write(fmt % repo.pathto(f, cwd))
430 ui.write(fmt % repo.pathto(f, cwd))
431
431
432 def shrink(ui, repo, *pats, **opts):
432 def shrink(ui, repo, *pats, **opts):
433 '''revert expanded keywords in the working directory
433 '''revert expanded keywords in the working directory
434
434
435 Run before changing/disabling active keywords or if you experience
435 Run before changing/disabling active keywords or if you experience
436 problems with :hg:`import` or :hg:`merge`.
436 problems with :hg:`import` or :hg:`merge`.
437
437
438 kwshrink refuses to run if given files contain local changes.
438 kwshrink refuses to run if given files contain local changes.
439 '''
439 '''
440 # 3rd argument sets expansion to False
440 # 3rd argument sets expansion to False
441 _kwfwrite(ui, repo, False, *pats, **opts)
441 _kwfwrite(ui, repo, False, *pats, **opts)
442
442
443
443
444 def uisetup(ui):
444 def uisetup(ui):
445 ''' Monkeypatches dispatch._parse to retrieve user command.'''
445 ''' Monkeypatches dispatch._parse to retrieve user command.'''
446
446
447 def kwdispatch_parse(orig, ui, args):
447 def kwdispatch_parse(orig, ui, args):
448 '''Monkeypatch dispatch._parse to obtain running hg command.'''
448 '''Monkeypatch dispatch._parse to obtain running hg command.'''
449 cmd, func, args, options, cmdoptions = orig(ui, args)
449 cmd, func, args, options, cmdoptions = orig(ui, args)
450 kwtools['hgcmd'] = cmd
450 kwtools['hgcmd'] = cmd
451 return cmd, func, args, options, cmdoptions
451 return cmd, func, args, options, cmdoptions
452
452
453 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
453 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
454
454
455 def reposetup(ui, repo):
455 def reposetup(ui, repo):
456 '''Sets up repo as kwrepo for keyword substitution.
456 '''Sets up repo as kwrepo for keyword substitution.
457 Overrides file method to return kwfilelog instead of filelog
457 Overrides file method to return kwfilelog instead of filelog
458 if file matches user configuration.
458 if file matches user configuration.
459 Wraps commit to overwrite configured files with updated
459 Wraps commit to overwrite configured files with updated
460 keyword substitutions.
460 keyword substitutions.
461 Monkeypatches patch and webcommands.'''
461 Monkeypatches patch and webcommands.'''
462
462
463 try:
463 try:
464 if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split()
464 if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split()
465 or '.hg' in util.splitpath(repo.root)
465 or '.hg' in util.splitpath(repo.root)
466 or repo._url.startswith('bundle:')):
466 or repo._url.startswith('bundle:')):
467 return
467 return
468 except AttributeError:
468 except AttributeError:
469 pass
469 pass
470
470
471 inc, exc = [], ['.hg*']
471 inc, exc = [], ['.hg*']
472 for pat, opt in ui.configitems('keyword'):
472 for pat, opt in ui.configitems('keyword'):
473 if opt != 'ignore':
473 if opt != 'ignore':
474 inc.append(pat)
474 inc.append(pat)
475 else:
475 else:
476 exc.append(pat)
476 exc.append(pat)
477 if not inc:
477 if not inc:
478 return
478 return
479
479
480 kwtools['templater'] = kwt = kwtemplater(ui, repo, inc, exc)
480 kwtools['templater'] = kwt = kwtemplater(ui, repo, inc, exc)
481
481
482 class kwrepo(repo.__class__):
482 class kwrepo(repo.__class__):
483 def file(self, f):
483 def file(self, f):
484 if f[0] == '/':
484 if f[0] == '/':
485 f = f[1:]
485 f = f[1:]
486 return kwfilelog(self.sopener, kwt, f)
486 return kwfilelog(self.sopener, kwt, f)
487
487
488 def wread(self, filename):
488 def wread(self, filename):
489 data = super(kwrepo, self).wread(filename)
489 data = super(kwrepo, self).wread(filename)
490 return kwt.wread(filename, data)
490 return kwt.wread(filename, data)
491
491
492 def commit(self, *args, **opts):
492 def commit(self, *args, **opts):
493 # use custom commitctx for user commands
493 # use custom commitctx for user commands
494 # other extensions can still wrap repo.commitctx directly
494 # other extensions can still wrap repo.commitctx directly
495 self.commitctx = self.kwcommitctx
495 self.commitctx = self.kwcommitctx
496 try:
496 try:
497 return super(kwrepo, self).commit(*args, **opts)
497 return super(kwrepo, self).commit(*args, **opts)
498 finally:
498 finally:
499 del self.commitctx
499 del self.commitctx
500
500
501 def kwcommitctx(self, ctx, error=False):
501 def kwcommitctx(self, ctx, error=False):
502 n = super(kwrepo, self).commitctx(ctx, error)
502 n = super(kwrepo, self).commitctx(ctx, error)
503 # no lock needed, only called from repo.commit() which already locks
503 # no lock needed, only called from repo.commit() which already locks
504 if not kwt.record:
504 if not kwt.record:
505 restrict = kwt.restrict
505 restrict = kwt.restrict
506 kwt.restrict = True
506 kwt.restrict = True
507 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
507 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
508 False, True)
508 False, True)
509 kwt.restrict = restrict
509 kwt.restrict = restrict
510 return n
510 return n
511
511
512 def rollback(self, dryrun=False):
512 def rollback(self, dryrun=False):
513 wlock = repo.wlock()
513 wlock = repo.wlock()
514 try:
514 try:
515 if not dryrun:
515 if not dryrun:
516 changed = self['.'].files()
516 changed = self['.'].files()
517 ret = super(kwrepo, self).rollback(dryrun)
517 ret = super(kwrepo, self).rollback(dryrun)
518 if not dryrun:
518 if not dryrun:
519 ctx = self['.']
519 ctx = self['.']
520 modified, added = self[None].status()[:2]
520 modified, added = self[None].status()[:2]
521 modified = [f for f in modified if f in changed]
521 modified = [f for f in modified if f in changed]
522 added = [f for f in added if f in changed]
522 added = [f for f in added if f in changed]
523 kwt.overwrite(ctx, added, True, False)
523 kwt.overwrite(ctx, added, True, False)
524 kwt.overwrite(ctx, modified, True, True)
524 kwt.overwrite(ctx, modified, True, True)
525 return ret
525 return ret
526 finally:
526 finally:
527 wlock.release()
527 wlock.release()
528
528
529 # monkeypatches
529 # monkeypatches
530 def kwpatchfile_init(orig, self, ui, fname, opener,
530 def kwpatchfile_init(orig, self, ui, fname, opener,
531 missing=False, eolmode=None):
531 missing=False, eolmode=None):
532 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
532 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
533 rejects or conflicts due to expanded keywords in working dir.'''
533 rejects or conflicts due to expanded keywords in working dir.'''
534 orig(self, ui, fname, opener, missing, eolmode)
534 orig(self, ui, fname, opener, missing, eolmode)
535 # shrink keywords read from working dir
535 # shrink keywords read from working dir
536 self.lines = kwt.shrinklines(self.fname, self.lines)
536 self.lines = kwt.shrinklines(self.fname, self.lines)
537
537
538 def kw_diff(orig, repo, node1=None, node2=None, match=None, changes=None,
538 def kw_diff(orig, repo, node1=None, node2=None, match=None, changes=None,
539 opts=None, prefix=''):
539 opts=None, prefix=''):
540 '''Monkeypatch patch.diff to avoid expansion.'''
540 '''Monkeypatch patch.diff to avoid expansion.'''
541 kwt.restrict = True
541 kwt.restrict = True
542 return orig(repo, node1, node2, match, changes, opts, prefix)
542 return orig(repo, node1, node2, match, changes, opts, prefix)
543
543
544 def kwweb_skip(orig, web, req, tmpl):
544 def kwweb_skip(orig, web, req, tmpl):
545 '''Wraps webcommands.x turning off keyword expansion.'''
545 '''Wraps webcommands.x turning off keyword expansion.'''
546 kwt.match = util.never
546 kwt.match = util.never
547 return orig(web, req, tmpl)
547 return orig(web, req, tmpl)
548
548
549 def kw_copy(orig, ui, repo, pats, opts, rename=False):
549 def kw_copy(orig, ui, repo, pats, opts, rename=False):
550 '''Wraps cmdutil.copy so that copy/rename destinations do not
550 '''Wraps cmdutil.copy so that copy/rename destinations do not
551 contain expanded keywords.
551 contain expanded keywords.
552 Note that the source may also be a symlink as:
552 Note that the source may also be a symlink as:
553 hg cp sym x -> x is symlink
553 hg cp sym x -> x is symlink
554 cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords)
554 cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords)
555 '''
555 '''
556 orig(ui, repo, pats, opts, rename)
556 orig(ui, repo, pats, opts, rename)
557 if opts.get('dry_run'):
557 if opts.get('dry_run'):
558 return
558 return
559 wctx = repo[None]
559 wctx = repo[None]
560 candidates = [f for f in repo.dirstate.copies() if
560 candidates = [f for f in repo.dirstate.copies() if
561 kwt.match(repo.dirstate.copied(f)) and
561 kwt.match(repo.dirstate.copied(f)) and
562 not 'l' in wctx.flags(f)]
562 not 'l' in wctx.flags(f)]
563 kwt.overwrite(wctx, candidates, False, False)
563 kwt.overwrite(wctx, candidates, False, False)
564
564
565 def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
565 def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
566 '''Wraps record.dorecord expanding keywords after recording.'''
566 '''Wraps record.dorecord expanding keywords after recording.'''
567 wlock = repo.wlock()
567 wlock = repo.wlock()
568 try:
568 try:
569 # record returns 0 even when nothing has changed
569 # record returns 0 even when nothing has changed
570 # therefore compare nodes before and after
570 # therefore compare nodes before and after
571 kwt.record = True
571 kwt.record = True
572 ctx = repo['.']
572 ctx = repo['.']
573 modified, added = repo[None].status()[:2]
573 modified, added = repo[None].status()[:2]
574 ret = orig(ui, repo, commitfunc, *pats, **opts)
574 ret = orig(ui, repo, commitfunc, *pats, **opts)
575 recctx = repo['.']
575 recctx = repo['.']
576 if ctx != recctx:
576 if ctx != recctx:
577 modified = [f for f in modified if f in recctx]
577 changed = recctx.files()
578 added = [f for f in added if f in recctx]
578 modified = [f for f in modified if f in changed]
579 added = [f for f in added if f in changed]
579 kwt.restrict = False
580 kwt.restrict = False
580 kwt.overwrite(recctx, modified, False, True, kwt.re_kwexp.subn)
581 kwt.overwrite(recctx, modified, False, True, kwt.re_kwexp.subn)
581 kwt.overwrite(recctx, added, False, True, kwt.re_kw.subn)
582 kwt.overwrite(recctx, added, False, True, kwt.re_kw.subn)
582 kwt.restrict = True
583 kwt.restrict = True
583 return ret
584 return ret
584 finally:
585 finally:
585 wlock.release()
586 wlock.release()
586
587
587 repo.__class__ = kwrepo
588 repo.__class__ = kwrepo
588
589
589 extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
590 extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
590 extensions.wrapfunction(patch, 'diff', kw_diff)
591 extensions.wrapfunction(patch, 'diff', kw_diff)
591 extensions.wrapfunction(cmdutil, 'copy', kw_copy)
592 extensions.wrapfunction(cmdutil, 'copy', kw_copy)
592 for c in 'annotate changeset rev filediff diff'.split():
593 for c in 'annotate changeset rev filediff diff'.split():
593 extensions.wrapfunction(webcommands, c, kwweb_skip)
594 extensions.wrapfunction(webcommands, c, kwweb_skip)
594 for name in recordextensions.split():
595 for name in recordextensions.split():
595 try:
596 try:
596 record = extensions.find(name)
597 record = extensions.find(name)
597 extensions.wrapfunction(record, 'dorecord', kw_dorecord)
598 extensions.wrapfunction(record, 'dorecord', kw_dorecord)
598 except KeyError:
599 except KeyError:
599 pass
600 pass
600
601
601 cmdtable = {
602 cmdtable = {
602 'kwdemo':
603 'kwdemo':
603 (demo,
604 (demo,
604 [('d', 'default', None, _('show default keyword template maps')),
605 [('d', 'default', None, _('show default keyword template maps')),
605 ('f', 'rcfile', '',
606 ('f', 'rcfile', '',
606 _('read maps from rcfile'), _('FILE'))],
607 _('read maps from rcfile'), _('FILE'))],
607 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...')),
608 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...')),
608 'kwexpand': (expand, commands.walkopts,
609 'kwexpand': (expand, commands.walkopts,
609 _('hg kwexpand [OPTION]... [FILE]...')),
610 _('hg kwexpand [OPTION]... [FILE]...')),
610 'kwfiles':
611 'kwfiles':
611 (files,
612 (files,
612 [('A', 'all', None, _('show keyword status flags of all files')),
613 [('A', 'all', None, _('show keyword status flags of all files')),
613 ('i', 'ignore', None, _('show files excluded from expansion')),
614 ('i', 'ignore', None, _('show files excluded from expansion')),
614 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
615 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
615 ] + commands.walkopts,
616 ] + commands.walkopts,
616 _('hg kwfiles [OPTION]... [FILE]...')),
617 _('hg kwfiles [OPTION]... [FILE]...')),
617 'kwshrink': (shrink, commands.walkopts,
618 'kwshrink': (shrink, commands.walkopts,
618 _('hg kwshrink [OPTION]... [FILE]...')),
619 _('hg kwshrink [OPTION]... [FILE]...')),
619 }
620 }
@@ -1,1015 +1,1018 b''
1 $ cat <<EOF >> $HGRCPATH
1 $ cat <<EOF >> $HGRCPATH
2 > [extensions]
2 > [extensions]
3 > keyword =
3 > keyword =
4 > mq =
4 > mq =
5 > notify =
5 > notify =
6 > record =
6 > record =
7 > transplant =
7 > transplant =
8 > [ui]
8 > [ui]
9 > interactive = true
9 > interactive = true
10 > EOF
10 > EOF
11
11
12 Run kwdemo before [keyword] files are set up
12 Run kwdemo before [keyword] files are set up
13 as it would succeed without uisetup otherwise
13 as it would succeed without uisetup otherwise
14
14
15 $ hg --quiet kwdemo
15 $ hg --quiet kwdemo
16 [extensions]
16 [extensions]
17 keyword =
17 keyword =
18 [keyword]
18 [keyword]
19 demo.txt =
19 demo.txt =
20 [keywordmaps]
20 [keywordmaps]
21 Author = {author|user}
21 Author = {author|user}
22 Date = {date|utcdate}
22 Date = {date|utcdate}
23 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
23 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
24 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
24 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
25 RCSFile = {file|basename},v
25 RCSFile = {file|basename},v
26 RCSfile = {file|basename},v
26 RCSfile = {file|basename},v
27 Revision = {node|short}
27 Revision = {node|short}
28 Source = {root}/{file},v
28 Source = {root}/{file},v
29 $Author: test $
29 $Author: test $
30 $Date: ????/??/?? ??:??:?? $ (glob)
30 $Date: ????/??/?? ??:??:?? $ (glob)
31 $Header: */demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
31 $Header: */demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
32 $Id: demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
32 $Id: demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
33 $RCSFile: demo.txt,v $
33 $RCSFile: demo.txt,v $
34 $RCSfile: demo.txt,v $
34 $RCSfile: demo.txt,v $
35 $Revision: ???????????? $ (glob)
35 $Revision: ???????????? $ (glob)
36 $Source: */demo.txt,v $ (glob)
36 $Source: */demo.txt,v $ (glob)
37
37
38 $ hg --quiet kwdemo "Branch = {branches}"
38 $ hg --quiet kwdemo "Branch = {branches}"
39 [extensions]
39 [extensions]
40 keyword =
40 keyword =
41 [keyword]
41 [keyword]
42 demo.txt =
42 demo.txt =
43 [keywordmaps]
43 [keywordmaps]
44 Branch = {branches}
44 Branch = {branches}
45 $Branch: demobranch $
45 $Branch: demobranch $
46
46
47 $ cat <<EOF >> $HGRCPATH
47 $ cat <<EOF >> $HGRCPATH
48 > [keyword]
48 > [keyword]
49 > ** =
49 > ** =
50 > b = ignore
50 > b = ignore
51 > i = ignore
51 > i = ignore
52 > [hooks]
52 > [hooks]
53 > EOF
53 > EOF
54 $ cp $HGRCPATH $HGRCPATH.nohooks
54 $ cp $HGRCPATH $HGRCPATH.nohooks
55 > cat <<EOF >> $HGRCPATH
55 > cat <<EOF >> $HGRCPATH
56 > commit=
56 > commit=
57 > commit.test=cp a hooktest
57 > commit.test=cp a hooktest
58 > EOF
58 > EOF
59
59
60 $ hg init Test-bndl
60 $ hg init Test-bndl
61 $ cd Test-bndl
61 $ cd Test-bndl
62
62
63 kwshrink should exit silently in empty/invalid repo
63 kwshrink should exit silently in empty/invalid repo
64
64
65 $ hg kwshrink
65 $ hg kwshrink
66
66
67 Symlinks cannot be created on Windows.
67 Symlinks cannot be created on Windows.
68 A bundle to test this was made with:
68 A bundle to test this was made with:
69 hg init t
69 hg init t
70 cd t
70 cd t
71 echo a > a
71 echo a > a
72 ln -s a sym
72 ln -s a sym
73 hg add sym
73 hg add sym
74 hg ci -m addsym -u mercurial
74 hg ci -m addsym -u mercurial
75 hg bundle --base null ../test-keyword.hg
75 hg bundle --base null ../test-keyword.hg
76
76
77 $ hg pull -u "$TESTDIR"/test-keyword.hg
77 $ hg pull -u "$TESTDIR"/test-keyword.hg
78 pulling from *test-keyword.hg (glob)
78 pulling from *test-keyword.hg (glob)
79 requesting all changes
79 requesting all changes
80 adding changesets
80 adding changesets
81 adding manifests
81 adding manifests
82 adding file changes
82 adding file changes
83 added 1 changesets with 1 changes to 1 files
83 added 1 changesets with 1 changes to 1 files
84 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
84 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
85
85
86 $ echo 'expand $Id$' > a
86 $ echo 'expand $Id$' > a
87 $ echo 'do not process $Id:' >> a
87 $ echo 'do not process $Id:' >> a
88 $ echo 'xxx $' >> a
88 $ echo 'xxx $' >> a
89 $ echo 'ignore $Id$' > b
89 $ echo 'ignore $Id$' > b
90
90
91 Output files as they were created
91 Output files as they were created
92
92
93 $ cat a b
93 $ cat a b
94 expand $Id$
94 expand $Id$
95 do not process $Id:
95 do not process $Id:
96 xxx $
96 xxx $
97 ignore $Id$
97 ignore $Id$
98
98
99 no kwfiles
99 no kwfiles
100
100
101 $ hg kwfiles
101 $ hg kwfiles
102
102
103 untracked candidates
103 untracked candidates
104
104
105 $ hg -v kwfiles --unknown
105 $ hg -v kwfiles --unknown
106 k a
106 k a
107
107
108 Add files and check status
108 Add files and check status
109
109
110 $ hg addremove
110 $ hg addremove
111 adding a
111 adding a
112 adding b
112 adding b
113 $ hg status
113 $ hg status
114 A a
114 A a
115 A b
115 A b
116
116
117
117
118 Default keyword expansion including commit hook
118 Default keyword expansion including commit hook
119 Interrupted commit should not change state or run commit hook
119 Interrupted commit should not change state or run commit hook
120
120
121 $ hg --debug commit
121 $ hg --debug commit
122 abort: empty commit message
122 abort: empty commit message
123 [255]
123 [255]
124 $ hg status
124 $ hg status
125 A a
125 A a
126 A b
126 A b
127
127
128 Commit with several checks
128 Commit with several checks
129
129
130 $ hg --debug commit -mabsym -u 'User Name <user@example.com>'
130 $ hg --debug commit -mabsym -u 'User Name <user@example.com>'
131 a
131 a
132 b
132 b
133 overwriting a expanding keywords
133 overwriting a expanding keywords
134 running hook commit.test: cp a hooktest
134 running hook commit.test: cp a hooktest
135 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
135 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
136 $ hg status
136 $ hg status
137 ? hooktest
137 ? hooktest
138 $ hg debugrebuildstate
138 $ hg debugrebuildstate
139 $ hg --quiet identify
139 $ hg --quiet identify
140 ef63ca68695b
140 ef63ca68695b
141
141
142 cat files in working directory with keywords expanded
142 cat files in working directory with keywords expanded
143
143
144 $ cat a b
144 $ cat a b
145 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
145 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
146 do not process $Id:
146 do not process $Id:
147 xxx $
147 xxx $
148 ignore $Id$
148 ignore $Id$
149
149
150 hg cat files and symlink, no expansion
150 hg cat files and symlink, no expansion
151
151
152 $ hg cat sym a b && echo
152 $ hg cat sym a b && echo
153 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
153 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
154 do not process $Id:
154 do not process $Id:
155 xxx $
155 xxx $
156 ignore $Id$
156 ignore $Id$
157 a
157 a
158
158
159 Test hook execution
159 Test hook execution
160
160
161 $ diff a hooktest
161 $ diff a hooktest
162
162
163 $ cp $HGRCPATH.nohooks $HGRCPATH
163 $ cp $HGRCPATH.nohooks $HGRCPATH
164 $ rm hooktest
164 $ rm hooktest
165
165
166 bundle
166 bundle
167
167
168 $ hg bundle --base null ../kw.hg
168 $ hg bundle --base null ../kw.hg
169 2 changesets found
169 2 changesets found
170 $ cd ..
170 $ cd ..
171 $ hg init Test
171 $ hg init Test
172 $ cd Test
172 $ cd Test
173
173
174 Notify on pull to check whether keywords stay as is in email
174 Notify on pull to check whether keywords stay as is in email
175 ie. if patch.diff wrapper acts as it should
175 ie. if patch.diff wrapper acts as it should
176
176
177 $ cat <<EOF >> $HGRCPATH
177 $ cat <<EOF >> $HGRCPATH
178 > [hooks]
178 > [hooks]
179 > incoming.notify = python:hgext.notify.hook
179 > incoming.notify = python:hgext.notify.hook
180 > [notify]
180 > [notify]
181 > sources = pull
181 > sources = pull
182 > diffstat = False
182 > diffstat = False
183 > maxsubject = 15
183 > maxsubject = 15
184 > [reposubs]
184 > [reposubs]
185 > * = Test
185 > * = Test
186 > EOF
186 > EOF
187
187
188 Pull from bundle and trigger notify
188 Pull from bundle and trigger notify
189
189
190 $ hg pull -u ../kw.hg
190 $ hg pull -u ../kw.hg
191 pulling from ../kw.hg
191 pulling from ../kw.hg
192 requesting all changes
192 requesting all changes
193 adding changesets
193 adding changesets
194 adding manifests
194 adding manifests
195 adding file changes
195 adding file changes
196 added 2 changesets with 3 changes to 3 files
196 added 2 changesets with 3 changes to 3 files
197 Content-Type: text/plain; charset="us-ascii"
197 Content-Type: text/plain; charset="us-ascii"
198 MIME-Version: 1.0
198 MIME-Version: 1.0
199 Content-Transfer-Encoding: 7bit
199 Content-Transfer-Encoding: 7bit
200 Date: * (glob)
200 Date: * (glob)
201 Subject: changeset in...
201 Subject: changeset in...
202 From: mercurial
202 From: mercurial
203 X-Hg-Notification: changeset a2392c293916
203 X-Hg-Notification: changeset a2392c293916
204 Message-Id: <hg.a2392c293916*> (glob)
204 Message-Id: <hg.a2392c293916*> (glob)
205 To: Test
205 To: Test
206
206
207 changeset a2392c293916 in $TESTTMP/Test
207 changeset a2392c293916 in $TESTTMP/Test
208 details: *cmd=changeset;node=a2392c293916 (glob)
208 details: *cmd=changeset;node=a2392c293916 (glob)
209 description:
209 description:
210 addsym
210 addsym
211
211
212 diffs (6 lines):
212 diffs (6 lines):
213
213
214 diff -r 000000000000 -r a2392c293916 sym
214 diff -r 000000000000 -r a2392c293916 sym
215 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
215 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
216 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
216 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
217 @@ -0,0 +1,1 @@
217 @@ -0,0 +1,1 @@
218 +a
218 +a
219 \ No newline at end of file
219 \ No newline at end of file
220 Content-Type: text/plain; charset="us-ascii"
220 Content-Type: text/plain; charset="us-ascii"
221 MIME-Version: 1.0
221 MIME-Version: 1.0
222 Content-Transfer-Encoding: 7bit
222 Content-Transfer-Encoding: 7bit
223 Date:* (glob)
223 Date:* (glob)
224 Subject: changeset in...
224 Subject: changeset in...
225 From: User Name <user@example.com>
225 From: User Name <user@example.com>
226 X-Hg-Notification: changeset ef63ca68695b
226 X-Hg-Notification: changeset ef63ca68695b
227 Message-Id: <hg.ef63ca68695b*> (glob)
227 Message-Id: <hg.ef63ca68695b*> (glob)
228 To: Test
228 To: Test
229
229
230 changeset ef63ca68695b in $TESTTMP/Test
230 changeset ef63ca68695b in $TESTTMP/Test
231 details: $TESTTMP/Test?cmd=changeset;node=ef63ca68695b
231 details: $TESTTMP/Test?cmd=changeset;node=ef63ca68695b
232 description:
232 description:
233 absym
233 absym
234
234
235 diffs (12 lines):
235 diffs (12 lines):
236
236
237 diff -r a2392c293916 -r ef63ca68695b a
237 diff -r a2392c293916 -r ef63ca68695b a
238 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
238 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
239 +++ b/a Thu Jan 01 00:00:00 1970 +0000
239 +++ b/a Thu Jan 01 00:00:00 1970 +0000
240 @@ -0,0 +1,3 @@
240 @@ -0,0 +1,3 @@
241 +expand $Id$
241 +expand $Id$
242 +do not process $Id:
242 +do not process $Id:
243 +xxx $
243 +xxx $
244 diff -r a2392c293916 -r ef63ca68695b b
244 diff -r a2392c293916 -r ef63ca68695b b
245 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
245 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
246 +++ b/b Thu Jan 01 00:00:00 1970 +0000
246 +++ b/b Thu Jan 01 00:00:00 1970 +0000
247 @@ -0,0 +1,1 @@
247 @@ -0,0 +1,1 @@
248 +ignore $Id$
248 +ignore $Id$
249 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
249 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
250
250
251 $ cp $HGRCPATH.nohooks $HGRCPATH
251 $ cp $HGRCPATH.nohooks $HGRCPATH
252
252
253 Touch files and check with status
253 Touch files and check with status
254
254
255 $ touch a b
255 $ touch a b
256 $ hg status
256 $ hg status
257
257
258 Update and expand
258 Update and expand
259
259
260 $ rm sym a b
260 $ rm sym a b
261 $ hg update -C
261 $ hg update -C
262 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
262 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
263 $ cat a b
263 $ cat a b
264 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
264 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
265 do not process $Id:
265 do not process $Id:
266 xxx $
266 xxx $
267 ignore $Id$
267 ignore $Id$
268
268
269 Check whether expansion is filewise
269 Check whether expansion is filewise
270
270
271 $ echo '$Id$' > c
271 $ echo '$Id$' > c
272 $ echo 'tests for different changenodes' >> c
272 $ echo 'tests for different changenodes' >> c
273
273
274 commit file c
274 commit file c
275
275
276 $ hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
276 $ hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
277 adding c
277 adding c
278
278
279 force expansion
279 force expansion
280
280
281 $ hg -v kwexpand
281 $ hg -v kwexpand
282 overwriting a expanding keywords
282 overwriting a expanding keywords
283 overwriting c expanding keywords
283 overwriting c expanding keywords
284
284
285 compare changenodes in a and c
285 compare changenodes in a and c
286
286
287 $ cat a c
287 $ cat a c
288 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
288 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
289 do not process $Id:
289 do not process $Id:
290 xxx $
290 xxx $
291 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
291 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
292 tests for different changenodes
292 tests for different changenodes
293
293
294 record
295
296 $ echo '$Id$' > r
297 $ hg add r
298
294 record chunk
299 record chunk
295
300
296 $ python -c \
301 $ python -c \
297 > 'l=open("a").readlines();l.insert(1,"foo\n");l.append("bar\n");open("a","w").writelines(l);'
302 > 'l=open("a").readlines();l.insert(1,"foo\n");l.append("bar\n");open("a","w").writelines(l);'
298 $ hg record -d '1 10' -m rectest<<EOF
303 $ hg record -d '1 10' -m rectest a<<EOF
299 > y
304 > y
300 > y
305 > y
301 > n
306 > n
302 > EOF
307 > EOF
303 diff --git a/a b/a
308 diff --git a/a b/a
304 2 hunks, 2 lines changed
309 2 hunks, 2 lines changed
305 examine changes to 'a'? [Ynsfdaq?]
310 examine changes to 'a'? [Ynsfdaq?]
306 @@ -1,3 +1,4 @@
311 @@ -1,3 +1,4 @@
307 expand $Id$
312 expand $Id$
308 +foo
313 +foo
309 do not process $Id:
314 do not process $Id:
310 xxx $
315 xxx $
311 record change 1/2 to 'a'? [Ynsfdaq?]
316 record change 1/2 to 'a'? [Ynsfdaq?]
312 @@ -2,2 +3,3 @@
317 @@ -2,2 +3,3 @@
313 do not process $Id:
318 do not process $Id:
314 xxx $
319 xxx $
315 +bar
320 +bar
316 record change 2/2 to 'a'? [Ynsfdaq?]
321 record change 2/2 to 'a'? [Ynsfdaq?]
317
322
318 $ hg identify
323 $ hg identify
319 d17e03c92c97+ tip
324 d17e03c92c97+ tip
320 $ hg status
325 $ hg status
321 M a
326 M a
327 A r
322
328
323 Cat modified file a
329 Cat modified file a
324
330
325 $ cat a
331 $ cat a
326 expand $Id: a,v d17e03c92c97 1970/01/01 00:00:01 test $
332 expand $Id: a,v d17e03c92c97 1970/01/01 00:00:01 test $
327 foo
333 foo
328 do not process $Id:
334 do not process $Id:
329 xxx $
335 xxx $
330 bar
336 bar
331
337
332 Diff remaining chunk
338 Diff remaining chunk
333
339
334 $ hg diff
340 $ hg diff a
335 diff -r d17e03c92c97 a
341 diff -r d17e03c92c97 a
336 --- a/a Wed Dec 31 23:59:51 1969 -0000
342 --- a/a Wed Dec 31 23:59:51 1969 -0000
337 +++ b/a * (glob)
343 +++ b/a * (glob)
338 @@ -2,3 +2,4 @@
344 @@ -2,3 +2,4 @@
339 foo
345 foo
340 do not process $Id:
346 do not process $Id:
341 xxx $
347 xxx $
342 +bar
348 +bar
343
349
344 $ hg rollback
350 $ hg rollback
345 rolling back to revision 2 (undo commit)
351 rolling back to revision 2 (undo commit)
346
352
347 Record all chunks in file a
353 Record all chunks in file a
348
354
349 $ echo foo > msg
355 $ echo foo > msg
350
356
351 - do not use "hg record -m" here!
357 - do not use "hg record -m" here!
352
358
353 $ hg record -l msg -d '1 11'<<EOF
359 $ hg record -l msg -d '1 11' a<<EOF
354 > y
360 > y
355 > y
361 > y
356 > y
362 > y
357 > EOF
363 > EOF
358 diff --git a/a b/a
364 diff --git a/a b/a
359 2 hunks, 2 lines changed
365 2 hunks, 2 lines changed
360 examine changes to 'a'? [Ynsfdaq?]
366 examine changes to 'a'? [Ynsfdaq?]
361 @@ -1,3 +1,4 @@
367 @@ -1,3 +1,4 @@
362 expand $Id$
368 expand $Id$
363 +foo
369 +foo
364 do not process $Id:
370 do not process $Id:
365 xxx $
371 xxx $
366 record change 1/2 to 'a'? [Ynsfdaq?]
372 record change 1/2 to 'a'? [Ynsfdaq?]
367 @@ -2,2 +3,3 @@
373 @@ -2,2 +3,3 @@
368 do not process $Id:
374 do not process $Id:
369 xxx $
375 xxx $
370 +bar
376 +bar
371 record change 2/2 to 'a'? [Ynsfdaq?]
377 record change 2/2 to 'a'? [Ynsfdaq?]
372
378
373 File a should be clean
379 File a should be clean
374
380
375 $ hg status -A a
381 $ hg status -A a
376 C a
382 C a
377
383
378 rollback and revert expansion
384 rollback and revert expansion
379
385
380 $ cat a
386 $ cat a
381 expand $Id: a,v 59f969a3b52c 1970/01/01 00:00:01 test $
387 expand $Id: a,v 59f969a3b52c 1970/01/01 00:00:01 test $
382 foo
388 foo
383 do not process $Id:
389 do not process $Id:
384 xxx $
390 xxx $
385 bar
391 bar
386 $ hg --verbose rollback
392 $ hg --verbose rollback
387 rolling back to revision 2 (undo commit)
393 rolling back to revision 2 (undo commit)
388 overwriting a expanding keywords
394 overwriting a expanding keywords
389 $ hg status a
395 $ hg status a
390 M a
396 M a
391 $ cat a
397 $ cat a
392 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
398 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
393 foo
399 foo
394 do not process $Id:
400 do not process $Id:
395 xxx $
401 xxx $
396 bar
402 bar
397 $ echo '$Id$' > y
403 $ echo '$Id$' > y
398 $ echo '$Id$' > z
404 $ echo '$Id$' > z
399 $ hg add y
405 $ hg add y
400 $ hg commit -Am "rollback only" z
406 $ hg commit -Am "rollback only" z
401 $ cat z
407 $ cat z
402 $Id: z,v 45a5d3adce53 1970/01/01 00:00:00 test $
408 $Id: z,v 45a5d3adce53 1970/01/01 00:00:00 test $
403 $ hg --verbose rollback
409 $ hg --verbose rollback
404 rolling back to revision 2 (undo commit)
410 rolling back to revision 2 (undo commit)
405 overwriting z shrinking keywords
411 overwriting z shrinking keywords
406
412
407 Only z should be overwritten
413 Only z should be overwritten
408
414
409 $ hg status a y z
415 $ hg status a y z
410 M a
416 M a
411 A y
417 A y
412 A z
418 A z
413 $ cat z
419 $ cat z
414 $Id$
420 $Id$
415 $ hg forget y z
421 $ hg forget y z
416 $ rm y z
422 $ rm y z
417
423
418 $ hg update -C
424 record added file alone
419 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
420
425
421 record added file
422
423 $ echo '$Id$' > r
424 $ hg add r
425 $ hg -v record -l msg -d '1 12' r<<EOF
426 $ hg -v record -l msg -d '1 12' r<<EOF
426 > y
427 > y
427 > EOF
428 > EOF
428 diff --git a/r b/r
429 diff --git a/r b/r
429 new file mode 100644
430 new file mode 100644
430 examine changes to 'r'? [Ynsfdaq?]
431 examine changes to 'r'? [Ynsfdaq?]
431 r
432 r
432 committed changeset 3:899491280810
433 committed changeset 3:899491280810
433 overwriting r expanding keywords
434 overwriting r expanding keywords
434 $ hg --verbose rollback
435 $ hg --verbose rollback
435 rolling back to revision 2 (undo commit)
436 rolling back to revision 2 (undo commit)
436 overwriting r shrinking keywords
437 overwriting r shrinking keywords
437 $ hg forget r
438 $ hg forget r
438 $ rm msg r
439 $ rm msg r
440 $ hg update -C
441 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
439
442
440 Test patch queue repo
443 Test patch queue repo
441
444
442 $ hg init --mq
445 $ hg init --mq
443 $ hg qimport -r tip -n mqtest.diff
446 $ hg qimport -r tip -n mqtest.diff
444 $ hg commit --mq -m mqtest
447 $ hg commit --mq -m mqtest
445
448
446 Keywords should not be expanded in patch
449 Keywords should not be expanded in patch
447
450
448 $ cat .hg/patches/mqtest.diff
451 $ cat .hg/patches/mqtest.diff
449 # HG changeset patch
452 # HG changeset patch
450 # User User Name <user@example.com>
453 # User User Name <user@example.com>
451 # Date 1 0
454 # Date 1 0
452 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
455 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
453 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
456 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
454 cndiff
457 cndiff
455
458
456 diff -r ef63ca68695b -r 40a904bbbe4c c
459 diff -r ef63ca68695b -r 40a904bbbe4c c
457 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
460 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
458 +++ b/c Thu Jan 01 00:00:01 1970 +0000
461 +++ b/c Thu Jan 01 00:00:01 1970 +0000
459 @@ -0,0 +1,2 @@
462 @@ -0,0 +1,2 @@
460 +$Id$
463 +$Id$
461 +tests for different changenodes
464 +tests for different changenodes
462
465
463 $ hg qpop
466 $ hg qpop
464 popping mqtest.diff
467 popping mqtest.diff
465 patch queue now empty
468 patch queue now empty
466
469
467 qgoto, implying qpush, should expand
470 qgoto, implying qpush, should expand
468
471
469 $ hg qgoto mqtest.diff
472 $ hg qgoto mqtest.diff
470 applying mqtest.diff
473 applying mqtest.diff
471 now at: mqtest.diff
474 now at: mqtest.diff
472 $ cat c
475 $ cat c
473 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
476 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
474 tests for different changenodes
477 tests for different changenodes
475 $ hg cat c
478 $ hg cat c
476 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
479 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
477 tests for different changenodes
480 tests for different changenodes
478
481
479 Keywords should not be expanded in filelog
482 Keywords should not be expanded in filelog
480
483
481 $ hg --config 'extensions.keyword=!' cat c
484 $ hg --config 'extensions.keyword=!' cat c
482 $Id$
485 $Id$
483 tests for different changenodes
486 tests for different changenodes
484
487
485 qpop and move on
488 qpop and move on
486
489
487 $ hg qpop
490 $ hg qpop
488 popping mqtest.diff
491 popping mqtest.diff
489 patch queue now empty
492 patch queue now empty
490
493
491 Copy and show added kwfiles
494 Copy and show added kwfiles
492
495
493 $ hg cp a c
496 $ hg cp a c
494 $ hg kwfiles
497 $ hg kwfiles
495 a
498 a
496 c
499 c
497
500
498 Commit and show expansion in original and copy
501 Commit and show expansion in original and copy
499
502
500 $ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
503 $ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
501 c
504 c
502 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
505 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
503 overwriting c expanding keywords
506 overwriting c expanding keywords
504 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
507 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
505 $ cat a c
508 $ cat a c
506 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
509 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
507 do not process $Id:
510 do not process $Id:
508 xxx $
511 xxx $
509 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
512 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
510 do not process $Id:
513 do not process $Id:
511 xxx $
514 xxx $
512
515
513 Touch copied c and check its status
516 Touch copied c and check its status
514
517
515 $ touch c
518 $ touch c
516 $ hg status
519 $ hg status
517
520
518 Copy kwfile to keyword ignored file unexpanding keywords
521 Copy kwfile to keyword ignored file unexpanding keywords
519
522
520 $ hg --verbose copy a i
523 $ hg --verbose copy a i
521 copying a to i
524 copying a to i
522 overwriting i shrinking keywords
525 overwriting i shrinking keywords
523 $ head -n 1 i
526 $ head -n 1 i
524 expand $Id$
527 expand $Id$
525 $ hg forget i
528 $ hg forget i
526 $ rm i
529 $ rm i
527
530
528 Copy ignored file to ignored file: no overwriting
531 Copy ignored file to ignored file: no overwriting
529
532
530 $ hg --verbose copy b i
533 $ hg --verbose copy b i
531 copying b to i
534 copying b to i
532 $ hg forget i
535 $ hg forget i
533 $ rm i
536 $ rm i
534
537
535 cp symlink (becomes regular file), and hg copy after
538 cp symlink (becomes regular file), and hg copy after
536
539
537 $ cp sym i
540 $ cp sym i
538 $ ls -l i
541 $ ls -l i
539 -rw-r--r--* (glob)
542 -rw-r--r--* (glob)
540 $ head -1 i
543 $ head -1 i
541 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
544 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
542 $ hg copy --after --verbose sym i
545 $ hg copy --after --verbose sym i
543 copying sym to i
546 copying sym to i
544 overwriting i shrinking keywords
547 overwriting i shrinking keywords
545 $ head -1 i
548 $ head -1 i
546 expand $Id$
549 expand $Id$
547 $ hg forget i
550 $ hg forget i
548 $ rm i
551 $ rm i
549
552
550 Test different options of hg kwfiles
553 Test different options of hg kwfiles
551
554
552 $ hg kwfiles
555 $ hg kwfiles
553 a
556 a
554 c
557 c
555 $ hg -v kwfiles --ignore
558 $ hg -v kwfiles --ignore
556 I b
559 I b
557 I sym
560 I sym
558 $ hg kwfiles --all
561 $ hg kwfiles --all
559 K a
562 K a
560 K c
563 K c
561 I b
564 I b
562 I sym
565 I sym
563
566
564 Diff specific revision
567 Diff specific revision
565
568
566 $ hg diff --rev 1
569 $ hg diff --rev 1
567 diff -r ef63ca68695b c
570 diff -r ef63ca68695b c
568 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
571 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
569 +++ b/c * (glob)
572 +++ b/c * (glob)
570 @@ -0,0 +1,3 @@
573 @@ -0,0 +1,3 @@
571 +expand $Id$
574 +expand $Id$
572 +do not process $Id:
575 +do not process $Id:
573 +xxx $
576 +xxx $
574
577
575 Status after rollback:
578 Status after rollback:
576
579
577 $ hg rollback
580 $ hg rollback
578 rolling back to revision 1 (undo commit)
581 rolling back to revision 1 (undo commit)
579 $ hg status
582 $ hg status
580 A c
583 A c
581 $ hg update --clean
584 $ hg update --clean
582 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
585 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
583
586
584 Custom keywordmaps as argument to kwdemo
587 Custom keywordmaps as argument to kwdemo
585
588
586 $ hg --quiet kwdemo "Xinfo = {author}: {desc}"
589 $ hg --quiet kwdemo "Xinfo = {author}: {desc}"
587 [extensions]
590 [extensions]
588 keyword =
591 keyword =
589 [keyword]
592 [keyword]
590 ** =
593 ** =
591 b = ignore
594 b = ignore
592 demo.txt =
595 demo.txt =
593 i = ignore
596 i = ignore
594 [keywordmaps]
597 [keywordmaps]
595 Xinfo = {author}: {desc}
598 Xinfo = {author}: {desc}
596 $Xinfo: test: hg keyword configuration and expansion example $
599 $Xinfo: test: hg keyword configuration and expansion example $
597
600
598 Configure custom keywordmaps
601 Configure custom keywordmaps
599
602
600 $ cat <<EOF >>$HGRCPATH
603 $ cat <<EOF >>$HGRCPATH
601 > [keywordmaps]
604 > [keywordmaps]
602 > Id = {file} {node|short} {date|rfc822date} {author|user}
605 > Id = {file} {node|short} {date|rfc822date} {author|user}
603 > Xinfo = {author}: {desc}
606 > Xinfo = {author}: {desc}
604 > EOF
607 > EOF
605
608
606 Cat and hg cat files before custom expansion
609 Cat and hg cat files before custom expansion
607
610
608 $ cat a b
611 $ cat a b
609 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
612 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
610 do not process $Id:
613 do not process $Id:
611 xxx $
614 xxx $
612 ignore $Id$
615 ignore $Id$
613 $ hg cat sym a b && echo
616 $ hg cat sym a b && echo
614 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
617 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
615 do not process $Id:
618 do not process $Id:
616 xxx $
619 xxx $
617 ignore $Id$
620 ignore $Id$
618 a
621 a
619
622
620 Write custom keyword and prepare multiline commit message
623 Write custom keyword and prepare multiline commit message
621
624
622 $ echo '$Xinfo$' >> a
625 $ echo '$Xinfo$' >> a
623 $ cat <<EOF >> log
626 $ cat <<EOF >> log
624 > firstline
627 > firstline
625 > secondline
628 > secondline
626 > EOF
629 > EOF
627
630
628 Interrupted commit should not change state
631 Interrupted commit should not change state
629
632
630 $ hg commit
633 $ hg commit
631 abort: empty commit message
634 abort: empty commit message
632 [255]
635 [255]
633 $ hg status
636 $ hg status
634 M a
637 M a
635 ? c
638 ? c
636 ? log
639 ? log
637
640
638 Commit with multiline message and custom expansion
641 Commit with multiline message and custom expansion
639
642
640 $ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
643 $ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
641 a
644 a
642 overwriting a expanding keywords
645 overwriting a expanding keywords
643 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
646 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
644 $ rm log
647 $ rm log
645
648
646 Stat, verify and show custom expansion (firstline)
649 Stat, verify and show custom expansion (firstline)
647
650
648 $ hg status
651 $ hg status
649 ? c
652 ? c
650 $ hg verify
653 $ hg verify
651 checking changesets
654 checking changesets
652 checking manifests
655 checking manifests
653 crosschecking files in changesets and manifests
656 crosschecking files in changesets and manifests
654 checking files
657 checking files
655 3 files, 3 changesets, 4 total revisions
658 3 files, 3 changesets, 4 total revisions
656 $ cat a b
659 $ cat a b
657 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
660 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
658 do not process $Id:
661 do not process $Id:
659 xxx $
662 xxx $
660 $Xinfo: User Name <user@example.com>: firstline $
663 $Xinfo: User Name <user@example.com>: firstline $
661 ignore $Id$
664 ignore $Id$
662 $ hg cat sym a b && echo
665 $ hg cat sym a b && echo
663 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
666 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
664 do not process $Id:
667 do not process $Id:
665 xxx $
668 xxx $
666 $Xinfo: User Name <user@example.com>: firstline $
669 $Xinfo: User Name <user@example.com>: firstline $
667 ignore $Id$
670 ignore $Id$
668 a
671 a
669
672
670 annotate
673 annotate
671
674
672 $ hg annotate a
675 $ hg annotate a
673 1: expand $Id$
676 1: expand $Id$
674 1: do not process $Id:
677 1: do not process $Id:
675 1: xxx $
678 1: xxx $
676 2: $Xinfo$
679 2: $Xinfo$
677
680
678 remove with status checks
681 remove with status checks
679
682
680 $ hg debugrebuildstate
683 $ hg debugrebuildstate
681 $ hg remove a
684 $ hg remove a
682 $ hg --debug commit -m rma
685 $ hg --debug commit -m rma
683 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
686 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
684 $ hg status
687 $ hg status
685 ? c
688 ? c
686
689
687 Rollback, revert, and check expansion
690 Rollback, revert, and check expansion
688
691
689 $ hg rollback
692 $ hg rollback
690 rolling back to revision 2 (undo commit)
693 rolling back to revision 2 (undo commit)
691 $ hg status
694 $ hg status
692 R a
695 R a
693 ? c
696 ? c
694 $ hg revert --no-backup --rev tip a
697 $ hg revert --no-backup --rev tip a
695 $ cat a
698 $ cat a
696 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
699 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
697 do not process $Id:
700 do not process $Id:
698 xxx $
701 xxx $
699 $Xinfo: User Name <user@example.com>: firstline $
702 $Xinfo: User Name <user@example.com>: firstline $
700
703
701 Clone to test global and local configurations
704 Clone to test global and local configurations
702
705
703 $ cd ..
706 $ cd ..
704
707
705 Expansion in destinaton with global configuration
708 Expansion in destinaton with global configuration
706
709
707 $ hg --quiet clone Test globalconf
710 $ hg --quiet clone Test globalconf
708 $ cat globalconf/a
711 $ cat globalconf/a
709 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
712 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
710 do not process $Id:
713 do not process $Id:
711 xxx $
714 xxx $
712 $Xinfo: User Name <user@example.com>: firstline $
715 $Xinfo: User Name <user@example.com>: firstline $
713
716
714 No expansion in destination with local configuration in origin only
717 No expansion in destination with local configuration in origin only
715
718
716 $ hg --quiet --config 'keyword.**=ignore' clone Test localconf
719 $ hg --quiet --config 'keyword.**=ignore' clone Test localconf
717 $ cat localconf/a
720 $ cat localconf/a
718 expand $Id$
721 expand $Id$
719 do not process $Id:
722 do not process $Id:
720 xxx $
723 xxx $
721 $Xinfo$
724 $Xinfo$
722
725
723 Clone to test incoming
726 Clone to test incoming
724
727
725 $ hg clone -r1 Test Test-a
728 $ hg clone -r1 Test Test-a
726 requesting all changes
729 requesting all changes
727 adding changesets
730 adding changesets
728 adding manifests
731 adding manifests
729 adding file changes
732 adding file changes
730 added 2 changesets with 3 changes to 3 files
733 added 2 changesets with 3 changes to 3 files
731 updating to branch default
734 updating to branch default
732 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
735 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
733 $ cd Test-a
736 $ cd Test-a
734 $ cat <<EOF >> .hg/hgrc
737 $ cat <<EOF >> .hg/hgrc
735 > [paths]
738 > [paths]
736 > default = ../Test
739 > default = ../Test
737 > EOF
740 > EOF
738 $ hg incoming
741 $ hg incoming
739 comparing with $TESTTMP/Test
742 comparing with $TESTTMP/Test
740 searching for changes
743 searching for changes
741 changeset: 2:bb948857c743
744 changeset: 2:bb948857c743
742 tag: tip
745 tag: tip
743 user: User Name <user@example.com>
746 user: User Name <user@example.com>
744 date: Thu Jan 01 00:00:02 1970 +0000
747 date: Thu Jan 01 00:00:02 1970 +0000
745 summary: firstline
748 summary: firstline
746
749
747 Imported patch should not be rejected
750 Imported patch should not be rejected
748
751
749 $ python -c \
752 $ python -c \
750 > 'import re; s=re.sub("(Id.*)","\\1 rejecttest",open("a").read()); open("a","wb").write(s);'
753 > 'import re; s=re.sub("(Id.*)","\\1 rejecttest",open("a").read()); open("a","wb").write(s);'
751 $ hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
754 $ hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
752 a
755 a
753 overwriting a expanding keywords
756 overwriting a expanding keywords
754 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
757 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
755 $ hg export -o ../rejecttest.diff tip
758 $ hg export -o ../rejecttest.diff tip
756 $ cd ../Test
759 $ cd ../Test
757 $ hg import ../rejecttest.diff
760 $ hg import ../rejecttest.diff
758 applying ../rejecttest.diff
761 applying ../rejecttest.diff
759 $ cat a b
762 $ cat a b
760 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
763 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
761 do not process $Id: rejecttest
764 do not process $Id: rejecttest
762 xxx $
765 xxx $
763 $Xinfo: User Name <user@example.com>: rejects? $
766 $Xinfo: User Name <user@example.com>: rejects? $
764 ignore $Id$
767 ignore $Id$
765
768
766 $ hg rollback
769 $ hg rollback
767 rolling back to revision 2 (undo commit)
770 rolling back to revision 2 (undo commit)
768 $ hg update --clean
771 $ hg update --clean
769 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
772 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
770
773
771 kwexpand/kwshrink on selected files
774 kwexpand/kwshrink on selected files
772
775
773 $ mkdir x
776 $ mkdir x
774 $ hg copy a x/a
777 $ hg copy a x/a
775 $ hg --verbose kwexpand a
778 $ hg --verbose kwexpand a
776 overwriting a expanding keywords
779 overwriting a expanding keywords
777
780
778 kwexpand x/a should abort
781 kwexpand x/a should abort
779
782
780 $ hg --verbose kwexpand x/a
783 $ hg --verbose kwexpand x/a
781 abort: outstanding uncommitted changes
784 abort: outstanding uncommitted changes
782 [255]
785 [255]
783 $ cd x
786 $ cd x
784 $ hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
787 $ hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
785 x/a
788 x/a
786 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
789 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
787 overwriting x/a expanding keywords
790 overwriting x/a expanding keywords
788 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
791 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
789 $ cat a
792 $ cat a
790 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
793 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
791 do not process $Id:
794 do not process $Id:
792 xxx $
795 xxx $
793 $Xinfo: User Name <user@example.com>: xa $
796 $Xinfo: User Name <user@example.com>: xa $
794
797
795 kwshrink a inside directory x
798 kwshrink a inside directory x
796
799
797 $ hg --verbose kwshrink a
800 $ hg --verbose kwshrink a
798 overwriting x/a shrinking keywords
801 overwriting x/a shrinking keywords
799 $ cat a
802 $ cat a
800 expand $Id$
803 expand $Id$
801 do not process $Id:
804 do not process $Id:
802 xxx $
805 xxx $
803 $Xinfo$
806 $Xinfo$
804 $ cd ..
807 $ cd ..
805
808
806 kwexpand nonexistent
809 kwexpand nonexistent
807
810
808 $ hg kwexpand nonexistent
811 $ hg kwexpand nonexistent
809 nonexistent:* (glob)
812 nonexistent:* (glob)
810
813
811
814
812 hg serve
815 hg serve
813 - expand with hgweb file
816 - expand with hgweb file
814 - no expansion with hgweb annotate/changeset/filediff
817 - no expansion with hgweb annotate/changeset/filediff
815 - check errors
818 - check errors
816
819
817 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
820 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
818 $ cat hg.pid >> $DAEMON_PIDS
821 $ cat hg.pid >> $DAEMON_PIDS
819 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/file/tip/a/?style=raw'
822 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/file/tip/a/?style=raw'
820 200 Script output follows
823 200 Script output follows
821
824
822 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
825 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
823 do not process $Id:
826 do not process $Id:
824 xxx $
827 xxx $
825 $Xinfo: User Name <user@example.com>: firstline $
828 $Xinfo: User Name <user@example.com>: firstline $
826 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/annotate/tip/a/?style=raw'
829 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/annotate/tip/a/?style=raw'
827 200 Script output follows
830 200 Script output follows
828
831
829
832
830 user@1: expand $Id$
833 user@1: expand $Id$
831 user@1: do not process $Id:
834 user@1: do not process $Id:
832 user@1: xxx $
835 user@1: xxx $
833 user@2: $Xinfo$
836 user@2: $Xinfo$
834
837
835
838
836
839
837
840
838 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/rev/tip/?style=raw'
841 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/rev/tip/?style=raw'
839 200 Script output follows
842 200 Script output follows
840
843
841
844
842 # HG changeset patch
845 # HG changeset patch
843 # User User Name <user@example.com>
846 # User User Name <user@example.com>
844 # Date 3 0
847 # Date 3 0
845 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
848 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
846 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
849 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
847 xa
850 xa
848
851
849 diff -r bb948857c743 -r b4560182a3f9 x/a
852 diff -r bb948857c743 -r b4560182a3f9 x/a
850 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
853 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
851 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
854 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
852 @@ -0,0 +1,4 @@
855 @@ -0,0 +1,4 @@
853 +expand $Id$
856 +expand $Id$
854 +do not process $Id:
857 +do not process $Id:
855 +xxx $
858 +xxx $
856 +$Xinfo$
859 +$Xinfo$
857
860
858 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/diff/bb948857c743/a?style=raw'
861 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/diff/bb948857c743/a?style=raw'
859 200 Script output follows
862 200 Script output follows
860
863
861
864
862 diff -r ef63ca68695b -r bb948857c743 a
865 diff -r ef63ca68695b -r bb948857c743 a
863 --- a/a Thu Jan 01 00:00:00 1970 +0000
866 --- a/a Thu Jan 01 00:00:00 1970 +0000
864 +++ b/a Thu Jan 01 00:00:02 1970 +0000
867 +++ b/a Thu Jan 01 00:00:02 1970 +0000
865 @@ -1,3 +1,4 @@
868 @@ -1,3 +1,4 @@
866 expand $Id$
869 expand $Id$
867 do not process $Id:
870 do not process $Id:
868 xxx $
871 xxx $
869 +$Xinfo$
872 +$Xinfo$
870
873
871
874
872
875
873
876
874 $ cat errors.log
877 $ cat errors.log
875
878
876 Prepare merge and resolve tests
879 Prepare merge and resolve tests
877
880
878 $ echo '$Id$' > m
881 $ echo '$Id$' > m
879 $ hg add m
882 $ hg add m
880 $ hg commit -m 4kw
883 $ hg commit -m 4kw
881 $ echo foo >> m
884 $ echo foo >> m
882 $ hg commit -m 5foo
885 $ hg commit -m 5foo
883
886
884 simplemerge
887 simplemerge
885
888
886 $ hg update 4
889 $ hg update 4
887 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
890 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
888 $ echo foo >> m
891 $ echo foo >> m
889 $ hg commit -m 6foo
892 $ hg commit -m 6foo
890 created new head
893 created new head
891 $ hg merge
894 $ hg merge
892 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
895 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
893 (branch merge, don't forget to commit)
896 (branch merge, don't forget to commit)
894 $ hg commit -m simplemerge
897 $ hg commit -m simplemerge
895 $ cat m
898 $ cat m
896 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
899 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
897 foo
900 foo
898
901
899 conflict: keyword should stay outside conflict zone
902 conflict: keyword should stay outside conflict zone
900
903
901 $ hg update 4
904 $ hg update 4
902 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
905 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
903 $ echo bar >> m
906 $ echo bar >> m
904 $ hg commit -m 8bar
907 $ hg commit -m 8bar
905 created new head
908 created new head
906 $ hg merge
909 $ hg merge
907 merging m
910 merging m
908 warning: conflicts during merge.
911 warning: conflicts during merge.
909 merging m failed!
912 merging m failed!
910 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
913 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
911 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
914 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
912 [1]
915 [1]
913 $ cat m
916 $ cat m
914 $Id$
917 $Id$
915 <<<<<<< local
918 <<<<<<< local
916 bar
919 bar
917 =======
920 =======
918 foo
921 foo
919 >>>>>>> other
922 >>>>>>> other
920
923
921 resolve to local
924 resolve to local
922
925
923 $ HGMERGE=internal:local hg resolve -a
926 $ HGMERGE=internal:local hg resolve -a
924 $ hg commit -m localresolve
927 $ hg commit -m localresolve
925 $ cat m
928 $ cat m
926 $Id: m 41efa6d38e9b Thu, 01 Jan 1970 00:00:00 +0000 test $
929 $Id: m 41efa6d38e9b Thu, 01 Jan 1970 00:00:00 +0000 test $
927 bar
930 bar
928
931
929 Test restricted mode with transplant -b
932 Test restricted mode with transplant -b
930
933
931 $ hg update 6
934 $ hg update 6
932 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
935 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
933 $ hg branch foo
936 $ hg branch foo
934 marked working directory as branch foo
937 marked working directory as branch foo
935 $ mv a a.bak
938 $ mv a a.bak
936 $ echo foobranch > a
939 $ echo foobranch > a
937 $ cat a.bak >> a
940 $ cat a.bak >> a
938 $ rm a.bak
941 $ rm a.bak
939 $ hg commit -m 9foobranch
942 $ hg commit -m 9foobranch
940 $ hg update default
943 $ hg update default
941 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
944 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
942 $ hg -y transplant -b foo tip
945 $ hg -y transplant -b foo tip
943 applying 4aa30d025d50
946 applying 4aa30d025d50
944 4aa30d025d50 transplanted to 5a4da427c162
947 4aa30d025d50 transplanted to 5a4da427c162
945
948
946 Expansion in changeset but not in file
949 Expansion in changeset but not in file
947
950
948 $ hg tip -p
951 $ hg tip -p
949 changeset: 11:5a4da427c162
952 changeset: 11:5a4da427c162
950 tag: tip
953 tag: tip
951 parent: 9:41efa6d38e9b
954 parent: 9:41efa6d38e9b
952 user: test
955 user: test
953 date: Thu Jan 01 00:00:00 1970 +0000
956 date: Thu Jan 01 00:00:00 1970 +0000
954 summary: 9foobranch
957 summary: 9foobranch
955
958
956 diff -r 41efa6d38e9b -r 5a4da427c162 a
959 diff -r 41efa6d38e9b -r 5a4da427c162 a
957 --- a/a Thu Jan 01 00:00:00 1970 +0000
960 --- a/a Thu Jan 01 00:00:00 1970 +0000
958 +++ b/a Thu Jan 01 00:00:00 1970 +0000
961 +++ b/a Thu Jan 01 00:00:00 1970 +0000
959 @@ -1,3 +1,4 @@
962 @@ -1,3 +1,4 @@
960 +foobranch
963 +foobranch
961 expand $Id$
964 expand $Id$
962 do not process $Id:
965 do not process $Id:
963 xxx $
966 xxx $
964
967
965 $ head -n 2 a
968 $ head -n 2 a
966 foobranch
969 foobranch
967 expand $Id: a 5a4da427c162 Thu, 01 Jan 1970 00:00:00 +0000 test $
970 expand $Id: a 5a4da427c162 Thu, 01 Jan 1970 00:00:00 +0000 test $
968
971
969 Turn off expansion
972 Turn off expansion
970
973
971 $ hg -q rollback
974 $ hg -q rollback
972 $ hg -q update -C
975 $ hg -q update -C
973
976
974 kwshrink with unknown file u
977 kwshrink with unknown file u
975
978
976 $ cp a u
979 $ cp a u
977 $ hg --verbose kwshrink
980 $ hg --verbose kwshrink
978 overwriting a shrinking keywords
981 overwriting a shrinking keywords
979 overwriting m shrinking keywords
982 overwriting m shrinking keywords
980 overwriting x/a shrinking keywords
983 overwriting x/a shrinking keywords
981
984
982 Keywords shrunk in working directory, but not yet disabled
985 Keywords shrunk in working directory, but not yet disabled
983 - cat shows unexpanded keywords
986 - cat shows unexpanded keywords
984 - hg cat shows expanded keywords
987 - hg cat shows expanded keywords
985
988
986 $ cat a b
989 $ cat a b
987 expand $Id$
990 expand $Id$
988 do not process $Id:
991 do not process $Id:
989 xxx $
992 xxx $
990 $Xinfo$
993 $Xinfo$
991 ignore $Id$
994 ignore $Id$
992 $ hg cat sym a b && echo
995 $ hg cat sym a b && echo
993 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
996 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
994 do not process $Id:
997 do not process $Id:
995 xxx $
998 xxx $
996 $Xinfo: User Name <user@example.com>: firstline $
999 $Xinfo: User Name <user@example.com>: firstline $
997 ignore $Id$
1000 ignore $Id$
998 a
1001 a
999
1002
1000 Now disable keyword expansion
1003 Now disable keyword expansion
1001
1004
1002 $ rm "$HGRCPATH"
1005 $ rm "$HGRCPATH"
1003 $ cat a b
1006 $ cat a b
1004 expand $Id$
1007 expand $Id$
1005 do not process $Id:
1008 do not process $Id:
1006 xxx $
1009 xxx $
1007 $Xinfo$
1010 $Xinfo$
1008 ignore $Id$
1011 ignore $Id$
1009 $ hg cat sym a b && echo
1012 $ hg cat sym a b && echo
1010 expand $Id$
1013 expand $Id$
1011 do not process $Id:
1014 do not process $Id:
1012 xxx $
1015 xxx $
1013 $Xinfo$
1016 $Xinfo$
1014 ignore $Id$
1017 ignore $Id$
1015 a
1018 a
General Comments 0
You need to be logged in to leave comments. Login now