hgext/mq.py
changeset 4917 126f527b3ba3
parent 4915 97b734fb9c6f
child 4970 30d4d8985dd8
equal deleted inserted replaced
4916:5c5d23d93447 4917:126f527b3ba3
   321         fns, matchfn, anypats = cmdutil.matchpats(repo, files, opts)
   321         fns, matchfn, anypats = cmdutil.matchpats(repo, files, opts)
   322 
   322 
   323         patch.diff(repo, node1, node2, fns, match=matchfn,
   323         patch.diff(repo, node1, node2, fns, match=matchfn,
   324                    fp=fp, changes=changes, opts=self.diffopts())
   324                    fp=fp, changes=changes, opts=self.diffopts())
   325 
   325 
   326     def mergeone(self, repo, mergeq, head, patch, rev, wlock):
   326     def mergeone(self, repo, mergeq, head, patch, rev):
   327         # first try just applying the patch
   327         # first try just applying the patch
   328         (err, n) = self.apply(repo, [ patch ], update_status=False,
   328         (err, n) = self.apply(repo, [ patch ], update_status=False,
   329                               strict=True, merge=rev, wlock=wlock)
   329                               strict=True, merge=rev)
   330 
   330 
   331         if err == 0:
   331         if err == 0:
   332             return (err, n)
   332             return (err, n)
   333 
   333 
   334         if n is None:
   334         if n is None:
   335             raise util.Abort(_("apply failed for patch %s") % patch)
   335             raise util.Abort(_("apply failed for patch %s") % patch)
   336 
   336 
   337         self.ui.warn("patch didn't work out, merging %s\n" % patch)
   337         self.ui.warn("patch didn't work out, merging %s\n" % patch)
   338 
   338 
   339         # apply failed, strip away that rev and merge.
   339         # apply failed, strip away that rev and merge.
   340         hg.clean(repo, head, wlock=wlock)
   340         hg.clean(repo, head)
   341         self.strip(repo, n, update=False, backup='strip', wlock=wlock)
   341         self.strip(repo, n, update=False, backup='strip')
   342 
   342 
   343         ctx = repo.changectx(rev)
   343         ctx = repo.changectx(rev)
   344         ret = hg.merge(repo, rev, wlock=wlock)
   344         ret = hg.merge(repo, rev)
   345         if ret:
   345         if ret:
   346             raise util.Abort(_("update returned %d") % ret)
   346             raise util.Abort(_("update returned %d") % ret)
   347         n = repo.commit(None, ctx.description(), ctx.user(),
   347         n = repo.commit(None, ctx.description(), ctx.user(), force=1)
   348                         force=1, wlock=wlock)
       
   349         if n == None:
   348         if n == None:
   350             raise util.Abort(_("repo commit failed"))
   349             raise util.Abort(_("repo commit failed"))
   351         try:
   350         try:
   352             message, comments, user, date, patchfound = mergeq.readheaders(patch)
   351             message, comments, user, date, patchfound = mergeq.readheaders(patch)
   353         except:
   352         except:
   379                 return pp[0]
   378                 return pp[0]
   380             if p1 in arevs:
   379             if p1 in arevs:
   381                 return pp[1]
   380                 return pp[1]
   382         return pp[0]
   381         return pp[0]
   383 
   382 
   384     def mergepatch(self, repo, mergeq, series, wlock):
   383     def mergepatch(self, repo, mergeq, series):
   385         if len(self.applied) == 0:
   384         if len(self.applied) == 0:
   386             # each of the patches merged in will have two parents.  This
   385             # each of the patches merged in will have two parents.  This
   387             # can confuse the qrefresh, qdiff, and strip code because it
   386             # can confuse the qrefresh, qdiff, and strip code because it
   388             # needs to know which parent is actually in the patch queue.
   387             # needs to know which parent is actually in the patch queue.
   389             # so, we insert a merge marker with only one parent.  This way
   388             # so, we insert a merge marker with only one parent.  This way
   390             # the first patch in the queue is never a merge patch
   389             # the first patch in the queue is never a merge patch
   391             #
   390             #
   392             pname = ".hg.patches.merge.marker"
   391             pname = ".hg.patches.merge.marker"
   393             n = repo.commit(None, '[mq]: merge marker', user=None, force=1,
   392             n = repo.commit(None, '[mq]: merge marker', user=None, force=1)
   394                             wlock=wlock)
       
   395             self.removeundo(repo)
   393             self.removeundo(repo)
   396             self.applied.append(statusentry(revlog.hex(n), pname))
   394             self.applied.append(statusentry(revlog.hex(n), pname))
   397             self.applied_dirty = 1
   395             self.applied_dirty = 1
   398 
   396 
   399         head = self.qparents(repo)
   397         head = self.qparents(repo)
   410             info = mergeq.isapplied(patch)
   408             info = mergeq.isapplied(patch)
   411             if not info:
   409             if not info:
   412                 self.ui.warn("patch %s is not applied\n" % patch)
   410                 self.ui.warn("patch %s is not applied\n" % patch)
   413                 return (1, None)
   411                 return (1, None)
   414             rev = revlog.bin(info[1])
   412             rev = revlog.bin(info[1])
   415             (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock)
   413             (err, head) = self.mergeone(repo, mergeq, head, patch, rev)
   416             if head:
   414             if head:
   417                 self.applied.append(statusentry(revlog.hex(head), patch))
   415                 self.applied.append(statusentry(revlog.hex(head), patch))
   418                 self.applied_dirty = 1
   416                 self.applied_dirty = 1
   419             if err:
   417             if err:
   420                 return (err, head)
   418                 return (err, head)
   435             return (False, files, False)
   433             return (False, files, False)
   436 
   434 
   437         return (True, files, fuzz)
   435         return (True, files, fuzz)
   438 
   436 
   439     def apply(self, repo, series, list=False, update_status=True,
   437     def apply(self, repo, series, list=False, update_status=True,
   440               strict=False, patchdir=None, merge=None, wlock=None,
   438               strict=False, patchdir=None, merge=None, all_files={}):
   441               all_files={}):
   439         wlock = lock = tr = None
   442         lock = tr = None
       
   443         try:
   440         try:
   444             if not wlock:
   441             wlock = repo.wlock()
   445                 wlock = repo.wlock()
       
   446             lock = repo.lock()
   442             lock = repo.lock()
   447             tr = repo.transaction()
   443             tr = repo.transaction()
   448             try:
   444             try:
   449                 ret = self._apply(tr, repo, series, list, update_status,
   445                 ret = self._apply(tr, repo, series, list, update_status,
   450                                   strict, patchdir, merge, wlock,
   446                                   strict, patchdir, merge, all_files=all_files)
   451                                   lock=lock, all_files=all_files)
       
   452                 tr.close()
   447                 tr.close()
   453                 self.save_dirty()
   448                 self.save_dirty()
   454                 return ret
   449                 return ret
   455             except:
   450             except:
   456                 try:
   451                 try:
   461                 raise
   456                 raise
   462         finally:
   457         finally:
   463             del lock, wlock, tr
   458             del lock, wlock, tr
   464 
   459 
   465     def _apply(self, tr, repo, series, list=False, update_status=True,
   460     def _apply(self, tr, repo, series, list=False, update_status=True,
   466                strict=False, patchdir=None, merge=None, wlock=None,
   461                strict=False, patchdir=None, merge=None, all_files={}):
   467                lock=None, all_files={}):
       
   468         # TODO unify with commands.py
   462         # TODO unify with commands.py
   469         if not patchdir:
   463         if not patchdir:
   470             patchdir = self.path
   464             patchdir = self.path
   471         err = 0
   465         err = 0
   472         n = None
   466         n = None
   509                     repo.dirstate.remove(f)
   503                     repo.dirstate.remove(f)
   510                 for f in merged:
   504                 for f in merged:
   511                     repo.dirstate.merge(f)
   505                     repo.dirstate.merge(f)
   512                 p1, p2 = repo.dirstate.parents()
   506                 p1, p2 = repo.dirstate.parents()
   513                 repo.dirstate.setparents(p1, merge)
   507                 repo.dirstate.setparents(p1, merge)
   514             files = patch.updatedir(self.ui, repo, files, wlock=wlock)
   508             files = patch.updatedir(self.ui, repo, files)
   515             n = repo.commit(files, message, user, date, force=1, lock=lock,
   509             n = repo.commit(files, message, user, date, force=1)
   516                             wlock=wlock)
       
   517 
   510 
   518             if n == None:
   511             if n == None:
   519                 raise util.Abort(_("repo commit failed"))
   512                 raise util.Abort(_("repo commit failed"))
   520 
   513 
   521             if update_status:
   514             if update_status:
   621         self.check_toppatch(repo)
   614         self.check_toppatch(repo)
   622         wlock = repo.wlock()
   615         wlock = repo.wlock()
   623         try:
   616         try:
   624             insert = self.full_series_end()
   617             insert = self.full_series_end()
   625             if msg:
   618             if msg:
   626                 n = repo.commit(commitfiles, msg, force=True, wlock=wlock)
   619                 n = repo.commit(commitfiles, msg, force=True)
   627             else:
   620             else:
   628                 n = repo.commit(commitfiles,
   621                 n = repo.commit(commitfiles, "[mq]: %s" % patch, force=True)
   629                                 "[mq]: %s" % patch, force=True, wlock=wlock)
       
   630             if n == None:
   622             if n == None:
   631                 raise util.Abort(_("repo commit failed"))
   623                 raise util.Abort(_("repo commit failed"))
   632             self.full_series[insert:insert] = [patch]
   624             self.full_series[insert:insert] = [patch]
   633             self.applied.append(statusentry(revlog.hex(n), patch))
   625             self.applied.append(statusentry(revlog.hex(n), patch))
   634             self.parse_series()
   626             self.parse_series()
   646                 self.refresh(repo, short=True)
   638                 self.refresh(repo, short=True)
   647             self.removeundo(repo)
   639             self.removeundo(repo)
   648         finally:
   640         finally:
   649             del wlock
   641             del wlock
   650 
   642 
   651     def strip(self, repo, rev, update=True, backup="all", wlock=None):
   643     def strip(self, repo, rev, update=True, backup="all"):
   652         lock = None
   644         wlock = lock = None
   653         try:
   645         try:
   654             if not wlock:
   646             wlock = repo.wlock()
   655                 wlock = repo.wlock()
       
   656             lock = repo.lock()
   647             lock = repo.lock()
   657 
   648 
   658             if update:
   649             if update:
   659                 self.check_localchanges(repo, refresh=False)
   650                 self.check_localchanges(repo, refresh=False)
   660                 urev = self.qparents(repo, rev)
   651                 urev = self.qparents(repo, rev)
   661                 hg.clean(repo, urev, wlock=wlock)
   652                 hg.clean(repo, urev)
   662                 repo.dirstate.write()
   653                 repo.dirstate.write()
   663 
   654 
   664             self.removeundo(repo)
   655             self.removeundo(repo)
   665             repair.strip(self.ui, repo, rev, backup)
   656             repair.strip(self.ui, repo, rev, backup)
   666         finally:
   657         finally:
   746                             if i + off < len(self.series):
   737                             if i + off < len(self.series):
   747                                 return self.series[i + off]
   738                                 return self.series[i + off]
   748         raise util.Abort(_("patch %s not in series") % patch)
   739         raise util.Abort(_("patch %s not in series") % patch)
   749 
   740 
   750     def push(self, repo, patch=None, force=False, list=False,
   741     def push(self, repo, patch=None, force=False, list=False,
   751              mergeq=None, wlock=None):
   742              mergeq=None):
   752         if not wlock:
   743         wlock = repo.wlock()
   753             wlock = repo.wlock()
       
   754         try:
   744         try:
   755             patch = self.lookup(patch)
   745             patch = self.lookup(patch)
   756             # Suppose our series file is: A B C and the current 'top'
   746             # Suppose our series file is: A B C and the current 'top'
   757             # patch is B. qpush C should be performed (moving forward)
   747             # patch is B. qpush C should be performed (moving forward)
   758             # qpush B is a NOP (no change) qpush A is an error (can't
   748             # qpush B is a NOP (no change) qpush A is an error (can't
   792                 end = self.series.index(patch, start) + 1
   782                 end = self.series.index(patch, start) + 1
   793             s = self.series[start:end]
   783             s = self.series[start:end]
   794             all_files = {}
   784             all_files = {}
   795             try:
   785             try:
   796                 if mergeq:
   786                 if mergeq:
   797                     ret = self.mergepatch(repo, mergeq, s, wlock)
   787                     ret = self.mergepatch(repo, mergeq, s)
   798                 else:
   788                 else:
   799                     ret = self.apply(repo, s, list, wlock=wlock,
   789                     ret = self.apply(repo, s, list, all_files=all_files)
   800                                      all_files=all_files)
       
   801             except:
   790             except:
   802                 self.ui.warn(_('cleaning up working directory...'))
   791                 self.ui.warn(_('cleaning up working directory...'))
   803                 node = repo.dirstate.parents()[0]
   792                 node = repo.dirstate.parents()[0]
   804                 hg.revert(repo, node, None, wlock)
   793                 hg.revert(repo, node, None)
   805                 unknown = repo.status(wlock=wlock)[4]
   794                 unknown = repo.status()[4]
   806                 # only remove unknown files that we know we touched or
   795                 # only remove unknown files that we know we touched or
   807                 # created while patching
   796                 # created while patching
   808                 for f in unknown:
   797                 for f in unknown:
   809                     if f in all_files:
   798                     if f in all_files:
   810                         util.unlink(repo.wjoin(f))
   799                         util.unlink(repo.wjoin(f))
   818                 self.ui.write("Now at: %s\n" % top)
   807                 self.ui.write("Now at: %s\n" % top)
   819             return ret[0]
   808             return ret[0]
   820         finally:
   809         finally:
   821             del wlock
   810             del wlock
   822 
   811 
   823     def pop(self, repo, patch=None, force=False, update=True, all=False,
   812     def pop(self, repo, patch=None, force=False, update=True, all=False):
   824             wlock=None):
       
   825         def getfile(f, rev):
   813         def getfile(f, rev):
   826             t = repo.file(f).read(rev)
   814             t = repo.file(f).read(rev)
   827             repo.wfile(f, "w").write(t)
   815             repo.wfile(f, "w").write(t)
   828 
   816 
   829         if not wlock:
   817         wlock = repo.wlock()
   830             wlock = repo.wlock()
       
   831         try:
   818         try:
   832             if patch:
   819             if patch:
   833                 # index, rev, patch
   820                 # index, rev, patch
   834                 info = self.isapplied(patch)
   821                 info = self.isapplied(patch)
   835                 if not info:
   822                 if not info:
   897                             raise
   884                             raise
   898                     try: os.removedirs(os.path.dirname(repo.wjoin(f)))
   885                     try: os.removedirs(os.path.dirname(repo.wjoin(f)))
   899                     except: pass
   886                     except: pass
   900                     repo.dirstate.forget(f)
   887                     repo.dirstate.forget(f)
   901                 repo.dirstate.setparents(qp, revlog.nullid)
   888                 repo.dirstate.setparents(qp, revlog.nullid)
   902             self.strip(repo, rev, update=False, backup='strip', wlock=wlock)
   889             self.strip(repo, rev, update=False, backup='strip')
   903             del self.applied[start:end]
   890             del self.applied[start:end]
   904             if len(self.applied):
   891             if len(self.applied):
   905                 self.ui.write("Now at: %s\n" % self.applied[-1].name)
   892                 self.ui.write("Now at: %s\n" % self.applied[-1].name)
   906             else:
   893             else:
   907                 self.ui.write("Patch queue now empty\n")
   894                 self.ui.write("Patch queue now empty\n")
  1073                         message = "\n".join(message)
  1060                         message = "\n".join(message)
  1074                 else:
  1061                 else:
  1075                     message = msg
  1062                     message = msg
  1076 
  1063 
  1077                 self.strip(repo, top, update=False,
  1064                 self.strip(repo, top, update=False,
  1078                            backup='strip', wlock=wlock)
  1065                            backup='strip')
  1079                 n = repo.commit(filelist, message, changes[1], match=matchfn,
  1066                 n = repo.commit(filelist, message, changes[1], match=matchfn,
  1080                                 force=1, wlock=wlock)
  1067                                 force=1)
  1081                 self.applied[-1] = statusentry(revlog.hex(n), patchfn)
  1068                 self.applied[-1] = statusentry(revlog.hex(n), patchfn)
  1082                 self.applied_dirty = 1
  1069                 self.applied_dirty = 1
  1083                 self.removeundo(repo)
  1070                 self.removeundo(repo)
  1084             else:
  1071             else:
  1085                 self.printdiff(repo, patchparent, fp=patchf)
  1072                 self.printdiff(repo, patchparent, fp=patchf)
  1095                     try: os.removedirs(os.path.dirname(f))
  1082                     try: os.removedirs(os.path.dirname(f))
  1096                     except: pass
  1083                     except: pass
  1097                     # forget the file copies in the dirstate
  1084                     # forget the file copies in the dirstate
  1098                     # push should readd the files later on
  1085                     # push should readd the files later on
  1099                     repo.dirstate.forget(a)
  1086                     repo.dirstate.forget(a)
  1100                 self.pop(repo, force=True, wlock=wlock)
  1087                 self.pop(repo, force=True)
  1101                 self.push(repo, force=True, wlock=wlock)
  1088                 self.push(repo, force=True)
  1102         finally:
  1089         finally:
  1103             del wlock
  1090             del wlock
  1104 
  1091 
  1105     def init(self, repo, create=False):
  1092     def init(self, repo, create=False):
  1106         if not create and os.path.isdir(self.path):
  1093         if not create and os.path.isdir(self.path):
  1896     r = q.qrepo()
  1883     r = q.qrepo()
  1897     if r:
  1884     if r:
  1898         wlock = r.wlock()
  1885         wlock = r.wlock()
  1899         try:
  1886         try:
  1900             if r.dirstate[name] == 'r':
  1887             if r.dirstate[name] == 'r':
  1901                 r.undelete([name], wlock)
  1888                 r.undelete([name])
  1902             r.copy(patch, name, wlock)
  1889             r.copy(patch, name)
  1903             r.remove([patch], False, wlock)
  1890             r.remove([patch], False)
  1904         finally:
  1891         finally:
  1905             del wlock
  1892             del wlock
  1906 
  1893 
  1907     q.save_dirty()
  1894     q.save_dirty()
  1908 
  1895