hgkw/keyword.py
changeset 264 7c637046c0e2
parent 263 fc7f60b109b6
child 265 1b6b7835e3f9
equal deleted inserted replaced
263:fc7f60b109b6 264:7c637046c0e2
    81 '''
    81 '''
    82 
    82 
    83 from mercurial import commands, cmdutil, context, fancyopts
    83 from mercurial import commands, cmdutil, context, fancyopts
    84 from mercurial import filelog, localrepo, revlog, templater, util
    84 from mercurial import filelog, localrepo, revlog, templater, util
    85 from mercurial.i18n import gettext as _
    85 from mercurial.i18n import gettext as _
    86 import getopt, re, shutil, sys, tempfile, time
    86 import getopt, os.path, re, shutil, sys, tempfile, time
    87 
    87 
    88 # backwards compatibility hacks
    88 # backwards compatibility hacks
    89 
    89 
    90 try:
    90 try:
    91     # cmdutil.parse moves to dispatch._parse in 18a9fbb5cd78
    91     # cmdutil.parse moves to dispatch._parse in 18a9fbb5cd78
   101 try:
   101 try:
   102     # bail_if_changed moves from commands to cmdutil in 0c61124ad877
   102     # bail_if_changed moves from commands to cmdutil in 0c61124ad877
   103     bail_if_changed = cmdutil.bail_if_changed
   103     bail_if_changed = cmdutil.bail_if_changed
   104 except AttributeError:
   104 except AttributeError:
   105     bail_if_changed = commands.bail_if_changed
   105     bail_if_changed = commands.bail_if_changed
       
   106 
       
   107 def _pathto(repo, cwd, f):
       
   108     '''kwfiles behaves similar to status, using pathto since 78b6add1f966.'''
       
   109     try:
       
   110         return repo.pathto(f, cwd)
       
   111     except AttributeError:
       
   112         return f
   106 
   113 
   107 # commands.parse/cmdutil.parse returned nothing for
   114 # commands.parse/cmdutil.parse returned nothing for
   108 # "hg diff --rev" before 88803a69b24a due to bug in fancyopts
   115 # "hg diff --rev" before 88803a69b24a due to bug in fancyopts
   109 def _fancyopts(args, options, state):
   116 def _fancyopts(args, options, state):
   110     '''Fixed fancyopts from 88803a69b24a.'''
   117     '''Fixed fancyopts from 88803a69b24a.'''
   298         if self.renamed(node):
   305         if self.renamed(node):
   299             t2 = super(kwfilelog, self).read(node)
   306             t2 = super(kwfilelog, self).read(node)
   300             return t2 != text
   307             return t2 != text
   301         return revlog.revlog.cmp(self, node, text)
   308         return revlog.revlog.cmp(self, node, text)
   302 
   309 
   303 _nokwfiles = 'no files configured for keyword expansion'
   310 def _weedfiles(ui, repo, *pats, **opts):
   304 
   311     '''Collects files matching arguments and/or walkopts,
   305 def _weedcandidates(ui, man, candidates):
   312     sorts out those that are configured for keyword expansion
   306     '''Weeds out files that do not match keyword file matcher,
   313     and not links, and returns both lists.'''
   307     are not tracked, or are links.'''
   314     files, match, anypats = cmdutil.matchpats(repo, pats, opts)
   308     files = man.keys()
   315     status = repo.status(files=files, match=match, list_clean=True)
   309     if candidates:
   316     modified, added, removed, deleted, unknown, ignored, clean = status
   310         return [f for f in candidates if ui.kwfmatcher(f)
   317     files = modified + added + clean
   311                 and f in files and not man.linkf(f)]
   318     files.sort()
   312     return [f for f in files if ui.kwfmatcher(f) and not man.linkf(f)]
   319     try:
   313 
   320         # use the full definition of repo._link for backwards compatibility
   314 def _overwrite(ui, repo, files, expand):
   321         kwfiles = [f for f in files if ui.kwfmatcher(f)
       
   322                    and not os.path.islink(repo.wjoin(f))]
       
   323         return kwfiles, files
       
   324     except AttributeError:
       
   325         if ui.configitems('keyword'):
       
   326             err = _('[keyword] patterns cannot match')
       
   327         else:
       
   328             err = _('no [keyword] patterns configured')
       
   329         raise util.Abort(err)
       
   330 
       
   331 def _overwrite(ui, repo, expand, *pats, **opts):
   315     '''Expands/shrinks keywords in working directory.'''
   332     '''Expands/shrinks keywords in working directory.'''
   316     if not hasattr(ui, 'kwfmatcher'):
       
   317         ui.warn(_('%s\n') % _nokwfiles)
       
   318         return
       
   319     bail_if_changed(repo)
   333     bail_if_changed(repo)
   320     wlock = lock = None
   334     wlock = lock = None
   321     try:
   335     try:
   322         wlock = repo.wlock()
   336         wlock = repo.wlock()
   323         lock = repo.lock()
   337         lock = repo.lock()
   324         ctx = repo.changectx()
   338         kwfiles, files = _weedfiles(ui, repo, *pats, **opts)
   325         man = ctx.manifest()
   339         if kwfiles:
   326         if files:
   340             ctx = repo.changectx()
   327             cwd = repo.getcwd()
       
   328             files = [util.canonpath(repo.root, cwd, f) for f in files]
       
   329         files = _weedcandidates(ui, man, files)
       
   330         if files:
       
   331             kwt = kwtemplater(ui, repo, expand, node=ctx.node())
   341             kwt = kwtemplater(ui, repo, expand, node=ctx.node())
   332             # 3rd argument sets commit to False
   342             # 3rd argument sets commit to False
   333             kwt.overwrite(files, man, False)
   343             kwt.overwrite(kwfiles, ctx.manifest(), False)
   334     finally:
   344     finally:
   335         del wlock, lock
   345         del wlock, lock
   336 
   346 
   337 
   347 
   338 def shrink(ui, repo, *args):
   348 def shrink(ui, repo, *pats, **opts):
   339     '''revert expanded keywords in working directory
   349     '''revert expanded keywords in working directory
   340 
   350 
   341     Run before changing/disabling active keywords
   351     Run before changing/disabling active keywords
   342     or if you experience problems with "hg import" or "hg merge".
   352     or if you experience problems with "hg import" or "hg merge".
   343     '''
   353     '''
   344     # 4th argument sets expansion to False
   354     # 3rd argument sets expansion to False
   345     _overwrite(ui, repo, args, False)
   355     _overwrite(ui, repo, False, *pats, **opts)
   346 
   356 
   347 def expand(ui, repo, *args):
   357 def expand(ui, repo, *pats, **opts):
   348     '''expand keywords in working directory
   358     '''expand keywords in working directory
   349 
   359 
   350     Run after (re)enabling keyword expansion.
   360     Run after (re)enabling keyword expansion.
   351     '''
   361     '''
   352     # 4th argument sets expansion to True
   362     # 3rd argument sets expansion to True
   353     _overwrite(ui, repo, args, True)
   363     _overwrite(ui, repo, True, *pats, **opts)
   354 
   364 
   355 def files(ui, repo):
   365 def files(ui, repo, *pats, **opts):
   356     '''print files currently configured for keyword expansion
   366     '''print files currently configured for keyword expansion
   357 
   367 
   358     Crosscheck which files in working directory
   368     Crosscheck which files in working directory
   359     are matched by [keyword] config patterns.
   369     are matched by [keyword] config patterns.
   360     '''
   370     '''
   361     if not hasattr(ui, 'kwfmatcher'):
   371     kwfiles, files = _weedfiles(ui, repo, *pats, **opts)
   362         ui.note(_('%s\n') % _nokwfiles)
   372     cwd = pats and repo.getcwd() or ''
   363         return
   373     flag = opts['all'] and 1 or 0
   364     ctx = repo.workingctx()
   374     ignored = opts['ignored']
   365     man = ctx.manifest().copy()
   375     if not ignored:
   366     for f in ctx.unknown():
   376         format = ('%s\n', 'K %s\n')[flag]
   367         del man[f]
   377         for k in kwfiles:
   368     files = _weedcandidates(ui, man, None)
   378             ui.write(format % _pathto(repo, cwd, k))
   369     files.sort()
   379     if flag or ignored:
   370     ui.write('\n'.join(files) + '\n')
   380         format = ('%s\n', 'I %s\n')[flag]
       
   381         for i in [f for f in files if f not in kwfiles]:
       
   382             ui.write(format % _pathto(repo, cwd, i))
   371 
   383 
   372 def demo(ui, repo, *args, **opts):
   384 def demo(ui, repo, *args, **opts):
   373     '''print [keywordmaps] configuration and an expansion example
   385     '''print [keywordmaps] configuration and an expansion example
   374 
   386 
   375     Show current, custom, or default keyword template maps
   387     Show current, custom, or default keyword template maps
   517                 node = self._commit(files, text, user, date, match, force,
   529                 node = self._commit(files, text, user, date, match, force,
   518                                     _lock, _wlock, force_editor, p1, p2, extra)
   530                                     _lock, _wlock, force_editor, p1, p2, extra)
   519                 if node is not None:
   531                 if node is not None:
   520                     cl = self.changelog.read(node)
   532                     cl = self.changelog.read(node)
   521                     mn = self.manifest.read(cl[0])
   533                     mn = self.manifest.read(cl[0])
   522                     candidates = _weedcandidates(ui, mn, cl[3])
   534                     candidates = [f for f in cl[3] if ui.kwfmatcher(f)
       
   535                                   and mn.has_key(f) and not mn.linkf(f)]
   523                     if candidates:
   536                     if candidates:
   524                         # 3rd argument sets expansion to True
   537                         # 3rd argument sets expansion to True
   525                         kwt = kwtemplater(ui, self, True, node=node)
   538                         kwt = kwtemplater(ui, self, True, node=node)
   526                         # 3rd argument sets commit to True
   539                         # 3rd argument sets commit to True
   527                         kwt.overwrite(candidates, mn, True)
   540                         kwt.overwrite(candidates, mn, True)
   536     'kwdemo':
   549     'kwdemo':
   537         (demo,
   550         (demo,
   538          [('d', 'default', None, _('show default keyword template maps')),
   551          [('d', 'default', None, _('show default keyword template maps')),
   539           ('f', 'rcfile', [], _('read maps from RCFILE'))],
   552           ('f', 'rcfile', [], _('read maps from RCFILE'))],
   540          _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP ...]')),
   553          _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP ...]')),
   541     'kwfiles': (files, [], _('hg kwfiles')),
   554     'kwfiles':
   542     'kwshrink': (shrink, [], _('hg kwshrink [NAME] ...')),
   555         (files,
   543     'kwexpand': (expand, [], _('hg kwexpand [NAME] ...')),
   556          [('i', 'ignored', None, _('show files ignored by [keyword] patterns')),
       
   557           ('a', 'all', None, _('show keyword status flags of all files')),
       
   558          ] + commands.walkopts,
       
   559          _('hg kwfiles [OPTION]... [FILE]...')),
       
   560     'kwshrink': (shrink, commands.walkopts,
       
   561                  _('hg kwshrink [OPTION]... [FILE]...')),
       
   562     'kwexpand': (expand, commands.walkopts,
       
   563                  _('hg kwexpand [OPTION]... [FILE]...')),
   544 }
   564 }