fig 0.1.62 → 0.1.64
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 +156 -0
- data/VERSION +1 -1
- data/bin/fig +9 -2
- data/bin/fig-debug +9 -2
- data/lib/fig/applicationconfiguration.rb +3 -2
- data/lib/fig/atexit.rb +37 -0
- data/lib/fig/backtrace.rb +23 -6
- data/lib/fig/command.rb +131 -31
- data/lib/fig/command/coveragesupport.rb +40 -0
- data/lib/fig/command/listing.rb +8 -8
- data/lib/fig/command/optionerror.rb +8 -0
- data/lib/fig/{options.rb → command/options.rb} +248 -144
- data/lib/fig/command/packageload.rb +161 -62
- data/lib/fig/configfileerror.rb +2 -0
- data/lib/fig/environment.rb +350 -246
- data/lib/fig/environmentvariables/casesensitive.rb +1 -1
- data/lib/fig/figrc.rb +78 -78
- data/lib/fig/grammar.treetop +204 -219
- data/lib/fig/log4rconfigerror.rb +2 -0
- data/lib/fig/operatingsystem.rb +382 -334
- data/lib/fig/package.rb +11 -33
- data/lib/fig/packagecache.rb +1 -1
- data/lib/fig/packagedescriptor.rb +103 -21
- data/lib/fig/packagedescriptorparseerror.rb +16 -0
- data/lib/fig/parser.rb +36 -19
- data/lib/fig/parserpackagebuildstate.rb +56 -0
- data/lib/fig/repository.rb +504 -259
- data/lib/fig/statement.rb +30 -12
- data/lib/fig/statement/archive.rb +8 -5
- data/lib/fig/statement/asset.rb +19 -0
- data/lib/fig/statement/command.rb +2 -2
- data/lib/fig/statement/configuration.rb +20 -20
- data/lib/fig/statement/include.rb +13 -34
- data/lib/fig/statement/override.rb +21 -7
- data/lib/fig/statement/path.rb +22 -2
- data/lib/fig/statement/resource.rb +14 -4
- data/lib/fig/statement/retrieve.rb +34 -4
- data/lib/fig/statement/set.rb +22 -2
- data/lib/fig/workingdirectorymaintainer.rb +197 -0
- data/lib/fig/workingdirectorymetadata.rb +45 -0
- metadata +52 -46
- data/lib/fig/retriever.rb +0 -141
- data/lib/fig/statement/publish.rb +0 -15
data/lib/fig/package.rb
CHANGED
@@ -37,7 +37,14 @@ class Fig::Package
|
|
37
37
|
end
|
38
38
|
|
39
39
|
descriptor = Fig::PackageDescriptor.new(@name, @version, config_name)
|
40
|
-
|
40
|
+
config_description = nil
|
41
|
+
if @name.nil? and @version.nil?
|
42
|
+
config_description = config_name
|
43
|
+
else
|
44
|
+
config_description = descriptor.to_string(:use_default_config)
|
45
|
+
end
|
46
|
+
|
47
|
+
message = %Q<There is no "#{config_description}" config.>
|
41
48
|
|
42
49
|
raise Fig::NoSuchPackageConfigError.new(message, descriptor)
|
43
50
|
end
|
@@ -58,15 +65,7 @@ class Fig::Package
|
|
58
65
|
end
|
59
66
|
|
60
67
|
def retrieves
|
61
|
-
|
62
|
-
|
63
|
-
statements.each do
|
64
|
-
|statement|
|
65
|
-
|
66
|
-
retrieves[statement.var] = statement.path if statement.is_a?(Fig::Statement::Retrieve)
|
67
|
-
end
|
68
|
-
|
69
|
-
return retrieves
|
68
|
+
return @statements.select { |statement| statement.is_a?(Fig::Statement::Retrieve) }
|
70
69
|
end
|
71
70
|
|
72
71
|
def archive_urls
|
@@ -98,6 +97,8 @@ class Fig::Package
|
|
98
97
|
|
99
98
|
if statement.is_a?(Fig::Statement::Include)
|
100
99
|
descriptors << statement.resolved_dependency_descriptor(self, backtrace)
|
100
|
+
elsif statement.is_a?(Fig::Statement::Override)
|
101
|
+
backtrace.add_override(statement)
|
101
102
|
end
|
102
103
|
end
|
103
104
|
|
@@ -114,22 +115,6 @@ class Fig::Package
|
|
114
115
|
return
|
115
116
|
end
|
116
117
|
|
117
|
-
# Block will receive a Package and a Statement.
|
118
|
-
def walk_statements_following_package_dependencies(repository, &block)
|
119
|
-
@statements.each do |statement|
|
120
|
-
yield self, statement
|
121
|
-
statement.walk_statements_following_package_dependencies(
|
122
|
-
repository, self, nil, &block
|
123
|
-
)
|
124
|
-
end
|
125
|
-
|
126
|
-
return
|
127
|
-
end
|
128
|
-
|
129
|
-
def unparse
|
130
|
-
return @statements.map { |statement| statement.unparse('') }.join("\n")
|
131
|
-
end
|
132
|
-
|
133
118
|
def ==(other)
|
134
119
|
return false if other.nil?
|
135
120
|
|
@@ -182,10 +167,3 @@ class Fig::Package
|
|
182
167
|
return mine <=> others
|
183
168
|
end
|
184
169
|
end
|
185
|
-
|
186
|
-
# TODO: get this out of the global namespace
|
187
|
-
def unparse_statements(indent, prefix, statements, suffix)
|
188
|
-
body = @statements.map { |statement| statement.unparse(indent+' ') }.join("\n")
|
189
|
-
|
190
|
-
return ["\n#{indent}#{prefix}", body, "#{indent}#{suffix}"].join("\n")
|
191
|
-
end
|
data/lib/fig/packagecache.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
require 'fig/packagedescriptorparseerror'
|
2
|
+
|
1
3
|
module Fig; end
|
2
4
|
|
3
|
-
# Parsed representation of a package
|
5
|
+
# Parsed representation of a package specification, i.e. "name/version:config".
|
4
6
|
class Fig::PackageDescriptor
|
5
7
|
include Comparable
|
6
8
|
|
7
|
-
attr_reader :name, :version, :config
|
9
|
+
attr_reader :name, :version, :config, :original_string
|
8
10
|
|
9
11
|
def self.format(name, version, config, use_default_config = false)
|
10
12
|
string = name || ''
|
@@ -24,34 +26,45 @@ class Fig::PackageDescriptor
|
|
24
26
|
return string
|
25
27
|
end
|
26
28
|
|
27
|
-
def self.parse(raw_string)
|
29
|
+
def self.parse(raw_string, options = {})
|
30
|
+
filled_in_options = {}
|
31
|
+
filled_in_options.merge!(options)
|
32
|
+
filled_in_options[:original_string] = raw_string
|
33
|
+
filled_in_options[:require_at_least_one_component] = true
|
34
|
+
|
28
35
|
# Additional checks in validate_component() will take care of the looseness
|
29
36
|
# of the regexes. These just need to ensure that the entire string gets
|
30
37
|
# assigned to one component or another.
|
31
|
-
|
32
|
-
self.new(
|
38
|
+
return self.new(
|
33
39
|
raw_string =~ %r< \A ( [^:/]+ ) >x ? $1 : nil,
|
34
40
|
raw_string =~ %r< \A [^/]* / ( [^:]+ ) >x ? $1 : nil,
|
35
|
-
raw_string =~ %r< \A [^:]* : ( .+ ) \z >x ? $1 : nil
|
41
|
+
raw_string =~ %r< \A [^:]* : ( .+ ) \z >x ? $1 : nil,
|
42
|
+
filled_in_options
|
36
43
|
)
|
37
44
|
end
|
38
45
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
46
|
+
# Options are:
|
47
|
+
#
|
48
|
+
# :name => { :required | :forbidden }
|
49
|
+
# :version => { :required | :forbidden }
|
50
|
+
# :config => { :required | :forbidden }
|
51
|
+
# :original_string => the unparsed form
|
52
|
+
# :require_at_least_one_component => should we have at least one of
|
53
|
+
# name, version, and config
|
54
|
+
# :validation_context => what the descriptor is for
|
55
|
+
# :source_description => where the descriptor came from,
|
56
|
+
# most likely the result of invoking
|
57
|
+
# Fig::Statement.position_description().
|
58
|
+
def initialize(name, version, config, options = {})
|
59
|
+
@name = name
|
60
|
+
@version = version
|
61
|
+
@config = config
|
62
|
+
@original_string = options[:original_string]
|
53
63
|
|
54
|
-
|
64
|
+
validate_component name, 'name', :name, options
|
65
|
+
validate_component version, 'version', :version, options
|
66
|
+
validate_component config, 'config', :config, options
|
67
|
+
validate_across_components options
|
55
68
|
end
|
56
69
|
|
57
70
|
# Specifically not named :to_s because it doesn't act like that should.
|
@@ -64,4 +77,73 @@ class Fig::PackageDescriptor
|
|
64
77
|
def <=>(other)
|
65
78
|
return to_string() <=> other.to_string()
|
66
79
|
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def validate_component(
|
84
|
+
value, name, presence_requirement_symbol, options
|
85
|
+
)
|
86
|
+
validate_component_format(value, name, options)
|
87
|
+
|
88
|
+
case options[presence_requirement_symbol]
|
89
|
+
when :required
|
90
|
+
if value.nil?
|
91
|
+
throw_presence_exception(name, presence_requirement_symbol, options)
|
92
|
+
end
|
93
|
+
when :forbidden
|
94
|
+
if ! value.nil?
|
95
|
+
throw_presence_exception(name, presence_requirement_symbol, options)
|
96
|
+
end
|
97
|
+
else
|
98
|
+
# No requirements
|
99
|
+
end
|
100
|
+
|
101
|
+
return
|
102
|
+
end
|
103
|
+
|
104
|
+
def validate_component_format(value, name, options)
|
105
|
+
return if value.nil?
|
106
|
+
|
107
|
+
return if value =~ / \A [a-zA-Z0-9_.-]+ \z /x
|
108
|
+
|
109
|
+
raise Fig::PackageDescriptorParseError.new(
|
110
|
+
%Q<Invalid #{name} ("#{value}")#{standard_exception_suffix(options)}>,
|
111
|
+
@original_string
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
def throw_presence_exception(name, presence_requirement_symbol, options)
|
116
|
+
presence = options[presence_requirement_symbol]
|
117
|
+
raise Fig::PackageDescriptorParseError.new(
|
118
|
+
"Package #{name} #{presence}#{standard_exception_suffix(options)}",
|
119
|
+
@original_string
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
def validate_across_components(options)
|
124
|
+
if ! @version.nil? && @name.nil?
|
125
|
+
raise Fig::PackageDescriptorParseError.new(
|
126
|
+
"Cannot specify a version without a name#{standard_exception_suffix(options)}",
|
127
|
+
@original_string
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
return if not options[:require_at_least_one_component]
|
132
|
+
if @name.nil? && @version.nil? && @config.nil?
|
133
|
+
raise Fig::PackageDescriptorParseError.new(
|
134
|
+
"Must specify at least one of name, version, and config#{standard_exception_suffix(options)}",
|
135
|
+
@original_string
|
136
|
+
)
|
137
|
+
end
|
138
|
+
|
139
|
+
return
|
140
|
+
end
|
141
|
+
|
142
|
+
def standard_exception_suffix(options)
|
143
|
+
original_string = @original_string.nil? ? '' : %Q< ("#{@original_string}")>
|
144
|
+
context = options[:validation_context] || ''
|
145
|
+
source_description = options[:source_description] || ''
|
146
|
+
|
147
|
+
return " in package descriptor#{original_string}#{context}#{source_description}."
|
148
|
+
end
|
67
149
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'fig/userinputerror'
|
2
|
+
|
3
|
+
module Fig
|
4
|
+
# Could not turn a string into a PackageDescriptor.
|
5
|
+
class PackageDescriptorParseError < UserInputError
|
6
|
+
attr_accessor :original_string
|
7
|
+
|
8
|
+
def initialize(message, original_string)
|
9
|
+
super(message)
|
10
|
+
|
11
|
+
@file = original_string
|
12
|
+
|
13
|
+
return
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/fig/parser.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require 'polyglot'
|
2
1
|
require 'treetop'
|
3
2
|
|
4
|
-
require 'fig/grammar'
|
3
|
+
require 'fig/grammar' # this is grammar.treetop, not grammar.rb.
|
5
4
|
require 'fig/logging'
|
6
5
|
require 'fig/packageparseerror'
|
6
|
+
require 'fig/parserpackagebuildstate'
|
7
7
|
require 'fig/repository'
|
8
|
+
require 'fig/statement'
|
8
9
|
require 'fig/urlaccesserror'
|
9
10
|
require 'fig/userinputerror'
|
10
11
|
|
@@ -13,36 +14,32 @@ module Fig; end
|
|
13
14
|
# Parses .fig files (wrapping the Treetop-generated parser object) and deals
|
14
15
|
# with a few restrictions on them.
|
15
16
|
class Fig::Parser
|
16
|
-
def self.node_location(node)
|
17
|
-
offset_from_start_of_file = node.interval.first
|
18
|
-
input = node.input
|
19
|
-
|
20
|
-
return [
|
21
|
-
input.line_of(offset_from_start_of_file),
|
22
|
-
input.column_of(offset_from_start_of_file)
|
23
|
-
]
|
24
|
-
end
|
25
|
-
|
26
17
|
def initialize(application_config, check_include_versions)
|
27
|
-
|
18
|
+
# Fig::FigParser class is synthesized by Treetop.
|
19
|
+
@treetop_parser = Fig::FigParser.new
|
28
20
|
@application_config = application_config
|
29
21
|
@check_include_versions = check_include_versions
|
30
22
|
end
|
31
23
|
|
32
|
-
def parse_package(descriptor, directory, input)
|
24
|
+
def parse_package(descriptor, directory, source_description, input)
|
33
25
|
# Bye bye comments.
|
34
26
|
input = input.gsub(/#.*$/, '')
|
35
27
|
|
36
28
|
# Extra space at the end because most of the rules in the grammar require
|
37
29
|
# trailing whitespace.
|
38
|
-
result = @
|
30
|
+
result = @treetop_parser.parse(input + ' ')
|
31
|
+
|
32
|
+
extended_description =
|
33
|
+
extend_source_description(directory, source_description)
|
39
34
|
|
40
35
|
if result.nil?
|
41
|
-
|
42
|
-
raise Fig::PackageParseError.new("#{directory}: #{@parser.failure_reason}")
|
36
|
+
raise_parse_error(extended_description)
|
43
37
|
end
|
44
38
|
|
45
|
-
package = result.to_package(
|
39
|
+
package = result.to_package(
|
40
|
+
directory,
|
41
|
+
Fig::ParserPackageBuildState.new(descriptor, extended_description)
|
42
|
+
)
|
46
43
|
|
47
44
|
check_for_bad_urls(package, descriptor)
|
48
45
|
check_for_multiple_command_statements(package)
|
@@ -53,6 +50,26 @@ class Fig::Parser
|
|
53
50
|
|
54
51
|
private
|
55
52
|
|
53
|
+
def extend_source_description(directory, original_description)
|
54
|
+
if original_description
|
55
|
+
extended = original_description
|
56
|
+
if directory != '.'
|
57
|
+
extended << " (#{directory})"
|
58
|
+
end
|
59
|
+
|
60
|
+
return extended
|
61
|
+
end
|
62
|
+
|
63
|
+
return directory
|
64
|
+
end
|
65
|
+
|
66
|
+
def raise_parse_error(extended_description)
|
67
|
+
message = extended_description
|
68
|
+
message << ": #{@treetop_parser.failure_reason}"
|
69
|
+
|
70
|
+
raise Fig::PackageParseError.new(message)
|
71
|
+
end
|
72
|
+
|
56
73
|
def check_for_bad_urls(package, descriptor)
|
57
74
|
bad_urls = []
|
58
75
|
package.walk_statements do |statement|
|
@@ -73,7 +90,7 @@ class Fig::Parser
|
|
73
90
|
package.walk_statements do |statement|
|
74
91
|
if statement.is_a?(Fig::Statement::Command)
|
75
92
|
if command_processed == true
|
76
|
-
raise Fig::
|
93
|
+
raise Fig::PackageParseError.new(
|
77
94
|
%Q<Found a second "command" statement within a "config" block#{statement.position_string()}.>
|
78
95
|
)
|
79
96
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'fig/packageparseerror'
|
2
|
+
require 'fig/statement'
|
3
|
+
|
4
|
+
module Fig; end
|
5
|
+
|
6
|
+
class Fig::ParserPackageBuildState
|
7
|
+
attr_reader :descriptor
|
8
|
+
attr_reader :source_description
|
9
|
+
|
10
|
+
def initialize(descriptor, source_description)
|
11
|
+
@descriptor = descriptor
|
12
|
+
@source_description = source_description
|
13
|
+
end
|
14
|
+
|
15
|
+
def node_location(node)
|
16
|
+
offset_from_start_of_file = node.interval.first
|
17
|
+
input = node.input
|
18
|
+
|
19
|
+
return [
|
20
|
+
input.line_of(offset_from_start_of_file),
|
21
|
+
input.column_of(offset_from_start_of_file)
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
# This method is necessary due to ruby v1.8 not allowing array splat
|
26
|
+
# notation, i.e. Fig::Statement.position_description(*node_location(node),
|
27
|
+
# source_description)
|
28
|
+
def node_location_description(node)
|
29
|
+
location = node_location(node)
|
30
|
+
|
31
|
+
return Fig::Statement.position_description(
|
32
|
+
location[0], location[1], source_description
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def new_environment_variable_statement(
|
37
|
+
statement_class, keyword_node, value_node
|
38
|
+
)
|
39
|
+
name, value = statement_class.parse_name_value(value_node.text_value) {
|
40
|
+
raise_invalid_value_parse_error(
|
41
|
+
keyword_node,
|
42
|
+
value_node,
|
43
|
+
statement_class.const_get(:ARGUMENT_DESCRIPTION)
|
44
|
+
)
|
45
|
+
}
|
46
|
+
return statement_class.new(
|
47
|
+
node_location(keyword_node), source_description, name, value
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
def raise_invalid_value_parse_error(keyword_node, value_node, description)
|
52
|
+
raise Fig::PackageParseError.new(
|
53
|
+
%Q<Invalid value for #{keyword_node.text_value} statement: "#{value_node.text_value}" #{description}#{node_location_description(value_node)}>
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
data/lib/fig/repository.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
require 'set'
|
1
2
|
require 'socket'
|
2
3
|
require 'sys/admin'
|
4
|
+
require 'tmpdir'
|
3
5
|
|
6
|
+
require 'fig/atexit'
|
7
|
+
require 'fig/command'
|
4
8
|
require 'fig/logging'
|
5
9
|
require 'fig/notfounderror'
|
6
10
|
require 'fig/packagecache'
|
@@ -11,353 +15,594 @@ require 'fig/statement/archive'
|
|
11
15
|
require 'fig/statement/resource'
|
12
16
|
require 'fig/urlaccesserror'
|
13
17
|
|
14
|
-
module Fig
|
15
|
-
# Overall management of a repository. Handles local operations itself;
|
16
|
-
# defers remote operations to others.
|
17
|
-
class Repository
|
18
|
-
METADATA_SUBDIRECTORY = '_meta'
|
18
|
+
module Fig; end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
# Overall management of a repository. Handles local operations itself;
|
21
|
+
# defers remote operations to others.
|
22
|
+
class Fig::Repository
|
23
|
+
METADATA_SUBDIRECTORY = '_meta'
|
24
|
+
RESOURCES_FILE = 'resources.tar.gz'
|
25
|
+
VERSION_FILE_NAME = 'repository-format-version'
|
26
|
+
VERSION_SUPPORTED = 1
|
23
27
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
remote_repository_url,
|
28
|
-
application_config,
|
29
|
-
remote_repository_user,
|
30
|
-
update,
|
31
|
-
update_if_missing,
|
32
|
-
check_include_versions
|
33
|
-
)
|
34
|
-
@operating_system = os
|
35
|
-
@local_repository_dir = local_repository_dir
|
36
|
-
@remote_repository_url = remote_repository_url
|
37
|
-
@remote_repository_user = remote_repository_user
|
38
|
-
@update = update
|
39
|
-
@update_if_missing = update_if_missing
|
28
|
+
def self.is_url?(url)
|
29
|
+
not (/ftp:\/\/|http:\/\/|file:\/\/|ssh:\/\// =~ url).nil?
|
30
|
+
end
|
40
31
|
|
41
|
-
|
32
|
+
def initialize(
|
33
|
+
os,
|
34
|
+
local_repository_directory,
|
35
|
+
application_config,
|
36
|
+
remote_repository_user,
|
37
|
+
update,
|
38
|
+
update_if_missing,
|
39
|
+
check_include_versions
|
40
|
+
)
|
41
|
+
@operating_system = os
|
42
|
+
@local_repository_directory = local_repository_directory
|
43
|
+
@application_config = application_config
|
44
|
+
@remote_repository_user = remote_repository_user
|
45
|
+
@update = update
|
46
|
+
@update_if_missing = update_if_missing
|
47
|
+
|
48
|
+
@parser = Fig::Parser.new(application_config, check_include_versions)
|
49
|
+
|
50
|
+
initialize_local_repository()
|
51
|
+
reset_cached_data()
|
52
|
+
end
|
42
53
|
|
43
|
-
|
44
|
-
|
54
|
+
def reset_cached_data()
|
55
|
+
@package_cache = Fig::PackageCache.new()
|
56
|
+
end
|
45
57
|
|
46
|
-
|
47
|
-
|
48
|
-
end
|
58
|
+
def list_packages
|
59
|
+
check_local_repository_format()
|
49
60
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
@operating_system.list(
|
54
|
-
|
55
|
-
|
56
|
-
end
|
61
|
+
results = []
|
62
|
+
if File.exist?(local_package_directory())
|
63
|
+
@operating_system.list(local_package_directory()).each do |name|
|
64
|
+
@operating_system.list(File.join(local_package_directory(), name)).each do
|
65
|
+
|version|
|
66
|
+
results << Fig::PackageDescriptor.format(name, version, nil)
|
57
67
|
end
|
58
68
|
end
|
59
|
-
|
60
|
-
return results
|
61
69
|
end
|
62
70
|
|
63
|
-
|
64
|
-
|
71
|
+
return results
|
72
|
+
end
|
65
73
|
|
66
|
-
|
67
|
-
|
74
|
+
def list_remote_packages
|
75
|
+
check_remote_repository_format()
|
68
76
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
if not descriptor.version
|
74
|
-
if allow_any_version
|
75
|
-
package = @packages.get_any_version_of_package(descriptor.name)
|
76
|
-
if package
|
77
|
-
Logging.warn(
|
78
|
-
"Picked version #{package.version} of #{package.name} at random."
|
79
|
-
)
|
80
|
-
return package
|
81
|
-
end
|
82
|
-
end
|
77
|
+
paths = @operating_system.download_list(remote_repository_url())
|
78
|
+
|
79
|
+
return paths.reject { |path| path =~ %r< ^ #{METADATA_SUBDIRECTORY} / >xs }
|
80
|
+
end
|
83
81
|
|
84
|
-
|
85
|
-
|
86
|
-
|
82
|
+
def get_package(
|
83
|
+
descriptor,
|
84
|
+
allow_any_version = false
|
85
|
+
)
|
86
|
+
check_local_repository_format()
|
87
|
+
|
88
|
+
if not descriptor.version
|
89
|
+
if allow_any_version
|
90
|
+
package = @package_cache.get_any_version_of_package(descriptor.name)
|
91
|
+
if package
|
92
|
+
Fig::Logging.warn(
|
93
|
+
"Picked version #{package.version} of #{package.name} at random."
|
94
|
+
)
|
95
|
+
return package
|
96
|
+
end
|
87
97
|
end
|
88
98
|
|
89
|
-
|
90
|
-
|
99
|
+
raise Fig::RepositoryError.new(
|
100
|
+
%Q<Cannot retrieve "#{descriptor.name}" without a version.>
|
101
|
+
)
|
102
|
+
end
|
91
103
|
|
92
|
-
|
93
|
-
|
104
|
+
package = @package_cache.get_package(descriptor.name, descriptor.version)
|
105
|
+
return package if package
|
94
106
|
|
95
|
-
|
96
|
-
|
97
|
-
|
107
|
+
Fig::Logging.debug \
|
108
|
+
"Considering #{Fig::PackageDescriptor.format(descriptor.name, descriptor.version, nil)}."
|
109
|
+
|
110
|
+
if should_update?(descriptor)
|
111
|
+
check_remote_repository_format()
|
98
112
|
|
99
|
-
|
113
|
+
update_package(descriptor)
|
100
114
|
end
|
101
115
|
|
102
|
-
|
103
|
-
|
116
|
+
return read_local_package(descriptor)
|
117
|
+
end
|
118
|
+
|
119
|
+
def clean(descriptor)
|
120
|
+
check_local_repository_format()
|
104
121
|
|
105
|
-
|
106
|
-
dir = File.join(dir, descriptor.version) if descriptor.version
|
122
|
+
@package_cache.remove_package(descriptor.name, descriptor.version)
|
107
123
|
|
108
|
-
|
124
|
+
FileUtils.rm_rf(local_dir_for_package(descriptor))
|
109
125
|
|
110
|
-
|
126
|
+
return
|
127
|
+
end
|
128
|
+
|
129
|
+
def publish_package(package_statements, descriptor, local_only)
|
130
|
+
check_local_repository_format()
|
131
|
+
if not local_only
|
132
|
+
check_remote_repository_format()
|
111
133
|
end
|
112
134
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
135
|
+
validate_asset_names(package_statements)
|
136
|
+
|
137
|
+
temp_dir = publish_temp_dir()
|
138
|
+
@operating_system.delete_and_recreate_directory(temp_dir)
|
139
|
+
local_dir = local_dir_for_package(descriptor)
|
140
|
+
@operating_system.delete_and_recreate_directory(local_dir)
|
141
|
+
fig_file = File.join(temp_dir, PACKAGE_FILE_IN_REPO)
|
142
|
+
content = publish_package_content_and_derive_dot_fig_contents(
|
143
|
+
package_statements, descriptor, local_dir, local_only
|
144
|
+
)
|
145
|
+
@operating_system.write(fig_file, content)
|
146
|
+
|
147
|
+
if not local_only
|
123
148
|
@operating_system.upload(
|
124
149
|
fig_file,
|
125
150
|
remote_fig_file_for_package(descriptor),
|
126
151
|
@remote_repository_user
|
127
|
-
) unless local_only
|
128
|
-
@operating_system.copy(
|
129
|
-
fig_file, local_fig_file_for_package(descriptor)
|
130
152
|
)
|
153
|
+
end
|
154
|
+
@operating_system.copy(
|
155
|
+
fig_file, local_fig_file_for_package(descriptor)
|
156
|
+
)
|
131
157
|
|
132
|
-
|
158
|
+
FileUtils.rm_rf(temp_dir)
|
159
|
+
|
160
|
+
return true
|
161
|
+
end
|
162
|
+
|
163
|
+
def updating?
|
164
|
+
return @update || @update_if_missing
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
PACKAGE_FILE_IN_REPO = '.fig'
|
170
|
+
|
171
|
+
def initialize_local_repository()
|
172
|
+
if not File.exist?(@local_repository_directory)
|
173
|
+
Dir.mkdir(@local_repository_directory)
|
133
174
|
end
|
134
175
|
|
135
|
-
|
136
|
-
|
176
|
+
version_file = local_version_file()
|
177
|
+
if not File.exist?(version_file)
|
178
|
+
File.open(version_file, 'w') { |handle| handle.write(VERSION_SUPPORTED) }
|
137
179
|
end
|
138
180
|
|
139
|
-
|
181
|
+
return
|
182
|
+
end
|
140
183
|
|
141
|
-
|
142
|
-
|
184
|
+
def check_local_repository_format()
|
185
|
+
check_repository_format('Local', local_repository_version())
|
143
186
|
|
144
|
-
|
145
|
-
|
187
|
+
return
|
188
|
+
end
|
189
|
+
|
190
|
+
def check_remote_repository_format()
|
191
|
+
check_repository_format('Remote', remote_repository_version())
|
192
|
+
|
193
|
+
return
|
194
|
+
end
|
146
195
|
|
147
|
-
|
148
|
-
|
149
|
-
|
196
|
+
def check_repository_format(name, version)
|
197
|
+
if version != VERSION_SUPPORTED
|
198
|
+
Fig::Logging.fatal \
|
199
|
+
"#{name} repository is in version #{version} format. This version of fig can only deal with repositories in version #{VERSION_SUPPORTED} format."
|
200
|
+
raise Fig::RepositoryError.new
|
150
201
|
end
|
151
202
|
|
152
|
-
|
153
|
-
|
154
|
-
new_package_statements = package_statements.reject do |statement|
|
155
|
-
if (
|
156
|
-
statement.is_a?(Statement::Resource) &&
|
157
|
-
! Repository.is_url?(statement.url)
|
158
|
-
)
|
159
|
-
resources << statement.url
|
160
|
-
true
|
161
|
-
else
|
162
|
-
false
|
163
|
-
end
|
164
|
-
end
|
203
|
+
return
|
204
|
+
end
|
165
205
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
@operating_system.create_archive(file, resources)
|
170
|
-
new_package_statements.unshift(Statement::Archive.new(nil, file))
|
171
|
-
at_exit { File.delete(file) }
|
172
|
-
end
|
206
|
+
def local_repository_version()
|
207
|
+
if @local_repository_version.nil?
|
208
|
+
version_file = local_version_file()
|
173
209
|
|
174
|
-
|
210
|
+
@local_repository_version =
|
211
|
+
parse_repository_version(version_file, version_file)
|
175
212
|
end
|
176
213
|
|
177
|
-
|
178
|
-
|
214
|
+
return @local_repository_version
|
215
|
+
end
|
216
|
+
|
217
|
+
def local_version_file()
|
218
|
+
return File.join(@local_repository_directory, VERSION_FILE_NAME)
|
219
|
+
end
|
179
220
|
|
221
|
+
def local_package_directory()
|
222
|
+
return File.expand_path(File.join(@local_repository_directory, 'repos'))
|
223
|
+
end
|
224
|
+
|
225
|
+
def remote_repository_version()
|
226
|
+
if @remote_repository_version.nil?
|
227
|
+
temp_dir = base_temp_dir()
|
228
|
+
@operating_system.delete_and_recreate_directory(temp_dir)
|
229
|
+
remote_version_file = "#{remote_repository_url()}/#{VERSION_FILE_NAME}"
|
230
|
+
local_version_file = File.join(temp_dir, "remote-#{VERSION_FILE_NAME}")
|
180
231
|
begin
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
archive_url = remote_dir_for_package(descriptor) + '/' + archive_url
|
187
|
-
end
|
188
|
-
@operating_system.download_archive(archive_url, File.join(temp_dir))
|
189
|
-
end
|
190
|
-
package.resource_urls.each do |resource_url|
|
191
|
-
if not Repository.is_url?(resource_url)
|
192
|
-
resource_url =
|
193
|
-
remote_dir_for_package(descriptor) + '/' + resource_url
|
194
|
-
end
|
195
|
-
@operating_system.download_resource(resource_url, File.join(temp_dir))
|
196
|
-
end
|
197
|
-
local_dir = local_dir_for_package(descriptor)
|
198
|
-
@operating_system.clear_directory(local_dir)
|
199
|
-
# some packages contain no files, only a fig file.
|
200
|
-
if not (package.archive_urls.empty? && package.resource_urls.empty?)
|
201
|
-
FileUtils.mv(Dir.glob(File.join(temp_dir, '*')), local_dir)
|
202
|
-
end
|
203
|
-
write_local_package(descriptor, package)
|
204
|
-
rescue
|
205
|
-
Logging.fatal 'Install failed, cleaning up.'
|
206
|
-
delete_local_package(descriptor)
|
207
|
-
raise RepositoryError.new
|
208
|
-
ensure
|
209
|
-
if temp_dir
|
210
|
-
FileUtils.rm_rf(temp_dir)
|
232
|
+
@operating_system.download(remote_version_file, local_version_file)
|
233
|
+
rescue Fig::NotFoundError
|
234
|
+
# The download may create an empty file, so get rid of it.
|
235
|
+
if File.exist?(local_version_file)
|
236
|
+
File.unlink(local_version_file)
|
211
237
|
end
|
212
238
|
end
|
239
|
+
|
240
|
+
@remote_repository_version =
|
241
|
+
parse_repository_version(local_version_file, remote_version_file)
|
213
242
|
end
|
214
243
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
end
|
222
|
-
rescue NotFoundError
|
223
|
-
Logging.fatal "Package not found in remote repository: #{descriptor.to_string()}"
|
224
|
-
delete_local_package(descriptor)
|
225
|
-
raise RepositoryError.new
|
226
|
-
end
|
244
|
+
return @remote_repository_version
|
245
|
+
end
|
246
|
+
|
247
|
+
def parse_repository_version(version_file, description)
|
248
|
+
if not File.exist?(version_file)
|
249
|
+
return 1 # Since there was no version file early in Fig development.
|
227
250
|
end
|
228
251
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
252
|
+
version_string = IO.read(version_file)
|
253
|
+
version_string.strip!()
|
254
|
+
if version_string !~ / \A \d+ \z /x
|
255
|
+
Fig::Logging.fatal \
|
256
|
+
%Q<Could not parse the contents of "#{description}" ("#{version_string}") as a version.>
|
257
|
+
raise Fig::RepositoryError.new
|
235
258
|
end
|
236
259
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
260
|
+
return version_string.to_i()
|
261
|
+
end
|
262
|
+
|
263
|
+
def validate_asset_names(package_statements)
|
264
|
+
asset_statements = package_statements.select { |s| s.is_asset? }
|
265
|
+
|
266
|
+
asset_names = Set.new()
|
267
|
+
asset_statements.each do
|
268
|
+
|statement|
|
269
|
+
|
270
|
+
asset_name = statement.asset_name()
|
271
|
+
if not asset_name.nil?
|
272
|
+
if asset_name == RESOURCES_FILE
|
273
|
+
Fig::Logging.fatal \
|
274
|
+
%Q<You cannot have an asset with the name "#{RESOURCES_FILE}"#{statement.position_string()} due to Fig implementation details.>
|
247
275
|
end
|
248
276
|
|
249
|
-
|
277
|
+
if asset_names.include?(asset_name)
|
278
|
+
Fig::Logging.fatal \
|
279
|
+
%Q<Found multiple archives with the name "#{asset_name}"#{statement.position_string()}. If these were allowed, archives would overwrite each other.>
|
280
|
+
raise Fig::RepositoryError.new
|
281
|
+
else
|
282
|
+
asset_names.add(asset_name)
|
283
|
+
end
|
250
284
|
end
|
251
|
-
|
252
|
-
return read_package_from_file(file, descriptor)
|
253
285
|
end
|
286
|
+
end
|
254
287
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
raise RepositoryError.new
|
259
|
-
end
|
260
|
-
content = File.read(file_name)
|
288
|
+
def remote_repository_url()
|
289
|
+
return @application_config.remote_repository_url()
|
290
|
+
end
|
261
291
|
|
262
|
-
|
263
|
-
|
264
|
-
)
|
292
|
+
def should_update?(descriptor)
|
293
|
+
return true if @update
|
265
294
|
|
266
|
-
|
295
|
+
return @update_if_missing && package_missing?(descriptor)
|
296
|
+
end
|
267
297
|
|
268
|
-
|
269
|
-
|
298
|
+
def read_local_package(descriptor)
|
299
|
+
directory = local_dir_for_package(descriptor)
|
300
|
+
return read_package_from_directory(directory, descriptor)
|
301
|
+
end
|
270
302
|
|
271
|
-
|
272
|
-
|
273
|
-
|
303
|
+
def update_package(descriptor)
|
304
|
+
temp_dir = package_download_temp_dir(descriptor)
|
305
|
+
begin
|
306
|
+
install_package(descriptor, temp_dir)
|
307
|
+
rescue Fig::NotFoundError
|
308
|
+
Fig::Logging.fatal \
|
309
|
+
"Package not found in remote repository: #{descriptor.to_string()}"
|
274
310
|
|
275
|
-
|
276
|
-
file = local_fig_file_for_package(descriptor)
|
277
|
-
@operating_system.write(file, package.unparse)
|
278
|
-
end
|
311
|
+
delete_local_package(descriptor)
|
279
312
|
|
280
|
-
|
281
|
-
|
282
|
-
|
313
|
+
raise Fig::RepositoryError.new
|
314
|
+
rescue StandardError => exception
|
315
|
+
Fig::Logging.debug exception
|
316
|
+
Fig::Logging.fatal 'Install failed, cleaning up.'
|
283
317
|
|
284
|
-
|
285
|
-
|
318
|
+
delete_local_package(descriptor)
|
319
|
+
|
320
|
+
raise Fig::RepositoryError.new
|
321
|
+
ensure
|
322
|
+
FileUtils.rm_rf(temp_dir)
|
286
323
|
end
|
287
324
|
|
288
|
-
|
289
|
-
|
325
|
+
return
|
326
|
+
end
|
327
|
+
|
328
|
+
def install_package(descriptor, temp_dir)
|
329
|
+
@operating_system.delete_and_recreate_directory(temp_dir)
|
330
|
+
|
331
|
+
remote_fig_file = remote_fig_file_for_package(descriptor)
|
332
|
+
local_fig_file = fig_file_for_package_download(temp_dir)
|
333
|
+
|
334
|
+
return if not @operating_system.download(remote_fig_file, local_fig_file)
|
335
|
+
|
336
|
+
package = read_package_from_directory(temp_dir, descriptor)
|
337
|
+
|
338
|
+
package.archive_urls.each do |archive_url|
|
339
|
+
if not Fig::Repository.is_url?(archive_url)
|
340
|
+
archive_url = remote_dir_for_package(descriptor) + '/' + archive_url
|
341
|
+
end
|
342
|
+
@operating_system.download_and_unpack_archive(archive_url, temp_dir)
|
343
|
+
end
|
344
|
+
package.resource_urls.each do |resource_url|
|
345
|
+
if not Fig::Repository.is_url?(resource_url)
|
346
|
+
resource_url =
|
347
|
+
remote_dir_for_package(descriptor) + '/' + resource_url
|
348
|
+
end
|
349
|
+
@operating_system.download_resource(resource_url, temp_dir)
|
290
350
|
end
|
291
351
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
352
|
+
local_dir = local_dir_for_package(descriptor)
|
353
|
+
FileUtils.rm_rf(local_dir)
|
354
|
+
FileUtils.mkdir_p( File.dirname(local_dir) )
|
355
|
+
FileUtils.mv(temp_dir, local_dir)
|
356
|
+
|
357
|
+
return
|
358
|
+
end
|
359
|
+
|
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
|
296
374
|
end
|
297
375
|
|
298
|
-
|
299
|
-
|
376
|
+
return expanded_files
|
377
|
+
end
|
378
|
+
|
379
|
+
def read_package_from_directory(directory, descriptor)
|
380
|
+
dot_fig_file = File.join(directory, PACKAGE_FILE_IN_REPO)
|
381
|
+
if not File.exist?(dot_fig_file)
|
382
|
+
Fig::Logging.fatal %Q<Fig file not found for package "#{descriptor.name || '<unnamed>'}". There is nothing in "#{dot_fig_file}".>
|
383
|
+
raise Fig::RepositoryError.new
|
300
384
|
end
|
301
385
|
|
302
|
-
|
303
|
-
|
386
|
+
return read_package_from_file(dot_fig_file, descriptor)
|
387
|
+
end
|
388
|
+
|
389
|
+
def read_package_from_file(file_name, descriptor)
|
390
|
+
if not File.exist?(file_name)
|
391
|
+
Fig::Logging.fatal "Package not found: #{descriptor.to_string()}"
|
392
|
+
raise Fig::RepositoryError.new
|
304
393
|
end
|
394
|
+
content = File.read(file_name)
|
395
|
+
|
396
|
+
package = @parser.parse_package(
|
397
|
+
descriptor, File.dirname(file_name), descriptor.to_string(), content
|
398
|
+
)
|
399
|
+
|
400
|
+
@package_cache.add_package(package)
|
401
|
+
|
402
|
+
return package
|
403
|
+
end
|
404
|
+
|
405
|
+
def delete_local_package(descriptor)
|
406
|
+
FileUtils.rm_rf(local_dir_for_package(descriptor))
|
407
|
+
end
|
408
|
+
|
409
|
+
def remote_fig_file_for_package(descriptor)
|
410
|
+
"#{remote_dir_for_package(descriptor)}/#{PACKAGE_FILE_IN_REPO}"
|
411
|
+
end
|
412
|
+
|
413
|
+
def local_fig_file_for_package(descriptor)
|
414
|
+
File.join(local_dir_for_package(descriptor), PACKAGE_FILE_IN_REPO)
|
415
|
+
end
|
416
|
+
|
417
|
+
def fig_file_for_package_download(package_download_dir)
|
418
|
+
File.join(package_download_dir, PACKAGE_FILE_IN_REPO)
|
419
|
+
end
|
420
|
+
|
421
|
+
def remote_dir_for_package(descriptor)
|
422
|
+
"#{remote_repository_url()}/#{descriptor.name}/#{descriptor.version}"
|
423
|
+
end
|
424
|
+
|
425
|
+
def local_dir_for_package(descriptor)
|
426
|
+
return File.join(
|
427
|
+
local_package_directory(), descriptor.name, descriptor.version
|
428
|
+
)
|
429
|
+
end
|
430
|
+
|
431
|
+
def base_temp_dir()
|
432
|
+
File.join(@local_repository_directory, 'tmp')
|
433
|
+
end
|
434
|
+
|
435
|
+
def publish_temp_dir()
|
436
|
+
File.join(base_temp_dir(), 'publish')
|
437
|
+
end
|
438
|
+
|
439
|
+
def package_download_temp_dir(descriptor)
|
440
|
+
base_directory = File.join(base_temp_dir(), 'package-download')
|
441
|
+
FileUtils.mkdir_p(base_directory)
|
442
|
+
|
443
|
+
return Dir.mktmpdir(
|
444
|
+
"#{descriptor.name}.version.#{descriptor.version}+", base_directory
|
445
|
+
)
|
446
|
+
end
|
447
|
+
|
448
|
+
def package_missing?(descriptor)
|
449
|
+
not File.exist?(local_fig_file_for_package(descriptor))
|
450
|
+
end
|
305
451
|
|
306
|
-
|
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(
|
307
459
|
package_statements, descriptor, local_dir, local_only
|
308
460
|
)
|
309
|
-
header_strings = derive_package_metadata_comments(descriptor)
|
310
|
-
resource_statement_strings = derive_package_resources(
|
311
|
-
package_statements, descriptor, local_dir, local_only
|
312
|
-
)
|
313
461
|
|
314
|
-
|
315
|
-
|
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()
|
316
468
|
|
317
|
-
|
318
|
-
|
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
|
319
474
|
|
320
|
-
|
321
|
-
|
475
|
+
if asset_strings.empty?
|
476
|
+
asset_summary = [
|
322
477
|
%q<#>,
|
323
|
-
%
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
%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
|
328
486
|
]
|
329
487
|
end
|
330
488
|
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
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::Command.get_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
|
355
525
|
end
|
356
|
-
statement.class.new(nil, archive_name).unparse('')
|
357
526
|
else
|
358
|
-
statement.
|
527
|
+
asset_local = statement.url
|
528
|
+
check_asset_path(asset_local)
|
359
529
|
end
|
360
|
-
|
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
|
361
546
|
end
|
362
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
|
363
608
|
end
|