Skip to content

Commit 990aa5b

Browse files
jawshooahsds
authored andcommitted
Monkeypatch File class for Windows mklink support
`File.symlink` is not implemented for Windows in the core library. Here we override `File.symlink` and `File.symlink?` to use the Windows `mklink` command as an alternative. We also override `File.readlink` to add Windows compatibility.
1 parent 60e614f commit 990aa5b

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

lib/overcommit.rb

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'overcommit/os'
2+
require 'overcommit/extend/file'
23
require 'overcommit/constants'
34
require 'overcommit/exceptions'
45
require 'overcommit/utils'

lib/overcommit/extend/file.rb

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
require 'overcommit/os'
2+
require 'overcommit/subprocess'
3+
4+
# Adapted from http://stackoverflow.com/a/22716582
5+
class << File
6+
alias_method :old_symlink, :symlink
7+
alias_method :old_symlink?, :symlink?
8+
alias_method :old_readlink, :readlink
9+
10+
def symlink(old_name, new_name)
11+
return old_symlink(old_name, new_name) unless Overcommit::OS.windows?
12+
13+
result = win32_mklink_cmd(old_name, new_name)
14+
result.status
15+
end
16+
17+
def symlink?(file_name)
18+
return old_symlink?(file_name) unless Overcommit::OS.windows?
19+
20+
result = win32_dir_cmd(file_name)
21+
!(result.stdout =~ /<SYMLINK>/).nil?
22+
end
23+
24+
def readlink(link_name)
25+
return old_readlink(link_name) unless Overcommit::OS.windows?
26+
27+
result = win32_dir_cmd(link_name)
28+
29+
unless result.stdout =~ /<SYMLINK>/
30+
raise ArgumentError, "#{link_name} is not a symlink"
31+
end
32+
33+
# Extract symlink target from output, which looks like:
34+
# 11/13/2012 12:53 AM <SYMLINK> mysymlink [C:\Windows\Temp\somefile.txt]
35+
result.stdout[/\[.+\]/][1..-2]
36+
end
37+
38+
private
39+
40+
def win32_dir_cmd(file_name)
41+
Overcommit::Subprocess.spawn(
42+
%W[cmd.exe /c dir #{file_name}]
43+
)
44+
end
45+
46+
def win32_mklink_cmd(old_name, new_name)
47+
Overcommit::Subprocess.spawn(
48+
%W[cmd.exe /c mklink #{new_name} #{old_name}]
49+
)
50+
end
51+
end

0 commit comments

Comments
 (0)