hgweb: detect change based on changelog size too
Before, there was a race between an access and a modification made
within the same second.
--- a/mercurial/hgweb/common.py Tue Apr 19 13:25:19 2011 +0200
+++ b/mercurial/hgweb/common.py Tue Apr 19 15:15:56 2011 +0200
@@ -86,12 +86,16 @@
def statusmessage(code, message=None):
return '%d %s' % (code, message or _statusmessage(code))
-def get_mtime(spath):
+def get_stat(spath):
+ """stat changelog if it exists, spath otherwise"""
cl_path = os.path.join(spath, "00changelog.i")
if os.path.exists(cl_path):
- return os.stat(cl_path).st_mtime
+ return os.stat(cl_path)
else:
- return os.stat(spath).st_mtime
+ return os.stat(spath)
+
+def get_mtime(spath):
+ return get_stat(spath).st_mtime
def staticfile(directory, fname, req):
"""return a file inside directory with guessed Content-Type header
--- a/mercurial/hgweb/hgweb_mod.py Tue Apr 19 13:25:19 2011 +0200
+++ b/mercurial/hgweb/hgweb_mod.py Tue Apr 19 15:15:56 2011 +0200
@@ -8,7 +8,7 @@
import os
from mercurial import ui, hg, hook, error, encoding, templater
-from common import get_mtime, ErrorResponse, permhooks, caching
+from common import get_stat, ErrorResponse, permhooks, caching
from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST
from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR
from request import wsgirequest
@@ -38,6 +38,7 @@
self.repo.ui.setconfig('ui', 'interactive', 'off')
hook.redirect(True)
self.mtime = -1
+ self.size = -1
self.reponame = name
self.archives = 'zip', 'gz', 'bz2'
self.stripecount = 1
@@ -62,9 +63,12 @@
def refresh(self, request=None):
if request:
self.repo.ui.environ = request.env
- mtime = get_mtime(self.repo.spath)
- if mtime != self.mtime:
- self.mtime = mtime
+ st = get_stat(self.repo.spath)
+ # compare changelog size in addition to mtime to catch
+ # rollbacks made less than a second ago
+ if st.st_mtime != self.mtime or st.st_size != self.size:
+ self.mtime = st.st_mtime
+ self.size = st.st_size
self.repo = hg.repository(self.repo.ui, self.repo.root)
self.maxchanges = int(self.config("web", "maxchanges", 10))
self.stripecount = int(self.config("web", "stripes", 1))
--- a/tests/test-rollback.t Tue Apr 19 13:25:19 2011 +0200
+++ b/tests/test-rollback.t Tue Apr 19 15:15:56 2011 +0200
@@ -92,3 +92,29 @@
$ cat .hg/last-message.txt
another precious commit message
+test rollback on served repository
+
+ $ hg commit -m "precious commit message"
+ $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
+ $ cat hg.pid >> $DAEMON_PIDS
+ $ cd ..
+ $ hg clone http://localhost:$HGPORT u
+ requesting all changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 1 files
+ updating to branch test
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ cd u
+ $ hg id default
+ 1df294f7b1a2
+
+now rollback and observe that 'hg serve' reloads the repository and
+presents the correct tip changeset:
+
+ $ hg -R ../t rollback
+ repository tip rolled back to revision -1 (undo commit)
+ working directory now based on revision -1
+ $ hg id default
+ 000000000000