diff --git a/hgext/bookmarks.py b/hgext/bookmarks.py --- a/hgext/bookmarks.py +++ b/hgext/bookmarks.py @@ -136,6 +136,9 @@ def bookmark(ui, repo, mark=None, rev=No if "\n" in mark: raise util.Abort(_("bookmark name cannot contain newlines")) mark = mark.strip() + if not mark: + raise util.Abort(_("bookmark names cannot consist entirely of " + "whitespace")) if mark in marks and not force: raise util.Abort(_("a bookmark of the same name already exists")) if ((mark in repo.branchtags() or mark == repo.dirstate.branch()) diff --git a/hgext/mq.py b/hgext/mq.py --- a/hgext/mq.py +++ b/hgext/mq.py @@ -1687,11 +1687,22 @@ class queue(object): if existing: if filename == '-': raise util.Abort(_('-e is incompatible with import from -')) - if not patchname: - patchname = normname(filename) - self.check_reserved_name(patchname) - if not os.path.isfile(self.join(patchname)): - raise util.Abort(_("patch %s does not exist") % patchname) + filename = normname(filename) + self.check_reserved_name(filename) + originpath = self.join(filename) + if not os.path.isfile(originpath): + raise util.Abort(_("patch %s does not exist") % filename) + + if patchname: + self.check_reserved_name(patchname) + checkfile(patchname) + + self.ui.write(_('renaming %s to %s\n') + % (filename, patchname)) + util.rename(originpath, self.join(patchname)) + else: + patchname = filename + else: try: if filename == '-': @@ -1806,6 +1817,10 @@ def qimport(ui, repo, *filename, **opts) To import a patch from standard input, pass - as the patch file. When importing from standard input, a patch name must be specified using the --name flag. + + To import an existing patch while renaming it:: + + hg qimport -e existing-patch -n new-name """ q = repo.mq try: diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -352,12 +352,12 @@ class filectx(object): def size(self): return self._filelog.size(self._filerev) - def cmp(self, text): - """compare text with stored file revision + def cmp(self, fctx): + """compare with other file context - returns True if text is different than what is stored. + returns True if different than fctx. """ - return self._filelog.cmp(self._filenode, text) + return self._filelog.cmp(self._filenode, fctx.data()) def renamed(self): """check if file was actually renamed in this changeset revision @@ -935,12 +935,14 @@ class workingfilectx(filectx): raise return (t, tz) - def cmp(self, text): - """compare text with disk content + def cmp(self, fctx): + """compare with other file context - returns True if text is different than what is on disk. + returns True if different than fctx. """ - return self._repo.wread(self._path) != text + # fctx should be a filectx (not a wfctx) + # invert comparison to reuse the same code path + return fctx.cmp(self) class memctx(object): """Use memctx to perform in-memory commits via localrepo.commitctx(). diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py --- a/mercurial/filemerge.py +++ b/mercurial/filemerge.py @@ -135,7 +135,7 @@ def filemerge(repo, mynode, orig, fcd, f except IOError: return False - if not fco.cmp(fcd.data()): # files identical? + if not fco.cmp(fcd): # files identical? return None if fca == fco: # backwards, use working dir parent as ancestor diff --git a/mercurial/help/revsets.txt b/mercurial/help/revsets.txt --- a/mercurial/help/revsets.txt +++ b/mercurial/help/revsets.txt @@ -100,6 +100,9 @@ The following predicates are supported: ``max(set)`` Changeset with highest revision number in set. +``min(set)`` + Changeset with lowest revision number in set. + ``merge()`` Changeset is a merge changeset. diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -510,7 +510,7 @@ class localrepository(repo.repository): def _link(self, f): return os.path.islink(self.wjoin(f)) - def _filter(self, filter, filename, data): + def _loadfilter(self, filter): if filter not in self.filterpats: l = [] for pat, cmd in self.ui.configitems(filter): @@ -533,6 +533,9 @@ class localrepository(repo.repository): l.append((mf, fn, params)) self.filterpats[filter] = l + def _filter(self, filter, filename, data): + self._loadfilter(filter) + for mf, fn, cmd in self.filterpats[filter]: if mf(filename): self.ui.debug("filtering %s through %s\n" % (filename, cmd)) @@ -1059,7 +1062,7 @@ class localrepository(repo.repository): # do a full compare of any files that might have changed for f in sorted(cmp): if (f not in ctx1 or ctx2.flags(f) != ctx1.flags(f) - or ctx1[f].cmp(ctx2[f].data())): + or ctx1[f].cmp(ctx2[f])): modified.append(f) else: fixup.append(f) @@ -1103,7 +1106,7 @@ class localrepository(repo.repository): if fn in mf1: if (mf1.flags(fn) != mf2.flags(fn) or (mf1[fn] != mf2[fn] and - (mf2[fn] or ctx1[fn].cmp(ctx2[fn].data())))): + (mf2[fn] or ctx1[fn].cmp(ctx2[fn])))): modified.append(fn) elif listclean: clean.append(fn) diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -73,7 +73,7 @@ class mergestate(object): def _checkunknown(wctx, mctx): "check for collisions between unknown files and files in mctx" for f in wctx.unknown(): - if f in mctx and mctx[f].cmp(wctx[f].data()): + if f in mctx and mctx[f].cmp(wctx[f]): raise util.Abort(_("untracked file in working directory differs" " from file in requested revision: '%s'") % f) diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -195,6 +195,14 @@ def maxrev(repo, subset, x): return [m] return [] +def minrev(repo, subset, x): + s = getset(repo, subset, x) + if s: + m = min(s) + if m in subset: + return [m] + return [] + def limit(repo, subset, x): l = getargs(x, 2, 2, _("limit wants two arguments")) try: @@ -466,6 +474,7 @@ symbols = { "keyword": keyword, "limit": limit, "max": maxrev, + "min": minrev, "merge": merge, "modifies": modifies, "outgoing": outgoing, diff --git a/tests/test-bookmarks b/tests/test-bookmarks --- a/tests/test-bookmarks +++ b/tests/test-bookmarks @@ -100,4 +100,7 @@ hg bookmark echo % revision but no bookmark name hg bookmark -r . +echo % bookmark name with whitespace only +hg bookmark ' ' + true diff --git a/tests/test-bookmarks.out b/tests/test-bookmarks.out --- a/tests/test-bookmarks.out +++ b/tests/test-bookmarks.out @@ -74,3 +74,5 @@ abort: a bookmark of the same name alrea * x y 2:0316ce92851d % revision but no bookmark name abort: bookmark name required +% bookmark name with whitespace only +abort: bookmark names cannot consist entirely of whitespace diff --git a/tests/test-mq-qimport b/tests/test-mq-qimport --- a/tests/test-mq-qimport +++ b/tests/test-mq-qimport @@ -109,3 +109,19 @@ hg up -C hg qimport --push another.diff hg qfin -a hg qimport -rtip -P + +hg qpop -a +hg qdel -k 2.diff +echo % qimport -e +hg qimport -e 2.diff +hg qdel -k 2.diff +echo % qimport -e --name newname oldexisitingpatch +hg qimport -e --name this-name-is-better 2.diff +hg qser +echo % qimport -e --name without --force +cp .hg/patches/this-name-is-better .hg/patches/3.diff +hg qimport -e --name this-name-is-better 3.diff +hg qser +echo % qimport -e --name with --force +hg qimport --force -e --name this-name-is-better 3.diff +hg qser diff --git a/tests/test-mq-qimport.out b/tests/test-mq-qimport.out --- a/tests/test-mq-qimport.out +++ b/tests/test-mq-qimport.out @@ -52,3 +52,21 @@ applying another.diff now at: another.diff patch b.diff finalized without changeset message patch another.diff finalized without changeset message +popping 2.diff +patch queue now empty +% qimport -e +adding 2.diff to series file +% qimport -e --name newname oldexisitingpatch +renaming 2.diff to this-name-is-better +adding this-name-is-better to series file +this-name-is-better +url.diff +% qimport -e --name without --force +abort: patch "this-name-is-better" already exists +this-name-is-better +url.diff +% qimport -e --name with --force +renaming 3.diff to this-name-is-better +adding this-name-is-better to series file +this-name-is-better +url.diff diff --git a/tests/test-revset b/tests/test-revset --- a/tests/test-revset +++ b/tests/test-revset @@ -110,6 +110,7 @@ log 'heads(6::)' log 'keyword(issue)' log 'limit(head(), 1)' log 'max(contains(a))' +log 'min(contains(a))' log 'merge()' log 'modifies(b)' log 'p1(merge())' diff --git a/tests/test-revset.out b/tests/test-revset.out --- a/tests/test-revset.out +++ b/tests/test-revset.out @@ -152,6 +152,8 @@ 6 0 % log 'max(contains(a))' 5 +% log 'min(contains(a))' +0 % log 'merge()' 6 % log 'modifies(b)'