fig18 0.1.38

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,241 @@
1
+ require 'fig/parser'
2
+
3
+ module Fig
4
+ class Repository
5
+ def initialize(os, local_repository_dir, remote_repository_url, remote_repository_user=nil, update=false, update_if_missing=true)
6
+ @os = os
7
+ @local_repository_dir = local_repository_dir
8
+ @remote_repository_url = remote_repository_url
9
+ @remote_repository_user = remote_repository_user
10
+ @update = update
11
+ @update_if_missing = update_if_missing
12
+ @parser = Parser.new
13
+
14
+ @overrides = {}
15
+ if File.exist?('fig.properties')
16
+ File.readlines('fig.properties').each do |line|
17
+ descriptor, path = line.strip.split('=')
18
+ @overrides[descriptor] = path
19
+ end
20
+ end
21
+ end
22
+
23
+ def clean(package_name, version_name)
24
+ dir = File.join(@local_repository_dir, package_name)
25
+ dir = File.join(dir, version_name) if version_name
26
+ FileUtils.rm_rf(dir)
27
+ end
28
+
29
+ def list_packages
30
+ results = []
31
+ if File.exist?(@local_repository_dir)
32
+ @os.list(@local_repository_dir).each do |package_name|
33
+ @os.list(File.join(@local_repository_dir, package_name)).each do |version_name|
34
+ results << "#{package_name}/#{version_name}"
35
+ end
36
+ end
37
+ end
38
+ results
39
+ end
40
+
41
+ def list_remote_packages
42
+ @os.download_list(@remote_repository_url)
43
+ end
44
+
45
+ def publish_package(package_statements, package_name, version_name, local_only)
46
+ temp_dir = temp_dir_for_package(package_name, version_name)
47
+ @os.clear_directory(temp_dir)
48
+ local_dir = local_dir_for_package(package_name, version_name)
49
+ @os.clear_directory(local_dir)
50
+ fig_file = File.join(temp_dir, ".fig")
51
+ content = bundle_resources(package_statements).map do |statement|
52
+ if statement.is_a?(Publish)
53
+ nil
54
+ elsif statement.is_a?(Archive) || statement.is_a?(Resource)
55
+ if statement.is_a?(Resource) && !is_url?(statement.url)
56
+ archive_name = statement.url
57
+ archive_remote = "#{remote_dir_for_package(package_name, version_name)}/#{statement.url}"
58
+ else
59
+ archive_name = statement.url.split("/").last
60
+ archive_remote = "#{remote_dir_for_package(package_name, version_name)}/#{archive_name}"
61
+ end
62
+ if is_url?(statement.url)
63
+ archive_local = File.join(temp_dir, archive_name)
64
+ @os.download(statement.url, archive_local)
65
+ else
66
+ archive_local = statement.url
67
+ end
68
+ @os.upload(archive_local, archive_remote, @remote_repository_user) unless local_only
69
+ @os.copy(archive_local, local_dir + "/" + archive_name)
70
+ if statement.is_a?(Archive)
71
+ @os.unpack_archive(local_dir, archive_name)
72
+ end
73
+ statement.class.new(archive_name).unparse('')
74
+ else
75
+ statement.unparse('')
76
+ end
77
+ end.select {|s|not s.nil?}
78
+ @os.write(fig_file, content.join("\n").strip)
79
+ @os.upload(fig_file, remote_fig_file_for_package(package_name, version_name), @remote_repository_user) unless local_only
80
+ @os.copy(fig_file, local_fig_file_for_package(package_name, version_name))
81
+ end
82
+
83
+ def bundle_resources(package_statements)
84
+ resources = []
85
+ new_package_statements = package_statements.reject do |statement|
86
+ if statement.is_a?(Resource) && !is_url?(statement.url)
87
+ resources << statement.url
88
+ true
89
+ else
90
+ false
91
+ end
92
+ end
93
+ if resources.size > 0
94
+ resources = expand_globs_from(resources)
95
+ file = "resources.tar.gz"
96
+ @os.create_archive(file, resources)
97
+ new_package_statements.unshift(Archive.new(file))
98
+ at_exit { File.delete(file) }
99
+ end
100
+ new_package_statements
101
+ end
102
+
103
+ def load_package(package_name, version_name)
104
+ if @update || (@update_if_missing && package_missing?(package_name, version_name))
105
+ update_package(package_name, version_name)
106
+ end
107
+ read_local_package(package_name, version_name)
108
+ end
109
+
110
+ def update_package(package_name, version_name)
111
+ remote_fig_file = remote_fig_file_for_package(package_name, version_name)
112
+ local_fig_file = local_fig_file_for_package(package_name, version_name)
113
+ begin
114
+ if @os.download(remote_fig_file, local_fig_file)
115
+ install_package(package_name, version_name)
116
+ end
117
+ rescue NotFoundException
118
+ $stderr.puts "Package not found in remote repository: #{package_name}/#{version_name}"
119
+ delete_local_package(package_name, version_name)
120
+ exit 1
121
+ end
122
+ end
123
+
124
+ def read_local_package(package_name, version_name)
125
+ dir = local_dir_for_package(package_name, version_name)
126
+ read_package_from_directory(dir, package_name, version_name)
127
+ end
128
+
129
+ def read_remote_package(package_name, version_name)
130
+ url = remote_fig_file_for_package(package_name, version_name)
131
+ content = @os.read_url(url)
132
+ @parser.parse_package(package_name, version_name, nil, content)
133
+ end
134
+
135
+ def read_package_from_directory(dir, package_name, version_name)
136
+ file = File.join(dir, ".fig")
137
+ if not File.exist?(file)
138
+ file = File.join(dir, "package.fig")
139
+ end
140
+ if not File.exist?(file)
141
+ $stderr.puts "Fig file not found for package: #{file}"
142
+ exit 10
143
+ end
144
+ read_package_from_file(file, package_name, version_name)
145
+ end
146
+
147
+ def read_package_from_file(file_name, package_name, version_name)
148
+ if not @os.exist?(file_name)
149
+ $stderr.puts "Package not found: #{package_name}/#{version_name}"
150
+ exit 1
151
+ end
152
+ modified_time = @os.mtime(file_name)
153
+ content = @os.read(file_name)
154
+ @parser.parse_package(package_name, version_name, File.dirname(file_name), content)
155
+ end
156
+
157
+ def local_dir_for_package(package_name, version_name)
158
+ descriptor = "#{package_name}/#{version_name}"
159
+ dir = @overrides[descriptor]
160
+ if dir
161
+ $stderr.puts "override: #{descriptor}=#{dir}"
162
+ else
163
+ dir = File.join(@local_repository_dir, package_name, version_name)
164
+ end
165
+ dir
166
+ end
167
+
168
+ private
169
+
170
+ def install_package(package_name, version_name)
171
+ begin
172
+ package = read_local_package(package_name, version_name)
173
+ temp_dir = temp_dir_for_package(package_name, version_name)
174
+ @os.clear_directory(temp_dir)
175
+ package.archive_urls.each do |archive_url|
176
+ if not is_url?(archive_url)
177
+ archive_url = remote_dir_for_package(package_name, version_name) + "/" + archive_url
178
+ end
179
+ @os.download_archive(archive_url, File.join(temp_dir))
180
+ end
181
+ package.resource_urls.each do |resource_url|
182
+ if not is_url?(resource_url)
183
+ resource_url = remote_dir_for_package(package_name, version_name) + "/" + resource_url
184
+ end
185
+ @os.download_resource(resource_url, File.join(temp_dir))
186
+ end
187
+ local_dir = local_dir_for_package(package_name, version_name)
188
+ @os.clear_directory(local_dir)
189
+ # some packages contain no files, only a fig file.
190
+ if not (package.archive_urls.empty? && package.resource_urls.empty?)
191
+ FileUtils.mv(Dir.glob(File.join(temp_dir, "*")), local_dir)
192
+ end
193
+ write_local_package(package_name, version_name, package)
194
+ rescue
195
+ $stderr.puts "Install failed, cleaning up"
196
+ delete_local_package(package_name, version_name)
197
+ exit 10
198
+ end
199
+ end
200
+
201
+ # 'resources' is an Array of filenames: ['tmp/foo/file1', 'tmp/foo/*.jar']
202
+ def expand_globs_from(resources)
203
+ expanded_files = []
204
+ resources.each {|f| expanded_files.concat(Dir.glob(f))}
205
+ expanded_files
206
+ end
207
+
208
+ def is_url?(url)
209
+ not (/ftp:\/\/|http:\/\/|file:\/\/|ssh:\/\// =~ url).nil?
210
+ end
211
+
212
+ def delete_local_package(package_name, version_name)
213
+ FileUtils.rm_rf(local_dir_for_package(package_name, version_name))
214
+ end
215
+
216
+ def write_local_package(package_name, version_name, package)
217
+ file = local_fig_file_for_package(package_name, version_name)
218
+ @os.write(file, package.unparse)
219
+ end
220
+
221
+ def remote_fig_file_for_package(package_name, version_name)
222
+ "#{@remote_repository_url}/#{package_name}/#{version_name}/.fig"
223
+ end
224
+
225
+ def local_fig_file_for_package(package_name, version_name)
226
+ File.join(local_dir_for_package(package_name, version_name), ".fig")
227
+ end
228
+
229
+ def remote_dir_for_package(package_name, version_name)
230
+ "#{@remote_repository_url}/#{package_name}/#{version_name}"
231
+ end
232
+
233
+ def temp_dir_for_package(package_name, version_name)
234
+ File.join(@local_repository_dir, "tmp")
235
+ end
236
+
237
+ def package_missing?(package_name, version_name)
238
+ not File.exist?(local_fig_file_for_package(package_name, version_name))
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,107 @@
1
+ require 'ostruct'
2
+ require 'set'
3
+
4
+ # This class copies files from the project directories in ~/.fighome to the
5
+ # user's working directory. It keeps track of which files have already been copied, and which
6
+ # package/versions they came from, and deletes files as necessary to ensure that
7
+ # we never have files from two different versions of the same package in the user's
8
+ # working directory.
9
+ class Retriever
10
+ def initialize(base_dir)
11
+ @base_dir = base_dir
12
+ @configs = {}
13
+ @fig_dir = File.join(@base_dir, ".fig")
14
+
15
+ file = File.join(@fig_dir, "retrieve")
16
+ if File.exist?(file)
17
+ load(file)
18
+ end
19
+ end
20
+
21
+ def with_config(name, version)
22
+ if name and version
23
+ @config = @configs[name]
24
+ if @config && @config.version != version
25
+ @config.files.each do |relpath|
26
+ $stderr.puts "\033[31m- [#{@config.name}/#{@config.version}] #{relpath}\033[0m"
27
+ FileUtils.rm_f(File.join(@base_dir, relpath))
28
+ end
29
+ @config = nil
30
+ end
31
+ if not @config
32
+ @config = new_config(name, version)
33
+ @configs[name] = @config
34
+ end
35
+ else
36
+ @config = nil
37
+ end
38
+ yield
39
+ end
40
+
41
+ def retrieve(source, relpath)
42
+ copy(source, relpath)
43
+ end
44
+
45
+ def save
46
+ FileUtils.mkdir_p(@fig_dir)
47
+ File.open(File.join(@fig_dir, "retrieve"), 'w') do |f|
48
+ @configs.each do |name,config|
49
+ config.files.each do |target|
50
+ f << target << "=" << config.name << "/" << config.version << "\n"
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def load(file)
59
+ File.open(file).each_line do |line|
60
+ line = line.strip()
61
+ if line =~ /^(.+)=(.+)\/(.+)$/
62
+ target = $1
63
+ config_name = $2
64
+ config_version = $3
65
+ config = @configs[config_name]
66
+ if config
67
+ if config.version != config_version
68
+ raise "version mismatch in .figretrieve"
69
+ end
70
+ else
71
+ config = new_config(config_name, config_version)
72
+ @configs[config_name] = config
73
+ end
74
+ config.files << target
75
+ else
76
+ raise "parse error in #{file}: #{line}"
77
+ end
78
+ end
79
+ end
80
+
81
+ def new_config(name, version)
82
+ config = OpenStruct.new
83
+ config.name = name
84
+ config.version = version
85
+ config.files = Set.new()
86
+ return config
87
+ end
88
+
89
+ def copy(source, relpath)
90
+ target = File.join(@base_dir, relpath)
91
+ if File.directory?(source)
92
+ FileUtils.mkdir_p(target)
93
+ Dir.foreach(source) do |child|
94
+ if child != "." and child != ".."
95
+ copy(File.join(source, child), File.join(relpath, child))
96
+ end
97
+ end
98
+ else
99
+ if !File.exist?(target) || File.mtime(source) > File.mtime(target)
100
+ $stderr.puts "\033[32m+ [#{@config.name}/#{@config.version}] #{relpath}\033[0m"
101
+ FileUtils.mkdir_p(File.dirname(target))
102
+ FileUtils.cp(source, target, :preserve => true)
103
+ end
104
+ @config.files << relpath if @config
105
+ end
106
+ end
107
+ end
@@ -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
File without changes
metadata ADDED
@@ -0,0 +1,269 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fig18
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.38
6
+ platform: ruby
7
+ authors:
8
+ - Matthew Foemmel
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-10-06 00:00:00 -05:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: libarchive-static-ruby186
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - "="
23
+ - !ruby/object:Gem::Version
24
+ version: 1.0.0
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: net-ssh
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: 2.0.15
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: net-sftp
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.0.5
47
+ type: :runtime
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: net-netrc
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 0.2.2
58
+ type: :runtime
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: polyglot
62
+ prerelease: false
63
+ requirement: &id005 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.2.9
69
+ type: :runtime
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: treetop
73
+ prerelease: false
74
+ requirement: &id006 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 1.4.2
80
+ type: :runtime
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: highline
84
+ prerelease: false
85
+ requirement: &id007 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 1.6.2
91
+ type: :runtime
92
+ version_requirements: *id007
93
+ - !ruby/object:Gem::Dependency
94
+ name: rspec
95
+ prerelease: false
96
+ requirement: &id008 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: "1.3"
102
+ type: :development
103
+ version_requirements: *id008
104
+ - !ruby/object:Gem::Dependency
105
+ name: open4
106
+ prerelease: false
107
+ requirement: &id009 !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 1.0.1
113
+ type: :development
114
+ version_requirements: *id009
115
+ - !ruby/object:Gem::Dependency
116
+ name: libarchive-static-ruby186
117
+ prerelease: false
118
+ requirement: &id010 !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - "="
122
+ - !ruby/object:Gem::Version
123
+ version: 1.0.0
124
+ type: :runtime
125
+ version_requirements: *id010
126
+ - !ruby/object:Gem::Dependency
127
+ name: net-ssh
128
+ prerelease: false
129
+ requirement: &id011 !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: 2.0.15
135
+ type: :runtime
136
+ version_requirements: *id011
137
+ - !ruby/object:Gem::Dependency
138
+ name: net-sftp
139
+ prerelease: false
140
+ requirement: &id012 !ruby/object:Gem::Requirement
141
+ none: false
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: 2.0.5
146
+ type: :runtime
147
+ version_requirements: *id012
148
+ - !ruby/object:Gem::Dependency
149
+ name: net-netrc
150
+ prerelease: false
151
+ requirement: &id013 !ruby/object:Gem::Requirement
152
+ none: false
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: 0.2.2
157
+ type: :runtime
158
+ version_requirements: *id013
159
+ - !ruby/object:Gem::Dependency
160
+ name: polyglot
161
+ prerelease: false
162
+ requirement: &id014 !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: 0.2.9
168
+ type: :runtime
169
+ version_requirements: *id014
170
+ - !ruby/object:Gem::Dependency
171
+ name: treetop
172
+ prerelease: false
173
+ requirement: &id015 !ruby/object:Gem::Requirement
174
+ none: false
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: 1.4.2
179
+ type: :runtime
180
+ version_requirements: *id015
181
+ - !ruby/object:Gem::Dependency
182
+ name: highline
183
+ prerelease: false
184
+ requirement: &id016 !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: 1.6.2
190
+ type: :runtime
191
+ version_requirements: *id016
192
+ - !ruby/object:Gem::Dependency
193
+ name: rspec
194
+ prerelease: false
195
+ requirement: &id017 !ruby/object:Gem::Requirement
196
+ none: false
197
+ requirements:
198
+ - - ~>
199
+ - !ruby/object:Gem::Version
200
+ version: "1.3"
201
+ type: :development
202
+ version_requirements: *id017
203
+ - !ruby/object:Gem::Dependency
204
+ name: open4
205
+ prerelease: false
206
+ requirement: &id018 !ruby/object:Gem::Requirement
207
+ none: false
208
+ requirements:
209
+ - - ">="
210
+ - !ruby/object:Gem::Version
211
+ version: 1.0.1
212
+ type: :development
213
+ version_requirements: *id018
214
+ description: Fig is a utility for configuring environments and managing dependencies across a team of developers. You give it a list of packages and a shell command to run; it creates an environment that includes those packages, then executes the shell command in it (the caller's environment is not affected).
215
+ email: git@foemmel.com
216
+ executables:
217
+ - fig
218
+ - fig-download
219
+ extensions: []
220
+
221
+ extra_rdoc_files:
222
+ - LICENSE
223
+ - README.md
224
+ files:
225
+ - bin/fig
226
+ - bin/fig-download
227
+ - lib/fig.rb
228
+ - lib/fig/backtrace.rb
229
+ - lib/fig/environment.rb
230
+ - lib/fig/grammar.treetop
231
+ - lib/fig/options.rb
232
+ - lib/fig/os.rb
233
+ - lib/fig/package.rb
234
+ - lib/fig/parser.rb
235
+ - lib/fig/repository.rb
236
+ - lib/fig/retriever.rb
237
+ - lib/fig/windows.rb
238
+ - LICENSE
239
+ - README.md
240
+ has_rdoc: true
241
+ homepage: http://github.com/mfoemmel/fig
242
+ licenses: []
243
+
244
+ post_install_message:
245
+ rdoc_options: []
246
+
247
+ require_paths:
248
+ - lib
249
+ required_ruby_version: !ruby/object:Gem::Requirement
250
+ none: false
251
+ requirements:
252
+ - - ">="
253
+ - !ruby/object:Gem::Version
254
+ version: "0"
255
+ required_rubygems_version: !ruby/object:Gem::Requirement
256
+ none: false
257
+ requirements:
258
+ - - ">="
259
+ - !ruby/object:Gem::Version
260
+ version: "0"
261
+ requirements: []
262
+
263
+ rubyforge_project:
264
+ rubygems_version: 1.5.3
265
+ signing_key:
266
+ specification_version: 3
267
+ summary: Fig is a utility for configuring environments and managing dependencies across a team of developers..
268
+ test_files: []
269
+