hgext3rd/topic/__init__.py
changeset 2850 a0d6741d4bb8
parent 2831 eda8eb561134
child 2866 736ab58641f0
equal deleted inserted replaced
2849:95470e817c00 2850:a0d6741d4bb8
   354             topic = None
   354             topic = None
   355         elif not topic:
   355         elif not topic:
   356             raise error.Abort('changing topic requires a topic name or --clear')
   356             raise error.Abort('changing topic requires a topic name or --clear')
   357         if any(not c.mutable() for c in repo.set('%r and public()', rev)):
   357         if any(not c.mutable() for c in repo.set('%r and public()', rev)):
   358             raise error.Abort("can't change topic of a public change")
   358             raise error.Abort("can't change topic of a public change")
   359         return _changetopics(ui, repo, rev, topic)
   359         wl = l = txn = None
       
   360         try:
       
   361             wl = repo.wlock()
       
   362             l = repo.lock()
       
   363             txn = repo.transaction('rewrite-topics')
       
   364             rewrote = _changetopics(ui, repo, rev, topic)
       
   365             txn.close()
       
   366         finally:
       
   367             lock.release(txn, l, wl)
       
   368             repo.invalidate()
       
   369             ui.status('changed topic on %d changes\n' % rewrote)
       
   370         return
   360 
   371 
   361     if clear:
   372     if clear:
   362         return _changecurrenttopic(repo, None)
   373         return _changecurrenttopic(repo, None)
   363 
   374 
   364     if topic:
   375     if topic:
   395     else:
   406     else:
   396         if repo.vfs.exists('topic'):
   407         if repo.vfs.exists('topic'):
   397             repo.vfs.unlink('topic')
   408             repo.vfs.unlink('topic')
   398 
   409 
   399 def _changetopics(ui, repo, revset, newtopic):
   410 def _changetopics(ui, repo, revset, newtopic):
       
   411     """ Changes topic to newtopic of all the revisions in the revset and return
       
   412     the count of revisions whose topic has been changed.
       
   413     """
   400     rewrote = 0
   414     rewrote = 0
   401     wl = l = txn = None
   415     p1 = None
   402     try:
   416     p2 = None
   403         wl = repo.wlock()
   417     successors = {}
   404         l = repo.lock()
   418     for c in repo.set('%r', revset):
   405         txn = repo.transaction('rewrite-topics')
   419         def filectxfn(repo, ctx, path):
   406         p1 = None
   420             try:
   407         p2 = None
   421                 return c[path]
   408         successors = {}
   422             except error.ManifestLookupError:
   409         for c in repo.set('%r', revset):
   423                 return None
   410             def filectxfn(repo, ctx, path):
   424         fixedextra = dict(c.extra())
   411                 try:
   425         ui.debug('old node id is %s\n' % node.hex(c.node()))
   412                     return c[path]
   426         ui.debug('origextra: %r\n' % fixedextra)
   413                 except error.ManifestLookupError:
   427         oldtopic = fixedextra.get(constants.extrakey, None)
   414                     return None
   428         if oldtopic == newtopic:
   415             fixedextra = dict(c.extra())
   429             continue
   416             ui.debug('old node id is %s\n' % node.hex(c.node()))
   430         if newtopic is None:
   417             ui.debug('origextra: %r\n' % fixedextra)
   431             del fixedextra[constants.extrakey]
   418             oldtopic = fixedextra.get(constants.extrakey, None)
   432         else:
   419             if oldtopic == newtopic:
   433             fixedextra[constants.extrakey] = newtopic
   420                 continue
   434         fixedextra[constants.changekey] = c.hex()
   421             if newtopic is None:
   435         if 'amend_source' in fixedextra:
   422                 del fixedextra[constants.extrakey]
   436             # TODO: right now the commitctx wrapper in
   423             else:
   437             # topicrepo overwrites the topic in extra if
   424                 fixedextra[constants.extrakey] = newtopic
   438             # amend_source is set to support 'hg commit
   425             fixedextra[constants.changekey] = c.hex()
   439             # --amend'. Support for amend should be adjusted
   426             if 'amend_source' in fixedextra:
   440             # to not be so invasive.
   427                 # TODO: right now the commitctx wrapper in
   441             del fixedextra['amend_source']
   428                 # topicrepo overwrites the topic in extra if
   442         ui.debug('changing topic of %s from %s to %s\n' % (
   429                 # amend_source is set to support 'hg commit
   443             c, oldtopic, newtopic))
   430                 # --amend'. Support for amend should be adjusted
   444         ui.debug('fixedextra: %r\n' % fixedextra)
   431                 # to not be so invasive.
   445         # While changing topic of set of linear commits, make sure that
   432                 del fixedextra['amend_source']
   446         # we base our commits on new parent rather than old parent which
   433             ui.debug('changing topic of %s from %s to %s\n' % (
   447         # was obsoleted while changing the topic
   434                 c, oldtopic, newtopic))
   448         p1 = c.p1().node()
   435             ui.debug('fixedextra: %r\n' % fixedextra)
   449         p2 = c.p2().node()
   436             # While changing topic of set of linear commits, make sure that
   450         if p1 in successors:
   437             # we base our commits on new parent rather than old parent which
   451             p1 = successors[p1]
   438             # was obsoleted while changing the topic
   452         if p2 in successors:
   439             p1 = c.p1().node()
   453             p2 = successors[p2]
   440             p2 = c.p2().node()
   454         mc = context.memctx(
   441             if p1 in successors:
   455             repo, (p1, p2), c.description(),
   442                 p1 = successors[p1]
   456             c.files(), filectxfn,
   443             if p2 in successors:
   457             user=c.user(), date=c.date(), extra=fixedextra)
   444                 p2 = successors[p2]
   458         newnode = repo.commitctx(mc)
   445             mc = context.memctx(
   459         successors[c.node()] = newnode
   446                 repo, (p1, p2), c.description(),
   460         ui.debug('new node id is %s\n' % node.hex(newnode))
   447                 c.files(), filectxfn,
   461         obsolete.createmarkers(repo, [(c, (repo[newnode],))])
   448                 user=c.user(), date=c.date(), extra=fixedextra)
   462         rewrote += 1
   449             newnode = repo.commitctx(mc)
   463     # move the working copy too
   450             successors[c.node()] = newnode
   464     wctx = repo[None]
   451             ui.debug('new node id is %s\n' % node.hex(newnode))
   465     # in-progress merge is a bit too complex for now.
   452             obsolete.createmarkers(repo, [(c, (repo[newnode],))])
   466     if len(wctx.parents()) == 1:
   453             rewrote += 1
   467         newid = successors.get(wctx.p1().node())
   454         # move the working copy too
   468         if newid is not None:
   455         wctx = repo[None]
   469             hg.update(repo, newid, quietempty=True)
   456         # in-progress merge is a bit too complex for now.
   470     return rewrote
   457         if len(wctx.parents()) == 1:
       
   458             newid = successors.get(wctx.p1().node())
       
   459             if newid is not None:
       
   460                 hg.update(repo, newid, quietempty=True)
       
   461         txn.close()
       
   462     finally:
       
   463         lock.release(txn, l, wl)
       
   464         repo.invalidate()
       
   465     ui.status('changed topic on %d changes\n' % rewrote)
       
   466 
   471 
   467 def _listtopics(ui, repo, opts):
   472 def _listtopics(ui, repo, opts):
   468     fm = ui.formatter('topics', opts)
   473     fm = ui.formatter('topics', opts)
   469     showlast = opts.get('age')
   474     showlast = opts.get('age')
   470     if showlast:
   475     if showlast: