|
| 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