@@ -6,6 +6,10 @@ module ArduinoCI
66
77 # Tools for interacting with the host machine
88 class Host
9+ # TODO: this came from https://stackoverflow.com/a/22716582/2063546
10+ # and I'm not sure if it can be replaced by self.os == :windows
11+ WINDOWS_VARIANT_REGEX = /mswin32|cygwin|mingw|bccwin/ . freeze
12+
913 # Cross-platform way of finding an executable in the $PATH.
1014 # via https://stackoverflow.com/a/5471032/2063546
1115 # which('ruby') #=> /usr/bin/ruby
@@ -38,13 +42,15 @@ def self.os
3842 return :windows if OS . windows?
3943 end
4044
45+ # Cross-platform symlinking
4146 # if on windows, call mklink, else self.symlink
4247 # @param [Pathname] old_path
4348 # @param [Pathname] new_path
4449 def self . symlink ( old_path , new_path )
45- return FileUtils . ln_s ( old_path . to_s , new_path . to_s ) unless RUBY_PLATFORM =~ /mswin32|cygwin|mingw|bccwin/
50+ # we would prefer `new_path.make_symlink(old_path)` but "symlink function is unimplemented on this machine" with windows
51+ return new_path . make_symlink ( old_path ) unless RUBY_PLATFORM =~ WINDOWS_VARIANT_REGEX
4652
47- # https://stackoverflow.com/a/22716582/2063546
53+ # via https://stackoverflow.com/a/22716582/2063546
4854 # windows mklink syntax is reverse of unix ln -s
4955 # windows mklink is built into cmd.exe
5056 # vulnerable to command injection, but okay because this is a hack to make a cli tool work.
@@ -54,5 +60,36 @@ def self.symlink(old_path, new_path)
5460 _stdout , _stderr , exitstatus = Open3 . capture3 ( 'cmd.exe' , "/C mklink /D #{ np } #{ orp } " )
5561 exitstatus . success?
5662 end
63+
64+ # Cross-platform is-this-a-symlink function
65+ # @param [Pathname] path
66+ # @return [String] the output of a dir command
67+ def self . get_windows_link_info ( path )
68+ # via https://stackoverflow.com/a/22716582/2063546
69+ # vulnerable to command injection, but okay because this is a hack to make a cli tool work.
70+ np = path . to_s . tr ( "/" , "\\ " ) # work around Pathname bug
71+
72+ stdout , _stderr , _exitstatus = Open3 . capture3 ( 'cmd.exe' , "/c dir #{ np } " )
73+ puts "get_windows_link_info got:\n #{ stdout } "
74+ stdout
75+ end
76+
77+ # Cross-platform is-this-a-symlink function
78+ # @param [Pathname] path
79+ # @return [bool] Whether the file is a symlink
80+ def self . symlink? ( path )
81+ return path . symlink? unless RUBY_PLATFORM =~ WINDOWS_VARIANT_REGEX
82+
83+ get_windows_link_info . include? ( "SYMLINK" )
84+ end
85+
86+ # Cross-platform "read link" function
87+ # @param [Pathname] path
88+ # @return [Pathname] the link target
89+ def self . readlink ( path )
90+ return path . readlink unless RUBY_PLATFORM =~ WINDOWS_VARIANT_REGEX
91+
92+ get_windows_link_info
93+ end
5794 end
5895end
0 commit comments