hgext/mq.py
changeset 10282 08a0f04b56bd
parent 10276 6109a02c682b
child 10359 ec02cf8d1628
equal deleted inserted replaced
10281:e7d3b509af8b 10282:08a0f04b56bd
   374         if self.active_guards is None:
   374         if self.active_guards is None:
   375             self.active_guards = []
   375             self.active_guards = []
   376             try:
   376             try:
   377                 guards = self.opener(self.guards_path).read().split()
   377                 guards = self.opener(self.guards_path).read().split()
   378             except IOError, err:
   378             except IOError, err:
   379                 if err.errno != errno.ENOENT: raise
   379                 if err.errno != errno.ENOENT:
       
   380                     raise
   380                 guards = []
   381                 guards = []
   381             for i, guard in enumerate(guards):
   382             for i, guard in enumerate(guards):
   382                 bad = self.check_guard(guard)
   383                 bad = self.check_guard(guard)
   383                 if bad:
   384                 if bad:
   384                     self.ui.warn('%s:%d: %s\n' %
   385                     self.ui.warn('%s:%d: %s\n' %
   448         def write_list(items, path):
   449         def write_list(items, path):
   449             fp = self.opener(path, 'w')
   450             fp = self.opener(path, 'w')
   450             for i in items:
   451             for i in items:
   451                 fp.write("%s\n" % i)
   452                 fp.write("%s\n" % i)
   452             fp.close()
   453             fp.close()
   453         if self.applied_dirty: write_list(map(str, self.applied), self.status_path)
   454         if self.applied_dirty:
   454         if self.series_dirty: write_list(self.full_series, self.series_path)
   455             write_list(map(str, self.applied), self.status_path)
   455         if self.guards_dirty: write_list(self.active_guards, self.guards_path)
   456         if self.series_dirty:
       
   457             write_list(self.full_series, self.series_path)
       
   458         if self.guards_dirty:
       
   459             write_list(self.active_guards, self.guards_path)
   456 
   460 
   457     def removeundo(self, repo):
   461     def removeundo(self, repo):
   458         undo = repo.sjoin('undo')
   462         undo = repo.sjoin('undo')
   459         if not os.path.exists(undo):
   463         if not os.path.exists(undo):
   460             return
   464             return
   480             for chunk in chunks:
   484             for chunk in chunks:
   481                 write(chunk)
   485                 write(chunk)
   482 
   486 
   483     def mergeone(self, repo, mergeq, head, patch, rev, diffopts):
   487     def mergeone(self, repo, mergeq, head, patch, rev, diffopts):
   484         # first try just applying the patch
   488         # first try just applying the patch
   485         (err, n) = self.apply(repo, [ patch ], update_status=False,
   489         (err, n) = self.apply(repo, [patch], update_status=False,
   486                               strict=True, merge=rev)
   490                               strict=True, merge=rev)
   487 
   491 
   488         if err == 0:
   492         if err == 0:
   489             return (err, n)
   493             return (err, n)
   490 
   494 
   527             if len(self.applied) == 0:
   531             if len(self.applied) == 0:
   528                 return None
   532                 return None
   529             return bin(self.applied[-1].rev)
   533             return bin(self.applied[-1].rev)
   530         pp = repo.changelog.parents(rev)
   534         pp = repo.changelog.parents(rev)
   531         if pp[1] != nullid:
   535         if pp[1] != nullid:
   532             arevs = [ x.rev for x in self.applied ]
   536             arevs = [x.rev for x in self.applied]
   533             p0 = hex(pp[0])
   537             p0 = hex(pp[0])
   534             p1 = hex(pp[1])
   538             p1 = hex(pp[1])
   535             if p0 in arevs:
   539             if p0 in arevs:
   536                 return pp[0]
   540                 return pp[0]
   537             if p1 in arevs:
   541             if p1 in arevs:
   862                             p.write(chunk)
   866                             p.write(chunk)
   863                     p.close()
   867                     p.close()
   864                     wlock.release()
   868                     wlock.release()
   865                     wlock = None
   869                     wlock = None
   866                     r = self.qrepo()
   870                     r = self.qrepo()
   867                     if r: r.add([patchfn])
   871                     if r:
       
   872                         r.add([patchfn])
   868                 except:
   873                 except:
   869                     repo.rollback()
   874                     repo.rollback()
   870                     raise
   875                     raise
   871             except Exception:
   876             except Exception:
   872                 patchpath = self.join(patchfn)
   877                 patchpath = self.join(patchfn)
   939             return patch
   944             return patch
   940 
   945 
   941         if not os.path.isfile(self.join(patch)):
   946         if not os.path.isfile(self.join(patch)):
   942             try:
   947             try:
   943                 sno = int(patch)
   948                 sno = int(patch)
   944             except(ValueError, OverflowError):
   949             except (ValueError, OverflowError):
   945                 pass
   950                 pass
   946             else:
   951             else:
   947                 if -len(self.series) <= sno < len(self.series):
   952                 if -len(self.series) <= sno < len(self.series):
   948                     return self.series[sno]
   953                     return self.series[sno]
   949 
   954 
   955                 if minus >= 0:
   960                 if minus >= 0:
   956                     res = partial_name(patch[:minus])
   961                     res = partial_name(patch[:minus])
   957                     if res:
   962                     if res:
   958                         i = self.series.index(res)
   963                         i = self.series.index(res)
   959                         try:
   964                         try:
   960                             off = int(patch[minus+1:] or 1)
   965                             off = int(patch[minus + 1:] or 1)
   961                         except(ValueError, OverflowError):
   966                         except (ValueError, OverflowError):
   962                             pass
   967                             pass
   963                         else:
   968                         else:
   964                             if i - off >= 0:
   969                             if i - off >= 0:
   965                                 return self.series[i - off]
   970                                 return self.series[i - off]
   966                 plus = patch.rfind('+')
   971                 plus = patch.rfind('+')
   967                 if plus >= 0:
   972                 if plus >= 0:
   968                     res = partial_name(patch[:plus])
   973                     res = partial_name(patch[:plus])
   969                     if res:
   974                     if res:
   970                         i = self.series.index(res)
   975                         i = self.series.index(res)
   971                         try:
   976                         try:
   972                             off = int(patch[plus+1:] or 1)
   977                             off = int(patch[plus + 1:] or 1)
   973                         except(ValueError, OverflowError):
   978                         except (ValueError, OverflowError):
   974                             pass
   979                             pass
   975                         else:
   980                         else:
   976                             if i + off < len(self.series):
   981                             if i + off < len(self.series):
   977                                 return self.series[i + off]
   982                                 return self.series[i + off]
   978         raise util.Abort(_("patch %s not in series") % patch)
   983         raise util.Abort(_("patch %s not in series") % patch)
  1104                 self.ui.warn(_("qpop: %s is already at the top\n") % patch)
  1109                 self.ui.warn(_("qpop: %s is already at the top\n") % patch)
  1105                 return
  1110                 return
  1106 
  1111 
  1107             if not update:
  1112             if not update:
  1108                 parents = repo.dirstate.parents()
  1113                 parents = repo.dirstate.parents()
  1109                 rr = [ bin(x.rev) for x in self.applied ]
  1114                 rr = [bin(x.rev) for x in self.applied]
  1110                 for p in parents:
  1115                 for p in parents:
  1111                     if p in rr:
  1116                     if p in rr:
  1112                         self.ui.warn(_("qpop: forcing dirstate update\n"))
  1117                         self.ui.warn(_("qpop: forcing dirstate update\n"))
  1113                         update = True
  1118                         update = True
  1114             else:
  1119             else:
  1304                         # remember the copies between patchparent and tip
  1309                         # remember the copies between patchparent and tip
  1305                         for dst in aaa:
  1310                         for dst in aaa:
  1306                             f = repo.file(dst)
  1311                             f = repo.file(dst)
  1307                             src = f.renamed(man[dst])
  1312                             src = f.renamed(man[dst])
  1308                             if src:
  1313                             if src:
  1309                                 copies.setdefault(src[0], []).extend(copies.get(dst, []))
  1314                                 copies.setdefault(src[0], []).extend(
       
  1315                                     copies.get(dst, []))
  1310                                 if dst in a:
  1316                                 if dst in a:
  1311                                     copies[src[0]].append(dst)
  1317                                     copies[src[0]].append(dst)
  1312                             # we can't copy a file created by the patch itself
  1318                             # we can't copy a file created by the patch itself
  1313                             if dst in copies:
  1319                             if dst in copies:
  1314                                 del copies[dst]
  1320                                 del copies[dst]
  1438         applied = set([p.name for p in self.applied])
  1444         applied = set([p.name for p in self.applied])
  1439         if length is None:
  1445         if length is None:
  1440             length = len(self.series) - start
  1446             length = len(self.series) - start
  1441         if not missing:
  1447         if not missing:
  1442             if self.ui.verbose:
  1448             if self.ui.verbose:
  1443                 idxwidth = len(str(start+length - 1))
  1449                 idxwidth = len(str(start + length - 1))
  1444             for i in xrange(start, start+length):
  1450             for i in xrange(start, start + length):
  1445                 patch = self.series[i]
  1451                 patch = self.series[i]
  1446                 if patch in applied:
  1452                 if patch in applied:
  1447                     stat = 'A'
  1453                     stat = 'A'
  1448                 elif self.pushable(i)[0]:
  1454                 elif self.pushable(i)[0]:
  1449                     stat = 'U'
  1455                     stat = 'U'
  1491             if line == 'Patch Data:':
  1497             if line == 'Patch Data:':
  1492                 datastart = i + 1
  1498                 datastart = i + 1
  1493             elif line.startswith('Dirstate:'):
  1499             elif line.startswith('Dirstate:'):
  1494                 l = line.rstrip()
  1500                 l = line.rstrip()
  1495                 l = l[10:].split(' ')
  1501                 l = l[10:].split(' ')
  1496                 qpp = [ bin(x) for x in l ]
  1502                 qpp = [bin(x) for x in l]
  1497             elif datastart != None:
  1503             elif datastart != None:
  1498                 l = line.rstrip()
  1504                 l = line.rstrip()
  1499                 se = statusentry(l)
  1505                 se = statusentry(l)
  1500                 file_ = se.name
  1506                 file_ = se.name
  1501                 if se.rev:
  1507                 if se.rev:
  1540             return 1
  1546             return 1
  1541         if self.issaveline(self.applied[-1]):
  1547         if self.issaveline(self.applied[-1]):
  1542             self.ui.warn(_("status is already saved\n"))
  1548             self.ui.warn(_("status is already saved\n"))
  1543             return 1
  1549             return 1
  1544 
  1550 
  1545         ar = [ ':' + x for x in self.full_series ]
  1551         ar = [':' + x for x in self.full_series]
  1546         if not msg:
  1552         if not msg:
  1547             msg = _("hg patches saved state")
  1553             msg = _("hg patches saved state")
  1548         else:
  1554         else:
  1549             msg = "hg patches: " + msg.rstrip('\r\n')
  1555             msg = "hg patches: " + msg.rstrip('\r\n')
  1550         r = self.qrepo()
  1556         r = self.qrepo()
  1692                     raise util.Abort(_("patch %s does not exist") % patchname)
  1698                     raise util.Abort(_("patch %s does not exist") % patchname)
  1693             else:
  1699             else:
  1694                 try:
  1700                 try:
  1695                     if filename == '-':
  1701                     if filename == '-':
  1696                         if not patchname:
  1702                         if not patchname:
  1697                             raise util.Abort(_('need --name to import a patch from -'))
  1703                             raise util.Abort(
       
  1704                                 _('need --name to import a patch from -'))
  1698                         text = sys.stdin.read()
  1705                         text = sys.stdin.read()
  1699                     else:
  1706                     else:
  1700                         text = url.open(self.ui, filename).read()
  1707                         text = url.open(self.ui, filename).read()
  1701                 except (OSError, IOError):
  1708                 except (OSError, IOError):
  1702                     raise util.Abort(_("unable to read %s") % filename)
  1709                     raise util.Abort(_("unable to read %s") % filename)
  1910 
  1917 
  1911 def commit(ui, repo, *pats, **opts):
  1918 def commit(ui, repo, *pats, **opts):
  1912     """commit changes in the queue repository"""
  1919     """commit changes in the queue repository"""
  1913     q = repo.mq
  1920     q = repo.mq
  1914     r = q.qrepo()
  1921     r = q.qrepo()
  1915     if not r: raise util.Abort('no queue repository')
  1922     if not r:
       
  1923         raise util.Abort('no queue repository')
  1916     commands.commit(r.ui, r, *pats, **opts)
  1924     commands.commit(r.ui, r, *pats, **opts)
  1917 
  1925 
  1918 def series(ui, repo, **opts):
  1926 def series(ui, repo, **opts):
  1919     """print the entire series file"""
  1927     """print the entire series file"""
  1920     repo.mq.qseries(repo, missing=opts['missing'], summary=opts['summary'])
  1928     repo.mq.qseries(repo, missing=opts['missing'], summary=opts['summary'])
  1923 def top(ui, repo, **opts):
  1931 def top(ui, repo, **opts):
  1924     """print the name of the current patch"""
  1932     """print the name of the current patch"""
  1925     q = repo.mq
  1933     q = repo.mq
  1926     t = q.applied and q.series_end(True) or 0
  1934     t = q.applied and q.series_end(True) or 0
  1927     if t:
  1935     if t:
  1928         return q.qseries(repo, start=t-1, length=1, status='A',
  1936         return q.qseries(repo, start=t - 1, length=1, status='A',
  1929                          summary=opts.get('summary'))
  1937                          summary=opts.get('summary'))
  1930     else:
  1938     else:
  1931         ui.write(_("no patches applied\n"))
  1939         ui.write(_("no patches applied\n"))
  1932         return 1
  1940         return 1
  1933 
  1941 
  1948         ui.write(_("only one patch applied\n"))
  1956         ui.write(_("only one patch applied\n"))
  1949         return 1
  1957         return 1
  1950     if not l:
  1958     if not l:
  1951         ui.write(_("no patches applied\n"))
  1959         ui.write(_("no patches applied\n"))
  1952         return 1
  1960         return 1
  1953     return q.qseries(repo, start=l-2, length=1, status='A',
  1961     return q.qseries(repo, start=l - 2, length=1, status='A',
  1954                      summary=opts.get('summary'))
  1962                      summary=opts.get('summary'))
  1955 
  1963 
  1956 def setupheaderopts(ui, opts):
  1964 def setupheaderopts(ui, opts):
  1957     if not opts.get('user') and opts.get('currentuser'):
  1965     if not opts.get('user') and opts.get('currentuser'):
  1958         opts['user'] = ui.username()
  1966         opts['user'] = ui.username()
  1982     format. Read the diffs help topic for more information on why this
  1990     format. Read the diffs help topic for more information on why this
  1983     is important for preserving permission changes and copy/rename
  1991     is important for preserving permission changes and copy/rename
  1984     information.
  1992     information.
  1985     """
  1993     """
  1986     msg = cmdutil.logmessage(opts)
  1994     msg = cmdutil.logmessage(opts)
  1987     def getmsg(): return ui.edit(msg, ui.username())
  1995     def getmsg():
       
  1996         return ui.edit(msg, ui.username())
  1988     q = repo.mq
  1997     q = repo.mq
  1989     opts['msg'] = msg
  1998     opts['msg'] = msg
  1990     if opts.get('edit'):
  1999     if opts.get('edit'):
  1991         opts['msg'] = getmsg
  2000         opts['msg'] = getmsg
  1992     else:
  2001     else:
  2270         absdest = q.join(name)
  2279         absdest = q.join(name)
  2271     if os.path.exists(absdest):
  2280     if os.path.exists(absdest):
  2272         raise util.Abort(_('%s already exists') % absdest)
  2281         raise util.Abort(_('%s already exists') % absdest)
  2273 
  2282 
  2274     if name in q.series:
  2283     if name in q.series:
  2275         raise util.Abort(_('A patch named %s already exists in the series file') % name)
  2284         raise util.Abort(
       
  2285             _('A patch named %s already exists in the series file') % name)
  2276 
  2286 
  2277     if ui.verbose:
  2287     if ui.verbose:
  2278         ui.write('renaming %s to %s\n' % (patch, name))
  2288         ui.write('renaming %s to %s\n' % (patch, name))
  2279     i = q.find_series(patch)
  2289     i = q.find_series(patch)
  2280     guards = q.guard_re.findall(q.full_series[i])
  2290     guards = q.guard_re.findall(q.full_series[i])
  2462                 ui.status(_('popping guarded patches\n'))
  2472                 ui.status(_('popping guarded patches\n'))
  2463                 popped = True
  2473                 popped = True
  2464                 if i == 0:
  2474                 if i == 0:
  2465                     q.pop(repo, all=True)
  2475                     q.pop(repo, all=True)
  2466                 else:
  2476                 else:
  2467                     q.pop(repo, i-1)
  2477                     q.pop(repo, i - 1)
  2468                 break
  2478                 break
  2469     if popped:
  2479     if popped:
  2470         try:
  2480         try:
  2471             if reapply:
  2481             if reapply:
  2472                 ui.status(_('reapplying unguarded patches\n'))
  2482                 ui.status(_('reapplying unguarded patches\n'))
  2573 
  2583 
  2574             qbase = cl.rev(qbasenode)
  2584             qbase = cl.rev(qbasenode)
  2575             start = lrev + 1
  2585             start = lrev + 1
  2576             if start < qbase:
  2586             if start < qbase:
  2577                 # update the cache (excluding the patches) and save it
  2587                 # update the cache (excluding the patches) and save it
  2578                 self._updatebranchcache(partial, lrev+1, qbase)
  2588                 self._updatebranchcache(partial, lrev + 1, qbase)
  2579                 self._writebranchcache(partial, cl.node(qbase-1), qbase-1)
  2589                 self._writebranchcache(partial, cl.node(qbase - 1), qbase - 1)
  2580                 start = qbase
  2590                 start = qbase
  2581             # if start = qbase, the cache is as updated as it should be.
  2591             # if start = qbase, the cache is as updated as it should be.
  2582             # if start > qbase, the cache includes (part of) the patches.
  2592             # if start > qbase, the cache includes (part of) the patches.
  2583             # we might as well use it, but we won't save it.
  2593             # we might as well use it, but we won't save it.
  2584 
  2594 
  2589 
  2599 
  2590     if repo.local():
  2600     if repo.local():
  2591         repo.__class__ = mqrepo
  2601         repo.__class__ = mqrepo
  2592 
  2602 
  2593 def mqimport(orig, ui, repo, *args, **kwargs):
  2603 def mqimport(orig, ui, repo, *args, **kwargs):
  2594     if hasattr(repo, 'abort_if_wdir_patched') and not kwargs.get('no_commit', False):
  2604     if (hasattr(repo, 'abort_if_wdir_patched')
       
  2605         and not kwargs.get('no_commit', False)):
  2595         repo.abort_if_wdir_patched(_('cannot import over an applied patch'),
  2606         repo.abort_if_wdir_patched(_('cannot import over an applied patch'),
  2596                                    kwargs.get('force'))
  2607                                    kwargs.get('force'))
  2597     return orig(ui, repo, *args, **kwargs)
  2608     return orig(ui, repo, *args, **kwargs)
  2598 
  2609 
  2599 def uisetup(ui):
  2610 def uisetup(ui):
  2686          _('hg qpush [-f] [-l] [-a] [-m] [-n NAME] [PATCH | INDEX]')),
  2697          _('hg qpush [-f] [-l] [-a] [-m] [-n NAME] [PATCH | INDEX]')),
  2687     "^qrefresh":
  2698     "^qrefresh":
  2688         (refresh,
  2699         (refresh,
  2689          [('e', 'edit', None, _('edit commit message')),
  2700          [('e', 'edit', None, _('edit commit message')),
  2690           ('g', 'git', None, _('use git extended diff format')),
  2701           ('g', 'git', None, _('use git extended diff format')),
  2691           ('s', 'short', None, _('refresh only files already in the patch and specified files')),
  2702           ('s', 'short', None,
  2692           ('U', 'currentuser', None, _('add/update author field in patch with current user')),
  2703            _('refresh only files already in the patch and specified files')),
  2693           ('u', 'user', '', _('add/update author field in patch with given user')),
  2704           ('U', 'currentuser', None,
  2694           ('D', 'currentdate', None, _('add/update date field in patch with current date')),
  2705            _('add/update author field in patch with current user')),
  2695           ('d', 'date', '', _('add/update date field in patch with given date'))
  2706           ('u', 'user', '',
       
  2707            _('add/update author field in patch with given user')),
       
  2708           ('D', 'currentdate', None,
       
  2709            _('add/update date field in patch with current date')),
       
  2710           ('d', 'date', '',
       
  2711            _('add/update date field in patch with given date'))
  2696           ] + commands.walkopts + commands.commitopts,
  2712           ] + commands.walkopts + commands.commitopts,
  2697          _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...')),
  2713          _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...')),
  2698     'qrename|qmv':
  2714     'qrename|qmv':
  2699         (rename, [], _('hg qrename PATCH1 [PATCH2]')),
  2715         (rename, [], _('hg qrename PATCH1 [PATCH2]')),
  2700     "qrestore":
  2716     "qrestore":