--- a/rakelib/hglib.rb Wed Nov 04 11:29:07 2020 +0000
+++ b/rakelib/hglib.rb Wed Nov 04 11:39:12 2020 +0000
@@ -6,7 +6,7 @@
require 'shellwords'
# Following hack is to make hglib.rb working wit both jv:scripts and
-# Smalltalk/X rakefiles.
+# Smalltalk/X rakefiles.
begin
require 'rakelib/inifile'
rescue
@@ -114,7 +114,7 @@
if block_given?
stdout, stderr, status = Open3.capture3(*cmd)
# For command that deal with remotes, handle check whether the failure
- # is because of missing remote repository. If so, raise exception.
+ # is because of missing remote repository. If so, raise exception.
if status.exitstatus == 255
if stdout =~ /remote:\ *Repository.*not found/ or stderr =~ /abort:.*HTTP.*404/
raise RepositoryNotFoundException.new("Remote repository not found!")
@@ -141,7 +141,7 @@
def self.config
if @@config.nil?
- files = Dir.glob('/etc/mercurial/hgrc.d/*.rc') +
+ files = Dir.glob('/etc/mercurial/hgrc.d/*.rc')
['/etc/mercurial/hgrc',
hgrc]
if Gem.win_platform?
@@ -176,48 +176,64 @@
# Return --ssh config string for use with passed remote url or nil
# if no special --ssh config is needed.
#
- # Rationale:
+ # This is used to tweak SSH connection in various ways, but only
+ # when `ui.ssh` is not set (or has default value on Windows, see below).
+ #
+ # Following tweaks are done:
+ #
+ # 1. On Windows, prefer MSYS2's `ssh.exe` over `plink.exe`.
#
- # On Windows, most of users tend to use TortoiseHG and hg.exe comming with
- # it. THG makes hg.exe to use (shipped) plink.exe which is bad for performance
- # since it uses 16k channel input buffer (!) leading to a pretty slow transfers
- # (a lot of iowaits...)
- # OpenSSH OTOH has 2MB input buffer which is good though on Windows bit
- # oversized as Windows TCP window size is fixed to 65k for all connections with
- # RTT less than 1ms. Still, 65k better then 16k.
- # As a workaround, look if MSYS2's OpenSSH client is installed and if so, use that
- # one - but only if `ui.ssh` config option has the default value.
- # Ugly, isn't it?
+ # Most of users tend to use TortoiseHG and hg.exe comming with
+ # it. THG makes hg.exe to use (shipped) plink.exe which is bad for performance
+ # since it uses 16k channel input buffer (!) leading to a pretty slow transfers
+ # (a lot of iowaits...)
+ # OpenSSH OTOH has 2MB input buffer which is good though on Windows bit
+ # oversized as Windows TCP window size is fixed to 65k for all connections with
+ # RTT less than 1ms. Still, 65k better then 16k.
+ # As a workaround, look if MSYS2's OpenSSH client is installed and if so, use that
+ # one - but only if `ui.ssh` config option has the default value.
+ # Ugly, isn't it?
+ #
+ # 2. If cloning / updating over LAN and using openssh client, add `-C` option to disable compression.
+ #
+ # Data transferred by Mercurial are either already compressed or --uncompressed
+ # was given to reduce CPU load in which case passing -C would reduce it further.
+ #
+ # 3. If cloning / updating non-interactively (from scripts or on CI servers), pass
+ # `-o "StrictHostKeyChecking off"`.
+ #
+ # This is to avoid failures on CI due to missing / changed host key. Not the best,
+ # but otherwise we'd have to configure each and every slave's `.ssh/config`
+
def self.sshconf(uri_string)
uri = URI(uri_string)
ssh = nil
if uri.scheme == 'ssh'
- ssh_in_path = HG::which('ssh') ? true : false
+ ssh_in_path = HG::which('ssh')
+ ssh_in_hgrc = HG::config['ui']['ssh']
if Gem.win_platform?
# Running on Windows
#
+ # On Windows, MSYS's ssh.exe may not be in the path. Check standard place
+ # and update `ssh_in_path`
+ if ssh_in_path == nil and File.exist? %q{c:\msys64\usr\bin\ssh.exe} then
+ ssh_in_path = %q{"c:\msys64\usr\bin\ssh.exe"}
+ end
+
# Mercurial uses `ssh` by default, so to use `plink.exe`, `ui.ssh`
# config option has to be explicitly set.
#
# It it's set to `plink.exe`, check whether MSYS's `ssh.exe` is available
# and if so, change it to `ssh.exe`...
- ssh_configured = HG::config['ui']['ssh']
- if /^.*[pP]link.exe"?\s*(-ssh)?\s*(-2)?$/ =~ ssh_configured
- if ssh_in_path
- ssh = 'ssh'
- else
- ssh = %q{"c:\msys64\usr\bin\ssh.exe"} if File.exist? %q{c:\msys64\usr\bin\ssh.exe}
- end
+ if /^.*[pP]link.exe"?\s*(-ssh)?\s*(-2)?$/ =~ ssh_in_hgrc
# Sigh, we should not tamper with SSH configuration wildly. User may have
# her ssh and mercurial properly configured to use `plink.exe` and `pageant`.
# If we just start using `ssh.exe` clone/pull might not work beause
# `ssh.exe` cannot talk to `pageant`. So, if we don't find OpenSSH's
# style of agent, don't use `ssh.exe` event if available.
- if ssh
+ if ssh_in_path
if ENV['SSH_AUTH_SOCK']
- # Good, OpenSSH agent running but still, be nice and tell the
- # user SSH configuration has been tampered wirh.
- $LOGGER.info("Passing --ssh \"#{ssh}\" option to 'hg' command for faster transfers")
+ ssh = ssh_in_path
else
# No agent, no fun. Be nice and give user a hit
$LOGGER.warn("Not using -ssh \"#{ssh}\" option because SSH agent is not running")
@@ -225,18 +241,26 @@
ssh = nil
end
end
- # Turn off SSH compression - data transferred by Mercurial are either
- # already compressed or --uncompressed was given to reduce CPU load
- # in which case passing -C would reduce it further.
- ssh += ' -C' if ssh and HG::Repository::host_on_lan?(uri.host)
end
else
- # Turn off SSH compression - data transferred by Mercurial are either
- # already compressed or --uncompressed was given to reduce CPU load
- # in which case passing -C would reduce it further.
- ssh = 'ssh -C' if ssh_in_path and HG::Repository::host_on_lan?(uri.host)
+ # Running on UNIX (actually, anything but Windows)
+ #
+ # Check if ui.ssh is configured, if not, use custom SSH command.
+ # Here we set `ssh` to non-nil value only to pass it through nil-checks
+ # below...
+ ssh = ssh_in_path
+ end
+
+ if ssh
+ ssh += " -C" if ssh and HG::Repository::host_on_lan?(uri.host)
+ ssh += " -o 'StrictHostKeyChecking off'" if not STDOUT.isatty
end
end
+
+ # Be nice and tell the user if SSH configuration has been tampered wirh.
+ $LOGGER.info("Passing --ssh \"#{ssh}\" option to 'hg' command for faster transfers") if ssh
+
+ # Done, tricky, wasn't it?
return ssh
end
@@ -256,7 +280,7 @@
# This may cause problems when using over VPN that assigns private address
# (the usuall case). In that case this code will treat is a local
# which may result in transfer of uncompressed data over WAN. Not nice,
- # This should be fixed, somehow.
+ # This should be fixed, somehow.
def self.host_on_lan?(hostname)
unless @@HOSTS_ON_LAN.has_key? hostname
require 'resolv'
@@ -368,7 +392,7 @@
def locate(revset = '.', pattern: '*')
files = []
hg('locate', rev: revset, include: pattern) do |status, out|
- if status.success?
+ if status.success?
files = out.split("\n")
end
end
@@ -376,9 +400,9 @@
end
# Return current branch name
- def branch()
+ def branch()
hg('branch') do | status, out |
- if status.success?
+ if status.success?
return out.strip()
end
end
@@ -515,13 +539,13 @@
end
end
- def outgoing(remote = 'default', user: nil, pass: nil, rev: nil, &block)
+ def outgoing(remote = 'default', user: nil, pass: nil, rev: nil, &block)
if !block_given?
hg('outgoing', remote, ssh: sshconf(remote), config: authconf(remote, user, pass), rev: rev) do |status, stdout, stderr|
STDOUT.print stdout
case status.exitstatus
when 0
- # notning
+ # notning
when 1
puts "No new changes going to #{remote}"
else
@@ -564,7 +588,7 @@
#
# hg update
#
- # would do.
+ # would do.
def update(rev = nil)
if rev
raise Exception.new("Revision #{rev} does not exist") unless has_revision? rev
@@ -602,7 +626,7 @@
repo_dir_parent = File.dirname(repo_dir)
repo_dir_parent == repo_dir ? (repo_dir = nil) : (repo_dir = repo_dir_parent)
end
- end
+ end
# Initializes and empty Mercurial repository in given `directory`
def self.init(directory)
@@ -610,7 +634,7 @@
HG::hg("init", directory)
return Repository.new(directory)
end
- end # class Repository
+ end # class Repository
# Return `true` if given `directory` is a root of mercurial
# repository, `false` otherwise.
@@ -630,6 +654,6 @@
forest(path, &block)
end
end
- end
+ end
end
end # module HG