fig 0.1.67 → 0.1.69
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.
- data/Changes +63 -1
- data/lib/fig.rb +1 -1
- data/lib/fig/command.rb +59 -24
- data/lib/fig/command/action.rb +7 -0
- data/lib/fig/command/action/publish.rb +6 -2
- data/lib/fig/command/action/publish_local.rb +5 -1
- data/lib/fig/command/action/role/publish.rb +34 -13
- data/lib/fig/command/action/version.rb +5 -1
- data/lib/fig/command/options.rb +153 -261
- data/lib/fig/command/options/parser.rb +187 -0
- data/lib/fig/logging.rb +2 -2
- data/lib/fig/operating_system.rb +1 -1
- data/lib/fig/package.rb +6 -6
- data/lib/fig/parser.rb +4 -3
- data/lib/fig/repository.rb +33 -247
- data/lib/fig/repository_package_publisher.rb +318 -0
- data/lib/fig/update_lock.rb +68 -0
- data/lib/fig/working_directory_maintainer.rb +66 -32
- metadata +29 -26
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
require 'optparse'
|
|
2
|
+
|
|
3
|
+
require 'fig/command/option_error'
|
|
4
|
+
|
|
5
|
+
module Fig; end
|
|
6
|
+
class Fig::Command; end
|
|
7
|
+
class Fig::Command::Options; end
|
|
8
|
+
|
|
9
|
+
# Command-line processing.
|
|
10
|
+
class Fig::Command::Options::Parser
|
|
11
|
+
# This class knows way too much about how OptionParser works.
|
|
12
|
+
|
|
13
|
+
USAGE = <<-EOF
|
|
14
|
+
Usage:
|
|
15
|
+
|
|
16
|
+
fig [...] [DESCRIPTOR] [--update | --update-if-missing] [-- COMMAND]
|
|
17
|
+
fig [...] [DESCRIPTOR] [--update | --update-if-missing] [--command-extra-args VALUES]
|
|
18
|
+
|
|
19
|
+
fig {--publish | --publish-local} DESCRIPTOR
|
|
20
|
+
[--resource PATH]
|
|
21
|
+
[--archive PATH]
|
|
22
|
+
[--include DESCRIPTOR]
|
|
23
|
+
[--override DESCRIPTOR]
|
|
24
|
+
[--force]
|
|
25
|
+
[...]
|
|
26
|
+
|
|
27
|
+
fig --clean DESCRIPTOR [...]
|
|
28
|
+
|
|
29
|
+
fig --get VARIABLE [DESCRIPTOR] [...]
|
|
30
|
+
fig --list-configs [DESCRIPTOR] [...]
|
|
31
|
+
fig --list-dependencies [--list-tree] [--list-all-configs] [DESCRIPTOR] [...]
|
|
32
|
+
fig --list-variables [--list-tree] [--list-all-configs] [DESCRIPTOR] [...]
|
|
33
|
+
fig {--list-local | --list-remote} [...]
|
|
34
|
+
|
|
35
|
+
fig {--version | --help}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
A DESCRIPTOR looks like <package name>[/<version>][:<config>] e.g. "foo",
|
|
39
|
+
"foo/1.2.3", and "foo/1.2.3:default". Whether ":<config>" and "/<version>" are
|
|
40
|
+
required or allowed is dependent upon what your are doing.
|
|
41
|
+
|
|
42
|
+
Standard options (represented as "[...]" above):
|
|
43
|
+
|
|
44
|
+
[--set VARIABLE=VALUE]
|
|
45
|
+
[--append VARIABLE=VALUE]
|
|
46
|
+
[--file PATH] [--no-file]
|
|
47
|
+
[--config CONFIG]
|
|
48
|
+
[--login]
|
|
49
|
+
[--log-level LEVEL] [--log-config PATH]
|
|
50
|
+
[--figrc PATH] [--no-figrc]
|
|
51
|
+
[--suppress-warning-include-statement-missing-version]
|
|
52
|
+
|
|
53
|
+
Environment variables:
|
|
54
|
+
|
|
55
|
+
FIG_REMOTE_URL (required),
|
|
56
|
+
FIG_HOME (path to local repository cache, defaults to $HOME/.fighome).
|
|
57
|
+
EOF
|
|
58
|
+
|
|
59
|
+
def initialize()
|
|
60
|
+
@switches = {}
|
|
61
|
+
@argument_description = {}
|
|
62
|
+
@parser = OptionParser.new
|
|
63
|
+
|
|
64
|
+
@parser.banner = "#{USAGE}\n"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def add_argument_description(options, description)
|
|
68
|
+
if options.is_a? Array
|
|
69
|
+
options.each do
|
|
70
|
+
|option|
|
|
71
|
+
|
|
72
|
+
@argument_description[option] = description
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
@argument_description[options] = description
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
return
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def on_head(*arguments, &block)
|
|
82
|
+
switch_array = make_switch_array(arguments, block)
|
|
83
|
+
|
|
84
|
+
return if not switch_array
|
|
85
|
+
|
|
86
|
+
@parser.top.prepend(*switch_array)
|
|
87
|
+
|
|
88
|
+
return
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def on(*arguments, &block)
|
|
92
|
+
switch_array = make_switch_array(arguments, block)
|
|
93
|
+
|
|
94
|
+
return if not switch_array
|
|
95
|
+
|
|
96
|
+
@parser.top.append(*switch_array)
|
|
97
|
+
|
|
98
|
+
return
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def on_tail(*arguments, &block)
|
|
102
|
+
switch_array = make_switch_array(arguments, block)
|
|
103
|
+
|
|
104
|
+
return if not switch_array
|
|
105
|
+
|
|
106
|
+
@parser.base.append(*switch_array)
|
|
107
|
+
|
|
108
|
+
return
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def help()
|
|
112
|
+
return @parser.help
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def parse!(argv)
|
|
116
|
+
begin
|
|
117
|
+
@parser.parse!(argv)
|
|
118
|
+
rescue OptionParser::InvalidArgument => error
|
|
119
|
+
raise_invalid_argument(error.args[0], error.args[1])
|
|
120
|
+
rescue OptionParser::MissingArgument => error
|
|
121
|
+
raise_missing_argument(error.args[0])
|
|
122
|
+
rescue OptionParser::InvalidOption => error
|
|
123
|
+
raise Fig::Command::OptionError.new(
|
|
124
|
+
"Unknown option #{error.args[0]}.\n\n#{USAGE}"
|
|
125
|
+
)
|
|
126
|
+
rescue OptionParser::ParseError => error
|
|
127
|
+
raise Fig::Command::OptionError.new(error.to_s)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
return
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def raise_invalid_argument(option, value)
|
|
134
|
+
# *sigh* OptionParser does not raise MissingArgument for the case of an
|
|
135
|
+
# option with a required value being followed by another option. It
|
|
136
|
+
# assigns the next option as the value instead. E.g. for
|
|
137
|
+
#
|
|
138
|
+
# fig --set --get FOO
|
|
139
|
+
#
|
|
140
|
+
# it assigns "--get" as the value of the "--set" option.
|
|
141
|
+
if @switches.has_key? value
|
|
142
|
+
raise_missing_argument(option)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
description = @argument_description[option]
|
|
146
|
+
if description.nil?
|
|
147
|
+
description = ''
|
|
148
|
+
else
|
|
149
|
+
description = ' ' + description
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
raise Fig::Command::OptionError.new(
|
|
153
|
+
%Q<Invalid value for #{option}: "#{value}".#{description}>
|
|
154
|
+
)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
private
|
|
158
|
+
|
|
159
|
+
def make_switch_array(arguments, block)
|
|
160
|
+
# From the OptionParser code, the contents of the array:
|
|
161
|
+
#
|
|
162
|
+
# +switch+:: OptionParser::Switch instance to be inserted.
|
|
163
|
+
# +short_opts+:: List of short style options.
|
|
164
|
+
# +long_opts+:: List of long style options.
|
|
165
|
+
# +nolong_opts+:: List of long style options with "no-" prefix.
|
|
166
|
+
#
|
|
167
|
+
# Why returning this data separate from the Switch object is necessary, I
|
|
168
|
+
# do not understand.
|
|
169
|
+
|
|
170
|
+
switch_array = @parser.make_switch(arguments, block)
|
|
171
|
+
switch = switch_array[0]
|
|
172
|
+
|
|
173
|
+
options = [switch.long, switch.short].flatten
|
|
174
|
+
|
|
175
|
+
return if options.any? {|option| @switches.has_key? option}
|
|
176
|
+
|
|
177
|
+
options.each {|option| @switches[option] = switch}
|
|
178
|
+
|
|
179
|
+
return switch_array
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def raise_missing_argument(option)
|
|
183
|
+
raise Fig::Command::OptionError.new(
|
|
184
|
+
"Please provide a value for #{option}."
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
end
|
data/lib/fig/logging.rb
CHANGED
|
@@ -45,14 +45,14 @@ module Fig::Logging
|
|
|
45
45
|
when / [.] ya?ml \z /x
|
|
46
46
|
Log4r::YamlConfigurator.load_yaml_file(config_file)
|
|
47
47
|
else
|
|
48
|
-
raise ConfigFileError, %Q<Don't know what format #{config_file} is in.>, config_file
|
|
48
|
+
raise Fig::ConfigFileError, %Q<Don't know what format #{config_file} is in.>, config_file
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
if Log4r::Logger['fig'].nil?
|
|
52
52
|
$stderr.puts %q<A value was provided for --log-config but no "fig" logger was defined.>
|
|
53
53
|
end
|
|
54
54
|
rescue Log4r::ConfigError, ArgumentError => exception
|
|
55
|
-
raise Log4rConfigError.new(config_file, exception)
|
|
55
|
+
raise Fig::Log4rConfigError.new(config_file, exception)
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
data/lib/fig/operating_system.rb
CHANGED
|
@@ -242,7 +242,7 @@ class Fig::OperatingSystem
|
|
|
242
242
|
end
|
|
243
243
|
end
|
|
244
244
|
|
|
245
|
-
def upload(local_file, remote_file
|
|
245
|
+
def upload(local_file, remote_file)
|
|
246
246
|
Fig::Logging.debug "Uploading #{local_file} to #{remote_file}."
|
|
247
247
|
uri = URI.parse(remote_file)
|
|
248
248
|
case uri.scheme
|
data/lib/fig/package.rb
CHANGED
|
@@ -20,15 +20,15 @@ class Fig::Package
|
|
|
20
20
|
DEFAULT_CONFIG = 'default'
|
|
21
21
|
|
|
22
22
|
attr_reader :name, :version, :directory, :statements
|
|
23
|
-
attr_accessor :backtrace
|
|
23
|
+
attr_accessor :backtrace, :unparsed_text
|
|
24
24
|
|
|
25
25
|
def initialize(name, version, directory, statements)
|
|
26
|
-
@name
|
|
27
|
-
@version
|
|
28
|
-
@directory
|
|
29
|
-
@statements
|
|
26
|
+
@name = name
|
|
27
|
+
@version = version
|
|
28
|
+
@directory = directory
|
|
29
|
+
@statements = statements
|
|
30
30
|
@applied_config_names = []
|
|
31
|
-
@backtrace
|
|
31
|
+
@backtrace = nil
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def [](config_name)
|
data/lib/fig/parser.rb
CHANGED
|
@@ -21,13 +21,13 @@ class Fig::Parser
|
|
|
21
21
|
@check_include_versions = check_include_versions
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def parse_package(descriptor, directory, source_description,
|
|
24
|
+
def parse_package(descriptor, directory, source_description, unparsed_text)
|
|
25
25
|
# Bye bye comments.
|
|
26
|
-
|
|
26
|
+
stripped_text = unparsed_text.gsub(/#.*$/, '')
|
|
27
27
|
|
|
28
28
|
# Extra space at the end because most of the rules in the grammar require
|
|
29
29
|
# trailing whitespace.
|
|
30
|
-
result = @treetop_parser.parse(
|
|
30
|
+
result = @treetop_parser.parse(stripped_text + ' ')
|
|
31
31
|
|
|
32
32
|
extended_description =
|
|
33
33
|
extend_source_description(directory, source_description)
|
|
@@ -40,6 +40,7 @@ class Fig::Parser
|
|
|
40
40
|
directory,
|
|
41
41
|
Fig::ParserPackageBuildState.new(descriptor, extended_description)
|
|
42
42
|
)
|
|
43
|
+
package.unparsed_text = unparsed_text
|
|
43
44
|
|
|
44
45
|
check_for_bad_urls(package, descriptor)
|
|
45
46
|
check_for_multiple_command_statements(package)
|
data/lib/fig/repository.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'fileutils'
|
|
1
2
|
require 'set'
|
|
2
3
|
require 'socket'
|
|
3
4
|
require 'sys/admin'
|
|
@@ -5,16 +6,13 @@ require 'tmpdir'
|
|
|
5
6
|
|
|
6
7
|
require 'fig'
|
|
7
8
|
require 'fig/at_exit'
|
|
8
|
-
require 'fig/command'
|
|
9
9
|
require 'fig/logging'
|
|
10
10
|
require 'fig/not_found_error'
|
|
11
11
|
require 'fig/package_cache'
|
|
12
12
|
require 'fig/package_descriptor'
|
|
13
13
|
require 'fig/parser'
|
|
14
14
|
require 'fig/repository_error'
|
|
15
|
-
require 'fig/
|
|
16
|
-
require 'fig/statement/resource'
|
|
17
|
-
require 'fig/url_access_error'
|
|
15
|
+
require 'fig/repository_package_publisher'
|
|
18
16
|
|
|
19
17
|
module Fig; end
|
|
20
18
|
|
|
@@ -22,6 +20,7 @@ module Fig; end
|
|
|
22
20
|
# defers remote operations to others.
|
|
23
21
|
class Fig::Repository
|
|
24
22
|
METADATA_SUBDIRECTORY = '_meta'
|
|
23
|
+
PACKAGE_FILE_IN_REPO = '.fig'
|
|
25
24
|
RESOURCES_FILE = 'resources.tar.gz'
|
|
26
25
|
VERSION_FILE_NAME = 'repository-format-version'
|
|
27
26
|
VERSION_SUPPORTED = 1
|
|
@@ -34,13 +33,13 @@ class Fig::Repository
|
|
|
34
33
|
os,
|
|
35
34
|
local_repository_directory,
|
|
36
35
|
application_config,
|
|
37
|
-
|
|
36
|
+
publish_listeners,
|
|
38
37
|
check_include_versions
|
|
39
38
|
)
|
|
40
39
|
@operating_system = os
|
|
41
40
|
@local_repository_directory = local_repository_directory
|
|
42
41
|
@application_config = application_config
|
|
43
|
-
@
|
|
42
|
+
@publish_listeners = publish_listeners
|
|
44
43
|
|
|
45
44
|
@parser = Fig::Parser.new(application_config, check_include_versions)
|
|
46
45
|
|
|
@@ -123,38 +122,31 @@ class Fig::Repository
|
|
|
123
122
|
return
|
|
124
123
|
end
|
|
125
124
|
|
|
126
|
-
def publish_package(
|
|
125
|
+
def publish_package(
|
|
126
|
+
package_statements, descriptor, local_only, source_package, was_forced
|
|
127
|
+
)
|
|
127
128
|
check_local_repository_format()
|
|
128
129
|
if not local_only
|
|
129
130
|
check_remote_repository_format()
|
|
130
131
|
end
|
|
131
132
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
)
|
|
150
|
-
end
|
|
151
|
-
@operating_system.copy(
|
|
152
|
-
fig_file, local_fig_file_for_package(descriptor)
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
FileUtils.rm_rf(temp_dir)
|
|
156
|
-
|
|
157
|
-
return true
|
|
133
|
+
publisher = Fig::RepositoryPackagePublisher.new
|
|
134
|
+
publisher.operating_system = @operating_system
|
|
135
|
+
publisher.publish_listeners = @publish_listeners
|
|
136
|
+
publisher.package_statements = package_statements
|
|
137
|
+
publisher.descriptor = descriptor
|
|
138
|
+
publisher.source_package = source_package
|
|
139
|
+
publisher.was_forced = was_forced
|
|
140
|
+
publisher.base_temp_dir = base_temp_dir
|
|
141
|
+
publisher.local_dir_for_package = local_dir_for_package(descriptor)
|
|
142
|
+
publisher.remote_dir_for_package = remote_dir_for_package(descriptor)
|
|
143
|
+
publisher.local_only = local_only
|
|
144
|
+
publisher.local_fig_file_for_package =
|
|
145
|
+
local_fig_file_for_package(descriptor)
|
|
146
|
+
publisher.remote_fig_file_for_package =
|
|
147
|
+
remote_fig_file_for_package(descriptor)
|
|
148
|
+
|
|
149
|
+
return publisher.publish_package()
|
|
158
150
|
end
|
|
159
151
|
|
|
160
152
|
def update_unconditionally()
|
|
@@ -167,12 +159,8 @@ class Fig::Repository
|
|
|
167
159
|
|
|
168
160
|
private
|
|
169
161
|
|
|
170
|
-
PACKAGE_FILE_IN_REPO = '.fig'
|
|
171
|
-
|
|
172
162
|
def initialize_local_repository()
|
|
173
|
-
|
|
174
|
-
Dir.mkdir(@local_repository_directory)
|
|
175
|
-
end
|
|
163
|
+
FileUtils.mkdir_p(@local_repository_directory)
|
|
176
164
|
|
|
177
165
|
version_file = local_version_file()
|
|
178
166
|
if not File.exist?(version_file)
|
|
@@ -261,31 +249,6 @@ class Fig::Repository
|
|
|
261
249
|
return version_string.to_i()
|
|
262
250
|
end
|
|
263
251
|
|
|
264
|
-
def validate_asset_names(package_statements)
|
|
265
|
-
asset_statements = package_statements.select { |s| s.is_asset? }
|
|
266
|
-
|
|
267
|
-
asset_names = Set.new()
|
|
268
|
-
asset_statements.each do
|
|
269
|
-
|statement|
|
|
270
|
-
|
|
271
|
-
asset_name = statement.asset_name()
|
|
272
|
-
if not asset_name.nil?
|
|
273
|
-
if asset_name == RESOURCES_FILE
|
|
274
|
-
Fig::Logging.fatal \
|
|
275
|
-
%Q<You cannot have an asset with the name "#{RESOURCES_FILE}"#{statement.position_string()} due to Fig implementation details.>
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
if asset_names.include?(asset_name)
|
|
279
|
-
Fig::Logging.fatal \
|
|
280
|
-
%Q<Found multiple archives with the name "#{asset_name}"#{statement.position_string()}. If these were allowed, archives would overwrite each other.>
|
|
281
|
-
raise Fig::RepositoryError.new
|
|
282
|
-
else
|
|
283
|
-
asset_names.add(asset_name)
|
|
284
|
-
end
|
|
285
|
-
end
|
|
286
|
-
end
|
|
287
|
-
end
|
|
288
|
-
|
|
289
252
|
def remote_repository_url()
|
|
290
253
|
return @application_config.remote_repository_url()
|
|
291
254
|
end
|
|
@@ -326,12 +289,16 @@ class Fig::Repository
|
|
|
326
289
|
end
|
|
327
290
|
|
|
328
291
|
def install_package(descriptor, temp_dir)
|
|
292
|
+
remote_fig_file = remote_fig_file_for_package(descriptor)
|
|
293
|
+
local_dir = local_dir_for_package(descriptor)
|
|
294
|
+
local_fig_file = fig_file_for_package_download(local_dir)
|
|
295
|
+
return if not @operating_system.download(remote_fig_file, local_fig_file)
|
|
296
|
+
|
|
329
297
|
@operating_system.delete_and_recreate_directory(temp_dir)
|
|
330
298
|
|
|
331
|
-
|
|
332
|
-
local_fig_file = fig_file_for_package_download(temp_dir)
|
|
299
|
+
temp_fig_file = fig_file_for_package_download(temp_dir)
|
|
333
300
|
|
|
334
|
-
|
|
301
|
+
@operating_system.download(remote_fig_file, temp_fig_file)
|
|
335
302
|
|
|
336
303
|
package = read_package_from_directory(temp_dir, descriptor)
|
|
337
304
|
|
|
@@ -349,7 +316,6 @@ class Fig::Repository
|
|
|
349
316
|
@operating_system.download_resource(resource_url, temp_dir)
|
|
350
317
|
end
|
|
351
318
|
|
|
352
|
-
local_dir = local_dir_for_package(descriptor)
|
|
353
319
|
FileUtils.rm_rf(local_dir)
|
|
354
320
|
FileUtils.mkdir_p( File.dirname(local_dir) )
|
|
355
321
|
FileUtils.mv(temp_dir, local_dir)
|
|
@@ -357,25 +323,6 @@ class Fig::Repository
|
|
|
357
323
|
return
|
|
358
324
|
end
|
|
359
325
|
|
|
360
|
-
# 'resources' is an Array of fileglob patterns: ['tmp/foo/file1',
|
|
361
|
-
# 'tmp/foo/*.jar']
|
|
362
|
-
def expand_globs_from(resources)
|
|
363
|
-
expanded_files = []
|
|
364
|
-
|
|
365
|
-
resources.each do
|
|
366
|
-
|path|
|
|
367
|
-
|
|
368
|
-
globbed_files = Dir.glob(path)
|
|
369
|
-
if globbed_files.empty?
|
|
370
|
-
expanded_files << path
|
|
371
|
-
else
|
|
372
|
-
expanded_files.concat(globbed_files)
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
return expanded_files
|
|
377
|
-
end
|
|
378
|
-
|
|
379
326
|
def read_package_from_directory(directory, descriptor)
|
|
380
327
|
dot_fig_file = File.join(directory, PACKAGE_FILE_IN_REPO)
|
|
381
328
|
if not File.exist?(dot_fig_file)
|
|
@@ -432,10 +379,6 @@ class Fig::Repository
|
|
|
432
379
|
File.join(@local_repository_directory, 'tmp')
|
|
433
380
|
end
|
|
434
381
|
|
|
435
|
-
def publish_temp_dir()
|
|
436
|
-
File.join(base_temp_dir(), 'publish')
|
|
437
|
-
end
|
|
438
|
-
|
|
439
382
|
def package_download_temp_dir(descriptor)
|
|
440
383
|
base_directory = File.join(base_temp_dir(), 'package-download')
|
|
441
384
|
FileUtils.mkdir_p(base_directory)
|
|
@@ -448,161 +391,4 @@ class Fig::Repository
|
|
|
448
391
|
def package_missing?(descriptor)
|
|
449
392
|
not File.exist?(local_fig_file_for_package(descriptor))
|
|
450
393
|
end
|
|
451
|
-
|
|
452
|
-
def publish_package_content_and_derive_dot_fig_contents(
|
|
453
|
-
package_statements, descriptor, local_dir, local_only
|
|
454
|
-
)
|
|
455
|
-
header_strings = derive_package_metadata_comments(
|
|
456
|
-
package_statements, descriptor
|
|
457
|
-
)
|
|
458
|
-
deparsed_statement_strings = publish_package_content(
|
|
459
|
-
package_statements, descriptor, local_dir, local_only
|
|
460
|
-
)
|
|
461
|
-
|
|
462
|
-
statement_strings = [header_strings, deparsed_statement_strings].flatten()
|
|
463
|
-
return statement_strings.join("\n").gsub(/\n{3,}/, "\n\n").strip() + "\n"
|
|
464
|
-
end
|
|
465
|
-
|
|
466
|
-
def derive_package_metadata_comments(package_statements, descriptor)
|
|
467
|
-
now = Time.now()
|
|
468
|
-
|
|
469
|
-
asset_statements =
|
|
470
|
-
package_statements.select { |statement| statement.is_asset? }
|
|
471
|
-
asset_strings =
|
|
472
|
-
asset_statements.collect { |statement| statement.unparse('# ') }
|
|
473
|
-
asset_summary = nil
|
|
474
|
-
|
|
475
|
-
if asset_strings.empty?
|
|
476
|
-
asset_summary = [
|
|
477
|
-
%q<#>,
|
|
478
|
-
%q<# There were no asset statements in the unpublished package definition.>
|
|
479
|
-
]
|
|
480
|
-
else
|
|
481
|
-
asset_summary = [
|
|
482
|
-
%q<#>,
|
|
483
|
-
%q<# Original asset statements: >,
|
|
484
|
-
%q<#>,
|
|
485
|
-
asset_strings
|
|
486
|
-
]
|
|
487
|
-
end
|
|
488
|
-
|
|
489
|
-
return [
|
|
490
|
-
%Q<# Publishing information for #{descriptor.to_string()}:>,
|
|
491
|
-
%q<#>,
|
|
492
|
-
%Q<# Time: #{now} (epoch: #{now.to_i()})>,
|
|
493
|
-
%Q<# User: #{Sys::Admin.get_login()}>,
|
|
494
|
-
%Q<# Host: #{Socket.gethostname()}>,
|
|
495
|
-
%Q<# Args: "#{ARGV.join %q[", "]}">,
|
|
496
|
-
%Q<# Fig: v#{Fig::VERSION}>,
|
|
497
|
-
asset_summary,
|
|
498
|
-
%Q<\n>,
|
|
499
|
-
].flatten()
|
|
500
|
-
end
|
|
501
|
-
|
|
502
|
-
# Deals with Archive and Resource statements. It downloads any remote
|
|
503
|
-
# files (those where the statement references a URL as opposed to a local
|
|
504
|
-
# file) and then copies all files into the local repository and the remote
|
|
505
|
-
# repository (if not a local-only publish).
|
|
506
|
-
#
|
|
507
|
-
# Returns the deparsed strings for the resource statements with URLs
|
|
508
|
-
# replaced with in-package paths.
|
|
509
|
-
def publish_package_content(
|
|
510
|
-
package_statements, descriptor, local_dir, local_only
|
|
511
|
-
)
|
|
512
|
-
return create_resource_archive(package_statements).map do |statement|
|
|
513
|
-
if statement.is_asset?
|
|
514
|
-
asset_name = statement.asset_name()
|
|
515
|
-
asset_remote = "#{remote_dir_for_package(descriptor)}/#{asset_name}"
|
|
516
|
-
|
|
517
|
-
if Fig::Repository.is_url?(statement.url)
|
|
518
|
-
asset_local = File.join(publish_temp_dir(), asset_name)
|
|
519
|
-
|
|
520
|
-
begin
|
|
521
|
-
@operating_system.download(statement.url, asset_local)
|
|
522
|
-
rescue Fig::NotFoundError
|
|
523
|
-
Fig::Logging.fatal "Could not download #{statement.url}."
|
|
524
|
-
raise Fig::RepositoryError.new
|
|
525
|
-
end
|
|
526
|
-
else
|
|
527
|
-
asset_local = statement.url
|
|
528
|
-
check_asset_path(asset_local)
|
|
529
|
-
end
|
|
530
|
-
|
|
531
|
-
if not local_only
|
|
532
|
-
@operating_system.upload(
|
|
533
|
-
asset_local, asset_remote, @remote_repository_user
|
|
534
|
-
)
|
|
535
|
-
end
|
|
536
|
-
|
|
537
|
-
@operating_system.copy(asset_local, local_dir + '/' + asset_name)
|
|
538
|
-
if statement.is_a?(Fig::Statement::Archive)
|
|
539
|
-
@operating_system.unpack_archive(local_dir, asset_name)
|
|
540
|
-
end
|
|
541
|
-
|
|
542
|
-
statement.class.new(nil, nil, asset_name).unparse('')
|
|
543
|
-
else
|
|
544
|
-
statement.unparse('')
|
|
545
|
-
end
|
|
546
|
-
end
|
|
547
|
-
end
|
|
548
|
-
|
|
549
|
-
# Grabs all of the Resource statements that don't reference URLs, creates a
|
|
550
|
-
# "resources.tar.gz" file containing all the referenced files, strips the
|
|
551
|
-
# Resource statements out of the statements, replacing them with a single
|
|
552
|
-
# Archive statement. Thus the caller should substitute its set of
|
|
553
|
-
# statements with the return value.
|
|
554
|
-
def create_resource_archive(package_statements)
|
|
555
|
-
asset_paths = []
|
|
556
|
-
new_package_statements = package_statements.reject do |statement|
|
|
557
|
-
if (
|
|
558
|
-
statement.is_a?(Fig::Statement::Resource) &&
|
|
559
|
-
! Fig::Repository.is_url?(statement.url)
|
|
560
|
-
)
|
|
561
|
-
asset_paths << statement.url
|
|
562
|
-
true
|
|
563
|
-
else
|
|
564
|
-
false
|
|
565
|
-
end
|
|
566
|
-
end
|
|
567
|
-
|
|
568
|
-
if asset_paths.size > 0
|
|
569
|
-
asset_paths = expand_globs_from(asset_paths)
|
|
570
|
-
check_asset_paths(asset_paths)
|
|
571
|
-
|
|
572
|
-
file = RESOURCES_FILE
|
|
573
|
-
@operating_system.create_archive(file, asset_paths)
|
|
574
|
-
new_package_statements.unshift(
|
|
575
|
-
Fig::Statement::Archive.new(nil, nil, file)
|
|
576
|
-
)
|
|
577
|
-
Fig::AtExit.add { File.delete(file) }
|
|
578
|
-
end
|
|
579
|
-
|
|
580
|
-
return new_package_statements
|
|
581
|
-
end
|
|
582
|
-
|
|
583
|
-
def check_asset_path(asset_path)
|
|
584
|
-
if not File.exist?(asset_path)
|
|
585
|
-
Fig::Logging.fatal "Could not find file #{asset_path}."
|
|
586
|
-
raise Fig::RepositoryError.new
|
|
587
|
-
end
|
|
588
|
-
|
|
589
|
-
return
|
|
590
|
-
end
|
|
591
|
-
|
|
592
|
-
def check_asset_paths(asset_paths)
|
|
593
|
-
non_existing_paths =
|
|
594
|
-
asset_paths.select {|path| ! File.exist?(path) && ! File.symlink?(path) }
|
|
595
|
-
|
|
596
|
-
if not non_existing_paths.empty?
|
|
597
|
-
if non_existing_paths.size > 1
|
|
598
|
-
Fig::Logging.fatal "Could not find files: #{ non_existing_paths.join(', ') }"
|
|
599
|
-
else
|
|
600
|
-
Fig::Logging.fatal "Could not find file #{non_existing_paths[0]}."
|
|
601
|
-
end
|
|
602
|
-
|
|
603
|
-
raise Fig::RepositoryError.new
|
|
604
|
-
end
|
|
605
|
-
|
|
606
|
-
return
|
|
607
|
-
end
|
|
608
394
|
end
|