librarian 0.0.20 → 0.0.21
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/.travis.yml +1 -0
- data/CHANGELOG.md +16 -0
- data/README.md +25 -18
- data/features/chef/cli/show.feature +65 -0
- data/features/support/env.rb +5 -1
- data/lib/librarian/action/clean.rb +0 -12
- data/lib/librarian/action/install.rb +1 -1
- data/lib/librarian/chef/manifest_reader.rb +47 -0
- data/lib/librarian/chef/source/local.rb +51 -3
- data/lib/librarian/chef/source/site.rb +318 -109
- data/lib/librarian/cli.rb +24 -9
- data/lib/librarian/cli/manifest_presenter.rb +79 -0
- data/lib/librarian/dependency.rb +2 -2
- data/lib/librarian/dsl/target.rb +1 -1
- data/lib/librarian/environment.rb +4 -3
- data/lib/librarian/manifest.rb +38 -24
- data/lib/librarian/manifest_set.rb +36 -20
- data/lib/librarian/mock/source/mock.rb +33 -21
- data/lib/librarian/resolution.rb +11 -0
- data/lib/librarian/source/git.rb +14 -2
- data/lib/librarian/source/git/repository.rb +79 -58
- data/lib/librarian/source/local.rb +19 -5
- data/lib/librarian/source/path.rb +13 -1
- data/lib/librarian/specfile.rb +1 -1
- data/lib/librarian/version.rb +1 -1
- data/librarian.gemspec +1 -1
- data/spec/unit/action/clean_spec.rb +0 -31
- data/spec/unit/action/install_spec.rb +7 -3
- data/spec/unit/dsl_spec.rb +14 -0
- data/spec/unit/manifest_set_spec.rb +202 -0
- data/spec/unit/resolver_spec.rb +36 -16
- data/spec/unit/source/git_spec.rb +29 -0
- metadata +28 -25
- data/lib/librarian/chef/manifest.rb +0 -43
- data/lib/librarian/chef/source/local/manifest.rb +0 -82
- data/lib/librarian/chef/source/site/manifest.rb +0 -94
data/lib/librarian/resolution.rb
CHANGED
@@ -1,4 +1,15 @@
|
|
1
1
|
module Librarian
|
2
|
+
#
|
3
|
+
# Represents the output of the resolution process. Captures the declared
|
4
|
+
# dependencies plus the full set of resolved manifests. The sources are
|
5
|
+
# already known by the dependencies and by the resolved manifests, so they do
|
6
|
+
# not need to be captured explicitly.
|
7
|
+
#
|
8
|
+
# This representation may be produced by the resolver, may be serialized into
|
9
|
+
# a lockfile, and may be deserialized from a lockfile. It is expected that the
|
10
|
+
# lockfile is a direct representation in text of this representation, so that
|
11
|
+
# the serialization-deserialization process is just the identity function.
|
12
|
+
#
|
2
13
|
class Resolution
|
3
14
|
attr_reader :dependencies, :manifests, :manifests_index
|
4
15
|
|
data/lib/librarian/source/git.rb
CHANGED
@@ -12,13 +12,25 @@ module Librarian
|
|
12
12
|
include Local
|
13
13
|
|
14
14
|
class << self
|
15
|
+
|
15
16
|
LOCK_NAME = 'GIT'
|
17
|
+
|
16
18
|
def lock_name
|
17
19
|
LOCK_NAME
|
18
20
|
end
|
21
|
+
|
19
22
|
def from_lock_options(environment, options)
|
20
23
|
new(environment, options[:remote], options.reject{|k, v| k == :remote})
|
21
24
|
end
|
25
|
+
|
26
|
+
def from_spec_args(environment, uri, options)
|
27
|
+
recognized_options = [:ref, :path]
|
28
|
+
unrecognized_options = options.keys - recognized_options
|
29
|
+
unrecognized_options.empty? or raise Error, "unrecognized options: #{unrecognized_options.join(", ")}"
|
30
|
+
|
31
|
+
new(environment, uri, options)
|
32
|
+
end
|
33
|
+
|
22
34
|
end
|
23
35
|
|
24
36
|
DEFAULTS = {
|
@@ -29,7 +41,7 @@ module Librarian
|
|
29
41
|
private :environment=
|
30
42
|
attr_reader :uri, :ref, :sha, :path
|
31
43
|
|
32
|
-
def initialize(environment, uri, options
|
44
|
+
def initialize(environment, uri, options)
|
33
45
|
self.environment = environment
|
34
46
|
@uri = uri
|
35
47
|
@ref = options[:ref] || DEFAULTS[:ref]
|
@@ -73,7 +85,7 @@ module Librarian
|
|
73
85
|
@sha = nil
|
74
86
|
end
|
75
87
|
|
76
|
-
def cache!(
|
88
|
+
def cache!(names)
|
77
89
|
unless repository.git?
|
78
90
|
repository.path.rmtree if repository.path.exist?
|
79
91
|
repository.path.mkpath
|
@@ -15,18 +15,40 @@ module Librarian
|
|
15
15
|
git.clone!(repository_url)
|
16
16
|
git
|
17
17
|
end
|
18
|
+
|
19
|
+
def bin
|
20
|
+
@bin ||= which("git") or raise Error, "cannot find git"
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Cross-platform way of finding an executable in the $PATH.
|
26
|
+
#
|
27
|
+
# which('ruby') #=> /usr/bin/ruby
|
28
|
+
#
|
29
|
+
# From:
|
30
|
+
# https://github.com/defunkt/hub/commit/353031307e704d860826fc756ff0070be5e1b430#L2R173
|
31
|
+
def which(cmd)
|
32
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
33
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
34
|
+
path = File.expand_path(path)
|
35
|
+
exts.each do |ext|
|
36
|
+
exe = File.join(path, cmd + ext)
|
37
|
+
return exe if File.executable?(exe)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
nil
|
41
|
+
end
|
18
42
|
end
|
19
43
|
|
20
44
|
include Helpers::Debug
|
21
45
|
|
22
|
-
attr_accessor :environment
|
23
|
-
private :environment=
|
24
|
-
attr_reader :path
|
46
|
+
attr_accessor :environment, :path
|
47
|
+
private :environment=, :path=
|
25
48
|
|
26
49
|
def initialize(environment, path)
|
27
50
|
self.environment = environment
|
28
|
-
path = Pathname.new(path)
|
29
|
-
@path = path
|
51
|
+
self.path = Pathname.new(path)
|
30
52
|
end
|
31
53
|
|
32
54
|
def git?
|
@@ -38,57 +60,45 @@ module Librarian
|
|
38
60
|
end
|
39
61
|
|
40
62
|
def clone!(repository_url)
|
41
|
-
|
42
|
-
|
43
|
-
run!(command)
|
44
|
-
end
|
63
|
+
command = %W(clone #{repository_url} . --quiet)
|
64
|
+
run!(command, :chdir => true)
|
45
65
|
end
|
46
66
|
|
47
67
|
def checkout!(reference, options ={ })
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
run!(command)
|
52
|
-
end
|
68
|
+
command = %W(checkout #{reference} --quiet)
|
69
|
+
command << "--force" if options[:force]
|
70
|
+
run!(command, :chdir => true)
|
53
71
|
end
|
54
72
|
|
55
73
|
def fetch!(remote, options = { })
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
run!(command)
|
60
|
-
end
|
74
|
+
command = %W(fetch #{remote} --quiet)
|
75
|
+
command << "--tags" if options[:tags]
|
76
|
+
run!(command, :chdir => true)
|
61
77
|
end
|
62
78
|
|
63
79
|
def reset_hard!
|
64
|
-
|
65
|
-
|
66
|
-
run!(command)
|
67
|
-
end
|
80
|
+
command = %W(reset --hard --quiet)
|
81
|
+
run!(command, :chdir => true)
|
68
82
|
end
|
69
83
|
|
70
84
|
def remote_names
|
71
|
-
|
72
|
-
|
73
|
-
run!(command, false).strip.lines.map(&:strip)
|
74
|
-
end
|
85
|
+
command = %W(remote)
|
86
|
+
run!(command, :chdir => true).strip.lines.map(&:strip)
|
75
87
|
end
|
76
88
|
|
77
89
|
def remote_branch_names
|
78
90
|
remotes = remote_names.sort_by(&:length).reverse
|
79
91
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end]
|
91
|
-
end
|
92
|
+
command = %W(branch -r)
|
93
|
+
names = run!(command, :chdir => true).strip.lines.map(&:strip).to_a
|
94
|
+
names.each{|n| n.gsub!(/\s*->.*$/, "")}
|
95
|
+
names.reject!{|n| n =~ /\/HEAD$/}
|
96
|
+
Hash[remotes.map do |r|
|
97
|
+
matching_names = names.select{|n| n.start_with?("#{r}/")}
|
98
|
+
matching_names.each{|n| names.delete(n)}
|
99
|
+
matching_names.each{|n| n.slice!(0, r.size + 1)}
|
100
|
+
[r, matching_names]
|
101
|
+
end]
|
92
102
|
end
|
93
103
|
|
94
104
|
def hash_from(remote, reference)
|
@@ -97,34 +107,45 @@ module Librarian
|
|
97
107
|
reference = "#{remote}/#{reference}"
|
98
108
|
end
|
99
109
|
|
100
|
-
|
101
|
-
|
102
|
-
run!(command).strip
|
103
|
-
end
|
110
|
+
command = %W(rev-parse #{reference} --quiet)
|
111
|
+
run!(command, :chdir => true).strip
|
104
112
|
end
|
105
113
|
|
106
114
|
def current_commit_hash
|
107
|
-
|
108
|
-
|
109
|
-
run!(command).strip!
|
110
|
-
end
|
115
|
+
command = %W(rev-parse HEAD --quiet)
|
116
|
+
run!(command, :chdir => true).strip!
|
111
117
|
end
|
118
|
+
|
112
119
|
private
|
113
120
|
|
114
|
-
def
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
+
def bin
|
122
|
+
self.class.bin
|
123
|
+
end
|
124
|
+
|
125
|
+
def run!(args, options = { })
|
126
|
+
chdir = options.delete(:chdir)
|
127
|
+
chdir = path.to_s if chdir == true
|
128
|
+
|
129
|
+
command = [bin]
|
130
|
+
command.concat(args)
|
131
|
+
|
132
|
+
maybe_within(chdir) do
|
133
|
+
debug { "Running `#{command.join(' ')}` in #{relative_path_to(Dir.pwd)}" }
|
134
|
+
out = Open3.popen3(*command) do |i, o, e, t|
|
135
|
+
raise StandardError, e.read unless (t ? t.value : $?).success?
|
136
|
+
o.read
|
137
|
+
end
|
138
|
+
debug { " -> #{out}" } if out.size > 0
|
139
|
+
out
|
121
140
|
end
|
122
|
-
debug { " -> #{out}" } if out.size > 0
|
123
|
-
out
|
124
141
|
end
|
125
142
|
|
126
|
-
def
|
127
|
-
|
143
|
+
def maybe_within(path)
|
144
|
+
if path
|
145
|
+
Dir.chdir(path) { yield }
|
146
|
+
else
|
147
|
+
yield
|
148
|
+
end
|
128
149
|
end
|
129
150
|
|
130
151
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'librarian/helpers/debug'
|
1
2
|
require 'librarian/support/abstract_method'
|
2
3
|
|
3
4
|
module Librarian
|
@@ -7,27 +8,40 @@ module Librarian
|
|
7
8
|
# #environment
|
8
9
|
module Local
|
9
10
|
|
11
|
+
include Helpers::Debug
|
10
12
|
include Support::AbstractMethod
|
11
13
|
|
12
14
|
abstract_method :path
|
13
15
|
|
14
|
-
def manifests(
|
15
|
-
manifest =
|
16
|
+
def manifests(name)
|
17
|
+
manifest = Manifest.new(self, name)
|
16
18
|
[manifest].compact
|
17
19
|
end
|
18
20
|
|
19
21
|
def manifest(name, version, dependencies)
|
20
|
-
manifest =
|
22
|
+
manifest = Manifest.new(self, name)
|
21
23
|
manifest.version = version
|
22
24
|
manifest.dependencies = dependencies
|
23
25
|
manifest
|
24
26
|
end
|
25
27
|
|
26
|
-
def manifest_search_paths(
|
27
|
-
paths = [filesystem_path, filesystem_path.join(
|
28
|
+
def manifest_search_paths(name)
|
29
|
+
paths = [filesystem_path, filesystem_path.join(name)]
|
28
30
|
paths.select{|s| s.exist?}
|
29
31
|
end
|
30
32
|
|
33
|
+
def found_path(name)
|
34
|
+
@_found_paths ||= { }
|
35
|
+
@_found_paths[name] ||= begin
|
36
|
+
paths = manifest_search_paths(name)
|
37
|
+
paths.find{|p| manifest?(name, p)}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
abstract_method :manifest? # (name, path) -> boolean
|
44
|
+
|
31
45
|
end
|
32
46
|
end
|
33
47
|
end
|
@@ -7,13 +7,25 @@ module Librarian
|
|
7
7
|
include Local
|
8
8
|
|
9
9
|
class << self
|
10
|
+
|
10
11
|
LOCK_NAME = 'PATH'
|
12
|
+
|
11
13
|
def lock_name
|
12
14
|
LOCK_NAME
|
13
15
|
end
|
16
|
+
|
14
17
|
def from_lock_options(environment, options)
|
15
18
|
new(environment, options[:remote], options.reject{|k, v| k == :remote})
|
16
19
|
end
|
20
|
+
|
21
|
+
def from_spec_args(environment, path, options)
|
22
|
+
recognized_options = []
|
23
|
+
unrecognized_options = options.keys - recognized_options
|
24
|
+
unrecognized_options.empty? or raise Error, "unrecognized options: #{unrecognized_options.join(", ")}"
|
25
|
+
|
26
|
+
new(environment, path, options)
|
27
|
+
end
|
28
|
+
|
17
29
|
end
|
18
30
|
|
19
31
|
attr_accessor :environment
|
@@ -50,7 +62,7 @@ module Librarian
|
|
50
62
|
def unpin!
|
51
63
|
end
|
52
64
|
|
53
|
-
def cache!(
|
65
|
+
def cache!(names)
|
54
66
|
end
|
55
67
|
|
56
68
|
def filesystem_path
|
data/lib/librarian/specfile.rb
CHANGED
data/lib/librarian/version.rb
CHANGED
data/librarian.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_dependency "thor"
|
22
|
+
s.add_dependency "thor", "~> 0.15"
|
23
23
|
|
24
24
|
s.add_development_dependency "rake"
|
25
25
|
s.add_development_dependency "rspec"
|
@@ -22,7 +22,6 @@ module Librarian
|
|
22
22
|
|
23
23
|
before do
|
24
24
|
action.stub(:clean_install_path)
|
25
|
-
action.stub(:clean_lockfile_path)
|
26
25
|
end
|
27
26
|
|
28
27
|
context "when the cache path is missing" do
|
@@ -51,7 +50,6 @@ module Librarian
|
|
51
50
|
|
52
51
|
before do
|
53
52
|
action.stub(:clean_cache_path)
|
54
|
-
action.stub(:clean_lockfile_path)
|
55
53
|
end
|
56
54
|
|
57
55
|
context "when the install path is missing" do
|
@@ -96,35 +94,6 @@ module Librarian
|
|
96
94
|
|
97
95
|
end
|
98
96
|
|
99
|
-
describe "clearing the lockfile path" do
|
100
|
-
|
101
|
-
before do
|
102
|
-
action.stub(:clean_cache_path)
|
103
|
-
action.stub(:clean_install_path)
|
104
|
-
end
|
105
|
-
|
106
|
-
context "when the lockfile path is missing" do
|
107
|
-
before do
|
108
|
-
env.stub_chain(:lockfile_path, :exist?) { false }
|
109
|
-
end
|
110
|
-
|
111
|
-
it "should not try to clear the lockfile path" do
|
112
|
-
env.lockfile_path.should_receive(:rmtree).never
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
context "when the lockfile path is present" do
|
117
|
-
before do
|
118
|
-
env.stub_chain(:lockfile_path, :exist?) { true }
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should try to clear the lockfile path" do
|
122
|
-
env.lockfile_path.should_receive(:rmtree).exactly(:once)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
127
|
-
|
128
97
|
end
|
129
98
|
|
130
99
|
end
|
@@ -63,8 +63,12 @@ module Librarian
|
|
63
63
|
|
64
64
|
describe "performing the install" do
|
65
65
|
|
66
|
-
|
67
|
-
|
66
|
+
def mock_manifest(i)
|
67
|
+
double(:name => "manifest-#{i}")
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:manifests) { 3.times.map{|i| mock_manifest(i)} }
|
71
|
+
let(:sorted_manifests) { 4.times.map{|i| mock_manifest(i + 3)} }
|
68
72
|
let(:install_path) { mock }
|
69
73
|
|
70
74
|
before do
|
@@ -83,7 +87,7 @@ module Librarian
|
|
83
87
|
sorted_manifests.each do |manifest|
|
84
88
|
source = mock
|
85
89
|
manifest.stub(:source) { source }
|
86
|
-
source.should_receive(:cache!).with([manifest]).exactly(:once).ordered
|
90
|
+
source.should_receive(:cache!).with([manifest.name]).exactly(:once).ordered
|
87
91
|
end
|
88
92
|
|
89
93
|
install_path.stub(:exist?) { false }
|
data/spec/unit/dsl_spec.rb
CHANGED
@@ -174,6 +174,20 @@ module Librarian
|
|
174
174
|
|
175
175
|
end
|
176
176
|
|
177
|
+
context "validating source options" do
|
178
|
+
|
179
|
+
it "should raise when given unrecognized optiosn options" do
|
180
|
+
expect do
|
181
|
+
env.dsl do
|
182
|
+
dep 'dependency-1',
|
183
|
+
:src => 'source-1',
|
184
|
+
:huh => 'yikes'
|
185
|
+
end
|
186
|
+
end.to raise_error(Error, %{unrecognized options: huh})
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
177
191
|
end
|
178
192
|
|
179
193
|
end
|