--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -257,7 +257,7 @@ class queue:
head = self.qparents(repo)
for patch in series:
- patch = mergeq.lookup(patch)
+ patch = mergeq.lookup(patch, strict=True)
if not patch:
self.ui.warn("patch %s does not exist\n" % patch)
return (1, None)
@@ -380,7 +380,7 @@ class queue:
return (err, n)
def delete(self, repo, patch):
- patch = self.lookup(patch)
+ patch = self.lookup(patch, strict=True)
info = self.isapplied(patch)
if info:
self.ui.warn("cannot delete applied patch %s\n" % patch)
@@ -418,7 +418,7 @@ class queue:
commitfiles = c + a + r
self.check_toppatch(repo)
wlock = repo.wlock()
- insert = self.series_end()
+ insert = self.full_series_end()
if msg:
n = repo.commit(commitfiles, "[mq]: %s" % msg, force=True,
wlock=wlock)
@@ -442,7 +442,7 @@ class queue:
r = self.qrepo()
if r: r.add([patch])
if commitfiles:
- self.refresh(repo, short=True)
+ self.refresh(repo, msg=None, short=True)
def strip(self, repo, rev, update=True, backup="all", wlock=None):
def limitheads(chlog, stop):
@@ -530,6 +530,9 @@ class queue:
revnum = chlog.rev(rev)
if update:
+ (c, a, r, d, u) = repo.changes(None, None)
+ if c or a or d or r:
+ raise util.Abort(_("Local changes found"))
urev = self.qparents(repo, rev)
repo.update(urev, allow=False, force=True, wlock=wlock)
repo.dirstate.write()
@@ -598,25 +601,79 @@ class queue:
return (i, a[0], a[1])
return None
- def lookup(self, patch):
+ # if the exact patch name does not exist, we try a few
+ # variations. If strict is passed, we try only #1
+ #
+ # 1) a number to indicate an offset in the series file
+ # 2) a unique substring of the patch name was given
+ # 3) patchname[-+]num to indicate an offset in the series file
+ def lookup(self, patch, strict=False):
+ def partial_name(s):
+ count = 0
+ if s in self.series:
+ return s
+ for x in self.series:
+ if s in x:
+ count += 1
+ last = x
+ if count > 1:
+ return None
+ if count:
+ return last
+ if len(self.series) > 0 and len(self.applied) > 0:
+ if s == 'qtip':
+ return self.series[self.series_end()-1]
+ if s == 'qbase':
+ return self.series[0]
+ return None
if patch == None:
return None
- if patch in self.series:
- return patch
+
+ # we don't want to return a partial match until we make
+ # sure the file name passed in does not exist (checked below)
+ res = partial_name(patch)
+ if res and res == patch:
+ return res
+
if not os.path.isfile(os.path.join(self.path, patch)):
try:
sno = int(patch)
except(ValueError, OverflowError):
- self.ui.warn("patch %s not in series\n" % patch)
- sys.exit(1)
- if sno >= len(self.series):
- self.ui.warn("patch number %d is out of range\n" % sno)
- sys.exit(1)
- patch = self.series[sno]
- else:
- self.ui.warn("patch %s not in series\n" % patch)
- sys.exit(1)
- return patch
+ pass
+ else:
+ if sno < len(self.series):
+ patch = self.series[sno]
+ return patch
+ if not strict:
+ # return any partial match made above
+ if res:
+ return res
+ minus = patch.rsplit('-', 1)
+ if len(minus) > 1:
+ res = partial_name(minus[0])
+ if res:
+ i = self.series.index(res)
+ try:
+ off = int(minus[1] or 1)
+ except(ValueError, OverflowError):
+ pass
+ else:
+ if i - off >= 0:
+ return self.series[i - off]
+ plus = patch.rsplit('+', 1)
+ if len(plus) > 1:
+ res = partial_name(plus[0])
+ if res:
+ i = self.series.index(res)
+ try:
+ off = int(plus[1] or 1)
+ except(ValueError, OverflowError):
+ pass
+ else:
+ if i + off < len(self.series):
+ return self.series[i + off]
+ self.ui.warn("patch %s not in series\n" % patch)
+ sys.exit(1)
def push(self, repo, patch=None, force=False, list=False,
mergeq=None, wlock=None):
@@ -654,7 +711,8 @@ class queue:
self.ui.write("Now at: %s\n" % top)
return ret[0]
- def pop(self, repo, patch=None, force=False, update=True, wlock=None):
+ def pop(self, repo, patch=None, force=False, update=True, all=False,
+ wlock=None):
def getfile(f, rev):
t = repo.file(f).read(rev)
try:
@@ -695,7 +753,17 @@ class queue:
self.applied_dirty = 1;
end = len(self.applied)
if not patch:
- info = [len(self.applied) - 1] + self.applied[-1].split(':')
+ if all:
+ popi = 0
+ else:
+ popi = len(self.applied) - 1
+ else:
+ popi = info[0] + 1
+ if popi >= end:
+ self.ui.warn("qpop: %s is already at the top\n" % patch)
+ return
+ info = [ popi ] + self.applied[popi].split(':')
+
start = info[0]
rev = revlog.bin(info[1])
@@ -739,7 +807,7 @@ class queue:
qp = self.qparents(repo, top)
commands.dodiff(sys.stdout, self.ui, repo, qp, None, files)
- def refresh(self, repo, short=False):
+ def refresh(self, repo, msg=None, short=False):
if len(self.applied) == 0:
self.ui.write("No patches applied\n")
return
@@ -822,10 +890,14 @@ class queue:
repo.dirstate.update(c, 'n')
repo.dirstate.forget(forget)
- if not message:
- message = "patch queue: %s\n" % patch
+ if not msg:
+ if not message:
+ message = "patch queue: %s\n" % patch
+ else:
+ message = "\n".join(message)
else:
- message = "\n".join(message)
+ message = msg
+
self.strip(repo, top, update=False, backup='strip', wlock=wlock)
n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock)
self.applied[-1] = revlog.hex(n) + ':' + patch
@@ -852,6 +924,8 @@ class queue:
else:
start = self.series.index(patch) + 1
for p in self.series[start:]:
+ if self.ui.verbose:
+ self.ui.write("%d " % self.series.index(p))
self.ui.write("%s\n" % p)
def qseries(self, repo, missing=None):
@@ -974,6 +1048,15 @@ class queue:
self.applied.append(revlog.hex(n) + ":" + '.hg.patches.save.line')
self.applied_dirty = 1
+ def full_series_end(self):
+ if len(self.applied) > 0:
+ (top, p) = self.applied[-1].split(':')
+ end = self.find_series(p)
+ if end == None:
+ return len(self.full_series)
+ return end + 1
+ return 0
+
def series_end(self):
end = 0
if len(self.applied) > 0:
@@ -999,8 +1082,11 @@ class queue:
def appliedname(self, index):
p = self.applied[index]
+ pname = p.split(':')[1]
if not self.ui.verbose:
- p = p.split(':')[1]
+ p = pname
+ else:
+ p = str(self.series.index(pname)) + " " + p
return p
def top(self, repo):
@@ -1015,7 +1101,10 @@ class queue:
if end == len(self.series):
self.ui.write("All patches applied\n")
else:
- self.ui.write(self.series[end] + '\n')
+ p = self.series[end]
+ if self.ui.verbose:
+ self.ui.write("%d " % self.series.index(p))
+ self.ui.write(p + '\n')
def prev(self, repo):
if len(self.applied) > 1:
@@ -1055,7 +1144,7 @@ class queue:
if patch in self.series:
self.ui.warn("patch %s is already in the series file\n" % patch)
sys.exit(1)
- index = self.series_end() + i
+ index = self.full_series_end() + i
self.full_series[index:index] = [patch]
self.read_series(self.full_series)
self.ui.warn("adding %s to series file\n" % patch)
@@ -1136,14 +1225,16 @@ def prev(ui, repo, **opts):
def new(ui, repo, patch, **opts):
"""create a new patch"""
q = repomap[repo]
- q.new(repo, patch, msg=opts['message'], force=opts['force'])
+ message=commands.logmessage(**opts)
+ q.new(repo, patch, msg=message, force=opts['force'])
q.save_dirty()
return 0
def refresh(ui, repo, **opts):
"""update the current patch"""
q = repomap[repo]
- q.refresh(repo, short=opts['short'])
+ message=commands.logmessage(**opts)
+ q.refresh(repo, msg=message, short=opts['short'])
q.save_dirty()
return 0
@@ -1208,9 +1299,7 @@ def pop(ui, repo, patch=None, **opts):
localupdate = False
else:
q = repomap[repo]
- if opts['all'] and len(q.applied) > 0:
- patch = q.applied[0].split(':')[1]
- q.pop(repo, patch, force=opts['force'], update=localupdate)
+ q.pop(repo, patch, force=opts['force'], update=localupdate, all=opts['all'])
q.save_dirty()
return 0
@@ -1226,7 +1315,8 @@ def restore(ui, repo, rev, **opts):
def save(ui, repo, **opts):
"""save current queue state"""
q = repomap[repo]
- ret = q.save(repo, msg=opts['message'])
+ message=commands.logmessage(**opts)
+ ret = q.save(repo, msg=message)
if ret:
return ret
q.save_dirty()
@@ -1272,28 +1362,30 @@ def version(ui, q=None):
def reposetup(ui, repo):
repomap[repo] = queue(ui, repo.join(""))
- oldlookup = repo.lookup
+ oldtags = repo.tags
+
+ def qtags():
+ if repo.tagscache:
+ return repo.tagscache
- def qlookup(key):
- try:
- return oldlookup(key)
- except hg.RepoError:
- q = repomap[repo]
+ tagscache = oldtags()
+
+ q = repomap[repo]
+ if len(q.applied) == 0:
+ return tagscache
- qpatchnames = { 'qtip': -1, 'qbase': 0 }
- if key in qpatchnames:
- if len(q.applied) == 0:
- self.ui.warn('No patches applied\n')
- raise
- patch = q.applied[qpatchnames[key]].split(':')[0]
- return revlog.bin(patch)
+ mqtags = [patch.split(':') for patch in q.applied]
+ mqtags.append((mqtags[-1][0], 'qtip'))
+ mqtags.append((mqtags[0][0], 'qbase'))
+ for patch in mqtags:
+ if patch[1] in tagscache:
+ repo.ui.warn('Tag %s overrides mq patch of the same name\n' % patch[1])
+ else:
+ tagscache[patch[1]] = revlog.bin(patch[0])
- patch = q.isapplied(key)
- if not patch:
- raise
- return revlog.bin(patch[1])
+ return tagscache
- repo.lookup = qlookup
+ repo.tags = qtags
cmdtable = {
"qapplied": (applied, [], 'hg qapplied [PATCH]'),
@@ -1315,9 +1407,10 @@ cmdtable = {
'hg qinit [-c]'),
"qnew":
(new,
- [('m', 'message', '', 'commit message'),
+ [('m', 'message', '', _('use <text> as commit message')),
+ ('l', 'logfile', '', _('read the commit message from <file>')),
('f', 'force', None, 'force')],
- 'hg qnew [-m TEXT] [-f] PATCH'),
+ 'hg qnew [-m TEXT] [-l FILE] [-f] PATCH'),
"qnext": (next, [], 'hg qnext'),
"qprev": (prev, [], 'hg qprev'),
"^qpop":
@@ -1336,8 +1429,10 @@ cmdtable = {
'hg qpush [-f] [-l] [-a] [-m] [-n NAME] [PATCH | INDEX]'),
"^qrefresh":
(refresh,
- [('s', 'short', None, 'short refresh')],
- 'hg qrefresh [-s]'),
+ [('m', 'message', '', _('change commit message with <text>')),
+ ('l', 'logfile', '', _('change commit message with <file> content')),
+ ('s', 'short', None, 'short refresh')],
+ 'hg qrefresh [-m TEXT] [-l FILE] [-s]'),
"qrestore":
(restore,
[('d', 'delete', None, 'delete save entry'),
@@ -1345,12 +1440,13 @@ cmdtable = {
'hg qrestore [-d] [-u] REV'),
"qsave":
(save,
- [('m', 'message', '', 'commit message'),
+ [('m', 'message', '', _('use <text> as commit message')),
+ ('l', 'logfile', '', _('read the commit message from <file>')),
('c', 'copy', None, 'copy patch directory'),
('n', 'name', '', 'copy directory name'),
('e', 'empty', None, 'clear queue status file'),
('f', 'force', None, 'force copy')],
- 'hg qsave [-m TEXT] [-c] [-n NAME] [-e] [-f]'),
+ 'hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'),
"qseries":
(series,
[('m', 'missing', None, 'print patches not in series')],