--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -5,10 +5,8 @@ include hgeditor rewrite-log
include tests/README tests/*.py tests/test-*[a-z0-9] tests/*.out
prune tests/*.err
include *.txt
-include templates/map templates/map-*[a-z0-9]
-include templates/*.tmpl
-include templates/static/*
include doc/README doc/Makefile doc/gendoc.py doc/*.txt doc/*.html doc/*.[0-9]
+recursive-include templates *
recursive-include contrib *
recursive-include hgext *
include README
--- a/contrib/churn.py
+++ b/contrib/churn.py
@@ -58,7 +58,7 @@ def __gather(ui, repo, node1, node2):
for f in added:
lines += dirtywork(f, None, mmap2)
-
+
for f in removed:
lines += dirtywork(f, mmap1, None)
@@ -72,7 +72,7 @@ def __gather(ui, repo, node1, node2):
def gather_stats(ui, repo, amap, revs=None, progress=False):
stats = {}
-
+
cl = repo.changelog
if not revs:
@@ -117,7 +117,7 @@ def gather_stats(ui, repo, amap, revs=No
def churn(ui, repo, **opts):
"Graphs the number of lines changed"
-
+
def pad(s, l):
if len(s) < l:
return s + " " * (l-len(s))
@@ -125,7 +125,7 @@ def churn(ui, repo, **opts):
def graph(n, maximum, width, char):
n = int(n * width / float(maximum))
-
+
return char * (n)
def get_aliases(f):
@@ -137,7 +137,7 @@ def churn(ui, repo, **opts):
aliases[alias] = actual
return aliases
-
+
amap = {}
aliases = opts.get('aliases')
if aliases:
--- a/hgext/fetch.py
+++ b/hgext/fetch.py
@@ -63,7 +63,7 @@ def fetch(ui, repo, source='default', **
revs = [other.lookup(rev) for rev in opts['rev']]
modheads = repo.pull(other, heads=revs, lock=lock)
return postincoming(other, modheads)
-
+
parent, p2 = repo.dirstate.parents()
if parent != repo.changelog.tip():
raise util.Abort(_('working dir not at tip '
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -130,7 +130,7 @@ class queue:
for c in bad_chars:
if c in guard:
return _('invalid character in guard %r: %r') % (guard, c)
-
+
def set_active(self, guards):
for guard in guards:
bad = self.check_guard(guard)
@@ -172,7 +172,7 @@ class queue:
self.full_series[idx] = drop + ''.join([' #' + g for g in guards])
self.parse_series()
self.series_dirty = True
-
+
def pushable(self, idx):
if isinstance(idx, str):
idx = self.series.index(idx)
@@ -724,7 +724,7 @@ class queue:
return (i, a.rev, a.name)
return None
- # if the exact patch name does not exist, we try a few
+ # if the exact patch name does not exist, we try a few
# variations. If strict is passed, we try only #1
#
# 1) a number to indicate an offset in the series file
@@ -1638,7 +1638,7 @@ def guard(ui, repo, *args, **opts):
hg qguard -- -foo
To set guards on another patch:
- hg qguard other.patch +2.6.17 -stable
+ hg qguard other.patch +2.6.17 -stable
'''
def status(idx):
guards = q.series_guards[idx] or ['unguarded']
@@ -1765,7 +1765,7 @@ def rename(ui, repo, patch, name=None, *
absdest = q.join(name)
if os.path.exists(absdest):
raise util.Abort(_('%s already exists') % absdest)
-
+
if name in q.series:
raise util.Abort(_('A patch named %s already exists in the series file') % name)
@@ -1862,7 +1862,7 @@ def select(ui, repo, *args, **opts):
With no arguments, prints the currently active guards.
With one argument, sets the active guard.
-
+
Use -n/--none to deactivate guards (no other arguments needed).
When no guards are active, patches with positive guards are skipped
and patches with negative guards are pushed.
@@ -1952,7 +1952,7 @@ def reposetup(ui, repo):
parent = revlog.hex(self.dirstate.parents()[0])
if parent in [s.rev for s in self.mq.applied]:
raise util.Abort(errmsg)
-
+
def commit(self, *args, **opts):
if len(args) >= 6:
force = args[5]
@@ -1968,7 +1968,7 @@ def reposetup(ui, repo):
if self.mq.applied and not force:
raise util.Abort(_('source has mq patches applied'))
return super(mqrepo, self).push(remote, force, revs)
-
+
def tags(self):
if self.tagscache:
return self.tagscache
--- a/mercurial/changelog.py
+++ b/mercurial/changelog.py
@@ -10,46 +10,91 @@ from i18n import gettext as _
from demandload import demandload
demandload(globals(), "os time util")
+def _string_escape(text):
+ """
+ >>> d = {'nl': chr(10), 'bs': chr(92), 'cr': chr(13), 'nul': chr(0)}
+ >>> s = "ab%(nl)scd%(bs)s%(bs)sn%(nul)sab%(cr)scd%(bs)s%(nl)s" % d
+ >>> s
+ 'ab\\ncd\\\\\\\\n\\x00ab\\rcd\\\\\\n'
+ >>> res = _string_escape(s)
+ >>> s == _string_unescape(res)
+ True
+ """
+ # subset of the string_escape codec
+ text = text.replace('\\', '\\\\').replace('\n', '\\n').replace('\r', '\\r')
+ return text.replace('\0', '\\0')
+
+def _string_unescape(text):
+ return text.decode('string_escape')
+
class changelog(revlog):
def __init__(self, opener, defversion=REVLOGV0):
revlog.__init__(self, opener, "00changelog.i", "00changelog.d",
defversion)
+ def decode_extra(self, text):
+ extra = {}
+ for l in text.split('\0'):
+ if not l:
+ continue
+ k, v = _string_unescape(l).split(':', 1)
+ extra[k] = v
+ return extra
+
+ def encode_extra(self, d):
+ items = [_string_escape(":".join(t)) for t in d.iteritems()]
+ return "\0".join(items)
+
def extract(self, text):
"""
format used:
- nodeid\n : manifest node in ascii
- user\n : user, no \n or \r allowed
- time tz\n : date (time is int or float, timezone is int)
- files\n\n : files modified by the cset, no \n or \r allowed
- (.*) : comment (free text, ideally utf-8)
+ nodeid\n : manifest node in ascii
+ user\n : user, no \n or \r allowed
+ time tz extra\n : date (time is int or float, timezone is int)
+ : extra is metadatas, encoded and separated by '\0'
+ : older versions ignore it
+ files\n\n : files modified by the cset, no \n or \r allowed
+ (.*) : comment (free text, ideally utf-8)
+
+ changelog v0 doesn't use extra
"""
if not text:
return (nullid, "", (0, 0), [], "")
last = text.index("\n\n")
desc = text[last + 2:]
- l = text[:last].splitlines()
+ l = text[:last].split('\n')
manifest = bin(l[0])
user = l[1]
- date = l[2].split(' ')
- time = float(date.pop(0))
- try:
- # various tools did silly things with the time zone field.
- timezone = int(date[0])
- except:
- timezone = 0
+
+ extra_data = l[2].split(' ', 2)
+ if len(extra_data) != 3:
+ time = float(extra_data.pop(0))
+ try:
+ # various tools did silly things with the time zone field.
+ timezone = int(extra_data[0])
+ except:
+ timezone = 0
+ extra = {}
+ else:
+ time, timezone, extra = extra_data
+ time, timezone = float(time), int(timezone)
+ extra = self.decode_extra(extra)
files = l[3:]
- return (manifest, user, (time, timezone), files, desc)
+ return (manifest, user, (time, timezone), files, desc, extra)
def read(self, node):
return self.extract(self.revision(node))
def add(self, manifest, list, desc, transaction, p1=None, p2=None,
- user=None, date=None):
+ user=None, date=None, extra={}):
+
if date:
parseddate = "%d %d" % util.parsedate(date)
else:
parseddate = "%d %d" % util.makedate()
+ if extra:
+ extra = self.encode_extra(extra)
+ parseddate = "%s %s" % (parseddate, extra)
list.sort()
l = [hex(manifest), user, parseddate] + list + ["", desc]
text = "\n".join(l)
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -2502,7 +2502,7 @@ def status(ui, repo, *pats, **opts):
"""
all = opts['all']
-
+
files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
cwd = (pats and repo.getcwd()) or ''
modified, added, removed, deleted, unknown, ignored, clean = [
@@ -3236,7 +3236,7 @@ def load_extensions(ui):
if t in table:
ui.warn(_("module %s overrides %s\n") % (name, t))
table.update(cmdtable)
-
+
def dispatch(args):
for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
num = getattr(signal, name, None)
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -5,13 +5,10 @@
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
-from demandload import *
from node import *
-demandload(globals(), 'bdiff')
-
-from node import *
+from i18n import gettext as _
from demandload import demandload
-demandload(globals(), "ancestor util")
+demandload(globals(), "ancestor bdiff repo revlog util")
class changectx(object):
"""A changecontext object makes access to data related to a particular
@@ -136,10 +133,13 @@ class filectx(object):
self._changeid = self._filelog.linkrev(self._filenode)
return self._changeid
elif name == '_filenode':
- if hasattr(self, "_fileid"):
- self._filenode = self._filelog.lookup(self._fileid)
- else:
- self._filenode = self._changectx.filenode(self._path)
+ try:
+ if hasattr(self, "_fileid"):
+ self._filenode = self._filelog.lookup(self._fileid)
+ else:
+ self._filenode = self._changectx.filenode(self._path)
+ except revlog.RevlogError, inst:
+ raise repo.LookupError(str(inst))
return self._filenode
elif name == '_filerev':
self._filerev = self._filelog.rev(self._filenode)
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -206,7 +206,7 @@ class dirstate(object):
self.dirs = {}
for f in self.map:
self.updatedirs(f, 1)
-
+
def updatedirs(self, path, delta):
if self.dirs is not None:
for c in strutil.findall(path, '/'):
--- a/mercurial/filelog.py
+++ b/mercurial/filelog.py
@@ -7,7 +7,7 @@
from revlog import *
from demandload import *
-demandload(globals(), "bdiff os")
+demandload(globals(), "os")
class filelog(revlog):
def __init__(self, opener, path, defversion=REVLOG_DEFAULT_VERSION):
@@ -84,72 +84,3 @@ class filelog(revlog):
return t2 != text
return revlog.cmp(self, node, text)
-
- def annotate(self, node):
-
- def decorate(text, rev):
- return ([rev] * len(text.splitlines()), text)
-
- def pair(parent, child):
- for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]):
- child[0][b1:b2] = parent[0][a1:a2]
- return child
-
- # find all ancestors
- needed = {(self, node):1}
- files = [self]
- visit = [(self, node)]
- while visit:
- f, n = visit.pop(0)
- rn = f.renamed(n)
- if rn:
- f, n = rn
- f = filelog(self.opener, f, self.defversion)
- files.insert(0, f)
- if (f, n) not in needed:
- needed[(f, n)] = 1
- else:
- needed[(f, n)] += 1
- for p in f.parents(n):
- if p == nullid:
- continue
- if (f, p) not in needed:
- needed[(f, p)] = 1
- visit.append((f, p))
- else:
- # count how many times we'll use this
- needed[(f, p)] += 1
-
- # sort by revision (per file) which is a topological order
- visit = []
- for f in files:
- fn = [(f.rev(n[1]), f, n[1]) for n in needed.keys() if n[0] == f]
- fn.sort()
- visit.extend(fn)
- hist = {}
-
- for i in range(len(visit)):
- r, f, n = visit[i]
- curr = decorate(f.read(n), f.linkrev(n))
- if r == -1:
- continue
- parents = f.parents(n)
- # follow parents across renames
- if r < 1 and i > 0:
- j = i
- while j > 0 and visit[j][1] == f:
- j -= 1
- parents = (visit[j][2],)
- f = visit[j][1]
- else:
- parents = f.parents(n)
- for p in parents:
- if p != nullid:
- curr = pair(hist[p], curr)
- # trim the history of unneeded revs
- needed[(f, p)] -= 1
- if not needed[(f, p)]:
- del hist[p]
- hist[n] = curr
-
- return zip(hist[n][0], hist[n][1].splitlines(1))
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -149,7 +149,8 @@ class hgweb(object):
yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
opts=diffopts), f, tn)
- def changelog(self, pos, shortlog=False):
+ def changelog(self, ctx, shortlog=False):
+ pos = ctx.rev()
def changenav(**map):
def seq(factor, maxchanges=None):
if maxchanges:
@@ -209,7 +210,6 @@ class hgweb(object):
maxchanges = shortlog and self.maxshortchanges or self.maxchanges
cl = self.repo.changelog
- mf = cl.read(cl.tip())[0]
count = cl.count()
start = max(0, pos - maxchanges + 1)
end = min(count, start + maxchanges)
@@ -274,8 +274,7 @@ class hgweb(object):
node=hex(cl.tip()),
entries=changelist)
- def changeset(self, nodeid):
- ctx = self.repo.changectx(nodeid)
+ def changeset(self, ctx):
n = ctx.node()
parents = ctx.parents()
p1 = parents[0].node()
@@ -302,11 +301,10 @@ class hgweb(object):
desc=ctx.description(),
date=ctx.date(),
files=files,
- archives=self.archivelist(nodeid))
+ archives=self.archivelist(hex(n)))
def filelog(self, fctx):
f = fctx.path()
- cl = self.repo.changelog
fl = fctx.filelog()
count = fl.count()
@@ -505,7 +503,6 @@ class hgweb(object):
break;
c = cl.read(n)
- m = c[0]
t = c[2]
yield self.t("tagentry",
@@ -552,21 +549,21 @@ class hgweb(object):
node = hex(self.repo.changelog.tip()),
archives=self.archivelist("tip"))
- def filediff(self, file, changeset):
- ctx = self.repo.changectx(changeset)
- n = ctx.node()
- parents = ctx.parents()
+ def filediff(self, fctx):
+ n = fctx.node()
+ path = fctx.path()
+ parents = fctx.changectx().parents()
p1 = parents[0].node()
def diff(**map):
- yield self.diff(p1, n, [file])
+ yield self.diff(p1, n, [path])
yield self.t("filediff",
- file=file,
+ file=path,
node=hex(n),
- rev=ctx.rev(),
+ rev=fctx.rev(),
parent=self.siblings(parents),
- child=self.siblings(ctx.children()),
+ child=self.siblings(fctx.children()),
diff=diff)
archive_specs = {
@@ -648,25 +645,6 @@ class hgweb(object):
form[name] = value
del form[k]
- if form.has_key('manifest'):
- changeid = req.form['manifest'][0]
- try:
- req.changectx = self.repo.changectx(changeid)
- except hg.RepoError:
- man = self.repo.manifest
- mn = man.lookup(changeid)
- req.changectx = self.repo.changectx(man.linkrev(mn))
-
- if form.has_key('filenode'):
- changeid = req.form['filenode'][0]
- path = self.cleanpath(req.form['file'][0])
- try:
- req.changectx = self.repo.changectx(changeid)
- req.filectx = req.changectx.filectx(path)
- except hg.RepoError:
- req.filectx = self.repo.filectx(path, fileid=changeid)
- req.changectx = req.filectx.changectx()
-
self.refresh()
expand_form(req.form)
@@ -710,6 +688,34 @@ class hgweb(object):
else:
req.write(self.t("error"))
+ def changectx(self, req):
+ if req.form.has_key('node'):
+ changeid = req.form['node'][0]
+ else:
+ changeid = req.form['manifest'][0]
+ try:
+ ctx = self.repo.changectx(changeid)
+ except hg.RepoError:
+ man = self.repo.manifest
+ mn = man.lookup(changeid)
+ ctx = self.repo.changectx(man.linkrev(mn))
+
+ return ctx
+
+ def filectx(self, req):
+ path = self.cleanpath(req.form['file'][0])
+ if req.form.has_key('node'):
+ changeid = req.form['node'][0]
+ else:
+ changeid = req.form['filenode'][0]
+ try:
+ ctx = self.repo.changectx(changeid)
+ fctx = ctx.filectx(path)
+ except hg.RepoError:
+ fctx = self.repo.filectx(path, fileid=changeid)
+
+ return fctx
+
def stripes(self, parity):
"make horizontal stripes for easier reading"
if self.stripecount:
@@ -717,35 +723,31 @@ class hgweb(object):
else:
return 0
- def do_changelog(self, req):
- hi = self.repo.changelog.count() - 1
- if req.form.has_key('rev'):
- hi = req.form['rev'][0]
+ def do_changelog(self, req, shortlog = False):
+ if req.form.has_key('node'):
+ ctx = self.changectx(req)
+ else:
+ if req.form.has_key('rev'):
+ hi = req.form['rev'][0]
+ else:
+ hi = self.repo.changelog.count() - 1
try:
- hi = self.repo.changelog.rev(self.repo.lookup(hi))
+ ctx = self.repo.changectx(hi)
except hg.RepoError:
req.write(self.search(hi)) # XXX redirect to 404 page?
return
- req.write(self.changelog(hi))
+ req.write(self.changelog(ctx, shortlog = shortlog))
def do_shortlog(self, req):
- hi = self.repo.changelog.count() - 1
- if req.form.has_key('rev'):
- hi = req.form['rev'][0]
- try:
- hi = self.repo.changelog.rev(self.repo.lookup(hi))
- except hg.RepoError:
- req.write(self.search(hi)) # XXX redirect to 404 page?
- return
-
- req.write(self.changelog(hi, shortlog = True))
+ self.do_changelog(req, shortlog = True)
def do_changeset(self, req):
- req.write(self.changeset(req.form['node'][0]))
+ ctx = self.repo.changectx(req.form['node'][0])
+ req.write(self.changeset(ctx))
def do_manifest(self, req):
- req.write(self.manifest(req.changectx,
+ req.write(self.manifest(self.changectx(req),
self.cleanpath(req.form['path'][0])))
def do_tags(self, req):
@@ -755,17 +757,16 @@ class hgweb(object):
req.write(self.summary())
def do_filediff(self, req):
- req.write(self.filediff(self.cleanpath(req.form['file'][0]),
- req.form['node'][0]))
+ req.write(self.filediff(self.filectx(req)))
def do_file(self, req):
- req.write(self.filerevision(req.filectx))
+ req.write(self.filerevision(self.filectx(req)))
def do_annotate(self, req):
- req.write(self.fileannotate(req.filectx))
+ req.write(self.fileannotate(self.filectx(req)))
def do_filelog(self, req):
- req.write(self.filelog(req.filectx))
+ req.write(self.filelog(self.filectx(req)))
def do_heads(self, req):
resp = " ".join(map(hex, self.repo.heads())) + "\n"
--- a/mercurial/hgweb/hgwebdir_mod.py
+++ b/mercurial/hgweb/hgwebdir_mod.py
@@ -21,6 +21,7 @@ class hgwebdir(object):
return [(name.strip(os.sep), path) for name, path in items]
self.motd = ""
+ self.style = ""
self.repos_sorted = ('name', False)
if isinstance(config, (list, tuple)):
self.repos = cleannames(config)
@@ -32,8 +33,11 @@ class hgwebdir(object):
cp = ConfigParser.SafeConfigParser()
cp.read(config)
self.repos = []
- if cp.has_section('web') and cp.has_option('web', 'motd'):
- self.motd = cp.get('web', 'motd')
+ if cp.has_section('web'):
+ if cp.has_option('web', 'motd'):
+ self.motd = cp.get('web', 'motd')
+ if cp.has_option('web', 'style'):
+ self.style = cp.get('web', 'style')
if cp.has_section('paths'):
self.repos.extend(cleannames(cp.items('paths')))
if cp.has_section('collections'):
@@ -66,6 +70,15 @@ class hgwebdir(object):
yield tmpl("footer", motd=self.motd, **map)
m = os.path.join(templater.templatepath(), "map")
+ style = self.style
+ if req.form.has_key('style'):
+ style = req.form['style'][0]
+ if style != "":
+ b = os.path.basename("map-" + style)
+ p = os.path.join(templater.templatepath(), b)
+ if os.path.isfile(p):
+ m = p
+
tmpl = templater.templater(m, templater.common_filters,
defaults={"header": header,
"footer": footer})
--- a/mercurial/httprepo.py
+++ b/mercurial/httprepo.py
@@ -165,7 +165,7 @@ class httprepository(remoterepository):
proxyuser, proxypasswd or ''),
proxypath, proxyquery, proxyfrag))
handler = urllib2.ProxyHandler({scheme: proxyurl})
- ui.debug(_('proxying through http://%s:%s\n') %
+ ui.debug(_('proxying through http://%s:%s\n') %
(proxyhost, proxyport))
# urllib2 takes proxy values from the environment and those
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1763,6 +1763,6 @@ def aftertrans(base):
def instance(ui, path, create):
return localrepository(ui, util.drop_scheme('file', path), create)
-
+
def islocal(path):
return True
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -53,7 +53,7 @@ class manifest(revlog):
for f, n in self.parselines(delta):
deltamap.rawset(f, n)
return deltamap
-
+
def read(self, node):
if node == nullid: return manifestdict() # don't upset local cache
if self.mapcache and self.mapcache[0] == node:
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -128,7 +128,7 @@ def readgitpatch(patchname):
self.op = 'MODIFY'
self.copymod = False
self.lineno = 0
-
+
# Filter patch for git information
gitre = re.compile('diff --git a/(.*) b/(.*)')
pf = file(patchname)
@@ -309,7 +309,6 @@ def updatedir(ui, repo, patches, wlock=N
copies = []
removes = []
cfiles = patches.keys()
- copts = {'after': False, 'force': False}
cwd = repo.getcwd()
if cwd:
cfiles = [util.pathto(cwd, f) for f in patches.keys()]
--- a/mercurial/repo.py
+++ b/mercurial/repo.py
@@ -9,6 +9,9 @@
class RepoError(Exception):
pass
+class LookupError(RepoError):
+ pass
+
class repository(object):
def capable(self, name):
'''tell whether repo supports named capability.
--- a/mercurial/sshserver.py
+++ b/mercurial/sshserver.py
@@ -124,7 +124,7 @@ class sshserver(object):
def client_url(self):
client = os.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
return 'remote:ssh:' + client
-
+
def do_unbundle(self):
their_heads = self.getarg()[1].split()
--- a/setup.py
+++ b/setup.py
@@ -9,7 +9,7 @@ import sys
if not hasattr(sys, 'version_info') or sys.version_info < (2, 3):
raise SystemExit, "Mercurial requires python 2.3 or later."
-import glob
+import os
from distutils.core import setup, Extension
from distutils.command.install_data import install_data
@@ -55,9 +55,9 @@ try:
self.includes = []
else:
self.includes = self.includes.split(',')
- mercurial.packagescan.scan(self.build_lib,'mercurial')
- mercurial.packagescan.scan(self.build_lib,'mercurial.hgweb')
- mercurial.packagescan.scan(self.build_lib,'hgext')
+ mercurial.packagescan.scan(self.build_lib, 'mercurial')
+ mercurial.packagescan.scan(self.build_lib, 'mercurial.hgweb')
+ mercurial.packagescan.scan(self.build_lib, 'hgext')
self.includes += mercurial.packagescan.getmodules()
build_exe.finalize_options(self)
except ImportError:
@@ -79,26 +79,24 @@ py2exe_opts = {}
if py2exe_for_demandload is not None:
cmdclass['py2exe'] = py2exe_for_demandload
py2exe_opts['console'] = ['hg']
+
setup(name='mercurial',
- version=mercurial.version.get_version(),
- author='Matt Mackall',
- author_email='mpm@selenic.com',
- url='http://selenic.com/mercurial',
- description='Scalable distributed SCM',
- license='GNU GPL',
- packages=['mercurial', 'mercurial.hgweb', 'hgext'],
- ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
- Extension('mercurial.bdiff', ['mercurial/bdiff.c'])],
- data_files=[('mercurial/templates',
- ['templates/map'] +
- glob.glob('templates/map-*') +
- glob.glob('templates/*.tmpl')),
- ('mercurial/templates/static',
- glob.glob('templates/static/*'))],
- cmdclass=cmdclass,
- scripts=['hg', 'hgmerge'],
- options=dict(bdist_mpkg=dict(zipdist=True,
- license='COPYING',
- readme='contrib/macosx/Readme.html',
- welcome='contrib/macosx/Welcome.html')),
- **py2exe_opts)
+ version=mercurial.version.get_version(),
+ author='Matt Mackall',
+ author_email='mpm@selenic.com',
+ url='http://selenic.com/mercurial',
+ description='Scalable distributed SCM',
+ license='GNU GPL',
+ packages=['mercurial', 'mercurial.hgweb', 'hgext'],
+ ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
+ Extension('mercurial.bdiff', ['mercurial/bdiff.c'])],
+ data_files=[(os.path.join('mercurial', root),
+ [os.path.join(root, file_) for file_ in files])
+ for root, dirs, files in os.walk('templates')],
+ cmdclass=cmdclass,
+ scripts=['hg', 'hgmerge'],
+ options=dict(bdist_mpkg=dict(zipdist=True,
+ license='COPYING',
+ readme='contrib/macosx/Readme.html',
+ welcome='contrib/macosx/Welcome.html')),
+ **py2exe_opts)
rename from templates/changelog-gitweb.tmpl
rename to templates/gitweb/changelog.tmpl
rename from templates/changelogentry-gitweb.tmpl
rename to templates/gitweb/changelogentry.tmpl
rename from templates/changeset-gitweb.tmpl
rename to templates/gitweb/changeset.tmpl
rename from templates/error-gitweb.tmpl
rename to templates/gitweb/error.tmpl
rename from templates/fileannotate-gitweb.tmpl
rename to templates/gitweb/fileannotate.tmpl
rename from templates/filelog-gitweb.tmpl
rename to templates/gitweb/filelog.tmpl
rename from templates/filerevision-gitweb.tmpl
rename to templates/gitweb/filerevision.tmpl
rename from templates/footer-gitweb.tmpl
rename to templates/gitweb/footer.tmpl
rename from templates/header-gitweb.tmpl
rename to templates/gitweb/header.tmpl
new file mode 100644
--- /dev/null
+++ b/templates/gitweb/index.tmpl
@@ -0,0 +1,23 @@
+#header#
+<title>Mercurial repositories index</title>
+</head>
+<body>
+
+<div class="page_header">
+<a href="http://www.selenic.com/mercurial/" title="Mercurial"><div style="float:right;">Mercurial</div></a>Repositories list
+</div>
+
+<table cellspacing="0">
+ <tr>
+ <td><a href="?sort=#sort_name#">Name</a></td>
+ <td><a href="?sort=#sort_description#">Description</a></td>
+ <td><a href="?sort=#sort_contact#">Contact</a></td>
+ <td><a href="?sort=#sort_lastchange#">Last change</a></td>
+ <td> </td>
+ <tr>
+ #entries%indexentry#
+</table>
+<div class="page_footer">
+</div>
+</body>
+</html>
rename from templates/manifest-gitweb.tmpl
rename to templates/gitweb/manifest.tmpl
rename from templates/search-gitweb.tmpl
rename to templates/gitweb/search.tmpl
rename from templates/shortlog-gitweb.tmpl
rename to templates/gitweb/shortlog.tmpl
rename from templates/summary-gitweb.tmpl
rename to templates/gitweb/summary.tmpl
rename from templates/tags-gitweb.tmpl
rename to templates/gitweb/tags.tmpl
--- a/templates/map-gitweb
+++ b/templates/map-gitweb
@@ -1,24 +1,24 @@
default = 'summary'
-header = header-gitweb.tmpl
-footer = footer-gitweb.tmpl
-search = search-gitweb.tmpl
-changelog = changelog-gitweb.tmpl
-summary = summary-gitweb.tmpl
-error = error-gitweb.tmpl
+header = gitweb/header.tmpl
+footer = gitweb/footer.tmpl
+search = gitweb/search.tmpl
+changelog = gitweb/changelog.tmpl
+summary = gitweb/summary.tmpl
+error = gitweb/error.tmpl
naventry = '<a href="?cmd=changelog;rev=#rev#;style=gitweb">#label|escape#</a> '
navshortentry = '<a href="?cmd=shortlog;rev=#rev#;style=gitweb">#label|escape#</a> '
filedifflink = '<a href="?cmd=filediff;node=#node#;file=#file|urlescape#;style=gitweb">#file|escape#</a> '
filenodelink = '<tr class="parity#parity#"><td><a class="list" href="">#file|escape#</a></td><td></td><td class="link"><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">file</a> | <a href="?fa=#node|short#;file=#file|urlescape#;style=gitweb">annotate</a> | <!-- FIXME: <a href="?fd=#node|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?cmd=filelog;filenode=#node|short#;file=#file|urlescape#;style=gitweb">revisions</a></td></tr>'
fileellipses = '...'
-changelogentry = changelogentry-gitweb.tmpl
-searchentry = changelogentry-gitweb.tmpl
-changeset = changeset-gitweb.tmpl
-manifest = manifest-gitweb.tmpl
+changelogentry = gitweb/changelogentry.tmpl
+searchentry = gitweb/changelogentry.tmpl
+changeset = gitweb/changeset.tmpl
+manifest = gitweb/manifest.tmpl
manifestdirentry = '<tr class="parity#parity#"><td style="font-family:monospace">drwxr-xr-x</td><td><a href="?mf=#node|short#;path=#path|urlescape#;style=gitweb">#basename|escape#/</a></td><td class="link"><a href="?mf=#node|short#;path=#path|urlescape#;style=gitweb">manifest</a></td></tr>'
manifestfileentry = '<tr class="parity#parity#"><td style="font-family:monospace">#permissions|permissions#</td><td class="list"><a class="list" href="?f=#node|short#;file=#file|urlescape#;style=gitweb">#basename|escape#</a></td><td class="link"><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">file</a> | <a href="?fl=#node|short#;file=#file|urlescape#;style=gitweb">revisions</a> | <a href="?fa=#node|short#;file=#file|urlescape#;style=gitweb">annotate</a></td></tr>'
-filerevision = filerevision-gitweb.tmpl
-fileannotate = fileannotate-gitweb.tmpl
-filelog = filelog-gitweb.tmpl
+filerevision = gitweb/filerevision.tmpl
+fileannotate = gitweb/fileannotate.tmpl
+filelog = gitweb/filelog.tmpl
fileline = '<div style="font-family:monospace" class="parity#parity#"><pre><span class="linenr"> #linenumber#</span> #line|escape#</pre></div>'
annotateline = '<tr style="font-family:monospace" class="parity#parity#"><td class="linenr" style="text-align: right;"><a href="?fa=#node|short#;file=#file|urlescape#;style=gitweb">#author|obfuscate#@#rev#</a></td><td><pre>#line|escape#</pre></td></tr>'
difflineplus = '<div style="color:#008800;">#line|escape#</div>'
@@ -35,7 +35,7 @@ changelogchild = '<tr><th class="child">
changesetchild = '<tr><td>child</td><td style="font-family:monospace"><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb">#node|short#</a></td></tr>'
filerevchild = '<tr><td class="metatag">child:</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="?cmd=annotate;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
-tags = tags-gitweb.tmpl
+tags = gitweb/tags.tmpl
tagentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#tag|escape#</b></a></td><td class="link"><a href="?cmd=changeset;node=#node|short#;style=gitweb">changeset</a> | <a href="?cmd=changelog;rev=#node|short#;style=gitweb">changelog</a> | <a href="?mf=#node|short#;path=/;style=gitweb">manifest</a></td></tr>'
diffblock = '<pre>#lines#</pre>'
changelogtag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
@@ -44,7 +44,9 @@ filediffparent = '<tr><th class="parent"
filelogparent = '<tr><td align="right">parent #rev#: </td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
filediffchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
filelogchild = '<tr><td align="right">child #rev#: </td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
-shortlog = shortlog-gitweb.tmpl
+shortlog = gitweb/shortlog.tmpl
shortlogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><i>#author#</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="?cmd=changeset;node=#node|short#;style=gitweb">changeset</a> | <a href="?cmd=manifest;manifest=#node|short#;path=/;style=gitweb">manifest</a></td></tr>'
filelogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">file</a> | <!-- FIXME: <a href="?fd=#node|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?fa=#node|short#;file=#file|urlescape#;style=gitweb">annotate</a> #rename%filelogrename#</td></tr>'
-archiveentry = ' | <a href="?ca=#node|short#;type=#type|urlescape#">#type|escape#</a> '
+archiveentry = ' | <a href="#url#?ca=#node|short#;type=#type|urlescape#">#type|escape#</a> '
+indexentry = '<tr class="parity#parity#"><td><a class="list" href="#url#"><b>#name|escape#</b></a></td><td>#description#</td><td>#contact|obfuscate#</td><td class="age">#lastchange|age# ago</td><td class="indexlinks"><a class="rss_logo" href="#url#?cl=tip;style=rss">RSS</a> #archives%archiveentry#</td></tr>'
+index = gitweb/index.tmpl
--- a/templates/map-raw
+++ b/templates/map-raw
@@ -1,6 +1,6 @@
-header = header-raw.tmpl
+header = raw/header.tmpl
footer = ''
-changeset = changeset-raw.tmpl
+changeset = raw/changeset.tmpl
difflineplus = '#line#'
difflineminus = '#line#'
difflineat = '#line#'
@@ -11,6 +11,6 @@ filenodelink = ''
filerevision = '#rawfileheader##raw#'
fileline = '#line#'
diffblock = '#lines#'
-filediff = filediff-raw.tmpl
-fileannotate = fileannotate-raw.tmpl
+filediff = raw/filediff.tmpl
+fileannotate = raw/fileannotate.tmpl
annotateline = '#author#@#rev#: #line#'
--- a/templates/map-rss
+++ b/templates/map-rss
@@ -1,8 +1,8 @@
default = 'changelog'
-header = header-rss.tmpl
-changelog = changelog-rss.tmpl
-changelogentry = changelogentry-rss.tmpl
-filelog = filelog-rss.tmpl
-filelogentry = filelogentry-rss.tmpl
-tags = tags-rss.tmpl
-tagentry = tagentry-rss.tmpl
+header = rss/header.tmpl
+changelog = rss/changelog.tmpl
+changelogentry = rss/changelogentry.tmpl
+filelog = rss/filelog.tmpl
+filelogentry = rss/filelogentry.tmpl
+tags = rss/tags.tmpl
+tagentry = rss/tagentry.tmpl
rename from templates/changeset-raw.tmpl
rename to templates/raw/changeset.tmpl
rename from templates/fileannotate-raw.tmpl
rename to templates/raw/fileannotate.tmpl
rename from templates/filediff-raw.tmpl
rename to templates/raw/filediff.tmpl
rename from templates/header-raw.tmpl
rename to templates/raw/header.tmpl
rename from templates/changelog-rss.tmpl
rename to templates/rss/changelog.tmpl
rename from templates/changelogentry-rss.tmpl
rename to templates/rss/changelogentry.tmpl
rename from templates/filelog-rss.tmpl
rename to templates/rss/filelog.tmpl
rename from templates/filelogentry-rss.tmpl
rename to templates/rss/filelogentry.tmpl
rename from templates/header-rss.tmpl
rename to templates/rss/header.tmpl
rename from templates/tagentry-rss.tmpl
rename to templates/rss/tagentry.tmpl
rename from templates/tags-rss.tmpl
rename to templates/rss/tags.tmpl
--- a/templates/template-vars.txt
+++ b/templates/template-vars.txt
@@ -12,7 +12,7 @@ date a date string
age age in hours, days, etc
line a line of text (escaped)
desc a description (escaped, with breaks)
-shortdesc a short description (escaped)
+shortdesc a short description (escaped)
author a name or email addressv(obfuscated)
parent a list of the parent
child a list of the children
--- a/tests/coverage.py
+++ b/tests/coverage.py
@@ -87,19 +87,19 @@ class StatementFindingAstVisitor(compile
self.excluded = excluded
self.suite_spots = suite_spots
self.excluding_suite = 0
-
+
def doRecursive(self, node):
self.recordNodeLine(node)
for n in node.getChildNodes():
self.dispatch(n)
visitStmt = visitModule = doRecursive
-
+
def doCode(self, node):
if hasattr(node, 'decorators') and node.decorators:
self.dispatch(node.decorators)
self.doSuite(node, node.code)
-
+
visitFunction = visitClass = doCode
def getFirstLine(self, node):
@@ -119,17 +119,17 @@ class StatementFindingAstVisitor(compile
for n in node.getChildNodes():
lineno = max(lineno, self.getLastLine(n))
return lineno
-
+
def doStatement(self, node):
self.recordLine(self.getFirstLine(node))
visitAssert = visitAssign = visitAssTuple = visitDiscard = visitPrint = \
visitPrintnl = visitRaise = visitSubscript = visitDecorators = \
doStatement
-
+
def recordNodeLine(self, node):
return self.recordLine(node.lineno)
-
+
def recordLine(self, lineno):
# Returns a bool, whether the line is included or excluded.
if lineno:
@@ -153,9 +153,9 @@ class StatementFindingAstVisitor(compile
self.statements[lineno] = 1
return 1
return 0
-
+
default = recordNodeLine
-
+
def recordAndDispatch(self, node):
self.recordNodeLine(node)
self.dispatch(node)
@@ -166,7 +166,7 @@ class StatementFindingAstVisitor(compile
self.excluding_suite = 1
self.recordAndDispatch(body)
self.excluding_suite = exsuite
-
+
def doPlainWordSuite(self, prevsuite, suite):
# Finding the exclude lines for else's is tricky, because they aren't
# present in the compiler parse tree. Look at the previous suite,
@@ -180,11 +180,11 @@ class StatementFindingAstVisitor(compile
break
else:
self.doSuite(None, suite)
-
+
def doElse(self, prevsuite, node):
if node.else_:
self.doPlainWordSuite(prevsuite, node.else_)
-
+
def visitFor(self, node):
self.doSuite(node, node.body)
self.doElse(node.body, node)
@@ -216,11 +216,11 @@ class StatementFindingAstVisitor(compile
else:
self.doSuite(a, h)
self.doElse(node.handlers[-1][2], node)
-
+
def visitTryFinally(self, node):
self.doSuite(node, node.body)
self.doPlainWordSuite(node.body, node.final)
-
+
def visitGlobal(self, node):
# "global" statements don't execute like others (they don't call the
# trace function), so don't record their line numbers.
@@ -240,7 +240,7 @@ class coverage:
# A dictionary with an entry for (Python source file name, line number
# in that file) if that line has been executed.
c = {}
-
+
# A map from canonical Python source file name to a dictionary in
# which there's an entry for each line number that has been
# executed.
@@ -266,12 +266,12 @@ class coverage:
self.xstack = []
self.relative_dir = os.path.normcase(os.path.abspath(os.curdir)+os.path.sep)
- # t(f, x, y). This method is passed to sys.settrace as a trace function.
- # See [van Rossum 2001-07-20b, 9.2] for an explanation of sys.settrace and
+ # t(f, x, y). This method is passed to sys.settrace as a trace function.
+ # See [van Rossum 2001-07-20b, 9.2] for an explanation of sys.settrace and
# the arguments and return value of the trace function.
# See [van Rossum 2001-07-20a, 3.2] for a description of frame and code
# objects.
-
+
def t(self, f, w, a): #pragma: no cover
#print w, f.f_code.co_filename, f.f_lineno
if w == 'line':
@@ -279,7 +279,7 @@ class coverage:
for c in self.cstack:
c[(f.f_code.co_filename, f.f_lineno)] = 1
return self.t
-
+
def help(self, error=None):
if error:
print error
@@ -330,7 +330,7 @@ class coverage:
self.help("You must specify at least one of -e, -x, -r, or -a.")
if not args_needed and args:
self.help("Unexpected arguments %s." % args)
-
+
self.get_ready()
self.exclude('#pragma[: ]+[nN][oO] [cC][oO][vV][eE][rR]')
@@ -359,14 +359,14 @@ class coverage:
def use_cache(self, usecache):
self.usecache = usecache
-
+
def get_ready(self):
if self.usecache and not self.cache:
self.cache = os.path.abspath(os.environ.get(self.cache_env,
self.cache_default))
self.restore()
self.analysis_cache = {}
-
+
def start(self):
self.get_ready()
if self.nesting == 0: #pragma: no cover
@@ -374,7 +374,7 @@ class coverage:
if hasattr(threading, 'settrace'):
threading.settrace(self.t)
self.nesting += 1
-
+
def stop(self):
self.nesting -= 1
if self.nesting == 0: #pragma: no cover
@@ -398,7 +398,7 @@ class coverage:
def begin_recursive(self):
self.cstack.append(self.c)
self.xstack.append(self.exclude_re)
-
+
def end_recursive(self):
self.c = self.cstack.pop()
self.exclude_re = self.xstack.pop()
@@ -452,7 +452,7 @@ class coverage:
self.canonical_filename_cache[filename] = cf
return self.canonical_filename_cache[filename]
- # canonicalize_filenames(). Copy results from "c" to "cexecuted",
+ # canonicalize_filenames(). Copy results from "c" to "cexecuted",
# canonicalizing filenames on the way. Clear the "c" map.
def canonicalize_filenames(self):
@@ -550,7 +550,7 @@ class coverage:
import parser
tree = parser.suite(text+'\n\n').totuple(1)
self.get_suite_spots(tree, suite_spots)
-
+
# Use the compiler module to parse the text and find the executable
# statements. We add newlines to be impervious to final partial lines.
statements = {}
@@ -713,7 +713,7 @@ class coverage:
except:
if not ignore_errors:
raise
-
+
def annotate_file(self, filename, statements, excluded, missing, directory=None):
source = open(filename, 'r')
if directory:
@@ -741,7 +741,7 @@ class coverage:
if self.blank_re.match(line):
dest.write(' ')
elif self.else_re.match(line):
- # Special logic for lines containing only 'else:'.
+ # Special logic for lines containing only 'else:'.
# See [GDR 2001-12-04b, 3.2].
if i >= len(statements) and j >= len(missing):
dest.write('! ')
@@ -850,7 +850,7 @@ if __name__ == '__main__':
# Thanks, Allen.
#
# 2005-12-02 NMB Call threading.settrace so that all threads are measured.
-# Thanks Martin Fuzzey. Add a file argument to report so that reports can be
+# Thanks Martin Fuzzey. Add a file argument to report so that reports can be
# captured to a different destination.
#
# 2005-12-03 NMB coverage.py can now measure itself.
--- a/tests/md5sum.py
+++ b/tests/md5sum.py
@@ -16,7 +16,7 @@ for filename in sys.argv[1:]:
except IOError, msg:
sys.stderr.write('%s: Can\'t open: %s\n' % (filename, msg))
sys.exit(1)
-
+
m = md5.new()
try:
while 1:
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -104,7 +104,7 @@ def use_correct_python():
# windows fallback
shutil.copyfile(sys.executable, my_python)
shutil.copymode(sys.executable, my_python)
-
+
def install_hg():
vlog("# Performing temporary installation of HG")
installerrs = os.path.join("tests", "install.err")
@@ -358,7 +358,7 @@ try:
args = os.listdir(".")
for test in args:
if (test.startswith("test-") and '~' not in test and
- ('.' not in test or test.endswith('.py') or
+ ('.' not in test or test.endswith('.py') or
test.endswith('.bat'))):
ret = run_one(test)
if ret is None:
new file mode 100644
--- /dev/null
+++ b/tests/test-doctest.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+#
+
+import doctest
+
+import mercurial.changelog
+# test doctest from changelog
+
+doctest.testmod(mercurial.changelog)
+
--- a/tests/test-merge-revert2
+++ b/tests/test-merge-revert2
@@ -27,8 +27,7 @@ hg id
hg update -C 0
echo "changed file1 different" >> file1
HGMERGE=merge hg update
-#hg diff --nodates | sed -e "s/\(<<<<<<<\) .*/\1/" -e "s/\(>>>>>>>\) .*/\1/"
-hg diff --nodates | sed -e "s/\(<<<<<<<\|>>>>>>>\) .*/\1/"
+hg diff --nodates | sed -e "s/\(<<<<<<<\) .*/\1/" -e "s/\(>>>>>>>\) .*/\1/"
hg status
hg id
hg revert --no-backup --all