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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.vimproject +78 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/lib/scout/cmd.rb +348 -0
- data/lib/scout/concurrent_stream.rb +284 -0
- data/lib/scout/config.rb +168 -0
- data/lib/scout/exceptions.rb +77 -0
- data/lib/scout/indiferent_hash/case_insensitive.rb +30 -0
- data/lib/scout/indiferent_hash/options.rb +115 -0
- data/lib/scout/indiferent_hash.rb +96 -0
- data/lib/scout/log/color.rb +224 -0
- data/lib/scout/log/color_class.rb +269 -0
- data/lib/scout/log/fingerprint.rb +69 -0
- data/lib/scout/log/progress/report.rb +244 -0
- data/lib/scout/log/progress/util.rb +173 -0
- data/lib/scout/log/progress.rb +106 -0
- data/lib/scout/log/trap.rb +107 -0
- data/lib/scout/log.rb +441 -0
- data/lib/scout/meta_extension.rb +100 -0
- data/lib/scout/misc/digest.rb +63 -0
- data/lib/scout/misc/filesystem.rb +25 -0
- data/lib/scout/misc/format.rb +255 -0
- data/lib/scout/misc/helper.rb +31 -0
- data/lib/scout/misc/insist.rb +56 -0
- data/lib/scout/misc/monitor.rb +66 -0
- data/lib/scout/misc/system.rb +73 -0
- data/lib/scout/misc.rb +10 -0
- data/lib/scout/named_array.rb +138 -0
- data/lib/scout/open/lock/lockfile.rb +587 -0
- data/lib/scout/open/lock.rb +68 -0
- data/lib/scout/open/remote.rb +135 -0
- data/lib/scout/open/stream.rb +491 -0
- data/lib/scout/open/util.rb +244 -0
- data/lib/scout/open.rb +170 -0
- data/lib/scout/path/find.rb +204 -0
- data/lib/scout/path/tmpfile.rb +8 -0
- data/lib/scout/path/util.rb +127 -0
- data/lib/scout/path.rb +51 -0
- data/lib/scout/persist/open.rb +17 -0
- data/lib/scout/persist/path.rb +15 -0
- data/lib/scout/persist/serialize.rb +157 -0
- data/lib/scout/persist.rb +104 -0
- data/lib/scout/resource/open.rb +8 -0
- data/lib/scout/resource/path.rb +80 -0
- data/lib/scout/resource/produce/rake.rb +69 -0
- data/lib/scout/resource/produce.rb +151 -0
- data/lib/scout/resource/scout.rb +3 -0
- data/lib/scout/resource/software.rb +178 -0
- data/lib/scout/resource/util.rb +59 -0
- data/lib/scout/resource.rb +40 -0
- data/lib/scout/simple_opt/accessor.rb +54 -0
- data/lib/scout/simple_opt/doc.rb +126 -0
- data/lib/scout/simple_opt/get.rb +57 -0
- data/lib/scout/simple_opt/parse.rb +67 -0
- data/lib/scout/simple_opt/setup.rb +26 -0
- data/lib/scout/simple_opt.rb +5 -0
- data/lib/scout/tmpfile.rb +129 -0
- data/lib/scout-essentials.rb +10 -0
- data/scout-essentials.gemspec +143 -0
- data/share/color/color_names +507 -0
- data/share/color/diverging_colors.hex +12 -0
- data/share/software/install_helpers +523 -0
- data/test/scout/indiferent_hash/test_case_insensitive.rb +16 -0
- data/test/scout/indiferent_hash/test_options.rb +46 -0
- data/test/scout/log/test_color.rb +0 -0
- data/test/scout/log/test_progress.rb +108 -0
- data/test/scout/misc/test_digest.rb +30 -0
- data/test/scout/misc/test_filesystem.rb +30 -0
- data/test/scout/misc/test_insist.rb +13 -0
- data/test/scout/misc/test_system.rb +21 -0
- data/test/scout/open/test_lock.rb +52 -0
- data/test/scout/open/test_remote.rb +25 -0
- data/test/scout/open/test_stream.rb +676 -0
- data/test/scout/open/test_util.rb +73 -0
- data/test/scout/path/test_find.rb +110 -0
- data/test/scout/path/test_util.rb +22 -0
- data/test/scout/persist/test_open.rb +37 -0
- data/test/scout/persist/test_path.rb +37 -0
- data/test/scout/persist/test_serialize.rb +114 -0
- data/test/scout/resource/test_path.rb +58 -0
- data/test/scout/resource/test_produce.rb +94 -0
- data/test/scout/resource/test_software.rb +24 -0
- data/test/scout/resource/test_util.rb +38 -0
- data/test/scout/simple_opt/test_doc.rb +16 -0
- data/test/scout/simple_opt/test_get.rb +11 -0
- data/test/scout/simple_opt/test_parse.rb +10 -0
- data/test/scout/simple_opt/test_setup.rb +77 -0
- data/test/scout/test_cmd.rb +85 -0
- data/test/scout/test_concurrent_stream.rb +29 -0
- data/test/scout/test_config.rb +66 -0
- data/test/scout/test_indiferent_hash.rb +26 -0
- data/test/scout/test_log.rb +32 -0
- data/test/scout/test_meta_extension.rb +80 -0
- data/test/scout/test_misc.rb +6 -0
- data/test/scout/test_named_array.rb +43 -0
- data/test/scout/test_open.rb +146 -0
- data/test/scout/test_path.rb +54 -0
- data/test/scout/test_persist.rb +186 -0
- data/test/scout/test_resource.rb +26 -0
- data/test/scout/test_tmpfile.rb +53 -0
- data/test/test_helper.rb +50 -0
- 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,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
|