scout-essentials 1.0.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.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.vimproject +78 -0
  4. data/Gemfile +14 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +18 -0
  7. data/Rakefile +47 -0
  8. data/VERSION +1 -0
  9. data/lib/scout/cmd.rb +348 -0
  10. data/lib/scout/concurrent_stream.rb +284 -0
  11. data/lib/scout/config.rb +168 -0
  12. data/lib/scout/exceptions.rb +77 -0
  13. data/lib/scout/indiferent_hash/case_insensitive.rb +30 -0
  14. data/lib/scout/indiferent_hash/options.rb +115 -0
  15. data/lib/scout/indiferent_hash.rb +96 -0
  16. data/lib/scout/log/color.rb +224 -0
  17. data/lib/scout/log/color_class.rb +269 -0
  18. data/lib/scout/log/fingerprint.rb +69 -0
  19. data/lib/scout/log/progress/report.rb +244 -0
  20. data/lib/scout/log/progress/util.rb +173 -0
  21. data/lib/scout/log/progress.rb +106 -0
  22. data/lib/scout/log/trap.rb +107 -0
  23. data/lib/scout/log.rb +441 -0
  24. data/lib/scout/meta_extension.rb +100 -0
  25. data/lib/scout/misc/digest.rb +63 -0
  26. data/lib/scout/misc/filesystem.rb +25 -0
  27. data/lib/scout/misc/format.rb +255 -0
  28. data/lib/scout/misc/helper.rb +31 -0
  29. data/lib/scout/misc/insist.rb +56 -0
  30. data/lib/scout/misc/monitor.rb +66 -0
  31. data/lib/scout/misc/system.rb +73 -0
  32. data/lib/scout/misc.rb +10 -0
  33. data/lib/scout/named_array.rb +138 -0
  34. data/lib/scout/open/lock/lockfile.rb +587 -0
  35. data/lib/scout/open/lock.rb +68 -0
  36. data/lib/scout/open/remote.rb +135 -0
  37. data/lib/scout/open/stream.rb +491 -0
  38. data/lib/scout/open/util.rb +244 -0
  39. data/lib/scout/open.rb +170 -0
  40. data/lib/scout/path/find.rb +204 -0
  41. data/lib/scout/path/tmpfile.rb +8 -0
  42. data/lib/scout/path/util.rb +127 -0
  43. data/lib/scout/path.rb +51 -0
  44. data/lib/scout/persist/open.rb +17 -0
  45. data/lib/scout/persist/path.rb +15 -0
  46. data/lib/scout/persist/serialize.rb +157 -0
  47. data/lib/scout/persist.rb +104 -0
  48. data/lib/scout/resource/open.rb +8 -0
  49. data/lib/scout/resource/path.rb +80 -0
  50. data/lib/scout/resource/produce/rake.rb +69 -0
  51. data/lib/scout/resource/produce.rb +151 -0
  52. data/lib/scout/resource/scout.rb +3 -0
  53. data/lib/scout/resource/software.rb +178 -0
  54. data/lib/scout/resource/util.rb +59 -0
  55. data/lib/scout/resource.rb +40 -0
  56. data/lib/scout/simple_opt/accessor.rb +54 -0
  57. data/lib/scout/simple_opt/doc.rb +126 -0
  58. data/lib/scout/simple_opt/get.rb +57 -0
  59. data/lib/scout/simple_opt/parse.rb +67 -0
  60. data/lib/scout/simple_opt/setup.rb +26 -0
  61. data/lib/scout/simple_opt.rb +5 -0
  62. data/lib/scout/tmpfile.rb +129 -0
  63. data/lib/scout-essentials.rb +10 -0
  64. data/scout-essentials.gemspec +143 -0
  65. data/share/color/color_names +507 -0
  66. data/share/color/diverging_colors.hex +12 -0
  67. data/share/software/install_helpers +523 -0
  68. data/test/scout/indiferent_hash/test_case_insensitive.rb +16 -0
  69. data/test/scout/indiferent_hash/test_options.rb +46 -0
  70. data/test/scout/log/test_color.rb +0 -0
  71. data/test/scout/log/test_progress.rb +108 -0
  72. data/test/scout/misc/test_digest.rb +30 -0
  73. data/test/scout/misc/test_filesystem.rb +30 -0
  74. data/test/scout/misc/test_insist.rb +13 -0
  75. data/test/scout/misc/test_system.rb +21 -0
  76. data/test/scout/open/test_lock.rb +52 -0
  77. data/test/scout/open/test_remote.rb +25 -0
  78. data/test/scout/open/test_stream.rb +676 -0
  79. data/test/scout/open/test_util.rb +73 -0
  80. data/test/scout/path/test_find.rb +110 -0
  81. data/test/scout/path/test_util.rb +22 -0
  82. data/test/scout/persist/test_open.rb +37 -0
  83. data/test/scout/persist/test_path.rb +37 -0
  84. data/test/scout/persist/test_serialize.rb +114 -0
  85. data/test/scout/resource/test_path.rb +58 -0
  86. data/test/scout/resource/test_produce.rb +94 -0
  87. data/test/scout/resource/test_software.rb +24 -0
  88. data/test/scout/resource/test_util.rb +38 -0
  89. data/test/scout/simple_opt/test_doc.rb +16 -0
  90. data/test/scout/simple_opt/test_get.rb +11 -0
  91. data/test/scout/simple_opt/test_parse.rb +10 -0
  92. data/test/scout/simple_opt/test_setup.rb +77 -0
  93. data/test/scout/test_cmd.rb +85 -0
  94. data/test/scout/test_concurrent_stream.rb +29 -0
  95. data/test/scout/test_config.rb +66 -0
  96. data/test/scout/test_indiferent_hash.rb +26 -0
  97. data/test/scout/test_log.rb +32 -0
  98. data/test/scout/test_meta_extension.rb +80 -0
  99. data/test/scout/test_misc.rb +6 -0
  100. data/test/scout/test_named_array.rb +43 -0
  101. data/test/scout/test_open.rb +146 -0
  102. data/test/scout/test_path.rb +54 -0
  103. data/test/scout/test_persist.rb +186 -0
  104. data/test/scout/test_resource.rb +26 -0
  105. data/test/scout/test_tmpfile.rb +53 -0
  106. data/test/test_helper.rb +50 -0
  107. metadata +247 -0
@@ -0,0 +1,127 @@
1
+ module Path
2
+ def no_method_missing
3
+ class << self
4
+ undef_method :method_missing
5
+ end
6
+ end
7
+
8
+ def self.is_filename?(string, need_to_exists = true)
9
+ return false if string.nil?
10
+ return true if Path === string
11
+ return true if String === string and ! string.include?("\n") and string.split("/").select{|p| p.length > 265 }.empty? and (! need_to_exists || File.exist?(string))
12
+ return false
13
+ end
14
+
15
+ def self.sanitize_filename(filename, length = 254)
16
+ if filename.length > length
17
+ if filename =~ /(\..{2,9})$/
18
+ extension = $1
19
+ else
20
+ extension = ''
21
+ end
22
+
23
+ post_fix = "--#{filename.length}@#{length}_#{Misc.digest(filename)[0..4]}" + extension
24
+
25
+ filename = filename[0..(length - post_fix.length - 1)] << post_fix
26
+ else
27
+ filename
28
+ end
29
+ filename
30
+ end
31
+
32
+ def directory?
33
+ return nil unless self.exist?
34
+ File.directory?(self.find)
35
+ end
36
+
37
+ def dirname
38
+ self.annotate(File.dirname(self))
39
+ end
40
+
41
+ def basename
42
+ self.annotate(File.basename(self))
43
+ end
44
+
45
+ def glob(pattern = '*')
46
+ if self.include? "*"
47
+ self.glob_all
48
+ else
49
+ return [] unless self.exist?
50
+ found = self.find
51
+ exp = File.join(found, pattern)
52
+ paths = Dir.glob(exp).collect{|f| self.annotate(f) }
53
+
54
+ paths.each do |p|
55
+ p.original = File.join(found.original, p.sub(/^#{found}/, ''))
56
+ end if found.original
57
+
58
+ paths
59
+ end
60
+ end
61
+
62
+ def glob_all(pattern = nil, caller_lib = nil, search_paths = nil)
63
+ search_paths ||= Path.path_maps
64
+ search_paths = search_paths.dup
65
+
66
+ search_paths.keys.collect do |where|
67
+ found = find(where)
68
+ paths = pattern ? Dir.glob(File.join(found, pattern)) : Dir.glob(found)
69
+
70
+ paths = paths.collect{|p| self.annotate p }
71
+
72
+ paths = paths.each do |p|
73
+ p.original = File.join(found.original, p.sub(/^#{found}/, ''))
74
+ p.where = where
75
+ end if found.original and pattern
76
+
77
+ paths
78
+ end.flatten.uniq
79
+ end
80
+
81
+ def set_extension(extension)
82
+ self.annotate(self + ".#{extension}")
83
+ end
84
+
85
+ def unset_extension
86
+ self.annotate(self.split(".")[0..-2] * ".")
87
+ end
88
+
89
+ def remove_extension(extension = nil)
90
+ if extension.nil?
91
+ unset_extension
92
+ else
93
+ self.annotate(self.sub(/\.#{extension}$/,''))
94
+ end
95
+ end
96
+
97
+ def replace_extension(new_extension = nil, multiple = false)
98
+ if String === multiple
99
+ new_path = self.sub(/(\.[^\.\/]{1,5})(.#{multiple})?$/,'')
100
+ elsif multiple
101
+ new_path = self.sub(/(\.[^\.\/]{1,5})+$/,'')
102
+ else
103
+ new_path = self.sub(/\.[^\.\/]{1,5}$/,'')
104
+ end
105
+ new_path = new_path + "." + new_extension.to_s
106
+ self.annotate(new_path)
107
+ end
108
+
109
+
110
+ # Is 'file' newer than 'path'? return non-true if path is newer than file
111
+ def self.newer?(path, file, by_link = false)
112
+ return true if not Open.exists?(file)
113
+ path = path.find if Path === path
114
+ file = file.find if Path === file
115
+ if by_link
116
+ patht = File.exist?(path) ? File.lstat(path).mtime : nil
117
+ filet = File.exist?(file) ? File.lstat(file).mtime : nil
118
+ else
119
+ patht = Open.mtime(path)
120
+ filet = Open.mtime(file)
121
+ end
122
+ return true if patht.nil? || filet.nil?
123
+ diff = patht - filet
124
+ return diff if diff < 0
125
+ return false
126
+ end
127
+ end
data/lib/scout/path.rb ADDED
@@ -0,0 +1,51 @@
1
+ require_relative 'meta_extension'
2
+ require_relative 'path/find'
3
+ require_relative 'path/util'
4
+ require_relative 'path/tmpfile'
5
+
6
+ module Path
7
+ extend MetaExtension
8
+ extension_attr :pkgdir, :libdir, :path_maps
9
+
10
+ def self.default_pkgdir
11
+ @@default_pkgdir ||= 'scout'
12
+ end
13
+
14
+ def self.default_pkgdir=(pkgdir)
15
+ @@default_pkgdir = pkgdir
16
+ end
17
+
18
+ def pkgdir
19
+ @pkgdir ||= Path.default_pkgdir
20
+ end
21
+
22
+ def libdir
23
+ @libdir || Path.caller_lib_dir
24
+ end
25
+
26
+ def path_maps
27
+ @path_maps ||= Path.path_maps.dup
28
+ end
29
+
30
+ def join(subpath, prevpath = nil)
31
+ subpath = subpath.to_s if Symbol === subpath
32
+ prevpath = prevpath.to_s if Symbol === prevpath
33
+
34
+ subpath = File.join(prevpath.to_s, subpath) if prevpath
35
+ new = self.empty? ? subpath.dup : File.join(self, subpath)
36
+ self.annotate(new)
37
+ new
38
+ end
39
+
40
+ alias [] join
41
+ alias / join
42
+
43
+ def method_missing(name, prev = nil, *args, &block)
44
+ if block_given? || name.to_s.start_with?('to_')
45
+ super name, prev, *args, &block
46
+ else
47
+ join(name, prev)
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../open'
2
+ require 'json'
3
+ require 'yaml'
4
+
5
+ module Open
6
+ def self.json(file)
7
+ Open.open(file){|f| JSON.load(f) }
8
+ end
9
+
10
+ def self.yaml(file)
11
+ Open.open(file){|f| YAML.load(f) }
12
+ end
13
+
14
+ def self.marshal(file)
15
+ Open.open(file){|f| Marshal.load(f) }
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'open'
2
+
3
+ module Path
4
+ def yaml(*rest, &block)
5
+ Open.yaml(self, *rest, &block)
6
+ end
7
+
8
+ def json(*rest, &block)
9
+ Open.json(self, *rest, &block)
10
+ end
11
+
12
+ def marshal(*rest, &block)
13
+ Open.marshal(self, *rest, &block)
14
+ end
15
+ end
@@ -0,0 +1,157 @@
1
+ require_relative '../open'
2
+ require_relative 'open'
3
+ require 'set'
4
+
5
+ module Persist
6
+ TRUE_STRINGS = Set.new ["true", "True", "TRUE", "t", "T", "1", "yes", "Yes", "YES", "y", "Y", "ON", "on"] unless defined? TRUE_STRINGS
7
+ SERIALIZER = :json
8
+
9
+ class << self
10
+ attr_accessor :save_drivers, :load_drivers
11
+ def save_drivers
12
+ @save_drivers ||= {}
13
+ end
14
+ def load_drivers
15
+ @load_drivers ||= {}
16
+ end
17
+ end
18
+
19
+ def self.serialize(content, type)
20
+ type = type.to_sym if String === type
21
+ type = SERIALIZER if type == :serializer
22
+ case type
23
+ when nil, :string, :text, :integer, :float, :boolean, :file, :path, :select, :folder, :binary
24
+ if IO === content || StringIO === content
25
+ content.read
26
+ else
27
+ content.to_s
28
+ end
29
+ when :array
30
+ content * "\n"
31
+ when :yaml
32
+ content.to_yaml
33
+ when :json
34
+ content.to_json
35
+ when :marshal
36
+ Marshal.dump(content)
37
+ else
38
+ if m = type.to_s.match(/(.*)_array/)
39
+ type = m[1].to_sym
40
+ content.collect{|c| serialize(c, type) } * "\n"
41
+ else
42
+ raise "Persist does not know #{Log.fingerprint type}"
43
+ end
44
+ end
45
+ end
46
+
47
+ def self.deserialize(serialized, type)
48
+ type = type.to_sym if String === type
49
+ type = SERIALIZER if type == :serializer
50
+
51
+ case type
52
+ when nil, :string, :text, :file, :stream, :select, :folder
53
+ serialized
54
+ when :path
55
+ Path.setup(serialized)
56
+ when :integer
57
+ serialized.to_i
58
+ when :float
59
+ serialized.to_f
60
+ when :boolean
61
+ TRUE_STRINGS.include? serialized.strip
62
+ when :array
63
+ serialized.split("\n")
64
+ when :yaml
65
+ YAML.parse(serialized)
66
+ when :json
67
+ JSON.parse(serialized)
68
+ when :marshal
69
+ Marshal.load(serialized)
70
+ else
71
+ if m = type.to_s.match(/(.*)_array/)
72
+ type = m[1].to_sym
73
+ new_content = serialized.split("\n")
74
+ new_content.collect{|c| deserialize(c, type) }
75
+ else
76
+ raise "Persist does not know #{Log.fingerprint type}"
77
+ end
78
+ end
79
+ end
80
+
81
+ MEMORY = {}
82
+ def self.save(content, file, type = :serializer)
83
+ type = :serializer if type.nil?
84
+ type = type.to_sym if String === type
85
+ type = SERIALIZER if type == :serializer
86
+ type = MEMORY if type == :memory
87
+ return if content.nil?
88
+ type = MEMORY if type == :memory
89
+ type = :serializer if type.nil?
90
+
91
+ if Hash === type
92
+ type[file] = content
93
+ return
94
+ end
95
+
96
+ Log.debug "Save #{Log.fingerprint type} on #{file}"
97
+ if save_drivers[type]
98
+ if save_drivers[type].arity == 1
99
+ return Open.sensible_write(file, save_drivers[type].call(content))
100
+ else
101
+ return save_drivers[type].call(file, content)
102
+ end
103
+ end
104
+
105
+ if type == :binary
106
+ content.force_encoding("ASCII-8BIT") if content.respond_to? :force_encoding
107
+ Open.open(file, :mode => 'wb') do |f|
108
+ f.puts content
109
+ end
110
+ content
111
+ else
112
+ serialized = serialize(content, type)
113
+ Open.sensible_write(file, serialized, :force => true)
114
+ return nil
115
+ end
116
+ end
117
+
118
+ def self.load(file, type = :serializer)
119
+ file = file.find if Path === file
120
+ type = :serializer if type.nil?
121
+ type = type.to_sym if String === type
122
+ type = SERIALIZER if type == :serializer
123
+ type = MEMORY if type == :memory
124
+ return unless Hash === type || Open.exist?(file)
125
+
126
+ Log.debug "Load #{Log.fingerprint type} on #{file}"
127
+ if load_drivers[type]
128
+ return load_drivers[type].call(file)
129
+ end
130
+
131
+ case type
132
+ when :binary
133
+ Open.read(file, :mode => 'rb')
134
+ when :yaml
135
+ Open.yaml(file)
136
+ when :json
137
+ Open.json(file)
138
+ when :marshal, :serializer
139
+ Open.marshal(file)
140
+ when :stream
141
+ Open.open(file)
142
+ when :file
143
+ value = Open.read(file)
144
+ value.sub!(/^\./, File.dirname(file)) if value.start_with?("./")
145
+ value
146
+ when :file_array
147
+ Open.read(file).split("\n").collect do |f|
148
+ f.sub!(/^\./, File.dirname(file)) if f.start_with?("./")
149
+ f
150
+ end
151
+ when Hash
152
+ type[file]
153
+ else
154
+ deserialize(Open.read(file), type)
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,104 @@
1
+ require_relative 'persist/serialize'
2
+ require_relative 'persist/open'
3
+ require_relative 'persist/path'
4
+
5
+ module Persist
6
+ class << self
7
+ attr :cache_dir
8
+ def cache_dir=(cache_dir)
9
+ @cache_dir = Path === cache_dir ? cache_dir : Path.setup(cache_dir)
10
+ end
11
+ def cache_dir
12
+ @cache_dir ||= Path.setup("var/cache/persistence")
13
+ end
14
+
15
+ attr_writer :lock_dir
16
+ def lock_dir
17
+ @lock_dir ||= Path.setup("tmp/persist_locks").find
18
+ end
19
+ end
20
+
21
+ def self.persistence_path(name, options = {})
22
+ options = IndiferentHash.add_defaults options, :dir => Persist.cache_dir
23
+ other_options = IndiferentHash.pull_keys options, :other
24
+ name = name.filename if name.respond_to?(:filename) && name.filename
25
+ persist_options = {}
26
+ TmpFile.tmp_for_file(name, options.merge(persist_options), other_options)
27
+ end
28
+
29
+ MEMORY_CACHE = {}
30
+ CONNECTIONS = {}
31
+ def self.persist(name, type = :serializer, options = {}, &block)
32
+ persist_options = IndiferentHash.pull_keys options, :persist
33
+ return yield if FalseClass === persist_options[:persist]
34
+ file = persist_options[:path] || options[:path] || persistence_path(name, options)
35
+
36
+ if type == :memory
37
+ repo = options[:memory] || options[:repo] || MEMORY_CACHE
38
+ repo[file] ||= yield
39
+ return repo[file]
40
+ end
41
+
42
+ update = options[:update] || persist_options[:update]
43
+ update = Open.mtime(update) if Path === update
44
+ update = Open.mtime(file) >= update ? false : true if Time === update
45
+
46
+ lockfile = persist_options[:lockfile] || options[:lockfile] || Persist.persistence_path(file + '.persist', {:dir => Persist.lock_dir})
47
+
48
+ Open.lock lockfile do |lock|
49
+ if Open.exist?(file) && ! update
50
+ Persist.load(file, type)
51
+ else
52
+ begin
53
+ file = file.find if Path === file
54
+ return yield(file) if block.arity == 1
55
+ res = yield
56
+
57
+ if res.nil?
58
+ return Persist.load(file, type)
59
+ end
60
+
61
+ Open.rm(file)
62
+
63
+ if IO === res || StringIO === res
64
+ tee_copies = options[:tee_copies] || 1
65
+ main, *copies = Open.tee_stream_thread_multiple res, tee_copies + 1
66
+ main.lock = lock
67
+ t = Thread.new do
68
+ Thread.current.report_on_exception = false
69
+ Thread.current["name"] = "file saver: " + file
70
+ Open.sensible_write(file, main)
71
+ end
72
+ Thread.pass until t["name"]
73
+ copies.each_with_index do |copy,i|
74
+ next_stream = copies[i+1] if copies.length > i
75
+ ConcurrentStream.setup copy, :threads => t, :filename => file, :autojoin => true, :next => next_stream
76
+ end
77
+ res = copies.first
78
+ raise KeepLocked.new(res)
79
+ else
80
+ pres = Persist.save(res, file, type)
81
+ res = pres unless pres.nil?
82
+ end
83
+ rescue Exception
84
+ Thread.handle_interrupt(Exception => :never) do
85
+ if Open.exist?(file)
86
+ Log.debug "Failed persistence #{file} - erasing"
87
+ Open.rm file
88
+ else
89
+ Log.debug "Failed persistence #{file}"
90
+ end
91
+ end
92
+ raise $! unless options[:canfail]
93
+ end
94
+ res
95
+ end
96
+ end
97
+ end
98
+
99
+ def self.memory(name, options = {}, &block)
100
+ options[:persist_path] ||= options[:path] ||= [name, options[:key]].compact * ":"
101
+ self.persist(name, :memory, options, &block)
102
+ end
103
+
104
+ end
@@ -0,0 +1,8 @@
1
+ class << Open
2
+ alias _just_open open
3
+
4
+ def open(file, *args, **kwargs, &block)
5
+ file.produce if Path === file
6
+ _just_open(file, *args, **kwargs, &block)
7
+ end
8
+ end
@@ -0,0 +1,80 @@
1
+ module Path
2
+ def produce(force = false)
3
+ return self if ! force && (Open.exist?(self) || @produced)
4
+ begin
5
+ if Resource === self.pkgdir
6
+ self.pkgdir.produce self, force
7
+ else
8
+ false
9
+ end
10
+ rescue ResourceNotFound
11
+ false
12
+ rescue
13
+ message = $!.message
14
+ message = "No exception message" if message.nil? || message.empty?
15
+ Log.warn "Error producing #{self}: #{message}"
16
+ raise $!
17
+ ensure
18
+ @produced = true
19
+ end
20
+ end
21
+
22
+ def produce_with_extension(extension, *args)
23
+ begin
24
+ self.produce(*args)
25
+ rescue Exception
26
+ exception = $!
27
+ begin
28
+ self.set_extension(extension).produce(*args)
29
+ rescue Exception
30
+ raise exception
31
+ end
32
+ end
33
+ end
34
+
35
+ def produce_and_find(extension = nil, *args)
36
+ found = if extension
37
+ found = find_with_extension(extension, *args)
38
+ found.exists? ? found : produce_with_extension(extension, *args)
39
+ else
40
+ found = find
41
+ found.exists? ? found : produce(*args)
42
+ end
43
+ raise "Not found: #{self}" unless found
44
+
45
+ found
46
+ end
47
+
48
+ def relocate
49
+ return self if Open.exists?(self)
50
+ Resource.relocate(self)
51
+ end
52
+
53
+ def identify
54
+ Resource.identify(self)
55
+ end
56
+
57
+ def open(*args, &block)
58
+ produce
59
+ Open.open(self, *args, &block)
60
+ end
61
+
62
+ def read
63
+ produce
64
+ Open.read(self)
65
+ end
66
+
67
+ def write(*args, &block)
68
+ Open.write(self.find, *args, &block)
69
+ end
70
+
71
+ def list
72
+ found = produce_and_find('list')
73
+ Open.list(found)
74
+ end
75
+
76
+ def exists?
77
+ return true if Open.exists?(self.find)
78
+ self.produce
79
+ end
80
+ end
@@ -0,0 +1,69 @@
1
+ require_relative '../../misc'
2
+ require_relative '../../path'
3
+ require 'rake'
4
+
5
+ class Rake::FileTask
6
+ class << self
7
+ alias_method :old_define_task, :define_task
8
+ end
9
+
10
+ def self.define_task(file, *args, &block)
11
+ @@files ||= []
12
+ @@files << file
13
+ old_define_task(file, *args, &block)
14
+ end
15
+
16
+ def self.files
17
+ @@files
18
+ end
19
+
20
+ def self.clear_files
21
+ @@files = []
22
+ end
23
+ end
24
+
25
+ module ScoutRake
26
+ class TaskNotFound < StandardError; end
27
+ def self.run(rakefile, dir, task, &block)
28
+ old_pwd = FileUtils.pwd
29
+
30
+ Rake::Task.clear
31
+ Rake::FileTask.clear_files
32
+
33
+ t = nil
34
+ pid = Process.fork{
35
+ if block_given?
36
+ TOPLEVEL_BINDING.receiver.instance_exec &block
37
+ else
38
+ if Path.is_filename? rakefile
39
+ rakefile = rakefile.produce.find
40
+ load rakefile
41
+ else
42
+ TmpFile.with_file(rakefile) do |tmpfile|
43
+ load tmpfile
44
+ end
45
+ end
46
+ end
47
+
48
+ raise TaskNotFound if Rake::Task[task].nil?
49
+
50
+ #Misc.pre_fork
51
+ begin
52
+ Misc.in_dir(dir) do
53
+ Rake::Task[task].invoke
54
+
55
+ Rake::Task.clear
56
+ Rake::FileTask.clear_files
57
+ end
58
+ rescue Exception
59
+ Log.error "Error in rake: #{$!.message}"
60
+ Log.exception $!
61
+ Kernel.exit! -1
62
+ end
63
+ Kernel.exit! 0
64
+ }
65
+ Process.waitpid(pid)
66
+ raise "Rake failed" unless $?.success?
67
+
68
+ end
69
+ end