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