--- a/mercurial/cmdutil.py Sat Apr 28 11:43:31 2007 +0200
+++ b/mercurial/cmdutil.py Sat Apr 28 09:03:47 2007 -0700
@@ -200,6 +200,50 @@
if not dry_run:
repo.copy(old, new, wlock=wlock)
+def service(opts, parentfn=None, initfn=None, runfn=None):
+ '''Run a command as a service.'''
+
+ if opts['daemon'] and not opts['daemon_pipefds']:
+ rfd, wfd = os.pipe()
+ args = sys.argv[:]
+ args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
+ pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
+ args[0], args)
+ os.close(wfd)
+ os.read(rfd, 1)
+ if parentfn:
+ return parentfn(pid)
+ else:
+ os._exit(0)
+
+ if initfn:
+ initfn()
+
+ if opts['pid_file']:
+ fp = open(opts['pid_file'], 'w')
+ fp.write(str(os.getpid()) + '\n')
+ fp.close()
+
+ if opts['daemon_pipefds']:
+ rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
+ os.close(rfd)
+ try:
+ os.setsid()
+ except AttributeError:
+ pass
+ os.write(wfd, 'y')
+ os.close(wfd)
+ sys.stdout.flush()
+ sys.stderr.flush()
+ fd = os.open(util.nulldev, os.O_RDWR)
+ if fd != 0: os.dup2(fd, 0)
+ if fd != 1: os.dup2(fd, 1)
+ if fd != 2: os.dup2(fd, 2)
+ if fd not in (0, 1, 2): os.close(fd)
+
+ if runfn:
+ return runfn()
+
class changeset_printer(object):
'''show changeset information when templating not requested.'''
--- a/mercurial/commands.py Sat Apr 28 11:43:31 2007 +0200
+++ b/mercurial/commands.py Sat Apr 28 09:03:47 2007 -0700
@@ -2375,44 +2375,27 @@
raise hg.RepoError(_("There is no Mercurial repository here"
" (.hg not found)"))
- if opts['daemon'] and not opts['daemon_pipefds']:
- rfd, wfd = os.pipe()
- args = sys.argv[:]
- args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
- pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
- args[0], args)
- os.close(wfd)
- os.read(rfd, 1)
- os._exit(0)
-
- httpd = hgweb.server.create_server(parentui, repo)
-
- if ui.verbose:
- if httpd.port != 80:
- ui.status(_('listening at http://%s:%d/\n') %
- (httpd.addr, httpd.port))
- else:
- ui.status(_('listening at http://%s/\n') % httpd.addr)
-
- if opts['pid_file']:
- fp = open(opts['pid_file'], 'w')
- fp.write(str(os.getpid()) + '\n')
- fp.close()
-
- if opts['daemon_pipefds']:
- rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
- os.close(rfd)
- os.write(wfd, 'y')
- os.close(wfd)
- sys.stdout.flush()
- sys.stderr.flush()
- fd = os.open(util.nulldev, os.O_RDWR)
- if fd != 0: os.dup2(fd, 0)
- if fd != 1: os.dup2(fd, 1)
- if fd != 2: os.dup2(fd, 2)
- if fd not in (0, 1, 2): os.close(fd)
-
- httpd.serve_forever()
+ class service:
+ def init(self):
+ try:
+ self.httpd = hgweb.server.create_server(parentui, repo)
+ except socket.error, inst:
+ raise util.Abort(_('cannot start server: ') + inst.args[1])
+
+ if not ui.verbose: return
+
+ if httpd.port != 80:
+ ui.status(_('listening at http://%s:%d/\n') %
+ (httpd.addr, httpd.port))
+ else:
+ ui.status(_('listening at http://%s/\n') % httpd.addr)
+
+ def run(self):
+ self.httpd.serve_forever()
+
+ service = service()
+
+ cmdutil.service(opts, initfn=service.init, runfn=service.run)
def status(ui, repo, *pats, **opts):
"""show changed files in the working directory
--- a/mercurial/mpatch.c Sat Apr 28 11:43:31 2007 +0200
+++ b/mercurial/mpatch.c Sat Apr 28 09:03:47 2007 -0700
@@ -225,7 +225,7 @@
{
struct flist *l;
struct frag *lt;
- char *end = bin + len;
+ char *data = bin + 12, *end = bin + len;
char decode[12]; /* for dealing with alignment issues */
/* assume worst case size, we won't have many of these lists */
@@ -235,13 +235,18 @@
lt = l->tail;
- while (bin < end) {
+ while (data <= end) {
memcpy(decode, bin, 12);
lt->start = ntohl(*(uint32_t *)decode);
lt->end = ntohl(*(uint32_t *)(decode + 4));
lt->len = ntohl(*(uint32_t *)(decode + 8));
- lt->data = bin + 12;
- bin += 12 + lt->len;
+ if (lt->start > lt->end)
+ break; /* sanity check */
+ bin = data + lt->len;
+ if (bin < data)
+ break; /* big data + big (bogus) len can wrap around */
+ lt->data = data;
+ data = bin + 12;
lt++;
}
@@ -371,20 +376,26 @@
{
long orig, start, end, len, outlen = 0, last = 0;
int patchlen;
- char *bin, *binend;
+ char *bin, *binend, *data;
char decode[12]; /* for dealing with alignment issues */
if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen))
return NULL;
binend = bin + patchlen;
+ data = bin + 12;
- while (bin < binend) {
+ while (data <= binend) {
memcpy(decode, bin, 12);
start = ntohl(*(uint32_t *)decode);
end = ntohl(*(uint32_t *)(decode + 4));
len = ntohl(*(uint32_t *)(decode + 8));
- bin += 12 + len;
+ if (start > end)
+ break; /* sanity check */
+ bin = data + len;
+ if (bin < data)
+ break; /* big data + big (bogus) len can wrap around */
+ data = bin + 12;
outlen += start - last;
last = end;
outlen += len;
--- a/mercurial/util.py Sat Apr 28 11:43:31 2007 +0200
+++ b/mercurial/util.py Sat Apr 28 09:03:47 2007 -0700
@@ -1161,11 +1161,19 @@
class atomicfile(atomictempfile):
"""the file will only be copied on close"""
def __init__(self, name, mode):
+ self._err = False
atomictempfile.__init__(self, name, mode)
+ def write(self, s):
+ try:
+ atomictempfile.write(self, s)
+ except:
+ self._err = True
+ raise
def close(self):
self.rename()
def __del__(self):
- self.rename()
+ if not self._err:
+ self.rename()
def o(path, mode="r", text=False, atomic=False, atomictemp=False):
if audit_p: