Win32: Workarounds for bugs in eXept's Win32 makefiles as of 2017-01-13
As of 2017-01-13, mingwmake fails due to a slasg/backslash mess in OUTDIR
and OUTDIR_SLASH variables (presumably). As a consequence, `objmingw` directory
is either not created at all or an attemptp to create it fails because of
invalid command syntax.
To (temporarily, I hope) workaround it, checkout older makefiles (from
2017-01-01) which seems to work.
How could eXept mess up things so badly without noticing?
require 'rakelib/hglib'
module Rake
end
module Rake::StX
end
# Cross-platform way of finding an executable in the $PATH.
#
# which('ruby') #=> /usr/bin/ruby
def which(cmd)
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
exts.each { |ext|
exe = File.join(path, "#{cmd}#{ext}")
return exe if File.executable?(exe) && !File.directory?(exe)
}
end
return nil
end
cvs_rsh_set = false
module Rake::Stx::SCM
# Not quite sure why following code
#
# include RakeFileUtils
#
# does not make extra methods (like `sh`) defined in `extensions.rb`
# visible here. To workaround, define them here. Ugly...
module_function
def sh(cmd, cwd: Dir.pwd, &block)
begin
return RakeFileUtils::sh(cmd, cwd: cwd, &block)
rescue
return false
end
end
# Make sure CVS_RSH environment variable is properly set. Prefer MSYS2 ssh.exe
# over plink.exe. For details, see `hglib.rb`, method `sshconf()`
module_function
def ensure_cvs_rsh_set()
if @cvs_rsh_set then
return
end
ssh = nil
ssh_configured = ENV['CVS_RSH']
ssh_in_path = which('ssh') ? true : false
plink_in_path = which('plink') ? true : false
if Gem.win_platform? then
# If CVS_RSH is not set or is set to plink.exe, try to change to
# MSYS2 ssh.exe as it gives better performance on (fast) LANs.
if /^.*[pP]link(\.exe)?"?\s*(-ssh)?\s*(-2)?$/ =~ ssh_configured then
if ssh_in_path then
ssh = 'ssh'
else
if (File.exist? "c:\\msys64\\usr\\bin\\ssh.exe") then
ssh = "\"c:\\msys64\\usr\\bin\\ssh.exe\""
end
end
# 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 then
if ENV['SSH_AUTH_SOCK'] then
# Good, OpenSSH agent running but still, be nice and tell the
# user SSH configuration has been tampered wirh.
info("Setting CVS_RSH=\"#{ssh}\" for faster transfers")
else
# No agent, no fun. Be nice and give user a hit
warn("Not using CVS_RSH=\"#{ssh}\" option because SSH agent is not running")
warn("For faster CVS checkout over LAN, consider using ssh-agent or ssh-pageant (if you want to use PuTTY's pageant)")
ssh = nil
end
end
end
else
if not ssh_configured then
ssh = "ssh"
end
end
if ssh then
ENV['CVS_RSH'] = ssh
end
cvs_rsh_set = true
end
public
class CheckoutException < Exception
end # class CheckoutException
def self._check_type(type)
if (type != :cvs and type != :svn and type != :git and type != :hg)
raise CheckoutException.new("Unknown version control system type (#{type})")
end
end
def self.update(repository, directory, **kwargs)
type = repository.type
url = repository.canonical
self._check_type(type)
root = kwargs[:root] || BUILD_DIR
branch = kwargs[:branch]
if branch == nil
if type == :svn
branch = 'trunk'
elsif type == :hg
branch = 'default'
end
end
wc = root / directory
if (! File.exist? wc)
self.checkout(repository, directory, **kwargs)
return
end
case type
when :svn then _update_svn(repository, directory, branch, root, **kwargs)
when :cvs then _update_cvs(repository, directory, branch, root, **kwargs)
when :git then _update_git(repository, directory, branch, root, **kwargs)
when :hg then _update_hg(repository, directory, branch, root, **kwargs)
end
end
def self._update_hg(repository, directory, branch, root, **kwargs)
wc = root / directory
separator = kwargs[:separator] || '.'
revision = kwargs[:revision]
if directory != nil then
url = "#{repository.canonical}/#{directory.gsub('/', separator)}"
end
hg = HG::Repository.new(wc)
begin
paths = hg.paths
if repository.staging then
if not paths.has_key? 'staging'
paths['staging'] = "#{repository.staging}/#{directory.gsub('/', separator)}"
hg.paths = paths
end
hg.pull('staging')
end
if repository.upstream then
if not paths.has_key? 'upstream'
paths['upstream'] = "#{repository.upstream}/#{directory.gsub('/', separator)}"
hg.paths = paths
end
hg.pull('upstream')
end
if not paths.has_key? 'canonical'
paths['canonical'] = "#{repository.canonical}/#{directory.gsub('/', separator)}"
hg.paths = paths
end
hg.pull('canonical')
# If revision is not specified, then look for an active bookmark
# and update to it. If no bookmark is active, then look for bookmark
# `master`. If it exist, then update to `master`. If it
# does not, then update to tip or throw an error.
# The error is thrown if there's no bookmark `master` and
# branch has multiple heads since it's not clear which
# head rev to use.
if not revision then
revision = hg.bookmark()
if not revision then
bookmarks = hg.bookmarks(branch)
if (bookmarks.has_key? 'master') then
revision = 'master'
else
if (hg.heads(branch).size > 1) then
raise CheckoutException.new("HG: Cannot checkout #{directory}: branch #{branch} has multiple heads but no bookmark named 'master'!")
end
end
end
end
hg.update(revision || branch)
rescue Exception => ex
raise CheckoutException.new("HG: Cannot update #{wc}: #{ex.message}")
end
end
def self._update_svn(repository, directory, branch, root, **kwargs)
wc = root / directory
if not sh %W{svn --non-interactive --trust-server-cert update}, cwd: wc
raise CheckoutException.new("SVN: Cannot update #{wc}")
end
end
def self._update_cvs(repository, directory, branch, root, **kwargs)
ensure_cvs_rsh_set()
wc = root / directory
if File.directory? wc
if not sh %W{cvs -z 9 update -A -d}, cwd: wc
raise CheckoutException.new("CVS: Cannot update #{wc}")
end
else
if not sh %W{cvs -z 9 update -A #{File.basename(wc)}}, cwd: File.dirname(wc)
raise CheckoutException.new("CVS: Cannot update #{wc}")
end
end
end
def self.checkout(repository, directory, **kwargs)
type = repository.type
url = repository.canonical
self._check_type(type)
root = kwargs[:root] || BUILD_DIR
branch = kwargs[:branch]
if branch == nil
if type == :svn
branch = 'trunk'
elsif type == :hg
branch = 'default'
end
end
wc = root / directory
if (File.exist? wc)
self.update(repository, directory, **kwargs)
return
end
if (not File.exists? File.dirname(wc))
begin
FileUtils.mkdir_p(File.dirname(wc))
rescue => ex
raise CheckoutException.new("Cannot create directory for working copy (#{ex})")
end
end
case type
when :svn then _checkout_svn(repository, directory, branch, root, **kwargs)
when :cvs then _checkout_cvs(repository, directory, branch, root, **kwargs)
when :git then _checkout_git(repository, directory, branch, root, **kwargs)
when :hg then _checkout_hg(repository, directory, branch, root, **kwargs)
end
end
def self._checkout_svn(repository, directory, branch, root, **kwargs)
url = "#{repository.canonical}/#{directory}/#{branch}"
if not sh %W{svn --non-interactive --trust-server-cert co #{url} #{directory}}, cwd: root
raise CheckoutException.new("SVN: Cannot checkout from #{url}")
end
end
def self._checkout_hg(repository, directory, branch, root, **kwargs)
separator = kwargs[:separator] || '.'
revision = kwargs[:revision]
paths = {}
if repository.canonical then
paths['canonical'] = "#{repository.canonical}/#{directory.gsub('/', separator)}"
else
raise Exception.new("Repository named #{repository.name} does not define mandatory canonical repository URL")
end
if repository.upstream then
paths['upstream'] = "#{repository.upstream}/#{directory.gsub('/', separator)}"
end
if repository.staging then
paths['staging'] = "#{repository.staging}/#{directory.gsub('/', separator)}"
end
begin
if repository.staging then
paths['default'] = paths['staging']
hg = HG::Repository.clone(paths['staging'], root / directory, noupdate: true)
hg.paths = paths
hg.pull('upstream') if paths['upstream']
hg.pull('canonical')
elsif repository.upstream then
paths['default'] = paths['upstream']
hg = HG::Repository.clone(paths['upstream'], root / directory, noupdate: true)
hg.paths = paths
hg.pull('canonical')
else
paths['default'] = paths['canonical']
hg = HG::Repository.clone(paths['canonical'], root / directory, noupdate: true)
hg.paths = paths
end
# If revision is not specified, then look for bookmark
# `master`. If it exist, then check out `master`. If it
# does not, then checkout tip or throw an error.
# The error is thrown if there's no bookmark `master` and
# branch has multiple heads since it's not clear which
# head rev to use.
if not revision then
bookmarks = hg.bookmarks(branch)
if (bookmarks.has_key? 'master') then
revision = 'master'
else
if (hg.heads(branch).size > 1) then
raise CheckoutException.new("HG: Cannot checkout #{directory}: branch #{branch} has multiple heads but no bookmark named 'master'!")
end
end
end
hg.update(revision || branch)
#rescue Exception => e
# raise CheckoutException.new("HG: Cannot clone from #{url}: #{e.message}")
end
end
def self._checkout_cvs(repository, directory, branch, root, **kwargs)
revision = kwargs[:revision] || nil
revision_arg = ''
if revision then
if not revision.match(/^\d\d\d\d-\d\d-\d\d$/)
raise Exception.new("CVS only support date spec as revision: option (YYYY-MM-DD)")
end
revision_arg = " -D #{revision}"
end
ensure_cvs_rsh_set()
if not sh "cvs -z 9 -d #{repository.canonical} co #{revision_arg} #{directory}", cwd: root
raise CheckoutException.new("CVS: Cannot checkout #{directory}from #{repository.url}")
end
end
end # module Rake::Stx::SCM
def checkout(repo_name, directory, **kwargs)
# repository should be symbolic name
repo = Rake::Stx::Configuration::Repository::find(repo_name)
if not repo then
error("checkout(): No repository found (#{repo_name})")
end
kwargs[:separator] = repo.separator
Rake::Stx::SCM.checkout(repo, directory, **kwargs)
end
def update(repo_name, directory, **kwargs)
# repository should be symbolic name
repo = Rake::Stx::Configuration::Repository::find(repo_name)
if not repo then
error("update(): No repository found (#{repo_name})")
end
kwargs[:separator] = repo.separator
Rake::Stx::SCM.update(repo, directory, **kwargs)
end
def cvs(url, directory, **kwargs)
repo = Rake::Stx::Configuration::Repository.new(:type => :cvs, :url => url)
Rake::Stx::SCM.checkout(repo, directory, **kwargs)
end
def svn(url, directory, **kwargs)
repo = Rake::Stx::Configuration::Repository.new(:type => :svn, :url => url)
Rake::Stx::SCM.checkout(repo, directory, **kwargs)
end
def hg(url, directory, **kwargs)
repo = Rake::Stx::Configuration::Repository.new(:type => :hg, :url => url)
Rake::Stx::SCM.checkout(repo, directory, **kwargs)
end
def git(url, directory, **kwargs)
repo = Rake::Stx::Configuration::Repository.new(:type => :git, :url => url)
Rake::Stx::SCM.checkout(repo, directory, **kwargs)
end