# HG changeset patch # User Christian Ebert # Date 1194439258 -3600 # Node ID b05795ad5632518a54c82dd5483541c8d875b307 # Parent 80a300088654440a5dbc04d78590696fe8420121 Make keyword against current Mercurial available as standalone extension diff -r 80a300088654 -r b05795ad5632 hgkw/keyword.py --- a/hgkw/keyword.py Tue Nov 06 13:20:39 2007 +0100 +++ b/hgkw/keyword.py Wed Nov 07 13:40:58 2007 +0100 @@ -80,65 +80,10 @@ Or, better, use bundle/unbundle to share changes. ''' -from mercurial import commands, cmdutil, context, fancyopts +from mercurial import commands, cmdutil, context, dispatch from mercurial import filelog, localrepo, revlog, templater, util -from mercurial.i18n import gettext as _ -import getopt, os.path, re, shutil, sys, tempfile, time - -# backwards compatibility hacks - -try: - # cmdutil.parse moves to dispatch._parse in 18a9fbb5cd78 - # also avoid name conflict with other dispatch package(s) - from mercurial.dispatch import _parse -except ImportError: - try: - # commands.parse moves to cmdutil.parse in 0c61124ad877 - _parse = cmdutil.parse - except AttributeError: - _parse = commands.parse - -def _pathto(repo, f, cwd=None): - '''kwfiles behaves similar to status, using pathto since 78b6add1f966.''' - try: - return repo.pathto(f, cwd) - except AttributeError: - return f - -# commands.parse/cmdutil.parse returned nothing for -# "hg diff --rev" before 88803a69b24a due to bug in fancyopts -def _fancyopts(args, options, state): - '''Fixed fancyopts from 88803a69b24a.''' - long = [] - short = '' - map = {} - dt = {} - for s, l, d, c in options: - pl = l.replace('-', '_') - map['-'+s] = map['--'+l] = pl - if isinstance(d, list): - state[pl] = d[:] - else: - state[pl] = d - dt[pl] = type(d) - if (d is not None and d is not True and d is not False and - not callable(d)): - if s: s += ':' - if l: l += '=' - if s: short = short + s - if l: long.append(l) - opts, args = getopt.getopt(args, short, long) - for opt, arg in opts: - if dt[map[opt]] is type(fancyopts): state[map[opt]](state, map[opt], arg) - elif dt[map[opt]] is type(1): state[map[opt]] = int(arg) - elif dt[map[opt]] is type(''): state[map[opt]] = arg - elif dt[map[opt]] is type([]): state[map[opt]].append(arg) - elif dt[map[opt]] is type(None): state[map[opt]] = True - elif dt[map[opt]] is type(False): state[map[opt]] = True - return args - -fancyopts.fancyopts = _fancyopts - +from mercurial.i18n import _ +import re, shutil, sys, tempfile, time commands.optionalrepo += ' kwdemo' @@ -179,35 +124,8 @@ self.re_kw = re.compile(kwpat) if self.t: templater.common_filters['utcdate'] = utcdate - self.t = self._changeset_templater() - - def _changeset_templater(self): - '''Backwards compatible cmdutil.changeset_templater.''' - # before 1e0b94cfba0e there was an extra "brinfo" argument - try: - return cmdutil.changeset_templater(self.ui, self.repo, - False, '', False) - except TypeError: - return cmdutil.changeset_templater(self.ui, self.repo, - False, None, '', False) - - def _wwrite(self, f, data, man): - '''Makes repo.wwrite backwards compatible.''' - # 656e06eebda7 removed file descriptor argument - # 67982d3ee76c added flags argument - try: - self.repo.wwrite(f, data, man.flags(f)) - except (AttributeError, TypeError): - self.repo.wwrite(f, data) - - def _normal(self, files): - '''Backwards compatible repo.dirstate.normal/update.''' - # 6fd953d5faea introduced dirstate.normal() - try: - for f in files: - self.repo.dirstate.normal(f) - except AttributeError: - self.repo.dirstate.update(files, 'n') + self.t = cmdutil.changeset_templater(self.ui, self.repo, + False, '', False) def kwsub(self, mobj): '''Substitutes keyword using corresponding template.''' @@ -238,7 +156,8 @@ def process(self, node, data): '''Returns a tuple: data, count. - Count is number of keywords/keyword substitutions. + Count is number of keywords/keyword substitutions, indicates + to caller whether to act on file containing data. Keywords in data are expanded, if templater was initialized.''' if util.binary(data): return data, None @@ -259,15 +178,13 @@ expand = self.t is not None action = ('shrinking', 'expanding')[expand] notify = (self.ui.note, self.ui.debug)[commit] - overwritten = [] for f in candidates: fp = self.repo.file(f, kwexp=expand, kwmatch=True) data, kwfound = fp.kwctread(man[f]) if kwfound: notify(_('overwriting %s %s keywords\n') % (f, action)) - self._wwrite(f, data, man) - overwritten.append(f) - self._normal(overwritten) + self.repo.wwrite(f, data, man.flags(f)) + self.repo.dirstate.normal(f) class kwfilelog(filelog.filelog): ''' @@ -303,6 +220,8 @@ return revlog.revlog.cmp(self, node, text) def _status(ui, repo, *pats, **opts): + '''Bails out if [keyword] configuration is not active. + Returns status of working directory.''' if hasattr(ui, 'kwfmatcher'): files, match, anypats = cmdutil.matchpats(repo, pats, opts) return repo.status(files=files, match=match, list_clean=True) @@ -440,9 +359,7 @@ else: files = modified + added + clean files.sort() - # use the full definition of repo._link for backwards compatibility - kwfiles = [f for f in files if ui.kwfmatcher(f) - and not os.path.islink(repo.wjoin(f))] + kwfiles = [f for f in files if ui.kwfmatcher(f) and not repo._link(f)] cwd = pats and repo.getcwd() or '' allf = opts['all'] ignore = opts['ignore'] @@ -450,11 +367,11 @@ if not ignore: format = ('%s\n', 'K %s\n')[flag] for k in kwfiles: - ui.write(format % _pathto(repo, k, cwd)) + ui.write(format % repo.pathto(k, cwd)) if allf or ignore: format = ('%s\n', 'I %s\n')[flag] for i in [f for f in files if f not in kwfiles]: - ui.write(format % _pathto(repo, i, cwd)) + ui.write(format % repo.pathto(i, cwd)) def shrink(ui, repo, *pats, **opts): '''revert expanded keywords in working directory @@ -481,7 +398,8 @@ 'grep', 'identify', 'incoming', 'init', 'outgoing', 'push', 'remove', 'rename', 'rollback', 'convert'] - if not repo.local() or _parse(ui, sys.argv[1:])[0] in nokwcommands: + if (not repo.local() or + dispatch._parse(ui, sys.argv[1:])[0] in nokwcommands): return inc, exc = [], ['.hgtags'] @@ -504,39 +422,18 @@ return kwfilelog(self.sopener, f, kwt) return filelog.filelog(self.sopener, f) - def _commit(self, files, text, user, date, match, force, lock, wlock, - force_editor, p1, p2, extra): - '''Private commit wrapper for backwards compatibility.''' + def commit(self, files=None, text='', user=None, date=None, + match=util.always, force=False, force_editor=False, + p1=None, p2=None, extra={}): + wlock = lock = None try: - return super(kwrepo, self).commit(files=files, text=text, - user=user, date=date, - match=match, force=force, - lock=lock, wlock=wlock, - force_editor=force_editor, - p1=p1, p2=p2, extra=extra) - except TypeError: - return super(kwrepo, self).commit(files=files, text=text, - user=user, date=date, - match=match, force=force, - force_editor=force_editor, - p1=p1, p2=p2, extra=extra) - - def commit(self, files=None, text='', user=None, date=None, - match=util.always, force=False, lock=None, wlock=None, - force_editor=False, p1=None, p2=None, extra={}): - # (w)lock arguments removed in 126f527b3ba3 - # so they are None or what was passed to commit - # use private _(w)lock for deletion - _lock = lock - _wlock = wlock - del wlock, lock - try: - if not _wlock: - _wlock = self.wlock() - if not _lock: - _lock = self.lock() - node = self._commit(files, text, user, date, match, force, - _lock, _wlock, force_editor, p1, p2, extra) + wlock = self.wlock() + lock = self.lock() + node = super(kwrepo, + self).commit(files=files, text=text, user=user, + date=date, match=match, force=force, + force_editor=force_editor, + p1=p1, p2=p2, extra=extra) if node is not None: cl = self.changelog.read(node) mn = self.manifest.read(cl[0]) @@ -547,7 +444,7 @@ _overwrite(ui, self, candidates, node, mn, True, True) return node finally: - del _wlock, _lock + del wlock, lock repo.__class__ = kwrepo diff -r 80a300088654 -r b05795ad5632 tests/test-keyword --- a/tests/test-keyword Tue Nov 06 13:20:39 2007 +0100 +++ b/tests/test-keyword Wed Nov 07 13:40:58 2007 +0100 @@ -9,9 +9,7 @@ EOF echo % help -# grep for backwards compatibility -hg help keyword \ -| grep -E -v '^list of commands|hg -v help keyword|^$' +hg help keyword echo % hg kwdemo hg --quiet kwdemo --default \ @@ -35,31 +33,33 @@ echo 'do not process $Id:' >> a echo 'xxx $' >> a echo 'ignore $Id$' > b +ln -s a sym echo % cat -cat a b +cat sym a b echo % default keyword expansion echo % commit -hg --debug commit -A -mab -d '0 0' -u 'User Name ' +hg --debug commit -A -mabsym -d '0 0' -u 'User Name ' echo % status hg status echo % identify hg --quiet identify echo % cat -cat a b +cat sym a b echo % hg cat -hg cat a b +hg cat sym a b +echo echo % touch touch a b echo % status hg status -rm a b +rm sym a b echo % update hg update echo % cat -cat a b +cat sym a b echo % copy hg cp a c @@ -101,10 +101,11 @@ EOF echo % cat -cat a b +cat sym a b echo % hg cat -hg cat a b +hg cat sym a b +echo echo '$Xinfo$' >> a cat <> log firstline @@ -112,8 +113,7 @@ EOF echo % interrupted commit -# redirection and grep for backwards compatibility -HGEDITOR=false hg commit 2>&1 | grep -v 'edit failed:' +HGEDITOR=false hg commit echo % status hg status @@ -124,9 +124,10 @@ hg status echo % cat -cat a b +cat sym a b echo % hg cat -hg cat a b +hg cat sym a b +echo echo % remove hg remove a @@ -151,8 +152,8 @@ default = ../Test EOF echo % incoming -# remove path to temp dir for backwards compatibility -hg incoming | grep -v '^comparing with' +# remove path to temp dir +hg incoming | sed -e 's/^\(comparing with \).*\(test-keyword.*\)/\1\2/' cd ../Test echo % kwexpand/kwshrink on selected files @@ -181,12 +182,13 @@ cp a u hg --verbose kwshrink echo % cat -cat a b +cat sym a b echo % hg cat -hg cat a b - +hg cat sym a b +echo rm $HGRCPATH echo % cat -cat a b +cat sym a b echo % hg cat -hg cat a b +hg cat sym a b +echo diff -r 80a300088654 -r b05795ad5632 tests/test-keyword.out --- a/tests/test-keyword.out Tue Nov 06 13:20:39 2007 +0100 +++ b/tests/test-keyword.out Wed Nov 07 13:40:58 2007 +0100 @@ -1,39 +1,57 @@ % help keyword extension - keyword expansion in local repositories + This extension expands RCS/CVS-like or self-customized $Keywords$ in tracked text files selected by your configuration. + Keywords are only expanded in local repositories and not stored in the change history. The mechanism can be regarded as a convenience for the current user or for archive distribution. + Configuration is done in the [keyword] and [keywordmaps] sections of hgrc files. + Example: + [keyword] # expand keywords in every python file except those matching "x*" **.py = x* = ignore + Note: the more specific you are in your filename patterns the less you lose speed in huge repos. + For [keywordmaps] template mapping and expansion demonstration and control run "hg kwdemo". + An additional date template filter {date|utcdate} is provided. + The default template mappings (view with "hg kwdemo -d") can be replaced with customized keywords and templates. Again, run "hg kwdemo" to control the results of your config changes. + Before changing/disabling active keywords, run "hg kwshrink" to avoid the risk of inadvertedly storing expanded keywords in the change history. + To force expansion after enabling it, or a configuration change, run "hg kwexpand". + Expansions spanning more than one line and incremental expansions, like CVS' $Log$, are not supported. A keyword template map "Log = {desc}" expands to the first line of the changeset description. + Caveat: "hg import" fails if the patch context contains an active keyword. In that case run "hg kwshrink", and then reimport. Or, better, use bundle/unbundle to share changes. + +list of commands: + kwdemo print [keywordmaps] configuration and an expansion example kwexpand expand keywords in working directory kwfiles print files currently configured for keyword expansion kwshrink revert expanded keywords in working directory + +use "hg -v help keyword" to show aliases and global options % hg kwdemo [extensions] hgext.keyword = @@ -74,33 +92,45 @@ expand $Id$ do not process $Id: xxx $ +expand $Id$ +do not process $Id: +xxx $ ignore $Id$ % default keyword expansion % commit adding a adding b +adding sym a b +sym overwriting a expanding keywords % status % identify -7f0665a496fd +f782df5f9602 % cat -expand $Id: a,v 7f0665a496fd 1970/01/01 00:00:00 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ +do not process $Id: +xxx $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ ignore $Id$ % hg cat -expand $Id: a,v 7f0665a496fd 1970/01/01 00:00:00 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ ignore $Id$ +a % touch % status % update -2 files updated, 0 files merged, 0 files removed, 0 files unresolved +3 files updated, 0 files merged, 0 files removed, 0 files unresolved % cat -expand $Id: a,v 7f0665a496fd 1970/01/01 00:00:00 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ +do not process $Id: +xxx $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ ignore $Id$ @@ -113,10 +143,10 @@ c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292 overwriting c expanding keywords % cat a c -expand $Id: a,v 7f0665a496fd 1970/01/01 00:00:00 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ -expand $Id: c,v 6a127771f5db 1970/01/01 00:00:01 user $ +expand $Id: c,v 0ba462c0f077 1970/01/01 00:00:01 user $ do not process $Id: xxx $ % touch copied c after 1 second @@ -125,10 +155,10 @@ a c % diff --rev -diff -r 7f0665a496fd c +diff -r f782df5f9602 c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -0,0 +1,3 @@ -+expand $Id: c,v 6a127771f5db 1970/01/01 00:00:01 user $ ++expand $Id: c,v 0ba462c0f077 1970/01/01 00:00:01 user $ +do not process $Id: +xxx $ % rollback @@ -149,18 +179,23 @@ Xinfo = {author}: {desc} $Xinfo: test: hg keyword config and expansion example $ % cat -expand $Id: a,v 7f0665a496fd 1970/01/01 00:00:00 user $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ +do not process $Id: +xxx $ +expand $Id: a,v f782df5f9602 1970/01/01 00:00:00 user $ do not process $Id: xxx $ ignore $Id$ % hg cat -expand $Id: a 7f0665a496fd Thu, 01 Jan 1970 00:00:00 +0000 user $ +expand $Id: a f782df5f9602 Thu, 01 Jan 1970 00:00:00 +0000 user $ do not process $Id: xxx $ ignore $Id$ +a % interrupted commit transaction abort! rollback completed +abort: edit failed: false exited with status 1 % status M a ? log @@ -169,17 +204,22 @@ overwriting a expanding keywords % status % cat -expand $Id: a 576a35651b0a Thu, 01 Jan 1970 00:00:02 +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 0729690beff6 Thu, 01 Jan 1970 00:00:02 +0000 user $ do not process $Id: xxx $ $Xinfo: User Name : firstline $ ignore $Id$ % hg cat -expand $Id: a 576a35651b0a Thu, 01 Jan 1970 00:00:02 +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$ +a % remove % status % rollback @@ -188,7 +228,7 @@ R a % revert a % cat a -expand $Id: a 576a35651b0a Thu, 01 Jan 1970 00:00:02 +0000 user $ +expand $Id: a 0729690beff6 Thu, 01 Jan 1970 00:00:02 +0000 user $ do not process $Id: xxx $ $Xinfo: User Name : firstline $ @@ -197,11 +237,12 @@ adding changesets adding manifests adding file changes -added 1 changesets with 2 changes to 2 files -2 files updated, 0 files merged, 0 files removed, 0 files unresolved +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-a/../Test searching for changes -changeset: 1:576a35651b0a +changeset: 1:0729690beff6 tag: tip user: User Name date: Thu Jan 01 00:00:02 1970 +0000 @@ -217,7 +258,7 @@ x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e overwriting x/a expanding keywords % cat a -expand $Id: x/a 2d19a72f00da Thu, 01 Jan 1970 00:00:03 +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 $ @@ -239,18 +280,27 @@ do not process $Id: xxx $ $Xinfo$ +expand $Id$ +do not process $Id: +xxx $ +$Xinfo$ ignore $Id$ % hg cat -expand $Id: a 576a35651b0a Thu, 01 Jan 1970 00:00:02 +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$ +a % cat expand $Id$ do not process $Id: xxx $ $Xinfo$ +expand $Id$ +do not process $Id: +xxx $ +$Xinfo$ ignore $Id$ % hg cat expand $Id$ @@ -258,3 +308,4 @@ xxx $ $Xinfo$ ignore $Id$ +a