irpack 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.
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ir
2
+
3
+ =begin
4
+ Copyright (c) 2010 Ryuichi Sakamoto.
5
+
6
+ This software is provided 'as-is', without any express or implied
7
+ warranty. In no event will the authors be held liable for any damages
8
+ arising from the use of this software.
9
+
10
+ Permission is granted to anyone to use this software for any purpose,
11
+ including commercial applications, and to alter it and redistribute it
12
+ freely, subject to the following restrictions:
13
+
14
+ 1. The origin of this software must not be misrepresented; you must not
15
+ claim that you wrote the original software. If you use this software
16
+ in a product, an acknowledgment in the product documentation would be
17
+ appreciated but is not required.
18
+
19
+ 2. Altered source versions must be plainly marked as such, and must not be
20
+ misrepresented as being the original software.
21
+
22
+ 3. This notice may not be removed or altered from any source
23
+ distribution.
24
+ =end
25
+
26
+ require 'irpack'
27
+ require 'optparse'
28
+
29
+ packdir = nil
30
+ output_file = nil
31
+ target = :exe
32
+ compress = false
33
+ stdlib = true
34
+ opt = OptionParser.new
35
+ opt.on('-d SOURCEDIR', 'Specify pack directory. [base of ENTRYFILE]') {|v| packdir = v }
36
+ opt.on('-o OUTPUTFILE', 'Specify output file name.') {|v| output_file = v }
37
+ opt.on('-w', 'Generate window app.') { target = :winexe }
38
+ opt.on('-W', 'Generate console app.[default]') { target = :exe }
39
+ opt.on('--compress', 'Compress package.') { compress = true }
40
+ opt.on('--no-stdlib', 'Do not include IronRuby assemblies.') {|v| stdlib = v }
41
+ opt.banner = "Usage: #{$0} [options] ENTRYFILE"
42
+ opt.parse!(ARGV)
43
+
44
+ if ARGV.size<1 then
45
+ $stderr.puts opt.help
46
+ exit 1
47
+ end
48
+
49
+ entry_file = ARGV[0]
50
+ packdir ||= File.dirname(entry_file)
51
+ output_file ||= File.join(File.dirname(entry_file), File.basename(entry_file, '.*')+'.exe')
52
+ IRPack.pack_dir(packdir, entry_file, output_file,
53
+ :target => target,
54
+ :compress => compress,
55
+ :stdlib => stdlib)
56
+
@@ -0,0 +1,504 @@
1
+ =begin
2
+ Copyright (c) 2010 Ryuichi Sakamoto.
3
+
4
+ This software is provided 'as-is', without any express or implied
5
+ warranty. In no event will the authors be held liable for any damages
6
+ arising from the use of this software.
7
+
8
+ Permission is granted to anyone to use this software for any purpose,
9
+ including commercial applications, and to alter it and redistribute it
10
+ freely, subject to the following restrictions:
11
+
12
+ 1. The origin of this software must not be misrepresented; you must not
13
+ claim that you wrote the original software. If you use this software
14
+ in a product, an acknowledgment in the product documentation would be
15
+ appreciated but is not required.
16
+
17
+ 2. Altered source versions must be plainly marked as such, and must not be
18
+ misrepresented as being the original software.
19
+
20
+ 3. This notice may not be removed or altered from any source
21
+ distribution.
22
+ =end
23
+
24
+ require 'erb'
25
+ require 'fileutils'
26
+ require 'tmpdir'
27
+ require 'pathname'
28
+ require 'WindowsBase'
29
+
30
+ unless Dir.respond_to?(:mktmpdir) then
31
+ def Dir.mktmpdir(prefix_suffix=['d',''], tmpdir=Dir.tmpdir, &block)
32
+ if prefix_suffix.kind_of?(String) then
33
+ prefix = prefix_suffix
34
+ suffix = ''
35
+ else
36
+ prefix = prefix_suffix[0]
37
+ suffix = prefix_suffix[1]
38
+ end
39
+ n = 0
40
+ begin
41
+ path = File.join(tmpdir, "#{prefix}-#{Time.now.to_i}-#{$$}-#{rand(0x100000000).to_s(36)}-#{suffix}-#{n}")
42
+ Dir.mkdir(path, 0700)
43
+ rescue Errno::EEXIST
44
+ n += 1
45
+ retry
46
+ end
47
+
48
+ if block then
49
+ begin
50
+ block.call(path)
51
+ ensure
52
+ FileUtils.remove_entry_secure(path)
53
+ end
54
+ else
55
+ path
56
+ end
57
+ end
58
+ end
59
+
60
+ module IRPack
61
+ include System
62
+ include System::Reflection
63
+
64
+ module CSCompiler
65
+ include Microsoft::CSharp
66
+ include System::CodeDom::Compiler
67
+ include System::Reflection
68
+
69
+ module_function
70
+ def compiler_version
71
+ case System::Environment.version.major
72
+ when 4
73
+ 'v4.0'
74
+ when 2
75
+ 'v3.5'
76
+ end
77
+ end
78
+
79
+ def system_assemblies
80
+ case compiler_version
81
+ when 'v4.0'
82
+ [
83
+ 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
84
+ 'WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
85
+ 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
86
+ ]
87
+ when 'v3.5'
88
+ [
89
+ 'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
90
+ 'WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
91
+ 'System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
92
+ ]
93
+ end
94
+ end
95
+
96
+ def system_assembly_files
97
+ system_assemblies.collect {|name|
98
+ Assembly.reflection_only_load(name.to_clr_string).location
99
+ }
100
+ end
101
+
102
+ def find_assembly(paths, file)
103
+ path = paths.find {|path| File.exist?(File.join(path, file)) }
104
+ if path then
105
+ File.join(path, file)
106
+ else
107
+ file
108
+ end
109
+ end
110
+
111
+ class CompileError < RuntimeError; end
112
+ def compile(target, srcs, references, resources, output_name)
113
+ opts = System::Collections::Generic::Dictionary[System::String,System::String].new
114
+ opts['CompilerVersion'] = compiler_version
115
+ @compiler = CSharpCodeProvider.new(opts)
116
+ srcs = srcs.kind_of?(Array) ? srcs : [srcs]
117
+ refs = system_assembly_files + references
118
+ refs = System::Array[System::String].new(refs.size) {|i| refs[i] }
119
+ icon = resources.find {|rc| File.extname(rc)=='.ico' }
120
+
121
+ params = CompilerParameters.new(refs, output_name, false)
122
+ params.generate_in_memory = false
123
+ compiler_options = ['/optimize+']
124
+ case target
125
+ when :exe, 'exe'
126
+ params.generate_executable = true
127
+ compiler_options << '/target:exe'
128
+ compiler_options << "/win32icon:#{icon}" if icon
129
+ when :winexe, 'winexe'
130
+ params.generate_executable = true
131
+ compiler_options << '/target:winexe'
132
+ compiler_options << "/win32icon:#{icon}" if icon
133
+ else
134
+ params.generate_executable = false
135
+ compiler_options << '/target:library'
136
+ end
137
+ params.compiler_options = compiler_options.join(' ')
138
+ resources.each do |rc|
139
+ params.embedded_resources.add(rc)
140
+ end
141
+ srcs = System::Array[System::String].new(srcs.size) {|i| srcs[i] }
142
+ result = @compiler.compile_assembly_from_source(params, srcs)
143
+ result.errors.each do |err|
144
+ if err.is_warning then
145
+ $stderr.puts(err.to_s)
146
+ else
147
+ raise CompileError, err.to_s
148
+ end
149
+ end
150
+ result.path_to_assembly
151
+ end
152
+ end
153
+ end
154
+
155
+ module IRPack
156
+ BootLoaderSource = <<CS
157
+ using System;
158
+ using System.IO;
159
+ using System.IO.Packaging;
160
+ using System.Reflection;
161
+
162
+ namespace <%= module_name %> {
163
+ public class BootLoader
164
+ {
165
+ private static Assembly LoadAssemblyFromPackage(AppDomain domain, Package package, string file)
166
+ {
167
+ var uri = PackUriHelper.CreatePartUri(new Uri(file, UriKind.Relative));
168
+ if (package.PartExists(uri)) {
169
+ var stream = package.GetPart(uri).GetStream(FileMode.Open, FileAccess.Read);
170
+ var raw = new byte[stream.Length];
171
+ stream.Read(raw, 0, (int)stream.Length);
172
+ stream.Close();
173
+ return domain.Load(raw);
174
+ }
175
+ else {
176
+ return null;
177
+ }
178
+ }
179
+
180
+ private static Assembly LoadAssembly(AppDomain domain, Package package, string file)
181
+ {
182
+ try {
183
+ return domain.Load(file);
184
+ }
185
+ catch (FileNotFoundException)
186
+ {
187
+ return LoadAssemblyFromPackage(domain, package, file);
188
+ }
189
+ }
190
+
191
+ public static int Main(string[] args)
192
+ {
193
+ AppDomain domain = AppDomain.CurrentDomain;
194
+ domain.AssemblyResolve += new ResolveEventHandler(delegate (object sender, ResolveEventArgs e) {
195
+ foreach (var asm in domain.GetAssemblies()) {
196
+ if (e.Name==asm.FullName) {
197
+ return asm;
198
+ }
199
+ }
200
+ throw new FileNotFoundException(e.Name);
201
+ });
202
+ var stream = Assembly.GetEntryAssembly().GetManifestResourceStream(@"<%= package_file %>");
203
+ var package = Package.Open(stream, FileMode.Open, FileAccess.Read);
204
+ <% preload_assemblies.each do |asm| %>
205
+ LoadAssembly(domain, package, @"<%= asm %>");
206
+ <% end %>
207
+ var entry_point = LoadAssemblyFromPackage(domain, package, @"<%= module_name %>.EntryPoint.dll");
208
+ var main = entry_point.GetType(@"<%= module_name %>.EntryPoint").GetMethod("Main");
209
+ int result = (int)(main.Invoke(null, new object[] { package, args }));
210
+ package.Close();
211
+ return result;
212
+ }
213
+ }
214
+ }
215
+ CS
216
+
217
+ EntryPointSource = <<CS
218
+ using System;
219
+ using System.IO;
220
+ using System.IO.Packaging;
221
+ using System.Reflection;
222
+ using Microsoft.Scripting;
223
+ using Microsoft.Scripting.Hosting;
224
+
225
+ namespace <%= module_name %> {
226
+ public class EntryPoint
227
+ {
228
+ public class PackagePAL : PlatformAdaptationLayer
229
+ {
230
+ public Package CurrentPackage { get; set; }
231
+ public PackagePAL(Package pkg)
232
+ {
233
+ CurrentPackage = pkg;
234
+ }
235
+
236
+ private Uri ToPackageLoadPath(string path)
237
+ {
238
+ var domain = AppDomain.CurrentDomain;
239
+ var fullpath = Path.GetFullPath(path);
240
+ var searchpath = Path.GetFullPath(
241
+ domain.RelativeSearchPath!=null ?
242
+ Path.Combine(domain.BaseDirectory, domain.RelativeSearchPath) :
243
+ domain.BaseDirectory);
244
+ if (fullpath.StartsWith(searchpath)) {
245
+ var relpath = fullpath.Substring(searchpath.Length, fullpath.Length-searchpath.Length);
246
+ return PackUriHelper.CreatePartUri(new Uri(relpath, UriKind.Relative));
247
+ }
248
+ else {
249
+ return PackUriHelper.CreatePartUri(new Uri(path, UriKind.Relative));
250
+ }
251
+ }
252
+
253
+ private Uri ToPackagePath(string path)
254
+ {
255
+ var fullpath = Path.GetFullPath(path);
256
+ var searchpath = Path.GetDirectoryName(Path.GetFullPath(Assembly.GetEntryAssembly().Location));
257
+ if (fullpath.StartsWith(searchpath)) {
258
+ var relpath = fullpath.Substring(searchpath.Length, fullpath.Length-searchpath.Length);
259
+ return PackUriHelper.CreatePartUri(new Uri(relpath, UriKind.Relative));
260
+ }
261
+ else {
262
+ return PackUriHelper.CreatePartUri(new Uri(path, UriKind.Relative));
263
+ }
264
+ }
265
+
266
+ public override Assembly LoadAssembly(string name)
267
+ {
268
+ foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) {
269
+ if (asm.FullName==name) {
270
+ return asm;
271
+ }
272
+ }
273
+ return Assembly.Load(name);
274
+ }
275
+
276
+ public override Assembly LoadAssemblyFromPath(string path)
277
+ {
278
+ try {
279
+ return Assembly.LoadFile(path);
280
+ }
281
+ catch (FileNotFoundException e) {
282
+ var uri = ToPackageLoadPath(path);
283
+ if (CurrentPackage.PartExists(uri)) {
284
+ var stream = CurrentPackage.GetPart(uri).GetStream(FileMode.Open, FileAccess.Read);
285
+ var raw = new byte[stream.Length];
286
+ stream.Read(raw, 0, (int)stream.Length);
287
+ stream.Close();
288
+ return Assembly.Load(raw);
289
+ }
290
+ else {
291
+ throw e;
292
+ }
293
+ }
294
+ }
295
+
296
+ public override bool FileExists(string path)
297
+ {
298
+ if (File.Exists(path)) {
299
+ return true;
300
+ }
301
+ else {
302
+ var uri = ToPackagePath(path);
303
+ return CurrentPackage.PartExists(uri);
304
+ }
305
+ }
306
+
307
+ public override Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share)
308
+ {
309
+ if (mode==FileMode.Open && access==FileAccess.Read) {
310
+ var uri = ToPackagePath(path);
311
+ if (CurrentPackage.PartExists(uri)) {
312
+ return CurrentPackage.GetPart(uri).GetStream(mode, access);
313
+ }
314
+ else {
315
+ return new FileStream(path, mode, access, share);
316
+ }
317
+ }
318
+ else {
319
+ return new FileStream(path, mode, access, share);
320
+ }
321
+ }
322
+
323
+ public override Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
324
+ {
325
+ if (mode==FileMode.Open && access==FileAccess.Read) {
326
+ var uri = ToPackagePath(path);
327
+ if (CurrentPackage.PartExists(uri)) {
328
+ return CurrentPackage.GetPart(uri).GetStream(mode, access);
329
+ }
330
+ else {
331
+ return new FileStream(path, mode, access, share, bufferSize);
332
+ }
333
+ }
334
+ else {
335
+ return new FileStream(path, mode, access, share, bufferSize);
336
+ }
337
+ }
338
+
339
+ public override Stream OpenInputFileStream(string path)
340
+ {
341
+ var uri = ToPackagePath(path);
342
+ if (CurrentPackage.PartExists(uri)) {
343
+ return CurrentPackage.GetPart(uri).GetStream(FileMode.Open, FileAccess.Read);
344
+ }
345
+ else {
346
+ return new FileStream(path, FileMode.Open, FileAccess.Read);
347
+ }
348
+ }
349
+ }
350
+
351
+ public class IRHost : ScriptHost
352
+ {
353
+ private PlatformAdaptationLayer PAL_;
354
+ public override PlatformAdaptationLayer PlatformAdaptationLayer { get { return PAL_; } }
355
+ public IRHost(Package pkg)
356
+ {
357
+ PAL_ = new PackagePAL(pkg);
358
+ }
359
+ }
360
+
361
+ public static int Main(Package package, string[] args)
362
+ {
363
+ var runtime_setup = new ScriptRuntimeSetup();
364
+ runtime_setup.LanguageSetups.Add(IronRuby.Ruby.CreateRubySetup());
365
+ runtime_setup.Options["MainFile"] = "<%= entry_file %>";
366
+ runtime_setup.Options["Arguments"] = args;
367
+ runtime_setup.HostType = typeof(IRHost);
368
+ runtime_setup.HostArguments = new object[] { package };
369
+ var engine = IronRuby.Ruby.GetEngine(IronRuby.Ruby.CreateRuntime(runtime_setup));
370
+ try {
371
+ engine.ExecuteFile("<%= entry_file %>");
372
+ return 0;
373
+ }
374
+ catch (IronRuby.Builtins.SystemExit e) {
375
+ return e.Status;
376
+ }
377
+ }
378
+ }
379
+ }
380
+ CS
381
+ module_function
382
+ def bootloader_source(module_name, package_file, preload_assemblies)
383
+ ERB.new(BootLoaderSource).result(binding)
384
+ end
385
+
386
+ def entrypoint_source(module_name, entry_file)
387
+ ERB.new(EntryPointSource).result(binding)
388
+ end
389
+ end
390
+
391
+ module IRPack
392
+ module Packager
393
+ include System
394
+ include System::IO::Packaging
395
+
396
+ RelType = 'http://schemas.openxmlformats.org/package/2006/relationships/meta data/core-properties'
397
+ module_function
398
+ def pack(files, package_file, compress=false)
399
+ compress_option = compress ? CompressionOption.normal : CompressionOption.not_compressed
400
+ package = Package.open(package_file, System::IO::FileMode.create)
401
+ files.each do |src, dest|
402
+ uri = PackUriHelper.create_part_uri(Uri.new(dest, UriKind.relative))
403
+ part = package.create_part(uri, 'application/octet-stream', compress_option)
404
+ stream = part.get_stream
405
+ File.open(src, 'rb') do |f|
406
+ data = f.read
407
+ stream.write(data, 0, data.size)
408
+ end
409
+ stream.close
410
+ package.create_relationship(uri, TargetMode.internal, RelType)
411
+ end
412
+ package.close
413
+ end
414
+
415
+ def pack_dir(dir_name, package_file)
416
+ files = {}
417
+ base = Pathname.new(dir_name)
418
+ Dir.glob(base.join('**', '*')) do |fn|
419
+ files[fn] = Pathname.new(fn).relative_path_from(base)
420
+ end
421
+ pack(files, package_file)
422
+ end
423
+ end
424
+
425
+ AssemblyPath = ::File.dirname(Assembly.get_entry_assembly.location.to_s)
426
+ PreloadAssemblies = %w[
427
+ Microsoft.Dynamic.dll
428
+ Microsoft.Scripting.dll
429
+ Microsoft.Scripting.Core.dll
430
+ IronRuby.dll
431
+ IronRuby.Libraries.dll
432
+ IronRuby.Libraries.Yaml.dll
433
+ ]
434
+
435
+ module_function
436
+ def path_to_module_name(filename)
437
+ name = File.basename(filename, '.*')
438
+ name.gsub!(/[^A-Za-z0-9_]/, '_')
439
+ /^[A-Za-z]/=~name ? name : ('M'+name)
440
+ end
441
+
442
+ def pack(files, entry_file, output_file, options={})
443
+ preload_assemblies = PreloadAssemblies.collect {|fn|
444
+ File.join(AssemblyPath, fn)
445
+ }.select {|fn|
446
+ File.exist?(fn)
447
+ }
448
+ basename = File.basename(output_file, '.*')
449
+ module_name = path_to_module_name(output_file)
450
+ resources = options[:resources] || []
451
+ target = options[:target] || :exe
452
+ stdlib = options.include?(:stdlib) ? options[:stdlib] : true
453
+ compress = options.include?(:compress) ? options[:compress] : false
454
+ pack_files = files.dup
455
+
456
+ Dir.mktmpdir(File.basename($0,'.*')) do |tmp_path|
457
+ entry_src = entrypoint_source(module_name, entry_file)
458
+ entry_dll = File.join(tmp_path, module_name+'.EntryPoint.dll')
459
+ CSCompiler.compile(:dll, entry_src, preload_assemblies, [], entry_dll)
460
+ pack_files[entry_dll] = File.basename(entry_dll)
461
+ if stdlib then
462
+ preload_assemblies.each do |asm|
463
+ pack_files[asm] = File.basename(asm)
464
+ end
465
+ end
466
+ package_file = File.join(tmp_path, basename+'.pkg')
467
+ Packager.pack(pack_files, package_file, compress)
468
+
469
+ target_src = bootloader_source(
470
+ module_name,
471
+ File.basename(package_file),
472
+ preload_assemblies.collect {|fn| File.basename(fn) }
473
+ )
474
+ Dir.chdir(tmp_path) do
475
+ CSCompiler.compile(target, target_src, [], [File.basename(package_file)], output_file)
476
+ end
477
+ end
478
+ end
479
+
480
+ def pack_dir(pack_dir, entry_file, output_file, options={})
481
+ output_file = File.expand_path(output_file)
482
+ entry_packed = nil
483
+ pack_files = {}
484
+ resources = []
485
+ base = Pathname.new(pack_dir).expand_path
486
+ Dir.glob(base.join('**', '*')) do |fn|
487
+ path = Pathname.new(File.expand_path(fn))
488
+ next if path==output_file
489
+ relpath = path.relative_path_from(base)
490
+ pack_files[path] = relpath
491
+ if not entry_packed and
492
+ (path.to_s==File.expand_path(entry_file) or
493
+ path.basename.to_s==entry_file or
494
+ relpath.to_s==entry_file) then
495
+ entry_packed = relpath
496
+ end
497
+ resources << path.to_s if path.extname=='.ico'
498
+ end
499
+ raise ArgumentError, "Entry file `#{entry_file}' is not in packed directory."unless entry_packed
500
+ options = options.merge(:resources => resources)
501
+ pack(pack_files, entry_packed, output_file, options)
502
+ end
503
+ end
504
+
@@ -0,0 +1,48 @@
1
+
2
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'test/unit'
4
+ require 'tempfile'
5
+ require 'tmpdir'
6
+ require 'fileutils'
7
+ require 'irpack'
8
+
9
+ require 'WindowsBase'
10
+ include System
11
+ include System::IO
12
+ include System::IO::Packaging
13
+
14
+ class TC_CSCompiler < Test::Unit::TestCase
15
+ def test_compile_dll
16
+ src = <<-CS
17
+ using System;
18
+ namespace hoge {
19
+ class Hoge {
20
+ public static int Main(string[] args) {
21
+ System.Console.WriteLine("hoge");
22
+ return 0;
23
+ }
24
+ }
25
+ }
26
+ CS
27
+ references = []
28
+ resources = []
29
+ output_file = Tempfile.new(File.basename(__FILE__))
30
+ output_file.close
31
+ result = IRPack::CSCompiler.compile(
32
+ :dll,
33
+ src,
34
+ references,
35
+ resources,
36
+ output_file.path
37
+ )
38
+ assert_equal(output_file.path, result)
39
+ asm = nil
40
+ assert_nothing_raised do
41
+ asm = System::Reflection::Assembly.load_from(output_file.path)
42
+ end
43
+ assert(asm.get_type('hoge.Hoge'))
44
+ assert_nil(asm.entry_point)
45
+ assert_equal(System::Reflection::Assembly.get_entry_assembly.image_runtime_version, asm.image_runtime_version)
46
+ end
47
+ end
48
+
@@ -0,0 +1,56 @@
1
+
2
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'test/unit'
4
+ require 'tempfile'
5
+ require 'tmpdir'
6
+ require 'fileutils'
7
+ require 'irpack'
8
+
9
+ require 'WindowsBase'
10
+ include System
11
+ include System::IO
12
+ include System::IO::Packaging
13
+
14
+ class TC_Packager < Test::Unit::TestCase
15
+ SrcFiles = {
16
+ File.join(File.dirname(__FILE__), 'test_packager.rb') => 'foo.rb',
17
+ File.join(File.dirname(__FILE__), 'test_cscompiler.rb') => 'bar.rb',
18
+ }
19
+
20
+ def test_pack
21
+ target = Tempfile.new(File.basename(__FILE__))
22
+ target.close
23
+ IRPack::Packager.pack(SrcFiles, target.path)
24
+ package = Package.open(target.path, FileMode.open)
25
+ SrcFiles.each do |src, dest|
26
+ uri = Uri.new(File.join('/', dest), UriKind.relative)
27
+ assert(package.part_exists(uri))
28
+ stream = package.get_part(uri).get_stream
29
+ bytes = System::Array[System::Byte].new(stream.length)
30
+ stream.read(bytes, 0, stream.length)
31
+ assert_equal(File.open(src, 'rb'){|f|f.read}, bytes.to_a.pack('C*'))
32
+ end
33
+ end
34
+
35
+ def test_pack_dir
36
+ Dir.mktmpdir do |src_path|
37
+ SrcFiles.each do |src, dest|
38
+ FileUtils.mkdir_p(File.join(src_path, File.dirname(dest)))
39
+ FileUtils.copy(src, File.join(src_path, dest))
40
+ end
41
+ target = Tempfile.new(File.basename(__FILE__))
42
+ target.close
43
+ IRPack::Packager.pack_dir(src_path, target.path)
44
+ package = Package.open(target.path, FileMode.open)
45
+ SrcFiles.each do |src, dest|
46
+ uri = Uri.new(File.join('/', dest), UriKind.relative)
47
+ assert(package.part_exists(uri))
48
+ stream = package.get_part(uri).get_stream
49
+ bytes = System::Array[System::Byte].new(stream.length)
50
+ stream.read(bytes, 0, stream.length)
51
+ assert_equal(File.open(src, 'rb'){|f|f.read}, bytes.to_a.pack('C*'))
52
+ end
53
+ end
54
+ end
55
+ end
56
+
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: irpack
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - kumaryu
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-11 00:00:00 +09:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: |
22
+ IRPack converts your IronRuby scripts to a standalone .exe file.
23
+ Generated executable does not require IronRuby, but only .NET Framework or mono.
24
+
25
+ email: kumaryu@kumayu.net
26
+ executables:
27
+ - irpack
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - bin/irpack
34
+ - lib/irpack.rb
35
+ - test/test_cscompiler.rb
36
+ - test/test_packager.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/kumaryu/irpack
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirements:
63
+ - none
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.7
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Generate a standalone executable file from IronRuby scripts.
69
+ test_files: []
70
+