fig18 0.1.45-i386-mswin32
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 +55 -0
- data/LICENSE +27 -0
- data/README.md +283 -0
- data/VERSION +1 -0
- data/bin/fig +12 -0
- data/bin/fig-download +20 -0
- data/lib/fig/applicationconfiguration.rb +52 -0
- data/lib/fig/backtrace.rb +50 -0
- data/lib/fig/configfileerror.rb +15 -0
- data/lib/fig/environment.rb +216 -0
- data/lib/fig/figrc.rb +105 -0
- data/lib/fig/grammar.treetop +197 -0
- data/lib/fig/log4rconfigerror.rb +14 -0
- data/lib/fig/logging.rb +131 -0
- data/lib/fig/networkerror.rb +7 -0
- data/lib/fig/notfounderror.rb +4 -0
- data/lib/fig/options.rb +248 -0
- data/lib/fig/os.rb +416 -0
- data/lib/fig/package/archive.rb +24 -0
- data/lib/fig/package/command.rb +20 -0
- data/lib/fig/package/configuration.rb +40 -0
- data/lib/fig/package/include.rb +30 -0
- data/lib/fig/package/install.rb +21 -0
- data/lib/fig/package/override.rb +21 -0
- data/lib/fig/package/path.rb +21 -0
- data/lib/fig/package/publish.rb +21 -0
- data/lib/fig/package/resource.rb +24 -0
- data/lib/fig/package/retrieve.rb +21 -0
- data/lib/fig/package/set.rb +21 -0
- data/lib/fig/package/statement.rb +12 -0
- data/lib/fig/package.rb +73 -0
- data/lib/fig/packageerror.rb +7 -0
- data/lib/fig/parser.rb +37 -0
- data/lib/fig/repository.rb +252 -0
- data/lib/fig/repositoryerror.rb +7 -0
- data/lib/fig/retriever.rb +116 -0
- data/lib/fig/urlaccesserror.rb +13 -0
- data/lib/fig/userinputerror.rb +4 -0
- data/lib/fig/windows.rb +46 -0
- data/lib/fig.rb +230 -0
- metadata +336 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
require 'fig/logging'
|
5
|
+
|
6
|
+
# This class copies files from the project directories in ~/.fighome to the
|
7
|
+
# user's working directory. It keeps track of which files have already been copied, and which
|
8
|
+
# package/versions they came from, and deletes files as necessary to ensure that
|
9
|
+
# we never have files from two different versions of the same package in the user's
|
10
|
+
# working directory.
|
11
|
+
class Retriever
|
12
|
+
def initialize(base_dir)
|
13
|
+
@base_dir = base_dir
|
14
|
+
@configs = {}
|
15
|
+
@fig_dir = File.join(@base_dir, '.fig')
|
16
|
+
|
17
|
+
file = File.join(@fig_dir, 'retrieve')
|
18
|
+
if File.exist?(file)
|
19
|
+
load(file)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def with_package_config(name, version)
|
24
|
+
if name and version
|
25
|
+
@config = @configs[name]
|
26
|
+
if @config && @config.version != version
|
27
|
+
@config.files.each do |relpath|
|
28
|
+
Fig::Logging.info "- [#{@config.name}/#{@config.version}] #{relpath}"
|
29
|
+
FileUtils.rm_f(File.join(@base_dir, relpath))
|
30
|
+
end
|
31
|
+
@config = nil
|
32
|
+
end
|
33
|
+
if not @config
|
34
|
+
@config = new_package_config(name, version)
|
35
|
+
@configs[name] = @config
|
36
|
+
end
|
37
|
+
else
|
38
|
+
@config = nil
|
39
|
+
end
|
40
|
+
yield
|
41
|
+
end
|
42
|
+
|
43
|
+
def retrieve(source, relpath)
|
44
|
+
copy(source, relpath)
|
45
|
+
end
|
46
|
+
|
47
|
+
def save
|
48
|
+
FileUtils.mkdir_p(@fig_dir)
|
49
|
+
File.open(File.join(@fig_dir, 'retrieve'), 'w') do |f|
|
50
|
+
@configs.each do |name,config|
|
51
|
+
config.files.each do |target|
|
52
|
+
f << target << '=' << config.name << '/' << config.version << "\n"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def load(file)
|
61
|
+
File.open(file).each_line do |line|
|
62
|
+
line = line.strip()
|
63
|
+
if line =~ /^(.+)=(.+)\/(.+)$/
|
64
|
+
target = $1
|
65
|
+
config_name = $2
|
66
|
+
config_version = $3
|
67
|
+
config = @configs[config_name]
|
68
|
+
if config
|
69
|
+
if config.version != config_version
|
70
|
+
raise 'version mismatch in .figretrieve'
|
71
|
+
end
|
72
|
+
else
|
73
|
+
config = new_package_config(config_name, config_version)
|
74
|
+
@configs[config_name] = config
|
75
|
+
end
|
76
|
+
config.files << target
|
77
|
+
else
|
78
|
+
raise "parse error in #{file}: #{line}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def new_package_config(name, version)
|
84
|
+
config = OpenStruct.new
|
85
|
+
config.name = name
|
86
|
+
config.version = version
|
87
|
+
config.files = Set.new()
|
88
|
+
return config
|
89
|
+
end
|
90
|
+
|
91
|
+
def copy(source, relpath)
|
92
|
+
target = File.join(@base_dir, relpath)
|
93
|
+
if File.directory?(source)
|
94
|
+
FileUtils.mkdir_p(target)
|
95
|
+
Dir.foreach(source) do |child|
|
96
|
+
if child != '.' and child != '..'
|
97
|
+
source_file = File.join(source, child)
|
98
|
+
target_file = File.join(relpath, child)
|
99
|
+
Fig::Logging.debug "Copying #{source_file} to #{target_file}."
|
100
|
+
copy(source_file, target_file)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
else
|
104
|
+
if !File.exist?(target) || File.mtime(source) > File.mtime(target)
|
105
|
+
if Fig::Logging.debug?
|
106
|
+
Fig::Logging.debug "Copying package [#{@config.name}/#{@config.version}] from #{source} to #{target}."
|
107
|
+
else
|
108
|
+
Fig::Logging.info "+ [#{@config.name}/#{@config.version}] #{relpath}"
|
109
|
+
end
|
110
|
+
FileUtils.mkdir_p(File.dirname(target))
|
111
|
+
FileUtils.cp(source, target, :preserve => true)
|
112
|
+
end
|
113
|
+
@config.files << relpath if @config
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/lib/fig/windows.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Keeping Windows-specific implementation details here.
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
# I don't know how to set environment variables so that a sub-shell will
|
7
|
+
# be able to use them. Therefore, I'm punting, and creating a batch script
|
8
|
+
# on the fly to run a user supplied command.
|
9
|
+
|
10
|
+
module Fig
|
11
|
+
class Windows
|
12
|
+
|
13
|
+
BATCH_SCRIPT_TEMPLATE = <<EOF
|
14
|
+
@echo off
|
15
|
+
% ENV.each do |k,v|
|
16
|
+
set <%= k %>=<%= v %>
|
17
|
+
% end
|
18
|
+
|
19
|
+
cmd /C <%= command %>
|
20
|
+
EOF
|
21
|
+
|
22
|
+
|
23
|
+
def self.with_generated_batch_script(cmd)
|
24
|
+
command = cmd.join(' ')
|
25
|
+
template = ERB.new(BATCH_SCRIPT_TEMPLATE, 0, '%')
|
26
|
+
output = template.result(binding)
|
27
|
+
begin
|
28
|
+
tf = File.new('C:/tmp/fig_command.bat', 'w')
|
29
|
+
FileUtils.chmod(0755, tf.path)
|
30
|
+
File.open(tf.path, 'w') do |fh|
|
31
|
+
fh.puts output
|
32
|
+
end
|
33
|
+
tf.close
|
34
|
+
yield tf.path
|
35
|
+
ensure
|
36
|
+
# tf.delete
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.shell_exec_windows(cmd)
|
41
|
+
with_generated_batch_script(cmd) do |f|
|
42
|
+
Kernel.exec(f)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/fig.rb
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'net/ftp'
|
3
|
+
require 'log4r'
|
4
|
+
|
5
|
+
require 'fig/environment'
|
6
|
+
require 'fig/figrc'
|
7
|
+
require 'fig/logging'
|
8
|
+
require 'fig/options'
|
9
|
+
require 'fig/os'
|
10
|
+
require 'fig/package'
|
11
|
+
require 'fig/package/configuration'
|
12
|
+
require 'fig/package/publish'
|
13
|
+
require 'fig/parser'
|
14
|
+
require 'fig/repository'
|
15
|
+
require 'fig/retriever'
|
16
|
+
require 'fig/userinputerror'
|
17
|
+
require 'fig/windows'
|
18
|
+
|
19
|
+
module Fig
|
20
|
+
DEFAULT_FIG_FILE = 'package.fig'
|
21
|
+
|
22
|
+
def parse_descriptor(descriptor)
|
23
|
+
# todo should use treetop for these:
|
24
|
+
package_name = descriptor =~ %r< ^ ( [^:/]+ ) >x ? $1 : nil
|
25
|
+
config_name = descriptor =~ %r< : ( [^:/]+ ) >x ? $1 : nil
|
26
|
+
version_name = descriptor =~ %r< / ( [^:/]+ ) >x ? $1 : nil
|
27
|
+
return package_name, config_name, version_name
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_fig(argv)
|
31
|
+
shell_command = nil
|
32
|
+
argv.each_with_index do |arg, i|
|
33
|
+
if arg == '--'
|
34
|
+
shell_command = argv[(i+1)..-1]
|
35
|
+
argv.slice!(i..-1)
|
36
|
+
break
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
options, argv, exit_value = parse_options(argv)
|
41
|
+
if not exit_value.nil?
|
42
|
+
return exit_value
|
43
|
+
end
|
44
|
+
|
45
|
+
Logging.initialize_pre_configuration(options[:log_level])
|
46
|
+
|
47
|
+
vars = {}
|
48
|
+
ENV.each {|key,value| vars[key]=value }
|
49
|
+
|
50
|
+
remote_url = nil
|
51
|
+
if options[:update] || options[:publish] || options[:update_if_missing] || options[:list_remote]
|
52
|
+
remote_url = ENV['FIG_REMOTE_URL']
|
53
|
+
if remote_url.nil?
|
54
|
+
$stderr.puts 'Please define the FIG_REMOTE_URL environment variable.'
|
55
|
+
return 1
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
configuration = FigRC.find(
|
60
|
+
options[:figrc],
|
61
|
+
remote_url,
|
62
|
+
options[:login],
|
63
|
+
options[:home],
|
64
|
+
options[:no_figrc]
|
65
|
+
)
|
66
|
+
|
67
|
+
Logging.initialize_post_configuration(options[:log_config] || configuration['log configuration'], options[:log_level])
|
68
|
+
|
69
|
+
remote_user = nil
|
70
|
+
|
71
|
+
os = OS.new(options[:login])
|
72
|
+
repos = Repository.new(
|
73
|
+
os,
|
74
|
+
File.expand_path(File.join(options[:home], 'repos')),
|
75
|
+
remote_url,
|
76
|
+
configuration,
|
77
|
+
remote_user,
|
78
|
+
options[:update],
|
79
|
+
options[:update_if_missing]
|
80
|
+
)
|
81
|
+
retriever = Retriever.new('.')
|
82
|
+
# Check to see if this is still happening with the new layers of abstraction.
|
83
|
+
at_exit { retriever.save }
|
84
|
+
env = Environment.new(os, repos, vars, retriever)
|
85
|
+
|
86
|
+
options[:modifiers].each do |modifier|
|
87
|
+
env.apply_config_statement(nil, modifier, nil)
|
88
|
+
end
|
89
|
+
|
90
|
+
input = nil
|
91
|
+
if options[:input] == :none
|
92
|
+
# ignore
|
93
|
+
elsif options[:input] == '-'
|
94
|
+
input = $stdin.read
|
95
|
+
elsif options[:input].nil?
|
96
|
+
input = os.read(DEFAULT_FIG_FILE) if os.exist?(DEFAULT_FIG_FILE)
|
97
|
+
else
|
98
|
+
if os.exist?(options[:input])
|
99
|
+
input = os.read(options[:input])
|
100
|
+
else
|
101
|
+
$stderr.puts %Q<File not found: "#{options[:input]}".>
|
102
|
+
return 1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
options[:cleans].each do |descriptor|
|
107
|
+
package_name, version_name = descriptor.split('/')
|
108
|
+
repos.clean(package_name, version_name)
|
109
|
+
end
|
110
|
+
if options[:list]
|
111
|
+
repos.list_packages.sort.each do |item|
|
112
|
+
puts item
|
113
|
+
end
|
114
|
+
return 0
|
115
|
+
end
|
116
|
+
|
117
|
+
if options[:list_remote]
|
118
|
+
repos.list_remote_packages.sort.each do |item|
|
119
|
+
puts item
|
120
|
+
end
|
121
|
+
return 0
|
122
|
+
end
|
123
|
+
|
124
|
+
if not options[:list_configs].empty?
|
125
|
+
options[:list_configs].each do |descriptor|
|
126
|
+
package_name, version_name = descriptor.split('/')
|
127
|
+
repos.read_local_package(package_name, version_name).configs.each do |config|
|
128
|
+
puts config.name
|
129
|
+
end
|
130
|
+
end
|
131
|
+
return 0
|
132
|
+
end
|
133
|
+
|
134
|
+
if input
|
135
|
+
package = Parser.new(configuration).parse_package(nil, nil, '.', input)
|
136
|
+
direct_retrieves=[]
|
137
|
+
if options[:retrieve]
|
138
|
+
package.retrieves.each do |var, path|
|
139
|
+
if var =~ /^@([^\/]+)(.*)/
|
140
|
+
direct_retrieves << [$1, $2, path]
|
141
|
+
else
|
142
|
+
env.add_retrieve(var, path)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
unless options[:publish] || options[:list] || options[:publish_local]
|
147
|
+
env.register_package(package)
|
148
|
+
env.apply_config(package, options[:config], nil)
|
149
|
+
direct_retrieves.each do |info|
|
150
|
+
env.direct_retrieve(info[0], info[1], info[2])
|
151
|
+
end
|
152
|
+
end
|
153
|
+
else
|
154
|
+
package = Package.new(nil, nil, '.', [])
|
155
|
+
end
|
156
|
+
|
157
|
+
if options[:publish] || options[:publish_local]
|
158
|
+
if !argv.empty?
|
159
|
+
$stderr.puts %Q<Unexpected arguments: #{argv.join(' ')}>
|
160
|
+
return 10
|
161
|
+
end
|
162
|
+
package_name, config_name, version_name = parse_descriptor(options[:publish] || options[:publish_local])
|
163
|
+
if package_name.nil? || version_name.nil?
|
164
|
+
$stderr.puts 'Please specify a package name and a version name.'
|
165
|
+
return 10
|
166
|
+
end
|
167
|
+
if not options[:modifiers].empty?
|
168
|
+
publish_statements = options[:resources] + options[:archives] + [Package::Configuration.new('default', options[:modifiers])]
|
169
|
+
publish_statements << Package::Publish.new('default','default')
|
170
|
+
elsif not package.statements.empty?
|
171
|
+
publish_statements = package.statements
|
172
|
+
else
|
173
|
+
$stderr.puts 'Nothing to publish.'
|
174
|
+
return 1
|
175
|
+
end
|
176
|
+
if options[:publish]
|
177
|
+
Logging.info "Checking status of #{package_name}/#{version_name}..."
|
178
|
+
if repos.list_remote_packages.include?("#{package_name}/#{version_name}")
|
179
|
+
Logging.info "#{package_name}/#{version_name} has already been published."
|
180
|
+
if not options[:force]
|
181
|
+
Logging.fatal 'Use the --force option if you really want to overwrite, or use --publish-local for testing.'
|
182
|
+
return 1
|
183
|
+
else
|
184
|
+
Logging.info 'Overwriting...'
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
Logging.info "Publishing #{package_name}/#{version_name}."
|
189
|
+
repos.publish_package(publish_statements, package_name, version_name, options[:publish_local])
|
190
|
+
elsif options[:echo]
|
191
|
+
puts env[options[:echo]]
|
192
|
+
elsif shell_command
|
193
|
+
argv.shift
|
194
|
+
env.execute_shell(shell_command) { |cmd| os.shell_exec cmd }
|
195
|
+
elsif argv[0]
|
196
|
+
package_name, config_name, version_name = parse_descriptor(argv.shift)
|
197
|
+
env.include_config(package, package_name, config_name, version_name, {}, nil)
|
198
|
+
env.execute_config(package, package_name, config_name, nil, argv) { |cmd| os.shell_exec cmd }
|
199
|
+
elsif input
|
200
|
+
env.execute_config(package, nil, options[:config], nil, argv) { |cmd| os.shell_exec cmd }
|
201
|
+
elsif !repos.updating?
|
202
|
+
$stderr.puts USAGE
|
203
|
+
$stderr.puts %q<Run "fig --help" for a full list of commands.>
|
204
|
+
end
|
205
|
+
|
206
|
+
return 0
|
207
|
+
end
|
208
|
+
|
209
|
+
def run_with_exception_handling(argv)
|
210
|
+
begin
|
211
|
+
return_code = run_fig(argv)
|
212
|
+
return return_code
|
213
|
+
rescue URLAccessError => exception
|
214
|
+
urls = exception.urls.join(', ')
|
215
|
+
$stderr.puts "Access to #{urls} in #{exception.package}/#{exception.version} not allowed."
|
216
|
+
return 1
|
217
|
+
rescue UserInputError => exception
|
218
|
+
# If there's no message, we assume that the cause has already been logged.
|
219
|
+
if not exception.message.nil?
|
220
|
+
$stderr.puts exception.to_s
|
221
|
+
end
|
222
|
+
|
223
|
+
return 1
|
224
|
+
rescue OptionParser::InvalidOption => exception
|
225
|
+
$stderr.puts exception.to_s
|
226
|
+
$stderr.puts USAGE
|
227
|
+
return 1
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|