diff --git a/contrib/mercurial.el b/contrib/mercurial.el
--- a/contrib/mercurial.el
+++ b/contrib/mercurial.el
@@ -382,14 +382,27 @@ Handle frickin' frackin' gratuitous even
(set-buffer hg-prev-buffer))
(let ((path (or default (buffer-file-name))))
(if (or (not path) current-prefix-arg)
- (expand-file-name
- (read-file-name (format "File, directory or pattern%s: "
- (or prompt ""))
- (and path (file-name-directory path))
- nil nil
- (and path (file-name-nondirectory path))
- 'hg-file-history))
- path))))
+ (expand-file-name
+ (eval (list* 'read-file-name
+ (format "File, directory or pattern%s: "
+ (or prompt ""))
+ (and path (file-name-directory path))
+ nil nil
+ (and path (file-name-nondirectory path))
+ (if hg-running-xemacs
+ (cons (quote 'hg-file-history) nil)
+ nil))))
+ path))))
+
+(defun hg-read-number (&optional prompt default)
+ "Read a integer value."
+ (save-excursion
+ (if (or (not default) current-prefix-arg)
+ (string-to-number
+ (eval (list* 'read-string
+ (or prompt "")
+ (if default (cons (format "%d" default) nil) nil))))
+ default)))
(defun hg-read-config ()
"Return an alist of (key . value) pairs of Mercurial config data.
@@ -950,36 +963,55 @@ With a prefix argument, prompt for the p
(kill-entire-line))
(run-hooks 'hg-log-mode-hook))
-(defun hg-log (path &optional rev1 rev2)
- "Display the revision history of PATH, between REV1 and REV2.
-REV1 defaults to hg-log-limit changes from the tip revision, while
-REV2 defaults to the tip.
+(defun hg-log (path &optional rev1 rev2 log-limit)
+ "Display the revision history of PATH.
+History is displayed between REV1 and REV2.
+Number of displayed changesets is limited to LOG-LIMIT.
+REV1 defaults to the tip, while
+REV2 defaults to `hg-rev-completion-limit' changes from the tip revision.
+LOG-LIMIT defaults to `hg-log-limit'.
With a prefix argument, prompt for each parameter."
(interactive (list (hg-read-file-name " to log")
- (hg-read-rev " to start with" "-1")
- (hg-read-rev " to end with" (format "-%d" hg-log-limit))))
+ (hg-read-rev " to start with"
+ "tip")
+ (hg-read-rev " to end with"
+ (format "%d" (- hg-rev-completion-limit)))
+ (hg-read-number "Output limited to: "
+ hg-log-limit)))
(let ((a-path (hg-abbrev-file-name path))
- (r1 (or rev1 (format "-%d" hg-log-limit)))
- (r2 (or rev2 rev1 "-1")))
+ (r1 (or rev1 (format "-%d" hg-rev-completion-limit)))
+ (r2 (or rev2 rev1 "tip"))
+ (limit (format "%d" (or log-limit hg-log-limit))))
(hg-view-output ((if (equal r1 r2)
- (format "Mercurial: Log of rev %s of %s" rev1 a-path)
- (format "Mercurial: Log from rev %s to %s of %s"
- r1 r2 a-path)))
- (let ((revs (format "%s:%s" r1 r2)))
- (if (> (length path) (length (hg-root path)))
- (call-process (hg-binary) nil t nil "log" "-r" revs path)
- (call-process (hg-binary) nil t nil "log" "-r" revs)))
+ (format "Mercurial: Log of rev %s of %s" rev1 a-path)
+ (format
+ "Mercurial: at most %s log(s) from rev %s to %s of %s"
+ limit r1 r2 a-path)))
+ (eval (list* 'call-process (hg-binary) nil t nil
+ "log"
+ "-r" (format "%s:%s" r1 r2)
+ "-l" limit
+ (if (> (length path) (length (hg-root path)))
+ (cons path nil)
+ nil)))
(hg-log-mode))))
-(defun hg-log-repo (path &optional rev1 rev2)
+(defun hg-log-repo (path &optional rev1 rev2 log-limit)
"Display the revision history of the repository containing PATH.
-History is displayed between REV1, which defaults to the tip, and
-REV2, which defaults to the initial revision.
-Variable hg-log-limit controls the number of log entries displayed."
+History is displayed between REV1 and REV2.
+Number of displayed changesets is limited to LOG-LIMIT,
+REV1 defaults to the tip, while
+REV2 defaults to `hg-rev-completion-limit' changes from the tip revision.
+LOG-LIMIT defaults to `hg-log-limit'.
+With a prefix argument, prompt for each parameter."
(interactive (list (hg-read-file-name " to log")
- (hg-read-rev " to start with" "tip")
- (hg-read-rev " to end with" (format "-%d" hg-log-limit))))
- (hg-log (hg-root path) rev1 rev2))
+ (hg-read-rev " to start with"
+ "tip")
+ (hg-read-rev " to end with"
+ (format "%d" (- hg-rev-completion-limit)))
+ (hg-read-number "Output limited to: "
+ hg-log-limit)))
+ (hg-log (hg-root path) rev1 rev2 log-limit))
(defun hg-outgoing (&optional repo)
"Display changesets present locally that are not present in REPO."
diff --git a/contrib/win32/ReadMe.html b/contrib/win32/ReadMe.html
--- a/contrib/win32/ReadMe.html
+++ b/contrib/win32/ReadMe.html
@@ -89,6 +89,16 @@ hg
This command should print a useful help message. If it does,
other Mercurial commands should work fine for you.
+ Configuration notes
+ The default editor for commit messages is 'vi'. You can set the EDITOR
+ (or HGEDITOR) environment variable to specify your preference or set it in
+ mercurial.ini:
+
+[ui]
+editor = whatever
+
+
+
Reporting problems
Before you report any problems, please consult the /.hg/hgrc::
Per-repository configuration options that only apply in a
diff --git a/hgext/bugzilla.py b/hgext/bugzilla.py
--- a/hgext/bugzilla.py
+++ b/hgext/bugzilla.py
@@ -22,13 +22,16 @@
#
# config items:
#
+# section name is 'bugzilla'.
+# [bugzilla]
+#
# REQUIRED:
# host = bugzilla # mysql server where bugzilla database lives
# password = ** # user's password
# version = 2.16 # version of bugzilla installed
#
# OPTIONAL:
-# bzuser = ... # bugzilla user id to record comments with
+# bzuser = ... # fallback bugzilla user name to record comments with
# db = bugs # database to connect to
# notify = ... # command to run to get bugzilla to send mail
# regexp = ... # regexp to match bug ids (must contain one "()" group)
@@ -39,6 +42,15 @@
# user = bugs # user to connect to database as
# [web]
# baseurl = http://hgserver/... # root of hg web site for browsing commits
+#
+# if hg committer names are not same as bugzilla user names, use
+# "usermap" feature to map from committer email to bugzilla user name.
+# usermap can be in hgrc or separate config file.
+#
+# [bugzilla]
+# usermap = filename # cfg file with "committer"="bugzilla user" info
+# [usermap]
+# committer_email = bugzilla_user_name
from mercurial.demandload import *
from mercurial.i18n import gettext as _
@@ -60,6 +72,9 @@ class bugzilla_2_16(object):
passwd = self.ui.config('bugzilla', 'password')
db = self.ui.config('bugzilla', 'db', 'bugs')
timeout = int(self.ui.config('bugzilla', 'timeout', 5))
+ usermap = self.ui.config('bugzilla', 'usermap')
+ if usermap:
+ self.ui.readconfig(usermap)
self.ui.note(_('connecting to %s:%s as %s, password %s\n') %
(host, db, user, '*' * len(passwd)))
self.conn = MySQLdb.connect(host=host, user=user, passwd=passwd,
@@ -139,18 +154,29 @@ class bugzilla_2_16(object):
self.user_ids[user] = userid
return userid
- def add_comment(self, bugid, text, prefuser):
+ def map_committer(self, user):
+ '''map name of committer to bugzilla user name.'''
+ for committer, bzuser in self.ui.configitems('usermap'):
+ if committer.lower() == user.lower():
+ return bzuser
+ return user
+
+ def add_comment(self, bugid, text, committer):
'''add comment to bug. try adding comment as committer of
changeset, otherwise as default bugzilla user.'''
+ user = self.map_committer(committer)
try:
- userid = self.get_user_id(prefuser)
+ userid = self.get_user_id(user)
except KeyError:
try:
defaultuser = self.ui.config('bugzilla', 'bzuser')
+ if not defaultuser:
+ raise util.Abort(_('cannot find bugzilla user id for %s') %
+ user)
userid = self.get_user_id(defaultuser)
except KeyError:
- raise util.Abort(_('cannot find user id for %s or %s') %
- (prefuser, defaultuser))
+ raise util.Abort(_('cannot find bugzilla user id for %s or %s') %
+ (user, defaultuser))
now = time.strftime('%Y-%m-%d %H:%M:%S')
self.run('''insert into longdescs
(bug_id, who, bug_when, thetext)
diff --git a/hgext/hbisect.py b/hgext/hbisect.py
--- a/hgext/hbisect.py
+++ b/hgext/hbisect.py
@@ -173,7 +173,7 @@ class bisect(object):
self.ui.warn("Could not find the first bad revision\n")
sys.exit(1)
self.ui.write(
- "The first bad revision is : %s\n" % hg.hex(self.badrev))
+ "The first bad revision is: %s\n" % hg.hex(self.badrev))
sys.exit(0)
self.ui.write("%d revisions left\n" % tot)
best_rev = None
diff --git a/hgext/mq.py b/hgext/mq.py
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -102,6 +102,7 @@ class queue:
message = []
comments = []
user = None
+ date = None
format = None
subject = None
diffstart = 0
@@ -119,6 +120,8 @@ class queue:
# parse values when importing the result of an hg export
if line.startswith("# User "):
user = line[7:]
+ elif line.startswith("# Date "):
+ date = line[7:]
elif not line.startswith("# ") and line:
message.append(line)
format = None
@@ -136,7 +139,7 @@ class queue:
# when looking for tags (subject: from: etc) they
# end once you find a blank line in the source
format = "tagdone"
- else:
+ elif message or line:
message.append(line)
comments.append(line)
@@ -149,7 +152,7 @@ class queue:
if format and format.startswith("tag") and subject:
message.insert(0, "")
message.insert(0, subject)
- return (message, comments, user, diffstart > 1)
+ return (message, comments, user, date, diffstart > 1)
def mergeone(self, repo, mergeq, head, patch, rev, wlock):
# first try just applying the patch
@@ -179,7 +182,7 @@ class queue:
self.ui.warn("repo commit failed\n")
sys.exit(1)
try:
- message, comments, user, patchfound = mergeq.readheaders(patch)
+ message, comments, user, date, patchfound = mergeq.readheaders(patch)
except:
self.ui.warn("Unable to read %s\n" % patch)
sys.exit(1)
@@ -267,7 +270,7 @@ class queue:
pf = os.path.join(patchdir, patch)
try:
- message, comments, user, patchfound = self.readheaders(patch)
+ message, comments, user, date, patchfound = self.readheaders(patch)
except:
self.ui.warn("Unable to read %s\n" % pf)
err = 1
@@ -326,7 +329,7 @@ class queue:
if len(files) > 0:
commands.addremove_lock(self.ui, repo, files,
opts={}, wlock=wlock)
- n = repo.commit(files, message, user, force=1, lock=lock,
+ n = repo.commit(files, message, user, date, force=1, lock=lock,
wlock=wlock)
if n == None:
@@ -716,7 +719,7 @@ class queue:
top = revlog.bin(top)
cparents = repo.changelog.parents(top)
patchparent = self.qparents(repo, top)
- message, comments, user, patchfound = self.readheaders(patch)
+ message, comments, user, date, patchfound = self.readheaders(patch)
patchf = self.opener(patch, "w")
if comments:
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1392,6 +1392,7 @@ def doexport(ui, repo, changeset, seqno,
fp.write("# HG changeset patch\n")
fp.write("# User %s\n" % change[1])
+ fp.write("# Date %d %d\n" % change[2])
fp.write("# Node ID %s\n" % hex(node))
fp.write("# Parent %s\n" % hex(prev))
if len(parents) > 1:
@@ -1687,6 +1688,7 @@ def import_(ui, repo, patch1, *patches,
message = []
user = None
+ date = None
hgpatch = False
for line in file(pf):
line = line.rstrip()
@@ -1703,27 +1705,29 @@ def import_(ui, repo, patch1, *patches,
if line.startswith("# User "):
user = line[7:]
ui.debug(_('User: %s\n') % user)
+ elif line.startswith("# Date "):
+ date = line[7:]
elif not line.startswith("# ") and line:
message.append(line)
hgpatch = False
elif line == '# HG changeset patch':
hgpatch = True
message = [] # We may have collected garbage
- else:
+ elif message or line:
message.append(line)
# make sure message isn't empty
if not message:
message = _("imported patch %s\n") % patch
else:
- message = "%s\n" % '\n'.join(message)
+ message = '\n'.join(message).rstrip()
ui.debug(_('message:\n%s\n') % message)
files = util.patch(strip, pf, ui)
if len(files) > 0:
addremove_lock(ui, repo, files, {})
- repo.commit(files, message, user)
+ repo.commit(files, message, user, date)
def incoming(ui, repo, source="default", **opts):
"""show new changesets found in source
@@ -2185,34 +2189,42 @@ def remove(ui, repo, *pats, **opts):
entire project history. If the files still exist in the working
directory, they will be deleted from it. If invoked with --after,
files that have been manually deleted are marked as removed.
+
+ Modified files and added files are not removed by default. To
+ remove them, use the -f/--force option.
"""
names = []
if not opts['after'] and not pats:
raise util.Abort(_('no files specified'))
- def okaytoremove(abs, rel, exact):
- modified, added, removed, deleted, unknown = repo.changes(files=[abs])
+ files, matchfn, anypats = matchpats(repo, pats, opts)
+ exact = dict.fromkeys(files)
+ mardu = map(dict.fromkeys, repo.changes(files=files, match=matchfn))
+ modified, added, removed, deleted, unknown = mardu
+ remove, forget = [], []
+ for src, abs, rel, exact in walk(repo, pats, opts):
reason = None
- if not deleted and opts['after']:
+ if abs not in deleted and opts['after']:
reason = _('is still present')
- elif modified and not opts['force']:
- reason = _('is modified')
- elif added:
- reason = _('has been marked for add')
- elif unknown:
+ elif abs in modified and not opts['force']:
+ reason = _('is modified (use -f to force removal)')
+ elif abs in added:
+ if opts['force']:
+ forget.append(abs)
+ continue
+ reason = _('has been marked for add (use -f to force removal)')
+ elif abs in unknown:
reason = _('is not managed')
- elif removed:
- return False
+ elif abs in removed:
+ continue
if reason:
if exact:
ui.warn(_('not removing %s: file %s\n') % (rel, reason))
else:
- return True
- for src, abs, rel, exact in walk(repo, pats, opts):
- if okaytoremove(abs, rel, exact):
if ui.verbose or not exact:
ui.status(_('removing %s\n') % rel)
- names.append(abs)
- repo.remove(names, unlink=not opts['after'])
+ remove.append(abs)
+ repo.forget(forget)
+ repo.remove(remove, unlink=not opts['after'])
def rename(ui, repo, *pats, **opts):
"""rename files; equivalent of copy + remove
diff --git a/mercurial/demandload.py b/mercurial/demandload.py
--- a/mercurial/demandload.py
+++ b/mercurial/demandload.py
@@ -81,6 +81,10 @@ class _replacer_from(_replacer):
return getattr(importer.module(), target)
+ def __call__(self, *args, **kwargs):
+ target = object.__getattribute__(self, 'module')()
+ return target(*args, **kwargs)
+
def demandload(scope, modules):
'''import modules into scope when each is first used.
diff --git a/mercurial/hgweb.py b/mercurial/hgweb/__init__.py
rename from mercurial/hgweb.py
rename to mercurial/hgweb/__init__.py
--- a/mercurial/hgweb.py
+++ b/mercurial/hgweb/__init__.py
@@ -8,12 +8,12 @@
import os, cgi, sys
import mimetypes
-from demandload import demandload
-demandload(globals(), "mdiff time re socket zlib errno ui hg ConfigParser")
-demandload(globals(), "tempfile StringIO BaseHTTPServer util SocketServer")
-demandload(globals(), "archival mimetypes templater urllib")
-from node import *
-from i18n import gettext as _
+from mercurial.demandload import demandload
+demandload(globals(), "time re socket zlib errno ConfigParser tempfile")
+demandload(globals(), "StringIO BaseHTTPServer SocketServer urllib")
+demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,templater")
+from mercurial.node import *
+from mercurial.i18n import gettext as _
def splitURI(uri):
""" Return path and query splited from uri
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -166,37 +166,44 @@ class localrepository(object):
return
s = l.split(" ", 1)
if len(s) != 2:
- self.ui.warn(_("%s: ignoring invalid tag\n") % context)
+ self.ui.warn(_("%s: cannot parse entry\n") % context)
return
node, key = s
+ key = key.strip()
try:
bin_n = bin(node)
except TypeError:
- self.ui.warn(_("%s: ignoring invalid tag\n") % context)
+ self.ui.warn(_("%s: node '%s' is not well formed\n") %
+ (context, node))
return
if bin_n not in self.changelog.nodemap:
- self.ui.warn(_("%s: ignoring invalid tag\n") % context)
+ self.ui.warn(_("%s: tag '%s' refers to unknown node\n") %
+ (context, key))
return
- self.tagscache[key.strip()] = bin_n
+ self.tagscache[key] = bin_n
- # read each head of the tags file, ending with the tip
+ # read the tags file from each head, ending with the tip,
# and add each tag found to the map, with "newer" ones
# taking precedence
+ heads = self.heads()
+ heads.reverse()
fl = self.file(".hgtags")
- h = fl.heads()
- h.reverse()
- for r in h:
+ for node in heads:
+ change = self.changelog.read(node)
+ rev = self.changelog.rev(node)
+ fn, ff = self.manifest.find(change[0], '.hgtags')
+ if fn is None: continue
count = 0
- for l in fl.read(r).splitlines():
+ for l in fl.read(fn).splitlines():
count += 1
- parsetag(l, ".hgtags:%d" % count)
-
+ parsetag(l, _(".hgtags (rev %d:%s), line %d") %
+ (rev, short(node), count))
try:
f = self.opener("localtags")
count = 0
for l in f:
count += 1
- parsetag(l, "localtags:%d" % count)
+ parsetag(l, _("localtags, line %d") % count)
except IOError:
pass
@@ -550,12 +557,15 @@ class localrepository(object):
# run editor in the repository root
olddir = os.getcwd()
os.chdir(self.root)
- edittext = self.ui.edit("\n".join(edittext), user)
+ text = self.ui.edit("\n".join(edittext), user)
os.chdir(olddir)
- if not edittext.rstrip():
- return None
- text = edittext
+ lines = [line.rstrip() for line in text.rstrip().splitlines()]
+ while lines and not lines[0]:
+ del lines[0]
+ if not lines:
+ return None
+ text = '\n'.join(lines)
n = self.changelog.add(mn, changed + remove, text, tr, p1, p2, user, date)
self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
parent2=xp2)
diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -43,48 +43,61 @@ class manifest(revlog):
def diff(self, a, b):
return mdiff.textdiff(str(a), str(b))
+ def _search(self, m, s, lo=0, hi=None):
+ '''return a tuple (start, end) that says where to find s within m.
+
+ If the string is found m[start:end] are the line containing
+ that string. If start == end the string was not found and
+ they indicate the proper sorted insertion point. This was
+ taken from bisect_left, and modified to find line start/end as
+ it goes along.
+
+ m should be a buffer or a string
+ s is a string'''
+ def advance(i, c):
+ while i < lenm and m[i] != c:
+ i += 1
+ return i
+ lenm = len(m)
+ if not hi:
+ hi = lenm
+ while lo < hi:
+ mid = (lo + hi) // 2
+ start = mid
+ while start > 0 and m[start-1] != '\n':
+ start -= 1
+ end = advance(start, '\0')
+ if m[start:end] < s:
+ # we know that after the null there are 40 bytes of sha1
+ # this translates to the bisect lo = mid + 1
+ lo = advance(end + 40, '\n') + 1
+ else:
+ # this translates to the bisect hi = mid
+ hi = start
+ end = advance(lo, '\0')
+ found = m[lo:end]
+ if cmp(s, found) == 0:
+ # we know that after the null there are 40 bytes of sha1
+ end = advance(end + 40, '\n')
+ return (lo, end+1)
+ else:
+ return (lo, lo)
+
+ def find(self, node, f):
+ '''look up entry for a single file efficiently.
+ return (node, flag) pair if found, (None, None) if not.'''
+ if self.mapcache and node == self.mapcache[0]:
+ return self.mapcache[1].get(f), self.mapcache[2].get(f)
+ text = self.revision(node)
+ start, end = self._search(text, f)
+ if start == end:
+ return None, None
+ l = text[start:end]
+ f, n = l.split('\0')
+ return bin(n[:40]), n[40:-1] == 'x'
+
def add(self, map, flags, transaction, link, p1=None, p2=None,
changed=None):
-
- # returns a tuple (start, end). If the string is found
- # m[start:end] are the line containing that string. If start == end
- # the string was not found and they indicate the proper sorted
- # insertion point. This was taken from bisect_left, and modified
- # to find line start/end as it goes along.
- #
- # m should be a buffer or a string
- # s is a string
- #
- def manifestsearch(m, s, lo=0, hi=None):
- def advance(i, c):
- while i < lenm and m[i] != c:
- i += 1
- return i
- lenm = len(m)
- if not hi:
- hi = lenm
- while lo < hi:
- mid = (lo + hi) // 2
- start = mid
- while start > 0 and m[start-1] != '\n':
- start -= 1
- end = advance(start, '\0')
- if m[start:end] < s:
- # we know that after the null there are 40 bytes of sha1
- # this translates to the bisect lo = mid + 1
- lo = advance(end + 40, '\n') + 1
- else:
- # this translates to the bisect hi = mid
- hi = start
- end = advance(lo, '\0')
- found = m[lo:end]
- if cmp(s, found) == 0:
- # we know that after the null there are 40 bytes of sha1
- end = advance(end + 40, '\n')
- return (lo, end+1)
- else:
- return (lo, lo)
-
# apply the changes collected during the bisect loop to our addlist
# return a delta suitable for addrevision
def addlistdelta(addlist, x):
@@ -137,7 +150,7 @@ class manifest(revlog):
for w in work:
f = w[0]
# bs will either be the index of the item or the insert point
- start, end = manifestsearch(addbuf, f, start)
+ start, end = self._search(addbuf, f, start)
if w[1] == 0:
l = "%s\000%s%s\n" % (f, hex(map[f]),
flags[f] and "x" or '')
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -94,7 +94,7 @@ def patch(strip, patchname, ui):
"""apply the patch to the working directory.
a list of patched files is returned"""
patcher = find_in_path('gpatch', os.environ.get('PATH', ''), 'patch')
- fp = os.popen('"%s" -p%d < "%s"' % (patcher, strip, patchname))
+ fp = os.popen('%s -p%d < "%s"' % (patcher, strip, patchname))
files = {}
for line in fp:
line = line.rstrip()
@@ -734,7 +734,7 @@ def opener(base, audit=True):
def rename(self):
if not self.closed:
posixfile.close(self)
- rename(self.temp, self.__name)
+ rename(self.temp, localpath(self.__name))
def __del__(self):
if not self.closed:
try:
diff --git a/mercurial/util_win32.py b/mercurial/util_win32.py
--- a/mercurial/util_win32.py
+++ b/mercurial/util_win32.py
@@ -194,7 +194,7 @@ def user_rcpath():
# We are on win < nt: fetch the APPDATA directory location and use
# the parent directory as the user home dir.
appdir = shell.SHGetPathFromIDList(
- qshell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
+ shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
userdir = os.path.dirname(appdir)
return os.path.join(userdir, 'mercurial.ini')
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -56,6 +56,7 @@ try:
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')
self.includes += mercurial.packagescan.getmodules()
build_exe.finalize_options(self)
@@ -85,7 +86,7 @@ setup(name='mercurial',
url='http://selenic.com/mercurial',
description='Scalable distributed SCM',
license='GNU GPL',
- packages=['mercurial', 'hgext'],
+ packages=['mercurial', 'mercurial.hgweb', 'hgext'],
ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
Extension('mercurial.bdiff', ['mercurial/bdiff.c'])],
data_files=[('mercurial/templates',
diff --git a/tests/test-backout.out b/tests/test-backout.out
--- a/tests/test-backout.out
+++ b/tests/test-backout.out
@@ -1,19 +1,19 @@
# basic operation
adding a
-changeset 2:c86754337410 backs out changeset 1:a820f4f40a57
+changeset 2:b38a34ddfd9f backs out changeset 1:a820f4f40a57
a
# file that was removed is recreated
adding a
adding a
-changeset 2:d2d961bd79f2 backs out changeset 1:76862dcce372
+changeset 2:44cd84c7349a backs out changeset 1:76862dcce372
content
# backout of backout is as if nothing happened
removing a
-changeset 3:8a7eeb5ab5ce backs out changeset 2:d2d961bd79f2
+changeset 3:0dd8a0ed5e99 backs out changeset 2:44cd84c7349a
cat: a: No such file or directory
# backout with merge
adding a
-changeset 3:3c9e845b409c backs out changeset 1:314f55b1bf23
+changeset 3:6c77ecc28460 backs out changeset 1:314f55b1bf23
merging with changeset 2:b66ea5b77abb
merging a
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
diff --git a/tests/test-command-template.out b/tests/test-command-template.out
--- a/tests/test-command-template.out
+++ b/tests/test-command-template.out
@@ -6,40 +6,40 @@ 29a31
43a46
> files:
# compact style works
-3[tip] 8c7f028fbabf 1970-01-16 01:06 +0000 person
+3[tip] 10e46f2dcbf4 1970-01-16 01:06 +0000 person
no user, no domain
-2 259081bc29d1 1970-01-14 21:20 +0000 other
+2 97054abb4ab8 1970-01-14 21:20 +0000 other
no person
-1 1c37ba774509 1970-01-13 17:33 +0000 other
+1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
other 1
-0 6eb5362d59ec 1970-01-12 13:46 +0000 user
+0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
line 1
-3[tip] 8c7f028fbabf 1970-01-16 01:06 +0000 person
+3[tip] 10e46f2dcbf4 1970-01-16 01:06 +0000 person
no user, no domain
-2 259081bc29d1 1970-01-14 21:20 +0000 other
+2 97054abb4ab8 1970-01-14 21:20 +0000 other
no person
-1 1c37ba774509 1970-01-13 17:33 +0000 other
+1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
other 1
-0 6eb5362d59ec 1970-01-12 13:46 +0000 user
+0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
line 1
-3[tip]:2,-1 8c7f028fbabf 1970-01-16 01:06 +0000 person
+3[tip]:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
no user, no domain
-2:1,-1 259081bc29d1 1970-01-14 21:20 +0000 other
+2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other
no person
-1:0,-1 1c37ba774509 1970-01-13 17:33 +0000 other
+1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
other 1
-0:-1,-1 6eb5362d59ec 1970-01-12 13:46 +0000 user
+0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
line 1
# error if style not readable
@@ -103,30 +103,24 @@ desc: other 1
other 2
other 3
-
desc: line 1
line 2
-
desc--verbose: no user, no domain
desc--verbose: no person
desc--verbose: other 1
other 2
other 3
-
desc--verbose: line 1
line 2
-
desc--debug: no user, no domain
desc--debug: no person
desc--debug: other 1
other 2
other 3
-
desc--debug: line 1
line 2
-
file_adds:
file_adds:
file_adds:
@@ -175,18 +169,18 @@ manifest--debug: 3:cb5a1327723b
manifest--debug: 2:6e0e82995c35
manifest--debug: 1:4e8d705b1e53
manifest--debug: 0:a0c8bcbbb45c
-node: 8c7f028fbabf93fde80ef788885370b36abeff33
-node: 259081bc29d176c6ae17af5dd01a3440b3288c97
-node: 1c37ba7745099d0f206b3a663abcfe127b037433
-node: 6eb5362d59ec784e4431d3e140c8cc6e1b77ce82
-node--verbose: 8c7f028fbabf93fde80ef788885370b36abeff33
-node--verbose: 259081bc29d176c6ae17af5dd01a3440b3288c97
-node--verbose: 1c37ba7745099d0f206b3a663abcfe127b037433
-node--verbose: 6eb5362d59ec784e4431d3e140c8cc6e1b77ce82
-node--debug: 8c7f028fbabf93fde80ef788885370b36abeff33
-node--debug: 259081bc29d176c6ae17af5dd01a3440b3288c97
-node--debug: 1c37ba7745099d0f206b3a663abcfe127b037433
-node--debug: 6eb5362d59ec784e4431d3e140c8cc6e1b77ce82
+node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
+node: 97054abb4ab824450e9164180baf491ae0078465
+node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
+node: 1e4e1b8f71e05681d422154f5421e385fec3454f
+node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
+node--verbose: 97054abb4ab824450e9164180baf491ae0078465
+node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
+node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
+node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
+node--debug: 97054abb4ab824450e9164180baf491ae0078465
+node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
+node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
parents:
parents:
parents:
@@ -195,9 +189,9 @@ parents--verbose:
parents--verbose:
parents--verbose:
parents--verbose:
-parents--debug: 2:259081bc29d1 -1:000000000000
-parents--debug: 1:1c37ba774509 -1:000000000000
-parents--debug: 0:6eb5362d59ec -1:000000000000
+parents--debug: 2:97054abb4ab8 -1:000000000000
+parents--debug: 1:b608e9d1a3f0 -1:000000000000
+parents--debug: 0:1e4e1b8f71e0 -1:000000000000
parents--debug: -1:000000000000 -1:000000000000
rev: 3
rev: 2
@@ -252,10 +246,10 @@ no user, no domain
no person
other 1
line 1
-8c7f028fbabf
-259081bc29d1
-1c37ba774509
-6eb5362d59ec
+10e46f2dcbf4
+97054abb4ab8
+b608e9d1a3f0
+1e4e1b8f71e0
# error on syntax
abort: t:3: unmatched quotes
# done
diff --git a/tests/test-globalopts b/tests/test-globalopts
--- a/tests/test-globalopts
+++ b/tests/test-globalopts
@@ -62,7 +62,7 @@ echo %% --time
hg --cwd a --time tip 2>&1 | grep '^Time:' | sed 's/[0-9][0-9]*/x/g'
echo %% --version
-hg --version -q | sed 's/version [a-f0-9+]*/version xxx/'
+hg --version -q | sed 's/version \([a-f0-9+]*\|unknown\)/version xxx/'
echo %% -h/--help
hg -h
diff --git a/tests/test-remove b/tests/test-remove
--- a/tests/test-remove
+++ b/tests/test-remove
@@ -3,6 +3,7 @@
hg init a
cd a
echo a > foo
+hg rm foo
hg add foo
hg commit -m 1 -d "1000000 0"
hg remove
@@ -17,5 +18,15 @@ hg export 1
hg log -p -r 0
hg log -p -r 1
+echo a > a
+hg add a
+hg rm a
+hg rm -f a
+echo b > b
+hg ci -A -m 3 -d "1000001 0"
+echo c >> b
+hg rm b
+hg rm -f b
+
cd ..
hg clone a b
diff --git a/tests/test-remove.out b/tests/test-remove.out
--- a/tests/test-remove.out
+++ b/tests/test-remove.out
@@ -1,8 +1,10 @@
+not removing foo: file is not managed
abort: no files specified
undeleting foo
removing foo
# HG changeset patch
# User test
+# Date 1000000 0
# Node ID 8ba83d44753d6259db5ce6524974dd1174e90f47
# Parent 0000000000000000000000000000000000000000
1
@@ -14,6 +16,7 @@ diff -r 000000000000 -r 8ba83d44753d foo
+a
# HG changeset patch
# User test
+# Date 1000000 0
# Node ID a1fce69c50d97881c5c014ab23f580f720c78678
# Parent 8ba83d44753d6259db5ce6524974dd1174e90f47
2
@@ -48,4 +51,8 @@ diff -r 8ba83d44753d -r a1fce69c50d9 foo
-a
-0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+not removing a: file has been marked for add (use -f to force removal)
+adding a
+adding b
+not removing b: file is modified (use -f to force removal)
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
diff --git a/tests/test-tags b/tests/test-tags
--- a/tests/test-tags
+++ b/tests/test-tags
@@ -32,12 +32,31 @@ hg id
hg status
hg commit -m "merge" -d "1000000 0"
+
+# create fake head, make sure tag not visible afterwards
+cp .hgtags tags
+hg tag -d "1000000 0" last
+hg rm .hgtags
+hg commit -m "remove" -d "1000000 0"
+
+mv tags .hgtags
+hg add .hgtags
+hg commit -m "readd" -d "1000000 0"
+
+hg tags
+
# invalid tags
echo "spam" >> .hgtags
echo >> .hgtags
echo "foo bar" >> .hgtags
echo "$T invalid" | sed "s/..../a5a5/" >> .hg/localtags
hg commit -m "tags" -d "1000000 0"
+
+# report tag parse error on other head
+hg up 3
+echo 'x y' >> .hgtags
+hg commit -m "head" -d "1000000 0"
+
hg tags
hg tip
diff --git a/tests/test-tags.out b/tests/test-tags.out
--- a/tests/test-tags.out
+++ b/tests/test-tags.out
@@ -16,17 +16,26 @@ 1 files updated, 0 files merged, 0 files
(branch merge, don't forget to commit)
8216907a933d+8a3ca90d111d+ tip
M .hgtags
-.hgtags:2: ignoring invalid tag
-.hgtags:4: ignoring invalid tag
-localtags:1: ignoring invalid tag
-tip 4:fd868a874787a7b5af31e1675666ce691c803035
+tip 6:c6af9d771a81bb9c7f267ec03491224a9f8ba1cd
first 0:0acdaf8983679e0aac16e811534eb49d7ee1f2b4
-changeset: 4:fd868a874787
-.hgtags:2: ignoring invalid tag
-.hgtags:4: ignoring invalid tag
-localtags:1: ignoring invalid tag
+.hgtags (rev 7:39bba1bbbc4c), line 2: cannot parse entry
+.hgtags (rev 7:39bba1bbbc4c), line 4: node 'foo' is not well formed
+localtags, line 1: tag 'invalid' refers to unknown node
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+.hgtags (rev 7:39bba1bbbc4c), line 2: cannot parse entry
+.hgtags (rev 7:39bba1bbbc4c), line 4: node 'foo' is not well formed
+.hgtags (rev 8:4ca6f1b1a68c), line 2: node 'x' is not well formed
+localtags, line 1: tag 'invalid' refers to unknown node
+tip 8:4ca6f1b1a68c77be687a03aaeb1614671ba59b20
+first 0:0acdaf8983679e0aac16e811534eb49d7ee1f2b4
+changeset: 8:4ca6f1b1a68c
+.hgtags (rev 7:39bba1bbbc4c), line 2: cannot parse entry
+.hgtags (rev 7:39bba1bbbc4c), line 4: node 'foo' is not well formed
+.hgtags (rev 8:4ca6f1b1a68c), line 2: node 'x' is not well formed
+localtags, line 1: tag 'invalid' refers to unknown node
tag: tip
+parent: 3:b2ef3841386b
user: test
date: Mon Jan 12 13:46:40 1970 +0000
-summary: tags
+summary: head