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