# HG changeset patch # User Christian Ebert # Date 1202315137 -3600 # Node ID 0683aaf458d82e69815c345c5684b81c46dc8edb # Parent ce5eb725d0c66b32b47383899ee08788c9a12511# Parent ed160b097badb0b97aa87cb7ad30ffd94f113499 Discard wread/wwrite approach, merge with stable A basic "hg update" did not give correct results. diff -r ce5eb725d0c6 -r 0683aaf458d8 hgkw/keyword.py --- a/hgkw/keyword.py Wed Feb 06 11:32:34 2008 +0100 +++ b/hgkw/keyword.py Wed Feb 06 17:25:37 2008 +0100 @@ -80,19 +80,29 @@ "Log = {desc}" expands to the first line of the changeset description. ''' -from mercurial import commands, cmdutil, context, localrepo -from mercurial import patch, revlog, templater, templatefilters, util +from mercurial import commands, cmdutil, context, dispatch, filelog, revlog +from mercurial import patch, localrepo, templater, templatefilters, util from mercurial.node import * -from mercurial.hgweb import webcommands from mercurial.i18n import _ -import mimetypes, re, shutil, tempfile, time +import re, shutil, sys, tempfile, time commands.optionalrepo += ' kwdemo' +# hg commands that do not act on keywords +nokwcommands = ('add addremove bundle copy export grep identify incoming init' + ' log outgoing push remove rename rollback tip convert') + +# hg commands that trigger expansion only when writing to working dir, +# not when reading filelog, and unexpand when reading from working dir +restricted = 'diff1 record qfold qimport qnew qpush qrefresh qrecord' + def utcdate(date): '''Returns hgdate in cvs-like UTC format.''' return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) + +_kwtemplater = None + class kwtemplater(object): ''' Sets up keyword templates, corresponding keyword regex, and @@ -108,11 +118,13 @@ 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}', } - def __init__(self, ui, repo, inc, exc): + def __init__(self, ui, repo, inc, exc, restricted): self.ui = ui self.repo = repo self.matcher = util.matcher(repo.root, inc=inc, exc=exc)[1] - self.ctx = None + self.restricted = restricted + self.commitnode = None + self.path = '' kwmaps = self.ui.configitems('keywordmaps') if kwmaps: # override default templates @@ -127,67 +139,102 @@ self.ct = cmdutil.changeset_templater(self.ui, self.repo, False, '', False) - def substitute(self, path, data, node, subfunc): - '''Obtains file's changenode if node not given, + def substitute(self, node, data, subfunc): + '''Obtains file's changenode if commit node not given, and calls given substitution function.''' - if node is None: - # kwrepo.wwrite except when overwriting on commit - try: - fnode = self.ctx.filenode(path) - fl = self.repo.file(path) - c = context.filectx(self.repo, path, fileid=fnode, filelog=fl) - node = c.node() - except revlog.LookupError: - # eg: convert - return subfunc == self.re_kw.sub and data or (data, None) + if self.commitnode: + fnode = self.commitnode + else: + c = context.filectx(self.repo, self.path, fileid=node) + fnode = c.node() def kwsub(mobj): '''Substitutes keyword using corresponding template.''' kw = mobj.group(1) self.ct.use_template(self.templates[kw]) self.ui.pushbuffer() - self.ct.show(changenode=node, root=self.repo.root, file=path) + self.ct.show(changenode=fnode, root=self.repo.root, file=self.path) ekw = templatefilters.firstline(self.ui.popbuffer()) return '$%s: %s $' % (kw, ekw) return subfunc(kwsub, data) - def expand(self, path, data, ctx): + def expand(self, node, data): '''Returns data with keywords expanded.''' - if util.binary(data): + if self.restricted or util.binary(data): return data - if self.ctx is None: - self.ctx = ctx or self.repo.changectx() - return self.substitute(path, data, None, self.re_kw.sub) + return self.substitute(node, data, self.re_kw.sub) - def process(self, path, data, expand, ctx, node): + def process(self, node, data, expand): '''Returns a tuple: data, count. Count is number of keywords/keyword substitutions, telling caller whether to act on file containing data.''' if util.binary(data): return data, None if expand: - self.ctx = ctx - return self.substitute(path, data, node, self.re_kw.subn) - return self.re_kw.subn(r'$\1$', data) + return self.substitute(node, data, self.re_kw.subn) + return data, self.re_kw.search(data) + + def shrink(self, text): + '''Returns text with all keyword substitutions removed.''' + if util.binary(text): + return text + return self.re_kw.sub(r'$\1$', text) + +class kwfilelog(filelog.filelog): + ''' + Subclass of filelog to hook into its read, add, cmp methods. + Keywords are "stored" unexpanded, and processed on reading. + ''' + def __init__(self, opener, path): + super(kwfilelog, self).__init__(opener, path) + _kwtemplater.path = path - def shrink(self, data): - '''Returns text with all keyword substitutions removed.''' - if util.binary(data): - return data - return self.re_kw.sub(r'$\1$', data) + def kwctread(self, node, expand): + '''Reads expanding and counting keywords, called from _overwrite.''' + data = super(kwfilelog, self).read(node) + return _kwtemplater.process(node, data, expand) + + def read(self, node): + '''Expands keywords when reading filelog.''' + data = super(kwfilelog, self).read(node) + return _kwtemplater.expand(node, data) + + def add(self, text, meta, tr, link, p1=None, p2=None): + '''Removes keyword substitutions when adding to filelog.''' + text = _kwtemplater.shrink(text) + return super(kwfilelog, self).add(text, meta, tr, link, p1=p1, p2=p2) + + def cmp(self, node, text): + '''Removes keyword substitutions for comparison.''' + text = _kwtemplater.shrink(text) + if self.renamed(node): + t2 = super(kwfilelog, self).read(node) + return t2 != text + return revlog.revlog.cmp(self, node, text) + # store original patch.patchfile.__init__ _patchfile_init = patch.patchfile.__init__ +def _kwpatchfile_init(self, ui, fname, missing=False): + '''Monkeypatch/wrap patch.patchfile.__init__ to avoid + rejects or conflicts due to expanded keywords in working dir.''' + _patchfile_init(self, ui, fname, missing=missing) -def _iskwfile(f, link, kwt): - return not link(f) and kwt.matcher(f) + if _kwtemplater.matcher(self.fname): + # shrink keywords read from working dir + kwshrunk = _kwtemplater.shrink(''.join(self.lines)) + self.lines = kwshrunk.splitlines(True) + + +def _iskwfile(f, link): + return not link(f) and _kwtemplater.matcher(f) def _status(ui, repo, *pats, **opts): '''Bails out if [keyword] configuration is not active. Returns status of working directory.''' - if hasattr(repo, '_kwt'): + if _kwtemplater: files, match, anypats = cmdutil.matchpats(repo, pats, opts) return repo.status(files=files, match=match, list_clean=True) if ui.configitems('keyword'): @@ -198,22 +245,22 @@ '''Overwrites selected files expanding/shrinking keywords.''' ctx = repo.changectx(node) mf = ctx.manifest() - if node is not None: - # commit + if node is not None: # commit + _kwtemplater.commitnode = node files = [f for f in ctx.files() if f in mf] notify = ui.debug - else: - # kwexpand/kwshrink + else: # kwexpand/kwshrink notify = ui.note - candidates = [f for f in files if _iskwfile(f, mf.linkf, repo._kwt)] + candidates = [f for f in files if _iskwfile(f, mf.linkf)] if candidates: candidates.sort() action = expand and 'expanding' or 'shrinking' for f in candidates: - data, kwfound = repo._wreadkwct(f, expand, ctx, node) + fp = repo.file(f, kwmatch=True) + data, kwfound = fp.kwctread(mf[f], expand) if kwfound: notify(_('overwriting %s %s keywords\n') % (f, action)) - repo.wwrite(f, data, mf.flags(f), overwrite=True) + repo.wwrite(f, data, mf.flags(f)) repo.dirstate.normal(f) def _kwfwrite(ui, repo, expand, *pats, **opts): @@ -230,35 +277,6 @@ finally: del wlock, lock -def cat(ui, repo, file1, *pats, **opts): - '''output the current or given revision of files expanding keywords - - Print the specified files as they were at the given revision. - If no revision is given, the parent of the working directory is used, - or tip if no revision is checked out. - - Output may be to a file, in which case the name of the file is - given using a format string. The formatting rules are the same as - for the export command, with the following additions: - - %s basename of file being printed - %d dirname of file being printed, or '.' if in repo root - %p root-relative path name of file being printed - ''' - ctx = repo.changectx(opts['rev']) - err = 1 - for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts, - ctx.node()): - fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs) - data = ctx.filectx(abs).data() - try: - if repo._kwt.matcher(abs): - data = repo._kwt.expand(abs, data, ctx) - except AttributeError: - pass - fp.write(data) - err = 0 - return err def demo(ui, repo, *args, **opts): '''print [keywordmaps] configuration and an expansion example @@ -336,7 +354,7 @@ repo.commit(text=msg) format = ui.verbose and ' in %s' % path or '' demostatus('%s keywords expanded%s' % (kwstatus, format)) - ui.write(repo.wopener(fn).read()) + ui.write(repo.wread(fn)) ui.debug(_('\nremoving temporary repo %s\n') % tmpdir) shutil.rmtree(tmpdir, ignore_errors=True) @@ -363,7 +381,7 @@ if opts.get('untracked'): files += unknown files.sort() - kwfiles = [f for f in files if _iskwfile(f, repo._link, repo._kwt)] + kwfiles = [f for f in files if _iskwfile(f, repo._link)] cwd = pats and repo.getcwd() or '' kwfstats = not opts.get('ignore') and (('K', kwfiles),) or () if opts.get('all') or opts.get('ignore'): @@ -386,10 +404,31 @@ def reposetup(ui, repo): - if not repo.local() or repo.root.endswith('/.hg/patches'): + '''Sets up repo as kwrepo for keyword substitution. + Overrides file method to return kwfilelog instead of filelog + if file matches user configuration. + Wraps commit to overwrite configured files with updated + keyword substitutions. + This is done for local repos only, and only if there are + files configured at all for keyword substitution.''' + + if not repo.local(): return - inc, exc = [], ['.hgtags', '.hg_archival.txt'] + hgcmd, func, args, opts, cmdopts = dispatch._parse(ui, sys.argv[1:]) + if hgcmd in nokwcommands.split(): + return + + if hgcmd == 'diff': + # only expand if comparing against working dir + node1, node2 = cmdutil.revpair(repo, cmdopts.get('rev')) + if node2 is not None: + return + # shrink if rev is not current node + if node1 is not None and node1 != repo.changectx().node(): + hgcmd = 'diff1' + + inc, exc = [], ['.hgtags'] for pat, opt in ui.configitems('keyword'): if opt != 'ignore': inc.append(pat) @@ -398,29 +437,24 @@ if not inc: return + global _kwtemplater + _restricted = hgcmd in restricted.split() + _kwtemplater = kwtemplater(ui, repo, inc, exc, _restricted) + class kwrepo(repo.__class__): - def _wreadkwct(self, filename, expand, ctx, node): - '''Reads filename and returns tuple of data with keywords - expanded/shrunk and count of keywords (for _overwrite).''' - data = super(kwrepo, self).wread(filename) - return self._kwt.process(filename, data, expand, ctx, node) + def file(self, f, kwmatch=False): + if f[0] == '/': + f = f[1:] + if kwmatch or _kwtemplater.matcher(f): + return kwfilelog(self.sopener, f) + return filelog.filelog(self.sopener, f) def wread(self, filename): data = super(kwrepo, self).wread(filename) - if self._kwt.matcher(filename): - return self._kwt.shrink(data) + if _restricted and _kwtemplater.matcher(filename): + return _kwtemplater.shrink(data) return data - def wwrite(self, filename, data, flags, overwrite=False): - if not overwrite and self._kwt.matcher(filename): - data = self._kwt.expand(filename, data, None) - super(kwrepo, self).wwrite(filename, data, flags) - - def wwritedata(self, filename, data): - if self._kwt.matcher(filename): - data = self._kwt.expand(filename, data, None) - return super(kwrepo, self).wwritedata(filename, data) - def commit(self, files=None, text='', user=None, date=None, match=util.always, force=False, force_editor=False, p1=None, p2=None, extra={}, empty_ok=False): @@ -464,50 +498,11 @@ finally: del wlock, lock - kwt = kwrepo._kwt = kwtemplater(ui, repo, inc, exc) - - def kwpatchfile_init(self, ui, fname, missing=False): - '''Monkeypatch/wrap patch.patchfile.__init__ to avoid - rejects or conflicts due to expanded keywords in working dir.''' - _patchfile_init(self, ui, fname, missing=missing) - - if kwt.matcher(self.fname): - # shrink keywords read from working dir - kwshrunk = kwt.shrink(''.join(self.lines)) - self.lines = kwshrunk.splitlines(True) - - def kwweb_rawfile(web, req, tmpl): - '''Monkeypatch webcommands.rawfile so it expands keywords.''' - path = web.cleanpath(req.form.get('file', [''])[0]) - if not path: - content = web.manifest(tmpl, web.changectx(req), path) - req.respond(webcommands.HTTP_OK, web.ctype) - return content - try: - fctx = web.filectx(req) - except revlog.LookupError: - content = web.manifest(tmpl, web.changectx(req), path) - req.respond(webcommands.HTTP_OK, web.ctype) - return content - path = fctx.path() - text = fctx.data() - if kwt.matcher(path): - text = kwt.expand(path, text, web.changectx(req)) - mt = mimetypes.guess_type(path)[0] - if mt is None or util.binary(text): - mt = mt or 'application/octet-stream' - req.respond(webcommands.HTTP_OK, mt, path, len(text)) - return [text] - repo.__class__ = kwrepo - patch.patchfile.__init__ = kwpatchfile_init - webcommands.rawfile = kwweb_rawfile + patch.patchfile.__init__ = _kwpatchfile_init cmdtable = { - 'kwcat': - (cat, commands.table['cat'][1], - _('hg kwcat [OPTION]... FILE...')), 'kwdemo': (demo, [('d', 'default', None, _('show default keyword template maps')), diff -r ce5eb725d0c6 -r 0683aaf458d8 tests/test-keyword --- a/tests/test-keyword Wed Feb 06 11:32:34 2008 +0100 +++ b/tests/test-keyword Wed Feb 06 17:25:37 2008 +0100 @@ -24,29 +24,17 @@ hg --quiet kwdemo "Branch = {branches}" -hg init t -cd t -echo % kwshrink should exit silently in empty/invalid repo -hg kwshrink - -echo % symlink nonexisting file -ln -s a sym -echo % commit hook must fail with missing file -hg --debug commit -A -msym -d '0 0' -u 'User Name ' -echo % bundle null revision containing empty symlink -hg bundle --base null ../test-keyword.hg -cd .. - hg init Test cd Test -echo % pull from bundle -hg pull --traceback -u ../test-keyword.hg +echo % kwshrink should exit silently in empty/invalid repo +hg kwshrink echo 'expand $Id$' > a echo 'do not process $Id:' >> a echo 'xxx $' >> a echo 'ignore $Id$' > b +ln -s a sym echo % cat cat sym a b @@ -62,15 +50,15 @@ hg status echo % commit -hg --debug commit -mabsym -d '1 0' -u 'User Name ' +hg --debug commit -mabsym -d '0 0' -u 'User Name ' echo % status hg status echo % identify hg --quiet identify echo % cat cat sym a b -echo % hg kwcat -hg kwcat sym a b +echo % hg cat +hg cat sym a b echo echo % diff a hooktest @@ -96,18 +84,14 @@ echo '$Id$' > c echo 'tests for different changenodes' >> c echo % commit c -hg commit -A -mcndiff -d '2 0' -u 'User Name ' +hg commit -A -mcndiff -d '1 0' -u 'User Name ' echo % force expansion hg -v kwexpand echo % compare changenodes in a c cat a c -echo % qinit -c -hg qinit -c echo % qimport hg qimport -r tip -n mqtest.diff -echo % qcommit -hg qcommit -mqtest echo % keywords should not be expanded in patch cat .hg/patches/mqtest.diff echo % qpop @@ -126,7 +110,7 @@ hg kwfiles echo % commit -hg --debug commit -ma2c -d '2 0' -u 'User Name ' +hg --debug commit -ma2c -d '1 0' -u 'User Name ' echo % cat a c cat a c echo % touch copied c after 1 second @@ -139,7 +123,7 @@ hg kwfiles echo % diff --rev -hg diff --rev 1 | grep -v 'b/c' +hg diff --rev 0 | grep -v 'b/c' echo % rollback hg rollback @@ -160,8 +144,8 @@ echo % cat cat sym a b -echo % hg kwcat -hg kwcat sym a b +echo % hg cat +hg cat sym a b echo echo '$Xinfo$' >> a @@ -176,15 +160,15 @@ hg status echo % commit -hg --debug commit -l log -d '3 0' -u 'User Name ' +hg --debug commit -l log -d '2 0' -u 'User Name ' rm log echo % status hg status echo % cat cat sym a b -echo % hg kwcat -hg kwcat sym a b +echo % hg cat +hg cat sym a b echo echo % remove @@ -203,7 +187,7 @@ echo % clone to test incoming cd .. -hg clone -r1 Test Test-a +hg clone -r0 Test Test-a cd Test-a cat <> .hg/hgrc [paths] @@ -216,7 +200,7 @@ sed -e 's/Id.*/& rejecttest/' a > a.new mv a.new a echo % commit rejecttest -hg --debug commit -m'rejects?' -d '4 0' -u 'User Name ' +hg --debug commit -m'rejects?' -d '3 0' -u 'User Name ' echo % export hg export -o ../rejecttest.diff tip @@ -240,7 +224,7 @@ echo % kwexpand x/a should abort hg --verbose kwexpand x/a cd x -hg --debug commit -m xa -d '4 0' -u 'User Name ' +hg --debug commit -m xa -d '3 0' -u 'User Name ' echo % cat a cat a echo % kwshrink a inside directory x @@ -252,11 +236,18 @@ echo % kwexpand nonexistent hg kwexpand nonexistent +echo % switch off expansion echo % kwshrink with unknown file u cp a u hg --verbose kwshrink echo % cat cat sym a b -echo % hg kwcat -hg kwcat sym a b +echo % hg cat +hg cat sym a b echo +rm $HGRCPATH +echo % cat +cat sym a b +echo % hg cat +hg cat sym a b +echo diff -r ce5eb725d0c6 -r 0683aaf458d8 tests/test-keyword.out --- a/tests/test-keyword.out Wed Feb 06 11:32:34 2008 +0100 +++ b/tests/test-keyword.out Wed Feb 06 17:25:37 2008 +0100 @@ -46,7 +46,6 @@ list of commands: - kwcat output the current or given revision of files expanding keywords kwdemo print [keywordmaps] configuration and an expansion example kwexpand expand keywords in working directory kwfiles print files currently configured for keyword expansion @@ -85,23 +84,6 @@ Branch = {branches} $Branch: demobranch $ % kwshrink should exit silently in empty/invalid repo -% symlink nonexisting file -% commit hook must fail with missing file -cp: a: No such file or directory -adding sym -sym -running hook commit.test: cp a hooktest -warning: commit.test hook exited with status 1 -% bundle null revision containing empty symlink -1 changesets found -% pull from bundle -pulling from ../test-keyword.hg -requesting all changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files -1 files updated, 0 files merged, 0 files removed, 0 files unresolved % cat expand $Id$ do not process $Id: @@ -113,38 +95,43 @@ % addremove adding a adding b +adding sym % status A a A b +A sym % default keyword expansion including commit hook % interrupted commit should not change state or run commit hook a b +sym transaction abort! rollback completed abort: empty commit message % status A a A b +A sym % commit a b +sym overwriting a expanding keywords running hook commit.test: cp a hooktest % status ? hooktest % identify -cecf1e2cc3d3 +f782df5f9602 % cat -expand $Id: a,v cecf1e2cc3d3 1970/01/01 00:00:01 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ -expand $Id: a,v cecf1e2cc3d3 1970/01/01 00:00:01 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ ignore $Id$ -% hg kwcat -expand $Id: a,v cecf1e2cc3d3 1970/01/01 00:00:01 user $ +% hg cat +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ ignore $Id$ @@ -156,10 +143,10 @@ % update 3 files updated, 0 files merged, 0 files removed, 0 files unresolved % cat -expand $Id: a,v cecf1e2cc3d3 1970/01/01 00:00:01 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ -expand $Id: a,v cecf1e2cc3d3 1970/01/01 00:00:01 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ ignore $Id$ @@ -170,25 +157,23 @@ overwriting a expanding keywords overwriting c expanding keywords % compare changenodes in a c -expand $Id: a,v cecf1e2cc3d3 1970/01/01 00:00:01 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ -$Id: c,v c033759cd8fd 1970/01/01 00:00:02 user $ +$Id: c,v ba4426d1938e 1970/01/01 00:00:01 user $ tests for different changenodes -% qinit -c % qimport -% qcommit % keywords should not be expanded in patch # HG changeset patch # User User Name -# Date 2 0 -# Node ID c033759cd8fd162b7863dc4e5d1eea433603880f -# Parent cecf1e2cc3d3447fcc20dd4eac5c4faa8a615df3 +# Date 1 0 +# Node ID ba4426d1938ec9673e03ab274d88c44e24618f7f +# Parent f782df5f9602483b4e51c31a12315f353bba380c cndiff -diff -r cecf1e2cc3d3 -r c033759cd8fd c +diff -r f782df5f9602 -r ba4426d1938e c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/c Thu Jan 01 00:00:02 1970 +0000 ++++ b/c Thu Jan 01 00:00:01 1970 +0000 @@ -0,0 +1,2 @@ +$Id$ +tests for different changenodes @@ -198,7 +183,7 @@ applying mqtest.diff Now at: mqtest.diff % cat -$Id: c,v c033759cd8fd 1970/01/01 00:00:02 user $ +$Id: c,v ba4426d1938e 1970/01/01 00:00:01 user $ tests for different changenodes % qpop and move on Patch queue now empty @@ -211,10 +196,10 @@ c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292 overwriting c expanding keywords % cat a c -expand $Id: a,v cecf1e2cc3d3 1970/01/01 00:00:01 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ -expand $Id: c,v 1fed52d26fd0 1970/01/01 00:00:02 user $ +expand $Id: c,v 0ba462c0f077 1970/01/01 00:00:01 user $ do not process $Id: xxx $ % touch copied c after 1 second @@ -223,7 +208,7 @@ a c % diff --rev -diff -r cecf1e2cc3d3 c +diff -r f782df5f9602 c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -0,0 +1,3 @@ +expand $Id$ @@ -247,15 +232,15 @@ Xinfo = {author}: {desc} $Xinfo: test: hg keyword config and expansion example $ % cat -expand $Id: a,v cecf1e2cc3d3 1970/01/01 00:00:01 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ -expand $Id: a,v cecf1e2cc3d3 1970/01/01 00:00:01 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ ignore $Id$ -% hg kwcat -expand $Id: a cecf1e2cc3d3 Thu, 01 Jan 1970 00:00:01 +0000 user $ +% hg cat +expand $Id: a f782df5f9602 Thu, 01 Jan 1970 00:00:00 +0000 user $ do not process $Id: xxx $ ignore $Id$ @@ -272,17 +257,17 @@ overwriting a expanding keywords % status % cat -expand $Id: a a576e5647736 Thu, 01 Jan 1970 00:00:03 +0000 user $ +expand $Id: a 0729690beff6 Thu, 01 Jan 1970 00:00:02 +0000 user $ do not process $Id: xxx $ $Xinfo: User Name : firstline $ -expand $Id: a a576e5647736 Thu, 01 Jan 1970 00:00:03 +0000 user $ +expand $Id: a 0729690beff6 Thu, 01 Jan 1970 00:00:02 +0000 user $ do not process $Id: xxx $ $Xinfo: User Name : firstline $ ignore $Id$ -% hg kwcat -expand $Id: a a576e5647736 Thu, 01 Jan 1970 00:00:03 +0000 user $ +% hg cat +expand $Id: a 0729690beff6 Thu, 01 Jan 1970 00:00:02 +0000 user $ do not process $Id: xxx $ $Xinfo: User Name : firstline $ @@ -296,7 +281,7 @@ R a % revert a % cat a -expand $Id: a a576e5647736 Thu, 01 Jan 1970 00:00:03 +0000 user $ +expand $Id: a 0729690beff6 Thu, 01 Jan 1970 00:00:02 +0000 user $ do not process $Id: xxx $ $Xinfo: User Name : firstline $ @@ -305,15 +290,15 @@ adding changesets adding manifests adding file changes -added 2 changesets with 3 changes to 3 files +added 1 changesets with 3 changes to 3 files 3 files updated, 0 files merged, 0 files removed, 0 files unresolved % incoming comparing with test-keyword/Test searching for changes -changeset: 2:a576e5647736 +changeset: 1:0729690beff6 tag: tip user: User Name -date: Thu Jan 01 00:00:03 1970 +0000 +date: Thu Jan 01 00:00:02 1970 +0000 summary: firstline % commit rejecttest @@ -323,11 +308,11 @@ % import applying ../rejecttest.diff % cat -expand $Id: a 97b8d4afd122 Thu, 01 Jan 1970 00:00:04 +0000 user $ rejecttest +expand $Id: a 82983f13f138 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest do not process $Id: rejecttest xxx $ $Xinfo: User Name : rejects? $ -expand $Id: a 97b8d4afd122 Thu, 01 Jan 1970 00:00:04 +0000 user $ rejecttest +expand $Id: a 82983f13f138 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest do not process $Id: rejecttest xxx $ $Xinfo: User Name : rejects? $ @@ -347,7 +332,7 @@ x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e overwriting x/a expanding keywords % cat a -expand $Id: x/a 6ae8e7fbf16c Thu, 01 Jan 1970 00:00:04 +0000 user $ +expand $Id: x/a f27c134d2d9b Thu, 01 Jan 1970 00:00:03 +0000 user $ do not process $Id: xxx $ $Xinfo: User Name : xa $ @@ -360,6 +345,7 @@ $Xinfo$ % kwexpand nonexistent nonexistent: No such file or directory +% switch off expansion % kwshrink with unknown file u overwriting a shrinking keywords overwriting x/a shrinking keywords @@ -373,10 +359,27 @@ xxx $ $Xinfo$ ignore $Id$ -% hg kwcat -expand $Id: a a576e5647736 Thu, 01 Jan 1970 00:00:03 +0000 user $ +% hg cat +expand $Id: a 0729690beff6 Thu, 01 Jan 1970 00:00:02 +0000 user $ do not process $Id: xxx $ $Xinfo: User Name : firstline $ ignore $Id$ a +% cat +expand $Id$ +do not process $Id: +xxx $ +$Xinfo$ +expand $Id$ +do not process $Id: +xxx $ +$Xinfo$ +ignore $Id$ +% hg cat +expand $Id$ +do not process $Id: +xxx $ +$Xinfo$ +ignore $Id$ +a