diff --git a/.hgsigs b/.hgsigs --- a/.hgsigs +++ b/.hgsigs @@ -246,3 +246,5 @@ f952be90b0514a576dcc8bbe758ce3847faba9bb fc445f8abcf90b33db7c463816a1b3560681767f 0 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 diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -262,3 +262,5 @@ f952be90b0514a576dcc8bbe758ce3847faba9bb fc445f8abcf90b33db7c463816a1b3560681767f 6.4.3 da372c745e0f053bb7a64e74cccd15810d96341d 6.4.4 271a4ab29605ffa0bae5d3208eaa21a95427ff92 6.4.5 +bb42988c7e156931b0ff1e93732b98173ebbcb7f 6.5rc0 +3ffc7209bbae5804a53084c9dc2d41139e88c867 6.5 diff --git a/contrib/check-code.py b/contrib/check-code.py --- a/contrib/check-code.py +++ b/contrib/check-code.py @@ -146,10 +146,8 @@ testpats = [ r'\[[^\]]+==', '[ foo == bar ] is a bashism, use [ foo = bar ] instead', ), - ( - r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w', - "use egrep for extended grep syntax", - ), + (r'(^|\|\s*)egrep', "use grep -E for extended grep syntax"), + (r'(^|\|\s*)fgrep', "use grep -F for fixed string grepping"), (r'(^|\|\s*)e?grep .*\\S', "don't use \\S in regular expression"), (r'(? Result { - if rev == NULL_REVISION { - return Ok(ChangelogRevisionData::null()); - } self.entry_for_rev(rev)?.data() } @@ -336,6 +333,11 @@ message", changelog.data_for_rev(NULL_REVISION)?, ChangelogRevisionData::null() ); + // same with the intermediate entry object + assert_eq!( + changelog.entry_for_rev(NULL_REVISION)?.data()?, + ChangelogRevisionData::null() + ); Ok(()) } } diff --git a/rust/hg-core/src/revlog/mod.rs b/rust/hg-core/src/revlog/mod.rs --- a/rust/hg-core/src/revlog/mod.rs +++ b/rust/hg-core/src/revlog/mod.rs @@ -225,20 +225,35 @@ impl Revlog { &self, node: NodePrefix, ) -> Result { - if node.is_prefix_of(&NULL_NODE) { - return Ok(NULL_REVISION); - } - - if let Some(nodemap) = &self.nodemap { - return nodemap + let looked_up = if let Some(nodemap) = &self.nodemap { + nodemap .find_bin(&self.index, node)? - .ok_or(RevlogError::InvalidRevision); - } + .ok_or(RevlogError::InvalidRevision) + } else { + self.rev_from_node_no_persistent_nodemap(node) + }; + + if node.is_prefix_of(&NULL_NODE) { + return match looked_up { + Ok(_) => Err(RevlogError::AmbiguousPrefix), + Err(RevlogError::InvalidRevision) => Ok(NULL_REVISION), + res => res, + }; + }; - // Fallback to linear scan when a persistent nodemap is not present. - // This happens when the persistent-nodemap experimental feature is not - // enabled, or for small revlogs. - // + looked_up + } + + /// Same as `rev_from_node`, without using a persistent nodemap + /// + /// This is used as fallback when a persistent nodemap is not present. + /// This happens when the persistent-nodemap experimental feature is not + /// enabled, or for small revlogs. + fn rev_from_node_no_persistent_nodemap( + &self, + node: NodePrefix, + ) -> Result { + // Linear scan of the revlog // TODO: consider building a non-persistent nodemap in memory to // optimize these cases. let mut found_by_prefix = None; @@ -547,6 +562,9 @@ impl<'revlog> RevlogEntry<'revlog> { pub fn data(&self) -> Result, HgError> { let data = self.rawdata()?; + if self.rev == NULL_REVISION { + return Ok(data); + } if self.is_censored() { return Err(HgError::CensoredNodeError); } @@ -669,6 +687,13 @@ mod tests { assert_eq!(revlog.len(), 0); assert!(revlog.get_entry(0).is_err()); assert!(!revlog.has_rev(0)); + assert_eq!( + revlog.rev_from_node(NULL_NODE.into()).unwrap(), + NULL_REVISION + ); + let null_entry = revlog.get_entry(NULL_REVISION).ok().unwrap(); + assert_eq!(null_entry.revision(), NULL_REVISION); + assert!(null_entry.data().unwrap().is_empty()); } #[test] @@ -740,4 +765,65 @@ mod tests { assert!(p2_entry.is_some()); assert_eq!(p2_entry.unwrap().revision(), 1); } + + #[test] + fn test_nodemap() { + let temp = tempfile::tempdir().unwrap(); + let vfs = Vfs { base: temp.path() }; + + // building a revlog with a forced Node starting with zeros + // This is a corruption, but it does not preclude using the nodemap + // if we don't try and access the data + let node0 = Node::from_hex("00d2a3912a0b24502043eae84ee4b279c18b90dd") + .unwrap(); + let node1 = Node::from_hex("b004912a8510032a0350a74daa2803dadfb00e12") + .unwrap(); + let entry0_bytes = IndexEntryBuilder::new() + .is_first(true) + .with_version(1) + .with_inline(true) + .with_offset(INDEX_ENTRY_SIZE) + .with_node(node0) + .build(); + let entry1_bytes = IndexEntryBuilder::new() + .with_offset(INDEX_ENTRY_SIZE) + .with_node(node1) + .build(); + let contents = vec![entry0_bytes, entry1_bytes] + .into_iter() + .flatten() + .collect_vec(); + std::fs::write(temp.path().join("foo.i"), contents).unwrap(); + let revlog = Revlog::open(&vfs, "foo.i", None, false).unwrap(); + + // accessing the data shows the corruption + revlog.get_entry(0).unwrap().data().unwrap_err(); + + assert_eq!(revlog.rev_from_node(NULL_NODE.into()).unwrap(), -1); + assert_eq!(revlog.rev_from_node(node0.into()).unwrap(), 0); + assert_eq!(revlog.rev_from_node(node1.into()).unwrap(), 1); + assert_eq!( + revlog + .rev_from_node(NodePrefix::from_hex("000").unwrap()) + .unwrap(), + -1 + ); + assert_eq!( + revlog + .rev_from_node(NodePrefix::from_hex("b00").unwrap()) + .unwrap(), + 1 + ); + // RevlogError does not implement PartialEq + // (ultimately because io::Error does not) + match revlog + .rev_from_node(NodePrefix::from_hex("00").unwrap()) + .expect_err("Expected to give AmbiguousPrefix error") + { + RevlogError::AmbiguousPrefix => (), + e => { + panic!("Got another error than AmbiguousPrefix: {:?}", e); + } + }; + } } diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -112,7 +112,10 @@ issetuptools = os.name == 'nt' or 'FORCE if issetuptools: from setuptools import setup else: - from distutils.core import setup + try: + from distutils.core import setup + except ModuleNotFoundError: + from setuptools import setup from distutils.ccompiler import new_compiler from distutils.core import Command, Extension from distutils.dist import Distribution diff --git a/tests/dummysmtpd.py b/tests/dummysmtpd.py --- a/tests/dummysmtpd.py +++ b/tests/dummysmtpd.py @@ -3,12 +3,11 @@ """dummy SMTP server for use in tests""" -import asyncore import optparse -import smtpd +import os +import socket import ssl import sys -import traceback from mercurial import ( pycompat, @@ -18,54 +17,97 @@ from mercurial import ( ) +if os.environ.get('HGIPV6', '0') == '1': + family = socket.AF_INET6 +else: + family = socket.AF_INET + + def log(msg): sys.stdout.write(msg) sys.stdout.flush() -class dummysmtpserver(smtpd.SMTPServer): - def __init__(self, localaddr): - smtpd.SMTPServer.__init__(self, localaddr, remoteaddr=None) +def mocksmtpserversession(conn, addr): + conn.send(b'220 smtp.example.com ESMTP\r\n') + + line = conn.recv(1024) + if not line.lower().startswith(b'ehlo '): + log('no hello: %s\n' % line) + return + + conn.send(b'250 Hello\r\n') - def process_message(self, peer, mailfrom, rcpttos, data, **kwargs): - log('%s from=%s to=%s\n' % (peer[0], mailfrom, ', '.join(rcpttos))) + line = conn.recv(1024) + if not line.lower().startswith(b'mail from:'): + log('no mail from: %s\n' % line) + return + mailfrom = line[10:].decode().rstrip() + if mailfrom.startswith('<') and mailfrom.endswith('>'): + mailfrom = mailfrom[1:-1] + + conn.send(b'250 Ok\r\n') - def handle_error(self): - # On Windows, a bad SSL connection sometimes generates a WSAECONNRESET. - # The default handler will shutdown this server, and then both the - # current connection and subsequent ones fail on the client side with - # "No connection could be made because the target machine actively - # refused it". If we eat the error, then the client properly aborts in - # the expected way, and the server is available for subsequent requests. - traceback.print_exc() + rcpttos = [] + while True: + line = conn.recv(1024) + if not line.lower().startswith(b'rcpt to:'): + break + rcptto = line[8:].decode().rstrip() + if rcptto.startswith('<') and rcptto.endswith('>'): + rcptto = rcptto[1:-1] + rcpttos.append(rcptto) + + conn.send(b'250 Ok\r\n') + + if not line.lower().strip() == b'data': + log('no rcpt to or data: %s' % line) + + conn.send(b'354 Go ahead\r\n') + + data = b'' + while True: + line = conn.recv(1024) + if not line: + log('connection closed before end of data') + break + data += line + if data.endswith(b'\r\n.\r\n'): + data = data[:-5] + break + + conn.send(b'250 Ok\r\n') + + log( + '%s from=%s to=%s\n%s\n' + % (addr[0], mailfrom, ', '.join(rcpttos), data.decode()) + ) -class dummysmtpsecureserver(dummysmtpserver): - def __init__(self, localaddr, certfile): - dummysmtpserver.__init__(self, localaddr) - self._certfile = certfile - - def handle_accept(self): - pair = self.accept() - if not pair: - return - conn, addr = pair - ui = uimod.ui.load() +def run(host, port, certificate): + ui = uimod.ui.load() + with socket.socket(family, socket.SOCK_STREAM) as s: + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind((host, port)) + # log('listening at %s:%d\n' % (host, port)) + s.listen(1) try: - # wrap_socket() would block, but we don't care - conn = sslutil.wrapserversocket(conn, ui, certfile=self._certfile) - except ssl.SSLError: - log('%s ssl error\n' % addr[0]) - conn.close() - return - smtpd.SMTPChannel(self, conn, addr) - - -def run(): - try: - asyncore.loop() - except KeyboardInterrupt: - pass + while True: + conn, addr = s.accept() + if certificate: + try: + conn = sslutil.wrapserversocket( + conn, ui, certfile=certificate + ) + except ssl.SSLError as e: + log('%s ssl error: %s\n' % (addr[0], e)) + conn.close() + continue + log("connection from %s:%s\n" % addr) + mocksmtpserversession(conn, addr) + conn.close() + except KeyboardInterrupt: + pass def _encodestrsonly(v): @@ -93,26 +135,18 @@ def main(): op.add_option('--pid-file', metavar='FILE') op.add_option('--tls', choices=['none', 'smtps'], default='none') op.add_option('--certificate', metavar='FILE') + op.add_option('--logfile', metavar='FILE') opts, args = op.parse_args() - if opts.tls == 'smtps' and not opts.certificate: - op.error('--certificate must be specified') - - addr = (opts.address, opts.port) - - def init(): - if opts.tls == 'none': - dummysmtpserver(addr) - else: - dummysmtpsecureserver(addr, opts.certificate) - log('listening at %s:%d\n' % addr) + if (opts.tls == 'smtps') != bool(opts.certificate): + op.error('--certificate must be specified with --tls=smtps') server.runservice( bytesvars(opts), - initfn=init, - runfn=run, + runfn=lambda: run(opts.address, opts.port, opts.certificate), runargs=[pycompat.sysexecutable, pycompat.fsencode(__file__)] + pycompat.sysargv[1:], + logfile=opts.logfile, ) diff --git a/tests/remotefilelog-library.sh b/tests/remotefilelog-library.sh --- a/tests/remotefilelog-library.sh +++ b/tests/remotefilelog-library.sh @@ -69,5 +69,5 @@ ls_l() { } identifyrflcaps() { - xargs -n 1 echo | egrep '(remotefilelog|getflogheads|getfile)' | sort + xargs -n 1 echo | grep -E '(remotefilelog|getflogheads|getfile)' | sort } diff --git a/tests/test-archive.t b/tests/test-archive.t --- a/tests/test-archive.t +++ b/tests/test-archive.t @@ -51,12 +51,12 @@ hg subrepos are shared into existence on $ hg -R clone1 update -C tip cloning subrepo subrepo from $TESTTMP/test/subrepo 3 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ find share2 | egrep 'sharedpath|00.+\.i' | sort + $ find share2 | grep -E 'sharedpath|00.+\.i' | sort share2/.hg/sharedpath share2/subrepo/.hg/sharedpath $ hg -R share2 unshare unsharing subrepo 'subrepo' - $ find share2 | egrep 'sharedpath|00.+\.i' | sort + $ find share2 | grep -E 'sharedpath|00.+\.i' | sort share2/.hg/00changelog.i share2/.hg/sharedpath.old share2/.hg/store/00changelog.i @@ -566,7 +566,7 @@ old file -- date clamped to 1980 $ hg add old $ hg commit -m old $ hg archive ../old.zip - $ unzip -l ../old.zip | grep -v -- ----- | egrep -v files$ + $ unzip -l ../old.zip | grep -v -- ----- | grep -E -v files$ Archive: ../old.zip \s*Length.* (re) *172*80*00:00*old/.hg_archival.txt (glob) diff --git a/tests/test-bad-extension.t b/tests/test-bad-extension.t --- a/tests/test-bad-extension.t +++ b/tests/test-bad-extension.t @@ -57,7 +57,7 @@ another bad extension show traceback - $ hg -q help help --traceback 2>&1 | egrep ' extension|^Exception|Traceback|ImportError|ModuleNotFound' + $ hg -q help help --traceback 2>&1 | grep -E ' extension|^Exception|Traceback|ImportError|ModuleNotFound' *** failed to import extension "badext" from $TESTTMP/badext.py: bit bucket overflow Traceback (most recent call last): Exception: bit bucket overflow @@ -88,7 +88,7 @@ show traceback for ImportError of hgext. $ (hg help help --traceback --debug --config devel.debug.extensions=yes 2>&1) \ > | grep -v '^ ' \ > | filterlog \ - > | egrep 'extension..[^p]|^Exception|Traceback|ImportError|^YYYY|not import|ModuleNotFound' + > | grep -E 'extension..[^p]|^Exception|Traceback|ImportError|^YYYY|not import|ModuleNotFound' YYYY/MM/DD HH:MM:SS (PID)> loading extensions YYYY/MM/DD HH:MM:SS (PID)> - processing 5 entries YYYY/MM/DD HH:MM:SS (PID)> - loading extension: gpg diff --git a/tests/test-blackbox.t b/tests/test-blackbox.t --- a/tests/test-blackbox.t +++ b/tests/test-blackbox.t @@ -393,7 +393,7 @@ a '*' entry in blackbox.track is interpr > EOF (only look for entries with specific logged sources, otherwise this test is pretty brittle) - $ hg blackbox | egrep '\[command(finish)?\]' + $ hg blackbox | grep -E '\[command(finish)?\]' 1970-01-01 00:00:00.000 bob @0000000000000000000000000000000000000000 (5000) [commandfinish]> --config *blackbox.track=* --config *blackbox.logsource=True* init track_star exited 0 after * seconds (glob) 1970-01-01 00:00:00.000 bob @0000000000000000000000000000000000000000 (5000) [command]> blackbox $ cd $TESTTMP diff --git a/tests/test-bookflow.t b/tests/test-bookflow.t --- a/tests/test-bookflow.t +++ b/tests/test-bookflow.t @@ -230,17 +230,17 @@ test shelving make the bookmark move by updating it on a, and then pulling with a local change # add a commit to a $ cd ../a - $ hg up -C X |fgrep "activating bookmark X" + $ hg up -C X |grep -F "activating bookmark X" (activating bookmark X) # go back to b, and check out X $ cd ../b - $ hg up -C X |fgrep "activating bookmark X" + $ hg up -C X |grep -F "activating bookmark X" (activating bookmark X) # update and push from a $ make_changes ../a created new head $ echo "more" >> test - $ hg pull -u 2>&1 | fgrep -v TESTTMP| fgrep -v "searching for changes" | fgrep -v adding + $ hg pull -u 2>&1 | grep -F -v TESTTMP| grep -F -v "searching for changes" | grep -F -v adding pulling from $TESTTMP/a updating bookmark X added 1 changesets with 0 changes to 0 files (+1 heads) diff --git a/tests/test-chg.t b/tests/test-chg.t --- a/tests/test-chg.t +++ b/tests/test-chg.t @@ -70,7 +70,7 @@ by default, system() should be redirecte $ touch foo $ CHGDEBUG= HGEDITOR=cat chg ci -Am channeled --edit 2>&1 \ - > | egrep "HG:|run 'cat" + > | grep -E "HG:|run 'cat" chg: debug: * run 'cat "*"' at '$TESTTMP/editor' (glob) HG: Enter commit message. Lines beginning with 'HG:' are removed. HG: Leave message empty to abort commit. @@ -84,7 +84,7 @@ but no redirection should be made if out $ touch bar $ CHGDEBUG= HGEDITOR=cat chg ci -Am bufferred --edit \ > --config extensions.pushbuffer="$TESTTMP/pushbuffer.py" 2>&1 \ - > | egrep "HG:|run 'cat" + > | grep -E "HG:|run 'cat" [1] check that commit commands succeeded: @@ -237,14 +237,14 @@ isolate socket directory for stable resu warm up server: - $ CHGDEBUG= chg log 2>&1 | egrep 'instruction|start' + $ CHGDEBUG= chg log 2>&1 | grep -E 'instruction|start' chg: debug: * start cmdserver at $TESTTMP/extreload/chgsock/server.* (glob) new server should be started if extension modified: $ sleep 1 $ touch dummyext.py - $ CHGDEBUG= chg log 2>&1 | egrep 'instruction|start' + $ CHGDEBUG= chg log 2>&1 | grep -E 'instruction|start' chg: debug: * instruction: unlink $TESTTMP/extreload/chgsock/server-* (glob) chg: debug: * instruction: reconnect (glob) chg: debug: * start cmdserver at $TESTTMP/extreload/chgsock/server.* (glob) @@ -252,7 +252,7 @@ new server should be started if extensio old server will shut down, while new server should still be reachable: $ sleep 2 - $ CHGDEBUG= chg log 2>&1 | (egrep 'instruction|start' || true) + $ CHGDEBUG= chg log 2>&1 | (grep -E 'instruction|start' || true) socket file should never be unlinked by old server: (simulates unowned socket by updating mtime, which makes sure server exits @@ -268,7 +268,7 @@ at polling cycle) since no server is reachable from socket file, new server should be started: (this test makes sure that old server shut down automatically) - $ CHGDEBUG= chg log 2>&1 | egrep 'instruction|start' + $ CHGDEBUG= chg log 2>&1 | grep -E 'instruction|start' chg: debug: * start cmdserver at $TESTTMP/extreload/chgsock/server.* (glob) shut down servers and restore environment: @@ -495,7 +495,7 @@ share the same server > } $ newchg() { > chg --kill-chg-daemon - > filteredchg "$@" | egrep -v 'start cmdserver' || true + > filteredchg "$@" | grep -E -v 'start cmdserver' || true > } (--profile isn't permanently on just because it was specified when chg was started) @@ -561,12 +561,12 @@ If CHGHG is not set, chg will set it bef $ hg --kill-chg-daemon $ HG=$CHGHG CHGHG= CHGDEBUG= hg debugshell -c \ > 'ui.write(b"CHGHG=%s\n" % ui.environ.get(b"CHGHG"))' 2>&1 \ - > | egrep 'CHGHG|start' + > | grep -E 'CHGHG|start' chg: debug: * start cmdserver at * (glob) CHGHG=/*/install/bin/hg (glob) Running the same command a second time shouldn't spawn a new command server. $ HG=$CHGHG CHGHG= CHGDEBUG= hg debugshell -c \ > 'ui.write(b"CHGHG=%s\n" % ui.environ.get(b"CHGHG"))' 2>&1 \ - > | egrep 'CHGHG|start' + > | grep -E 'CHGHG|start' CHGHG=/*/install/bin/hg (glob) diff --git a/tests/test-clone-cgi.t b/tests/test-clone-cgi.t --- a/tests/test-clone-cgi.t +++ b/tests/test-clone-cgi.t @@ -12,8 +12,6 @@ initialize repository $ cat >hgweb.cgi < # > # An example CGI script to use hgweb, edit as necessary - > import cgitb - > cgitb.enable() > from mercurial import demandimport; demandimport.enable() > from mercurial.hgweb import hgweb > from mercurial.hgweb import wsgicgi diff --git a/tests/test-clone-stream-format.t b/tests/test-clone-stream-format.t --- a/tests/test-clone-stream-format.t +++ b/tests/test-clone-stream-format.t @@ -245,7 +245,7 @@ The resulting clone should not use share $ hg clone --quiet --stream -U http://localhost:$HGPORT clone-from-share $ hg -R clone-from-share verify -q - $ hg debugrequires -R clone-from-share | egrep 'share$' + $ hg debugrequires -R clone-from-share | grep -E 'share$' [1] $ killdaemons.py diff --git a/tests/test-clone.t b/tests/test-clone.t --- a/tests/test-clone.t +++ b/tests/test-clone.t @@ -714,7 +714,7 @@ Test clone from the repository in (emula $ hg -R src commit -m '#0' $ hg -R src log -q 0:e1bab28bca43 - $ hg -R src debugrevlog -c | egrep 'format|flags' + $ hg -R src debugrevlog -c | grep -E 'format|flags' format : 0 flags : (none) $ hg root -R src -T json | sed 's|\\\\|\\|g' diff --git a/tests/test-clonebundles-autogen.t b/tests/test-clonebundles-autogen.t --- a/tests/test-clonebundles-autogen.t +++ b/tests/test-clonebundles-autogen.t @@ -10,7 +10,6 @@ initial setup > > [clone-bundles] > auto-generate.on-change = yes - > auto-generate.formats = v2 > upload-command = cp "\$HGCB_BUNDLE_PATH" "$TESTTMP"/final-upload/ > delete-command = rm -f "$TESTTMP/final-upload/\$HGCB_BASENAME" > url-template = file://$TESTTMP/final-upload/{basename} @@ -25,9 +24,36 @@ initial setup 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd client +Test bundles are not generated if formats are not given +======================================================= + + $ touch noformats + $ hg -q commit -A -m 'add noformats' + $ hg push + pushing to $TESTTMP/server + searching for changes + clone-bundle auto-generate enabled, but no formats specified: disabling generation + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ test -f ../server/.hg/clonebundles.manifest + [1] + $ hg debugstrip -r tip + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/client/.hg/strip-backup/4823cdad4f38-4b2c3b65-backup.hg + $ hg --cwd ../server debugstrip -r tip + saved backup bundle to $TESTTMP/server/.hg/strip-backup/4823cdad4f38-4b2c3b65-backup.hg + clone-bundle auto-generate enabled, but no formats specified: disabling generation + clone-bundle auto-generate enabled, but no formats specified: disabling generation + Test bundles are generated on push ================================== + $ cat >> ../server/.hg/hgrc << EOF + > [clone-bundles] + > auto-generate.formats = v2 + > EOF $ touch foo $ hg -q commit -A -m 'add foo' $ touch bar diff --git a/tests/test-context-metadata.t b/tests/test-context-metadata.t --- a/tests/test-context-metadata.t +++ b/tests/test-context-metadata.t @@ -36,7 +36,7 @@ Tests about metadataonlyctx date: Thu Jan 01 00:00:00 1970 +0000 summary: Changed - $ hg --config extensions.metaedit=$TESTTMP/metaedit.py metaedit 'parents=0' 2>&1 | egrep '^RuntimeError' + $ hg --config extensions.metaedit=$TESTTMP/metaedit.py metaedit 'parents=0' 2>&1 | grep -E '^RuntimeError' RuntimeError: can't reuse the manifest: its p1 doesn't match the new ctx p1 $ hg --config extensions.metaedit=$TESTTMP/metaedit.py metaedit 'user=foo ' diff --git a/tests/test-contrib-perf.t b/tests/test-contrib-perf.t --- a/tests/test-contrib-perf.t +++ b/tests/test-contrib-perf.t @@ -408,7 +408,7 @@ test profile-benchmark option Function to check that statprof ran $ statprofran () { - > egrep 'Sample count:|No samples recorded' > /dev/null + > grep -E 'Sample count:|No samples recorded' > /dev/null > } $ hg perfdiscovery . --config perf.stub=no --config perf.run-limits='0.000000001-1' --config perf.profile-benchmark=yes 2>&1 | statprofran diff --git a/tests/test-convert-cvs-synthetic.t b/tests/test-convert-cvs-synthetic.t --- a/tests/test-convert-cvs-synthetic.t +++ b/tests/test-convert-cvs-synthetic.t @@ -108,7 +108,7 @@ merge file6 from trunk to v1_2 cvs rlog output - $ cvscall -q rlog proj | egrep '^(RCS file|revision)' + $ cvscall -q rlog proj | grep -E '^(RCS file|revision)' RCS file: $TESTTMP/cvsrepo/proj/file1,v revision 1.1 RCS file: $TESTTMP/cvsrepo/proj/Attic/file2,v diff --git a/tests/test-convert-hg-svn.t b/tests/test-convert-hg-svn.t --- a/tests/test-convert-hg-svn.t +++ b/tests/test-convert-hg-svn.t @@ -1,7 +1,7 @@ #require svn svn-bindings $ filter_svn_output () { - > egrep -v 'Committing|Updating|(^$)' | sed -e 's/done$//' || true + > grep -E -v 'Committing|Updating|(^$)' | sed -e 's/done$//' || true > } $ cat <> $HGRCPATH diff --git a/tests/test-convert-svn-source.t b/tests/test-convert-svn-source.t --- a/tests/test-convert-svn-source.t +++ b/tests/test-convert-svn-source.t @@ -1,7 +1,7 @@ #require svn svn-bindings $ filter_svn_output () { - > egrep -v 'Committing|Updating|(^$)' | sed -e 's/done$//' || true + > grep -E -v 'Committing|Updating|(^$)' | sed -e 's/done$//' || true > } $ cat >> $HGRCPATH < [format] > exp-use-copies-side-data-changeset = yes > EOF - $ hg debugformat -v | egrep 'changelog-v2|revlog-v2|copies-sdc' + $ hg debugformat -v | grep -E 'changelog-v2|revlog-v2|copies-sdc' copies-sdc: no yes no revlog-v2: no no no changelog-v2: no yes no @@ -1675,7 +1675,7 @@ We upgrade a repository that is not usin > enabled=yes > numcpus=8 > EOF - $ hg debugformat -v | egrep 'changelog-v2|revlog-v2|copies-sdc' + $ hg debugformat -v | grep -E 'changelog-v2|revlog-v2|copies-sdc' copies-sdc: no yes no revlog-v2: no no no changelog-v2: no yes no @@ -2919,14 +2919,14 @@ In this case, the file hash from "f-2" i Details on this hash ordering pick: - $ hg manifest --debug 'desc("g-1")' | egrep 'd$' + $ hg manifest --debug 'desc("g-1")' | grep -E 'd$' 17ec97e605773eb44a117d1136b3849bcdc1924f 644 d (no-changeset !) 5cce88bf349f7c742bb440f2c53f81db9c294279 644 d (changeset !) $ hg status --copies --rev 'desc("i-0")' --rev 'desc("g-1")' d A d a (no-changeset no-compatibility !) - $ hg manifest --debug 'desc("f-2")' | egrep 'd$' + $ hg manifest --debug 'desc("f-2")' | grep -E 'd$' 7b79e2fe0c8924e0e598a82f048a7b024afa4d96 644 d (no-changeset !) ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 d (changeset !) $ hg status --copies --rev 'desc("i-0")' --rev 'desc("f-2")' d diff --git a/tests/test-copies-in-changeset.t b/tests/test-copies-in-changeset.t --- a/tests/test-copies-in-changeset.t +++ b/tests/test-copies-in-changeset.t @@ -32,13 +32,13 @@ Check that copies are recorded correctly $ hg init repo $ cd repo #if sidedata - $ hg debugformat -v | egrep 'format-variant|revlog-v2|copies-sdc|changelog-v2' + $ hg debugformat -v | grep -E 'format-variant|revlog-v2|copies-sdc|changelog-v2' format-variant repo config default copies-sdc: yes yes no revlog-v2: no no no changelog-v2: yes yes no #else - $ hg debugformat -v | egrep 'format-variant|revlog-v2|copies-sdc|changelog-v2' + $ hg debugformat -v | grep -E 'format-variant|revlog-v2|copies-sdc|changelog-v2' format-variant repo config default copies-sdc: no no no revlog-v2: no no no @@ -419,7 +419,7 @@ Test upgrading/downgrading to sidedata s downgrading - $ hg debugformat -v | egrep 'format-variant|revlog-v2|copies-sdc|changelog-v2' + $ hg debugformat -v | grep -E 'format-variant|revlog-v2|copies-sdc|changelog-v2' format-variant repo config default copies-sdc: yes yes no revlog-v2: no no no @@ -445,7 +445,7 @@ downgrading processed revlogs: - changelog - $ hg debugformat -v | egrep 'format-variant|revlog-v2|copies-sdc|changelog-v2' + $ hg debugformat -v | grep -E 'format-variant|revlog-v2|copies-sdc|changelog-v2' format-variant repo config default copies-sdc: no no no revlog-v2: no no no @@ -470,7 +470,7 @@ upgrading processed revlogs: - changelog - $ hg debugformat -v | egrep 'format-variant|revlog-v2|copies-sdc|changelog-v2' + $ hg debugformat -v | grep -E 'format-variant|revlog-v2|copies-sdc|changelog-v2' format-variant repo config default copies-sdc: yes yes no revlog-v2: no no no diff --git a/tests/test-debian-packages.t b/tests/test-debian-packages.t --- a/tests/test-debian-packages.t +++ b/tests/test-debian-packages.t @@ -15,16 +15,16 @@ Ensure debuild doesn't run the testsuite $ ls *.deb | grep -v 'dbg' mercurial_*.deb (glob) should have .so and .py - $ dpkg --contents mercurial_*.deb | egrep '(localrepo|parsers)' + $ dpkg --contents mercurial_*.deb | grep -E '(localrepo|parsers)' * ./usr/lib/python3/dist-packages/mercurial/cext/parsers*.so (glob) * ./usr/lib/python3/dist-packages/mercurial/localrepo.py (glob) * ./usr/lib/python3/dist-packages/mercurial/pure/parsers.py (glob) should have zsh completions - $ dpkg --contents mercurial_*.deb | egrep 'zsh.*[^/]$' + $ dpkg --contents mercurial_*.deb | grep -E 'zsh.*[^/]$' * ./usr/share/zsh/vendor-completions/_hg (glob) should have chg - $ dpkg --contents mercurial_*.deb | egrep 'chg$' + $ dpkg --contents mercurial_*.deb | grep -E 'chg$' * ./usr/bin/chg (glob) chg should come with a man page - $ dpkg --contents mercurial_*.deb | egrep 'man.*chg' + $ dpkg --contents mercurial_*.deb | grep -E 'man.*chg' * ./usr/share/man/man1/chg.1.gz (glob) diff --git a/tests/test-debug-rebuild-dirstate.t b/tests/test-debug-rebuild-dirstate.t new file mode 100644 --- /dev/null +++ b/tests/test-debug-rebuild-dirstate.t @@ -0,0 +1,39 @@ +#require rust + + $ cat >> $HGRCPATH << EOF + > [format] + > use-dirstate-v2=1 + > [storage] + > dirstate-v2.slow-path=allow + > EOF + + $ hg init t + $ cd t + + $ for i in 1 2 3 4 5 6 7 8 9 10; do touch foobar$i; done + $ hg add . + adding foobar1 + adding foobar10 + adding foobar2 + adding foobar3 + adding foobar4 + adding foobar5 + adding foobar6 + adding foobar7 + adding foobar8 + adding foobar9 + $ hg commit -m "1" + +Check that there's no space leak on debugrebuilddirstate + + $ f --size .hg/dirstate* + .hg/dirstate: size=133 + .hg/dirstate.b870a51b: size=511 + $ hg debugrebuilddirstate + $ f --size .hg/dirstate* + .hg/dirstate: size=133 + .hg/dirstate.88698448: size=511 + $ hg debugrebuilddirstate + $ f --size .hg/dirstate* + .hg/dirstate: size=133 + .hg/dirstate.6b8ab34b: size=511 diff --git a/tests/test-debugcommands.t b/tests/test-debugcommands.t --- a/tests/test-debugcommands.t +++ b/tests/test-debugcommands.t @@ -576,7 +576,7 @@ Test cache warming command Test debugcolor #if no-windows - $ hg debugcolor --style --color always | egrep 'mode|style|log\.' + $ hg debugcolor --style --color always | grep -E 'mode|style|log\.' color mode: 'ansi' available style: \x1b[0;33mlog.changeset\x1b[0m: \x1b[0;33myellow\x1b[0m (esc) diff --git a/tests/test-devel-warnings.t b/tests/test-devel-warnings.t --- a/tests/test-devel-warnings.t +++ b/tests/test-devel-warnings.t @@ -191,7 +191,7 @@ Stripping from a transaction $ echo a > a $ hg add a $ hg commit -m a - $ hg stripintr 2>&1 | egrep -v '^(\*\*| )' + $ hg stripintr 2>&1 | grep -E -v '^(\*\*| )' Traceback (most recent call last): *ProgrammingError: cannot strip from inside a transaction (glob) @@ -384,7 +384,7 @@ Stripping from a transaction Test programming error failure: - $ hg buggytransaction 2>&1 | egrep -v '^ ' + $ hg buggytransaction 2>&1 | grep -E -v '^ ' ** Unknown exception encountered with possibly-broken third-party extension "buggylocking" (version N/A) ** which supports versions unknown of Mercurial. ** Please disable "buggylocking" and try your action again. @@ -396,7 +396,7 @@ Test programming error failure: Traceback (most recent call last): *ProgrammingError: transaction requires locking (glob) - $ hg programmingerror 2>&1 | egrep -v '^ ' + $ hg programmingerror 2>&1 | grep -E -v '^ ' ** Unknown exception encountered with possibly-broken third-party extension "buggylocking" (version N/A) ** which supports versions unknown of Mercurial. ** Please disable "buggylocking" and try your action again. diff --git a/tests/test-dirstate-version-fallback.t b/tests/test-dirstate-version-fallback.t --- a/tests/test-dirstate-version-fallback.t +++ b/tests/test-dirstate-version-fallback.t @@ -10,8 +10,8 @@ Set up a v1 repo $ hg init repo $ cd repo $ echo a > a - $ hg add a - $ hg commit -m a + $ touch file-with-somewhat-long-name-to-make-dirstate-v1-bigger-than-v2 + $ hg commit -Aqm a $ hg debugrequires | grep dirstate [1] $ ls -1 .hg/dirstate* @@ -22,7 +22,7 @@ Copy v1 dirstate Upgrade it to v2 - $ hg debugupgraderepo -q --config format.use-dirstate-v2=1 --run | egrep 'added:|removed:' + $ hg debugupgraderepo -q --config format.use-dirstate-v2=1 --run | grep -E 'added:|removed:' added: dirstate-v2 $ hg debugrequires | grep dirstate dirstate-v2 diff --git a/tests/test-docker-packaging.t b/tests/test-docker-packaging.t --- a/tests/test-docker-packaging.t +++ b/tests/test-docker-packaging.t @@ -22,10 +22,10 @@ built using docker. main deb should have .so but no .py $ ar x mercurial_*.deb - $ tar tf data.tar* | egrep '(localrepo|parsers)' + $ tar tf data.tar* | grep -E '(localrepo|parsers)' ./usr/lib/python2.7/dist-packages/mercurial/parsers*.so (glob) mercurial-common should have .py but no .so or .pyc $ ar x mercurial-common_*.deb - $ tar tf data.tar* | egrep '(localrepo|parsers)' + $ tar tf data.tar* | grep -E '(localrepo|parsers)' ./usr/lib/python2.7/dist-packages/mercurial/pure/parsers.py ./usr/lib/python2.7/dist-packages/mercurial/localrepo.py diff --git a/tests/test-extension.t b/tests/test-extension.t --- a/tests/test-extension.t +++ b/tests/test-extension.t @@ -1375,7 +1375,7 @@ accessed. throw external 1.0.0 No declared supported version, extension complains: - $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' + $ hg --config extensions.throw=throw.py throw 2>&1 | grep -E '^\*\*' ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0 ** which supports versions unknown of Mercurial. ** Please disable "throw" and try your action again. @@ -1387,7 +1387,7 @@ No declared supported version, extension empty declaration of supported version, extension complains (but doesn't choke if the value is improperly a str instead of bytes): $ echo "testedwith = ''" >> throw.py - $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' + $ hg --config extensions.throw=throw.py throw 2>&1 | grep -E '^\*\*' ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0 ** which supports versions unknown of Mercurial. ** Please disable "throw" and try your action again. @@ -1401,7 +1401,7 @@ improperly a str instead of bytes): $ echo 'buglink = "http://example.com/bts"' >> throw.py $ rm -f throw.pyc throw.pyo $ rm -Rf __pycache__ - $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' + $ hg --config extensions.throw=throw.py throw 2>&1 | grep -E '^\*\*' ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0 ** which supports versions unknown of Mercurial. ** Please disable "throw" and try your action again. @@ -1418,7 +1418,7 @@ If the extensions declare outdated versi $ rm -f throw.pyc throw.pyo $ rm -Rf __pycache__ $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ - > throw 2>&1 | egrep '^\*\*' + > throw 2>&1 | grep -E '^\*\*' ** Unknown exception encountered with possibly-broken third-party extension "older" (version N/A) ** which supports versions 1.9 of Mercurial. ** Please disable "older" and try your action again. @@ -1432,7 +1432,7 @@ One extension only tested with older, on $ rm -f older.pyc older.pyo $ rm -Rf __pycache__ $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ - > throw 2>&1 | egrep '^\*\*' + > throw 2>&1 | grep -E '^\*\*' ** Unknown exception encountered with possibly-broken third-party extension "older" (version N/A) ** which supports versions 1.9 of Mercurial. ** Please disable "older" and try your action again. @@ -1446,7 +1446,7 @@ Older extension is tested with current v $ rm -f older.pyc older.pyo $ rm -Rf __pycache__ $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ - > throw 2>&1 | egrep '^\*\*' + > throw 2>&1 | grep -E '^\*\*' ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0 ** which supports versions 2.1 of Mercurial. ** Please disable "throw" and try your action again. @@ -1457,7 +1457,7 @@ Older extension is tested with current v Ability to point to a different point $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ - > --config ui.supportcontact='Your Local Goat Lenders' throw 2>&1 | egrep '^\*\*' + > --config ui.supportcontact='Your Local Goat Lenders' throw 2>&1 | grep -E '^\*\*' ** unknown exception encountered, please report by visiting ** Your Local Goat Lenders ** Python * (glob) @@ -1472,7 +1472,7 @@ Declare the version as supporting this h > fi $ rm -f throw.pyc throw.pyo $ rm -Rf __pycache__ - $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' + $ hg --config extensions.throw=throw.py throw 2>&1 | grep -E '^\*\*' ** unknown exception encountered, please report by visiting ** https://mercurial-scm.org/wiki/BugTracker ** Python * (glob) @@ -1484,7 +1484,7 @@ Patch version is ignored during compatib $ echo "util.version = lambda:b'3.2.2'" >> throw.py $ rm -f throw.pyc throw.pyo $ rm -Rf __pycache__ - $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' + $ hg --config extensions.throw=throw.py throw 2>&1 | grep -E '^\*\*' ** unknown exception encountered, please report by visiting ** https://mercurial-scm.org/wiki/BugTracker ** Python * (glob) @@ -1595,7 +1595,7 @@ Refuse to load extensions with minimum v > util.version = lambda: b'3.6' > minimumhgversion = b'3.7' > EOF - $ hg --config extensions.minversion=minversion2.py version 2>&1 | egrep '\(third' + $ hg --config extensions.minversion=minversion2.py version 2>&1 | grep -E '\(third' (third party extension minversion requires version 3.7 or newer of Mercurial (current: 3.6); disabling) Can load version that is only off by point release @@ -1605,7 +1605,7 @@ Can load version that is only off by poi > util.version = lambda: b'3.6.1' > minimumhgversion = b'3.6' > EOF - $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third' + $ hg --config extensions.minversion=minversion3.py version 2>&1 | grep -E '\(third' [1] Can load minimum version identical to current @@ -1615,7 +1615,7 @@ Can load minimum version identical to cu > util.version = lambda: b'3.5' > minimumhgversion = b'3.5' > EOF - $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third' + $ hg --config extensions.minversion=minversion3.py version 2>&1 | grep -E '\(third' [1] Don't explode on py3 with a bad version number (both str vs bytes, and not enough diff --git a/tests/test-flagprocessor.t b/tests/test-flagprocessor.t --- a/tests/test-flagprocessor.t +++ b/tests/test-flagprocessor.t @@ -215,7 +215,7 @@ Ensure the data got to the server OK raise error.Abort(msg) mercurial.error.Abort: cannot register multiple processors on flag '0x8'. *** failed to set up extension duplicate: cannot register multiple processors on flag '0x8'. - $ hg st 2>&1 | egrep 'cannot register multiple processors|flagprocessorext' + $ hg st 2>&1 | grep -E 'cannot register multiple processors|flagprocessorext' File "*/tests/flagprocessorext.py", line *, in extsetup (glob) mercurial.error.Abort: cannot register multiple processors on flag '0x8'. *** failed to set up extension duplicate: cannot register multiple processors on flag '0x8'. diff --git a/tests/test-git-interop.t b/tests/test-git-interop.t --- a/tests/test-git-interop.t +++ b/tests/test-git-interop.t @@ -358,7 +358,7 @@ Status should be consistent for both sys $ hg status heads mismatch, rebuilding dagcache M beta - $ git status | egrep -v '^$|^ \(use ' + $ git status | grep -E -v '^$|^ \(use ' On branch master Changes not staged for commit: modified: beta diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -799,7 +799,7 @@ Disabled extension gets suggested Checking that help adapts based on the config: - $ hg help diff --config ui.tweakdefaults=true | egrep -e '^ *(-g|config)' + $ hg help diff --config ui.tweakdefaults=true | grep -E -e '^ *(-g|config)' -g --[no-]git use git extended diff format (default: on from config) @@ -1585,7 +1585,7 @@ Help subsection: Show nested definitions ("profiling.type"[break]"ls"[break]"stat"[break]) - $ hg help config.type | egrep '^$'|wc -l + $ hg help config.type | grep -E '^$'|wc -l \s*3 (re) $ hg help config.profiling.type.ls @@ -1598,7 +1598,7 @@ Show nested definitions Separate sections from subsections - $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq + $ hg help config.format | grep -E '^ ("|-)|^\s*$' | uniq "format" -------- @@ -1660,7 +1660,7 @@ note to use help -c for general hg help Test templating help - $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) ' + $ hg help templating | grep -E '(desc|diffstat|firstline|nonempty) ' desc String. The text of the changeset description. diffstat String. Statistics of changes with the following format: firstline Any text. Returns the first line of text. @@ -1701,12 +1701,12 @@ Test help hooks help -c should only show debug --debug - $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$' + $ hg help -c --debug|grep -E debug|wc -l|grep -E '^\s*0\s*$' [1] help -c should only show deprecated for -v - $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$' + $ hg help -c -v|grep -E DEPRECATED|wc -l|grep -E '^\s*0\s*$' [1] Test -s / --system @@ -1720,11 +1720,11 @@ Test -s / --system Test -e / -c / -k combinations - $ hg help -c|egrep '^[A-Z].*:|^ debug' + $ hg help -c|grep -E '^[A-Z].*:|^ debug' Commands: - $ hg help -e|egrep '^[A-Z].*:|^ debug' + $ hg help -e|grep -E '^[A-Z].*:|^ debug' Extensions: - $ hg help -k|egrep '^[A-Z].*:|^ debug' + $ hg help -k|grep -E '^[A-Z].*:|^ debug' Topics: Commands: Extensions: @@ -1735,11 +1735,11 @@ Test -e / -c / -k combinations [10] $ hg help -e schemes |head -1 schemes extension - extend schemes with shortcuts to repository swarms - $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):' + $ hg help -c -k dates |grep -E '^(Topics|Extensions|Commands):' Commands: - $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):' + $ hg help -e -k a |grep -E '^(Topics|Extensions|Commands):' Extensions: - $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):' + $ hg help -e -c -k date |grep -E '^(Topics|Extensions|Commands):' Extensions: Commands: $ hg help -c commit > /dev/null diff --git a/tests/test-hgweb-csp.t b/tests/test-hgweb-csp.t --- a/tests/test-hgweb-csp.t +++ b/tests/test-hgweb-csp.t @@ -69,7 +69,7 @@ repo page should send CSP by default, in nonce should not be added to html if CSP doesn't use it - $ get-with-headers.py localhost:$HGPORT repo1/graph/tip | egrep 'content-security-policy|