hgkw/keyword.py
branch0.9.2compat
changeset 311 6160401f94f2
parent 303 46ccec2f325f
child 312 b92767fb8fb5
equal deleted inserted replaced
303:46ccec2f325f 311:6160401f94f2
    80         Or, better, use bundle/unbundle to share changes.
    80         Or, better, use bundle/unbundle to share changes.
    81 '''
    81 '''
    82 
    82 
    83 from mercurial import commands, cmdutil, context
    83 from mercurial import commands, cmdutil, context
    84 from mercurial import filelog, localrepo, revlog, templater, util
    84 from mercurial import filelog, localrepo, revlog, templater, util
       
    85 from mercurial.node import *
    85 from mercurial.i18n import gettext as _
    86 from mercurial.i18n import gettext as _
    86 import getopt, os.path, re, shutil, sys, tempfile, time
    87 import getopt, os.path, re, shutil, sys, tempfile, time
    87 
    88 
    88 # backwards compatibility hacks
    89 # backwards compatibility hacks
       
    90 
       
    91 def _wwrite(repo, f, data, mf):
       
    92     '''Makes repo.wwrite backwards compatible.'''
       
    93     # 656e06eebda7 removed file descriptor argument
       
    94     # 67982d3ee76c added flags argument
       
    95     try:
       
    96         repo.wwrite(f, data, mf.flags(f))
       
    97     except (AttributeError, TypeError):
       
    98         repo.wwrite(f, data)
       
    99 
       
   100 def _normal(repo, files):
       
   101     '''Backwards compatible repo.dirstate.normal/update.'''
       
   102     # 6fd953d5faea introduced dirstate.normal()
       
   103     try:
       
   104         for f in files:
       
   105             repo.dirstate.normal(f)
       
   106     except AttributeError:
       
   107         repo.dirstate.update(files, 'n')
    89 
   108 
    90 def _pathto(repo, f, cwd=None):
   109 def _pathto(repo, f, cwd=None):
    91     '''kwfiles behaves similar to status, using pathto since 78b6add1f966.'''
   110     '''kwfiles behaves similar to status, using pathto since 78b6add1f966.'''
    92     try:
   111     try:
    93         return repo.pathto(f, cwd)
   112         return repo.pathto(f, cwd)
   145 
   164 
   146 def utcdate(date):
   165 def utcdate(date):
   147     '''Returns hgdate in cvs-like UTC format.'''
   166     '''Returns hgdate in cvs-like UTC format.'''
   148     return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
   167     return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
   149 
   168 
       
   169 _kwtemplater = None
       
   170 
   150 class kwtemplater(object):
   171 class kwtemplater(object):
   151     '''
   172     '''
   152     Sets up keyword templates, corresponding keyword regex, and
   173     Sets up keyword templates, corresponding keyword regex, and
   153     provides keyword substitution functions.
   174     provides keyword substitution functions.
   154     '''
   175     '''
   160         'Source': '{root}/{file},v',
   181         'Source': '{root}/{file},v',
   161         'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
   182         'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
   162         'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
   183         'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
   163     }
   184     }
   164 
   185 
   165     def __init__(self, ui, repo, expand, path='', node=None):
   186     def __init__(self, ui, repo, inc, exc):
   166         self.ui = ui
   187         self.ui = ui
   167         self.repo = repo
   188         self.repo = repo
   168         self.t = expand or None
   189         self.matcher = util.matcher(repo.root, inc=inc, exc=exc)[1]
   169         self.path = path
   190         self.node = None
   170         self.node = node
   191         self.path = ''
   171 
   192 
   172         kwmaps = self.ui.configitems('keywordmaps')
   193         kwmaps = self.ui.configitems('keywordmaps')
   173         if kwmaps: # override default templates
   194         if kwmaps: # override default templates
   174             kwmaps = [(k, templater.parsestring(v, quoted=False))
   195             kwmaps = [(k, templater.parsestring(v, quoted=False))
   175                       for (k, v) in kwmaps]
   196                       for (k, v) in kwmaps]
   176             self.templates = dict(kwmaps)
   197             self.templates = dict(kwmaps)
   177         escaped = map(re.escape, self.templates.keys())
   198         escaped = map(re.escape, self.templates.keys())
   178         kwpat = r'\$(%s)(: [^$\n\r]*? )??\$' % '|'.join(escaped)
   199         kwpat = r'\$(%s)(: [^$\n\r]*? )??\$' % '|'.join(escaped)
   179         self.re_kw = re.compile(kwpat)
   200         self.re_kw = re.compile(kwpat)
   180         if self.t:
   201 
   181             templater.common_filters['utcdate'] = utcdate
   202         templater.common_filters['utcdate'] = utcdate
   182             self.t = self._changeset_templater()
   203         self.ct = self._changeset_templater()
   183 
   204 
   184     def _changeset_templater(self):
   205     def _changeset_templater(self):
   185         '''Backwards compatible cmdutil.changeset_templater.'''
   206         '''Backwards compatible cmdutil.changeset_templater.'''
   186         # before 1e0b94cfba0e there was an extra "brinfo" argument
   207         # before 1e0b94cfba0e there was an extra "brinfo" argument
   187         try:
   208         try:
   189                                                False, '', False)
   210                                                False, '', False)
   190         except TypeError:
   211         except TypeError:
   191             return cmdutil.changeset_templater(self.ui, self.repo,
   212             return cmdutil.changeset_templater(self.ui, self.repo,
   192                                                False, None, '', False)
   213                                                False, None, '', False)
   193 
   214 
   194     def _wwrite(self, f, data, man):
       
   195         '''Makes repo.wwrite backwards compatible.'''
       
   196         # 656e06eebda7 removed file descriptor argument
       
   197         # 67982d3ee76c added flags argument
       
   198         try:
       
   199             self.repo.wwrite(f, data, man.flags(f))
       
   200         except (AttributeError, TypeError):
       
   201             self.repo.wwrite(f, data)
       
   202 
       
   203     def _normal(self, files):
       
   204         '''Backwards compatible repo.dirstate.normal/update.'''
       
   205         # 6fd953d5faea introduced dirstate.normal()
       
   206         try:
       
   207             for f in files:
       
   208                 self.repo.dirstate.normal(f)
       
   209         except AttributeError:
       
   210             self.repo.dirstate.update(files, 'n')
       
   211 
       
   212     def substitute(self, node, data, subfunc):
   215     def substitute(self, node, data, subfunc):
   213         '''Obtains node if missing, and calls given substitution function.'''
   216         '''Obtains node if missing, and calls given substitution function.'''
   214         if not self.node:
   217         if not self.node:
   215             c = context.filectx(self.repo, self.path, fileid=node)
   218             c = context.filectx(self.repo, self.path, fileid=node)
   216             self.node = c.node()
   219             self.node = c.node()
   217 
   220 
   218         def kwsub(mobj):
   221         def kwsub(mobj):
   219             '''Substitutes keyword using corresponding template.'''
   222             '''Substitutes keyword using corresponding template.'''
   220             kw = mobj.group(1)
   223             kw = mobj.group(1)
   221             self.t.use_template(self.templates[kw])
   224             self.ct.use_template(self.templates[kw])
   222             self.ui.pushbuffer()
   225             self.ui.pushbuffer()
   223             self.t.show(changenode=self.node,
   226             self.ct.show(changenode=self.node,
   224                         root=self.repo.root, file=self.path)
   227                          root=self.repo.root, file=self.path)
   225             return '$%s: %s $' % (kw, templater.firstline(self.ui.popbuffer()))
   228             return '$%s: %s $' % (kw, templater.firstline(self.ui.popbuffer()))
   226 
   229 
   227         return subfunc(kwsub, data)
   230         return subfunc(kwsub, data)
   228 
   231 
   229     def expand(self, node, data):
   232     def expand(self, node, data):
   230         '''Returns data with keywords expanded.'''
   233         '''Returns data with keywords expanded.'''
   231         if util.binary(data):
   234         if util.binary(data):
   232             return data
   235             return data
   233         return self.substitute(node, data, self.re_kw.sub)
   236         return self.substitute(node, data, self.re_kw.sub)
   234 
   237 
   235     def process(self, node, data):
   238     def process(self, node, data, expand):
   236         '''Returns a tuple: data, count.
   239         '''Returns a tuple: data, count.
   237         Count is number of keywords/keyword substitutions, indicates
   240         Count is number of keywords/keyword substitutions, indicates
   238         to caller whether to act on file containing data.
   241         to caller whether to act on file containing data.
   239         Keywords in data are expanded, if templater was initialized.'''
   242         Keywords in data are expanded, if templater was initialized.'''
   240         if util.binary(data):
   243         if util.binary(data):
   241             return data, None
   244             return data, None
   242         if self.t:
   245         if expand:
   243             return self.substitute(node, data, self.re_kw.subn)
   246             return self.substitute(node, data, self.re_kw.subn)
   244         return data, self.re_kw.search(data)
   247         return data, self.re_kw.search(data)
   245 
   248 
   246     def shrink(self, text):
   249     def shrink(self, text):
   247         '''Returns text with all keyword substitutions removed.'''
   250         '''Returns text with all keyword substitutions removed.'''
   248         if util.binary(text):
   251         if util.binary(text):
   249             return text
   252             return text
   250         return self.re_kw.sub(r'$\1$', text)
   253         return self.re_kw.sub(r'$\1$', text)
   251 
   254 
   252     def overwrite(self, candidates, man, commit):
       
   253         '''Overwrites files in working directory if keywords are detected.
       
   254         Keywords are expanded if keyword templater is initialized,
       
   255         otherwise their substitution is removed.'''
       
   256         expand = self.t is not None
       
   257         action = ('shrinking', 'expanding')[expand]
       
   258         notify = (self.ui.note, self.ui.debug)[commit]
       
   259         overwritten = []
       
   260         for f in candidates:
       
   261             fp = self.repo.file(f, kwexp=expand, kwmatch=True)
       
   262             data, kwfound = fp.kwctread(man[f])
       
   263             if kwfound:
       
   264                 notify(_('overwriting %s %s keywords\n') % (f, action))
       
   265                 self._wwrite(f, data, man)
       
   266                 overwritten.append(f)
       
   267         self._normal(overwritten)
       
   268 
       
   269 class kwfilelog(filelog.filelog):
   255 class kwfilelog(filelog.filelog):
   270     '''
   256     '''
   271     Subclass of filelog to hook into its read, add, cmp methods.
   257     Subclass of filelog to hook into its read, add, cmp methods.
   272     Keywords are "stored" unexpanded, and processed on reading.
   258     Keywords are "stored" unexpanded, and processed on reading.
   273     '''
   259     '''
   274     def __init__(self, opener, path, kwtemplater):
   260     def __init__(self, opener, path, kwtemplater):
   275         super(kwfilelog, self).__init__(opener, path)
   261         super(kwfilelog, self).__init__(opener, path)
   276         self.kwtemplater = kwtemplater
   262         self.kwtemplater = kwtemplater
   277 
   263         self.kwtemplater.path = path
   278     def kwctread(self, node):
   264 
       
   265     def kwctread(self, node, expand):
   279         '''Reads expanding and counting keywords
   266         '''Reads expanding and counting keywords
   280         (only called from kwtemplater.overwrite).'''
   267         (only called from kwtemplater.overwrite).'''
   281         data = super(kwfilelog, self).read(node)
   268         data = super(kwfilelog, self).read(node)
   282         return self.kwtemplater.process(node, data)
   269         return self.kwtemplater.process(node, data, expand)
   283 
   270 
   284     def read(self, node):
   271     def read(self, node):
   285         '''Expands keywords when reading filelog.'''
   272         '''Expands keywords when reading filelog.'''
   286         data = super(kwfilelog, self).read(node)
   273         data = super(kwfilelog, self).read(node)
   287         return self.kwtemplater.expand(node, data)
   274         return self.kwtemplater.expand(node, data)
   297         if self.renamed(node):
   284         if self.renamed(node):
   298             t2 = super(kwfilelog, self).read(node)
   285             t2 = super(kwfilelog, self).read(node)
   299             return t2 != text
   286             return t2 != text
   300         return revlog.revlog.cmp(self, node, text)
   287         return revlog.revlog.cmp(self, node, text)
   301 
   288 
   302 def _status(ui, repo, *pats, **opts):
   289 def _iskwfile(f, kwtemplater, link):
       
   290     return not link(f) and kwtemplater.matcher(f)
       
   291 
       
   292 def _status(ui, repo, kwtemplater, *pats, **opts):
   303     '''Bails out if [keyword] configuration is not active.
   293     '''Bails out if [keyword] configuration is not active.
   304     Returns status of working directory.'''
   294     Returns status of working directory.'''
   305     if hasattr(ui, 'kwfmatcher'):
   295     if kwtemplater:
   306         files, match, anypats = cmdutil.matchpats(repo, pats, opts)
   296         files, match, anypats = cmdutil.matchpats(repo, pats, opts)
   307         return repo.status(files=files, match=match, list_clean=True)
   297         return repo.status(files=files, match=match, list_clean=True)
   308     if ui.configitems('keyword'):
   298     if ui.configitems('keyword'):
   309         raise util.Abort(_('[keyword] patterns cannot match'))
   299         raise util.Abort(_('[keyword] patterns cannot match'))
   310     raise util.Abort(_('no [keyword] patterns configured'))
   300     raise util.Abort(_('no [keyword] patterns configured'))
   311 
   301 
   312 def _iskwfile(ui, man, f):
   302 def _overwrite(ui, repo, kwtemplater, node=None, expand=True, files=None):
   313     return not man.linkf(f) and ui.kwfmatcher(f)
   303     '''Overwrites selected files expanding/shrinking keywords.'''
   314 
   304     ctx = repo.changectx(node)
   315 def _overwrite(ui, repo, files, node, man, expand, commit):
   305     mf = ctx.manifest()
   316     '''Passes given files to kwtemplater for overwriting.'''
   306     if files is None:
   317     files.sort()
   307         notify = ui.debug # commit
   318     kwt = kwtemplater(ui, repo, expand, node=node)
   308         files = [f for f in ctx.files() if mf.has_key(f)]
   319     kwt.overwrite(files, man, commit)
   309     else:
       
   310         notify = ui.note  # kwexpand/kwshrink
       
   311     candidates = [f for f in files if _iskwfile(f, kwtemplater, mf.linkf)]
       
   312     if candidates:
       
   313         overwritten = []
       
   314         candidates.sort()
       
   315         action = expand and 'expanding' or 'shrinking'
       
   316         kwtemplater.node = node or ctx.node()
       
   317         for f in candidates:
       
   318             fp = repo.file(f, kwmatch=True)
       
   319             data, kwfound = fp.kwctread(mf[f], expand)
       
   320             if kwfound:
       
   321                 notify(_('overwriting %s %s keywords\n') % (f, action))
       
   322                 _wwrite(repo, f, data, mf)
       
   323                 overwritten.append(f)
       
   324         _normal(repo, overwritten)
   320 
   325 
   321 def _kwfwrite(ui, repo, expand, *pats, **opts):
   326 def _kwfwrite(ui, repo, expand, *pats, **opts):
   322     '''Selects files and passes them to _overwrite.'''
   327     '''Selects files and passes them to _overwrite.'''
   323     status = _status(ui, repo, *pats, **opts)
   328     global _kwtemplater
       
   329     status = _status(ui, repo, _kwtemplater, *pats, **opts)
   324     modified, added, removed, deleted, unknown, ignored, clean = status
   330     modified, added, removed, deleted, unknown, ignored, clean = status
   325     if modified or added or removed or deleted:
   331     if modified or added or removed or deleted:
   326         raise util.Abort(_('outstanding uncommitted changes in given files'))
   332         raise util.Abort(_('outstanding uncommitted changes in given files'))
   327     wlock = lock = None
   333     wlock = lock = None
   328     try:
   334     try:
   329         wlock = repo.wlock()
   335         wlock = repo.wlock()
   330         lock = repo.lock()
   336         lock = repo.lock()
   331         ctx = repo.changectx()
   337         _overwrite(ui, repo, _kwtemplater, expand=expand, files=clean)
   332         man = ctx.manifest()
       
   333         candidates = [f for f in clean if _iskwfile(ui, man, f)]
       
   334         if candidates:
       
   335             # 7th argument sets commit to False
       
   336             _overwrite(ui, repo, candidates, ctx.node(), man, expand, False)
       
   337     finally:
   338     finally:
   338         del wlock, lock
   339         del wlock, lock
   339 
   340 
   340 
   341 
   341 def demo(ui, repo, *args, **opts):
   342 def demo(ui, repo, *args, **opts):
   405     quiet = ui.quiet
   406     quiet = ui.quiet
   406     verbose = ui.verbose
   407     verbose = ui.verbose
   407     ui.quiet = not verbose
   408     ui.quiet = not verbose
   408     commands.branch(ui, repo, branchname)
   409     commands.branch(ui, repo, branchname)
   409     ui.quiet = quiet
   410     ui.quiet = quiet
       
   411     for name, cmd in ui.configitems('hooks'):
       
   412         if name.split('.', 1)[0].find('commit') > -1:
       
   413             repo.ui.setconfig('hooks', name, '')
       
   414     ui.note(_('unhooked all commit hooks\n'))
   410     ui.note('hg -R "%s" ci -m "%s"\n' % (tmpdir, msg))
   415     ui.note('hg -R "%s" ci -m "%s"\n' % (tmpdir, msg))
   411     repo.commit(text=msg)
   416     repo.commit(text=msg)
   412     pathinfo = ('', ' in %s' % path)[ui.verbose]
   417     format = ui.verbose and ' in %s' % path or ''
   413     demostatus('%s keywords expanded%s' % (kwstatus, pathinfo))
   418     demostatus('%s keywords expanded%s' % (kwstatus, format))
   414     ui.write(repo.wread(fn))
   419     ui.write(repo.wread(fn))
   415     ui.debug(_('\nremoving temporary repo %s\n') % tmpdir)
   420     ui.debug(_('\nremoving temporary repo %s\n') % tmpdir)
   416     shutil.rmtree(tmpdir, ignore_errors=True)
   421     shutil.rmtree(tmpdir, ignore_errors=True)
   417 
   422 
   418 def expand(ui, repo, *pats, **opts):
   423 def expand(ui, repo, *pats, **opts):
   430 
   435 
   431     Crosscheck which files in working directory are potential targets for
   436     Crosscheck which files in working directory are potential targets for
   432     keyword expansion.
   437     keyword expansion.
   433     That is, files matched by [keyword] config patterns but not symlinks.
   438     That is, files matched by [keyword] config patterns but not symlinks.
   434     '''
   439     '''
   435     status = _status(ui, repo, *pats, **opts)
   440     global _kwtemplater
       
   441     status = _status(ui, repo, _kwtemplater, *pats, **opts)
   436     modified, added, removed, deleted, unknown, ignored, clean = status
   442     modified, added, removed, deleted, unknown, ignored, clean = status
   437     if opts['untracked']:
   443     if opts['untracked']:
   438         files = modified + added + unknown + clean
   444         files = modified + added + unknown + clean
   439     else:
   445     else:
   440         files = modified + added + clean
   446         files = modified + added + clean
   441     files.sort()
   447     files.sort()
   442     # use the full definition of repo._link for backwards compatibility
   448     # use the full definition of repo._link for backwards compatibility
   443     kwfiles = [f for f in files if ui.kwfmatcher(f)
   449     kwfiles = [f for f in files if _kwtemplater.matcher(f)
   444                and not os.path.islink(repo.wjoin(f))]
   450                and not os.path.islink(repo.wjoin(f))]
   445     cwd = pats and repo.getcwd() or ''
   451     cwd = pats and repo.getcwd() or ''
   446     allf = opts['all']
   452     allf = opts['all']
   447     ignore = opts['ignore']
   453     ignore = opts['ignore']
   448     if ignore:
   454     if ignore:
   450     else:
   456     else:
   451         kwfstats = (('K', kwfiles),)
   457         kwfstats = (('K', kwfiles),)
   452     if allf or ignore:
   458     if allf or ignore:
   453         kwfstats += (('I', [f for f in files if f not in kwfiles]),)
   459         kwfstats += (('I', [f for f in files if f not in kwfiles]),)
   454     for char, filenames in kwfstats:
   460     for char, filenames in kwfstats:
   455         if allf or ui.verbose:
   461         format = (allf or ui.verbose) and '%s %%s\n' % char or '%s\n'
   456             format = '%s %%s\n' % char
       
   457         else:
       
   458             format = '%s\n'
       
   459         for f in filenames:
   462         for f in filenames:
   460             ui.write(format % repo.pathto(f, cwd))
   463             ui.write(format % _pathto(repo, f, cwd))
   461 
   464 
   462 def shrink(ui, repo, *pats, **opts):
   465 def shrink(ui, repo, *pats, **opts):
   463     '''revert expanded keywords in working directory
   466     '''revert expanded keywords in working directory
   464 
   467 
   465     Run before changing/disabling active keywords
   468     Run before changing/disabling active keywords
   501         else:
   504         else:
   502             exc.append(pat)
   505             exc.append(pat)
   503     if not inc:
   506     if not inc:
   504         return
   507         return
   505 
   508 
   506     ui.kwfmatcher = util.matcher(repo.root, inc=inc, exc=exc)[1]
   509     global _kwtemplater
       
   510     _kwtemplater = kwtemplater(ui, repo, inc, exc)
   507 
   511 
   508     class kwrepo(repo.__class__):
   512     class kwrepo(repo.__class__):
   509         def file(self, f, kwexp=True, kwmatch=False):
   513         def file(self, f, kwmatch=False):
   510             if f[0] == '/':
   514             if f[0] == '/':
   511                 f = f[1:]
   515                 f = f[1:]
   512             if kwmatch or ui.kwfmatcher(f):
   516             if kwmatch or _kwtemplater.matcher(f):
   513                 kwt = kwtemplater(ui, self, kwexp, path=f)
   517                 return kwfilelog(self.sopener, f, _kwtemplater)
   514                 return kwfilelog(self.sopener, f, kwt)
       
   515             return filelog.filelog(self.sopener, f)
   518             return filelog.filelog(self.sopener, f)
   516 
   519 
   517         def _commit(self, files, text, user, date, match, force, lock, wlock,
   520         def _commit(self, files, text, user, date, match, force, lock, wlock,
   518                     force_editor, p1, p2, extra):
   521                     force_editor, p1, p2, extra):
   519             '''Private commit wrapper for backwards compatibility.'''
   522             '''Private commit wrapper for backwards compatibility.'''
   538             # so they are None or what was passed to commit
   541             # so they are None or what was passed to commit
   539             # use private _(w)lock for deletion
   542             # use private _(w)lock for deletion
   540             _lock = lock
   543             _lock = lock
   541             _wlock = wlock
   544             _wlock = wlock
   542             del wlock, lock
   545             del wlock, lock
       
   546             _p1 = _p2 = None
   543             try:
   547             try:
   544                 if not _wlock:
   548                 if not _wlock:
   545                     _wlock = self.wlock()
   549                     _wlock = self.wlock()
   546                 if not _lock:
   550                 if not _lock:
   547                     _lock = self.lock()
   551                     _lock = self.lock()
       
   552                 # store and postpone commit hooks
       
   553                 commithooks = []
       
   554                 for name, cmd in ui.configitems('hooks'):
       
   555                     if name.split('.', 1)[0] == 'commit':
       
   556                         commithooks.append((name, cmd))
       
   557                         ui.setconfig('hooks', name, '')
       
   558                 if commithooks:
       
   559                     # store parents for commit hook environment
       
   560                     if p1 is None:
       
   561                         _p1, _p2 = repo.dirstate.parents()
       
   562                     else:
       
   563                         _p1, _p2 = p1, p2 or nullid
       
   564                     _p1 = hex(_p1)
       
   565                     if _p2 == nullid:
       
   566                         _p2 = ''
       
   567                     else:
       
   568                         _p2 = hex(_p2)
       
   569 
   548                 node = self._commit(files, text, user, date, match, force,
   570                 node = self._commit(files, text, user, date, match, force,
   549                                     _lock, _wlock, force_editor, p1, p2, extra)
   571                                     _lock, _wlock, force_editor, p1, p2, extra)
       
   572 
       
   573                 # restore commit hooks
       
   574                 for name, cmd in commithooks:
       
   575                     ui.setconfig('hooks', name, cmd)
   550                 if node is not None:
   576                 if node is not None:
   551                     cl = self.changelog.read(node)
   577                     _overwrite(ui, self, _kwtemplater, node=node)
   552                     mn = self.manifest.read(cl[0])
   578                     repo.hook('commit', node=node, parent1=_p1, parent2=_p2)
   553                     candidates = [f for f in cl[3] if mn.has_key(f)
       
   554                                   and _iskwfile(ui, mn, f)]
       
   555                     if candidates:
       
   556                         # 6th, 7th arguments set expansion, commit to True
       
   557                         _overwrite(ui, self, candidates, node, mn, True, True)
       
   558                 return node
   579                 return node
   559             finally:
   580             finally:
   560                 del _wlock, _lock
   581                 del _wlock, _lock
   561 
   582 
   562     repo.__class__ = kwrepo
   583     repo.__class__ = kwrepo