fig 0.1.35 → 0.1.36
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/bin/fig +10 -7
- data/lib/fig/backtrace.rb +37 -0
- data/lib/fig/environment.rb +22 -12
- data/lib/fig/grammar.treetop +1 -1
- data/lib/fig/os.rb +2 -1
- data/lib/fig/package.rb +7 -1
- data/lib/fig/retriever.rb +107 -0
- data/spec/fig_spec.rb +331 -0
- data/spec/retriever_spec.rb +47 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/win_spec.rb +21 -0
- metadata +50 -110
data/bin/fig
CHANGED
@@ -5,6 +5,7 @@ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
|
|
5
5
|
require 'rubygems'
|
6
6
|
require 'net/ftp'
|
7
7
|
|
8
|
+
require 'fig/retriever'
|
8
9
|
require 'fig/options'
|
9
10
|
require 'fig/environment'
|
10
11
|
require 'fig/repository'
|
@@ -59,16 +60,18 @@ end
|
|
59
60
|
|
60
61
|
os = OS.new(options[:login])
|
61
62
|
repos = Repository.new(os, File.expand_path(File.join(options[:home], 'repos')), remote_url, remote_user, options[:update], options[:update_if_missing])
|
62
|
-
|
63
|
+
retriever = Retriever.new(".")
|
64
|
+
at_exit { retriever.save }
|
65
|
+
env = Environment.new(os, repos, vars, retriever)
|
63
66
|
|
64
67
|
options[:modifiers].each do |modifier|
|
65
|
-
env.apply_config_statement(nil, modifier)
|
68
|
+
env.apply_config_statement(nil, modifier, nil)
|
66
69
|
end
|
67
70
|
|
68
|
-
if File.exist?(".fig")
|
69
|
-
$stderr.puts "The '.fig' file is deprecated. Please rename to 'package.fig'"
|
70
|
-
exit 1
|
71
|
-
end
|
71
|
+
#if File.exist?(".fig")
|
72
|
+
# $stderr.puts "The '.fig' file is deprecated. Please rename to 'package.fig'"
|
73
|
+
# exit 1
|
74
|
+
#end
|
72
75
|
|
73
76
|
DEFAULT_FIG_FILE = 'package.fig'
|
74
77
|
|
@@ -131,7 +134,7 @@ if input
|
|
131
134
|
end
|
132
135
|
unless options[:publish] || options[:list] || options[:publish_local]
|
133
136
|
env.register_package(package)
|
134
|
-
env.apply_config(package, options[:config])
|
137
|
+
env.apply_config(package, options[:config], nil)
|
135
138
|
direct_retrieves.each do |info|
|
136
139
|
env.direct_retrieve(info[0], info[1], info[2])
|
137
140
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Backtrace
|
2
|
+
def initialize(parent, package_name, version_name, config_name)
|
3
|
+
@parent = parent
|
4
|
+
@package_name = package_name
|
5
|
+
@version_name = version_name
|
6
|
+
@config_name = config_name || "default"
|
7
|
+
end
|
8
|
+
|
9
|
+
def collect(stack)
|
10
|
+
if @parent
|
11
|
+
@parent.collect(stack)
|
12
|
+
end
|
13
|
+
elem = ""
|
14
|
+
if @package_name
|
15
|
+
elem = @package_name
|
16
|
+
end
|
17
|
+
if @version_name
|
18
|
+
elem += "/" + @version_name
|
19
|
+
end
|
20
|
+
if @config_name
|
21
|
+
elem += ":" + @config_name
|
22
|
+
end
|
23
|
+
stack << elem
|
24
|
+
end
|
25
|
+
|
26
|
+
def dump(out)
|
27
|
+
stack = []
|
28
|
+
collect(stack)
|
29
|
+
i=0
|
30
|
+
for elem in stack
|
31
|
+
indent=""
|
32
|
+
i.times { indent += " " }
|
33
|
+
out.puts indent+elem
|
34
|
+
i += 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/fig/environment.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'fig/backtrace'
|
2
|
+
|
1
3
|
module Fig
|
2
4
|
|
3
5
|
# This class manages the program's state, including the value of all environment
|
@@ -5,13 +7,14 @@ module Fig
|
|
5
7
|
class Environment
|
6
8
|
DEFAULT_VERSION_NAME = "current"
|
7
9
|
|
8
|
-
def initialize(os, repository, variables)
|
10
|
+
def initialize(os, repository, variables, retriever)
|
9
11
|
@os = os
|
10
12
|
@repository = repository
|
11
13
|
@variables = variables
|
12
14
|
@retrieve_vars = {}
|
13
15
|
@packages = {}
|
14
16
|
@applied_configs = {}
|
17
|
+
@retriever = retriever
|
15
18
|
end
|
16
19
|
|
17
20
|
# Returns the value of an envirionment variable
|
@@ -34,12 +37,13 @@ module Fig
|
|
34
37
|
@packages[name] = package
|
35
38
|
end
|
36
39
|
|
37
|
-
def apply_config(package, config_name)
|
40
|
+
def apply_config(package, config_name, backtrace)
|
38
41
|
if (@applied_configs[package.package_name] ||= []).member?(config_name)
|
39
42
|
return
|
40
43
|
end
|
44
|
+
new_backtrace = Backtrace.new(backtrace, package.package_name, package.version_name, config_name)
|
41
45
|
config = package[config_name]
|
42
|
-
config.statements.each { |stmt| apply_config_statement(package, stmt) }
|
46
|
+
config.statements.each { |stmt| apply_config_statement(package, stmt, new_backtrace) }
|
43
47
|
@applied_configs[package.package_name] << config_name
|
44
48
|
end
|
45
49
|
|
@@ -50,7 +54,7 @@ module Fig
|
|
50
54
|
end
|
51
55
|
|
52
56
|
def execute_config(base_package, package_name, config_name, version_name, args)
|
53
|
-
package = lookup_package(package_name || base_package.package_name, version_name)
|
57
|
+
package = lookup_package(package_name || base_package.package_name, version_name, Backtrace.new(nil, package_name, version_name, config_name))
|
54
58
|
result = nil
|
55
59
|
commands = package[config_name || "default"].commands
|
56
60
|
with_environment do
|
@@ -62,14 +66,14 @@ module Fig
|
|
62
66
|
result
|
63
67
|
end
|
64
68
|
|
65
|
-
def apply_config_statement(base_package, statement)
|
69
|
+
def apply_config_statement(base_package, statement, backtrace)
|
66
70
|
case statement
|
67
71
|
when Path
|
68
72
|
append_variable(base_package, statement.name, statement.value)
|
69
73
|
when Set
|
70
74
|
set_variable(base_package, statement.name, statement.value)
|
71
75
|
when Include
|
72
|
-
include_config(base_package, statement.package_name, statement.config_name, statement.version_name)
|
76
|
+
include_config(base_package, statement.package_name, statement.config_name, statement.version_name, backtrace)
|
73
77
|
when Command
|
74
78
|
# ignore
|
75
79
|
else
|
@@ -77,13 +81,14 @@ module Fig
|
|
77
81
|
end
|
78
82
|
end
|
79
83
|
|
80
|
-
def include_config(base_package, package_name, config_name, version_name)
|
81
|
-
|
82
|
-
|
84
|
+
def include_config(base_package, package_name, config_name, version_name, backtrace)
|
85
|
+
new_backtrace = Backtrace.new(backtrace, package_name, version_name, config_name)
|
86
|
+
package = lookup_package(package_name || base_package.package_name, version_name, new_backtrace)
|
87
|
+
apply_config(package, config_name || "default", backtrace)
|
83
88
|
end
|
84
89
|
|
85
90
|
def direct_retrieve(package_name, source_path, target_path)
|
86
|
-
package = lookup_package(package_name, nil)
|
91
|
+
package = lookup_package(package_name, nil, nil)
|
87
92
|
FileUtils.mkdir_p(target_path)
|
88
93
|
FileUtils.cp_r(File.join(package.directory, source_path, '.'), target_path)
|
89
94
|
end
|
@@ -123,13 +128,16 @@ module Fig
|
|
123
128
|
end
|
124
129
|
end
|
125
130
|
|
126
|
-
def lookup_package(package_name, version_name)
|
131
|
+
def lookup_package(package_name, version_name, backtrace)
|
127
132
|
package = @packages[package_name]
|
128
133
|
if package.nil?
|
129
134
|
package = @repository.load_package(package_name, version_name || DEFAULT_VERSION_NAME)
|
135
|
+
package.backtrace = backtrace
|
130
136
|
@packages[package_name] = package
|
131
137
|
elsif version_name && version_name != package.version_name
|
132
138
|
$stderr.puts "Version mismatch: #{package_name}"
|
139
|
+
backtrace.dump($stderr) if backtrace
|
140
|
+
package.backtrace.dump($stderr) if package.backtrace
|
133
141
|
exit 10
|
134
142
|
end
|
135
143
|
package
|
@@ -151,7 +159,9 @@ module Fig
|
|
151
159
|
target = File.join(target, File.basename(file))
|
152
160
|
end
|
153
161
|
end
|
154
|
-
@
|
162
|
+
@retriever.with_config(base_package.package_name, base_package.version_name) do
|
163
|
+
@retriever.retrieve(file, target)
|
164
|
+
end
|
155
165
|
file = target
|
156
166
|
end
|
157
167
|
file
|
data/lib/fig/grammar.treetop
CHANGED
@@ -32,7 +32,7 @@ grammar Fig
|
|
32
32
|
end
|
33
33
|
|
34
34
|
rule retrieve
|
35
|
-
"retrieve" ws var:[@a-zA-Z0-9/\._]+ "->" path:[a-zA-Z0-
|
35
|
+
"retrieve" ws var:[@a-zA-Z0-9/\._]+ "->" path:[a-zA-Z0-9_/\.\-\[\]]+ ws {
|
36
36
|
def to_package_statement
|
37
37
|
Retrieve.new(var.text_value, path.text_value)
|
38
38
|
end
|
data/lib/fig/os.rb
CHANGED
@@ -255,10 +255,11 @@ module Fig
|
|
255
255
|
end
|
256
256
|
end
|
257
257
|
else
|
258
|
-
if !
|
258
|
+
if !File.exist?(target) || File.mtime(source) != File.mtime(target)
|
259
259
|
log_info "#{msg} #{target}" if msg
|
260
260
|
FileUtils.mkdir_p(File.dirname(target))
|
261
261
|
FileUtils.cp(source, target)
|
262
|
+
File.utime(File.atime(source), File.mtime(source), target)
|
262
263
|
end
|
263
264
|
end
|
264
265
|
end
|
data/lib/fig/package.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
module Fig
|
2
2
|
class Package
|
3
3
|
attr_reader :package_name, :version_name, :directory, :statements
|
4
|
+
attr_accessor :backtrace
|
4
5
|
|
5
6
|
def initialize(package_name, version_name, directory, statements)
|
6
7
|
@package_name = package_name
|
7
8
|
@version_name = version_name
|
8
9
|
@directory = directory
|
9
10
|
@statements = statements
|
11
|
+
@backtrace = nil
|
10
12
|
end
|
11
|
-
|
13
|
+
|
12
14
|
def [](config_name)
|
13
15
|
@statements.each do |stmt|
|
14
16
|
return stmt if stmt.is_a?(Configuration) && stmt.name == config_name
|
@@ -42,6 +44,10 @@ module Fig
|
|
42
44
|
def ==(other)
|
43
45
|
@package_name == other.package_name && @version_name == other.version_name && @statements.to_yaml == other.statements.to_yaml
|
44
46
|
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
@package_name + "/" + @version_name
|
50
|
+
end
|
45
51
|
end
|
46
52
|
|
47
53
|
class Archive
|
@@ -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)
|
103
|
+
end
|
104
|
+
@config.files << relpath if @config
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
data/spec/fig_spec.rb
ADDED
@@ -0,0 +1,331 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'fig/os'
|
5
|
+
require 'rake'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
class Popen
|
9
|
+
if Fig::OS.windows?
|
10
|
+
require 'win32/open3'
|
11
|
+
def self.popen(*cmd)
|
12
|
+
Open3.popen3(*cmd) { |stdin,stdout,stderr|
|
13
|
+
yield stdin, stdout, stderr
|
14
|
+
}
|
15
|
+
end
|
16
|
+
elsif Fig::OS.java?
|
17
|
+
require 'open3'
|
18
|
+
def self.popen(*cmd)
|
19
|
+
Open3.popen3(*cmd) { |stdin,stdout,stderr|
|
20
|
+
yield stdin, stdout, stderr
|
21
|
+
}
|
22
|
+
end
|
23
|
+
else
|
24
|
+
require 'open4'
|
25
|
+
def self.popen(*cmd)
|
26
|
+
Open4::popen4(*cmd) { |pid, stdin, stdout, stderr|
|
27
|
+
yield stdin, stdout, stderr
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
FIG_HOME = File.expand_path(File.dirname(__FILE__) + '/../tmp/fighome')
|
34
|
+
FileUtils.mkdir_p(FIG_HOME)
|
35
|
+
ENV['FIG_HOME'] = FIG_HOME
|
36
|
+
|
37
|
+
FIG_REMOTE_DIR = File.expand_path(File.dirname(__FILE__) + '/../tmp/remote')
|
38
|
+
FileUtils.mkdir_p(FIG_REMOTE_DIR)
|
39
|
+
ENV['FIG_REMOTE_URL'] = "ssh://#{ENV['USER']}@localhost#{FIG_REMOTE_DIR}"
|
40
|
+
|
41
|
+
FIG_EXE = File.expand_path(File.dirname(__FILE__) + '/../bin/fig')
|
42
|
+
|
43
|
+
def fig(args, input=nil)
|
44
|
+
args = "--file - #{args}" if input
|
45
|
+
out = nil
|
46
|
+
err = nil
|
47
|
+
Popen.popen("#{RUBY} #{FIG_EXE} #{args}") do |stdin, stdout, stderr|
|
48
|
+
if input
|
49
|
+
stdin.puts input
|
50
|
+
stdin.close
|
51
|
+
end
|
52
|
+
err = stderr.read.strip
|
53
|
+
out = stdout.read.strip
|
54
|
+
if err != ""
|
55
|
+
$stderr.puts err
|
56
|
+
end
|
57
|
+
end
|
58
|
+
return out, err, $?.exitstatus
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "Fig" do
|
62
|
+
it "set environment variable from command line" do
|
63
|
+
fig('-s FOO=BAR -g FOO')[0].should == 'BAR'
|
64
|
+
fig('--set FOO=BAR -g FOO')[0].should == 'BAR'
|
65
|
+
end
|
66
|
+
|
67
|
+
it "set environment variable from fig file" do
|
68
|
+
input = <<-END
|
69
|
+
config default
|
70
|
+
set FOO=BAR
|
71
|
+
end
|
72
|
+
END
|
73
|
+
fig('-g FOO', input)[0].should == 'BAR'
|
74
|
+
end
|
75
|
+
|
76
|
+
it "append environment variable from command line" do
|
77
|
+
fig('-p PATH=foo -g PATH').should == ["foo#{File::PATH_SEPARATOR}#{ENV['PATH']}","",0]
|
78
|
+
end
|
79
|
+
|
80
|
+
it "append environment variable from fig file" do
|
81
|
+
input = <<-END
|
82
|
+
config default
|
83
|
+
add PATH=foo
|
84
|
+
end
|
85
|
+
END
|
86
|
+
fig('-g PATH', input).should == ["foo#{File::PATH_SEPARATOR}#{ENV['PATH']}","",0]
|
87
|
+
end
|
88
|
+
|
89
|
+
it "append empty environment variable" do
|
90
|
+
fig('-p XYZZY=foo -g XYZZY').should == ["foo","",0]
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should ignore comments" do
|
94
|
+
input = <<-END
|
95
|
+
#/usr/bin/env fig
|
96
|
+
|
97
|
+
# Some comment
|
98
|
+
config default
|
99
|
+
set FOO=BAR # Another comment
|
100
|
+
end
|
101
|
+
END
|
102
|
+
fig('-g FOO', input)[0].should == 'BAR'
|
103
|
+
end
|
104
|
+
|
105
|
+
it "publish to remote repository" do
|
106
|
+
FileUtils.rm_rf(FIG_HOME)
|
107
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
108
|
+
input = <<-END
|
109
|
+
config default
|
110
|
+
set FOO=BAR
|
111
|
+
end
|
112
|
+
END
|
113
|
+
fig('--publish foo/1.2.3', input)
|
114
|
+
fail unless File.exists? FIG_HOME + "/repos/foo/1.2.3/.fig"
|
115
|
+
fail unless File.exists? FIG_REMOTE_DIR + "/foo/1.2.3/.fig"
|
116
|
+
fig('-u -i foo/1.2.3 -g FOO')[0].should == 'BAR'
|
117
|
+
end
|
118
|
+
|
119
|
+
it "publish resource to remote repository" do
|
120
|
+
FileUtils.rm_rf(FIG_HOME)
|
121
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
122
|
+
FileUtils.mkdir_p("tmp/bin")
|
123
|
+
File.open("tmp/bin/hello", "w") { |f| f << "echo bar" }
|
124
|
+
fail unless system "chmod +x tmp/bin/hello"
|
125
|
+
input = <<-END
|
126
|
+
resource tmp/bin/hello
|
127
|
+
config default
|
128
|
+
append PATH=@/tmp/bin
|
129
|
+
end
|
130
|
+
END
|
131
|
+
fig('--publish foo/1.2.3', input)
|
132
|
+
fail unless File.exists? FIG_HOME + "/repos/foo/1.2.3/.fig"
|
133
|
+
fail unless File.exists? FIG_REMOTE_DIR + "/foo/1.2.3/.fig"
|
134
|
+
fig('-u -i foo/1.2.3 -- hello')[0].should == 'bar'
|
135
|
+
end
|
136
|
+
|
137
|
+
it "publish resource to remote repository using command line" do
|
138
|
+
FileUtils.rm_rf(FIG_HOME)
|
139
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
140
|
+
FileUtils.mkdir_p("tmp/bin")
|
141
|
+
File.open("tmp/bin/hello", "w") { |f| f << "echo bar" }
|
142
|
+
fail unless system "chmod +x tmp/bin/hello"
|
143
|
+
fig('--publish foo/1.2.3 --resource tmp/bin/hello --append PATH=@/tmp/bin')
|
144
|
+
fail unless File.exists? FIG_HOME + "/repos/foo/1.2.3/.fig"
|
145
|
+
fail unless File.exists? FIG_REMOTE_DIR + "/foo/1.2.3/.fig"
|
146
|
+
fig('-u -i foo/1.2.3 -- hello')[0].should == 'bar'
|
147
|
+
end
|
148
|
+
|
149
|
+
it "refuses to overwrite existing version in remote repository without being forced" do
|
150
|
+
FileUtils.rm_rf(FIG_HOME)
|
151
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
152
|
+
input = <<-END
|
153
|
+
config default
|
154
|
+
set FOO=SHEEP
|
155
|
+
end
|
156
|
+
END
|
157
|
+
fig('--publish foo/1.2.3', input)
|
158
|
+
fail unless File.exists? FIG_HOME + "/repos/foo/1.2.3/.fig"
|
159
|
+
fail unless File.exists? FIG_REMOTE_DIR + "/foo/1.2.3/.fig"
|
160
|
+
fig('-u -i foo/1.2.3 -g FOO')[0].should == 'SHEEP'
|
161
|
+
|
162
|
+
input = <<-END
|
163
|
+
config default
|
164
|
+
set FOO=CHEESE
|
165
|
+
end
|
166
|
+
END
|
167
|
+
(out, err, exitstatus) = fig('--publish foo/1.2.3', input)
|
168
|
+
exitstatus.should == 1
|
169
|
+
fig('-u -i foo/1.2.3 -g FOO')[0].should == 'SHEEP'
|
170
|
+
|
171
|
+
(out, err, exitstatus) = fig('--publish foo/1.2.3 --force', input)
|
172
|
+
exitstatus.should == 0
|
173
|
+
fig('-u -i foo/1.2.3 -g FOO')[0].should == 'CHEESE'
|
174
|
+
end
|
175
|
+
|
176
|
+
it "publishes to the local repo only when told to" do
|
177
|
+
FileUtils.rm_rf(FIG_HOME)
|
178
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
179
|
+
FileUtils.mkdir_p("tmp/bin")
|
180
|
+
File.open("tmp/bin/hello", "w") { |f| f << "echo bar" }
|
181
|
+
fail unless system "chmod +x tmp/bin/hello"
|
182
|
+
fig('--publish-local foo/1.2.3 --resource tmp/bin/hello --append PATH=@/tmp/bin')
|
183
|
+
fail if File.exists? FIG_REMOTE_DIR + "/foo/1.2.3/.fig"
|
184
|
+
fig('-m -i foo/1.2.3 -- hello')[0].should == 'bar'
|
185
|
+
end
|
186
|
+
|
187
|
+
it "retrieve resource" do
|
188
|
+
FileUtils.rm_rf(FIG_HOME)
|
189
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
190
|
+
FileUtils.rm_rf("tmp")
|
191
|
+
FileUtils.mkdir_p("tmp/lib")
|
192
|
+
File.open("tmp/lib/hello", "w") { |f| f << "some library" }
|
193
|
+
input = <<-END
|
194
|
+
resource tmp/lib/hello
|
195
|
+
config default
|
196
|
+
append FOOPATH=@/tmp/lib/hello
|
197
|
+
end
|
198
|
+
END
|
199
|
+
fig('--publish foo/1.2.3', input)
|
200
|
+
input = <<-END
|
201
|
+
retrieve FOOPATH->tmp/lib2/[package]
|
202
|
+
config default
|
203
|
+
include foo/1.2.3
|
204
|
+
end
|
205
|
+
END
|
206
|
+
fig('-m', input)
|
207
|
+
File.read("tmp/lib2/foo/hello").should == "some library"
|
208
|
+
end
|
209
|
+
|
210
|
+
it "retrieves resource that is a directory" do
|
211
|
+
FileUtils.rm_rf(FIG_HOME)
|
212
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
213
|
+
FileUtils.rm_rf("tmp")
|
214
|
+
FileUtils.mkdir_p("tmp/lib")
|
215
|
+
File.open("tmp/lib/hello", "w") { |f| f << "some library" }
|
216
|
+
# To copy the contents of a directory, instead of the directory itself,
|
217
|
+
# use '/.' as a suffix to the directory name in 'append'.
|
218
|
+
input = <<-END
|
219
|
+
resource tmp/lib/hello
|
220
|
+
config default
|
221
|
+
append FOOPATH=@/tmp/lib/.
|
222
|
+
end
|
223
|
+
END
|
224
|
+
fig('--publish foo/1.2.3', input)
|
225
|
+
input = <<-END
|
226
|
+
retrieve FOOPATH->tmp/lib2/[package]
|
227
|
+
config default
|
228
|
+
include foo/1.2.3
|
229
|
+
end
|
230
|
+
END
|
231
|
+
fig('-m', input)
|
232
|
+
File.read("tmp/lib2/foo/hello").should == "some library"
|
233
|
+
end
|
234
|
+
|
235
|
+
it "retrieve preserves the path after '//' when copying files into your project directory" do
|
236
|
+
FileUtils.rm_rf(FIG_HOME)
|
237
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
238
|
+
FileUtils.rm_rf("tmp")
|
239
|
+
FileUtils.mkdir_p("tmp/include")
|
240
|
+
File.open("tmp/include/hello.h", "w") { |f| f << "a header file" }
|
241
|
+
File.open("tmp/include/hello2.h", "w") { |f| f << "another header file" }
|
242
|
+
input = <<-END
|
243
|
+
resource tmp/include/hello.h
|
244
|
+
resource tmp/include/hello2.h
|
245
|
+
config default
|
246
|
+
append INCLUDE=@/tmp//include/hello.h
|
247
|
+
append INCLUDE=@/tmp//include/hello2.h
|
248
|
+
end
|
249
|
+
END
|
250
|
+
fig('--publish foo/1.2.3', input)
|
251
|
+
|
252
|
+
input = <<-END
|
253
|
+
retrieve INCLUDE->tmp/include2/[package]
|
254
|
+
config default
|
255
|
+
include foo/1.2.3
|
256
|
+
end
|
257
|
+
END
|
258
|
+
fig('-u', input)
|
259
|
+
|
260
|
+
File.read("tmp/include2/foo/include/hello.h").should == "a header file"
|
261
|
+
File.read("tmp/include2/foo/include/hello2.h").should == "another header file"
|
262
|
+
end
|
263
|
+
|
264
|
+
it "package multiple resources" do
|
265
|
+
FileUtils.rm_rf(FIG_HOME)
|
266
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
267
|
+
FileUtils.rm_rf("tmp")
|
268
|
+
FileUtils.mkdir_p("tmp/lib")
|
269
|
+
File.open("tmp/lib/hello", "w") { |f| f << "some library" }
|
270
|
+
File.open("tmp/lib/hello2", "w") { |f| f << "some other library" }
|
271
|
+
input = <<-END
|
272
|
+
resource tmp/lib/hello
|
273
|
+
resource tmp/lib/hello2
|
274
|
+
config default
|
275
|
+
append FOOPATH=@/tmp/lib/hello
|
276
|
+
append FOOPATH=@/tmp/lib/hello2
|
277
|
+
end
|
278
|
+
END
|
279
|
+
fig('--publish foo/1.2.3', input)
|
280
|
+
input = <<-END
|
281
|
+
retrieve FOOPATH->tmp/lib2/[package]
|
282
|
+
config default
|
283
|
+
include foo/1.2.3
|
284
|
+
end
|
285
|
+
END
|
286
|
+
fig('-m', input)
|
287
|
+
File.read("tmp/lib2/foo/hello").should == "some library"
|
288
|
+
File.read("tmp/lib2/foo/hello2").should == "some other library"
|
289
|
+
end
|
290
|
+
|
291
|
+
it "packages multiple resources with wildcards" do
|
292
|
+
FileUtils.rm_rf(FIG_HOME)
|
293
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
294
|
+
FileUtils.rm_rf("tmp")
|
295
|
+
FileUtils.mkdir_p("tmp/lib")
|
296
|
+
File.open("tmp/lib/foo.jar", "w") { |f| f << "some library" }
|
297
|
+
File.open("tmp/lib/bar.jar", "w") { |f| f << "some other library" }
|
298
|
+
input = <<-END
|
299
|
+
resource tmp/**/*.jar
|
300
|
+
config default
|
301
|
+
append FOOPATH=@/tmp/lib/foo.jar
|
302
|
+
end
|
303
|
+
END
|
304
|
+
fig('--publish foo/1.2.3', input)
|
305
|
+
input = <<-END
|
306
|
+
retrieve FOOPATH->tmp/lib2/[package]
|
307
|
+
config default
|
308
|
+
include foo/1.2.3
|
309
|
+
end
|
310
|
+
END
|
311
|
+
fig('-m', input)
|
312
|
+
File.read("tmp/lib2/foo/foo.jar").should == "some library"
|
313
|
+
end
|
314
|
+
|
315
|
+
it "update local packages if they already exist" do
|
316
|
+
FileUtils.rm_rf(FIG_HOME)
|
317
|
+
FileUtils.rm_rf(FIG_REMOTE_DIR)
|
318
|
+
FileUtils.mkdir_p("tmp/bin")
|
319
|
+
File.open("tmp/bin/hello", "w") { |f| f << "echo sheep" }
|
320
|
+
fail unless system "chmod +x tmp/bin/hello"
|
321
|
+
fig('--publish-local foo/1.2.3 --resource tmp/bin/hello --append PATH=@/tmp/bin')
|
322
|
+
fail if File.exists? FIG_REMOTE_DIR + "/foo/1.2.3/.fig"
|
323
|
+
fig('-m -i foo/1.2.3 -- hello')[0].should == 'sheep'
|
324
|
+
|
325
|
+
File.open("tmp/bin/hello", "w") { |f| f << "echo cheese" }
|
326
|
+
fail unless system "chmod +x tmp/bin/hello"
|
327
|
+
fig('--publish-local foo/1.2.3 --resource tmp/bin/hello --append PATH=@/tmp/bin')
|
328
|
+
fail if File.exists? FIG_REMOTE_DIR + "/foo/1.2.3/.fig"
|
329
|
+
fig('-m -i foo/1.2.3 -- hello')[0].should == 'cheese'
|
330
|
+
end
|
331
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'fig/retriever'
|
2
|
+
|
3
|
+
describe "Retriever" do
|
4
|
+
it "retrieves single file" do
|
5
|
+
|
6
|
+
# Set up some test files
|
7
|
+
test_dir = "tmp/retrieve-test"
|
8
|
+
FileUtils.rm_rf(test_dir)
|
9
|
+
FileUtils.mkdir_p(test_dir)
|
10
|
+
|
11
|
+
File.open("tmp/foo.txt", 'w') {|f| f << "FOO"}
|
12
|
+
File.open("tmp/bar.txt", 'w') {|f| f << "BAR"}
|
13
|
+
File.open("tmp/baz.txt", 'w') {|f| f << "BAZ"}
|
14
|
+
|
15
|
+
# Retrieve files A and B
|
16
|
+
r = Retriever.new(test_dir)
|
17
|
+
r.with_config("foo", "1.2.3") do
|
18
|
+
r.retrieve("tmp/foo.txt", "foo.txt")
|
19
|
+
r.retrieve("tmp/bar.txt", "bar.txt")
|
20
|
+
File.read(File.join(test_dir, "foo.txt")).should == "FOO"
|
21
|
+
File.read(File.join(test_dir, "bar.txt")).should == "BAR"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Retrieve files B and C for a different version
|
25
|
+
r.with_config("foo", "4.5.6") do
|
26
|
+
r.retrieve("tmp/bar.txt", "bar.txt")
|
27
|
+
r.retrieve("tmp/baz.txt", "baz.txt")
|
28
|
+
File.read(File.join(test_dir, "bar.txt")).should == "BAR"
|
29
|
+
File.read(File.join(test_dir, "baz.txt")).should == "BAZ"
|
30
|
+
File.exist?(File.join(test_dir, "foo.txt")).should == false
|
31
|
+
end
|
32
|
+
|
33
|
+
# Save and reload
|
34
|
+
r.save
|
35
|
+
r = Retriever.new(test_dir)
|
36
|
+
|
37
|
+
# Switch back to original version
|
38
|
+
r.with_config("foo", "1.2.3") do
|
39
|
+
r.retrieve("tmp/foo.txt", "foo.txt")
|
40
|
+
r.retrieve("tmp/bar.txt", "bar.txt")
|
41
|
+
|
42
|
+
File.read(File.join(test_dir, "foo.txt")).should == "FOO"
|
43
|
+
File.read(File.join(test_dir, "bar.txt")).should == "BAR"
|
44
|
+
File.exist?(File.join(test_dir, "baz.txt")).should == false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/win_spec.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'fig/os'
|
3
|
+
require 'fig/windows'
|
4
|
+
|
5
|
+
|
6
|
+
# Only run on Windows...
|
7
|
+
if Fig::OS.windows?
|
8
|
+
describe "Fig on Windows" do
|
9
|
+
it "batch script should exist" do
|
10
|
+
Fig::Windows.with_generated_batch_script(["echo", "Hello World"]) do |filename|
|
11
|
+
File.exist?(filename).should == true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "batch script should say 'Hello World' when executed" do
|
16
|
+
Fig::Windows.with_generated_batch_script(["echo", "Hello World"]) do |filename|
|
17
|
+
%x[#{filename}].should == "Hello World\n"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fig
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 35
|
10
|
-
version: 0.1.35
|
4
|
+
version: 0.1.36
|
11
5
|
platform: ruby
|
12
6
|
authors:
|
13
7
|
- Matthew Foemmel
|
@@ -15,152 +9,99 @@ autorequire:
|
|
15
9
|
bindir: bin
|
16
10
|
cert_chain: []
|
17
11
|
|
18
|
-
date: 2011-
|
12
|
+
date: 2011-09-02 00:00:00 -05:00
|
19
13
|
default_executable:
|
20
14
|
dependencies:
|
21
15
|
- !ruby/object:Gem::Dependency
|
22
16
|
name: libarchive
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
20
|
requirements:
|
27
21
|
- - ">="
|
28
22
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 25
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
- 1
|
33
|
-
- 1
|
34
23
|
version: 0.1.1
|
35
|
-
|
36
|
-
version_requirements: *id001
|
24
|
+
version:
|
37
25
|
- !ruby/object:Gem::Dependency
|
38
26
|
name: net-ssh
|
39
|
-
|
40
|
-
|
41
|
-
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
30
|
requirements:
|
43
31
|
- - ">="
|
44
32
|
- !ruby/object:Gem::Version
|
45
|
-
hash: 17
|
46
|
-
segments:
|
47
|
-
- 2
|
48
|
-
- 0
|
49
|
-
- 15
|
50
33
|
version: 2.0.15
|
51
|
-
|
52
|
-
version_requirements: *id002
|
34
|
+
version:
|
53
35
|
- !ruby/object:Gem::Dependency
|
54
36
|
name: net-sftp
|
55
|
-
|
56
|
-
|
57
|
-
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
40
|
requirements:
|
59
41
|
- - ">="
|
60
42
|
- !ruby/object:Gem::Version
|
61
|
-
hash: 5
|
62
|
-
segments:
|
63
|
-
- 2
|
64
|
-
- 0
|
65
|
-
- 5
|
66
43
|
version: 2.0.5
|
67
|
-
|
68
|
-
version_requirements: *id003
|
44
|
+
version:
|
69
45
|
- !ruby/object:Gem::Dependency
|
70
46
|
name: net-netrc
|
71
|
-
|
72
|
-
|
73
|
-
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
50
|
requirements:
|
75
51
|
- - ">="
|
76
52
|
- !ruby/object:Gem::Version
|
77
|
-
hash: 19
|
78
|
-
segments:
|
79
|
-
- 0
|
80
|
-
- 2
|
81
|
-
- 2
|
82
53
|
version: 0.2.2
|
83
|
-
|
84
|
-
version_requirements: *id004
|
54
|
+
version:
|
85
55
|
- !ruby/object:Gem::Dependency
|
86
56
|
name: polyglot
|
87
|
-
|
88
|
-
|
89
|
-
|
57
|
+
type: :runtime
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
60
|
requirements:
|
91
61
|
- - ">="
|
92
62
|
- !ruby/object:Gem::Version
|
93
|
-
hash: 5
|
94
|
-
segments:
|
95
|
-
- 0
|
96
|
-
- 2
|
97
|
-
- 9
|
98
63
|
version: 0.2.9
|
99
|
-
|
100
|
-
version_requirements: *id005
|
64
|
+
version:
|
101
65
|
- !ruby/object:Gem::Dependency
|
102
66
|
name: treetop
|
103
|
-
|
104
|
-
|
105
|
-
|
67
|
+
type: :runtime
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
70
|
requirements:
|
107
71
|
- - ">="
|
108
72
|
- !ruby/object:Gem::Version
|
109
|
-
hash: 3
|
110
|
-
segments:
|
111
|
-
- 1
|
112
|
-
- 4
|
113
|
-
- 2
|
114
73
|
version: 1.4.2
|
115
|
-
|
116
|
-
version_requirements: *id006
|
74
|
+
version:
|
117
75
|
- !ruby/object:Gem::Dependency
|
118
76
|
name: highline
|
119
|
-
|
120
|
-
|
121
|
-
|
77
|
+
type: :runtime
|
78
|
+
version_requirement:
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
80
|
requirements:
|
123
81
|
- - ">="
|
124
82
|
- !ruby/object:Gem::Version
|
125
|
-
hash: 11
|
126
|
-
segments:
|
127
|
-
- 1
|
128
|
-
- 6
|
129
|
-
- 2
|
130
83
|
version: 1.6.2
|
131
|
-
|
132
|
-
version_requirements: *id007
|
84
|
+
version:
|
133
85
|
- !ruby/object:Gem::Dependency
|
134
86
|
name: rspec
|
135
|
-
|
136
|
-
|
137
|
-
|
87
|
+
type: :development
|
88
|
+
version_requirement:
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
138
90
|
requirements:
|
139
91
|
- - ~>
|
140
92
|
- !ruby/object:Gem::Version
|
141
|
-
hash: 9
|
142
|
-
segments:
|
143
|
-
- 1
|
144
|
-
- 3
|
145
93
|
version: "1.3"
|
146
|
-
|
147
|
-
version_requirements: *id008
|
94
|
+
version:
|
148
95
|
- !ruby/object:Gem::Dependency
|
149
96
|
name: open4
|
150
|
-
|
151
|
-
|
152
|
-
|
97
|
+
type: :development
|
98
|
+
version_requirement:
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
100
|
requirements:
|
154
101
|
- - ">="
|
155
102
|
- !ruby/object:Gem::Version
|
156
|
-
hash: 21
|
157
|
-
segments:
|
158
|
-
- 1
|
159
|
-
- 0
|
160
|
-
- 1
|
161
103
|
version: 1.0.1
|
162
|
-
|
163
|
-
version_requirements: *id009
|
104
|
+
version:
|
164
105
|
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).
|
165
106
|
email: git@foemmel.com
|
166
107
|
executables:
|
@@ -175,6 +116,7 @@ files:
|
|
175
116
|
- bin/fig
|
176
117
|
- bin/fig-download
|
177
118
|
- lib/fig.rb
|
119
|
+
- lib/fig/backtrace.rb
|
178
120
|
- lib/fig/environment.rb
|
179
121
|
- lib/fig/grammar.treetop
|
180
122
|
- lib/fig/options.rb
|
@@ -182,6 +124,7 @@ files:
|
|
182
124
|
- lib/fig/package.rb
|
183
125
|
- lib/fig/parser.rb
|
184
126
|
- lib/fig/repository.rb
|
127
|
+
- lib/fig/retriever.rb
|
185
128
|
- lib/fig/windows.rb
|
186
129
|
- LICENSE
|
187
130
|
- README.md
|
@@ -190,34 +133,31 @@ homepage: http://github.com/mfoemmel/fig
|
|
190
133
|
licenses: []
|
191
134
|
|
192
135
|
post_install_message:
|
193
|
-
rdoc_options:
|
194
|
-
|
136
|
+
rdoc_options:
|
137
|
+
- --charset=UTF-8
|
195
138
|
require_paths:
|
196
139
|
- lib
|
197
140
|
required_ruby_version: !ruby/object:Gem::Requirement
|
198
|
-
none: false
|
199
141
|
requirements:
|
200
142
|
- - ">="
|
201
143
|
- !ruby/object:Gem::Version
|
202
|
-
hash: 3
|
203
|
-
segments:
|
204
|
-
- 0
|
205
144
|
version: "0"
|
145
|
+
version:
|
206
146
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
207
|
-
none: false
|
208
147
|
requirements:
|
209
148
|
- - ">="
|
210
149
|
- !ruby/object:Gem::Version
|
211
|
-
hash: 3
|
212
|
-
segments:
|
213
|
-
- 0
|
214
150
|
version: "0"
|
151
|
+
version:
|
215
152
|
requirements: []
|
216
153
|
|
217
154
|
rubyforge_project:
|
218
|
-
rubygems_version: 1.
|
155
|
+
rubygems_version: 1.3.5
|
219
156
|
signing_key:
|
220
157
|
specification_version: 3
|
221
158
|
summary: Fig is a utility for configuring environments and managing dependencies across a team of developers..
|
222
|
-
test_files:
|
223
|
-
|
159
|
+
test_files:
|
160
|
+
- spec/fig_spec.rb
|
161
|
+
- spec/retriever_spec.rb
|
162
|
+
- spec/spec_helper.rb
|
163
|
+
- spec/win_spec.rb
|