hgkw/keyword.py
branchstable
changeset 1083 64fc3d450713
parent 1082 2ba350253f76
child 1114 22b300b7a7c1
equal deleted inserted replaced
1077:2a1ab2f6559c 1083:64fc3d450713
     1 # keyword.py - $Keyword$ expansion for Mercurial
     1 # keyword.py - $Keyword$ expansion for Mercurial
     2 #
     2 #
     3 # Copyright 2007-2010 Christian Ebert <blacktrash@gmx.net>
     3 # Copyright 2007-2012 Christian Ebert <blacktrash@gmx.net>
     4 #
     4 #
     5 # This software may be used and distributed according to the terms of the
     5 # This software may be used and distributed according to the terms of the
     6 # GNU General Public License version 2 or any later version.
     6 # GNU General Public License version 2 or any later version.
     7 #
     7 #
     8 # $Id$
     8 # $Id$
   186     def __init__(self, ui, repo, inc, exc):
   186     def __init__(self, ui, repo, inc, exc):
   187         self.ui = ui
   187         self.ui = ui
   188         self.repo = repo
   188         self.repo = repo
   189         self.match = match.match(repo.root, '', [], inc, exc)
   189         self.match = match.match(repo.root, '', [], inc, exc)
   190         self.restrict = kwtools['hgcmd'] in restricted.split()
   190         self.restrict = kwtools['hgcmd'] in restricted.split()
   191         self.record = False
   191         self.postcommit = False
   192 
   192 
   193         kwmaps = self.ui.configitems('keywordmaps')
   193         kwmaps = self.ui.configitems('keywordmaps')
   194         if kwmaps: # override default templates
   194         if kwmaps: # override default templates
   195             self.templates = dict((k, templater.parsestring(v, False))
   195             self.templates = dict((k, templater.parsestring(v, False))
   196                                   for k, v in kwmaps)
   196                                   for k, v in kwmaps)
   241         expansion but are not symbolic links.'''
   241         expansion but are not symbolic links.'''
   242         return [f for f in cand if self.match(f) and 'l' not in ctx.flags(f)]
   242         return [f for f in cand if self.match(f) and 'l' not in ctx.flags(f)]
   243 
   243 
   244     def overwrite(self, ctx, candidates, lookup, expand, rekw=False):
   244     def overwrite(self, ctx, candidates, lookup, expand, rekw=False):
   245         '''Overwrites selected files expanding/shrinking keywords.'''
   245         '''Overwrites selected files expanding/shrinking keywords.'''
   246         if self.restrict or lookup or self.record: # exclude kw_copy
   246         if self.restrict or lookup or self.postcommit: # exclude kw_copy
   247             candidates = self.iskwfile(candidates, ctx)
   247             candidates = self.iskwfile(candidates, ctx)
   248         if not candidates:
   248         if not candidates:
   249             return
   249             return
   250         kwcmd = self.restrict and lookup # kwexpand/kwshrink
   250         kwcmd = self.restrict and lookup # kwexpand/kwshrink
   251         if self.restrict or expand and lookup:
   251         if self.restrict or expand and lookup:
   278                 fp = self.repo.wopener(f, "wb", atomictemp=True)
   278                 fp = self.repo.wopener(f, "wb", atomictemp=True)
   279                 fp.write(data)
   279                 fp.write(data)
   280                 fp.close()
   280                 fp.close()
   281                 if kwcmd:
   281                 if kwcmd:
   282                     self.repo.dirstate.normal(f)
   282                     self.repo.dirstate.normal(f)
   283                 elif self.record:
   283                 elif self.postcommit:
   284                     self.repo.dirstate.normallookup(f)
   284                     self.repo.dirstate.normallookup(f)
   285 
   285 
   286     def shrink(self, fname, text):
   286     def shrink(self, fname, text):
   287         '''Returns text with all keyword substitutions removed.'''
   287         '''Returns text with all keyword substitutions removed.'''
   288         if self.match(fname) and not util.binary(text):
   288         if self.match(fname) and not util.binary(text):
   581                 del self.commitctx
   581                 del self.commitctx
   582 
   582 
   583         def kwcommitctx(self, ctx, error=False):
   583         def kwcommitctx(self, ctx, error=False):
   584             n = super(kwrepo, self).commitctx(ctx, error)
   584             n = super(kwrepo, self).commitctx(ctx, error)
   585             # no lock needed, only called from repo.commit() which already locks
   585             # no lock needed, only called from repo.commit() which already locks
   586             if not kwt.record:
   586             if not kwt.postcommit:
   587                 restrict = kwt.restrict
   587                 restrict = kwt.restrict
   588                 kwt.restrict = True
   588                 kwt.restrict = True
   589                 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
   589                 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
   590                               False, True)
   590                               False, True)
   591                 kwt.restrict = restrict
   591                 kwt.restrict = restrict
   623     def kwweb_skip(orig, web, req, tmpl):
   623     def kwweb_skip(orig, web, req, tmpl):
   624         '''Wraps webcommands.x turning off keyword expansion.'''
   624         '''Wraps webcommands.x turning off keyword expansion.'''
   625         kwt.match = util.never
   625         kwt.match = util.never
   626         return orig(web, req, tmpl)
   626         return orig(web, req, tmpl)
   627 
   627 
       
   628     def kw_amend(orig, ui, repo, commitfunc, old, extra, pats, opts):
       
   629         '''Wraps cmdutil.amend expanding keywords after amend.'''
       
   630         wlock = repo.wlock()
       
   631         try:
       
   632             kwt.postcommit = True
       
   633             newid = orig(ui, repo, commitfunc, old, extra, pats, opts)
       
   634             if newid != old.node():
       
   635                 ctx = repo[newid]
       
   636                 kwt.restrict = True
       
   637                 kwt.overwrite(ctx, ctx.files(), False, True)
       
   638                 kwt.restrict = False
       
   639             return newid
       
   640         finally:
       
   641             wlock.release()
       
   642 
   628     def kw_copy(orig, ui, repo, pats, opts, rename=False):
   643     def kw_copy(orig, ui, repo, pats, opts, rename=False):
   629         '''Wraps cmdutil.copy so that copy/rename destinations do not
   644         '''Wraps cmdutil.copy so that copy/rename destinations do not
   630         contain expanded keywords.
   645         contain expanded keywords.
   631         Note that the source of a regular file destination may also be a
   646         Note that the source of a regular file destination may also be a
   632         symlink:
   647         symlink:
   633         hg cp sym x                -> x is symlink
   648         hg cp sym x                -> x is symlink
   634         cp sym x; hg cp -A sym x   -> x is file (maybe expanded keywords)
   649         cp sym x; hg cp -A sym x   -> x is file (maybe expanded keywords)
   635         For the latter we have to follow the symlink to find out whether its
   650         For the latter we have to follow the symlink to find out whether its
   636         target is configured for expansion and we therefore must unexpand the
   651         target is configured for expansion and we therefore must unexpand the
   637         keywords in the destination.'''
   652         keywords in the destination.'''
   638         orig(ui, repo, pats, opts, rename)
   653         wlock = repo.wlock()
   639         if opts.get('dry_run'):
   654         try:
   640             return
   655             orig(ui, repo, pats, opts, rename)
   641         wctx = repo[None]
   656             if opts.get('dry_run'):
   642         cwd = repo.getcwd()
   657                 return
   643 
   658             wctx = repo[None]
   644         def haskwsource(dest):
   659             cwd = repo.getcwd()
   645             '''Returns true if dest is a regular file and configured for
   660 
   646             expansion or a symlink which points to a file configured for
   661             def haskwsource(dest):
   647             expansion. '''
   662                 '''Returns true if dest is a regular file and configured for
   648             source = repo.dirstate.copied(dest)
   663                 expansion or a symlink which points to a file configured for
   649             if 'l' in wctx.flags(source):
   664                 expansion. '''
   650                 source = scmutil.canonpath(repo.root, cwd,
   665                 source = repo.dirstate.copied(dest)
   651                                            os.path.realpath(source))
   666                 if 'l' in wctx.flags(source):
   652             return kwt.match(source)
   667                     source = scmutil.canonpath(repo.root, cwd,
   653 
   668                                                os.path.realpath(source))
   654         candidates = [f for f in repo.dirstate.copies() if
   669                 return kwt.match(source)
   655                       'l' not in wctx.flags(f) and haskwsource(f)]
   670 
   656         kwt.overwrite(wctx, candidates, False, False)
   671             candidates = [f for f in repo.dirstate.copies() if
       
   672                           'l' not in wctx.flags(f) and haskwsource(f)]
       
   673             kwt.overwrite(wctx, candidates, False, False)
       
   674         finally:
       
   675             wlock.release()
   657 
   676 
   658     def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
   677     def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
   659         '''Wraps record.dorecord expanding keywords after recording.'''
   678         '''Wraps record.dorecord expanding keywords after recording.'''
   660         wlock = repo.wlock()
   679         wlock = repo.wlock()
   661         try:
   680         try:
   662             # record returns 0 even when nothing has changed
   681             # record returns 0 even when nothing has changed
   663             # therefore compare nodes before and after
   682             # therefore compare nodes before and after
   664             kwt.record = True
   683             kwt.postcommit = True
   665             ctx = repo['.']
   684             ctx = repo['.']
   666             wstatus = repo[None].status()
   685             wstatus = repo[None].status()
   667             ret = orig(ui, repo, commitfunc, *pats, **opts)
   686             ret = orig(ui, repo, commitfunc, *pats, **opts)
   668             recctx = repo['.']
   687             recctx = repo['.']
   669             if ctx != recctx:
   688             if ctx != recctx:
   688         return True
   707         return True
   689 
   708 
   690     extensions.wrapfunction(context.filectx, 'cmp', kwfilectx_cmp)
   709     extensions.wrapfunction(context.filectx, 'cmp', kwfilectx_cmp)
   691     extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
   710     extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
   692     extensions.wrapfunction(patch, 'diff', kw_diff)
   711     extensions.wrapfunction(patch, 'diff', kw_diff)
       
   712     extensions.wrapfunction(cmdutil, 'amend', kw_amend)
   693     extensions.wrapfunction(cmdutil, 'copy', kw_copy)
   713     extensions.wrapfunction(cmdutil, 'copy', kw_copy)
   694     for c in 'annotate changeset rev filediff diff'.split():
   714     for c in 'annotate changeset rev filediff diff'.split():
   695         extensions.wrapfunction(webcommands, c, kwweb_skip)
   715         extensions.wrapfunction(webcommands, c, kwweb_skip)
   696     for name in recordextensions.split():
   716     for name in recordextensions.split():
   697         try:
   717         try: