--- a/doc/hg.1.txt Thu Aug 04 18:23:07 2005 +0100
+++ b/doc/hg.1.txt Thu Aug 04 13:27:41 2005 -0800
@@ -330,6 +330,7 @@
-p, --port <n> port to use (default: 8000)
-n, --name <name> name to show in web pages (default: working dir)
-t, --templatedir <path> web templates to use
+ -6, --ipv6 use IPv6 in addition to IPv4
status [options] [files]::
Show changed files in the working directory. If no names are
--- a/mercurial/bdiff.c Thu Aug 04 18:23:07 2005 +0100
+++ b/mercurial/bdiff.c Thu Aug 04 13:27:41 2005 -0800
@@ -229,7 +229,8 @@
/* allocate and fill arrays */
t = equatelines(a, an, b, bn);
pos = calloc(bn, sizeof(struct pos));
- l.head = l.base = malloc(sizeof(struct hunk) * ((an + bn) / 4 + 2));
+ /* we can't have more matches than lines in the shorter file */
+ l.head = l.base = malloc(sizeof(struct hunk) * ((an<bn ? an:bn) + 1));
if (pos && l.base && t) {
/* generate the matching block list */
--- a/mercurial/commands.py Thu Aug 04 18:23:07 2005 +0100
+++ b/mercurial/commands.py Thu Aug 04 13:27:41 2005 -0800
@@ -40,16 +40,24 @@
return args
def matchpats(cwd, pats = [], opts = {}, head = ''):
- return util.matcher(cwd, pats, opts.get('include'),
+ return util.matcher(cwd, pats or ['.'], opts.get('include'),
opts.get('exclude'), head)
+def pathto(n1, n2):
+ '''return the relative path from one place to another'''
+ if not n1: return n2
+ a, b = n1.split(os.sep), n2.split(os.sep)
+ a.reverse(), b.reverse()
+ while a and b and a[-1] == b[-1]:
+ a.pop(), b.pop()
+ b.reverse()
+ return os.sep.join((['..'] * len(a)) + b)
+
def walk(repo, pats, opts, head = ''):
cwd = repo.getcwd()
- c = 0
- if cwd: c = len(cwd) + 1
files, matchfn = matchpats(cwd, pats, opts, head)
for src, fn in repo.walk(files = files, match = matchfn):
- yield src, fn, fn[c:]
+ yield src, fn, pathto(cwd, fn)
revrangesep = ':'
@@ -565,6 +573,11 @@
ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
ui.write("}\n")
+def debugwalk(ui, repo, *pats, **opts):
+ items = list(walk(repo, pats, opts))
+ fmt = '%%s %%-%ds %%s' % max([len(abs) for (src, abs, rel) in items])
+ for i in items: print fmt % i
+
def diff(ui, repo, *pats, **opts):
"""diff working directory (or selected files)"""
revs = []
@@ -690,7 +703,7 @@
message = "%s\n" % '\n'.join(message)
ui.debug('message:\n%s\n' % message)
- f = os.popen("patch -p%d < %s" % (strip, pf))
+ f = os.popen("patch -p%d < '%s'" % (strip, pf))
files = []
for l in f.read().splitlines():
l.rstrip('\r\n');
@@ -989,7 +1002,7 @@
return default
httpd = hgweb.create_server(repo.root, opts["name"], opts["templates"],
- opts["address"], opts["port"],
+ opts["address"], opts["port"], opts["ipv6"],
openlog('accesslog', sys.stdout),
openlog('errorlog', sys.stderr))
if ui.verbose:
@@ -1015,9 +1028,10 @@
R = removed
? = not tracked'''
- files, matchfn = matchpats(repo.getcwd(), pats, opts)
- (c, a, d, u) = repo.changes(files = files, match = matchfn)
- (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
+ cwd = repo.getcwd()
+ files, matchfn = matchpats(cwd, pats, opts)
+ (c, a, d, u) = [[pathto(cwd, x) for x in n]
+ for n in repo.changes(files=files, match=matchfn)]
for f in c:
ui.write("M ", f, "\n")
@@ -1160,6 +1174,10 @@
"debugstate": (debugstate, [], 'debugstate'),
"debugindex": (debugindex, [], 'debugindex FILE'),
"debugindexdot": (debugindexdot, [], 'debugindexdot FILE'),
+ "debugwalk": (debugwalk,
+ [('I', 'include', [], 'include path in search'),
+ ('X', 'exclude', [], 'exclude path from search')],
+ 'debugwalk [OPTIONS]... [FILE]...'),
"^diff":
(diff,
[('r', 'rev', [], 'revision'),
@@ -1233,7 +1251,8 @@
('a', 'address', '', 'interface address'),
('n', 'name', os.getcwd(), 'repository name'),
('', 'stdio', None, 'for remote clients'),
- ('t', 'templates', "", 'template map')],
+ ('t', 'templates', "", 'template map'),
+ ('6', 'ipv6', None, 'use IPv6 in addition to IPv4')],
"hg serve [OPTION]..."),
"^status": (status,
[('I', 'include', [], 'include path in search'),
--- a/mercurial/hg.py Thu Aug 04 18:23:07 2005 +0100
+++ b/mercurial/hg.py Thu Aug 04 13:27:41 2005 -0800
@@ -440,32 +440,43 @@
dc = self.map.copy()
# walk all files by default
if not files: files = [self.root]
+ known = {'.hg': 1}
+ def seen(fn):
+ if fn in known: return True
+ known[fn] = 1
def traverse():
for f in util.unique(files):
f = os.path.join(self.root, f)
if os.path.isdir(f):
for dir, subdirs, fl in os.walk(f):
d = dir[len(self.root) + 1:]
- if d == '.hg':
+ nd = os.path.normpath(d)
+ if seen(nd):
subdirs[:] = []
continue
for sd in subdirs:
- ds = os.path.join(d, sd +'/')
+ ds = os.path.join(nd, sd +'/')
if self.ignore(ds) or not match(ds):
subdirs.remove(sd)
+ subdirs.sort()
+ fl.sort()
for fn in fl:
fn = util.pconvert(os.path.join(d, fn))
yield 'f', fn
else:
yield 'f', f[len(self.root) + 1:]
- for k in dc.keys():
+ ks = dc.keys()
+ ks.sort()
+ for k in ks:
yield 'm', k
# yield only files that match: all in dirstate, others only if
# not in .hgignore
for src, fn in util.unique(traverse()):
+ fn = os.path.normpath(fn)
+ if seen(fn): continue
if fn in dc:
del dc[fn]
elif self.ignore(fn):
@@ -868,7 +879,7 @@
def walk(self, node = None, files = [], match = util.always):
if node:
for fn in self.manifest.read(self.changelog.read(node)[0]):
- yield 'm', fn
+ if match(fn): yield 'm', fn
else:
for src, fn in self.dirstate.walk(files, match):
yield src, fn
--- a/mercurial/hgweb.py Thu Aug 04 18:23:07 2005 +0100
+++ b/mercurial/hgweb.py Thu Aug 04 13:27:41 2005 -0800
@@ -6,7 +6,7 @@
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
-import os, cgi, time, re, difflib, sys, zlib
+import os, cgi, time, re, difflib, socket, sys, zlib
from mercurial.hg import *
from mercurial.ui import *
@@ -699,11 +699,14 @@
else:
write(self.t("error"))
-def create_server(path, name, templates, address, port,
+def create_server(path, name, templates, address, port, use_ipv6 = False,
accesslog = sys.stdout, errorlog = sys.stderr):
import BaseHTTPServer
+ class IPv6HTTPServer(BaseHTTPServer.HTTPServer):
+ address_family = socket.AF_INET6
+
class hgwebhandler(BaseHTTPServer.BaseHTTPRequestHandler):
def log_error(self, format, *args):
errorlog.write("%s - - [%s] %s\n" % (self.address_string(),
@@ -774,10 +777,13 @@
sys.argv, sys.stdin, sys.stdout, sys.stderr = save
hg = hgweb(path, name, templates)
- return BaseHTTPServer.HTTPServer((address, port), hgwebhandler)
+ if use_ipv6:
+ return IPv6HTTPServer((address, port), hgwebhandler)
+ else:
+ return BaseHTTPServer.HTTPServer((address, port), hgwebhandler)
-def server(path, name, templates, address, port,
+def server(path, name, templates, address, port, use_ipv6 = False,
accesslog = sys.stdout, errorlog = sys.stderr):
- httpd = create_server(path, name, templates, address, port,
+ httpd = create_server(path, name, templates, address, port, use_ipv6,
accesslog, errorlog)
httpd.serve_forever()
--- a/mercurial/util.py Thu Aug 04 18:23:07 2005 +0100
+++ b/mercurial/util.py Thu Aug 04 13:27:41 2005 -0800
@@ -69,24 +69,27 @@
_globchars = {'[': 1, '{': 1, '*': 1, '?': 1}
def matcher(cwd, names, inc, exc, head = ''):
- def patlike(name):
+ def patkind(name):
for prefix in 're:', 'glob:', 'path:':
- if name.startswith(prefix): return True
+ if name.startswith(prefix): return name.split(':', 1)
for c in name:
- if c in _globchars: return True
+ if c in _globchars: return 'glob', name
+ return 'relpath', name
+
+ cwdsep = cwd + os.sep
def regex(name, tail):
'''convert a pattern into a regular expression'''
- if name.startswith('re:'):
- return name[3:]
- elif name.startswith('path:'):
- return '^' + re.escape(name[5:]) + '$'
- elif name.startswith('glob:'):
- return head + globre(name[5:], '', tail)
+ kind, name = patkind(name)
+ if kind == 're':
+ return name
+ elif kind == 'path':
+ return '^' + re.escape(name) + '$'
+ if cwd: name = os.path.join(cwdsep, name)
+ name = os.path.normpath(name)
+ if name == '.': name = '**'
return head + globre(name, '', tail)
- cwdsep = cwd + os.sep
-
def under(fn):
"""check if fn is under our cwd"""
return not cwd or fn.startswith(cwdsep)
@@ -95,22 +98,28 @@
"""build a matching function from a set of patterns"""
if pats:
pat = '(?:%s)' % '|'.join([regex(p, tail) for p in pats])
- if cwd:
- pat = re.escape(cwdsep) + pat
return re.compile(pat).match
- pats = filter(patlike, names)
- files = [n for n in names if not patlike(n)]
- if pats: plain = []
- elif cwd: plain = [cwdsep + f for f in files]
- else: plain = files
+ def globprefix(pat):
+ '''return the non-glob prefix of a path, e.g. foo/* -> foo'''
+ root = []
+ for p in pat.split(os.sep):
+ if patkind(p)[0] == 'glob': break
+ root.append(p)
+ return os.sep.join(root)
+
+ patkinds = map(patkind, names)
+ pats = [name for (kind, name) in patkinds if kind != 'relpath']
+ files = [name for (kind, name) in patkinds if kind == 'relpath']
+ roots = filter(None, map(globprefix, pats)) + files
+ if cwd: roots = [cwdsep + r for r in roots]
- patmatch = matchfn(pats, '$')
- filematch = matchfn(files, '(?:/|$)')
- incmatch = matchfn(inc, '(?:/|$)') or under
+ patmatch = matchfn(pats, '$') or always
+ filematch = matchfn(files, '(?:/|$)') or always
+ incmatch = matchfn(inc, '(?:/|$)') or always
excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False)
- return plain, lambda fn: (incmatch(fn) and not excmatch(fn) and
+ return roots, lambda fn: (incmatch(fn) and not excmatch(fn) and
(fn.endswith('/') or
(not pats and not files) or
(pats and patmatch(fn)) or
--- a/tests/test-merge5.out Thu Aug 04 18:23:07 2005 +0100
+++ b/tests/test-merge5.out Thu Aug 04 13:27:41 2005 -0800
@@ -9,4 +9,4 @@
this update spans a branch affecting the following files:
b
aborting update spanning branches!
-(use update -m to perform a branch merge)
+(use update -m to merge across branches or -C to lose changes)