pione 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/History.txt +7 -0
- data/example/DeferredChoice/DeferredChoice.pione +14 -7
- data/{misc → example/DeferredChoice/bin}/ui.xml +11 -6
- data/example/DeferredChoice/pione-package.json +1 -1
- data/example/DeferredChoiceWithPage/DeferredChoiceWithPage.pione +47 -0
- data/example/DeferredChoiceWithPage/etc/index.html +22 -0
- data/example/DeferredChoiceWithPage/pione-package.json +18 -0
- data/example/Interaction/Interaction.pione +27 -0
- data/example/Interaction/bin/show-environment.cgi +45 -0
- data/example/Interaction/etc/.hidden-file.txt +1 -0
- data/example/Interaction/etc/cgi.html +46 -0
- data/example/Interaction/etc/create-files.html +51 -0
- data/example/Interaction/etc/delete-files.html +31 -0
- data/example/Interaction/etc/get-files.html +21 -0
- data/example/Interaction/etc/index.html +18 -0
- data/example/Interaction/etc/list-files.html +36 -0
- data/example/Interaction/pione-package.json +24 -0
- data/lib/pione/agent/job-manager.rb +19 -3
- data/lib/pione/agent/logger.rb +9 -9
- data/lib/pione/agent/messenger.rb +3 -2
- data/lib/pione/agent/task-worker.rb +32 -10
- data/lib/pione/command/option.rb +18 -0
- data/lib/pione/command/pione-client.rb +51 -22
- data/lib/pione/command/pione-interactive.rb +128 -55
- data/lib/pione/command/pione-package-build.rb +3 -3
- data/lib/pione/command/pione-task-worker.rb +23 -10
- data/lib/pione/command/pione-tuple-space-provider.rb +8 -8
- data/lib/pione/command/spawner.rb +28 -1
- data/lib/pione/front/interactive-front.rb +76 -0
- data/lib/pione/global/interactive-variable.rb +26 -0
- data/lib/pione/log/message-log-receiver.rb +4 -2
- data/lib/pione/model/task-worker-broker-model.rb +7 -1
- data/lib/pione/package/package-archiver.rb +16 -9
- data/lib/pione/package/package-handler.rb +6 -0
- data/lib/pione/package/package-info.rb +4 -0
- data/lib/pione/package/package-reader.rb +2 -4
- data/lib/pione/package/package-scanner.rb +23 -3
- data/lib/pione/rule-engine.rb +48 -19
- data/lib/pione/rule-engine/action-handler.rb +29 -5
- data/lib/pione/rule-engine/basic-handler.rb +27 -19
- data/lib/pione/test-helper/command-helper.rb +1 -1
- data/lib/pione/tuple-space/tuple-definition.yml +2 -3
- data/lib/pione/tuple-space/tuple-space-server.rb +8 -0
- data/lib/pione/util/cgi.rb +326 -0
- data/lib/pione/version.rb +1 -1
- data/lib/rootage/normalizer.rb +4 -0
- data/lib/rootage/option.rb +11 -4
- data/test/agent/spec_logger.rb +0 -1
- data/test/agent/spec_messenger.rb +1 -1
- data/test/command/spec_pione-client.rb +4 -4
- data/test/log/spec_message-log.rb +1 -1
- data/test/rule-engine/spec_action-handler.rb +25 -5
- data/test/rule-engine/spec_empty-handler.rb +36 -3
- data/test/rule-engine/spec_flow-handler.rb +90 -7
- metadata +22 -72
- data/misc/test-drb-stop-service.rb +0 -34
- data/misc/test-many-waiters-client.rb +0 -56
- data/misc/test-many-waiters-server.rb +0 -14
@@ -89,12 +89,12 @@ module Pione
|
|
89
89
|
item.process do
|
90
90
|
model[:source_locations].each do |location|
|
91
91
|
if ppg = try_to_archive(location)
|
92
|
-
Log::SystemLog.info("Package build
|
92
|
+
Log::SystemLog.info("Package build process has succeeded: %s" % ppg.address)
|
93
93
|
cmd.terminate
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
cmd.abort("Package build has failed
|
97
|
+
cmd.abort("Package build process has failed.")
|
98
98
|
end
|
99
99
|
end
|
100
100
|
end
|
@@ -111,7 +111,7 @@ module Pione
|
|
111
111
|
# archive
|
112
112
|
return archiver.archive(model[:output], false)
|
113
113
|
rescue => e
|
114
|
-
Log::Debug.system("PIONE failed to archive %s: %s" % [location, e.message])
|
114
|
+
Log::Debug.system("PIONE has failed to archive %s: %s" % [location, e.message])
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
@@ -7,24 +7,31 @@ module Pione
|
|
7
7
|
#
|
8
8
|
|
9
9
|
# Create a new process of `pione-task-worker` command.
|
10
|
-
|
10
|
+
#
|
11
|
+
# @param [Rootage::Model] model
|
12
|
+
# @param [Hash] param
|
13
|
+
# @option param [Array<String>] :features
|
14
|
+
# list of features that the task worker has
|
15
|
+
# @option param [String] :tuple_space_id
|
16
|
+
# ID of tuple space that the task worker works in
|
17
|
+
def self.spawn(model, param={})
|
11
18
|
spawner = Spawner.new(model, "pione-task-worker")
|
12
19
|
|
13
20
|
# debug options
|
14
|
-
spawner.
|
15
|
-
spawner.
|
16
|
-
spawner.
|
17
|
-
spawner.
|
18
|
-
spawner.
|
21
|
+
spawner.option_if(Global.debug_system, "--debug=system")
|
22
|
+
spawner.option_if(Global.debug_ignored_exception, "--debug=ignored_exception")
|
23
|
+
spawner.option_if(Global.debug_rule_engine, "--debug=rule_engine")
|
24
|
+
spawner.option_if(Global.debug_communication, "--debug=communication")
|
25
|
+
spawner.option_if(Global.debug_notification, "--debug=notification")
|
19
26
|
|
20
27
|
# requisite options
|
21
|
-
spawner.
|
22
|
-
spawner.
|
23
|
-
spawner.
|
28
|
+
spawner.option_from(model, :front, "--parent-front", lambda {|val| val.uri})
|
29
|
+
spawner.option_from(param, :tuple_space_id, "--tuple-space-id")
|
30
|
+
spawner.option_from(param, :features, "--features")
|
24
31
|
|
25
32
|
# others
|
26
33
|
spawner.option("--color", Global.color_enabled)
|
27
|
-
spawner.option("--file-cache-method", System::FileCache.cache_method.name
|
34
|
+
spawner.option("--file-cache-method", System::FileCache.cache_method.name)
|
28
35
|
spawner.option("--file-sliding", Global.file_sliding)
|
29
36
|
|
30
37
|
spawner.spawn # this method returns child front
|
@@ -51,6 +58,9 @@ module Pione
|
|
51
58
|
option CommonOption.file_cache_method
|
52
59
|
option CommonOption.file_sliding
|
53
60
|
|
61
|
+
option(SessionOption.request_from)
|
62
|
+
option(SessionOption.session_id)
|
63
|
+
|
54
64
|
option(:tuple_space_id) do |item|
|
55
65
|
item.type = :string
|
56
66
|
item.long = '--tuple-space-id'
|
@@ -99,6 +109,9 @@ module Pione
|
|
99
109
|
cmd.abort('"%{name}" cannot connect to tuple space.' % {name: cmd.name})
|
100
110
|
end
|
101
111
|
end
|
112
|
+
|
113
|
+
item.assign(:request_from) {model[:tuple_space].attribute("request_from")}
|
114
|
+
item.assign(:session_id) {model[:tuple_space].attribute("session_id")}
|
102
115
|
end
|
103
116
|
|
104
117
|
setup(:task_worker_agent) do |item|
|
@@ -11,17 +11,17 @@ module Pione
|
|
11
11
|
spawner = Spawner.new(cmd.model, "pione-tuple-space-provider")
|
12
12
|
|
13
13
|
# debug options
|
14
|
-
spawner.
|
15
|
-
spawner.
|
16
|
-
spawner.
|
17
|
-
spawner.
|
18
|
-
spawner.
|
14
|
+
spawner.option_if(Global.debug_system, "--debug=system")
|
15
|
+
spawner.option_if(Global.debug_ignored_exception, "--debug=ignored_exception")
|
16
|
+
spawner.option_if(Global.debug_rule_engine, "--debug=rule_engine")
|
17
|
+
spawner.option_if(Global.debug_communication, "--debug=communication")
|
18
|
+
spawner.option_if(Global.debug_notification, "--debug=notification")
|
19
19
|
|
20
20
|
# requisite options
|
21
|
-
spawner.option("--parent-front", cmd.model[:front].uri
|
22
|
-
spawner.option("--communication-address", Global.communication_address
|
21
|
+
spawner.option("--parent-front", cmd.model[:front].uri)
|
22
|
+
spawner.option("--communication-address", Global.communication_address)
|
23
23
|
Global.notification_targets.each do |address|
|
24
|
-
spawner.option("--notification-target", address
|
24
|
+
spawner.option("--notification-target", address)
|
25
25
|
end
|
26
26
|
|
27
27
|
# optionals
|
@@ -49,11 +49,38 @@ module Pione
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
#
|
52
|
+
# Add arguments as command arguments.
|
53
53
|
def option(*argv)
|
54
54
|
@argv += argv.map {|val| val.to_s}
|
55
55
|
end
|
56
56
|
|
57
|
+
# Add arguments if the condition is true.
|
58
|
+
def option_if(cond, *args)
|
59
|
+
if cond
|
60
|
+
option(*args)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Add the option name and the value as command arguments. If the value
|
65
|
+
# doesn't exist in the table or the value is `nil`, no options are
|
66
|
+
# added. This is useful for the case a caller's command option passes
|
67
|
+
# callee's.
|
68
|
+
#
|
69
|
+
# @param [Hash] table
|
70
|
+
# value table
|
71
|
+
# @param [Symbol] key
|
72
|
+
# key of the value table
|
73
|
+
# @param [String] option_name
|
74
|
+
# option name
|
75
|
+
# @return [void]
|
76
|
+
def option_from(table, key, option_name, converter=nil)
|
77
|
+
if table[key]
|
78
|
+
val = table[key]
|
79
|
+
val = converter.call(val) if converter
|
80
|
+
option(option_name, val)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
57
84
|
# Register the block that is executed when the spawned process is terminated.
|
58
85
|
def when_terminated(&b)
|
59
86
|
Thread.new do
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Pione
|
2
|
+
module Front
|
3
|
+
# InteractiveFront is a front interface for +pione-interactive+ command.
|
4
|
+
class InteractiveFront < BasicFront
|
5
|
+
def initialize(cmd)
|
6
|
+
super(cmd, Global.interactive_front_port_range)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Read data string from the path. This path should be relative from public
|
10
|
+
# directory of pione-interactive.
|
11
|
+
#
|
12
|
+
# @param [String] path
|
13
|
+
# relative path from public directory
|
14
|
+
# @param [Hash] params
|
15
|
+
# parameters to pass to the CGI program
|
16
|
+
def get(path, cgi_info)
|
17
|
+
local_file = (@cmd.model[:public] + path)
|
18
|
+
if local_file.path.executable?
|
19
|
+
return Util::CGIExecutor.new(local_file.path, cgi_info, @cmd.model[:public], @cmd.model[:timeout]).exec
|
20
|
+
else
|
21
|
+
begin
|
22
|
+
local_file.read
|
23
|
+
rescue
|
24
|
+
return nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Create a file with the content. Thie operation returns true only if the
|
30
|
+
# file creation has succeeded.
|
31
|
+
def create(path, content)
|
32
|
+
begin
|
33
|
+
(@cmd.model[:public] + path).write(content)
|
34
|
+
return true
|
35
|
+
rescue => e
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Delete the file. Thie operation returns true only if the file deletion
|
41
|
+
# has succeeded.
|
42
|
+
def delete(path)
|
43
|
+
begin
|
44
|
+
(@cmd.model[:public] + path).delete
|
45
|
+
return true
|
46
|
+
rescue => e
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Return entry informations in the directory. When the operation returns
|
52
|
+
# nil, the file listing has failed. When this returns false, the path is
|
53
|
+
# file.
|
54
|
+
def list(path, show_all)
|
55
|
+
begin
|
56
|
+
unless (@cmd.model[:public] + path).directory?
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
|
60
|
+
(@cmd.model[:public] + path).entries.each_with_object([]) do |entry, list|
|
61
|
+
if show_all or not(entry.basename.start_with?("."))
|
62
|
+
list << {
|
63
|
+
"name" => entry.basename,
|
64
|
+
"type" => entry.directory? ? "dir" : "file",
|
65
|
+
"mtime" => entry.mtime.iso8601,
|
66
|
+
"size" => entry.size
|
67
|
+
}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
rescue => e
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Pione
|
2
|
+
module Global
|
3
|
+
# This is a begin number of port range for pione-interactive's front.
|
4
|
+
define_external_item(:interactive_front_port_range_begin) do |item|
|
5
|
+
item.desc = "start port number of interactive front"
|
6
|
+
item.init = 40900
|
7
|
+
end
|
8
|
+
|
9
|
+
# This is an end number of port range for pione-interactive's front.
|
10
|
+
define_external_item(:interactive_front_port_range_end) do |item|
|
11
|
+
item.desc = "end port number of interactive front"
|
12
|
+
item.init = 40999
|
13
|
+
end
|
14
|
+
|
15
|
+
# This is port range for pione-interactive's front.
|
16
|
+
define_computed_item(:interactive_front_port_range, [:interactive_front_port_range_begin, :interactive_front_port_range_end]) do |item|
|
17
|
+
item.desc = "port range of interactive front"
|
18
|
+
item.define_updater do
|
19
|
+
Range.new(
|
20
|
+
Global.interactive_front_port_range_begin,
|
21
|
+
Global.interactive_front_port_range_end
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -12,7 +12,9 @@ module Pione
|
|
12
12
|
# message header
|
13
13
|
# @param color [String]
|
14
14
|
# message color
|
15
|
-
|
15
|
+
# @param session_id [String]
|
16
|
+
# session_id
|
17
|
+
def receiver(message, level, header, color, session_id)
|
16
18
|
raise NotImplementedError.new
|
17
19
|
end
|
18
20
|
end
|
@@ -24,7 +26,7 @@ module Pione
|
|
24
26
|
@out = out
|
25
27
|
end
|
26
28
|
|
27
|
-
def receive(message, level, header, color)
|
29
|
+
def receive(message, level, header, color, session_id)
|
28
30
|
@out.puts "%s%s %s" % [" "*level, ("%5s" % header).color(color), message]
|
29
31
|
end
|
30
32
|
end
|
@@ -35,8 +35,14 @@ module Pione
|
|
35
35
|
|
36
36
|
# spawn a new process of pione-task-worker command
|
37
37
|
if self[:spawn_task_worker]
|
38
|
+
# make task worker's parameters
|
39
|
+
param = {
|
40
|
+
:features => Global.features,
|
41
|
+
:tuple_space_id => tuple_space.uuid
|
42
|
+
}
|
43
|
+
|
38
44
|
begin
|
39
|
-
spawner = Command::PioneTaskWorker.spawn(self,
|
45
|
+
spawner = Command::PioneTaskWorker.spawn(self, param)
|
40
46
|
@task_workers << spawner.child_front
|
41
47
|
spawner.when_terminated {delete_task_worker(spawner.child_front)}
|
42
48
|
rescue Command::SpawnError => e
|
@@ -31,6 +31,7 @@ module Pione
|
|
31
31
|
archive_documents(zip, info)
|
32
32
|
archive_scenarios(zip)
|
33
33
|
archive_bins(zip, info)
|
34
|
+
archive_etcs(zip, info)
|
34
35
|
archive_digest(zip, digest)
|
35
36
|
end
|
36
37
|
|
@@ -57,13 +58,13 @@ module Pione
|
|
57
58
|
|
58
59
|
# Archive package info file.
|
59
60
|
def archive_package_info(zip)
|
60
|
-
|
61
|
+
add_file_with_time(zip, "pione-package.json", @location + "pione-package.json")
|
61
62
|
end
|
62
63
|
|
63
64
|
# Archive documents based on package info file.
|
64
65
|
def archive_documents(zip, info)
|
65
66
|
info.documents.each do |document|
|
66
|
-
|
67
|
+
add_file_with_time(zip, document, @location + document)
|
67
68
|
end
|
68
69
|
end
|
69
70
|
|
@@ -87,13 +88,13 @@ module Pione
|
|
87
88
|
# Archive scenario document file.
|
88
89
|
def archive_scenario_document(zip, scenario)
|
89
90
|
document_location = @location + scenario + "Scenario.pione"
|
90
|
-
|
91
|
+
add_file_with_time(zip, File.join(scenario, "Scenario.pione"), document_location)
|
91
92
|
end
|
92
93
|
|
93
94
|
# Archive scenario info file.
|
94
95
|
def archive_scenario_info(zip, scenario)
|
95
96
|
info_location = @location + scenario + "pione-scenario.json"
|
96
|
-
|
97
|
+
add_file_with_time(zip, File.join(scenario, "pione-scenario.json"), info_location)
|
97
98
|
end
|
98
99
|
|
99
100
|
# Archive input data of the scenario.
|
@@ -105,7 +106,7 @@ module Pione
|
|
105
106
|
# archive input data
|
106
107
|
info.inputs.each do |input|
|
107
108
|
input_location = @location + scenario + input
|
108
|
-
|
109
|
+
add_file_with_time(zip, File.join(scenario, input), input_location)
|
109
110
|
end
|
110
111
|
end
|
111
112
|
end
|
@@ -118,21 +119,27 @@ module Pione
|
|
118
119
|
|
119
120
|
info.outputs.each do |output|
|
120
121
|
output_location = @location + scenario + output
|
121
|
-
|
122
|
+
add_file_with_time(zip, File.join(scenario, output), output_location)
|
122
123
|
end
|
123
124
|
end
|
124
125
|
end
|
125
126
|
|
126
127
|
def archive_bins(zip, info)
|
127
128
|
info.bins.each do |bin|
|
128
|
-
|
129
|
+
add_file_with_time(zip, bin, @location + bin)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def archive_etcs(zip, info)
|
134
|
+
info.etcs.each do |file|
|
135
|
+
add_file_with_time(zip, file, @location + file)
|
129
136
|
end
|
130
137
|
end
|
131
138
|
|
132
139
|
def archive_digest(zip, digest)
|
133
140
|
digest_location = Location[Temppath.create]
|
134
141
|
digest_location.write(digest)
|
135
|
-
|
142
|
+
add_file_with_time(zip, ".digest", digest_location)
|
136
143
|
end
|
137
144
|
|
138
145
|
def mkdir_with_time(zip, path, time)
|
@@ -142,7 +149,7 @@ module Pione
|
|
142
149
|
entry.extra.delete("UniversalTime")
|
143
150
|
end
|
144
151
|
|
145
|
-
def
|
152
|
+
def add_file_with_time(zip, path, orig_location)
|
146
153
|
entry = zip.add(path, orig_location.path.to_s)
|
147
154
|
entry.time = Zip::DOSTime.at(orig_location.mtime)
|
148
155
|
entry.extra.delete("UniversalTime")
|
@@ -69,9 +69,15 @@ module Pione
|
|
69
69
|
|
70
70
|
# Upload the package files to the location.
|
71
71
|
def upload(dest)
|
72
|
+
# upload bins
|
72
73
|
@info.bins.each do |entry|
|
73
74
|
(@location + entry).copy(dest + entry)
|
74
75
|
end
|
76
|
+
|
77
|
+
# upload etc files
|
78
|
+
@info.etcs.each do |entry|
|
79
|
+
(@location + entry).copy(dest + entry)
|
80
|
+
end
|
75
81
|
end
|
76
82
|
|
77
83
|
# Find scenario that have the name.
|
@@ -9,6 +9,7 @@ module Pione
|
|
9
9
|
member :documents, default: lambda { Array.new }
|
10
10
|
member :scenarios, default: lambda { Array.new }
|
11
11
|
member :bins, default: lambda { Array.new }
|
12
|
+
member :etcs, default: lambda { Array.new }
|
12
13
|
|
13
14
|
# Read package information from the string.
|
14
15
|
def self.read(str)
|
@@ -21,6 +22,7 @@ module Pione
|
|
21
22
|
args[:documents] = data["Documents"]
|
22
23
|
args[:scenarios] = data["Scenarios"]
|
23
24
|
args[:bins] = data["Bins"]
|
25
|
+
args[:etcs] = data["Etcs"]
|
24
26
|
new(args)
|
25
27
|
end
|
26
28
|
|
@@ -29,6 +31,7 @@ module Pione
|
|
29
31
|
list = []
|
30
32
|
list += documents
|
31
33
|
list += bins
|
34
|
+
list += etcs
|
32
35
|
return list
|
33
36
|
end
|
34
37
|
|
@@ -42,6 +45,7 @@ module Pione
|
|
42
45
|
data["Documents"] = documents
|
43
46
|
data["Scenarios"] = scenarios
|
44
47
|
data["Bins"] = bins
|
48
|
+
data["Etcs"] = etcs
|
45
49
|
data.to_json(*args)
|
46
50
|
end
|
47
51
|
end
|
@@ -114,14 +114,12 @@ module Pione
|
|
114
114
|
# make temporary directory
|
115
115
|
local_location = Location[Temppath.create]
|
116
116
|
|
117
|
-
# copy files to local
|
118
|
-
|
119
117
|
# pione-package.json
|
120
118
|
info = PackageInfo.read((@location + "pione-package.json").read)
|
121
119
|
(@location + "pione-package.json").copy(local_location + "pione-package.json")
|
122
120
|
|
123
|
-
#
|
124
|
-
(info.documents + info.bins).each do |path|
|
121
|
+
# copy files
|
122
|
+
(info.documents + info.bins + info.etcs).each do |path|
|
125
123
|
(@location + path).copy(local_location + path)
|
126
124
|
end
|
127
125
|
|
@@ -18,10 +18,17 @@ module Pione
|
|
18
18
|
name, editor, tag, parents = scan_annotations(documents)
|
19
19
|
scenarios = scan_scenarios(@package_location)
|
20
20
|
bins = scan_bins(@package_location)
|
21
|
+
etcs = scan_etcs(@package_location)
|
21
22
|
|
22
23
|
return PackageInfo.new(
|
23
|
-
name: name,
|
24
|
-
|
24
|
+
name: name,
|
25
|
+
editor: editor,
|
26
|
+
tag: tag,
|
27
|
+
parents: parents,
|
28
|
+
documents: documents,
|
29
|
+
scenarios: scenarios,
|
30
|
+
bins: bins,
|
31
|
+
etcs: etcs
|
25
32
|
)
|
26
33
|
else
|
27
34
|
# the case for single document package
|
@@ -116,7 +123,7 @@ module Pione
|
|
116
123
|
end
|
117
124
|
end
|
118
125
|
|
119
|
-
# Scan
|
126
|
+
# Scan executable files.
|
120
127
|
def scan_bins(location)
|
121
128
|
if (location + "bin").exist?
|
122
129
|
(location + "bin").entries.each_with_object([]) do |entry, list|
|
@@ -128,6 +135,19 @@ module Pione
|
|
128
135
|
return []
|
129
136
|
end
|
130
137
|
end
|
138
|
+
|
139
|
+
# Scan etc files.
|
140
|
+
def scan_etcs(location)
|
141
|
+
if (location + "etc").exist?
|
142
|
+
(location + "etc").entries.each_with_object([]) do |entry, list|
|
143
|
+
if entry.file?
|
144
|
+
list << entry.path.relative_path_from(@package_location.path).to_s
|
145
|
+
end
|
146
|
+
end
|
147
|
+
else
|
148
|
+
return []
|
149
|
+
end
|
150
|
+
end
|
131
151
|
end
|
132
152
|
end
|
133
153
|
end
|