Merge
authorJan Vrany <jan.vrany@labware.com>
Wed, 04 Nov 2020 11:39:12 +0000
changeset 313 0d7537d100f9
parent 307 0531e67049d6 (diff)
parent 312 7f1be752f87a (current diff)
child 314 834d89a1e75d
Merge
--- a/ci/steps.groovy	Wed Nov 04 11:29:07 2020 +0000
+++ b/ci/steps.groovy	Wed Nov 04 11:39:12 2020 +0000
@@ -72,9 +72,9 @@
                     branch_to_use = branch != null ? branch : scm.getBranch()
                     sh  """
                         if [ -f build.rb ]; then
-                            hg pull --ssh ssh ${scm.getSource()}
+                            hg pull  --ssh "ssh -o 'StrictHostKeyChecking off'" ${scm.getSource()}
                         else
-                            hg clone --ssh ssh ${scm.getSource()} .
+                            hg clone --ssh "ssh -o 'StrictHostKeyChecking off'" ${scm.getSource()} .
                         fi
                         hg up ${branch_to_use}
                         """
--- 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