win32-symlink 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +5 -0
- data/LICENSE +22 -0
- data/README.md +28 -0
- data/Rakefile +21 -0
- data/ext/win32/extconf.rb +12 -0
- data/ext/win32/win32-symlink.cpp +297 -0
- data/lib/win32/symlink.rb +2 -0
- data/lib/win32/symlink/version.rb +12 -0
- data/lib/win32/symlink/win32_symlink.so +0 -0
- data/tasks/ext.rake +7 -0
- data/test/test_win32_symlink.rb +60 -0
- data/win32-symlink.gemspec +35 -0
- metadata +87 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 08a2aebcc89a9a0521a80869c5f9c045a6774374
|
4
|
+
data.tar.gz: 4aebff75b3ccd259ae3983f1577b959829f150e1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2a9451a6762f0cf0153dc760008a2f2e36f41a7884154db1bd0b6293b56d72ead206be01eecf60b8eef46ee37dffa9e308b133471be389d364167ffa7eafb4a4
|
7
|
+
data.tar.gz: 7e1af87d5b5cc8ffcdc135182b6563ec4a8cbc7bd42a074ac27684955ee7f5d3cf7a1eddb637c54506d0676a769acd195f18eef62a9ee90856bdafbf430d7dc6
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 boris
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Win32::Symlink
|
2
|
+
|
3
|
+
Since the standard ruby library lacks symlink functions on Windows, this
|
4
|
+
little library attempts to fill the gap.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'win32-symlink'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install win32-symlink
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
This library implements the following functons that mimic their ruby
|
23
|
+
counterparts:
|
24
|
+
|
25
|
+
readlink(link_name) -> file_name
|
26
|
+
symlink?(link_name) -> true or false
|
27
|
+
symlink(old_name, new_name) -> 0
|
28
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
|
13
|
+
$gemspec = Bundler.load_gemspec('win32-symlink.gemspec')
|
14
|
+
|
15
|
+
Rake::TestTask.new do |t|
|
16
|
+
t.warning = true
|
17
|
+
end
|
18
|
+
|
19
|
+
load 'tasks/ext.rake'
|
20
|
+
|
21
|
+
task :default => [:compile, :test]
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
if CONFIG['CXXFLAGS'] == '$(cxxflags)'
|
4
|
+
CONFIG['CXXFLAGS'] = CONFIG['cxxflags'].clone
|
5
|
+
end
|
6
|
+
|
7
|
+
# these are not relevant for C++
|
8
|
+
CONFIG['warnflags'].sub! '-Wdeclaration-after-statement', ''
|
9
|
+
CONFIG['warnflags'].sub! '-Wimplicit-function-declaration', ''
|
10
|
+
|
11
|
+
try_cppflags $CPPFLAGS.sub(/_WIN32_WINNT=\S+/, '_WIN32_WINNT=0x600')
|
12
|
+
create_makefile 'win32_symlink'
|
@@ -0,0 +1,297 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
#define filecp_to_wstr(str, plen) cstr_to_wstr(filecp(), str, -1, plen)
|
4
|
+
|
5
|
+
typedef BOOL (WINAPI* create_symbolic_linkW_t)(LPWSTR src, LPWSTR dest, DWORD flags);
|
6
|
+
create_symbolic_linkW_t create_symbolic_linkW = NULL;
|
7
|
+
|
8
|
+
|
9
|
+
typedef struct _REPARSE_DATA_BUFFER
|
10
|
+
{
|
11
|
+
ULONG ReparseTag;
|
12
|
+
USHORT ReparseDataLength;
|
13
|
+
USHORT Reserved;
|
14
|
+
union
|
15
|
+
{
|
16
|
+
struct
|
17
|
+
{
|
18
|
+
USHORT SubstituteNameOffset;
|
19
|
+
USHORT SubstituteNameLength;
|
20
|
+
USHORT PrintNameOffset;
|
21
|
+
USHORT PrintNameLength;
|
22
|
+
ULONG Flags;
|
23
|
+
WCHAR PathBuffer[1];
|
24
|
+
} SymbolicLinkReparseBuffer;
|
25
|
+
struct
|
26
|
+
{
|
27
|
+
USHORT SubstituteNameOffset;
|
28
|
+
USHORT SubstituteNameLength;
|
29
|
+
USHORT PrintNameOffset;
|
30
|
+
USHORT PrintNameLength;
|
31
|
+
WCHAR PathBuffer[1];
|
32
|
+
} MountPointReparseBuffer;
|
33
|
+
struct
|
34
|
+
{
|
35
|
+
UCHAR DataBuffer[1];
|
36
|
+
} GenericReparseBuffer;
|
37
|
+
} DUMMYUNIONNAME;
|
38
|
+
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
39
|
+
|
40
|
+
|
41
|
+
static inline UINT
|
42
|
+
filecp(void)
|
43
|
+
{
|
44
|
+
UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
|
45
|
+
return cp;
|
46
|
+
}
|
47
|
+
|
48
|
+
static wchar_t *
|
49
|
+
cstr_to_wstr(UINT code_page, const char *str, int clen, int *wstr_len)
|
50
|
+
{
|
51
|
+
int len;
|
52
|
+
wchar_t* wstr;
|
53
|
+
|
54
|
+
len = MultiByteToWideChar(code_page, 0, str, clen, NULL, 0);
|
55
|
+
wstr = (wchar_t *)xmalloc(len * sizeof(wchar_t));
|
56
|
+
|
57
|
+
MultiByteToWideChar(code_page, 0, str, clen, wstr, len);
|
58
|
+
if( wstr_len )
|
59
|
+
*wstr_len = len;
|
60
|
+
return wstr;
|
61
|
+
}
|
62
|
+
|
63
|
+
static VALUE
|
64
|
+
wstr_to_str(UINT code_page, const wchar_t* wstr, int clen)
|
65
|
+
{
|
66
|
+
int len, term_len;
|
67
|
+
VALUE v;
|
68
|
+
term_len = clen < 0 ? 1 : 0;
|
69
|
+
len = WideCharToMultiByte(code_page, 0, wstr, clen, NULL, 0, NULL, NULL) - term_len;
|
70
|
+
v = rb_str_new(NULL, len);
|
71
|
+
WideCharToMultiByte(code_page, 0, wstr, clen, RSTRING_PTR(v), len + term_len, NULL, NULL);
|
72
|
+
return v;
|
73
|
+
}
|
74
|
+
|
75
|
+
static VALUE
|
76
|
+
make_error_str(VALUE klass, const char* fmt, ...)
|
77
|
+
{
|
78
|
+
VALUE exc;
|
79
|
+
VALUE str;
|
80
|
+
|
81
|
+
va_list va;
|
82
|
+
va_start(va, fmt);
|
83
|
+
str = rb_vsprintf(fmt, va);
|
84
|
+
va_end(va);
|
85
|
+
exc = rb_exc_new3(klass, str);
|
86
|
+
rb_str_free(str);
|
87
|
+
return exc;
|
88
|
+
}
|
89
|
+
|
90
|
+
static VALUE
|
91
|
+
make_api_error(const char* msg)
|
92
|
+
{
|
93
|
+
DWORD w32_err;
|
94
|
+
int myerrno;
|
95
|
+
w32_err = GetLastError();
|
96
|
+
myerrno = rb_w32_map_errno(w32_err);
|
97
|
+
return rb_syserr_new( myerrno == EINVAL ? w32_err : myerrno, msg);
|
98
|
+
}
|
99
|
+
|
100
|
+
static wchar_t*
|
101
|
+
resolve_api_path(wchar_t* path)
|
102
|
+
{
|
103
|
+
if( 0 == wcsncmp(L"\\??\\UNC\\", path, 8) )
|
104
|
+
{
|
105
|
+
path += 6;
|
106
|
+
*path = L'\\';
|
107
|
+
}
|
108
|
+
else if( 0 == wcsncmp(L"\\??\\", path, 4) )
|
109
|
+
{
|
110
|
+
path += 4;
|
111
|
+
}
|
112
|
+
return path;
|
113
|
+
}
|
114
|
+
|
115
|
+
static VALUE
|
116
|
+
win32_readlink(const char* file)
|
117
|
+
{
|
118
|
+
VALUE error = Qnil;
|
119
|
+
VALUE target = Qnil;
|
120
|
+
HANDLE h = INVALID_HANDLE_VALUE;
|
121
|
+
bool ok = true;
|
122
|
+
REPARSE_DATA_BUFFER* buf = NULL;
|
123
|
+
const size_t buf_size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
|
124
|
+
|
125
|
+
buf = (REPARSE_DATA_BUFFER*)xmalloc(buf_size);
|
126
|
+
if(ok)
|
127
|
+
{
|
128
|
+
const DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
129
|
+
const DWORD access_mode = FILE_READ_EA;
|
130
|
+
const DWORD attributes =
|
131
|
+
FILE_FLAG_BACKUP_SEMANTICS
|
132
|
+
| FILE_ATTRIBUTE_REPARSE_POINT
|
133
|
+
| FILE_FLAG_OPEN_REPARSE_POINT;
|
134
|
+
|
135
|
+
h = CreateFile( file, access_mode, share_mode,
|
136
|
+
0, OPEN_EXISTING, attributes, NULL);
|
137
|
+
|
138
|
+
if(!(ok = (h != INVALID_HANDLE_VALUE)))
|
139
|
+
{
|
140
|
+
error = make_api_error(file);
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
if(ok)
|
145
|
+
{
|
146
|
+
DWORD returned_size;
|
147
|
+
ok = 0 != DeviceIoControl (h, FSCTL_GET_REPARSE_POINT,
|
148
|
+
NULL, 0, buf, buf_size, &returned_size, NULL);
|
149
|
+
if(!ok)
|
150
|
+
{
|
151
|
+
error = make_api_error(file);
|
152
|
+
}
|
153
|
+
}
|
154
|
+
if(ok)
|
155
|
+
{
|
156
|
+
wchar_t* raw_target = NULL;
|
157
|
+
long target_len = 0;
|
158
|
+
|
159
|
+
switch (buf->ReparseTag)
|
160
|
+
{
|
161
|
+
case IO_REPARSE_TAG_MOUNT_POINT:
|
162
|
+
{
|
163
|
+
raw_target = &buf->MountPointReparseBuffer.PathBuffer[
|
164
|
+
buf->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t)];
|
165
|
+
target_len = buf->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
|
166
|
+
break;
|
167
|
+
}
|
168
|
+
case IO_REPARSE_TAG_SYMLINK:
|
169
|
+
{
|
170
|
+
raw_target = &buf->SymbolicLinkReparseBuffer.PathBuffer[
|
171
|
+
buf->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t)];
|
172
|
+
target_len = buf->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
|
173
|
+
break;
|
174
|
+
}
|
175
|
+
default:
|
176
|
+
ok = false;
|
177
|
+
error = make_error_str(rb_eIOError, "file %s is not a symlink", file);
|
178
|
+
}
|
179
|
+
if(ok)
|
180
|
+
{
|
181
|
+
wchar_t* resolved;
|
182
|
+
resolved = resolve_api_path(raw_target);
|
183
|
+
target_len -= resolved - raw_target;
|
184
|
+
target = wstr_to_str(filecp(), resolved, target_len);
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
|
189
|
+
if( h != INVALID_HANDLE_VALUE )
|
190
|
+
{
|
191
|
+
CloseHandle(h);
|
192
|
+
}
|
193
|
+
xfree(buf);
|
194
|
+
|
195
|
+
if( !NIL_P(error) )
|
196
|
+
{
|
197
|
+
rb_exc_raise(error);
|
198
|
+
}
|
199
|
+
return target;
|
200
|
+
}
|
201
|
+
|
202
|
+
static VALUE
|
203
|
+
rb_readlink(VALUE mod, VALUE file)
|
204
|
+
{
|
205
|
+
(void)mod;
|
206
|
+
FilePathValue(file);
|
207
|
+
file = rb_str_encode_ospath(file);
|
208
|
+
return win32_readlink(RSTRING_PTR(file));
|
209
|
+
}
|
210
|
+
|
211
|
+
static VALUE
|
212
|
+
rb_symlink_p(VALUE mod, VALUE file)
|
213
|
+
{
|
214
|
+
(void)mod;
|
215
|
+
DWORD attrs;
|
216
|
+
FilePathValue(file);
|
217
|
+
file = rb_str_encode_ospath(file);
|
218
|
+
attrs = GetFileAttributes(RSTRING_PTR(file));
|
219
|
+
if( attrs == INVALID_FILE_ATTRIBUTES )
|
220
|
+
{
|
221
|
+
rb_exc_raise(make_api_error(RSTRING_PTR(file)));
|
222
|
+
}
|
223
|
+
return (attrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
|
224
|
+
}
|
225
|
+
|
226
|
+
static bool
|
227
|
+
is_directory(wchar_t* path)
|
228
|
+
{
|
229
|
+
HANDLE h = INVALID_HANDLE_VALUE;
|
230
|
+
WIN32_FIND_DATAW fd;
|
231
|
+
h = FindFirstFileW(path, &fd);
|
232
|
+
if( h != INVALID_HANDLE_VALUE )
|
233
|
+
{
|
234
|
+
FindClose(h);
|
235
|
+
return (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ;
|
236
|
+
}
|
237
|
+
return false;
|
238
|
+
}
|
239
|
+
|
240
|
+
static VALUE
|
241
|
+
rb_symlink(VALUE mod, VALUE target, VALUE symlink)
|
242
|
+
{
|
243
|
+
(void)mod;
|
244
|
+
|
245
|
+
VALUE error = Qnil;
|
246
|
+
wchar_t* wtarget = NULL;
|
247
|
+
wchar_t* wsymlink = NULL;
|
248
|
+
BOOL res;
|
249
|
+
DWORD flags = 0;
|
250
|
+
|
251
|
+
target = FilePathValue(target);
|
252
|
+
symlink = FilePathValue(symlink);
|
253
|
+
target = rb_str_encode_ospath(target);
|
254
|
+
symlink = rb_str_encode_ospath(symlink);
|
255
|
+
|
256
|
+
wtarget = filecp_to_wstr(RSTRING_PTR(target), NULL);
|
257
|
+
wsymlink = filecp_to_wstr(RSTRING_PTR(symlink), NULL);
|
258
|
+
|
259
|
+
if( is_directory(wsymlink) )
|
260
|
+
{
|
261
|
+
flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
|
262
|
+
}
|
263
|
+
res = create_symbolic_linkW(wsymlink, wtarget, flags);
|
264
|
+
if( !res )
|
265
|
+
{
|
266
|
+
error = make_api_error(RSTRING_PTR(target));
|
267
|
+
}
|
268
|
+
|
269
|
+
xfree(wtarget);
|
270
|
+
xfree(wsymlink);
|
271
|
+
|
272
|
+
if( !NIL_P(error) )
|
273
|
+
{
|
274
|
+
rb_exc_raise(error);
|
275
|
+
}
|
276
|
+
return INT2FIX(0);
|
277
|
+
}
|
278
|
+
|
279
|
+
extern "C" void
|
280
|
+
Init_win32_symlink()
|
281
|
+
{
|
282
|
+
VALUE mod_win32;
|
283
|
+
VALUE mod;
|
284
|
+
|
285
|
+
mod_win32 = rb_define_module("Win32");
|
286
|
+
mod = rb_define_module_under(mod_win32, "Symlink");
|
287
|
+
|
288
|
+
rb_define_module_function(mod, "readlink", RUBY_METHOD_FUNC(rb_readlink), 1);
|
289
|
+
rb_define_module_function(mod, "symlink?", RUBY_METHOD_FUNC(rb_symlink_p), 1);
|
290
|
+
|
291
|
+
create_symbolic_linkW = (create_symbolic_linkW_t)GetProcAddress(
|
292
|
+
GetModuleHandle("kernel32.dll"), "CreateSymbolicLinkW");
|
293
|
+
if( create_symbolic_linkW )
|
294
|
+
{
|
295
|
+
rb_define_module_function(mod, "symlink", RUBY_METHOD_FUNC(rb_symlink), 2);
|
296
|
+
}
|
297
|
+
}
|
Binary file
|
data/tasks/ext.rake
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(File.dirname(__FILE__)), 'ext')
|
2
|
+
|
3
|
+
# puts $LOAD_PATH
|
4
|
+
|
5
|
+
require 'test/unit'
|
6
|
+
require 'win32/symlink'
|
7
|
+
include Win32
|
8
|
+
|
9
|
+
class Errno::E4390 < SystemCallError
|
10
|
+
# The file is not a reparse point
|
11
|
+
end
|
12
|
+
class Errno::E1314 < SystemCallError
|
13
|
+
# A required privilege is not set
|
14
|
+
end
|
15
|
+
|
16
|
+
class TC_Win32Symlink < Test::Unit::TestCase
|
17
|
+
|
18
|
+
def setup
|
19
|
+
@users_dir = File.join(ENV['SYSTEMDRIVE'], '/Users')
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_bad_args
|
23
|
+
assert_raises(Errno::ENOENT) {Symlink.symlink? ""}
|
24
|
+
assert_raises(TypeError) { Symlink.symlink? nil }
|
25
|
+
assert_raises(TypeError) { Symlink.symlink?(Object.new) }
|
26
|
+
assert_raises(TypeError) { Symlink.symlink "", nil }
|
27
|
+
assert_raises(TypeError) { Symlink.symlink nil, "" }
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_system_links
|
31
|
+
assert(Symlink.symlink?(File.join(@users_dir, "All Users")))
|
32
|
+
assert(!Symlink.symlink?(ENV['WINDIR']))
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_readlink
|
36
|
+
assert_equal(Symlink.readlink(File.join(@users_dir, "All Users")), ENV['ALLUSERSPROFILE'])
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_nonlink
|
40
|
+
assert_raises(Errno::E4390) { Symlink.readlink(ENV['WINDIR']) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_makelink
|
44
|
+
Dir.chdir(ENV["TMP"]) do
|
45
|
+
IO::write("symlink-test-file", "test")
|
46
|
+
begin
|
47
|
+
Symlink.symlink("symlink-test-file", "symlink-test-symlink")
|
48
|
+
assert(Symlink.symlink? "symlink-test-symlink")
|
49
|
+
rescue Errno::E1314 => e
|
50
|
+
skip e.message
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def teardown
|
56
|
+
Dir.glob(File.join(ENV['TMP'], 'symlink-test*')).each {|f| File::unlink f}
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
require File.expand_path('../lib/win32/symlink/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ['Boris Kropivnitsky']
|
6
|
+
gem.email = ['boris.kro@gmail.com']
|
7
|
+
gem.description = <<DESC
|
8
|
+
Symlink functions for Windows (Vista and above)
|
9
|
+
DESC
|
10
|
+
gem.summary = 'symlink functions for Windows'
|
11
|
+
gem.homepage = ''
|
12
|
+
|
13
|
+
gem.files = %w{
|
14
|
+
Gemfile
|
15
|
+
LICENSE
|
16
|
+
README.md
|
17
|
+
Rakefile
|
18
|
+
ext/win32/extconf.rb
|
19
|
+
ext/win32/win32-symlink.cpp
|
20
|
+
lib/win32/symlink.rb
|
21
|
+
lib/win32/symlink/version.rb
|
22
|
+
lib/win32/symlink/win32_symlink.so
|
23
|
+
tasks/ext.rake
|
24
|
+
test/test_win32_symlink.rb
|
25
|
+
win32-symlink.gemspec
|
26
|
+
}
|
27
|
+
gem.extensions = ['ext/win32/extconf.rb']
|
28
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
29
|
+
gem.name = 'win32-symlink'
|
30
|
+
gem.require_paths = ['lib']
|
31
|
+
gem.version = Win32::Symlink::VERSION
|
32
|
+
gem.licenses = ['MIT']
|
33
|
+
gem.add_development_dependency 'bundler'
|
34
|
+
gem.add_development_dependency 'rake-compiler'
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: win32-symlink
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Boris Kropivnitsky
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake-compiler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: |
|
42
|
+
Symlink functions for Windows (Vista and above)
|
43
|
+
email:
|
44
|
+
- boris.kro@gmail.com
|
45
|
+
executables: []
|
46
|
+
extensions:
|
47
|
+
- ext/win32/extconf.rb
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- Gemfile
|
51
|
+
- LICENSE
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- ext/win32/extconf.rb
|
55
|
+
- ext/win32/win32-symlink.cpp
|
56
|
+
- lib/win32/symlink.rb
|
57
|
+
- lib/win32/symlink/version.rb
|
58
|
+
- lib/win32/symlink/win32_symlink.so
|
59
|
+
- tasks/ext.rake
|
60
|
+
- test/test_win32_symlink.rb
|
61
|
+
- win32-symlink.gemspec
|
62
|
+
homepage: ''
|
63
|
+
licenses:
|
64
|
+
- MIT
|
65
|
+
metadata: {}
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options: []
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 2.1.11
|
83
|
+
signing_key:
|
84
|
+
specification_version: 4
|
85
|
+
summary: symlink functions for Windows
|
86
|
+
test_files:
|
87
|
+
- test/test_win32_symlink.rb
|