# HG changeset patch # User Vadim Gelfer # Date 1148054232 25200 # Node ID 7cbe8cd69d6b0a381510875d57c37f05dc91babf # Parent c58a403aa830b798564e4ad88eec8236000301f7# Parent d9ca698e3c5a051075cce3aa84e1308939c13f4b merge with crew. 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