##// END OF EJS Templates
keyword: avoid traceback when kwdemo is run outside a repo...
Christian Ebert -
r29634:8421cbeb stable
parent child Browse files
Show More
@@ -1,754 +1,758 b''
1 1 # keyword.py - $Keyword$ expansion for Mercurial
2 2 #
3 3 # Copyright 2007-2015 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 or any later version.
7 7 #
8 8 # $Id$
9 9 #
10 10 # Keyword expansion hack against the grain of a Distributed SCM
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 # <https://mercurial-scm.org/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 Keywords expand to the changeset data pertaining to the latest change
39 39 relative to the working directory parent of each file.
40 40
41 41 Configuration is done in the [keyword], [keywordset] and [keywordmaps]
42 42 sections of hgrc files.
43 43
44 44 Example::
45 45
46 46 [keyword]
47 47 # expand keywords in every python file except those matching "x*"
48 48 **.py =
49 49 x* = ignore
50 50
51 51 [keywordset]
52 52 # prefer svn- over cvs-like default keywordmaps
53 53 svn = True
54 54
55 55 .. note::
56 56
57 57 The more specific you are in your filename patterns the less you
58 58 lose speed in huge repositories.
59 59
60 60 For [keywordmaps] template mapping and expansion demonstration and
61 61 control run :hg:`kwdemo`. See :hg:`help templates` for a list of
62 62 available templates and filters.
63 63
64 64 Three additional date template filters are provided:
65 65
66 66 :``utcdate``: "2006/09/18 15:13:13"
67 67 :``svnutcdate``: "2006-09-18 15:13:13Z"
68 68 :``svnisodate``: "2006-09-18 08:13:13 -700 (Mon, 18 Sep 2006)"
69 69
70 70 The default template mappings (view with :hg:`kwdemo -d`) can be
71 71 replaced with customized keywords and templates. Again, run
72 72 :hg:`kwdemo` to control the results of your configuration changes.
73 73
74 74 Before changing/disabling active keywords, you must run :hg:`kwshrink`
75 75 to avoid storing expanded keywords in the change history.
76 76
77 77 To force expansion after enabling it, or a configuration change, run
78 78 :hg:`kwexpand`.
79 79
80 80 Expansions spanning more than one line and incremental expansions,
81 81 like CVS' $Log$, are not supported. A keyword template map "Log =
82 82 {desc}" expands to the first line of the changeset description.
83 83 '''
84 84
85 85
86 86 from __future__ import absolute_import
87 87
88 88 import os
89 89 import re
90 90 import tempfile
91 91
92 92 from mercurial.i18n import _
93 93 from mercurial.hgweb import webcommands
94 94
95 95 from mercurial import (
96 96 cmdutil,
97 97 commands,
98 98 context,
99 99 dispatch,
100 100 error,
101 101 extensions,
102 102 filelog,
103 103 localrepo,
104 104 match,
105 105 patch,
106 106 pathutil,
107 107 registrar,
108 108 scmutil,
109 109 templatefilters,
110 110 util,
111 111 )
112 112
113 113 cmdtable = {}
114 114 command = cmdutil.command(cmdtable)
115 115 # Note for extension authors: ONLY specify testedwith = 'internal' for
116 116 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
117 117 # be specifying the version(s) of Mercurial they are tested with, or
118 118 # leave the attribute unspecified.
119 119 testedwith = 'internal'
120 120
121 121 # hg commands that do not act on keywords
122 122 nokwcommands = ('add addremove annotate bundle export grep incoming init log'
123 123 ' outgoing push tip verify convert email glog')
124 124
125 125 # hg commands that trigger expansion only when writing to working dir,
126 126 # not when reading filelog, and unexpand when reading from working dir
127 127 restricted = ('merge kwexpand kwshrink record qrecord resolve transplant'
128 128 ' unshelve rebase graft backout histedit fetch')
129 129
130 130 # names of extensions using dorecord
131 131 recordextensions = 'record'
132 132
133 133 colortable = {
134 134 'kwfiles.enabled': 'green bold',
135 135 'kwfiles.deleted': 'cyan bold underline',
136 136 'kwfiles.enabledunknown': 'green',
137 137 'kwfiles.ignored': 'bold',
138 138 'kwfiles.ignoredunknown': 'none'
139 139 }
140 140
141 141 templatefilter = registrar.templatefilter()
142 142
143 143 # date like in cvs' $Date
144 144 @templatefilter('utcdate')
145 145 def utcdate(text):
146 146 '''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13".
147 147 '''
148 148 return util.datestr((util.parsedate(text)[0], 0), '%Y/%m/%d %H:%M:%S')
149 149 # date like in svn's $Date
150 150 @templatefilter('svnisodate')
151 151 def svnisodate(text):
152 152 '''Date. Returns a date in this format: "2009-08-18 13:00:13
153 153 +0200 (Tue, 18 Aug 2009)".
154 154 '''
155 155 return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
156 156 # date like in svn's $Id
157 157 @templatefilter('svnutcdate')
158 158 def svnutcdate(text):
159 159 '''Date. Returns a UTC-date in this format: "2009-08-18
160 160 11:00:13Z".
161 161 '''
162 162 return util.datestr((util.parsedate(text)[0], 0), '%Y-%m-%d %H:%M:%SZ')
163 163
164 164 # make keyword tools accessible
165 165 kwtools = {'templater': None, 'hgcmd': ''}
166 166
167 167 def _defaultkwmaps(ui):
168 168 '''Returns default keywordmaps according to keywordset configuration.'''
169 169 templates = {
170 170 'Revision': '{node|short}',
171 171 'Author': '{author|user}',
172 172 }
173 173 kwsets = ({
174 174 'Date': '{date|utcdate}',
175 175 'RCSfile': '{file|basename},v',
176 176 'RCSFile': '{file|basename},v', # kept for backwards compatibility
177 177 # with hg-keyword
178 178 'Source': '{root}/{file},v',
179 179 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
180 180 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
181 181 }, {
182 182 'Date': '{date|svnisodate}',
183 183 'Id': '{file|basename},v {node|short} {date|svnutcdate} {author|user}',
184 184 'LastChangedRevision': '{node|short}',
185 185 'LastChangedBy': '{author|user}',
186 186 'LastChangedDate': '{date|svnisodate}',
187 187 })
188 188 templates.update(kwsets[ui.configbool('keywordset', 'svn')])
189 189 return templates
190 190
191 191 def _shrinktext(text, subfunc):
192 192 '''Helper for keyword expansion removal in text.
193 193 Depending on subfunc also returns number of substitutions.'''
194 194 return subfunc(r'$\1$', text)
195 195
196 196 def _preselect(wstatus, changed):
197 197 '''Retrieves modified and added files from a working directory state
198 198 and returns the subset of each contained in given changed files
199 199 retrieved from a change context.'''
200 200 modified = [f for f in wstatus.modified if f in changed]
201 201 added = [f for f in wstatus.added if f in changed]
202 202 return modified, added
203 203
204 204
205 205 class kwtemplater(object):
206 206 '''
207 207 Sets up keyword templates, corresponding keyword regex, and
208 208 provides keyword substitution functions.
209 209 '''
210 210
211 211 def __init__(self, ui, repo, inc, exc):
212 212 self.ui = ui
213 213 self.repo = repo
214 214 self.match = match.match(repo.root, '', [], inc, exc)
215 215 self.restrict = kwtools['hgcmd'] in restricted.split()
216 216 self.postcommit = False
217 217
218 218 kwmaps = self.ui.configitems('keywordmaps')
219 219 if kwmaps: # override default templates
220 220 self.templates = dict(kwmaps)
221 221 else:
222 222 self.templates = _defaultkwmaps(self.ui)
223 223
224 224 @util.propertycache
225 225 def escape(self):
226 226 '''Returns bar-separated and escaped keywords.'''
227 227 return '|'.join(map(re.escape, self.templates.keys()))
228 228
229 229 @util.propertycache
230 230 def rekw(self):
231 231 '''Returns regex for unexpanded keywords.'''
232 232 return re.compile(r'\$(%s)\$' % self.escape)
233 233
234 234 @util.propertycache
235 235 def rekwexp(self):
236 236 '''Returns regex for expanded keywords.'''
237 237 return re.compile(r'\$(%s): [^$\n\r]*? \$' % self.escape)
238 238
239 239 def substitute(self, data, path, ctx, subfunc):
240 240 '''Replaces keywords in data with expanded template.'''
241 241 def kwsub(mobj):
242 242 kw = mobj.group(1)
243 243 ct = cmdutil.changeset_templater(self.ui, self.repo, False, None,
244 244 self.templates[kw], '', False)
245 245 self.ui.pushbuffer()
246 246 ct.show(ctx, root=self.repo.root, file=path)
247 247 ekw = templatefilters.firstline(self.ui.popbuffer())
248 248 return '$%s: %s $' % (kw, ekw)
249 249 return subfunc(kwsub, data)
250 250
251 251 def linkctx(self, path, fileid):
252 252 '''Similar to filelog.linkrev, but returns a changectx.'''
253 253 return self.repo.filectx(path, fileid=fileid).changectx()
254 254
255 255 def expand(self, path, node, data):
256 256 '''Returns data with keywords expanded.'''
257 257 if not self.restrict and self.match(path) and not util.binary(data):
258 258 ctx = self.linkctx(path, node)
259 259 return self.substitute(data, path, ctx, self.rekw.sub)
260 260 return data
261 261
262 262 def iskwfile(self, cand, ctx):
263 263 '''Returns subset of candidates which are configured for keyword
264 264 expansion but are not symbolic links.'''
265 265 return [f for f in cand if self.match(f) and 'l' not in ctx.flags(f)]
266 266
267 267 def overwrite(self, ctx, candidates, lookup, expand, rekw=False):
268 268 '''Overwrites selected files expanding/shrinking keywords.'''
269 269 if self.restrict or lookup or self.postcommit: # exclude kw_copy
270 270 candidates = self.iskwfile(candidates, ctx)
271 271 if not candidates:
272 272 return
273 273 kwcmd = self.restrict and lookup # kwexpand/kwshrink
274 274 if self.restrict or expand and lookup:
275 275 mf = ctx.manifest()
276 276 if self.restrict or rekw:
277 277 re_kw = self.rekw
278 278 else:
279 279 re_kw = self.rekwexp
280 280 if expand:
281 281 msg = _('overwriting %s expanding keywords\n')
282 282 else:
283 283 msg = _('overwriting %s shrinking keywords\n')
284 284 for f in candidates:
285 285 if self.restrict:
286 286 data = self.repo.file(f).read(mf[f])
287 287 else:
288 288 data = self.repo.wread(f)
289 289 if util.binary(data):
290 290 continue
291 291 if expand:
292 292 parents = ctx.parents()
293 293 if lookup:
294 294 ctx = self.linkctx(f, mf[f])
295 295 elif self.restrict and len(parents) > 1:
296 296 # merge commit
297 297 # in case of conflict f is in modified state during
298 298 # merge, even if f does not differ from f in parent
299 299 for p in parents:
300 300 if f in p and not p[f].cmp(ctx[f]):
301 301 ctx = p[f].changectx()
302 302 break
303 303 data, found = self.substitute(data, f, ctx, re_kw.subn)
304 304 elif self.restrict:
305 305 found = re_kw.search(data)
306 306 else:
307 307 data, found = _shrinktext(data, re_kw.subn)
308 308 if found:
309 309 self.ui.note(msg % f)
310 310 fp = self.repo.wvfs(f, "wb", atomictemp=True)
311 311 fp.write(data)
312 312 fp.close()
313 313 if kwcmd:
314 314 self.repo.dirstate.normal(f)
315 315 elif self.postcommit:
316 316 self.repo.dirstate.normallookup(f)
317 317
318 318 def shrink(self, fname, text):
319 319 '''Returns text with all keyword substitutions removed.'''
320 320 if self.match(fname) and not util.binary(text):
321 321 return _shrinktext(text, self.rekwexp.sub)
322 322 return text
323 323
324 324 def shrinklines(self, fname, lines):
325 325 '''Returns lines with keyword substitutions removed.'''
326 326 if self.match(fname):
327 327 text = ''.join(lines)
328 328 if not util.binary(text):
329 329 return _shrinktext(text, self.rekwexp.sub).splitlines(True)
330 330 return lines
331 331
332 332 def wread(self, fname, data):
333 333 '''If in restricted mode returns data read from wdir with
334 334 keyword substitutions removed.'''
335 335 if self.restrict:
336 336 return self.shrink(fname, data)
337 337 return data
338 338
339 339 class kwfilelog(filelog.filelog):
340 340 '''
341 341 Subclass of filelog to hook into its read, add, cmp methods.
342 342 Keywords are "stored" unexpanded, and processed on reading.
343 343 '''
344 344 def __init__(self, opener, kwt, path):
345 345 super(kwfilelog, self).__init__(opener, path)
346 346 self.kwt = kwt
347 347 self.path = path
348 348
349 349 def read(self, node):
350 350 '''Expands keywords when reading filelog.'''
351 351 data = super(kwfilelog, self).read(node)
352 352 if self.renamed(node):
353 353 return data
354 354 return self.kwt.expand(self.path, node, data)
355 355
356 356 def add(self, text, meta, tr, link, p1=None, p2=None):
357 357 '''Removes keyword substitutions when adding to filelog.'''
358 358 text = self.kwt.shrink(self.path, text)
359 359 return super(kwfilelog, self).add(text, meta, tr, link, p1, p2)
360 360
361 361 def cmp(self, node, text):
362 362 '''Removes keyword substitutions for comparison.'''
363 363 text = self.kwt.shrink(self.path, text)
364 364 return super(kwfilelog, self).cmp(node, text)
365 365
366 366 def _status(ui, repo, wctx, kwt, *pats, **opts):
367 367 '''Bails out if [keyword] configuration is not active.
368 368 Returns status of working directory.'''
369 369 if kwt:
370 370 return repo.status(match=scmutil.match(wctx, pats, opts), clean=True,
371 371 unknown=opts.get('unknown') or opts.get('all'))
372 372 if ui.configitems('keyword'):
373 373 raise error.Abort(_('[keyword] patterns cannot match'))
374 374 raise error.Abort(_('no [keyword] patterns configured'))
375 375
376 376 def _kwfwrite(ui, repo, expand, *pats, **opts):
377 377 '''Selects files and passes them to kwtemplater.overwrite.'''
378 378 wctx = repo[None]
379 379 if len(wctx.parents()) > 1:
380 380 raise error.Abort(_('outstanding uncommitted merge'))
381 381 kwt = kwtools['templater']
382 382 with repo.wlock():
383 383 status = _status(ui, repo, wctx, kwt, *pats, **opts)
384 384 if status.modified or status.added or status.removed or status.deleted:
385 385 raise error.Abort(_('outstanding uncommitted changes'))
386 386 kwt.overwrite(wctx, status.clean, True, expand)
387 387
388 388 @command('kwdemo',
389 389 [('d', 'default', None, _('show default keyword template maps')),
390 390 ('f', 'rcfile', '',
391 391 _('read maps from rcfile'), _('FILE'))],
392 392 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...'),
393 393 optionalrepo=True)
394 394 def demo(ui, repo, *args, **opts):
395 395 '''print [keywordmaps] configuration and an expansion example
396 396
397 397 Show current, custom, or default keyword template maps and their
398 398 expansions.
399 399
400 400 Extend the current configuration by specifying maps as arguments
401 401 and using -f/--rcfile to source an external hgrc file.
402 402
403 403 Use -d/--default to disable current configuration.
404 404
405 405 See :hg:`help templates` for information on templates and filters.
406 406 '''
407 407 def demoitems(section, items):
408 408 ui.write('[%s]\n' % section)
409 409 for k, v in sorted(items):
410 410 ui.write('%s = %s\n' % (k, v))
411 411
412 412 fn = 'demo.txt'
413 413 tmpdir = tempfile.mkdtemp('', 'kwdemo.')
414 414 ui.note(_('creating temporary repository at %s\n') % tmpdir)
415 repo = localrepo.localrepository(repo.baseui, tmpdir, True)
415 if repo is None:
416 baseui = ui
417 else:
418 baseui = repo.baseui
419 repo = localrepo.localrepository(baseui, tmpdir, True)
416 420 ui.setconfig('keyword', fn, '', 'keyword')
417 421 svn = ui.configbool('keywordset', 'svn')
418 422 # explicitly set keywordset for demo output
419 423 ui.setconfig('keywordset', 'svn', svn, 'keyword')
420 424
421 425 uikwmaps = ui.configitems('keywordmaps')
422 426 if args or opts.get('rcfile'):
423 427 ui.status(_('\n\tconfiguration using custom keyword template maps\n'))
424 428 if uikwmaps:
425 429 ui.status(_('\textending current template maps\n'))
426 430 if opts.get('default') or not uikwmaps:
427 431 if svn:
428 432 ui.status(_('\toverriding default svn keywordset\n'))
429 433 else:
430 434 ui.status(_('\toverriding default cvs keywordset\n'))
431 435 if opts.get('rcfile'):
432 436 ui.readconfig(opts.get('rcfile'))
433 437 if args:
434 438 # simulate hgrc parsing
435 439 rcmaps = '[keywordmaps]\n%s\n' % '\n'.join(args)
436 440 repo.vfs.write('hgrc', rcmaps)
437 441 ui.readconfig(repo.join('hgrc'))
438 442 kwmaps = dict(ui.configitems('keywordmaps'))
439 443 elif opts.get('default'):
440 444 if svn:
441 445 ui.status(_('\n\tconfiguration using default svn keywordset\n'))
442 446 else:
443 447 ui.status(_('\n\tconfiguration using default cvs keywordset\n'))
444 448 kwmaps = _defaultkwmaps(ui)
445 449 if uikwmaps:
446 450 ui.status(_('\tdisabling current template maps\n'))
447 451 for k, v in kwmaps.iteritems():
448 452 ui.setconfig('keywordmaps', k, v, 'keyword')
449 453 else:
450 454 ui.status(_('\n\tconfiguration using current keyword template maps\n'))
451 455 if uikwmaps:
452 456 kwmaps = dict(uikwmaps)
453 457 else:
454 458 kwmaps = _defaultkwmaps(ui)
455 459
456 460 uisetup(ui)
457 461 reposetup(ui, repo)
458 462 ui.write(('[extensions]\nkeyword =\n'))
459 463 demoitems('keyword', ui.configitems('keyword'))
460 464 demoitems('keywordset', ui.configitems('keywordset'))
461 465 demoitems('keywordmaps', kwmaps.iteritems())
462 466 keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
463 467 repo.wvfs.write(fn, keywords)
464 468 repo[None].add([fn])
465 469 ui.note(_('\nkeywords written to %s:\n') % fn)
466 470 ui.note(keywords)
467 471 with repo.wlock():
468 472 repo.dirstate.setbranch('demobranch')
469 473 for name, cmd in ui.configitems('hooks'):
470 474 if name.split('.', 1)[0].find('commit') > -1:
471 475 repo.ui.setconfig('hooks', name, '', 'keyword')
472 476 msg = _('hg keyword configuration and expansion example')
473 477 ui.note(("hg ci -m '%s'\n" % msg))
474 478 repo.commit(text=msg)
475 479 ui.status(_('\n\tkeywords expanded\n'))
476 480 ui.write(repo.wread(fn))
477 481 repo.wvfs.rmtree(repo.root)
478 482
479 483 @command('kwexpand',
480 484 commands.walkopts,
481 485 _('hg kwexpand [OPTION]... [FILE]...'),
482 486 inferrepo=True)
483 487 def expand(ui, repo, *pats, **opts):
484 488 '''expand keywords in the working directory
485 489
486 490 Run after (re)enabling keyword expansion.
487 491
488 492 kwexpand refuses to run if given files contain local changes.
489 493 '''
490 494 # 3rd argument sets expansion to True
491 495 _kwfwrite(ui, repo, True, *pats, **opts)
492 496
493 497 @command('kwfiles',
494 498 [('A', 'all', None, _('show keyword status flags of all files')),
495 499 ('i', 'ignore', None, _('show files excluded from expansion')),
496 500 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
497 501 ] + commands.walkopts,
498 502 _('hg kwfiles [OPTION]... [FILE]...'),
499 503 inferrepo=True)
500 504 def files(ui, repo, *pats, **opts):
501 505 '''show files configured for keyword expansion
502 506
503 507 List which files in the working directory are matched by the
504 508 [keyword] configuration patterns.
505 509
506 510 Useful to prevent inadvertent keyword expansion and to speed up
507 511 execution by including only files that are actual candidates for
508 512 expansion.
509 513
510 514 See :hg:`help keyword` on how to construct patterns both for
511 515 inclusion and exclusion of files.
512 516
513 517 With -A/--all and -v/--verbose the codes used to show the status
514 518 of files are::
515 519
516 520 K = keyword expansion candidate
517 521 k = keyword expansion candidate (not tracked)
518 522 I = ignored
519 523 i = ignored (not tracked)
520 524 '''
521 525 kwt = kwtools['templater']
522 526 wctx = repo[None]
523 527 status = _status(ui, repo, wctx, kwt, *pats, **opts)
524 528 if pats:
525 529 cwd = repo.getcwd()
526 530 else:
527 531 cwd = ''
528 532 files = []
529 533 if not opts.get('unknown') or opts.get('all'):
530 534 files = sorted(status.modified + status.added + status.clean)
531 535 kwfiles = kwt.iskwfile(files, wctx)
532 536 kwdeleted = kwt.iskwfile(status.deleted, wctx)
533 537 kwunknown = kwt.iskwfile(status.unknown, wctx)
534 538 if not opts.get('ignore') or opts.get('all'):
535 539 showfiles = kwfiles, kwdeleted, kwunknown
536 540 else:
537 541 showfiles = [], [], []
538 542 if opts.get('all') or opts.get('ignore'):
539 543 showfiles += ([f for f in files if f not in kwfiles],
540 544 [f for f in status.unknown if f not in kwunknown])
541 545 kwlabels = 'enabled deleted enabledunknown ignored ignoredunknown'.split()
542 546 kwstates = zip(kwlabels, 'K!kIi', showfiles)
543 547 fm = ui.formatter('kwfiles', opts)
544 548 fmt = '%.0s%s\n'
545 549 if opts.get('all') or ui.verbose:
546 550 fmt = '%s %s\n'
547 551 for kwstate, char, filenames in kwstates:
548 552 label = 'kwfiles.' + kwstate
549 553 for f in filenames:
550 554 fm.startitem()
551 555 fm.write('kwstatus path', fmt, char,
552 556 repo.pathto(f, cwd), label=label)
553 557 fm.end()
554 558
555 559 @command('kwshrink',
556 560 commands.walkopts,
557 561 _('hg kwshrink [OPTION]... [FILE]...'),
558 562 inferrepo=True)
559 563 def shrink(ui, repo, *pats, **opts):
560 564 '''revert expanded keywords in the working directory
561 565
562 566 Must be run before changing/disabling active keywords.
563 567
564 568 kwshrink refuses to run if given files contain local changes.
565 569 '''
566 570 # 3rd argument sets expansion to False
567 571 _kwfwrite(ui, repo, False, *pats, **opts)
568 572
569 573
570 574 def uisetup(ui):
571 575 ''' Monkeypatches dispatch._parse to retrieve user command.'''
572 576
573 577 def kwdispatch_parse(orig, ui, args):
574 578 '''Monkeypatch dispatch._parse to obtain running hg command.'''
575 579 cmd, func, args, options, cmdoptions = orig(ui, args)
576 580 kwtools['hgcmd'] = cmd
577 581 return cmd, func, args, options, cmdoptions
578 582
579 583 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
580 584
581 585 def reposetup(ui, repo):
582 586 '''Sets up repo as kwrepo for keyword substitution.
583 587 Overrides file method to return kwfilelog instead of filelog
584 588 if file matches user configuration.
585 589 Wraps commit to overwrite configured files with updated
586 590 keyword substitutions.
587 591 Monkeypatches patch and webcommands.'''
588 592
589 593 try:
590 594 if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split()
591 595 or '.hg' in util.splitpath(repo.root)
592 596 or repo._url.startswith('bundle:')):
593 597 return
594 598 except AttributeError:
595 599 pass
596 600
597 601 inc, exc = [], ['.hg*']
598 602 for pat, opt in ui.configitems('keyword'):
599 603 if opt != 'ignore':
600 604 inc.append(pat)
601 605 else:
602 606 exc.append(pat)
603 607 if not inc:
604 608 return
605 609
606 610 kwtools['templater'] = kwt = kwtemplater(ui, repo, inc, exc)
607 611
608 612 class kwrepo(repo.__class__):
609 613 def file(self, f):
610 614 if f[0] == '/':
611 615 f = f[1:]
612 616 return kwfilelog(self.svfs, kwt, f)
613 617
614 618 def wread(self, filename):
615 619 data = super(kwrepo, self).wread(filename)
616 620 return kwt.wread(filename, data)
617 621
618 622 def commit(self, *args, **opts):
619 623 # use custom commitctx for user commands
620 624 # other extensions can still wrap repo.commitctx directly
621 625 self.commitctx = self.kwcommitctx
622 626 try:
623 627 return super(kwrepo, self).commit(*args, **opts)
624 628 finally:
625 629 del self.commitctx
626 630
627 631 def kwcommitctx(self, ctx, error=False):
628 632 n = super(kwrepo, self).commitctx(ctx, error)
629 633 # no lock needed, only called from repo.commit() which already locks
630 634 if not kwt.postcommit:
631 635 restrict = kwt.restrict
632 636 kwt.restrict = True
633 637 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
634 638 False, True)
635 639 kwt.restrict = restrict
636 640 return n
637 641
638 642 def rollback(self, dryrun=False, force=False):
639 643 wlock = self.wlock()
640 644 origrestrict = kwt.restrict
641 645 try:
642 646 if not dryrun:
643 647 changed = self['.'].files()
644 648 ret = super(kwrepo, self).rollback(dryrun, force)
645 649 if not dryrun:
646 650 ctx = self['.']
647 651 modified, added = _preselect(ctx.status(), changed)
648 652 kwt.restrict = False
649 653 kwt.overwrite(ctx, modified, True, True)
650 654 kwt.overwrite(ctx, added, True, False)
651 655 return ret
652 656 finally:
653 657 kwt.restrict = origrestrict
654 658 wlock.release()
655 659
656 660 # monkeypatches
657 661 def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None):
658 662 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
659 663 rejects or conflicts due to expanded keywords in working dir.'''
660 664 orig(self, ui, gp, backend, store, eolmode)
661 665 # shrink keywords read from working dir
662 666 self.lines = kwt.shrinklines(self.fname, self.lines)
663 667
664 668 def kwdiff(orig, *args, **kwargs):
665 669 '''Monkeypatch patch.diff to avoid expansion.'''
666 670 kwt.restrict = True
667 671 return orig(*args, **kwargs)
668 672
669 673 def kwweb_skip(orig, web, req, tmpl):
670 674 '''Wraps webcommands.x turning off keyword expansion.'''
671 675 kwt.match = util.never
672 676 return orig(web, req, tmpl)
673 677
674 678 def kw_amend(orig, ui, repo, commitfunc, old, extra, pats, opts):
675 679 '''Wraps cmdutil.amend expanding keywords after amend.'''
676 680 with repo.wlock():
677 681 kwt.postcommit = True
678 682 newid = orig(ui, repo, commitfunc, old, extra, pats, opts)
679 683 if newid != old.node():
680 684 ctx = repo[newid]
681 685 kwt.restrict = True
682 686 kwt.overwrite(ctx, ctx.files(), False, True)
683 687 kwt.restrict = False
684 688 return newid
685 689
686 690 def kw_copy(orig, ui, repo, pats, opts, rename=False):
687 691 '''Wraps cmdutil.copy so that copy/rename destinations do not
688 692 contain expanded keywords.
689 693 Note that the source of a regular file destination may also be a
690 694 symlink:
691 695 hg cp sym x -> x is symlink
692 696 cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords)
693 697 For the latter we have to follow the symlink to find out whether its
694 698 target is configured for expansion and we therefore must unexpand the
695 699 keywords in the destination.'''
696 700 with repo.wlock():
697 701 orig(ui, repo, pats, opts, rename)
698 702 if opts.get('dry_run'):
699 703 return
700 704 wctx = repo[None]
701 705 cwd = repo.getcwd()
702 706
703 707 def haskwsource(dest):
704 708 '''Returns true if dest is a regular file and configured for
705 709 expansion or a symlink which points to a file configured for
706 710 expansion. '''
707 711 source = repo.dirstate.copied(dest)
708 712 if 'l' in wctx.flags(source):
709 713 source = pathutil.canonpath(repo.root, cwd,
710 714 os.path.realpath(source))
711 715 return kwt.match(source)
712 716
713 717 candidates = [f for f in repo.dirstate.copies() if
714 718 'l' not in wctx.flags(f) and haskwsource(f)]
715 719 kwt.overwrite(wctx, candidates, False, False)
716 720
717 721 def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
718 722 '''Wraps record.dorecord expanding keywords after recording.'''
719 723 with repo.wlock():
720 724 # record returns 0 even when nothing has changed
721 725 # therefore compare nodes before and after
722 726 kwt.postcommit = True
723 727 ctx = repo['.']
724 728 wstatus = ctx.status()
725 729 ret = orig(ui, repo, commitfunc, *pats, **opts)
726 730 recctx = repo['.']
727 731 if ctx != recctx:
728 732 modified, added = _preselect(wstatus, recctx.files())
729 733 kwt.restrict = False
730 734 kwt.overwrite(recctx, modified, False, True)
731 735 kwt.overwrite(recctx, added, False, True, True)
732 736 kwt.restrict = True
733 737 return ret
734 738
735 739 def kwfilectx_cmp(orig, self, fctx):
736 740 # keyword affects data size, comparing wdir and filelog size does
737 741 # not make sense
738 742 if (fctx._filenode is None and
739 743 (self._repo._encodefilterpats or
740 744 kwt.match(fctx.path()) and 'l' not in fctx.flags() or
741 745 self.size() - 4 == fctx.size()) or
742 746 self.size() == fctx.size()):
743 747 return self._filelog.cmp(self._filenode, fctx.data())
744 748 return True
745 749
746 750 extensions.wrapfunction(context.filectx, 'cmp', kwfilectx_cmp)
747 751 extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
748 752 extensions.wrapfunction(patch, 'diff', kwdiff)
749 753 extensions.wrapfunction(cmdutil, 'amend', kw_amend)
750 754 extensions.wrapfunction(cmdutil, 'copy', kw_copy)
751 755 extensions.wrapfunction(cmdutil, 'dorecord', kw_dorecord)
752 756 for c in 'annotate changeset rev filediff diff'.split():
753 757 extensions.wrapfunction(webcommands, c, kwweb_skip)
754 758 repo.__class__ = kwrepo
@@ -1,1363 +1,1375 b''
1 Run kwdemo outside a repo
2 $ hg -q --config extensions.keyword= --config keywordmaps.Foo="{author|user}" kwdemo
3 [extensions]
4 keyword =
5 [keyword]
6 demo.txt =
7 [keywordset]
8 svn = False
9 [keywordmaps]
10 Foo = {author|user}
11 $Foo: test $
12
1 13 $ cat <<EOF >> $HGRCPATH
2 14 > [extensions]
3 15 > keyword =
4 16 > mq =
5 17 > notify =
6 18 > record =
7 19 > transplant =
8 20 > [ui]
9 21 > interactive = true
10 22 > EOF
11 23
12 24 hide outer repo
13 25 $ hg init
14 26
15 27 Run kwdemo before [keyword] files are set up
16 28 as it would succeed without uisetup otherwise
17 29
18 30 $ hg --quiet kwdemo
19 31 [extensions]
20 32 keyword =
21 33 [keyword]
22 34 demo.txt =
23 35 [keywordset]
24 36 svn = False
25 37 [keywordmaps]
26 38 Author = {author|user}
27 39 Date = {date|utcdate}
28 40 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
29 41 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
30 42 RCSFile = {file|basename},v
31 43 RCSfile = {file|basename},v
32 44 Revision = {node|short}
33 45 Source = {root}/{file},v
34 46 $Author: test $
35 47 $Date: ????/??/?? ??:??:?? $ (glob)
36 48 $Header: */demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
37 49 $Id: demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
38 50 $RCSFile: demo.txt,v $
39 51 $RCSfile: demo.txt,v $
40 52 $Revision: ???????????? $ (glob)
41 53 $Source: */demo.txt,v $ (glob)
42 54
43 55 $ hg --quiet kwdemo "Branch = {branches}"
44 56 [extensions]
45 57 keyword =
46 58 [keyword]
47 59 demo.txt =
48 60 [keywordset]
49 61 svn = False
50 62 [keywordmaps]
51 63 Branch = {branches}
52 64 $Branch: demobranch $
53 65
54 66 (test template filter svnisodate and svnutcdate)
55 67
56 68 $ hg --quiet kwdemo --config keywordset.svn=True
57 69 [extensions]
58 70 keyword =
59 71 [keyword]
60 72 demo.txt =
61 73 [keywordset]
62 74 svn = True
63 75 [keywordmaps]
64 76 Author = {author|user}
65 77 Date = {date|svnisodate}
66 78 Id = {file|basename},v {node|short} {date|svnutcdate} {author|user}
67 79 LastChangedBy = {author|user}
68 80 LastChangedDate = {date|svnisodate}
69 81 LastChangedRevision = {node|short}
70 82 Revision = {node|short}
71 83 $Author: test $
72 84 $Date: ????-??-?? ??:??:?? ????? (???, ?? ??? ????) $ (glob)
73 85 $Id: demo.txt,v ???????????? ????-??-?? ??:??:??Z test $ (glob)
74 86 $LastChangedBy: test $
75 87 $LastChangedDate: ????-??-?? ??:??:?? ????? (???, ?? ??? ????) $ (glob)
76 88 $LastChangedRevision: ???????????? $ (glob)
77 89 $Revision: ???????????? $ (glob)
78 90
79 91 $ cat <<EOF >> $HGRCPATH
80 92 > [keyword]
81 93 > ** =
82 94 > b = ignore
83 95 > i = ignore
84 96 > [hooks]
85 97 > EOF
86 98 $ cp $HGRCPATH $HGRCPATH.nohooks
87 99 > cat <<EOF >> $HGRCPATH
88 100 > commit=
89 101 > commit.test=cp a hooktest
90 102 > EOF
91 103
92 104 $ hg init Test-bndl
93 105 $ cd Test-bndl
94 106
95 107 kwshrink should exit silently in empty/invalid repo
96 108
97 109 $ hg kwshrink
98 110
99 111 Symlinks cannot be created on Windows.
100 112 A bundle to test this was made with:
101 113 hg init t
102 114 cd t
103 115 echo a > a
104 116 ln -s a sym
105 117 hg add sym
106 118 hg ci -m addsym -u mercurial
107 119 hg bundle --base null ../test-keyword.hg
108 120
109 121 $ hg pull -u "$TESTDIR"/bundles/test-keyword.hg
110 122 pulling from *test-keyword.hg (glob)
111 123 requesting all changes
112 124 adding changesets
113 125 adding manifests
114 126 adding file changes
115 127 added 1 changesets with 1 changes to 1 files
116 128 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 129
118 130 $ echo 'expand $Id$' > a
119 131 $ echo 'do not process $Id:' >> a
120 132 $ echo 'xxx $' >> a
121 133 $ echo 'ignore $Id$' > b
122 134
123 135 Output files as they were created
124 136
125 137 $ cat a b
126 138 expand $Id$
127 139 do not process $Id:
128 140 xxx $
129 141 ignore $Id$
130 142
131 143 no kwfiles
132 144
133 145 $ hg kwfiles
134 146
135 147 untracked candidates
136 148
137 149 $ hg -v kwfiles --unknown
138 150 k a
139 151
140 152 Add files and check status
141 153
142 154 $ hg addremove
143 155 adding a
144 156 adding b
145 157 $ hg status
146 158 A a
147 159 A b
148 160
149 161
150 162 Default keyword expansion including commit hook
151 163 Interrupted commit should not change state or run commit hook
152 164
153 165 $ hg --debug commit
154 166 abort: empty commit message
155 167 [255]
156 168 $ hg status
157 169 A a
158 170 A b
159 171
160 172 Commit with several checks
161 173
162 174 $ hg --debug commit -mabsym -u 'User Name <user@example.com>'
163 175 committing files:
164 176 a
165 177 b
166 178 committing manifest
167 179 committing changelog
168 180 overwriting a expanding keywords
169 181 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
170 182 running hook commit.test: cp a hooktest
171 183 $ hg status
172 184 ? hooktest
173 185 $ hg debugrebuildstate
174 186 $ hg --quiet identify
175 187 ef63ca68695b
176 188
177 189 cat files in working directory with keywords expanded
178 190
179 191 $ cat a b
180 192 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
181 193 do not process $Id:
182 194 xxx $
183 195 ignore $Id$
184 196
185 197 hg cat files and symlink, no expansion
186 198
187 199 $ hg cat sym a b && echo
188 200 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
189 201 do not process $Id:
190 202 xxx $
191 203 ignore $Id$
192 204 a
193 205
194 206 $ diff a hooktest
195 207
196 208 $ cp $HGRCPATH.nohooks $HGRCPATH
197 209 $ rm hooktest
198 210
199 211 hg status of kw-ignored binary file starting with '\1\n'
200 212
201 213 >>> open("i", "wb").write("\1\nfoo")
202 214 $ hg -q commit -Am metasep i
203 215 $ hg status
204 216 >>> open("i", "wb").write("\1\nbar")
205 217 $ hg status
206 218 M i
207 219 $ hg -q commit -m "modify metasep" i
208 220 $ hg status --rev 2:3
209 221 M i
210 222 $ touch empty
211 223 $ hg -q commit -A -m "another file"
212 224 $ hg status -A --rev 3:4 i
213 225 C i
214 226
215 227 $ hg -q strip --no-backup 2
216 228
217 229 Test hook execution
218 230
219 231 bundle
220 232
221 233 $ hg bundle --base null ../kw.hg
222 234 2 changesets found
223 235 $ cd ..
224 236 $ hg init Test
225 237 $ cd Test
226 238
227 239 Notify on pull to check whether keywords stay as is in email
228 240 ie. if patch.diff wrapper acts as it should
229 241
230 242 $ cat <<EOF >> $HGRCPATH
231 243 > [hooks]
232 244 > incoming.notify = python:hgext.notify.hook
233 245 > [notify]
234 246 > sources = pull
235 247 > diffstat = False
236 248 > maxsubject = 15
237 249 > [reposubs]
238 250 > * = Test
239 251 > EOF
240 252
241 253 Pull from bundle and trigger notify
242 254
243 255 $ hg pull -u ../kw.hg
244 256 pulling from ../kw.hg
245 257 requesting all changes
246 258 adding changesets
247 259 adding manifests
248 260 adding file changes
249 261 added 2 changesets with 3 changes to 3 files
250 262 Content-Type: text/plain; charset="us-ascii"
251 263 MIME-Version: 1.0
252 264 Content-Transfer-Encoding: 7bit
253 265 Date: * (glob)
254 266 Subject: changeset in...
255 267 From: mercurial
256 268 X-Hg-Notification: changeset a2392c293916
257 269 Message-Id: <hg.a2392c293916*> (glob)
258 270 To: Test
259 271
260 272 changeset a2392c293916 in $TESTTMP/Test (glob)
261 273 details: $TESTTMP/Test?cmd=changeset;node=a2392c293916
262 274 description:
263 275 addsym
264 276
265 277 diffs (6 lines):
266 278
267 279 diff -r 000000000000 -r a2392c293916 sym
268 280 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
269 281 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
270 282 @@ -0,0 +1,1 @@
271 283 +a
272 284 \ No newline at end of file
273 285 Content-Type: text/plain; charset="us-ascii"
274 286 MIME-Version: 1.0
275 287 Content-Transfer-Encoding: 7bit
276 288 Date:* (glob)
277 289 Subject: changeset in...
278 290 From: User Name <user@example.com>
279 291 X-Hg-Notification: changeset ef63ca68695b
280 292 Message-Id: <hg.ef63ca68695b*> (glob)
281 293 To: Test
282 294
283 295 changeset ef63ca68695b in $TESTTMP/Test (glob)
284 296 details: $TESTTMP/Test?cmd=changeset;node=ef63ca68695b
285 297 description:
286 298 absym
287 299
288 300 diffs (12 lines):
289 301
290 302 diff -r a2392c293916 -r ef63ca68695b a
291 303 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
292 304 +++ b/a Thu Jan 01 00:00:00 1970 +0000
293 305 @@ -0,0 +1,3 @@
294 306 +expand $Id$
295 307 +do not process $Id:
296 308 +xxx $
297 309 diff -r a2392c293916 -r ef63ca68695b b
298 310 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
299 311 +++ b/b Thu Jan 01 00:00:00 1970 +0000
300 312 @@ -0,0 +1,1 @@
301 313 +ignore $Id$
302 314 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
303 315
304 316 $ cp $HGRCPATH.nohooks $HGRCPATH
305 317
306 318 Touch files and check with status
307 319
308 320 $ touch a b
309 321 $ hg status
310 322
311 323 Update and expand
312 324
313 325 $ rm sym a b
314 326 $ hg update -C
315 327 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
316 328 $ cat a b
317 329 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
318 330 do not process $Id:
319 331 xxx $
320 332 ignore $Id$
321 333
322 334 Check whether expansion is filewise and file mode is preserved
323 335
324 336 $ echo '$Id$' > c
325 337 $ echo 'tests for different changenodes' >> c
326 338 #if unix-permissions
327 339 $ chmod 600 c
328 340 $ ls -l c | cut -b 1-10
329 341 -rw-------
330 342 #endif
331 343
332 344 commit file c
333 345
334 346 $ hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
335 347 adding c
336 348 #if unix-permissions
337 349 $ ls -l c | cut -b 1-10
338 350 -rw-------
339 351 #endif
340 352
341 353 force expansion
342 354
343 355 $ hg -v kwexpand
344 356 overwriting a expanding keywords
345 357 overwriting c expanding keywords
346 358
347 359 compare changenodes in a and c
348 360
349 361 $ cat a c
350 362 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
351 363 do not process $Id:
352 364 xxx $
353 365 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
354 366 tests for different changenodes
355 367
356 368 record
357 369
358 370 $ echo '$Id$' > r
359 371 $ hg add r
360 372
361 373 record chunk
362 374
363 375 >>> lines = open('a', 'rb').readlines()
364 376 >>> lines.insert(1, 'foo\n')
365 377 >>> lines.append('bar\n')
366 378 >>> open('a', 'wb').writelines(lines)
367 379 $ hg record -d '10 1' -m rectest a<<EOF
368 380 > y
369 381 > y
370 382 > n
371 383 > EOF
372 384 diff --git a/a b/a
373 385 2 hunks, 2 lines changed
374 386 examine changes to 'a'? [Ynesfdaq?] y
375 387
376 388 @@ -1,3 +1,4 @@
377 389 expand $Id$
378 390 +foo
379 391 do not process $Id:
380 392 xxx $
381 393 record change 1/2 to 'a'? [Ynesfdaq?] y
382 394
383 395 @@ -2,2 +3,3 @@
384 396 do not process $Id:
385 397 xxx $
386 398 +bar
387 399 record change 2/2 to 'a'? [Ynesfdaq?] n
388 400
389 401
390 402 $ hg identify
391 403 5f5eb23505c3+ tip
392 404 $ hg status
393 405 M a
394 406 A r
395 407
396 408 Cat modified file a
397 409
398 410 $ cat a
399 411 expand $Id: a,v 5f5eb23505c3 1970/01/01 00:00:10 test $
400 412 foo
401 413 do not process $Id:
402 414 xxx $
403 415 bar
404 416
405 417 Diff remaining chunk
406 418
407 419 $ hg diff a
408 420 diff -r 5f5eb23505c3 a
409 421 --- a/a Thu Jan 01 00:00:09 1970 -0000
410 422 +++ b/a * (glob)
411 423 @@ -2,3 +2,4 @@
412 424 foo
413 425 do not process $Id:
414 426 xxx $
415 427 +bar
416 428
417 429 $ hg rollback
418 430 repository tip rolled back to revision 2 (undo commit)
419 431 working directory now based on revision 2
420 432
421 433 Record all chunks in file a
422 434
423 435 $ echo foo > msg
424 436
425 437 - do not use "hg record -m" here!
426 438
427 439 $ hg record -l msg -d '11 1' a<<EOF
428 440 > y
429 441 > y
430 442 > y
431 443 > EOF
432 444 diff --git a/a b/a
433 445 2 hunks, 2 lines changed
434 446 examine changes to 'a'? [Ynesfdaq?] y
435 447
436 448 @@ -1,3 +1,4 @@
437 449 expand $Id$
438 450 +foo
439 451 do not process $Id:
440 452 xxx $
441 453 record change 1/2 to 'a'? [Ynesfdaq?] y
442 454
443 455 @@ -2,2 +3,3 @@
444 456 do not process $Id:
445 457 xxx $
446 458 +bar
447 459 record change 2/2 to 'a'? [Ynesfdaq?] y
448 460
449 461
450 462 File a should be clean
451 463
452 464 $ hg status -A a
453 465 C a
454 466
455 467 rollback and revert expansion
456 468
457 469 $ cat a
458 470 expand $Id: a,v 78e0a02d76aa 1970/01/01 00:00:11 test $
459 471 foo
460 472 do not process $Id:
461 473 xxx $
462 474 bar
463 475 $ hg --verbose rollback
464 476 repository tip rolled back to revision 2 (undo commit)
465 477 working directory now based on revision 2
466 478 overwriting a expanding keywords
467 479 $ hg status a
468 480 M a
469 481 $ cat a
470 482 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
471 483 foo
472 484 do not process $Id:
473 485 xxx $
474 486 bar
475 487 $ echo '$Id$' > y
476 488 $ echo '$Id$' > z
477 489 $ hg add y
478 490 $ hg commit -Am "rollback only" z
479 491 $ cat z
480 492 $Id: z,v 45a5d3adce53 1970/01/01 00:00:00 test $
481 493 $ hg --verbose rollback
482 494 repository tip rolled back to revision 2 (undo commit)
483 495 working directory now based on revision 2
484 496 overwriting z shrinking keywords
485 497
486 498 Only z should be overwritten
487 499
488 500 $ hg status a y z
489 501 M a
490 502 A y
491 503 A z
492 504 $ cat z
493 505 $Id$
494 506 $ hg forget y z
495 507 $ rm y z
496 508
497 509 record added file alone
498 510
499 511 $ hg -v record -l msg -d '12 2' r<<EOF
500 512 > y
501 513 > y
502 514 > EOF
503 515 diff --git a/r b/r
504 516 new file mode 100644
505 517 examine changes to 'r'? [Ynesfdaq?] y
506 518
507 519 @@ -0,0 +1,1 @@
508 520 +$Id$
509 521 record this change to 'r'? [Ynesfdaq?] y
510 522
511 523 resolving manifests
512 524 patching file r
513 525 committing files:
514 526 r
515 527 committing manifest
516 528 committing changelog
517 529 committed changeset 3:82a2f715724d
518 530 overwriting r expanding keywords
519 531 $ hg status r
520 532 $ hg --verbose rollback
521 533 repository tip rolled back to revision 2 (undo commit)
522 534 working directory now based on revision 2
523 535 overwriting r shrinking keywords
524 536 $ hg forget r
525 537 $ rm msg r
526 538 $ hg update -C
527 539 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
528 540
529 541 record added keyword ignored file
530 542
531 543 $ echo '$Id$' > i
532 544 $ hg add i
533 545 $ hg --verbose record -d '13 1' -m recignored<<EOF
534 546 > y
535 547 > y
536 548 > EOF
537 549 diff --git a/i b/i
538 550 new file mode 100644
539 551 examine changes to 'i'? [Ynesfdaq?] y
540 552
541 553 @@ -0,0 +1,1 @@
542 554 +$Id$
543 555 record this change to 'i'? [Ynesfdaq?] y
544 556
545 557 resolving manifests
546 558 patching file i
547 559 committing files:
548 560 i
549 561 committing manifest
550 562 committing changelog
551 563 committed changeset 3:9f40ceb5a072
552 564 $ cat i
553 565 $Id$
554 566 $ hg -q rollback
555 567 $ hg forget i
556 568 $ rm i
557 569
558 570 amend
559 571
560 572 $ echo amend >> a
561 573 $ echo amend >> b
562 574 $ hg -q commit -d '14 1' -m 'prepare amend'
563 575
564 576 $ hg --debug commit --amend -d '15 1' -m 'amend without changes' | grep keywords
565 577 overwriting a expanding keywords
566 578 $ hg -q id
567 579 67d8c481a6be
568 580 $ head -1 a
569 581 expand $Id: a,v 67d8c481a6be 1970/01/01 00:00:15 test $
570 582
571 583 $ hg -q strip --no-backup tip
572 584
573 585 Test patch queue repo
574 586
575 587 $ hg init --mq
576 588 $ hg qimport -r tip -n mqtest.diff
577 589 $ hg commit --mq -m mqtest
578 590
579 591 Keywords should not be expanded in patch
580 592
581 593 $ cat .hg/patches/mqtest.diff
582 594 # HG changeset patch
583 595 # User User Name <user@example.com>
584 596 # Date 1 0
585 597 # Thu Jan 01 00:00:01 1970 +0000
586 598 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
587 599 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
588 600 cndiff
589 601
590 602 diff -r ef63ca68695b -r 40a904bbbe4c c
591 603 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
592 604 +++ b/c Thu Jan 01 00:00:01 1970 +0000
593 605 @@ -0,0 +1,2 @@
594 606 +$Id$
595 607 +tests for different changenodes
596 608
597 609 $ hg qpop
598 610 popping mqtest.diff
599 611 patch queue now empty
600 612
601 613 qgoto, implying qpush, should expand
602 614
603 615 $ hg qgoto mqtest.diff
604 616 applying mqtest.diff
605 617 now at: mqtest.diff
606 618 $ cat c
607 619 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
608 620 tests for different changenodes
609 621 $ hg cat c
610 622 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
611 623 tests for different changenodes
612 624
613 625 Keywords should not be expanded in filelog
614 626
615 627 $ hg --config 'extensions.keyword=!' cat c
616 628 $Id$
617 629 tests for different changenodes
618 630
619 631 qpop and move on
620 632
621 633 $ hg qpop
622 634 popping mqtest.diff
623 635 patch queue now empty
624 636
625 637 Copy and show added kwfiles
626 638
627 639 $ hg cp a c
628 640 $ hg kwfiles
629 641 a
630 642 c
631 643
632 644 Commit and show expansion in original and copy
633 645
634 646 $ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
635 647 committing files:
636 648 c
637 649 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
638 650 committing manifest
639 651 committing changelog
640 652 overwriting c expanding keywords
641 653 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
642 654 $ cat a c
643 655 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
644 656 do not process $Id:
645 657 xxx $
646 658 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
647 659 do not process $Id:
648 660 xxx $
649 661
650 662 Touch copied c and check its status
651 663
652 664 $ touch c
653 665 $ hg status
654 666
655 667 Copy kwfile to keyword ignored file unexpanding keywords
656 668
657 669 $ hg --verbose copy a i
658 670 copying a to i
659 671 overwriting i shrinking keywords
660 672 $ head -n 1 i
661 673 expand $Id$
662 674 $ hg forget i
663 675 $ rm i
664 676
665 677 Copy ignored file to ignored file: no overwriting
666 678
667 679 $ hg --verbose copy b i
668 680 copying b to i
669 681 $ hg forget i
670 682 $ rm i
671 683
672 684 cp symlink file; hg cp -A symlink file (part1)
673 685 - copied symlink points to kwfile: overwrite
674 686
675 687 #if symlink
676 688 $ cp sym i
677 689 $ ls -l i
678 690 -rw-r--r--* (glob)
679 691 $ head -1 i
680 692 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
681 693 $ hg copy --after --verbose sym i
682 694 copying sym to i
683 695 overwriting i shrinking keywords
684 696 $ head -1 i
685 697 expand $Id$
686 698 $ hg forget i
687 699 $ rm i
688 700 #endif
689 701
690 702 Test different options of hg kwfiles
691 703
692 704 $ hg kwfiles
693 705 a
694 706 c
695 707 $ hg -v kwfiles --ignore
696 708 I b
697 709 I sym
698 710 $ hg kwfiles --all
699 711 K a
700 712 K c
701 713 I b
702 714 I sym
703 715
704 716 Diff specific revision
705 717
706 718 $ hg diff --rev 1
707 719 diff -r ef63ca68695b c
708 720 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
709 721 +++ b/c * (glob)
710 722 @@ -0,0 +1,3 @@
711 723 +expand $Id$
712 724 +do not process $Id:
713 725 +xxx $
714 726
715 727 Status after rollback:
716 728
717 729 $ hg rollback
718 730 repository tip rolled back to revision 1 (undo commit)
719 731 working directory now based on revision 1
720 732 $ hg status
721 733 A c
722 734 $ hg update --clean
723 735 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
724 736
725 737 #if symlink
726 738
727 739 cp symlink file; hg cp -A symlink file (part2)
728 740 - copied symlink points to kw ignored file: do not overwrite
729 741
730 742 $ cat a > i
731 743 $ ln -s i symignored
732 744 $ hg commit -Am 'fake expansion in ignored and symlink' i symignored
733 745 $ cp symignored x
734 746 $ hg copy --after --verbose symignored x
735 747 copying symignored to x
736 748 $ head -n 1 x
737 749 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
738 750 $ hg forget x
739 751 $ rm x
740 752
741 753 $ hg rollback
742 754 repository tip rolled back to revision 1 (undo commit)
743 755 working directory now based on revision 1
744 756 $ hg update --clean
745 757 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
746 758 $ rm i symignored
747 759
748 760 #endif
749 761
750 762 Custom keywordmaps as argument to kwdemo
751 763
752 764 $ hg --quiet kwdemo "Xinfo = {author}: {desc}"
753 765 [extensions]
754 766 keyword =
755 767 [keyword]
756 768 ** =
757 769 b = ignore
758 770 demo.txt =
759 771 i = ignore
760 772 [keywordset]
761 773 svn = False
762 774 [keywordmaps]
763 775 Xinfo = {author}: {desc}
764 776 $Xinfo: test: hg keyword configuration and expansion example $
765 777
766 778 Configure custom keywordmaps
767 779
768 780 $ cat <<EOF >>$HGRCPATH
769 781 > [keywordmaps]
770 782 > Id = {file} {node|short} {date|rfc822date} {author|user}
771 783 > Xinfo = {author}: {desc}
772 784 > EOF
773 785
774 786 Cat and hg cat files before custom expansion
775 787
776 788 $ cat a b
777 789 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
778 790 do not process $Id:
779 791 xxx $
780 792 ignore $Id$
781 793 $ hg cat sym a b && echo
782 794 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
783 795 do not process $Id:
784 796 xxx $
785 797 ignore $Id$
786 798 a
787 799
788 800 Write custom keyword and prepare multi-line commit message
789 801
790 802 $ echo '$Xinfo$' >> a
791 803 $ cat <<EOF >> log
792 804 > firstline
793 805 > secondline
794 806 > EOF
795 807
796 808 Interrupted commit should not change state
797 809
798 810 $ hg commit
799 811 abort: empty commit message
800 812 [255]
801 813 $ hg status
802 814 M a
803 815 ? c
804 816 ? log
805 817
806 818 Commit with multi-line message and custom expansion
807 819
808 820 $ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
809 821 committing files:
810 822 a
811 823 committing manifest
812 824 committing changelog
813 825 overwriting a expanding keywords
814 826 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
815 827 $ rm log
816 828
817 829 Stat, verify and show custom expansion (firstline)
818 830
819 831 $ hg status
820 832 ? c
821 833 $ hg verify
822 834 checking changesets
823 835 checking manifests
824 836 crosschecking files in changesets and manifests
825 837 checking files
826 838 3 files, 3 changesets, 4 total revisions
827 839 $ cat a b
828 840 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
829 841 do not process $Id:
830 842 xxx $
831 843 $Xinfo: User Name <user@example.com>: firstline $
832 844 ignore $Id$
833 845 $ hg cat sym a b && echo
834 846 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
835 847 do not process $Id:
836 848 xxx $
837 849 $Xinfo: User Name <user@example.com>: firstline $
838 850 ignore $Id$
839 851 a
840 852
841 853 annotate
842 854
843 855 $ hg annotate a
844 856 1: expand $Id$
845 857 1: do not process $Id:
846 858 1: xxx $
847 859 2: $Xinfo$
848 860
849 861 remove with status checks
850 862
851 863 $ hg debugrebuildstate
852 864 $ hg remove a
853 865 $ hg --debug commit -m rma
854 866 committing files:
855 867 committing manifest
856 868 committing changelog
857 869 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
858 870 $ hg status
859 871 ? c
860 872
861 873 Rollback, revert, and check expansion
862 874
863 875 $ hg rollback
864 876 repository tip rolled back to revision 2 (undo commit)
865 877 working directory now based on revision 2
866 878 $ hg status
867 879 R a
868 880 ? c
869 881 $ hg revert --no-backup --rev tip a
870 882 $ cat a
871 883 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
872 884 do not process $Id:
873 885 xxx $
874 886 $Xinfo: User Name <user@example.com>: firstline $
875 887
876 888 Clone to test global and local configurations
877 889
878 890 $ cd ..
879 891
880 892 Expansion in destination with global configuration
881 893
882 894 $ hg --quiet clone Test globalconf
883 895 $ cat globalconf/a
884 896 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
885 897 do not process $Id:
886 898 xxx $
887 899 $Xinfo: User Name <user@example.com>: firstline $
888 900
889 901 No expansion in destination with local configuration in origin only
890 902
891 903 $ hg --quiet --config 'keyword.**=ignore' clone Test localconf
892 904 $ cat localconf/a
893 905 expand $Id$
894 906 do not process $Id:
895 907 xxx $
896 908 $Xinfo$
897 909
898 910 Clone to test incoming
899 911
900 912 $ hg clone -r1 Test Test-a
901 913 adding changesets
902 914 adding manifests
903 915 adding file changes
904 916 added 2 changesets with 3 changes to 3 files
905 917 updating to branch default
906 918 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
907 919 $ cd Test-a
908 920 $ cat <<EOF >> .hg/hgrc
909 921 > [paths]
910 922 > default = ../Test
911 923 > EOF
912 924 $ hg incoming
913 925 comparing with $TESTTMP/Test (glob)
914 926 searching for changes
915 927 changeset: 2:bb948857c743
916 928 tag: tip
917 929 user: User Name <user@example.com>
918 930 date: Thu Jan 01 00:00:02 1970 +0000
919 931 summary: firstline
920 932
921 933 Imported patch should not be rejected
922 934
923 935 >>> import re
924 936 >>> text = re.sub(r'(Id.*)', r'\1 rejecttest', open('a').read())
925 937 >>> open('a', 'wb').write(text)
926 938 $ hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
927 939 committing files:
928 940 a
929 941 committing manifest
930 942 committing changelog
931 943 overwriting a expanding keywords
932 944 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
933 945 $ hg export -o ../rejecttest.diff tip
934 946 $ cd ../Test
935 947 $ hg import ../rejecttest.diff
936 948 applying ../rejecttest.diff
937 949 $ cat a b
938 950 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
939 951 do not process $Id: rejecttest
940 952 xxx $
941 953 $Xinfo: User Name <user@example.com>: rejects? $
942 954 ignore $Id$
943 955
944 956 $ hg rollback
945 957 repository tip rolled back to revision 2 (undo import)
946 958 working directory now based on revision 2
947 959 $ hg update --clean
948 960 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
949 961
950 962 kwexpand/kwshrink on selected files
951 963
952 964 $ mkdir x
953 965 $ hg copy a x/a
954 966 $ hg --verbose kwshrink a
955 967 overwriting a shrinking keywords
956 968 - sleep required for dirstate.normal() check
957 969 $ sleep 1
958 970 $ hg status a
959 971 $ hg --verbose kwexpand a
960 972 overwriting a expanding keywords
961 973 $ hg status a
962 974
963 975 kwexpand x/a should abort
964 976
965 977 $ hg --verbose kwexpand x/a
966 978 abort: outstanding uncommitted changes
967 979 [255]
968 980 $ cd x
969 981 $ hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
970 982 committing files:
971 983 x/a
972 984 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
973 985 committing manifest
974 986 committing changelog
975 987 overwriting x/a expanding keywords
976 988 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
977 989 $ cat a
978 990 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
979 991 do not process $Id:
980 992 xxx $
981 993 $Xinfo: User Name <user@example.com>: xa $
982 994
983 995 kwshrink a inside directory x
984 996
985 997 $ hg --verbose kwshrink a
986 998 overwriting x/a shrinking keywords
987 999 $ cat a
988 1000 expand $Id$
989 1001 do not process $Id:
990 1002 xxx $
991 1003 $Xinfo$
992 1004 $ cd ..
993 1005
994 1006 kwexpand nonexistent
995 1007
996 1008 $ hg kwexpand nonexistent
997 1009 nonexistent:* (glob)
998 1010
999 1011
1000 1012 #if serve
1001 1013 hg serve
1002 1014 - expand with hgweb file
1003 1015 - no expansion with hgweb annotate/changeset/filediff
1004 1016 - check errors
1005 1017
1006 1018 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1007 1019 $ cat hg.pid >> $DAEMON_PIDS
1008 1020 $ get-with-headers.py localhost:$HGPORT 'file/tip/a/?style=raw'
1009 1021 200 Script output follows
1010 1022
1011 1023 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1012 1024 do not process $Id:
1013 1025 xxx $
1014 1026 $Xinfo: User Name <user@example.com>: firstline $
1015 1027 $ get-with-headers.py localhost:$HGPORT 'annotate/tip/a/?style=raw'
1016 1028 200 Script output follows
1017 1029
1018 1030
1019 1031 user@1: expand $Id$
1020 1032 user@1: do not process $Id:
1021 1033 user@1: xxx $
1022 1034 user@2: $Xinfo$
1023 1035
1024 1036
1025 1037
1026 1038
1027 1039 $ get-with-headers.py localhost:$HGPORT 'rev/tip/?style=raw'
1028 1040 200 Script output follows
1029 1041
1030 1042
1031 1043 # HG changeset patch
1032 1044 # User User Name <user@example.com>
1033 1045 # Date 3 0
1034 1046 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
1035 1047 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
1036 1048 xa
1037 1049
1038 1050 diff -r bb948857c743 -r b4560182a3f9 x/a
1039 1051 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1040 1052 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
1041 1053 @@ -0,0 +1,4 @@
1042 1054 +expand $Id$
1043 1055 +do not process $Id:
1044 1056 +xxx $
1045 1057 +$Xinfo$
1046 1058
1047 1059 $ get-with-headers.py localhost:$HGPORT 'diff/bb948857c743/a?style=raw'
1048 1060 200 Script output follows
1049 1061
1050 1062
1051 1063 diff -r ef63ca68695b -r bb948857c743 a
1052 1064 --- a/a Thu Jan 01 00:00:00 1970 +0000
1053 1065 +++ b/a Thu Jan 01 00:00:02 1970 +0000
1054 1066 @@ -1,3 +1,4 @@
1055 1067 expand $Id$
1056 1068 do not process $Id:
1057 1069 xxx $
1058 1070 +$Xinfo$
1059 1071
1060 1072
1061 1073
1062 1074
1063 1075 $ cat errors.log
1064 1076 #endif
1065 1077
1066 1078 Prepare merge and resolve tests
1067 1079
1068 1080 $ echo '$Id$' > m
1069 1081 $ hg add m
1070 1082 $ hg commit -m 4kw
1071 1083 $ echo foo >> m
1072 1084 $ hg commit -m 5foo
1073 1085
1074 1086 simplemerge
1075 1087
1076 1088 $ hg update 4
1077 1089 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1078 1090 $ echo foo >> m
1079 1091 $ hg commit -m 6foo
1080 1092 created new head
1081 1093 $ hg merge
1082 1094 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1083 1095 (branch merge, don't forget to commit)
1084 1096 $ hg commit -m simplemerge
1085 1097 $ cat m
1086 1098 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
1087 1099 foo
1088 1100
1089 1101 conflict: keyword should stay outside conflict zone
1090 1102
1091 1103 $ hg update 4
1092 1104 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1093 1105 $ echo bar >> m
1094 1106 $ hg commit -m 8bar
1095 1107 created new head
1096 1108 $ hg merge
1097 1109 merging m
1098 1110 warning: conflicts while merging m! (edit, then use 'hg resolve --mark')
1099 1111 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1100 1112 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1101 1113 [1]
1102 1114 $ cat m
1103 1115 $Id$
1104 1116 <<<<<<< local: 88a80c8d172e - test: 8bar
1105 1117 bar
1106 1118 =======
1107 1119 foo
1108 1120 >>>>>>> other: 85d2d2d732a5 - test: simplemerge
1109 1121
1110 1122 resolve to local, m must contain hash of last change (local parent)
1111 1123
1112 1124 $ hg resolve -t internal:local -a
1113 1125 (no more unresolved files)
1114 1126 $ hg commit -m localresolve
1115 1127 $ cat m
1116 1128 $Id: m 88a80c8d172e Thu, 01 Jan 1970 00:00:00 +0000 test $
1117 1129 bar
1118 1130
1119 1131 Test restricted mode with transplant -b
1120 1132
1121 1133 $ hg update 6
1122 1134 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1123 1135 $ hg branch foo
1124 1136 marked working directory as branch foo
1125 1137 (branches are permanent and global, did you want a bookmark?)
1126 1138 $ mv a a.bak
1127 1139 $ echo foobranch > a
1128 1140 $ cat a.bak >> a
1129 1141 $ rm a.bak
1130 1142 $ hg commit -m 9foobranch
1131 1143 $ hg update default
1132 1144 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1133 1145 $ hg -y transplant -b foo tip
1134 1146 applying 4aa30d025d50
1135 1147 4aa30d025d50 transplanted to e00abbf63521
1136 1148
1137 1149 Expansion in changeset but not in file
1138 1150
1139 1151 $ hg tip -p
1140 1152 changeset: 11:e00abbf63521
1141 1153 tag: tip
1142 1154 parent: 9:800511b3a22d
1143 1155 user: test
1144 1156 date: Thu Jan 01 00:00:00 1970 +0000
1145 1157 summary: 9foobranch
1146 1158
1147 1159 diff -r 800511b3a22d -r e00abbf63521 a
1148 1160 --- a/a Thu Jan 01 00:00:00 1970 +0000
1149 1161 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1150 1162 @@ -1,3 +1,4 @@
1151 1163 +foobranch
1152 1164 expand $Id$
1153 1165 do not process $Id:
1154 1166 xxx $
1155 1167
1156 1168 $ head -n 2 a
1157 1169 foobranch
1158 1170 expand $Id: a e00abbf63521 Thu, 01 Jan 1970 00:00:00 +0000 test $
1159 1171
1160 1172 Turn off expansion
1161 1173
1162 1174 $ hg -q rollback
1163 1175 $ hg -q update -C
1164 1176
1165 1177 kwshrink with unknown file u
1166 1178
1167 1179 $ cp a u
1168 1180 $ hg --verbose kwshrink
1169 1181 overwriting a shrinking keywords
1170 1182 overwriting m shrinking keywords
1171 1183 overwriting x/a shrinking keywords
1172 1184
1173 1185 Keywords shrunk in working directory, but not yet disabled
1174 1186 - cat shows unexpanded keywords
1175 1187 - hg cat shows expanded keywords
1176 1188
1177 1189 $ cat a b
1178 1190 expand $Id$
1179 1191 do not process $Id:
1180 1192 xxx $
1181 1193 $Xinfo$
1182 1194 ignore $Id$
1183 1195 $ hg cat sym a b && echo
1184 1196 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1185 1197 do not process $Id:
1186 1198 xxx $
1187 1199 $Xinfo: User Name <user@example.com>: firstline $
1188 1200 ignore $Id$
1189 1201 a
1190 1202
1191 1203 Now disable keyword expansion
1192 1204
1193 1205 $ cp $HGRCPATH $HGRCPATH.backup
1194 1206 $ rm "$HGRCPATH"
1195 1207 $ cat a b
1196 1208 expand $Id$
1197 1209 do not process $Id:
1198 1210 xxx $
1199 1211 $Xinfo$
1200 1212 ignore $Id$
1201 1213 $ hg cat sym a b && echo
1202 1214 expand $Id$
1203 1215 do not process $Id:
1204 1216 xxx $
1205 1217 $Xinfo$
1206 1218 ignore $Id$
1207 1219 a
1208 1220
1209 1221 enable keyword expansion again
1210 1222
1211 1223 $ cat $HGRCPATH.backup >> $HGRCPATH
1212 1224
1213 1225 Test restricted mode with unshelve
1214 1226
1215 1227 $ cat <<EOF >> $HGRCPATH
1216 1228 > [extensions]
1217 1229 > shelve =
1218 1230 > EOF
1219 1231
1220 1232 $ echo xxxx >> a
1221 1233 $ hg diff
1222 1234 diff -r 800511b3a22d a
1223 1235 --- a/a Thu Jan 01 00:00:00 1970 +0000
1224 1236 +++ b/a * (glob)
1225 1237 @@ -2,3 +2,4 @@
1226 1238 do not process $Id:
1227 1239 xxx $
1228 1240 $Xinfo$
1229 1241 +xxxx
1230 1242 $ hg shelve -q --name tmp
1231 1243 $ hg shelve --list --patch
1232 1244 tmp (*)* changes to: localresolve (glob)
1233 1245
1234 1246 diff --git a/a b/a
1235 1247 --- a/a
1236 1248 +++ b/a
1237 1249 @@ -2,3 +2,4 @@
1238 1250 do not process $Id:
1239 1251 xxx $
1240 1252 $Xinfo$
1241 1253 +xxxx
1242 1254
1243 1255 $ hg update -q -C 10
1244 1256 $ hg unshelve -q tmp
1245 1257 $ hg diff
1246 1258 diff -r 4aa30d025d50 a
1247 1259 --- a/a Thu Jan 01 00:00:00 1970 +0000
1248 1260 +++ b/a * (glob)
1249 1261 @@ -3,3 +3,4 @@
1250 1262 do not process $Id:
1251 1263 xxx $
1252 1264 $Xinfo$
1253 1265 +xxxx
1254 1266
1255 1267 Test restricted mode with rebase
1256 1268
1257 1269 $ cat <<EOF >> $HGRCPATH
1258 1270 > [extensions]
1259 1271 > rebase =
1260 1272 > EOF
1261 1273
1262 1274 $ hg update -q -C 9
1263 1275
1264 1276 $ echo xxxx >> a
1265 1277 $ hg commit -m '#11'
1266 1278 $ hg diff -c 11
1267 1279 diff -r 800511b3a22d -r b07670694489 a
1268 1280 --- a/a Thu Jan 01 00:00:00 1970 +0000
1269 1281 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1270 1282 @@ -2,3 +2,4 @@
1271 1283 do not process $Id:
1272 1284 xxx $
1273 1285 $Xinfo$
1274 1286 +xxxx
1275 1287
1276 1288 $ hg diff -c 10
1277 1289 diff -r 27d48ee14f67 -r 4aa30d025d50 a
1278 1290 --- a/a Thu Jan 01 00:00:00 1970 +0000
1279 1291 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1280 1292 @@ -1,3 +1,4 @@
1281 1293 +foobranch
1282 1294 expand $Id$
1283 1295 do not process $Id:
1284 1296 xxx $
1285 1297
1286 1298 $ hg rebase -q -s 10 -d 11 --keep
1287 1299 $ hg diff -r 9 -r 12 a
1288 1300 diff -r 800511b3a22d -r 1939b927726c a
1289 1301 --- a/a Thu Jan 01 00:00:00 1970 +0000
1290 1302 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1291 1303 @@ -1,4 +1,6 @@
1292 1304 +foobranch
1293 1305 expand $Id$
1294 1306 do not process $Id:
1295 1307 xxx $
1296 1308 $Xinfo$
1297 1309 +xxxx
1298 1310
1299 1311 Test restricted mode with graft
1300 1312
1301 1313 $ hg graft -q 10
1302 1314 $ hg diff -r 9 -r 13 a
1303 1315 diff -r 800511b3a22d -r 01a68de1003a a
1304 1316 --- a/a Thu Jan 01 00:00:00 1970 +0000
1305 1317 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1306 1318 @@ -1,4 +1,6 @@
1307 1319 +foobranch
1308 1320 expand $Id$
1309 1321 do not process $Id:
1310 1322 xxx $
1311 1323 $Xinfo$
1312 1324 +xxxx
1313 1325
1314 1326 Test restricted mode with backout
1315 1327
1316 1328 $ hg backout -q 11 --no-commit
1317 1329 $ hg diff a
1318 1330 diff -r 01a68de1003a a
1319 1331 --- a/a Thu Jan 01 00:00:00 1970 +0000
1320 1332 +++ b/a * (glob)
1321 1333 @@ -3,4 +3,3 @@
1322 1334 do not process $Id:
1323 1335 xxx $
1324 1336 $Xinfo$
1325 1337 -xxxx
1326 1338
1327 1339 Test restricted mode with histedit
1328 1340
1329 1341 $ cat <<EOF >> $HGRCPATH
1330 1342 > [extensions]
1331 1343 > histedit =
1332 1344 > EOF
1333 1345
1334 1346 $ hg commit -m 'backout #11'
1335 1347 $ hg histedit -q --command - 13 <<EOF
1336 1348 > pick 49f5f2d940c3 14 backout #11
1337 1349 > pick 01a68de1003a 13 9foobranch
1338 1350 > EOF
1339 1351
1340 1352 Test restricted mode with fetch (with merge)
1341 1353
1342 1354 $ cat <<EOF >> $HGRCPATH
1343 1355 > [extensions]
1344 1356 > fetch =
1345 1357 > EOF
1346 1358
1347 1359 $ hg clone -q -r 9 . ../fetch-merge
1348 1360 $ cd ../fetch-merge
1349 1361 $ hg -R ../Test export 10 | hg import -q -
1350 1362 $ hg fetch -q -r 11
1351 1363 $ hg diff -r 9 a
1352 1364 diff -r 800511b3a22d a
1353 1365 --- a/a Thu Jan 01 00:00:00 1970 +0000
1354 1366 +++ b/a * (glob)
1355 1367 @@ -1,4 +1,6 @@
1356 1368 +foobranch
1357 1369 expand $Id$
1358 1370 do not process $Id:
1359 1371 xxx $
1360 1372 $Xinfo$
1361 1373 +xxxx
1362 1374
1363 1375 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now