hgext/mq.py
changeset 1810 7596611ab3d5
parent 1808 7036cd7f770d
child 1839 876e4e6ad82b
equal deleted inserted replaced
1809:ef53d200df3d 1810:7596611ab3d5
    28         self.full_series = []
    28         self.full_series = []
    29         self.applied_dirty = 0
    29         self.applied_dirty = 0
    30         self.series_dirty = 0
    30         self.series_dirty = 0
    31         self.series_path = os.path.join(self.path, "series")
    31         self.series_path = os.path.join(self.path, "series")
    32         self.status_path = os.path.join(self.path, "status")
    32         self.status_path = os.path.join(self.path, "status")
    33         
    33 
    34         s = self.series_path
    34         s = self.series_path
    35         if os.path.exists(s):
    35         if os.path.exists(s):
    36             self.full_series = self.opener(s).read().splitlines()
    36             self.full_series = self.opener(s).read().splitlines()
    37         self.read_series(self.full_series)
    37         self.read_series(self.full_series)
    38 
    38 
    63                     s = s.rstrip()
    63                     s = s.rstrip()
    64                     if len(s) > 0:
    64                     if len(s) > 0:
    65                         yield s
    65                         yield s
    66         self.series = []
    66         self.series = []
    67         self.series = [ x for x in matcher(list) ]
    67         self.series = [ x for x in matcher(list) ]
    68         
    68 
    69     def save_dirty(self):
    69     def save_dirty(self):
    70         if self.applied_dirty:
    70         if self.applied_dirty:
    71             if len(self.applied) > 0:
    71             if len(self.applied) > 0:
    72                 nl = "\n"
    72                 nl = "\n"
    73             else:
    73             else:
    84 
    84 
    85     def readheaders(self, patch):
    85     def readheaders(self, patch):
    86         def eatdiff(lines):
    86         def eatdiff(lines):
    87             while lines:
    87             while lines:
    88                 l = lines[-1]
    88                 l = lines[-1]
    89                 if l.startswith("diff -") or \
    89                 if (l.startswith("diff -") or
    90                    l.startswith("Index:") or \
    90                     l.startswith("Index:") or
    91                    l.startswith("==========="):
    91                     l.startswith("===========")):
    92                     del lines[-1]
    92                     del lines[-1]
    93                 else:
    93                 else:
    94                     break
    94                     break
    95         def eatempty(lines):
    95         def eatempty(lines):
    96             while lines:
    96             while lines:
   124                 elif not line.startswith("# ") and line:
   124                 elif not line.startswith("# ") and line:
   125                     message.append(line)
   125                     message.append(line)
   126                     format = None
   126                     format = None
   127             elif line == '# HG changeset patch':
   127             elif line == '# HG changeset patch':
   128                 format = "hgpatch"
   128                 format = "hgpatch"
   129             elif format != "tagdone" and \
   129             elif (format != "tagdone" and (line.startswith("Subject: ") or
   130                  (line.startswith("Subject: ") or \
   130                                            line.startswith("subject: "))):
   131                  line.startswith("subject: ")):
       
   132                 subject = line[9:]
   131                 subject = line[9:]
   133                 format = "tag"
   132                 format = "tag"
   134             elif format != "tagdone" and \
   133             elif (format != "tagdone" and (line.startswith("From: ") or
   135                  (line.startswith("From: ") or \
   134                                            line.startswith("from: "))):
   136                  line.startswith("from: ")):
       
   137                 user = line[6:]
   135                 user = line[6:]
   138                 format = "tag"
   136                 format = "tag"
   139             elif format == "tag" and line == "":
   137             elif format == "tag" and line == "":
   140                 # when looking for tags (subject: from: etc) they
   138                 # when looking for tags (subject: from: etc) they
   141                 # end once you find a blank line in the source
   139                 # end once you find a blank line in the source
   155             message.insert(0, subject)
   153             message.insert(0, subject)
   156         return (message, comments, user, diffstart > 1)
   154         return (message, comments, user, diffstart > 1)
   157 
   155 
   158     def mergeone(self, repo, mergeq, head, patch, rev, wlock):
   156     def mergeone(self, repo, mergeq, head, patch, rev, wlock):
   159         # first try just applying the patch
   157         # first try just applying the patch
   160         (err, n) = self.apply(repo, [ patch ], update_status=False, 
   158         (err, n) = self.apply(repo, [ patch ], update_status=False,
   161                               strict=True, merge=rev, wlock=wlock)
   159                               strict=True, merge=rev, wlock=wlock)
   162 
   160 
   163         if err == 0:
   161         if err == 0:
   164             return (err, n)
   162             return (err, n)
   165 
   163 
   193             comments = "\n".join(comments) + '\n\n'
   191             comments = "\n".join(comments) + '\n\n'
   194             patchf.write(comments)
   192             patchf.write(comments)
   195         commands.dodiff(patchf, self.ui, repo, head, n)
   193         commands.dodiff(patchf, self.ui, repo, head, n)
   196         patchf.close()
   194         patchf.close()
   197         return (0, n)
   195         return (0, n)
   198         
   196 
   199     def qparents(self, repo, rev=None):
   197     def qparents(self, repo, rev=None):
   200         if rev is None:
   198         if rev is None:
   201             (p1, p2) = repo.dirstate.parents()
   199             (p1, p2) = repo.dirstate.parents()
   202             if p2 == revlog.nullid:
   200             if p2 == revlog.nullid:
   203                 return p1
   201                 return p1
   251                 self.applied_dirty = 1
   249                 self.applied_dirty = 1
   252             if err:
   250             if err:
   253                 return (err, head)
   251                 return (err, head)
   254         return (0, head)
   252         return (0, head)
   255 
   253 
   256     def apply(self, repo, series, list=False, update_status=True, 
   254     def apply(self, repo, series, list=False, update_status=True,
   257               strict=False, patchdir=None, merge=None, wlock=None):
   255               strict=False, patchdir=None, merge=None, wlock=None):
   258         # TODO unify with commands.py
   256         # TODO unify with commands.py
   259         if not patchdir:
   257         if not patchdir:
   260             patchdir = self.path
   258             patchdir = self.path
   261         pwd = os.getcwd()
   259         pwd = os.getcwd()
   283                 if list:
   281                 if list:
   284                     message.append("\nimported patch %s" % patch)
   282                     message.append("\nimported patch %s" % patch)
   285                 message = '\n'.join(message)
   283                 message = '\n'.join(message)
   286 
   284 
   287             try:
   285             try:
   288                 f = os.popen("patch -p1 --no-backup-if-mismatch < '%s'" % 
   286                 f = os.popen("patch -p1 --no-backup-if-mismatch < '%s'" % (pf))
   289                                   (pf))
       
   290             except:
   287             except:
   291                 self.ui.warn("patch failed, unable to continue (try -v)\n")
   288                 self.ui.warn("patch failed, unable to continue (try -v)\n")
   292                 err = 1
   289                 err = 1
   293                 break
   290                 break
   294             files = []
   291             files = []
   297                 l = l.rstrip('\r\n');
   294                 l = l.rstrip('\r\n');
   298                 if self.ui.verbose:
   295                 if self.ui.verbose:
   299                     self.ui.warn(l + "\n")
   296                     self.ui.warn(l + "\n")
   300                 if l[:14] == 'patching file ':
   297                 if l[:14] == 'patching file ':
   301                     pf = os.path.normpath(l[14:])
   298                     pf = os.path.normpath(l[14:])
   302                     # when patch finds a space in the file name, it puts 
   299                     # when patch finds a space in the file name, it puts
   303                     # single quotes around the filename.  strip them off
   300                     # single quotes around the filename.  strip them off
   304                     if pf[0] == "'" and pf[-1] == "'":
   301                     if pf[0] == "'" and pf[-1] == "'":
   305                         pf = pf[1:-1]
   302                         pf = pf[1:-1]
   306                     if pf not in files:
   303                     if pf not in files:
   307                         files.append(pf)
   304                         files.append(pf)
   321                         printed_file = True
   318                         printed_file = True
   322                     self.ui.warn(l + '\n')
   319                     self.ui.warn(l + '\n')
   323             patcherr = f.close()
   320             patcherr = f.close()
   324 
   321 
   325             if merge and len(files) > 0:
   322             if merge and len(files) > 0:
   326                  # Mark as merged and update dirstate parent info
   323                 # Mark as merged and update dirstate parent info
   327                  repo.dirstate.update(repo.dirstate.filterfiles(files), 'm')
   324                 repo.dirstate.update(repo.dirstate.filterfiles(files), 'm')
   328                  p1, p2 = repo.dirstate.parents()
   325                 p1, p2 = repo.dirstate.parents()
   329                  repo.dirstate.setparents(p1, merge)
   326                 repo.dirstate.setparents(p1, merge)
   330             if len(files) > 0:
   327             if len(files) > 0:
   331                 commands.addremove_lock(self.ui, repo, files, 
   328                 commands.addremove_lock(self.ui, repo, files,
   332                                         opts={}, wlock=wlock)
   329                                         opts={}, wlock=wlock)
   333             n = repo.commit(files, message, user, force=1, lock=lock,
   330             n = repo.commit(files, message, user, force=1, lock=lock,
   334                             wlock=wlock)
   331                             wlock=wlock)
   335 
   332 
   336             if n == None:
   333             if n == None:
   368             sys.exit(1)
   365             sys.exit(1)
   369         i = self.find_series(patch)
   366         i = self.find_series(patch)
   370         del self.full_series[i]
   367         del self.full_series[i]
   371         self.read_series(self.full_series)
   368         self.read_series(self.full_series)
   372         self.series_dirty = 1
   369         self.series_dirty = 1
   373     
   370 
   374     def check_toppatch(self, repo):
   371     def check_toppatch(self, repo):
   375         if len(self.applied) > 0:
   372         if len(self.applied) > 0:
   376             (top, patch) = self.applied[-1].split(':')
   373             (top, patch) = self.applied[-1].split(':')
   377             top = revlog.bin(top)
   374             top = revlog.bin(top)
   378             pp = repo.dirstate.parents()
   375             pp = repo.dirstate.parents()
   391             self.check_localchanges(repo)
   388             self.check_localchanges(repo)
   392         self.check_toppatch(repo)
   389         self.check_toppatch(repo)
   393         wlock = repo.wlock()
   390         wlock = repo.wlock()
   394         insert = self.series_end()
   391         insert = self.series_end()
   395         if msg:
   392         if msg:
   396            n = repo.commit([], "[mq]: %s" % msg, force=True, wlock=wlock)
   393             n = repo.commit([], "[mq]: %s" % msg, force=True, wlock=wlock)
   397         else:
   394         else:
   398            n = repo.commit([], "New patch: %s" % patch, force=True, wlock=wlock)
   395             n = repo.commit([],
       
   396                             "New patch: %s" % patch, force=True, wlock=wlock)
   399         if n == None:
   397         if n == None:
   400             self.ui.warn("repo commit failed\n")
   398             self.ui.warn("repo commit failed\n")
   401             sys.exit(1)
   399             sys.exit(1)
   402         self.full_series[insert:insert] = [patch]
   400         self.full_series[insert:insert] = [patch]
   403         self.applied.append(revlog.hex(n) + ":" + patch)
   401         self.applied.append(revlog.hex(n) + ":" + patch)
   536             if rev not in r:
   534             if rev not in r:
   537                 saveheads.append(h)
   535                 saveheads.append(h)
   538                 for x in r:
   536                 for x in r:
   539                     if chlog.rev(x) > revnum:
   537                     if chlog.rev(x) > revnum:
   540                         savebases[x] = 1
   538                         savebases[x] = 1
   541                 
   539 
   542         # create a changegroup for all the branches we need to keep
   540         # create a changegroup for all the branches we need to keep
   543         if backup is "all":
   541         if backup is "all":
   544             backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip')
   542             backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip')
   545             bundle(backupch)
   543             bundle(backupch)
   546         if saveheads:
   544         if saveheads:
   555         if saveheads:
   553         if saveheads:
   556             self.ui.status("adding branch\n")
   554             self.ui.status("adding branch\n")
   557             commands.unbundle(self.ui, repo, chgrpfile, update=False)
   555             commands.unbundle(self.ui, repo, chgrpfile, update=False)
   558             if backup is not "strip":
   556             if backup is not "strip":
   559                 os.unlink(chgrpfile)
   557                 os.unlink(chgrpfile)
   560              
   558 
   561     def isapplied(self, patch):
   559     def isapplied(self, patch):
   562         """returns (index, rev, patch)"""
   560         """returns (index, rev, patch)"""
   563         for i in xrange(len(self.applied)):
   561         for i in xrange(len(self.applied)):
   564             p = self.applied[i]
   562             p = self.applied[i]
   565             a = p.split(':')
   563             a = p.split(':')
   585         else:
   583         else:
   586             self.ui.warn("patch %s not in series\n" % patch)
   584             self.ui.warn("patch %s not in series\n" % patch)
   587             sys.exit(1)
   585             sys.exit(1)
   588         return patch
   586         return patch
   589 
   587 
   590     def push(self, repo, patch=None, force=False, list=False, 
   588     def push(self, repo, patch=None, force=False, list=False,
   591              mergeq=None, wlock=None):
   589              mergeq=None, wlock=None):
   592         if not wlock:
   590         if not wlock:
   593             wlock = repo.wlock()
   591             wlock = repo.wlock()
   594         patch = self.lookup(patch) 
   592         patch = self.lookup(patch)
   595         if patch and self.isapplied(patch):
   593         if patch and self.isapplied(patch):
   596             self.ui.warn("patch %s is already applied\n" % patch)
   594             self.ui.warn("patch %s is already applied\n" % patch)
   597             sys.exit(1)
   595             sys.exit(1)
   598         if self.series_end() == len(self.series):
   596         if self.series_end() == len(self.series):
   599             self.ui.warn("File series fully applied\n")
   597             self.ui.warn("File series fully applied\n")
   600             sys.exit(1)
   598             sys.exit(1)
   601         if not force:
   599         if not force:
   602             self.check_localchanges(repo)
   600             self.check_localchanges(repo)
   603             
   601 
   604         self.applied_dirty = 1;
   602         self.applied_dirty = 1;
   605         start = self.series_end()
   603         start = self.series_end()
   606         if start > 0:
   604         if start > 0:
   607             self.check_toppatch(repo)
   605             self.check_toppatch(repo)
   608         if not patch:
   606         if not patch:
   615             ret = self.mergepatch(repo, mergeq, s, wlock)
   613             ret = self.mergepatch(repo, mergeq, s, wlock)
   616         else:
   614         else:
   617             ret = self.apply(repo, s, list, wlock=wlock)
   615             ret = self.apply(repo, s, list, wlock=wlock)
   618         top = self.applied[-1].split(':')[1]
   616         top = self.applied[-1].split(':')[1]
   619         if ret[0]:
   617         if ret[0]:
   620             self.ui.write("Errors during apply, please fix and refresh %s\n" % 
   618             self.ui.write("Errors during apply, please fix and refresh %s\n" %
   621                           top)
   619                           top)
   622         else:
   620         else:
   623             self.ui.write("Now at: %s\n" % top)
   621             self.ui.write("Now at: %s\n" % top)
   624         return ret[0]
   622         return ret[0]
   625 
   623 
   723             comments = "\n".join(comments) + '\n\n'
   721             comments = "\n".join(comments) + '\n\n'
   724             patchf.write(comments)
   722             patchf.write(comments)
   725 
   723 
   726         tip = repo.changelog.tip()
   724         tip = repo.changelog.tip()
   727         if top == tip:
   725         if top == tip:
   728             # if the top of our patch queue is also the tip, there is an 
   726             # if the top of our patch queue is also the tip, there is an
   729             # optimization here.  We update the dirstate in place and strip
   727             # optimization here.  We update the dirstate in place and strip
   730             # off the tip commit.  Then just commit the current directory
   728             # off the tip commit.  Then just commit the current directory
   731             # tree.  We can also send repo.commit the list of files
   729             # tree.  We can also send repo.commit the list of files
   732             # changed to speed up the diff
   730             # changed to speed up the diff
   733             #
   731             #
   734             # in short mode, we only diff the files included in the 
   732             # in short mode, we only diff the files included in the
   735             # patch already
   733             # patch already
   736             #
   734             #
   737             # this should really read:
   735             # this should really read:
   738             #(cc, dd, aa, aa2, uu) = repo.changes(tip, patchparent)
   736             #(cc, dd, aa, aa2, uu) = repo.changes(tip, patchparent)
   739             # but we do it backwards to take advantage of manifest/chlog
   737             # but we do it backwards to take advantage of manifest/chlog
   740             # caching against the next repo.changes call
   738             # caching against the next repo.changes call
   741             # 
   739             #
   742             (cc, aa, dd, aa2, uu) = repo.changes(patchparent, tip)
   740             (cc, aa, dd, aa2, uu) = repo.changes(patchparent, tip)
   743             if short:
   741             if short:
   744                 filelist = cc + aa + dd
   742                 filelist = cc + aa + dd
   745             else:
   743             else:
   746                 filelist = None
   744                 filelist = None
   775 
   773 
   776             c = list(util.unique(cc))
   774             c = list(util.unique(cc))
   777             r = list(util.unique(dd))
   775             r = list(util.unique(dd))
   778             a = list(util.unique(aa))
   776             a = list(util.unique(aa))
   779             filelist = list(util.unique(c + r + a ))
   777             filelist = list(util.unique(c + r + a ))
   780             commands.dodiff(patchf, self.ui, repo, patchparent, None, 
   778             commands.dodiff(patchf, self.ui, repo, patchparent, None,
   781                             filelist, changes=(c, a, r, [], u))
   779                             filelist, changes=(c, a, r, [], u))
   782             patchf.close()
   780             patchf.close()
   783 
   781 
   784             changes = repo.changelog.read(tip)
   782             changes = repo.changelog.read(tip)
   785             repo.dirstate.setparents(*cparents)
   783             repo.dirstate.setparents(*cparents)
   786             repo.dirstate.update(a, 'a')
   784             repo.dirstate.update(a, 'a')
   787             repo.dirstate.update(r, 'r')
   785             repo.dirstate.update(r, 'r')
   788             repo.dirstate.update(c, 'n')   
   786             repo.dirstate.update(c, 'n')
   789             repo.dirstate.forget(forget)
   787             repo.dirstate.forget(forget)
   790 
   788 
   791             if not message:
   789             if not message:
   792                 message = "patch queue: %s\n" % patch
   790                 message = "patch queue: %s\n" % patch
   793             else:
   791             else:
   817             start = self.series_end()
   815             start = self.series_end()
   818         else:
   816         else:
   819             start = self.series.index(patch) + 1
   817             start = self.series.index(patch) + 1
   820         for p in self.series[start:]:
   818         for p in self.series[start:]:
   821             self.ui.write("%s\n" % p)
   819             self.ui.write("%s\n" % p)
   822         
   820 
   823     def qseries(self, repo, missing=None):
   821     def qseries(self, repo, missing=None):
   824         start = self.series_end()
   822         start = self.series_end()
   825         if not missing:
   823         if not missing:
   826             for p in self.series[:start]:
   824             for p in self.series[:start]:
   827                 if self.ui.verbose:
   825                 if self.ui.verbose:
   836             for root, dirs, files in os.walk(self.path):
   834             for root, dirs, files in os.walk(self.path):
   837                 d = root[len(self.path) + 1:]
   835                 d = root[len(self.path) + 1:]
   838                 for f in files:
   836                 for f in files:
   839                     fl = os.path.join(d, f)
   837                     fl = os.path.join(d, f)
   840                     if (fl not in self.series and fl != "status" and
   838                     if (fl not in self.series and fl != "status" and
   841                        fl != "series" and not fl.startswith('.')):
   839                         fl != "series" and not fl.startswith('.')):
   842                         list.append(fl)
   840                         list.append(fl)
   843             list.sort()
   841             list.sort()
   844             if list:
   842             if list:
   845                 for x in list: 
   843                 for x in list:
   846                     if self.ui.verbose:
   844                     if self.ui.verbose:
   847                         self.ui.write("D ")
   845                         self.ui.write("D ")
   848                     self.ui.write("%s\n" % x)
   846                     self.ui.write("%s\n" % x)
   849 
   847 
   850     def issaveline(self, l):
   848     def issaveline(self, l):
   900                     update = True
   898                     update = True
   901                 else:
   899                 else:
   902                     update = False
   900                     update = False
   903                 self.strip(repo, rev, update=update, backup='strip')
   901                 self.strip(repo, rev, update=update, backup='strip')
   904         if qpp:
   902         if qpp:
   905             self.ui.warn("saved queue repository parents: %s %s\n" % 
   903             self.ui.warn("saved queue repository parents: %s %s\n" %
   906                          (hg.short(qpp[0]), hg.short(qpp[1])))
   904                          (hg.short(qpp[0]), hg.short(qpp[1])))
   907             if qupdate:
   905             if qupdate:
   908                 print "queue directory updating"
   906                 print "queue directory updating"
   909                 r = self.qrepo()
   907                 r = self.qrepo()
   910                 if not r:
   908                 if not r:
   917             self.ui.warn("save: no patches applied, exiting\n")
   915             self.ui.warn("save: no patches applied, exiting\n")
   918             return 1
   916             return 1
   919         if self.issaveline(self.applied[-1]):
   917         if self.issaveline(self.applied[-1]):
   920             self.ui.warn("status is already saved\n")
   918             self.ui.warn("status is already saved\n")
   921             return 1
   919             return 1
   922         
   920 
   923         ar = [ ':' + x for x in self.full_series ]
   921         ar = [ ':' + x for x in self.full_series ]
   924         if not msg:
   922         if not msg:
   925             msg = "hg patches saved state"
   923             msg = "hg patches saved state"
   926         else:
   924         else:
   927             msg = "hg patches: " + msg.rstrip('\r\n')
   925             msg = "hg patches: " + msg.rstrip('\r\n')
   928         r = self.qrepo()
   926         r = self.qrepo()
   929         if r:
   927         if r:
   930             pp = r.dirstate.parents()
   928             pp = r.dirstate.parents()
   931             msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1]))
   929             msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1]))
   932         msg += "\n\nPatch Data:\n"
   930         msg += "\n\nPatch Data:\n"
   933         text = msg + "\n".join(self.applied) + '\n' + (ar and "\n".join(ar) 
   931         text = msg + "\n".join(self.applied) + '\n' + (ar and "\n".join(ar)
   934                                                     + '\n' or "")
   932                                                        + '\n' or "")
   935         n = repo.commit(None, text, user=None, force=1)
   933         n = repo.commit(None, text, user=None, force=1)
   936         if not n:
   934         if not n:
   937             self.ui.warn("repo commit failed\n")
   935             self.ui.warn("repo commit failed\n")
   938             return 1
   936             return 1
   939         self.applied.append(revlog.hex(n) + ":" + '.hg.patches.save.line')
   937         self.applied.append(revlog.hex(n) + ":" + '.hg.patches.save.line')
   965     def appliedname(self, index):
   963     def appliedname(self, index):
   966         p = self.applied[index]
   964         p = self.applied[index]
   967         if not self.ui.verbose:
   965         if not self.ui.verbose:
   968             p = p.split(':')[1]
   966             p = p.split(':')[1]
   969         return p
   967         return p
   970         
   968 
   971     def top(self, repo):
   969     def top(self, repo):
   972         if len(self.applied):
   970         if len(self.applied):
   973             p = self.appliedname(-1)
   971             p = self.appliedname(-1)
   974             self.ui.write(p + '\n')
   972             self.ui.write(p + '\n')
   975         else:
   973         else:
   996             self.ui.warn("-n option not valid when importing multiple files\n")
   994             self.ui.warn("-n option not valid when importing multiple files\n")
   997             sys.exit(1)
   995             sys.exit(1)
   998         i = 0
   996         i = 0
   999         for filename in files:
   997         for filename in files:
  1000             if existing:
   998             if existing:
  1001                 if not patch: 
   999                 if not patch:
  1002                     patch = filename
  1000                     patch = filename
  1003                 if not os.path.isfile(os.path.join(self.path, patch)):
  1001                 if not os.path.isfile(os.path.join(self.path, patch)):
  1004                     self.ui.warn("patch %s does not exist\n" % patch)
  1002                     self.ui.warn("patch %s does not exist\n" % patch)
  1005                     sys.exit(1)
  1003                     sys.exit(1)
  1006             else:
  1004             else:
  1045     return 0
  1043     return 0
  1046 
  1044 
  1047 def qimport(ui, repo, *filename, **opts):
  1045 def qimport(ui, repo, *filename, **opts):
  1048     """import a patch"""
  1046     """import a patch"""
  1049     q = repomap[repo]
  1047     q = repomap[repo]
  1050     q.qimport(repo, filename, patch=opts['name'], 
  1048     q.qimport(repo, filename, patch=opts['name'],
  1051                           existing=opts['existing'], force=opts['force'])
  1049               existing=opts['existing'], force=opts['force'])
  1052     q.save_dirty()
  1050     q.save_dirty()
  1053     return 0
  1051     return 0
  1054 
  1052 
  1055 def init(ui, repo, **opts):
  1053 def init(ui, repo, **opts):
  1056     """init a new queue repository"""
  1054     """init a new queue repository"""
  1125                 max = index
  1123                 max = index
  1126                 maxname = f
  1124                 maxname = f
  1127     if maxname:
  1125     if maxname:
  1128         return (os.path.join(dir, maxname), max)
  1126         return (os.path.join(dir, maxname), max)
  1129     return (None, None)
  1127     return (None, None)
  1130     
  1128 
  1131 def savename(path):
  1129 def savename(path):
  1132     (last, index) = lastsavename(path)
  1130     (last, index) = lastsavename(path)
  1133     if last is None:
  1131     if last is None:
  1134         index = 0
  1132         index = 0
  1135     newpath = path + ".%d" % (index + 1)
  1133     newpath = path + ".%d" % (index + 1)
  1137 
  1135 
  1138 def push(ui, repo, patch=None, **opts):
  1136 def push(ui, repo, patch=None, **opts):
  1139     """push the next patch onto the stack"""
  1137     """push the next patch onto the stack"""
  1140     q = repomap[repo]
  1138     q = repomap[repo]
  1141     mergeq = None
  1139     mergeq = None
  1142         
  1140 
  1143     if opts['all']:
  1141     if opts['all']:
  1144         patch = q.series[-1]
  1142         patch = q.series[-1]
  1145     if opts['merge']:
  1143     if opts['merge']:
  1146         if opts['name']:
  1144         if opts['name']:
  1147             newpath = opts['name']
  1145             newpath = opts['name']
  1148         else:
  1146         else:
  1149             newpath,i = lastsavename(q.path)
  1147             newpath, i = lastsavename(q.path)
  1150         if not newpath:
  1148         if not newpath:
  1151             ui.warn("no saved queues found, please use -n\n")
  1149             ui.warn("no saved queues found, please use -n\n")
  1152             return 1
  1150             return 1
  1153         mergeq = queue(ui, repo.join(""), newpath)
  1151         mergeq = queue(ui, repo.join(""), newpath)
  1154         ui.warn("merging with queue at: %s\n" % mergeq.path)
  1152         ui.warn("merging with queue at: %s\n" % mergeq.path)
  1155     ret = q.push(repo, patch, force=opts['force'], list=opts['list'], 
  1153     ret = q.push(repo, patch, force=opts['force'], list=opts['list'],
  1156                  mergeq=mergeq)
  1154                  mergeq=mergeq)
  1157     q.save_dirty()
  1155     q.save_dirty()
  1158     return ret
  1156     return ret
  1159 
  1157 
  1160 def pop(ui, repo, patch=None, **opts):
  1158 def pop(ui, repo, patch=None, **opts):
  1175 def restore(ui, repo, rev, **opts):
  1173 def restore(ui, repo, rev, **opts):
  1176     """restore the queue state saved by a rev"""
  1174     """restore the queue state saved by a rev"""
  1177     rev = repo.lookup(rev)
  1175     rev = repo.lookup(rev)
  1178     q = repomap[repo]
  1176     q = repomap[repo]
  1179     q.restore(repo, rev, delete=opts['delete'],
  1177     q.restore(repo, rev, delete=opts['delete'],
  1180                           qupdate=opts['update'])
  1178               qupdate=opts['update'])
  1181     q.save_dirty()
  1179     q.save_dirty()
  1182     return 0
  1180     return 0
  1183 
  1181 
  1184 def save(ui, repo, **opts):
  1182 def save(ui, repo, **opts):
  1185     """save current queue state"""
  1183     """save current queue state"""
  1193         if opts['name']:
  1191         if opts['name']:
  1194             newpath = os.path.join(q.basepath, opts['name'])
  1192             newpath = os.path.join(q.basepath, opts['name'])
  1195             if os.path.exists(newpath):
  1193             if os.path.exists(newpath):
  1196                 if not os.path.isdir(newpath):
  1194                 if not os.path.isdir(newpath):
  1197                     ui.warn("destination %s exists and is not a directory\n" %
  1195                     ui.warn("destination %s exists and is not a directory\n" %
  1198                              newpath)
  1196                             newpath)
  1199                     sys.exit(1)
  1197                     sys.exit(1)
  1200                 if not opts['force']:
  1198                 if not opts['force']:
  1201                     ui.warn("destination %s exists, use -f to force\n" %
  1199                     ui.warn("destination %s exists, use -f to force\n" %
  1202                              newpath)
  1200                             newpath)
  1203                     sys.exit(1)
  1201                     sys.exit(1)
  1204         else:
  1202         else:
  1205             newpath = savename(path)
  1203             newpath = savename(path)
  1206         ui.warn("copy %s to %s\n" % (path, newpath))
  1204         ui.warn("copy %s to %s\n" % (path, newpath))
  1207         util.copyfiles(path, newpath)
  1205         util.copyfiles(path, newpath)
  1209         try:
  1207         try:
  1210             os.unlink(q.status_path)
  1208             os.unlink(q.status_path)
  1211         except:
  1209         except:
  1212             pass
  1210             pass
  1213     return 0
  1211     return 0
  1214     
  1212 
  1215 def strip(ui, repo, rev, **opts):
  1213 def strip(ui, repo, rev, **opts):
  1216     """strip a revision and all later revs on the same branch"""
  1214     """strip a revision and all later revs on the same branch"""
  1217     rev = repo.lookup(rev)
  1215     rev = repo.lookup(rev)
  1218     backup = 'all'
  1216     backup = 'all'
  1219     if opts['backup']:
  1217     if opts['backup']:
  1230 
  1228 
  1231 def reposetup(ui, repo):
  1229 def reposetup(ui, repo):
  1232     repomap[repo] = queue(ui, repo.join(""))
  1230     repomap[repo] = queue(ui, repo.join(""))
  1233 
  1231 
  1234 cmdtable = {
  1232 cmdtable = {
  1235     "qapplied": (applied, [], "hg qapplied [patch]"),
  1233     "qapplied": (applied, [], 'hg qapplied [patch]'),
  1236     "qcommit|qci": (commit,
  1234     "qcommit|qci":
  1237                     [('A', 'addremove', None, _('run addremove during commit')),
  1235         (commit,
  1238                      ('I', 'include', [], _('include names matching the given patterns')),
  1236          [('A', 'addremove', None, _('run addremove during commit')),
  1239                      ('X', 'exclude', [], _('exclude names matching the given patterns')),
  1237           ('I', 'include', [], _('include names matching the given patterns')),
  1240                      ('m', 'message', "", _('use <text> as commit message')),
  1238           ('X', 'exclude', [], _('exclude names matching the given patterns')),
  1241                      ('l', 'logfile', "", _('read the commit message from <file>')),
  1239           ('m', 'message', '', _('use <text> as commit message')),
  1242                      ('d', 'date', "", _('record datecode as commit date')),
  1240           ('l', 'logfile', '', _('read the commit message from <file>')),
  1243                      ('u', 'user', "", _('record user as commiter'))],
  1241           ('d', 'date', '', _('record datecode as commit date')),
  1244                     "hg qcommit [options] [files]"),
  1242           ('u', 'user', '', _('record user as commiter'))],
  1245     "^qdiff": (diff, [], "hg qdiff [files]"),
  1243          'hg qcommit [options] [files]'),
  1246     "qdelete": (delete, [], "hg qdelete [patch]"),
  1244     "^qdiff": (diff, [], 'hg qdiff [files]'),
  1247     "^qimport": (qimport, [('e', 'existing', None, 'import file in patch dir'),
  1245     "qdelete": (delete, [], 'hg qdelete [patch]'),
  1248                            ('n', 'name', "", 'patch file name'),
  1246     "^qimport":
  1249                            ('f', 'force', None, 'overwrite existing files')],
  1247         (qimport,
  1250                  "hg qimport"),
  1248          [('e', 'existing', None, 'import file in patch dir'),
  1251     "^qinit": (init, [('c', 'create-repo', None, 'create patch repository')],
  1249           ('n', 'name', '', 'patch file name'),
  1252                "hg [-c] qinit"),
  1250           ('f', 'force', None, 'overwrite existing files')],
  1253     "qnew": (new, [('m', 'message', "", 'commit message'),
  1251          'hg qimport'),
  1254                    ('f', 'force', None, 'force')], 
  1252     "^qinit":
  1255                    "hg qnew [-m message ] patch"),
  1253         (init,
  1256     "qnext": (next, [], "hg qnext"),
  1254          [('c', 'create-repo', None, 'create patch repository')],
  1257     "qprev": (prev, [], "hg qprev"),
  1255          'hg [-c] qinit'),
  1258     "^qpop": (pop, [('a', 'all', None, 'pop all patches'),
  1256     "qnew":
  1259                      ('n', 'name', "", 'queue name to pop'),
  1257         (new,
  1260                    ('f', 'force', None, 'forget any local changes')], 
  1258          [('m', 'message', '', 'commit message'),
  1261             'hg qpop [options] [patch/index]'),
  1259           ('f', 'force', None, 'force')],
  1262     "^qpush": (push, [('f', 'force', None, 'apply if the patch has rejects'),
  1260          'hg qnew [-m message ] patch'),
  1263                      ('l', 'list', None, 'list patch name in commit text'),
  1261     "qnext": (next, [], 'hg qnext'),
  1264                      ('a', 'all', None, 'apply all patches'),
  1262     "qprev": (prev, [], 'hg qprev'),
  1265                      ('m', 'merge', None, 'merge from another queue'),
  1263     "^qpop":
  1266                      ('n', 'name', "", 'merge queue name')],
  1264         (pop,
  1267              'hg qpush [options] [patch/index]'),
  1265          [('a', 'all', None, 'pop all patches'),
  1268     "^qrefresh": (refresh, [('s', 'short', None, 'short refresh')],"hg qrefresh"),
  1266           ('n', 'name', '', 'queue name to pop'),
  1269     "qrestore": (restore, [('d', 'delete', None, 'delete save entry'),
  1267           ('f', 'force', None, 'forget any local changes')],
  1270                            ('u', 'update', None, 'update queue working dir')], 
  1268          'hg qpop [options] [patch/index]'),
  1271                  'hg qrestore rev'),
  1269     "^qpush":
  1272     "qsave": (save, [('m', 'message', "", 'commit message'),
  1270         (push,
  1273                      ('c', 'copy', None, 'copy patch directory'),
  1271          [('f', 'force', None, 'apply if the patch has rejects'),
  1274                      ('n', 'name', "", 'copy directory name'),
  1272           ('l', 'list', None, 'list patch name in commit text'),
  1275                      ('e', 'empty', None, 'clear queue status file'),
  1273           ('a', 'all', None, 'apply all patches'),
  1276                      ('f', 'force', None, 'force copy')], 'hg qsave'),
  1274           ('m', 'merge', None, 'merge from another queue'),
  1277     "qseries": (series, [('m', 'missing', None, 'print patches not in series')],
  1275           ('n', 'name', '', 'merge queue name')],
  1278                 "hg qseries"),
  1276          'hg qpush [options] [patch/index]'),
  1279     "^strip": (strip, [('f', 'force', None, 'force multi-head removal'),
  1277     "^qrefresh":
  1280                        ('b', 'backup', None, 'bundle unrelated changesets'),
  1278         (refresh,
  1281                        ('n', 'nobackup', None, 'no backups')], "hg strip rev"),
  1279          [('s', 'short', None, 'short refresh')],
  1282     "qtop": (top, [], "hg qtop"),
  1280          'hg qrefresh'),
  1283     "qunapplied": (unapplied, [], "hg qunapplied [patch]"),
  1281     "qrestore":
  1284     "qversion": (version, [], "hg qversion")
  1282         (restore,
       
  1283          [('d', 'delete', None, 'delete save entry'),
       
  1284           ('u', 'update', None, 'update queue working dir')],
       
  1285          'hg qrestore rev'),
       
  1286     "qsave":
       
  1287         (save,
       
  1288          [('m', 'message', '', 'commit message'),
       
  1289           ('c', 'copy', None, 'copy patch directory'),
       
  1290           ('n', 'name', '', 'copy directory name'),
       
  1291           ('e', 'empty', None, 'clear queue status file'),
       
  1292           ('f', 'force', None, 'force copy')],
       
  1293          'hg qsave'),
       
  1294     "qseries":
       
  1295         (series,
       
  1296          [('m', 'missing', None, 'print patches not in series')],
       
  1297          'hg qseries'),
       
  1298     "^strip":
       
  1299         (strip,
       
  1300          [('f', 'force', None, 'force multi-head removal'),
       
  1301           ('b', 'backup', None, 'bundle unrelated changesets'),
       
  1302           ('n', 'nobackup', None, 'no backups')],
       
  1303          'hg strip rev'),
       
  1304     "qtop": (top, [], 'hg qtop'),
       
  1305     "qunapplied": (unapplied, [], 'hg qunapplied [patch]'),
       
  1306     "qversion": (version, [], 'hg qversion')
  1285 }
  1307 }
  1286 
  1308