##// END OF EJS Templates
keyword: remove mq commands from restricted list...
Christian Ebert -
r11044:5ab414f7 default
parent child Browse files
Show More
@@ -1,521 +1,520 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 Configuration is done in the [keyword] and [keywordmaps] sections of
38 Configuration is done in the [keyword] and [keywordmaps] sections of
39 hgrc files.
39 hgrc files.
40
40
41 Example::
41 Example::
42
42
43 [keyword]
43 [keyword]
44 # expand keywords in every python file except those matching "x*"
44 # expand keywords in every python file except those matching "x*"
45 **.py =
45 **.py =
46 x* = ignore
46 x* = ignore
47
47
48 NOTE: the more specific you are in your filename patterns the less you
48 NOTE: the more specific you are in your filename patterns the less you
49 lose speed in huge repositories.
49 lose speed in huge repositories.
50
50
51 For [keywordmaps] template mapping and expansion demonstration and
51 For [keywordmaps] template mapping and expansion demonstration and
52 control run :hg:`kwdemo`. See :hg:`help templates` for a list of
52 control run :hg:`kwdemo`. See :hg:`help templates` for a list of
53 available templates and filters.
53 available templates and filters.
54
54
55 An additional date template filter {date|utcdate} is provided. It
55 An additional date template filter {date|utcdate} is provided. It
56 returns a date like "2006/09/18 15:13:13".
56 returns a date like "2006/09/18 15:13:13".
57
57
58 The default template mappings (view with :hg:`kwdemo -d`) can be
58 The default template mappings (view with :hg:`kwdemo -d`) can be
59 replaced with customized keywords and templates. Again, run
59 replaced with customized keywords and templates. Again, run
60 :hg:`kwdemo` to control the results of your config changes.
60 :hg:`kwdemo` to control the results of your config changes.
61
61
62 Before changing/disabling active keywords, run :hg:`kwshrink` to avoid
62 Before changing/disabling active keywords, run :hg:`kwshrink` to avoid
63 the risk of inadvertently storing expanded keywords in the change
63 the risk of inadvertently storing expanded keywords in the change
64 history.
64 history.
65
65
66 To force expansion after enabling it, or a configuration change, run
66 To force expansion after enabling it, or a configuration change, run
67 :hg:`kwexpand`.
67 :hg:`kwexpand`.
68
68
69 Also, when committing with the record extension or using mq's qrecord,
69 Also, when committing with the record extension or using mq's qrecord,
70 be aware that keywords cannot be updated. Again, run :hg:`kwexpand` on
70 be aware that keywords cannot be updated. Again, run :hg:`kwexpand` on
71 the files in question to update keyword expansions after all changes
71 the files in question to update keyword expansions after all changes
72 have been checked in.
72 have been checked in.
73
73
74 Expansions spanning more than one line and incremental expansions,
74 Expansions spanning more than one line and incremental expansions,
75 like CVS' $Log$, are not supported. A keyword template map "Log =
75 like CVS' $Log$, are not supported. A keyword template map "Log =
76 {desc}" expands to the first line of the changeset description.
76 {desc}" expands to the first line of the changeset description.
77 '''
77 '''
78
78
79 from mercurial import commands, cmdutil, dispatch, filelog, revlog, extensions
79 from mercurial import commands, cmdutil, dispatch, filelog, revlog, extensions
80 from mercurial import patch, localrepo, templater, templatefilters, util, match
80 from mercurial import patch, localrepo, templater, templatefilters, util, match
81 from mercurial.hgweb import webcommands
81 from mercurial.hgweb import webcommands
82 from mercurial.node import nullid
82 from mercurial.node import nullid
83 from mercurial.i18n import _
83 from mercurial.i18n import _
84 import re, shutil, tempfile
84 import re, shutil, tempfile
85
85
86 commands.optionalrepo += ' kwdemo'
86 commands.optionalrepo += ' kwdemo'
87
87
88 # hg commands that do not act on keywords
88 # hg commands that do not act on keywords
89 nokwcommands = ('add addremove annotate bundle copy export grep incoming init'
89 nokwcommands = ('add addremove annotate bundle copy export grep incoming init'
90 ' log outgoing push rename rollback tip verify'
90 ' log outgoing push rename rollback tip verify'
91 ' convert email glog')
91 ' convert email glog')
92
92
93 # hg commands that trigger expansion only when writing to working dir,
93 # hg commands that trigger expansion only when writing to working dir,
94 # not when reading filelog, and unexpand when reading from working dir
94 # not when reading filelog, and unexpand when reading from working dir
95 restricted = ('merge record resolve qfold qimport qnew qpush qrefresh qrecord'
95 restricted = 'merge record qrecord resolve transplant'
96 ' transplant')
97
96
98 # provide cvs-like UTC date filter
97 # provide cvs-like UTC date filter
99 utcdate = lambda x: util.datestr((x[0], 0), '%Y/%m/%d %H:%M:%S')
98 utcdate = lambda x: util.datestr((x[0], 0), '%Y/%m/%d %H:%M:%S')
100
99
101 # make keyword tools accessible
100 # make keyword tools accessible
102 kwtools = {'templater': None, 'hgcmd': '', 'inc': [], 'exc': ['.hg*']}
101 kwtools = {'templater': None, 'hgcmd': '', 'inc': [], 'exc': ['.hg*']}
103
102
104
103
105 class kwtemplater(object):
104 class kwtemplater(object):
106 '''
105 '''
107 Sets up keyword templates, corresponding keyword regex, and
106 Sets up keyword templates, corresponding keyword regex, and
108 provides keyword substitution functions.
107 provides keyword substitution functions.
109 '''
108 '''
110 templates = {
109 templates = {
111 'Revision': '{node|short}',
110 'Revision': '{node|short}',
112 'Author': '{author|user}',
111 'Author': '{author|user}',
113 'Date': '{date|utcdate}',
112 'Date': '{date|utcdate}',
114 'RCSfile': '{file|basename},v',
113 'RCSfile': '{file|basename},v',
115 'RCSFile': '{file|basename},v', # kept for backwards compatibility
114 'RCSFile': '{file|basename},v', # kept for backwards compatibility
116 # with hg-keyword
115 # with hg-keyword
117 'Source': '{root}/{file},v',
116 'Source': '{root}/{file},v',
118 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
117 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
119 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
118 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
120 }
119 }
121
120
122 def __init__(self, ui, repo):
121 def __init__(self, ui, repo):
123 self.ui = ui
122 self.ui = ui
124 self.repo = repo
123 self.repo = repo
125 self.match = match.match(repo.root, '', [],
124 self.match = match.match(repo.root, '', [],
126 kwtools['inc'], kwtools['exc'])
125 kwtools['inc'], kwtools['exc'])
127 self.restrict = kwtools['hgcmd'] in restricted.split()
126 self.restrict = kwtools['hgcmd'] in restricted.split()
128
127
129 kwmaps = self.ui.configitems('keywordmaps')
128 kwmaps = self.ui.configitems('keywordmaps')
130 if kwmaps: # override default templates
129 if kwmaps: # override default templates
131 self.templates = dict((k, templater.parsestring(v, False))
130 self.templates = dict((k, templater.parsestring(v, False))
132 for k, v in kwmaps)
131 for k, v in kwmaps)
133 escaped = map(re.escape, self.templates.keys())
132 escaped = map(re.escape, self.templates.keys())
134 kwpat = r'\$(%s)(: [^$\n\r]*? )??\$' % '|'.join(escaped)
133 kwpat = r'\$(%s)(: [^$\n\r]*? )??\$' % '|'.join(escaped)
135 self.re_kw = re.compile(kwpat)
134 self.re_kw = re.compile(kwpat)
136
135
137 templatefilters.filters['utcdate'] = utcdate
136 templatefilters.filters['utcdate'] = utcdate
138
137
139 def substitute(self, data, path, ctx, subfunc):
138 def substitute(self, data, path, ctx, subfunc):
140 '''Replaces keywords in data with expanded template.'''
139 '''Replaces keywords in data with expanded template.'''
141 def kwsub(mobj):
140 def kwsub(mobj):
142 kw = mobj.group(1)
141 kw = mobj.group(1)
143 ct = cmdutil.changeset_templater(self.ui, self.repo,
142 ct = cmdutil.changeset_templater(self.ui, self.repo,
144 False, None, '', False)
143 False, None, '', False)
145 ct.use_template(self.templates[kw])
144 ct.use_template(self.templates[kw])
146 self.ui.pushbuffer()
145 self.ui.pushbuffer()
147 ct.show(ctx, root=self.repo.root, file=path)
146 ct.show(ctx, root=self.repo.root, file=path)
148 ekw = templatefilters.firstline(self.ui.popbuffer())
147 ekw = templatefilters.firstline(self.ui.popbuffer())
149 return '$%s: %s $' % (kw, ekw)
148 return '$%s: %s $' % (kw, ekw)
150 return subfunc(kwsub, data)
149 return subfunc(kwsub, data)
151
150
152 def expand(self, path, node, data):
151 def expand(self, path, node, data):
153 '''Returns data with keywords expanded.'''
152 '''Returns data with keywords expanded.'''
154 if not self.restrict and self.match(path) and not util.binary(data):
153 if not self.restrict and self.match(path) and not util.binary(data):
155 ctx = self.repo.filectx(path, fileid=node).changectx()
154 ctx = self.repo.filectx(path, fileid=node).changectx()
156 return self.substitute(data, path, ctx, self.re_kw.sub)
155 return self.substitute(data, path, ctx, self.re_kw.sub)
157 return data
156 return data
158
157
159 def iskwfile(self, path, flagfunc):
158 def iskwfile(self, path, flagfunc):
160 '''Returns true if path matches [keyword] pattern
159 '''Returns true if path matches [keyword] pattern
161 and is not a symbolic link.
160 and is not a symbolic link.
162 Caveat: localrepository._link fails on Windows.'''
161 Caveat: localrepository._link fails on Windows.'''
163 return self.match(path) and not 'l' in flagfunc(path)
162 return self.match(path) and not 'l' in flagfunc(path)
164
163
165 def overwrite(self, node, expand, candidates):
164 def overwrite(self, node, expand, candidates):
166 '''Overwrites selected files expanding/shrinking keywords.'''
165 '''Overwrites selected files expanding/shrinking keywords.'''
167 ctx = self.repo[node]
166 ctx = self.repo[node]
168 mf = ctx.manifest()
167 mf = ctx.manifest()
169 if node is not None: # commit
168 if node is not None: # commit
170 candidates = [f for f in ctx.files() if f in mf]
169 candidates = [f for f in ctx.files() if f in mf]
171 candidates = [f for f in candidates if self.iskwfile(f, ctx.flags)]
170 candidates = [f for f in candidates if self.iskwfile(f, ctx.flags)]
172 if candidates:
171 if candidates:
173 self.restrict = True # do not expand when reading
172 self.restrict = True # do not expand when reading
174 msg = (expand and _('overwriting %s expanding keywords\n')
173 msg = (expand and _('overwriting %s expanding keywords\n')
175 or _('overwriting %s shrinking keywords\n'))
174 or _('overwriting %s shrinking keywords\n'))
176 for f in candidates:
175 for f in candidates:
177 fp = self.repo.file(f)
176 fp = self.repo.file(f)
178 data = fp.read(mf[f])
177 data = fp.read(mf[f])
179 if util.binary(data):
178 if util.binary(data):
180 continue
179 continue
181 if expand:
180 if expand:
182 if node is None:
181 if node is None:
183 ctx = self.repo.filectx(f, fileid=mf[f]).changectx()
182 ctx = self.repo.filectx(f, fileid=mf[f]).changectx()
184 data, found = self.substitute(data, f, ctx,
183 data, found = self.substitute(data, f, ctx,
185 self.re_kw.subn)
184 self.re_kw.subn)
186 else:
185 else:
187 found = self.re_kw.search(data)
186 found = self.re_kw.search(data)
188 if found:
187 if found:
189 self.ui.note(msg % f)
188 self.ui.note(msg % f)
190 self.repo.wwrite(f, data, mf.flags(f))
189 self.repo.wwrite(f, data, mf.flags(f))
191 if node is None:
190 if node is None:
192 self.repo.dirstate.normal(f)
191 self.repo.dirstate.normal(f)
193 self.restrict = False
192 self.restrict = False
194
193
195 def shrinktext(self, text):
194 def shrinktext(self, text):
196 '''Unconditionally removes all keyword substitutions from text.'''
195 '''Unconditionally removes all keyword substitutions from text.'''
197 return self.re_kw.sub(r'$\1$', text)
196 return self.re_kw.sub(r'$\1$', text)
198
197
199 def shrink(self, fname, text):
198 def shrink(self, fname, text):
200 '''Returns text with all keyword substitutions removed.'''
199 '''Returns text with all keyword substitutions removed.'''
201 if self.match(fname) and not util.binary(text):
200 if self.match(fname) and not util.binary(text):
202 return self.shrinktext(text)
201 return self.shrinktext(text)
203 return text
202 return text
204
203
205 def shrinklines(self, fname, lines):
204 def shrinklines(self, fname, lines):
206 '''Returns lines with keyword substitutions removed.'''
205 '''Returns lines with keyword substitutions removed.'''
207 if self.match(fname):
206 if self.match(fname):
208 text = ''.join(lines)
207 text = ''.join(lines)
209 if not util.binary(text):
208 if not util.binary(text):
210 return self.shrinktext(text).splitlines(True)
209 return self.shrinktext(text).splitlines(True)
211 return lines
210 return lines
212
211
213 def wread(self, fname, data):
212 def wread(self, fname, data):
214 '''If in restricted mode returns data read from wdir with
213 '''If in restricted mode returns data read from wdir with
215 keyword substitutions removed.'''
214 keyword substitutions removed.'''
216 return self.restrict and self.shrink(fname, data) or data
215 return self.restrict and self.shrink(fname, data) or data
217
216
218 class kwfilelog(filelog.filelog):
217 class kwfilelog(filelog.filelog):
219 '''
218 '''
220 Subclass of filelog to hook into its read, add, cmp methods.
219 Subclass of filelog to hook into its read, add, cmp methods.
221 Keywords are "stored" unexpanded, and processed on reading.
220 Keywords are "stored" unexpanded, and processed on reading.
222 '''
221 '''
223 def __init__(self, opener, kwt, path):
222 def __init__(self, opener, kwt, path):
224 super(kwfilelog, self).__init__(opener, path)
223 super(kwfilelog, self).__init__(opener, path)
225 self.kwt = kwt
224 self.kwt = kwt
226 self.path = path
225 self.path = path
227
226
228 def read(self, node):
227 def read(self, node):
229 '''Expands keywords when reading filelog.'''
228 '''Expands keywords when reading filelog.'''
230 data = super(kwfilelog, self).read(node)
229 data = super(kwfilelog, self).read(node)
231 return self.kwt.expand(self.path, node, data)
230 return self.kwt.expand(self.path, node, data)
232
231
233 def add(self, text, meta, tr, link, p1=None, p2=None):
232 def add(self, text, meta, tr, link, p1=None, p2=None):
234 '''Removes keyword substitutions when adding to filelog.'''
233 '''Removes keyword substitutions when adding to filelog.'''
235 text = self.kwt.shrink(self.path, text)
234 text = self.kwt.shrink(self.path, text)
236 return super(kwfilelog, self).add(text, meta, tr, link, p1, p2)
235 return super(kwfilelog, self).add(text, meta, tr, link, p1, p2)
237
236
238 def cmp(self, node, text):
237 def cmp(self, node, text):
239 '''Removes keyword substitutions for comparison.'''
238 '''Removes keyword substitutions for comparison.'''
240 text = self.kwt.shrink(self.path, text)
239 text = self.kwt.shrink(self.path, text)
241 if self.renamed(node):
240 if self.renamed(node):
242 t2 = super(kwfilelog, self).read(node)
241 t2 = super(kwfilelog, self).read(node)
243 return t2 != text
242 return t2 != text
244 return revlog.revlog.cmp(self, node, text)
243 return revlog.revlog.cmp(self, node, text)
245
244
246 def _status(ui, repo, kwt, *pats, **opts):
245 def _status(ui, repo, kwt, *pats, **opts):
247 '''Bails out if [keyword] configuration is not active.
246 '''Bails out if [keyword] configuration is not active.
248 Returns status of working directory.'''
247 Returns status of working directory.'''
249 if kwt:
248 if kwt:
250 return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
249 return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
251 unknown=opts.get('unknown') or opts.get('all'))
250 unknown=opts.get('unknown') or opts.get('all'))
252 if ui.configitems('keyword'):
251 if ui.configitems('keyword'):
253 raise util.Abort(_('[keyword] patterns cannot match'))
252 raise util.Abort(_('[keyword] patterns cannot match'))
254 raise util.Abort(_('no [keyword] patterns configured'))
253 raise util.Abort(_('no [keyword] patterns configured'))
255
254
256 def _kwfwrite(ui, repo, expand, *pats, **opts):
255 def _kwfwrite(ui, repo, expand, *pats, **opts):
257 '''Selects files and passes them to kwtemplater.overwrite.'''
256 '''Selects files and passes them to kwtemplater.overwrite.'''
258 if repo.dirstate.parents()[1] != nullid:
257 if repo.dirstate.parents()[1] != nullid:
259 raise util.Abort(_('outstanding uncommitted merge'))
258 raise util.Abort(_('outstanding uncommitted merge'))
260 kwt = kwtools['templater']
259 kwt = kwtools['templater']
261 wlock = repo.wlock()
260 wlock = repo.wlock()
262 try:
261 try:
263 status = _status(ui, repo, kwt, *pats, **opts)
262 status = _status(ui, repo, kwt, *pats, **opts)
264 modified, added, removed, deleted, unknown, ignored, clean = status
263 modified, added, removed, deleted, unknown, ignored, clean = status
265 if modified or added or removed or deleted:
264 if modified or added or removed or deleted:
266 raise util.Abort(_('outstanding uncommitted changes'))
265 raise util.Abort(_('outstanding uncommitted changes'))
267 kwt.overwrite(None, expand, clean)
266 kwt.overwrite(None, expand, clean)
268 finally:
267 finally:
269 wlock.release()
268 wlock.release()
270
269
271 def demo(ui, repo, *args, **opts):
270 def demo(ui, repo, *args, **opts):
272 '''print [keywordmaps] configuration and an expansion example
271 '''print [keywordmaps] configuration and an expansion example
273
272
274 Show current, custom, or default keyword template maps and their
273 Show current, custom, or default keyword template maps and their
275 expansions.
274 expansions.
276
275
277 Extend the current configuration by specifying maps as arguments
276 Extend the current configuration by specifying maps as arguments
278 and using -f/--rcfile to source an external hgrc file.
277 and using -f/--rcfile to source an external hgrc file.
279
278
280 Use -d/--default to disable current configuration.
279 Use -d/--default to disable current configuration.
281
280
282 See "hg help templates" for information on templates and filters.
281 See "hg help templates" for information on templates and filters.
283 '''
282 '''
284 def demoitems(section, items):
283 def demoitems(section, items):
285 ui.write('[%s]\n' % section)
284 ui.write('[%s]\n' % section)
286 for k, v in sorted(items):
285 for k, v in sorted(items):
287 ui.write('%s = %s\n' % (k, v))
286 ui.write('%s = %s\n' % (k, v))
288
287
289 fn = 'demo.txt'
288 fn = 'demo.txt'
290 tmpdir = tempfile.mkdtemp('', 'kwdemo.')
289 tmpdir = tempfile.mkdtemp('', 'kwdemo.')
291 ui.note(_('creating temporary repository at %s\n') % tmpdir)
290 ui.note(_('creating temporary repository at %s\n') % tmpdir)
292 repo = localrepo.localrepository(ui, tmpdir, True)
291 repo = localrepo.localrepository(ui, tmpdir, True)
293 ui.setconfig('keyword', fn, '')
292 ui.setconfig('keyword', fn, '')
294
293
295 uikwmaps = ui.configitems('keywordmaps')
294 uikwmaps = ui.configitems('keywordmaps')
296 if args or opts.get('rcfile'):
295 if args or opts.get('rcfile'):
297 ui.status(_('\n\tconfiguration using custom keyword template maps\n'))
296 ui.status(_('\n\tconfiguration using custom keyword template maps\n'))
298 if uikwmaps:
297 if uikwmaps:
299 ui.status(_('\textending current template maps\n'))
298 ui.status(_('\textending current template maps\n'))
300 if opts.get('default') or not uikwmaps:
299 if opts.get('default') or not uikwmaps:
301 ui.status(_('\toverriding default template maps\n'))
300 ui.status(_('\toverriding default template maps\n'))
302 if opts.get('rcfile'):
301 if opts.get('rcfile'):
303 ui.readconfig(opts.get('rcfile'))
302 ui.readconfig(opts.get('rcfile'))
304 if args:
303 if args:
305 # simulate hgrc parsing
304 # simulate hgrc parsing
306 rcmaps = ['[keywordmaps]\n'] + [a + '\n' for a in args]
305 rcmaps = ['[keywordmaps]\n'] + [a + '\n' for a in args]
307 fp = repo.opener('hgrc', 'w')
306 fp = repo.opener('hgrc', 'w')
308 fp.writelines(rcmaps)
307 fp.writelines(rcmaps)
309 fp.close()
308 fp.close()
310 ui.readconfig(repo.join('hgrc'))
309 ui.readconfig(repo.join('hgrc'))
311 kwmaps = dict(ui.configitems('keywordmaps'))
310 kwmaps = dict(ui.configitems('keywordmaps'))
312 elif opts.get('default'):
311 elif opts.get('default'):
313 ui.status(_('\n\tconfiguration using default keyword template maps\n'))
312 ui.status(_('\n\tconfiguration using default keyword template maps\n'))
314 kwmaps = kwtemplater.templates
313 kwmaps = kwtemplater.templates
315 if uikwmaps:
314 if uikwmaps:
316 ui.status(_('\tdisabling current template maps\n'))
315 ui.status(_('\tdisabling current template maps\n'))
317 for k, v in kwmaps.iteritems():
316 for k, v in kwmaps.iteritems():
318 ui.setconfig('keywordmaps', k, v)
317 ui.setconfig('keywordmaps', k, v)
319 else:
318 else:
320 ui.status(_('\n\tconfiguration using current keyword template maps\n'))
319 ui.status(_('\n\tconfiguration using current keyword template maps\n'))
321 kwmaps = dict(uikwmaps) or kwtemplater.templates
320 kwmaps = dict(uikwmaps) or kwtemplater.templates
322
321
323 uisetup(ui)
322 uisetup(ui)
324 reposetup(ui, repo)
323 reposetup(ui, repo)
325 ui.write('[extensions]\nkeyword =\n')
324 ui.write('[extensions]\nkeyword =\n')
326 demoitems('keyword', ui.configitems('keyword'))
325 demoitems('keyword', ui.configitems('keyword'))
327 demoitems('keywordmaps', kwmaps.iteritems())
326 demoitems('keywordmaps', kwmaps.iteritems())
328 keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
327 keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
329 repo.wopener(fn, 'w').write(keywords)
328 repo.wopener(fn, 'w').write(keywords)
330 repo.add([fn])
329 repo.add([fn])
331 ui.note(_('\nkeywords written to %s:\n') % fn)
330 ui.note(_('\nkeywords written to %s:\n') % fn)
332 ui.note(keywords)
331 ui.note(keywords)
333 repo.dirstate.setbranch('demobranch')
332 repo.dirstate.setbranch('demobranch')
334 for name, cmd in ui.configitems('hooks'):
333 for name, cmd in ui.configitems('hooks'):
335 if name.split('.', 1)[0].find('commit') > -1:
334 if name.split('.', 1)[0].find('commit') > -1:
336 repo.ui.setconfig('hooks', name, '')
335 repo.ui.setconfig('hooks', name, '')
337 msg = _('hg keyword configuration and expansion example')
336 msg = _('hg keyword configuration and expansion example')
338 ui.note("hg ci -m '%s'\n" % msg)
337 ui.note("hg ci -m '%s'\n" % msg)
339 repo.commit(text=msg)
338 repo.commit(text=msg)
340 ui.status(_('\n\tkeywords expanded\n'))
339 ui.status(_('\n\tkeywords expanded\n'))
341 ui.write(repo.wread(fn))
340 ui.write(repo.wread(fn))
342 shutil.rmtree(tmpdir, ignore_errors=True)
341 shutil.rmtree(tmpdir, ignore_errors=True)
343
342
344 def expand(ui, repo, *pats, **opts):
343 def expand(ui, repo, *pats, **opts):
345 '''expand keywords in the working directory
344 '''expand keywords in the working directory
346
345
347 Run after (re)enabling keyword expansion.
346 Run after (re)enabling keyword expansion.
348
347
349 kwexpand refuses to run if given files contain local changes.
348 kwexpand refuses to run if given files contain local changes.
350 '''
349 '''
351 # 3rd argument sets expansion to True
350 # 3rd argument sets expansion to True
352 _kwfwrite(ui, repo, True, *pats, **opts)
351 _kwfwrite(ui, repo, True, *pats, **opts)
353
352
354 def files(ui, repo, *pats, **opts):
353 def files(ui, repo, *pats, **opts):
355 '''show files configured for keyword expansion
354 '''show files configured for keyword expansion
356
355
357 List which files in the working directory are matched by the
356 List which files in the working directory are matched by the
358 [keyword] configuration patterns.
357 [keyword] configuration patterns.
359
358
360 Useful to prevent inadvertent keyword expansion and to speed up
359 Useful to prevent inadvertent keyword expansion and to speed up
361 execution by including only files that are actual candidates for
360 execution by including only files that are actual candidates for
362 expansion.
361 expansion.
363
362
364 See :hg:`help keyword` on how to construct patterns both for
363 See :hg:`help keyword` on how to construct patterns both for
365 inclusion and exclusion of files.
364 inclusion and exclusion of files.
366
365
367 With -A/--all and -v/--verbose the codes used to show the status
366 With -A/--all and -v/--verbose the codes used to show the status
368 of files are::
367 of files are::
369
368
370 K = keyword expansion candidate
369 K = keyword expansion candidate
371 k = keyword expansion candidate (not tracked)
370 k = keyword expansion candidate (not tracked)
372 I = ignored
371 I = ignored
373 i = ignored (not tracked)
372 i = ignored (not tracked)
374 '''
373 '''
375 kwt = kwtools['templater']
374 kwt = kwtools['templater']
376 status = _status(ui, repo, kwt, *pats, **opts)
375 status = _status(ui, repo, kwt, *pats, **opts)
377 cwd = pats and repo.getcwd() or ''
376 cwd = pats and repo.getcwd() or ''
378 modified, added, removed, deleted, unknown, ignored, clean = status
377 modified, added, removed, deleted, unknown, ignored, clean = status
379 files = []
378 files = []
380 if not opts.get('unknown') or opts.get('all'):
379 if not opts.get('unknown') or opts.get('all'):
381 files = sorted(modified + added + clean)
380 files = sorted(modified + added + clean)
382 wctx = repo[None]
381 wctx = repo[None]
383 kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)]
382 kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)]
384 kwunknown = [f for f in unknown if kwt.iskwfile(f, wctx.flags)]
383 kwunknown = [f for f in unknown if kwt.iskwfile(f, wctx.flags)]
385 if not opts.get('ignore') or opts.get('all'):
384 if not opts.get('ignore') or opts.get('all'):
386 showfiles = kwfiles, kwunknown
385 showfiles = kwfiles, kwunknown
387 else:
386 else:
388 showfiles = [], []
387 showfiles = [], []
389 if opts.get('all') or opts.get('ignore'):
388 if opts.get('all') or opts.get('ignore'):
390 showfiles += ([f for f in files if f not in kwfiles],
389 showfiles += ([f for f in files if f not in kwfiles],
391 [f for f in unknown if f not in kwunknown])
390 [f for f in unknown if f not in kwunknown])
392 for char, filenames in zip('KkIi', showfiles):
391 for char, filenames in zip('KkIi', showfiles):
393 fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
392 fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
394 for f in filenames:
393 for f in filenames:
395 ui.write(fmt % repo.pathto(f, cwd))
394 ui.write(fmt % repo.pathto(f, cwd))
396
395
397 def shrink(ui, repo, *pats, **opts):
396 def shrink(ui, repo, *pats, **opts):
398 '''revert expanded keywords in the working directory
397 '''revert expanded keywords in the working directory
399
398
400 Run before changing/disabling active keywords or if you experience
399 Run before changing/disabling active keywords or if you experience
401 problems with :hg:`import` or :hg:`merge`.
400 problems with :hg:`import` or :hg:`merge`.
402
401
403 kwshrink refuses to run if given files contain local changes.
402 kwshrink refuses to run if given files contain local changes.
404 '''
403 '''
405 # 3rd argument sets expansion to False
404 # 3rd argument sets expansion to False
406 _kwfwrite(ui, repo, False, *pats, **opts)
405 _kwfwrite(ui, repo, False, *pats, **opts)
407
406
408
407
409 def uisetup(ui):
408 def uisetup(ui):
410 '''Collects [keyword] config in kwtools.
409 '''Collects [keyword] config in kwtools.
411 Monkeypatches dispatch._parse if needed.'''
410 Monkeypatches dispatch._parse if needed.'''
412
411
413 for pat, opt in ui.configitems('keyword'):
412 for pat, opt in ui.configitems('keyword'):
414 if opt != 'ignore':
413 if opt != 'ignore':
415 kwtools['inc'].append(pat)
414 kwtools['inc'].append(pat)
416 else:
415 else:
417 kwtools['exc'].append(pat)
416 kwtools['exc'].append(pat)
418
417
419 if kwtools['inc']:
418 if kwtools['inc']:
420 def kwdispatch_parse(orig, ui, args):
419 def kwdispatch_parse(orig, ui, args):
421 '''Monkeypatch dispatch._parse to obtain running hg command.'''
420 '''Monkeypatch dispatch._parse to obtain running hg command.'''
422 cmd, func, args, options, cmdoptions = orig(ui, args)
421 cmd, func, args, options, cmdoptions = orig(ui, args)
423 kwtools['hgcmd'] = cmd
422 kwtools['hgcmd'] = cmd
424 return cmd, func, args, options, cmdoptions
423 return cmd, func, args, options, cmdoptions
425
424
426 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
425 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
427
426
428 def reposetup(ui, repo):
427 def reposetup(ui, repo):
429 '''Sets up repo as kwrepo for keyword substitution.
428 '''Sets up repo as kwrepo for keyword substitution.
430 Overrides file method to return kwfilelog instead of filelog
429 Overrides file method to return kwfilelog instead of filelog
431 if file matches user configuration.
430 if file matches user configuration.
432 Wraps commit to overwrite configured files with updated
431 Wraps commit to overwrite configured files with updated
433 keyword substitutions.
432 keyword substitutions.
434 Monkeypatches patch and webcommands.'''
433 Monkeypatches patch and webcommands.'''
435
434
436 try:
435 try:
437 if (not repo.local() or not kwtools['inc']
436 if (not repo.local() or not kwtools['inc']
438 or kwtools['hgcmd'] in nokwcommands.split()
437 or kwtools['hgcmd'] in nokwcommands.split()
439 or '.hg' in util.splitpath(repo.root)
438 or '.hg' in util.splitpath(repo.root)
440 or repo._url.startswith('bundle:')):
439 or repo._url.startswith('bundle:')):
441 return
440 return
442 except AttributeError:
441 except AttributeError:
443 pass
442 pass
444
443
445 kwtools['templater'] = kwt = kwtemplater(ui, repo)
444 kwtools['templater'] = kwt = kwtemplater(ui, repo)
446
445
447 class kwrepo(repo.__class__):
446 class kwrepo(repo.__class__):
448 def file(self, f):
447 def file(self, f):
449 if f[0] == '/':
448 if f[0] == '/':
450 f = f[1:]
449 f = f[1:]
451 return kwfilelog(self.sopener, kwt, f)
450 return kwfilelog(self.sopener, kwt, f)
452
451
453 def wread(self, filename):
452 def wread(self, filename):
454 data = super(kwrepo, self).wread(filename)
453 data = super(kwrepo, self).wread(filename)
455 return kwt.wread(filename, data)
454 return kwt.wread(filename, data)
456
455
457 def commit(self, *args, **opts):
456 def commit(self, *args, **opts):
458 # use custom commitctx for user commands
457 # use custom commitctx for user commands
459 # other extensions can still wrap repo.commitctx directly
458 # other extensions can still wrap repo.commitctx directly
460 self.commitctx = self.kwcommitctx
459 self.commitctx = self.kwcommitctx
461 try:
460 try:
462 return super(kwrepo, self).commit(*args, **opts)
461 return super(kwrepo, self).commit(*args, **opts)
463 finally:
462 finally:
464 del self.commitctx
463 del self.commitctx
465
464
466 def kwcommitctx(self, ctx, error=False):
465 def kwcommitctx(self, ctx, error=False):
467 n = super(kwrepo, self).commitctx(ctx, error)
466 n = super(kwrepo, self).commitctx(ctx, error)
468 # no lock needed, only called from repo.commit() which already locks
467 # no lock needed, only called from repo.commit() which already locks
469 kwt.overwrite(n, True, None)
468 kwt.overwrite(n, True, None)
470 return n
469 return n
471
470
472 # monkeypatches
471 # monkeypatches
473 def kwpatchfile_init(orig, self, ui, fname, opener,
472 def kwpatchfile_init(orig, self, ui, fname, opener,
474 missing=False, eolmode=None):
473 missing=False, eolmode=None):
475 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
474 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
476 rejects or conflicts due to expanded keywords in working dir.'''
475 rejects or conflicts due to expanded keywords in working dir.'''
477 orig(self, ui, fname, opener, missing, eolmode)
476 orig(self, ui, fname, opener, missing, eolmode)
478 # shrink keywords read from working dir
477 # shrink keywords read from working dir
479 self.lines = kwt.shrinklines(self.fname, self.lines)
478 self.lines = kwt.shrinklines(self.fname, self.lines)
480
479
481 def kw_diff(orig, repo, node1=None, node2=None, match=None, changes=None,
480 def kw_diff(orig, repo, node1=None, node2=None, match=None, changes=None,
482 opts=None):
481 opts=None):
483 '''Monkeypatch patch.diff to avoid expansion except when
482 '''Monkeypatch patch.diff to avoid expansion except when
484 comparing against working dir.'''
483 comparing against working dir.'''
485 if node2 is not None:
484 if node2 is not None:
486 kwt.match = util.never
485 kwt.match = util.never
487 elif node1 is not None and node1 != repo['.'].node():
486 elif node1 is not None and node1 != repo['.'].node():
488 kwt.restrict = True
487 kwt.restrict = True
489 return orig(repo, node1, node2, match, changes, opts)
488 return orig(repo, node1, node2, match, changes, opts)
490
489
491 def kwweb_skip(orig, web, req, tmpl):
490 def kwweb_skip(orig, web, req, tmpl):
492 '''Wraps webcommands.x turning off keyword expansion.'''
491 '''Wraps webcommands.x turning off keyword expansion.'''
493 kwt.match = util.never
492 kwt.match = util.never
494 return orig(web, req, tmpl)
493 return orig(web, req, tmpl)
495
494
496 repo.__class__ = kwrepo
495 repo.__class__ = kwrepo
497
496
498 extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
497 extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
499 if not kwt.restrict:
498 if not kwt.restrict:
500 extensions.wrapfunction(patch, 'diff', kw_diff)
499 extensions.wrapfunction(patch, 'diff', kw_diff)
501 for c in 'annotate changeset rev filediff diff'.split():
500 for c in 'annotate changeset rev filediff diff'.split():
502 extensions.wrapfunction(webcommands, c, kwweb_skip)
501 extensions.wrapfunction(webcommands, c, kwweb_skip)
503
502
504 cmdtable = {
503 cmdtable = {
505 'kwdemo':
504 'kwdemo':
506 (demo,
505 (demo,
507 [('d', 'default', None, _('show default keyword template maps')),
506 [('d', 'default', None, _('show default keyword template maps')),
508 ('f', 'rcfile', '', _('read maps from rcfile'))],
507 ('f', 'rcfile', '', _('read maps from rcfile'))],
509 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...')),
508 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...')),
510 'kwexpand': (expand, commands.walkopts,
509 'kwexpand': (expand, commands.walkopts,
511 _('hg kwexpand [OPTION]... [FILE]...')),
510 _('hg kwexpand [OPTION]... [FILE]...')),
512 'kwfiles':
511 'kwfiles':
513 (files,
512 (files,
514 [('A', 'all', None, _('show keyword status flags of all files')),
513 [('A', 'all', None, _('show keyword status flags of all files')),
515 ('i', 'ignore', None, _('show files excluded from expansion')),
514 ('i', 'ignore', None, _('show files excluded from expansion')),
516 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
515 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
517 ] + commands.walkopts,
516 ] + commands.walkopts,
518 _('hg kwfiles [OPTION]... [FILE]...')),
517 _('hg kwfiles [OPTION]... [FILE]...')),
519 'kwshrink': (shrink, commands.walkopts,
518 'kwshrink': (shrink, commands.walkopts,
520 _('hg kwshrink [OPTION]... [FILE]...')),
519 _('hg kwshrink [OPTION]... [FILE]...')),
521 }
520 }
@@ -1,372 +1,376 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 cat <<EOF >> $HGRCPATH
3 cat <<EOF >> $HGRCPATH
4 [extensions]
4 [extensions]
5 keyword =
5 keyword =
6 mq =
6 mq =
7 notify =
7 notify =
8 transplant =
8 transplant =
9 EOF
9 EOF
10
10
11 # demo before [keyword] files are set up
11 # demo before [keyword] files are set up
12 # would succeed without uisetup otherwise
12 # would succeed without uisetup otherwise
13 echo % hg kwdemo
13 echo % hg kwdemo
14 hg --quiet kwdemo \
14 hg --quiet kwdemo \
15 | sed -e 's![^ ][^ ]*demo.txt,v!/TMP/demo.txt,v!' \
15 | sed -e 's![^ ][^ ]*demo.txt,v!/TMP/demo.txt,v!' \
16 -e 's/,v [a-z0-9][a-z0-9]* /,v xxxxxxxxxxxx /' \
16 -e 's/,v [a-z0-9][a-z0-9]* /,v xxxxxxxxxxxx /' \
17 -e '/[$]Revision/ s/: [a-z0-9][a-z0-9]* /: xxxxxxxxxxxx /' \
17 -e '/[$]Revision/ s/: [a-z0-9][a-z0-9]* /: xxxxxxxxxxxx /' \
18 -e 's! 20[0-9][0-9]/[01][0-9]/[0-3][0-9] [0-2][0-9]:[0-6][0-9]:[0-6][0-9]! 2000/00/00 00:00:00!'
18 -e 's! 20[0-9][0-9]/[01][0-9]/[0-3][0-9] [0-2][0-9]:[0-6][0-9]:[0-6][0-9]! 2000/00/00 00:00:00!'
19
19
20 hg --quiet kwdemo "Branch = {branches}"
20 hg --quiet kwdemo "Branch = {branches}"
21
21
22 cat <<EOF >> $HGRCPATH
22 cat <<EOF >> $HGRCPATH
23 [keyword]
23 [keyword]
24 * =
24 ** =
25 b = ignore
25 b = ignore
26 [hooks]
26 [hooks]
27 commit=
27 commit=
28 commit.test=cp a hooktest
28 commit.test=cp a hooktest
29 EOF
29 EOF
30
30
31 hg init Test-bndl
31 hg init Test-bndl
32 cd Test-bndl
32 cd Test-bndl
33
33
34 echo % kwshrink should exit silently in empty/invalid repo
34 echo % kwshrink should exit silently in empty/invalid repo
35 hg kwshrink
35 hg kwshrink
36
36
37 # Symlinks cannot be created on Windows. The bundle was made with:
37 # Symlinks cannot be created on Windows. The bundle was made with:
38 #
38 #
39 # hg init t
39 # hg init t
40 # cd t
40 # cd t
41 # echo a > a
41 # echo a > a
42 # ln -s a sym
42 # ln -s a sym
43 # hg add sym
43 # hg add sym
44 # hg ci -m addsym -u mercurial
44 # hg ci -m addsym -u mercurial
45 # hg bundle --base null ../test-keyword.hg
45 # hg bundle --base null ../test-keyword.hg
46 #
46 #
47 hg pull -u "$TESTDIR/test-keyword.hg" \
47 hg pull -u "$TESTDIR/test-keyword.hg" \
48 | sed 's/pulling from.*test-keyword.hg/pulling from test-keyword.hg/'
48 | sed 's/pulling from.*test-keyword.hg/pulling from test-keyword.hg/'
49
49
50 echo 'expand $Id$' > a
50 echo 'expand $Id$' > a
51 echo 'do not process $Id:' >> a
51 echo 'do not process $Id:' >> a
52 echo 'xxx $' >> a
52 echo 'xxx $' >> a
53 echo 'ignore $Id$' > b
53 echo 'ignore $Id$' > b
54 echo % cat
54 echo % cat
55 cat a b
55 cat a b
56
56
57 echo % no kwfiles
57 echo % no kwfiles
58 hg kwfiles
58 hg kwfiles
59 echo % untracked candidates
59 echo % untracked candidates
60 hg -v kwfiles --unknown
60 hg -v kwfiles --unknown
61
61
62 echo % addremove
62 echo % addremove
63 hg addremove
63 hg addremove
64 echo % status
64 echo % status
65 hg status
65 hg status
66
66
67 echo % default keyword expansion including commit hook
67 echo % default keyword expansion including commit hook
68 echo % interrupted commit should not change state or run commit hook
68 echo % interrupted commit should not change state or run commit hook
69 hg --debug commit
69 hg --debug commit
70 echo % status
70 echo % status
71 hg status
71 hg status
72
72
73 echo % commit
73 echo % commit
74 hg --debug commit -mabsym -u 'User Name <user@example.com>'
74 hg --debug commit -mabsym -u 'User Name <user@example.com>'
75 echo % status
75 echo % status
76 hg status
76 hg status
77 echo % identify
77 echo % identify
78 hg debugrebuildstate
78 hg debugrebuildstate
79 hg --quiet identify
79 hg --quiet identify
80 echo % cat
80 echo % cat
81 cat a b
81 cat a b
82 echo % hg cat
82 echo % hg cat
83 hg cat sym a b
83 hg cat sym a b
84
84
85 echo
85 echo
86 echo % diff a hooktest
86 echo % diff a hooktest
87 diff a hooktest
87 diff a hooktest
88
88
89 echo % removing commit hook from config
89 echo % removing commit hook from config
90 sed -e '/\[hooks\]/,$ d' "$HGRCPATH" > $HGRCPATH.nohook
90 sed -e '/\[hooks\]/,$ d' "$HGRCPATH" > $HGRCPATH.nohook
91 mv "$HGRCPATH".nohook "$HGRCPATH"
91 mv "$HGRCPATH".nohook "$HGRCPATH"
92 rm hooktest
92 rm hooktest
93
93
94 echo % bundle
94 echo % bundle
95 hg bundle --base null ../kw.hg
95 hg bundle --base null ../kw.hg
96
96
97 cd ..
97 cd ..
98 hg init Test
98 hg init Test
99 cd Test
99 cd Test
100
100
101 echo % notify on pull to check whether keywords stay as is in email
101 echo % notify on pull to check whether keywords stay as is in email
102 echo % ie. if patch.diff wrapper acts as it should
102 echo % ie. if patch.diff wrapper acts as it should
103
103
104 cat <<EOF >> $HGRCPATH
104 cat <<EOF >> $HGRCPATH
105 [hooks]
105 [hooks]
106 incoming.notify = python:hgext.notify.hook
106 incoming.notify = python:hgext.notify.hook
107 [notify]
107 [notify]
108 sources = pull
108 sources = pull
109 diffstat = False
109 diffstat = False
110 [reposubs]
110 [reposubs]
111 * = Test
111 * = Test
112 EOF
112 EOF
113
113
114 echo % pull from bundle
114 echo % pull from bundle
115 hg pull -u ../kw.hg 2>&1 | sed -e '/^Content-Type:/,/^diffs (/ d'
115 hg pull -u ../kw.hg 2>&1 | sed -e '/^Content-Type:/,/^diffs (/ d'
116
116
117 echo % remove notify config
117 echo % remove notify config
118 sed -e '/\[hooks\]/,$ d' "$HGRCPATH" > $HGRCPATH.nonotify
118 sed -e '/\[hooks\]/,$ d' "$HGRCPATH" > $HGRCPATH.nonotify
119 mv "$HGRCPATH".nonotify "$HGRCPATH"
119 mv "$HGRCPATH".nonotify "$HGRCPATH"
120
120
121 echo % touch
121 echo % touch
122 touch a b
122 touch a b
123 echo % status
123 echo % status
124 hg status
124 hg status
125
125
126 rm sym a b
126 rm sym a b
127 echo % update
127 echo % update
128 hg update -C
128 hg update -C
129 echo % cat
129 echo % cat
130 cat a b
130 cat a b
131
131
132 echo % check whether expansion is filewise
132 echo % check whether expansion is filewise
133 echo '$Id$' > c
133 echo '$Id$' > c
134 echo 'tests for different changenodes' >> c
134 echo 'tests for different changenodes' >> c
135 echo % commit c
135 echo % commit c
136 hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
136 hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
137 echo % force expansion
137 echo % force expansion
138 hg -v kwexpand
138 hg -v kwexpand
139 echo % compare changenodes in a c
139 echo % compare changenodes in a c
140 cat a c
140 cat a c
141
141
142 echo % init --mq
142 echo % init --mq
143 hg init --mq
143 hg init --mq
144 echo % qimport
144 echo % qimport
145 hg qimport -r tip -n mqtest.diff
145 hg qimport -r tip -n mqtest.diff
146 echo % commit --mq
146 echo % commit --mq
147 hg commit --mq -m mqtest
147 hg commit --mq -m mqtest
148 echo % keywords should not be expanded in patch
148 echo % keywords should not be expanded in patch
149 cat .hg/patches/mqtest.diff
149 cat .hg/patches/mqtest.diff
150 echo % qpop
150 echo % qpop
151 hg qpop
151 hg qpop
152 echo % qgoto - should imply qpush
152 echo % qgoto - should imply qpush
153 hg qgoto mqtest.diff
153 hg qgoto mqtest.diff
154 echo % cat
154 echo % cat
155 cat c
155 cat c
156 echo % hg cat
157 hg cat c
158 echo % keyword should not be expanded in filelog
159 hg --config 'extensions.keyword=!' cat c
156 echo % qpop and move on
160 echo % qpop and move on
157 hg qpop
161 hg qpop
158
162
159 echo % copy
163 echo % copy
160 hg cp a c
164 hg cp a c
161
165
162 echo % kwfiles added
166 echo % kwfiles added
163 hg kwfiles
167 hg kwfiles
164
168
165 echo % commit
169 echo % commit
166 hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
170 hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
167 echo % cat a c
171 echo % cat a c
168 cat a c
172 cat a c
169 echo % touch copied c
173 echo % touch copied c
170 touch c
174 touch c
171 echo % status
175 echo % status
172 hg status
176 hg status
173
177
174 echo % kwfiles
178 echo % kwfiles
175 hg kwfiles
179 hg kwfiles
176 echo % ignored files
180 echo % ignored files
177 hg -v kwfiles --ignore
181 hg -v kwfiles --ignore
178 echo % all files
182 echo % all files
179 hg kwfiles --all
183 hg kwfiles --all
180
184
181 echo % diff --rev
185 echo % diff --rev
182 hg diff --rev 1 | grep -v 'b/c'
186 hg diff --rev 1 | grep -v 'b/c'
183
187
184 echo % rollback
188 echo % rollback
185 hg rollback
189 hg rollback
186 echo % status
190 echo % status
187 hg status
191 hg status
188 echo % update -C
192 echo % update -C
189 hg update --clean
193 hg update --clean
190
194
191 echo % custom keyword expansion
195 echo % custom keyword expansion
192 echo % try with kwdemo
196 echo % try with kwdemo
193 hg --quiet kwdemo "Xinfo = {author}: {desc}"
197 hg --quiet kwdemo "Xinfo = {author}: {desc}"
194
198
195 cat <<EOF >>$HGRCPATH
199 cat <<EOF >>$HGRCPATH
196 [keywordmaps]
200 [keywordmaps]
197 Id = {file} {node|short} {date|rfc822date} {author|user}
201 Id = {file} {node|short} {date|rfc822date} {author|user}
198 Xinfo = {author}: {desc}
202 Xinfo = {author}: {desc}
199 EOF
203 EOF
200
204
201 echo % cat
205 echo % cat
202 cat a b
206 cat a b
203 echo % hg cat
207 echo % hg cat
204 hg cat sym a b
208 hg cat sym a b
205
209
206 echo
210 echo
207 echo '$Xinfo$' >> a
211 echo '$Xinfo$' >> a
208 cat <<EOF >> log
212 cat <<EOF >> log
209 firstline
213 firstline
210 secondline
214 secondline
211 EOF
215 EOF
212
216
213 echo % interrupted commit should not change state
217 echo % interrupted commit should not change state
214 hg commit
218 hg commit
215 echo % status
219 echo % status
216 hg status
220 hg status
217
221
218 echo % commit
222 echo % commit
219 hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
223 hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
220 rm log
224 rm log
221 echo % status
225 echo % status
222 hg status
226 hg status
223 echo % verify
227 echo % verify
224 hg verify
228 hg verify
225
229
226 echo % cat
230 echo % cat
227 cat a b
231 cat a b
228 echo % hg cat
232 echo % hg cat
229 hg cat sym a b
233 hg cat sym a b
230 echo
234 echo
231 echo % annotate
235 echo % annotate
232 hg annotate a
236 hg annotate a
233
237
234 echo % remove
238 echo % remove
235 hg debugrebuildstate
239 hg debugrebuildstate
236 hg remove a
240 hg remove a
237 hg --debug commit -m rma
241 hg --debug commit -m rma
238 echo % status
242 echo % status
239 hg status
243 hg status
240 echo % rollback
244 echo % rollback
241 hg rollback
245 hg rollback
242 echo % status
246 echo % status
243 hg status
247 hg status
244 echo % revert a
248 echo % revert a
245 hg revert --no-backup --rev tip a
249 hg revert --no-backup --rev tip a
246 echo % cat a
250 echo % cat a
247 cat a
251 cat a
248
252
249 echo % clone to test incoming
253 echo % clone to test incoming
250 cd ..
254 cd ..
251 hg clone -r1 Test Test-a
255 hg clone -r1 Test Test-a
252 cd Test-a
256 cd Test-a
253 cat <<EOF >> .hg/hgrc
257 cat <<EOF >> .hg/hgrc
254 [paths]
258 [paths]
255 default = ../Test
259 default = ../Test
256 EOF
260 EOF
257 echo % incoming
261 echo % incoming
258 # remove path to temp dir
262 # remove path to temp dir
259 hg incoming | sed -e 's/^\(comparing with \).*\(test-keyword.*\)/\1\2/'
263 hg incoming | sed -e 's/^\(comparing with \).*\(test-keyword.*\)/\1\2/'
260
264
261 sed -e 's/Id.*/& rejecttest/' a > a.new
265 sed -e 's/Id.*/& rejecttest/' a > a.new
262 mv a.new a
266 mv a.new a
263 echo % commit rejecttest
267 echo % commit rejecttest
264 hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
268 hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
265 echo % export
269 echo % export
266 hg export -o ../rejecttest.diff tip
270 hg export -o ../rejecttest.diff tip
267
271
268 cd ../Test
272 cd ../Test
269 echo % import
273 echo % import
270 hg import ../rejecttest.diff
274 hg import ../rejecttest.diff
271 echo % cat
275 echo % cat
272 cat a b
276 cat a b
273 echo
277 echo
274 echo % rollback
278 echo % rollback
275 hg rollback
279 hg rollback
276 echo % clean update
280 echo % clean update
277 hg update --clean
281 hg update --clean
278
282
279 echo % kwexpand/kwshrink on selected files
283 echo % kwexpand/kwshrink on selected files
280 mkdir x
284 mkdir x
281 echo % copy a x/a
285 echo % copy a x/a
282 hg copy a x/a
286 hg copy a x/a
283 echo % kwexpand a
287 echo % kwexpand a
284 hg --verbose kwexpand a
288 hg --verbose kwexpand a
285 echo % kwexpand x/a should abort
289 echo % kwexpand x/a should abort
286 hg --verbose kwexpand x/a
290 hg --verbose kwexpand x/a
287 cd x
291 cd x
288 hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
292 hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
289 echo % cat a
293 echo % cat a
290 cat a
294 cat a
291 echo % kwshrink a inside directory x
295 echo % kwshrink a inside directory x
292 hg --verbose kwshrink a
296 hg --verbose kwshrink a
293 echo % cat a
297 echo % cat a
294 cat a
298 cat a
295 cd ..
299 cd ..
296
300
297 echo % kwexpand nonexistent
301 echo % kwexpand nonexistent
298 hg kwexpand nonexistent 2>&1 | sed 's/nonexistent:.*/nonexistent:/'
302 hg kwexpand nonexistent 2>&1 | sed 's/nonexistent:.*/nonexistent:/'
299
303
300 echo % hg serve
304 echo % hg serve
301 hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
305 hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
302 cat hg.pid >> $DAEMON_PIDS
306 cat hg.pid >> $DAEMON_PIDS
303 echo % expansion
307 echo % expansion
304 echo % hgweb file
308 echo % hgweb file
305 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/file/tip/a/?style=raw')
309 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/file/tip/a/?style=raw')
306 echo % no expansion
310 echo % no expansion
307 echo % hgweb annotate
311 echo % hgweb annotate
308 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/annotate/tip/a/?style=raw')
312 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/annotate/tip/a/?style=raw')
309 echo % hgweb changeset
313 echo % hgweb changeset
310 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/rev/tip/?style=raw')
314 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/rev/tip/?style=raw')
311 echo % hgweb filediff
315 echo % hgweb filediff
312 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/bb948857c743/a?style=raw')
316 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/bb948857c743/a?style=raw')
313 echo % errors encountered
317 echo % errors encountered
314 cat errors.log
318 cat errors.log
315
319
316 echo % merge/resolve
320 echo % merge/resolve
317 echo '$Id$' > m
321 echo '$Id$' > m
318 hg add m
322 hg add m
319 hg commit -m 4kw
323 hg commit -m 4kw
320 echo foo >> m
324 echo foo >> m
321 hg commit -m 5foo
325 hg commit -m 5foo
322 echo % simplemerge
326 echo % simplemerge
323 hg update 4
327 hg update 4
324 echo foo >> m
328 echo foo >> m
325 hg commit -m 6foo
329 hg commit -m 6foo
326 hg merge
330 hg merge
327 hg commit -m simplemerge
331 hg commit -m simplemerge
328 cat m
332 cat m
329 echo % conflict
333 echo % conflict
330 hg update 4
334 hg update 4
331 echo bar >> m
335 echo bar >> m
332 hg commit -m 8bar
336 hg commit -m 8bar
333 hg merge
337 hg merge
334 echo % keyword stays outside conflict zone
338 echo % keyword stays outside conflict zone
335 cat m
339 cat m
336 echo % resolve to local
340 echo % resolve to local
337 HGMERGE=internal:local hg resolve -a
341 HGMERGE=internal:local hg resolve -a
338 hg commit -m localresolve
342 hg commit -m localresolve
339 cat m
343 cat m
340
344
341 echo % test restricted mode with transplant -b
345 echo % test restricted mode with transplant -b
342 hg update 6
346 hg update 6
343 hg branch foo
347 hg branch foo
344 mv a a.bak
348 mv a a.bak
345 echo foobranch > a
349 echo foobranch > a
346 cat a.bak >> a
350 cat a.bak >> a
347 rm a.bak
351 rm a.bak
348 hg commit -m 9foobranch
352 hg commit -m 9foobranch
349 hg update default
353 hg update default
350 hg -y transplant -b foo tip
354 hg -y transplant -b foo tip
351 echo % no expansion in changeset
355 echo % no expansion in changeset
352 hg tip -p
356 hg tip -p
353 echo % expansion in file
357 echo % expansion in file
354 head -n 2 a
358 head -n 2 a
355 hg -q rollback
359 hg -q rollback
356 hg -q update -C
360 hg -q update -C
357
361
358 echo % switch off expansion
362 echo % switch off expansion
359 echo % kwshrink with unknown file u
363 echo % kwshrink with unknown file u
360 cp a u
364 cp a u
361 hg --verbose kwshrink
365 hg --verbose kwshrink
362 echo % cat
366 echo % cat
363 cat a b
367 cat a b
364 echo % hg cat
368 echo % hg cat
365 hg cat sym a b
369 hg cat sym a b
366 echo
370 echo
367 rm "$HGRCPATH"
371 rm "$HGRCPATH"
368 echo % cat
372 echo % cat
369 cat a b
373 cat a b
370 echo % hg cat
374 echo % hg cat
371 hg cat sym a b
375 hg cat sym a b
372 echo
376 echo
@@ -1,480 +1,486 b''
1 % hg kwdemo
1 % hg kwdemo
2 [extensions]
2 [extensions]
3 keyword =
3 keyword =
4 [keyword]
4 [keyword]
5 demo.txt =
5 demo.txt =
6 [keywordmaps]
6 [keywordmaps]
7 Author = {author|user}
7 Author = {author|user}
8 Date = {date|utcdate}
8 Date = {date|utcdate}
9 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
9 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
10 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
10 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
11 RCSFile = {file|basename},v
11 RCSFile = {file|basename},v
12 RCSfile = {file|basename},v
12 RCSfile = {file|basename},v
13 Revision = {node|short}
13 Revision = {node|short}
14 Source = {root}/{file},v
14 Source = {root}/{file},v
15 $Author: test $
15 $Author: test $
16 $Date: 2000/00/00 00:00:00 $
16 $Date: 2000/00/00 00:00:00 $
17 $Header: /TMP/demo.txt,v xxxxxxxxxxxx 2000/00/00 00:00:00 test $
17 $Header: /TMP/demo.txt,v xxxxxxxxxxxx 2000/00/00 00:00:00 test $
18 $Id: demo.txt,v xxxxxxxxxxxx 2000/00/00 00:00:00 test $
18 $Id: demo.txt,v xxxxxxxxxxxx 2000/00/00 00:00:00 test $
19 $RCSFile: demo.txt,v $
19 $RCSFile: demo.txt,v $
20 $RCSfile: demo.txt,v $
20 $RCSfile: demo.txt,v $
21 $Revision: xxxxxxxxxxxx $
21 $Revision: xxxxxxxxxxxx $
22 $Source: /TMP/demo.txt,v $
22 $Source: /TMP/demo.txt,v $
23 [extensions]
23 [extensions]
24 keyword =
24 keyword =
25 [keyword]
25 [keyword]
26 demo.txt =
26 demo.txt =
27 [keywordmaps]
27 [keywordmaps]
28 Branch = {branches}
28 Branch = {branches}
29 $Branch: demobranch $
29 $Branch: demobranch $
30 % kwshrink should exit silently in empty/invalid repo
30 % kwshrink should exit silently in empty/invalid repo
31 pulling from test-keyword.hg
31 pulling from test-keyword.hg
32 requesting all changes
32 requesting all changes
33 adding changesets
33 adding changesets
34 adding manifests
34 adding manifests
35 adding file changes
35 adding file changes
36 added 1 changesets with 1 changes to 1 files
36 added 1 changesets with 1 changes to 1 files
37 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
37 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 % cat
38 % cat
39 expand $Id$
39 expand $Id$
40 do not process $Id:
40 do not process $Id:
41 xxx $
41 xxx $
42 ignore $Id$
42 ignore $Id$
43 % no kwfiles
43 % no kwfiles
44 % untracked candidates
44 % untracked candidates
45 k a
45 k a
46 % addremove
46 % addremove
47 adding a
47 adding a
48 adding b
48 adding b
49 % status
49 % status
50 A a
50 A a
51 A b
51 A b
52 % default keyword expansion including commit hook
52 % default keyword expansion including commit hook
53 % interrupted commit should not change state or run commit hook
53 % interrupted commit should not change state or run commit hook
54 abort: empty commit message
54 abort: empty commit message
55 % status
55 % status
56 A a
56 A a
57 A b
57 A b
58 % commit
58 % commit
59 a
59 a
60 b
60 b
61 overwriting a expanding keywords
61 overwriting a expanding keywords
62 running hook commit.test: cp a hooktest
62 running hook commit.test: cp a hooktest
63 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
63 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
64 % status
64 % status
65 ? hooktest
65 ? hooktest
66 % identify
66 % identify
67 ef63ca68695b
67 ef63ca68695b
68 % cat
68 % cat
69 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
69 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
70 do not process $Id:
70 do not process $Id:
71 xxx $
71 xxx $
72 ignore $Id$
72 ignore $Id$
73 % hg cat
73 % hg cat
74 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
74 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
75 do not process $Id:
75 do not process $Id:
76 xxx $
76 xxx $
77 ignore $Id$
77 ignore $Id$
78 a
78 a
79 % diff a hooktest
79 % diff a hooktest
80 % removing commit hook from config
80 % removing commit hook from config
81 % bundle
81 % bundle
82 2 changesets found
82 2 changesets found
83 % notify on pull to check whether keywords stay as is in email
83 % notify on pull to check whether keywords stay as is in email
84 % ie. if patch.diff wrapper acts as it should
84 % ie. if patch.diff wrapper acts as it should
85 % pull from bundle
85 % pull from bundle
86 pulling from ../kw.hg
86 pulling from ../kw.hg
87 requesting all changes
87 requesting all changes
88 adding changesets
88 adding changesets
89 adding manifests
89 adding manifests
90 adding file changes
90 adding file changes
91 added 2 changesets with 3 changes to 3 files
91 added 2 changesets with 3 changes to 3 files
92
92
93 diff -r 000000000000 -r a2392c293916 sym
93 diff -r 000000000000 -r a2392c293916 sym
94 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
94 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
95 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
96 @@ -0,0 +1,1 @@
96 @@ -0,0 +1,1 @@
97 +a
97 +a
98 \ No newline at end of file
98 \ No newline at end of file
99
99
100 diff -r a2392c293916 -r ef63ca68695b a
100 diff -r a2392c293916 -r ef63ca68695b a
101 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
101 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
102 +++ b/a Thu Jan 01 00:00:00 1970 +0000
102 +++ b/a Thu Jan 01 00:00:00 1970 +0000
103 @@ -0,0 +1,3 @@
103 @@ -0,0 +1,3 @@
104 +expand $Id$
104 +expand $Id$
105 +do not process $Id:
105 +do not process $Id:
106 +xxx $
106 +xxx $
107 diff -r a2392c293916 -r ef63ca68695b b
107 diff -r a2392c293916 -r ef63ca68695b b
108 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
108 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
109 +++ b/b Thu Jan 01 00:00:00 1970 +0000
109 +++ b/b Thu Jan 01 00:00:00 1970 +0000
110 @@ -0,0 +1,1 @@
110 @@ -0,0 +1,1 @@
111 +ignore $Id$
111 +ignore $Id$
112 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
112 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
113 % remove notify config
113 % remove notify config
114 % touch
114 % touch
115 % status
115 % status
116 % update
116 % update
117 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
118 % cat
118 % cat
119 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
119 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
120 do not process $Id:
120 do not process $Id:
121 xxx $
121 xxx $
122 ignore $Id$
122 ignore $Id$
123 % check whether expansion is filewise
123 % check whether expansion is filewise
124 % commit c
124 % commit c
125 adding c
125 adding c
126 % force expansion
126 % force expansion
127 overwriting a expanding keywords
127 overwriting a expanding keywords
128 overwriting c expanding keywords
128 overwriting c expanding keywords
129 % compare changenodes in a c
129 % compare changenodes in a c
130 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
130 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
131 do not process $Id:
131 do not process $Id:
132 xxx $
132 xxx $
133 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
133 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
134 tests for different changenodes
134 tests for different changenodes
135 % init --mq
135 % init --mq
136 % qimport
136 % qimport
137 % commit --mq
137 % commit --mq
138 % keywords should not be expanded in patch
138 % keywords should not be expanded in patch
139 # HG changeset patch
139 # HG changeset patch
140 # User User Name <user@example.com>
140 # User User Name <user@example.com>
141 # Date 1 0
141 # Date 1 0
142 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
142 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
143 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
143 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
144 cndiff
144 cndiff
145
145
146 diff -r ef63ca68695b -r 40a904bbbe4c c
146 diff -r ef63ca68695b -r 40a904bbbe4c c
147 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
147 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
148 +++ b/c Thu Jan 01 00:00:01 1970 +0000
148 +++ b/c Thu Jan 01 00:00:01 1970 +0000
149 @@ -0,0 +1,2 @@
149 @@ -0,0 +1,2 @@
150 +$Id$
150 +$Id$
151 +tests for different changenodes
151 +tests for different changenodes
152 % qpop
152 % qpop
153 popping mqtest.diff
153 popping mqtest.diff
154 patch queue now empty
154 patch queue now empty
155 % qgoto - should imply qpush
155 % qgoto - should imply qpush
156 applying mqtest.diff
156 applying mqtest.diff
157 now at: mqtest.diff
157 now at: mqtest.diff
158 % cat
158 % cat
159 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
159 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
160 tests for different changenodes
160 tests for different changenodes
161 % hg cat
162 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
163 tests for different changenodes
164 % keyword should not be expanded in filelog
165 $Id$
166 tests for different changenodes
161 % qpop and move on
167 % qpop and move on
162 popping mqtest.diff
168 popping mqtest.diff
163 patch queue now empty
169 patch queue now empty
164 % copy
170 % copy
165 % kwfiles added
171 % kwfiles added
166 a
172 a
167 c
173 c
168 % commit
174 % commit
169 c
175 c
170 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
176 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
171 overwriting c expanding keywords
177 overwriting c expanding keywords
172 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
178 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
173 % cat a c
179 % cat a c
174 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
180 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
175 do not process $Id:
181 do not process $Id:
176 xxx $
182 xxx $
177 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
183 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
178 do not process $Id:
184 do not process $Id:
179 xxx $
185 xxx $
180 % touch copied c
186 % touch copied c
181 % status
187 % status
182 % kwfiles
188 % kwfiles
183 a
189 a
184 c
190 c
185 % ignored files
191 % ignored files
186 I b
192 I b
187 I sym
193 I sym
188 % all files
194 % all files
189 K a
195 K a
190 K c
196 K c
191 I b
197 I b
192 I sym
198 I sym
193 % diff --rev
199 % diff --rev
194 diff -r ef63ca68695b c
200 diff -r ef63ca68695b c
195 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
201 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
196 @@ -0,0 +1,3 @@
202 @@ -0,0 +1,3 @@
197 +expand $Id$
203 +expand $Id$
198 +do not process $Id:
204 +do not process $Id:
199 +xxx $
205 +xxx $
200 % rollback
206 % rollback
201 rolling back to revision 2 (undo commit)
207 rolling back to revision 2 (undo commit)
202 % status
208 % status
203 A c
209 A c
204 % update -C
210 % update -C
205 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
211 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 % custom keyword expansion
212 % custom keyword expansion
207 % try with kwdemo
213 % try with kwdemo
208 [extensions]
214 [extensions]
209 keyword =
215 keyword =
210 [keyword]
216 [keyword]
211 * =
217 ** =
212 b = ignore
218 b = ignore
213 demo.txt =
219 demo.txt =
214 [keywordmaps]
220 [keywordmaps]
215 Xinfo = {author}: {desc}
221 Xinfo = {author}: {desc}
216 $Xinfo: test: hg keyword configuration and expansion example $
222 $Xinfo: test: hg keyword configuration and expansion example $
217 % cat
223 % cat
218 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
224 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
219 do not process $Id:
225 do not process $Id:
220 xxx $
226 xxx $
221 ignore $Id$
227 ignore $Id$
222 % hg cat
228 % hg cat
223 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
229 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
224 do not process $Id:
230 do not process $Id:
225 xxx $
231 xxx $
226 ignore $Id$
232 ignore $Id$
227 a
233 a
228 % interrupted commit should not change state
234 % interrupted commit should not change state
229 abort: empty commit message
235 abort: empty commit message
230 % status
236 % status
231 M a
237 M a
232 ? c
238 ? c
233 ? log
239 ? log
234 % commit
240 % commit
235 a
241 a
236 overwriting a expanding keywords
242 overwriting a expanding keywords
237 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
243 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
238 % status
244 % status
239 ? c
245 ? c
240 % verify
246 % verify
241 checking changesets
247 checking changesets
242 checking manifests
248 checking manifests
243 crosschecking files in changesets and manifests
249 crosschecking files in changesets and manifests
244 checking files
250 checking files
245 3 files, 3 changesets, 4 total revisions
251 3 files, 3 changesets, 4 total revisions
246 % cat
252 % cat
247 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
253 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
248 do not process $Id:
254 do not process $Id:
249 xxx $
255 xxx $
250 $Xinfo: User Name <user@example.com>: firstline $
256 $Xinfo: User Name <user@example.com>: firstline $
251 ignore $Id$
257 ignore $Id$
252 % hg cat
258 % hg cat
253 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
259 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
254 do not process $Id:
260 do not process $Id:
255 xxx $
261 xxx $
256 $Xinfo: User Name <user@example.com>: firstline $
262 $Xinfo: User Name <user@example.com>: firstline $
257 ignore $Id$
263 ignore $Id$
258 a
264 a
259 % annotate
265 % annotate
260 1: expand $Id$
266 1: expand $Id$
261 1: do not process $Id:
267 1: do not process $Id:
262 1: xxx $
268 1: xxx $
263 2: $Xinfo$
269 2: $Xinfo$
264 % remove
270 % remove
265 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
271 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
266 % status
272 % status
267 ? c
273 ? c
268 % rollback
274 % rollback
269 rolling back to revision 3 (undo commit)
275 rolling back to revision 3 (undo commit)
270 % status
276 % status
271 R a
277 R a
272 ? c
278 ? c
273 % revert a
279 % revert a
274 % cat a
280 % cat a
275 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
281 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
276 do not process $Id:
282 do not process $Id:
277 xxx $
283 xxx $
278 $Xinfo: User Name <user@example.com>: firstline $
284 $Xinfo: User Name <user@example.com>: firstline $
279 % clone to test incoming
285 % clone to test incoming
280 requesting all changes
286 requesting all changes
281 adding changesets
287 adding changesets
282 adding manifests
288 adding manifests
283 adding file changes
289 adding file changes
284 added 2 changesets with 3 changes to 3 files
290 added 2 changesets with 3 changes to 3 files
285 updating to branch default
291 updating to branch default
286 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
292 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
287 % incoming
293 % incoming
288 comparing with test-keyword/Test
294 comparing with test-keyword/Test
289 searching for changes
295 searching for changes
290 changeset: 2:bb948857c743
296 changeset: 2:bb948857c743
291 tag: tip
297 tag: tip
292 user: User Name <user@example.com>
298 user: User Name <user@example.com>
293 date: Thu Jan 01 00:00:02 1970 +0000
299 date: Thu Jan 01 00:00:02 1970 +0000
294 summary: firstline
300 summary: firstline
295
301
296 % commit rejecttest
302 % commit rejecttest
297 a
303 a
298 overwriting a expanding keywords
304 overwriting a expanding keywords
299 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
305 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
300 % export
306 % export
301 % import
307 % import
302 applying ../rejecttest.diff
308 applying ../rejecttest.diff
303 % cat
309 % cat
304 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
310 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
305 do not process $Id: rejecttest
311 do not process $Id: rejecttest
306 xxx $
312 xxx $
307 $Xinfo: User Name <user@example.com>: rejects? $
313 $Xinfo: User Name <user@example.com>: rejects? $
308 ignore $Id$
314 ignore $Id$
309
315
310 % rollback
316 % rollback
311 rolling back to revision 3 (undo commit)
317 rolling back to revision 3 (undo commit)
312 % clean update
318 % clean update
313 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
314 % kwexpand/kwshrink on selected files
320 % kwexpand/kwshrink on selected files
315 % copy a x/a
321 % copy a x/a
316 % kwexpand a
322 % kwexpand a
317 overwriting a expanding keywords
323 overwriting a expanding keywords
318 % kwexpand x/a should abort
324 % kwexpand x/a should abort
319 abort: outstanding uncommitted changes
325 abort: outstanding uncommitted changes
320 x/a
326 x/a
321 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
327 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
322 overwriting x/a expanding keywords
328 overwriting x/a expanding keywords
323 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
329 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
324 % cat a
330 % cat a
325 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
331 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
326 do not process $Id:
332 do not process $Id:
327 xxx $
333 xxx $
328 $Xinfo: User Name <user@example.com>: xa $
334 $Xinfo: User Name <user@example.com>: xa $
329 % kwshrink a inside directory x
335 % kwshrink a inside directory x
330 overwriting x/a shrinking keywords
336 overwriting x/a shrinking keywords
331 % cat a
337 % cat a
332 expand $Id$
338 expand $Id$
333 do not process $Id:
339 do not process $Id:
334 xxx $
340 xxx $
335 $Xinfo$
341 $Xinfo$
336 % kwexpand nonexistent
342 % kwexpand nonexistent
337 nonexistent:
343 nonexistent:
338 % hg serve
344 % hg serve
339 % expansion
345 % expansion
340 % hgweb file
346 % hgweb file
341 200 Script output follows
347 200 Script output follows
342
348
343 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
349 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
344 do not process $Id:
350 do not process $Id:
345 xxx $
351 xxx $
346 $Xinfo: User Name <user@example.com>: firstline $
352 $Xinfo: User Name <user@example.com>: firstline $
347 % no expansion
353 % no expansion
348 % hgweb annotate
354 % hgweb annotate
349 200 Script output follows
355 200 Script output follows
350
356
351
357
352 user@1: expand $Id$
358 user@1: expand $Id$
353 user@1: do not process $Id:
359 user@1: do not process $Id:
354 user@1: xxx $
360 user@1: xxx $
355 user@2: $Xinfo$
361 user@2: $Xinfo$
356
362
357
363
358
364
359
365
360 % hgweb changeset
366 % hgweb changeset
361 200 Script output follows
367 200 Script output follows
362
368
363
369
364 # HG changeset patch
370 # HG changeset patch
365 # User User Name <user@example.com>
371 # User User Name <user@example.com>
366 # Date 3 0
372 # Date 3 0
367 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
373 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
368 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
374 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
369 xa
375 xa
370
376
371 diff -r bb948857c743 -r b4560182a3f9 x/a
377 diff -r bb948857c743 -r b4560182a3f9 x/a
372 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
378 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
373 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
379 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
374 @@ -0,0 +1,4 @@
380 @@ -0,0 +1,4 @@
375 +expand $Id$
381 +expand $Id$
376 +do not process $Id:
382 +do not process $Id:
377 +xxx $
383 +xxx $
378 +$Xinfo$
384 +$Xinfo$
379
385
380 % hgweb filediff
386 % hgweb filediff
381 200 Script output follows
387 200 Script output follows
382
388
383
389
384 diff -r ef63ca68695b -r bb948857c743 a
390 diff -r ef63ca68695b -r bb948857c743 a
385 --- a/a Thu Jan 01 00:00:00 1970 +0000
391 --- a/a Thu Jan 01 00:00:00 1970 +0000
386 +++ b/a Thu Jan 01 00:00:02 1970 +0000
392 +++ b/a Thu Jan 01 00:00:02 1970 +0000
387 @@ -1,3 +1,4 @@
393 @@ -1,3 +1,4 @@
388 expand $Id$
394 expand $Id$
389 do not process $Id:
395 do not process $Id:
390 xxx $
396 xxx $
391 +$Xinfo$
397 +$Xinfo$
392
398
393
399
394
400
395
401
396 % errors encountered
402 % errors encountered
397 % merge/resolve
403 % merge/resolve
398 % simplemerge
404 % simplemerge
399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
405 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 created new head
406 created new head
401 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
407 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
402 (branch merge, don't forget to commit)
408 (branch merge, don't forget to commit)
403 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
409 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
404 foo
410 foo
405 % conflict
411 % conflict
406 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
412 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
407 created new head
413 created new head
408 merging m
414 merging m
409 warning: conflicts during merge.
415 warning: conflicts during merge.
410 merging m failed!
416 merging m failed!
411 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
417 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
412 use 'hg resolve' to retry unresolved file merges or 'hg update -C' to abandon
418 use 'hg resolve' to retry unresolved file merges or 'hg update -C' to abandon
413 % keyword stays outside conflict zone
419 % keyword stays outside conflict zone
414 $Id$
420 $Id$
415 <<<<<<< local
421 <<<<<<< local
416 bar
422 bar
417 =======
423 =======
418 foo
424 foo
419 >>>>>>> other
425 >>>>>>> other
420 % resolve to local
426 % resolve to local
421 $Id: m 41efa6d38e9b Thu, 01 Jan 1970 00:00:00 +0000 test $
427 $Id: m 41efa6d38e9b Thu, 01 Jan 1970 00:00:00 +0000 test $
422 bar
428 bar
423 % test restricted mode with transplant -b
429 % test restricted mode with transplant -b
424 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
430 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
425 marked working directory as branch foo
431 marked working directory as branch foo
426 created new head
432 created new head
427 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
433 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 applying 4aa30d025d50
434 applying 4aa30d025d50
429 4aa30d025d50 transplanted to 5a4da427c162
435 4aa30d025d50 transplanted to 5a4da427c162
430 % no expansion in changeset
436 % no expansion in changeset
431 changeset: 11:5a4da427c162
437 changeset: 11:5a4da427c162
432 tag: tip
438 tag: tip
433 parent: 9:41efa6d38e9b
439 parent: 9:41efa6d38e9b
434 user: test
440 user: test
435 date: Thu Jan 01 00:00:00 1970 +0000
441 date: Thu Jan 01 00:00:00 1970 +0000
436 summary: 9foobranch
442 summary: 9foobranch
437
443
438 diff -r 41efa6d38e9b -r 5a4da427c162 a
444 diff -r 41efa6d38e9b -r 5a4da427c162 a
439 --- a/a Thu Jan 01 00:00:00 1970 +0000
445 --- a/a Thu Jan 01 00:00:00 1970 +0000
440 +++ b/a Thu Jan 01 00:00:00 1970 +0000
446 +++ b/a Thu Jan 01 00:00:00 1970 +0000
441 @@ -1,3 +1,4 @@
447 @@ -1,3 +1,4 @@
442 +foobranch
448 +foobranch
443 expand $Id$
449 expand $Id$
444 do not process $Id:
450 do not process $Id:
445 xxx $
451 xxx $
446
452
447 % expansion in file
453 % expansion in file
448 foobranch
454 foobranch
449 expand $Id: a 5a4da427c162 Thu, 01 Jan 1970 00:00:00 +0000 test $
455 expand $Id: a 5a4da427c162 Thu, 01 Jan 1970 00:00:00 +0000 test $
450 % switch off expansion
456 % switch off expansion
451 % kwshrink with unknown file u
457 % kwshrink with unknown file u
452 overwriting a shrinking keywords
458 overwriting a shrinking keywords
453 overwriting m shrinking keywords
459 overwriting m shrinking keywords
454 overwriting x/a shrinking keywords
460 overwriting x/a shrinking keywords
455 % cat
461 % cat
456 expand $Id$
462 expand $Id$
457 do not process $Id:
463 do not process $Id:
458 xxx $
464 xxx $
459 $Xinfo$
465 $Xinfo$
460 ignore $Id$
466 ignore $Id$
461 % hg cat
467 % hg cat
462 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
468 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
463 do not process $Id:
469 do not process $Id:
464 xxx $
470 xxx $
465 $Xinfo: User Name <user@example.com>: firstline $
471 $Xinfo: User Name <user@example.com>: firstline $
466 ignore $Id$
472 ignore $Id$
467 a
473 a
468 % cat
474 % cat
469 expand $Id$
475 expand $Id$
470 do not process $Id:
476 do not process $Id:
471 xxx $
477 xxx $
472 $Xinfo$
478 $Xinfo$
473 ignore $Id$
479 ignore $Id$
474 % hg cat
480 % hg cat
475 expand $Id$
481 expand $Id$
476 do not process $Id:
482 do not process $Id:
477 xxx $
483 xxx $
478 $Xinfo$
484 $Xinfo$
479 ignore $Id$
485 ignore $Id$
480 a
486 a
General Comments 0
You need to be logged in to leave comments. Login now