##// END OF EJS Templates
hgweb: fail if an invalid command was supplied in url path (issue4071)...
hgweb: fail if an invalid command was supplied in url path (issue4071) Traditionally, the way to specify a command for hgweb was to use url query arguments (e.g. "?cmd=batch"). If the command is unknown to hgweb, it gives an error (e.g. "400 no such method: badcmd"). But there's also another way to specify a command: as a url path fragment (e.g. "/graph"). Before, hgweb was made forgiving (looks like it was made in 44c5157474e7) and user could put any unknown command in the url. If hgweb couldn't understand it, it would just silently fall back to the default command, which depends on the actual style (e.g. for paper it's shortlog, for monoblue it's summary). This was inconsistent and was breaking some tools that rely on http status codes (as noted in the issue4071). So this patch changes that behavior to the more consistent one, i.e. hgweb will now return "400 no such method: badcmd". So if some tool was relying on having an invalid command return http status code 200 and also have some information, then it will stop working. That is, if somebody typed foobar when they really meant shortlog (and the user was lucky enough to choose a style where the default command is shortlog too), that fact will now be revealed. Code-wise, the changed if block is only relevant when there's no "?cmd" query parameter (i.e. only when command is specified as a url path fragment), and looks like the removed else branch was there only for falling back to default command. With that removed, the rest of the code works as expected: it looks at the command, and if it's not known, raises a proper ErrorResponse exception with an appropriate message. Evidently, there were no tests that required the old behavior. But, frankly, I don't know any way to tell if anyone actually exploited such forgiving behavior in some in-house tool.

File last commit:

r22057:44547222 default
r22506:6e1fbcb1 stable
Show More
repair.py
183 lines | 6.1 KiB | text/x-python | PythonLexer
Matt Mackall
strip: move strip code to a new repair module
r4702 # repair.py - functions for repository repair for mercurial
#
# Copyright 2005, 2006 Chris Mason <mason@suse.com>
# Copyright 2007 Matt Mackall
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
strip: move strip code to a new repair module
r4702
Pierre-Yves David
bundle2: move `readbundle` into the `exchange` module...
r21063 from mercurial import changegroup, exchange
Alexander Solovyov
remove unused imports and variables
r14064 from mercurial.node import short
from mercurial.i18n import _
Alain Leufroy
repair: fix missing import...
r16440 import errno
Matt Mackall
strip: move strip code to a new repair module
r4702
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 def _bundle(repo, bases, heads, node, suffix, compress=True):
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 """create a bundle with the specified revisions as a backup"""
Pierre-Yves David
localrepo: move the changegroupsubset method in changegroup module...
r20927 cg = changegroup.changegroupsubset(repo, bases, heads, 'strip')
FUJIWARA Katsunori
repair: make paths in "_bundle()" relative to ".hg"...
r20977 backupdir = "strip-backup"
vfs = repo.vfs
if not vfs.isdir(backupdir):
vfs.mkdir(backupdir)
name = "%s/%s-%s.hg" % (backupdir, short(node), suffix)
Nicolas Dumazet
repair: do not compress partial bundle if we do not keep it on disk...
r11791 if compress:
bundletype = "HG10BZ"
else:
bundletype = "HG10UN"
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 return changegroup.writebundle(cg, name, bundletype, vfs)
Matt Mackall
strip: move strip code to a new repair module
r4702
Alexis S. L. Carvalho
simplify revlog.strip interface and callers; add docstring...
r5910 def _collectfiles(repo, striprev):
"""find out the filelogs affected by the strip"""
Benoit Boissinot
repair: use set instead of dict
r8462 files = set()
Matt Mackall
strip: move strip code to a new repair module
r4702
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for x in xrange(striprev, len(repo)):
Martin Geisler
repair: bulk update sets...
r8479 files.update(repo[x].files())
Alexis S. L. Carvalho
repair.py: split stripall into two functions; clean it up a bit
r5902
Benoit Boissinot
repair: use set instead of dict
r8462 return sorted(files)
Alexis S. L. Carvalho
repair.py: split stripall into two functions; clean it up a bit
r5902
Benoit Boissinot
strip: remove usage of extranodes...
r13702 def _collectbrokencsets(repo, files, striprev):
"""return the changesets which will be broken by the truncation"""
Matt Mackall
strip: simplify collectone
r13705 s = set()
Benoit Boissinot
strip: remove usage of extranodes...
r13702 def collectone(revlog):
Durham Goode
strip: add faster revlog strip computation...
r20074 _, brokenset = revlog.getstrippoint(striprev)
s.update([revlog.linkrev(r) for r in brokenset])
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909
Matt Mackall
strip: simplify collectone
r13705 collectone(repo.manifest)
for fname in files:
collectone(repo.file(fname))
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909
Matt Mackall
strip: simplify collectone
r13705 return s
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909
Idan Kamara
repair: allow giving strip backup a different name...
r16388 def strip(ui, repo, nodelist, backup="all", topic='backup'):
Pierre-Yves David
clfilter: strip logic should be unfiltered...
r18004 repo = repo.unfiltered()
Idan Kamara
localrepo: introduce destroying function
r18310 repo.destroying()
Joshua Redstone
strip: incrementally update the branchheads cache after a strip...
r17013
Alexis S. L. Carvalho
repair.py: rename chlog to cl
r5901 cl = repo.changelog
Idan Kamara
repair: remove undo files after strip
r16237 # TODO handle undo of merge sets
Wagner Bruna
strip: enhance repair.strip to receive a list of nodes (issue3299)...
r16252 if isinstance(nodelist, str):
nodelist = [nodelist]
striplist = [cl.rev(node) for node in nodelist]
striprev = min(striplist)
Matt Mackall
strip: move strip code to a new repair module
r4702
Nicolas Dumazet
repair: do not compress partial bundle if we do not keep it on disk...
r11791 keeppartialbundle = backup == 'strip'
Alexis S. L. Carvalho
repair.py: rewrite a loop, making it cleaner and faster
r6147 # Some revisions with rev > striprev may not be descendants of striprev.
# We have to find these revisions and put them in a bundle, so that
# we can restore them after the truncations.
# To create the bundle we use repo.changegroupsubset which requires
# the list of heads and bases of the set of interesting revisions.
# (head = revision in the set that has no descendant in the set;
# base = revision in the set that has no ancestor in the set)
Wagner Bruna
strip: enhance repair.strip to receive a list of nodes (issue3299)...
r16252 tostrip = set(striplist)
for rev in striplist:
Bryan O'Sullivan
revlog: descendants(*revs) becomes descendants(revs) (API)...
r16867 for desc in cl.descendants([rev]):
Wagner Bruna
strip: enhance repair.strip to receive a list of nodes (issue3299)...
r16252 tostrip.add(desc)
Benoit Boissinot
strip: remove usage of extranodes...
r13702
files = _collectfiles(repo, striprev)
Matt Mackall
strip: simplify collectone
r13705 saverevs = _collectbrokencsets(repo, files, striprev)
Benoit Boissinot
strip: remove usage of extranodes...
r13702
# compute heads
saveheads = set(saverevs)
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for r in xrange(striprev + 1, len(cl)):
Benoit Boissinot
strip: remove usage of extranodes...
r13702 if r not in tostrip:
saverevs.add(r)
saveheads.difference_update(cl.parentrevs(r))
saveheads.add(r)
saveheads = [cl.node(r) for r in saveheads]
Matt Mackall
strip: move strip code to a new repair module
r4702
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 # compute base nodes
if saverevs:
Bryan O'Sullivan
revlog: descendants(*revs) becomes descendants(revs) (API)...
r16867 descendants = set(cl.descendants(saverevs))
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 saverevs.difference_update(descendants)
savebases = [cl.node(r) for r in saverevs]
Wagner Bruna
strip: enhance repair.strip to receive a list of nodes (issue3299)...
r16252 stripbases = [cl.node(r) for r in tostrip]
Siddharth Agarwal
strip: make query to get new bookmark target cheaper...
r18040
# For a set s, max(parents(s) - s) is the same as max(heads(::s - s)), but
# is much faster
newbmtarget = repo.revs('max(parents(%ld) - (%ld))', tostrip, tostrip)
Augie Fackler
strip: move bookmarks to nearest ancestor rather than '.'...
r17264 if newbmtarget:
Matt Mackall
repair: use node to track post-strip bookmark target...
r17796 newbmtarget = repo[newbmtarget[0]].node()
Augie Fackler
strip: move bookmarks to nearest ancestor rather than '.'...
r17264 else:
newbmtarget = '.'
Matt Mackall
strip: move strip code to a new repair module
r4702
Matt Mackall
bookmarks: move strip support to repair
r13362 bm = repo._bookmarks
updatebm = []
for m in bm:
rev = repo[bm[m]].rev()
if rev in tostrip:
updatebm.append(m)
Matt Mackall
strip: move strip code to a new repair module
r4702 # create a changegroup for all the branches we need to keep
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 backupfile = None
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 vfs = repo.vfs
Matt Mackall
strip: move strip code to a new repair module
r4702 if backup == "all":
Idan Kamara
repair: allow giving strip backup a different name...
r16388 backupfile = _bundle(repo, stripbases, cl.heads(), node, topic)
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 repo.ui.status(_("saved backup bundle to %s\n") %
vfs.join(backupfile))
repo.ui.log("backupbundle", "saved backup bundle to %s\n",
vfs.join(backupfile))
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 if saveheads or savebases:
Nicolas Dumazet
repair: do not compress partial bundle if we do not keep it on disk...
r11791 # do not compress partial bundle if we remove it from disk later
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 chgrpfile = _bundle(repo, savebases, saveheads, node, 'temp',
compress=keeppartialbundle)
Matt Mackall
strip: move strip code to a new repair module
r4702
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073 mfst = repo.manifest
Steve Borho
localrepo: add desc parameter to transaction...
r10881 tr = repo.transaction("strip")
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073 offset = len(tr.entries)
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 try:
tr.startgroup()
cl.strip(striprev, tr)
mfst.strip(striprev, tr)
for fn in files:
repo.file(fn).strip(striprev, tr)
tr.endgroup()
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 try:
for i in xrange(offset, len(tr.entries)):
file, troffset, ignore = tr.entries[i]
repo.sopener(file, 'a').truncate(troffset)
Durham Goode
fncache: clean up fncache during strips...
r20885 if troffset == 0:
repo.store.markremoved(file)
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 tr.close()
Brodie Rao
check-code: ignore naked excepts with a "re-raise" comment...
r16705 except: # re-raises
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 tr.abort()
raise
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 if saveheads or savebases:
Matt Mackall
strip: hide unbundle messages by default...
r11202 ui.note(_("adding branch\n"))
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 f = vfs.open(chgrpfile, "rb")
Pierre-Yves David
bundle2: add a ui argument to readbundle...
r21064 gen = exchange.readbundle(ui, f, chgrpfile, vfs)
Matt Mackall
strip: hide unbundle messages by default...
r11202 if not repo.ui.verbose:
# silence internal shuffling chatter
repo.ui.pushbuffer()
Pierre-Yves David
localrepo: move the addchangegroup method in changegroup module...
r20933 changegroup.addchangegroup(repo, gen, 'strip',
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 'bundle:' + vfs.join(chgrpfile), True)
Matt Mackall
strip: hide unbundle messages by default...
r11202 if not repo.ui.verbose:
repo.ui.popbuffer()
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 f.close()
Nicolas Dumazet
repair: do not compress partial bundle if we do not keep it on disk...
r11791 if not keeppartialbundle:
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 vfs.unlink(chgrpfile)
Matt Mackall
bookmarks: move strip support to repair
r13362
Idan Kamara
repair: remove undo files after strip
r16237 # remove undo files
FUJIWARA Katsunori
localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"...
r20975 for undovfs, undofile in repo.undofiles():
Idan Kamara
repair: remove undo files after strip
r16237 try:
FUJIWARA Katsunori
localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"...
r20975 undovfs.unlink(undofile)
Idan Kamara
repair: remove undo files after strip
r16237 except OSError, e:
if e.errno != errno.ENOENT:
FUJIWARA Katsunori
localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"...
r20975 ui.warn(_('error removing %s: %s\n') %
(undovfs.join(undofile), str(e)))
Idan Kamara
repair: remove undo files after strip
r16237
Matt Mackall
bookmarks: move strip support to repair
r13362 for m in updatebm:
Augie Fackler
strip: move bookmarks to nearest ancestor rather than '.'...
r17264 bm[m] = repo[newbmtarget].node()
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 bm.write()
Brodie Rao
check-code: ignore naked excepts with a "re-raise" comment...
r16705 except: # re-raises
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 if backupfile:
Martin Geisler
mark ui.warn strings for translation
r11600 ui.warn(_("strip failed, full bundle stored in '%s'\n")
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 % vfs.join(backupfile))
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 elif saveheads:
Martin Geisler
mark ui.warn strings for translation
r11600 ui.warn(_("strip failed, partial bundle stored in '%s'\n")
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 % vfs.join(chgrpfile))
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073 raise
Matt Mackall
strip: move strip code to a new repair module
r4702
Pierre-Yves David
destroyed: drop complex branchcache rebuilt logic...
r18395 repo.destroyed()