librarianp 0.1.2
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.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/.travis.yml +10 -0
- data/CHANGELOG.md +255 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +235 -0
- data/LICENSE.txt +22 -0
- data/README.md +55 -0
- data/Rakefile +28 -0
- data/VERSION +1 -0
- data/lib/librarian/action/base.rb +24 -0
- data/lib/librarian/action/clean.rb +44 -0
- data/lib/librarian/action/ensure.rb +24 -0
- data/lib/librarian/action/install.rb +95 -0
- data/lib/librarian/action/persist_resolution_mixin.rb +51 -0
- data/lib/librarian/action/resolve.rb +46 -0
- data/lib/librarian/action/update.rb +44 -0
- data/lib/librarian/action.rb +5 -0
- data/lib/librarian/algorithms.rb +133 -0
- data/lib/librarian/cli/manifest_presenter.rb +89 -0
- data/lib/librarian/cli.rb +225 -0
- data/lib/librarian/config/database.rb +205 -0
- data/lib/librarian/config/file_source.rb +47 -0
- data/lib/librarian/config/hash_source.rb +33 -0
- data/lib/librarian/config/source.rb +149 -0
- data/lib/librarian/config.rb +7 -0
- data/lib/librarian/dependency.rb +153 -0
- data/lib/librarian/dsl/receiver.rb +42 -0
- data/lib/librarian/dsl/target.rb +171 -0
- data/lib/librarian/dsl.rb +102 -0
- data/lib/librarian/environment/runtime_cache.rb +101 -0
- data/lib/librarian/environment.rb +230 -0
- data/lib/librarian/error.rb +4 -0
- data/lib/librarian/helpers.rb +29 -0
- data/lib/librarian/linter/source_linter.rb +55 -0
- data/lib/librarian/lockfile/compiler.rb +66 -0
- data/lib/librarian/lockfile/parser.rb +123 -0
- data/lib/librarian/lockfile.rb +29 -0
- data/lib/librarian/logger.rb +46 -0
- data/lib/librarian/manifest.rb +146 -0
- data/lib/librarian/manifest_set.rb +150 -0
- data/lib/librarian/mock/cli.rb +19 -0
- data/lib/librarian/mock/dsl.rb +15 -0
- data/lib/librarian/mock/environment.rb +21 -0
- data/lib/librarian/mock/extension.rb +9 -0
- data/lib/librarian/mock/source/mock/registry.rb +83 -0
- data/lib/librarian/mock/source/mock.rb +80 -0
- data/lib/librarian/mock/source.rb +1 -0
- data/lib/librarian/mock/version.rb +5 -0
- data/lib/librarian/mock.rb +1 -0
- data/lib/librarian/posix.rb +129 -0
- data/lib/librarian/resolution.rb +46 -0
- data/lib/librarian/resolver/implementation.rb +238 -0
- data/lib/librarian/resolver.rb +94 -0
- data/lib/librarian/rspec/support/cli_macro.rb +120 -0
- data/lib/librarian/source/basic_api.rb +45 -0
- data/lib/librarian/source/git/repository.rb +193 -0
- data/lib/librarian/source/git.rb +172 -0
- data/lib/librarian/source/local.rb +54 -0
- data/lib/librarian/source/path.rb +56 -0
- data/lib/librarian/source.rb +2 -0
- data/lib/librarian/spec.rb +13 -0
- data/lib/librarian/spec_change_set.rb +173 -0
- data/lib/librarian/specfile.rb +19 -0
- data/lib/librarian/support/abstract_method.rb +21 -0
- data/lib/librarian/ui.rb +64 -0
- data/lib/librarian/version.rb +3 -0
- data/lib/librarian.rb +11 -0
- data/librarian.gemspec +47 -0
- data/spec/functional/cli_spec.rb +27 -0
- data/spec/functional/posix_spec.rb +32 -0
- data/spec/functional/source/git/repository_spec.rb +199 -0
- data/spec/functional/source/git_spec.rb +174 -0
- data/spec/support/fakefs.rb +37 -0
- data/spec/support/method_patch_macro.rb +30 -0
- data/spec/support/project_path_macro.rb +14 -0
- data/spec/support/with_env_macro.rb +22 -0
- data/spec/unit/action/base_spec.rb +18 -0
- data/spec/unit/action/clean_spec.rb +102 -0
- data/spec/unit/action/ensure_spec.rb +37 -0
- data/spec/unit/action/install_spec.rb +111 -0
- data/spec/unit/algorithms_spec.rb +131 -0
- data/spec/unit/config/database_spec.rb +320 -0
- data/spec/unit/dependency/requirement_spec.rb +12 -0
- data/spec/unit/dependency_spec.rb +212 -0
- data/spec/unit/dsl_spec.rb +173 -0
- data/spec/unit/environment/runtime_cache_spec.rb +73 -0
- data/spec/unit/environment_spec.rb +209 -0
- data/spec/unit/lockfile/parser_spec.rb +162 -0
- data/spec/unit/lockfile_spec.rb +65 -0
- data/spec/unit/manifest/version_spec.rb +11 -0
- data/spec/unit/manifest_set_spec.rb +202 -0
- data/spec/unit/manifest_spec.rb +36 -0
- data/spec/unit/mock/environment_spec.rb +25 -0
- data/spec/unit/mock/source/mock_spec.rb +22 -0
- data/spec/unit/resolver_spec.rb +299 -0
- data/spec/unit/source/git_spec.rb +29 -0
- data/spec/unit/spec_change_set_spec.rb +169 -0
- metadata +257 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
require "librarian/action/base"
|
2
|
+
|
3
|
+
module Librarian
|
4
|
+
describe Action::Base do
|
5
|
+
|
6
|
+
let(:env) { double }
|
7
|
+
let(:action) { described_class.new(env) }
|
8
|
+
|
9
|
+
subject { action }
|
10
|
+
|
11
|
+
it { should respond_to :environment }
|
12
|
+
|
13
|
+
it "should have the environment that was assigned to it" do
|
14
|
+
expect(action.environment).to be env
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require "librarian/action/clean"
|
2
|
+
|
3
|
+
module Librarian
|
4
|
+
describe Action::Clean do
|
5
|
+
|
6
|
+
let(:env) { double }
|
7
|
+
let(:action) { described_class.new(env) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
action.stub(:debug)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#run" do
|
14
|
+
|
15
|
+
describe "behavior" do
|
16
|
+
|
17
|
+
after do
|
18
|
+
action.run
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "clearing the cache path" do
|
22
|
+
|
23
|
+
before do
|
24
|
+
action.stub(:clean_install_path)
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when the cache path is missing" do
|
28
|
+
before do
|
29
|
+
env.stub_chain(:cache_path, :exist?) { false }
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not try to clear the cache path" do
|
33
|
+
expect(env.cache_path).to receive(:rmtree).never
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when the cache path is present" do
|
38
|
+
before do
|
39
|
+
env.stub_chain(:cache_path, :exist?) { true }
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should try to clear the cache path" do
|
43
|
+
expect(env.cache_path).to receive(:rmtree).exactly(:once)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "clearing the install path" do
|
50
|
+
|
51
|
+
before do
|
52
|
+
action.stub(:clean_cache_path)
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when the install path is missing" do
|
56
|
+
before do
|
57
|
+
env.stub_chain(:install_path, :exist?) { false }
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should not try to clear the install path" do
|
61
|
+
expect(env.install_path).to receive(:children).never
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when the install path is present" do
|
66
|
+
before do
|
67
|
+
env.stub_chain(:install_path, :exist?) { true }
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should try to clear the install path" do
|
71
|
+
children = [double, double, double]
|
72
|
+
children.each do |child|
|
73
|
+
child.stub(:file?) { false }
|
74
|
+
end
|
75
|
+
env.stub_chain(:install_path, :children) { children }
|
76
|
+
|
77
|
+
children.each do |child|
|
78
|
+
expect(child).to receive(:rmtree).exactly(:once)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should only try to clear out directories from the install path, not files" do
|
83
|
+
children = [double(:file? => false), double(:file? => true), double(:file? => true)]
|
84
|
+
env.stub_chain(:install_path, :children) { children }
|
85
|
+
|
86
|
+
children.select(&:file?).each do |child|
|
87
|
+
expect(child).to receive(:rmtree).never
|
88
|
+
end
|
89
|
+
children.reject(&:file?).each do |child|
|
90
|
+
expect(child).to receive(:rmtree).exactly(:once)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "tmpdir"
|
2
|
+
|
3
|
+
require "librarian/error"
|
4
|
+
require "librarian/action/ensure"
|
5
|
+
|
6
|
+
module Librarian
|
7
|
+
describe Action::Ensure do
|
8
|
+
|
9
|
+
let(:env) { double }
|
10
|
+
let(:action) { described_class.new(env) }
|
11
|
+
|
12
|
+
before do
|
13
|
+
env.stub(:specfile_name) { "Specfile" }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#run" do
|
17
|
+
|
18
|
+
context "when the environment does not know its project path" do
|
19
|
+
before { env.stub(:project_path) { nil } }
|
20
|
+
|
21
|
+
it "should raise an error describing that the specfile is mising" do
|
22
|
+
expect { action.run }.to raise_error(Error, "Cannot find Specfile!")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when the environment knows its project path" do
|
27
|
+
before { env.stub(:project_path) { Dir.tmpdir } }
|
28
|
+
|
29
|
+
it "should not raise an error" do
|
30
|
+
expect { action.run }.to_not raise_error
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require "librarian/error"
|
2
|
+
require "librarian/action/install"
|
3
|
+
|
4
|
+
module Librarian
|
5
|
+
describe Action::Install do
|
6
|
+
|
7
|
+
let(:env) { double(:specfile_name => "Specfile", :lockfile_name => "Specfile.lock") }
|
8
|
+
let(:action) { described_class.new(env) }
|
9
|
+
|
10
|
+
describe "#run" do
|
11
|
+
|
12
|
+
describe "behavior" do
|
13
|
+
|
14
|
+
describe "checking preconditions" do
|
15
|
+
|
16
|
+
context "when the specfile is missing" do
|
17
|
+
before do
|
18
|
+
env.stub_chain(:specfile_path, :exist?) { false }
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should raise an error explaining that the specfile is missing" do
|
22
|
+
expect { action.run }.to raise_error(Error, "Specfile missing!")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when the specfile is present but the lockfile is missing" do
|
27
|
+
before do
|
28
|
+
env.stub_chain(:specfile_path, :exist?) { true }
|
29
|
+
env.stub_chain(:lockfile_path, :exist?) { false }
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should raise an error explaining that the lockfile is missing" do
|
33
|
+
expect { action.run }.to raise_error(Error, "Specfile.lock missing!")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when the specfile and lockfile are present but inconsistent" do
|
38
|
+
before do
|
39
|
+
env.stub_chain(:specfile_path, :exist?) { true }
|
40
|
+
env.stub_chain(:lockfile_path, :exist?) { true }
|
41
|
+
action.stub(:spec_consistent_with_lock?) { false }
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should raise an error explaining the inconsistenty" do
|
45
|
+
expect { action.run }.to raise_error(Error, "Specfile and Specfile.lock are out of sync!")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when the specfile and lockfile are present and consistent" do
|
50
|
+
before do
|
51
|
+
env.stub_chain(:specfile_path, :exist?) { true }
|
52
|
+
env.stub_chain(:lockfile_path, :exist?) { true }
|
53
|
+
action.stub(:spec_consistent_with_lock?) { true }
|
54
|
+
action.stub(:perform_installation)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should not raise an error" do
|
58
|
+
expect { action.run }.to_not raise_error
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "performing the install" do
|
65
|
+
|
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)} }
|
72
|
+
let(:install_path) { double }
|
73
|
+
|
74
|
+
before do
|
75
|
+
env.stub(:install_path) { install_path }
|
76
|
+
action.stub(:check_preconditions)
|
77
|
+
action.stub_chain(:lock, :manifests) { manifests }
|
78
|
+
end
|
79
|
+
|
80
|
+
after do
|
81
|
+
action.run
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should sort and install the manifests" do
|
85
|
+
expect(ManifestSet).to receive(:sort).with(manifests).exactly(:once).ordered { sorted_manifests }
|
86
|
+
|
87
|
+
install_path.stub(:exist?) { false }
|
88
|
+
expect(install_path).to receive(:mkpath).exactly(:once).ordered
|
89
|
+
|
90
|
+
sorted_manifests.each do |manifest|
|
91
|
+
expect(manifest).to receive(:install!).exactly(:once).ordered
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should recreate the install path if it already exists" do
|
96
|
+
action.stub(:sorted_manifests) { sorted_manifests }
|
97
|
+
action.stub(:install_manifests)
|
98
|
+
|
99
|
+
install_path.stub(:exist?) { true }
|
100
|
+
expect(install_path).to receive(:rmtree)
|
101
|
+
expect(install_path).to receive(:mkpath)
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require "librarian/algorithms"
|
2
|
+
|
3
|
+
module Librarian
|
4
|
+
module Algorithms
|
5
|
+
|
6
|
+
describe AdjacencyListDirectedGraph do
|
7
|
+
|
8
|
+
describe :cyclic? do
|
9
|
+
subject(:result) { described_class.cyclic?(graph) }
|
10
|
+
|
11
|
+
context "with an empty graph" do
|
12
|
+
let(:graph) { { } }
|
13
|
+
it { should be false }
|
14
|
+
end
|
15
|
+
|
16
|
+
context "with a 1-node acyclic graph" do
|
17
|
+
let(:graph) { { ?a => nil } }
|
18
|
+
it { should be false }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "with a 1-node cyclic graph" do
|
22
|
+
let(:graph) { { ?a => [?a] } }
|
23
|
+
it { should be true }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "with a 2-node no-edge graph" do
|
27
|
+
let(:graph) { { ?a => nil, ?b => nil } }
|
28
|
+
it { should be false }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with a 2-node acyclic graph" do
|
32
|
+
let(:graph) { { ?a => [?b], ?b => nil } }
|
33
|
+
it { should be false }
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with a 2-node cyclic graph" do
|
37
|
+
let(:graph) { { ?a => [?b], ?b => [?a] } }
|
38
|
+
it { should be true }
|
39
|
+
end
|
40
|
+
|
41
|
+
context "with a 2-scc graph" do
|
42
|
+
let(:graph) { { ?a => [?b], ?b => [?a], ?c => [?d, ?b], ?d => [?c] } }
|
43
|
+
it { should be true }
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
describe :feedback_arc_set do
|
49
|
+
subject(:result) { described_class.feedback_arc_set(graph) }
|
50
|
+
|
51
|
+
context "with an empty graph" do
|
52
|
+
let(:graph) { { } }
|
53
|
+
it { should be_empty }
|
54
|
+
end
|
55
|
+
|
56
|
+
context "with a 1-node acyclic graph" do
|
57
|
+
let(:graph) { { ?a => nil } }
|
58
|
+
it { should be_empty }
|
59
|
+
end
|
60
|
+
|
61
|
+
context "with a 1-node cyclic graph" do
|
62
|
+
let(:graph) { { ?a => [?a] } }
|
63
|
+
it { should be == [[?a, ?a]] }
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with a 2-node no-edge graph" do
|
67
|
+
let(:graph) { { ?a => nil, ?b => nil } }
|
68
|
+
it { should be_empty }
|
69
|
+
end
|
70
|
+
|
71
|
+
context "with a 2-node acyclic graph" do
|
72
|
+
let(:graph) { { ?a => [?b], ?b => nil } }
|
73
|
+
it { should be_empty }
|
74
|
+
end
|
75
|
+
|
76
|
+
context "with a 2-node cyclic graph" do
|
77
|
+
let(:graph) { { ?a => [?b], ?b => [?a] } }
|
78
|
+
it { should be == [[?a, ?b]] } # based on the explicit sort
|
79
|
+
end
|
80
|
+
|
81
|
+
context "with a 2-scc graph" do
|
82
|
+
let(:graph) { { ?a => [?b], ?b => [?a], ?c => [?d, ?b], ?d => [?c] } }
|
83
|
+
it { should be == [[?a, ?b], [?c, ?d]] }
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
describe :tsort_cyclic do
|
89
|
+
subject(:result) { described_class.tsort_cyclic(graph) }
|
90
|
+
|
91
|
+
context "with an empty graph" do
|
92
|
+
let(:graph) { { } }
|
93
|
+
it { should be == [] }
|
94
|
+
end
|
95
|
+
|
96
|
+
context "with a 1-node acyclic graph" do
|
97
|
+
let(:graph) { { ?a => nil } }
|
98
|
+
it { should be == [?a] }
|
99
|
+
end
|
100
|
+
|
101
|
+
context "with a 1-node cyclic graph" do
|
102
|
+
let(:graph) { { ?a => [?a] } }
|
103
|
+
it { should be == [?a] }
|
104
|
+
end
|
105
|
+
|
106
|
+
context "with a 2-node no-edge graph" do
|
107
|
+
let(:graph) { { ?a => nil, ?b => nil } }
|
108
|
+
it { should be == [?a, ?b] }
|
109
|
+
end
|
110
|
+
|
111
|
+
context "with a 2-node acyclic graph" do
|
112
|
+
let(:graph) { { ?a => [?b], ?b => nil } }
|
113
|
+
it { should be == [?b, ?a] } # based on the explicit sort
|
114
|
+
end
|
115
|
+
|
116
|
+
context "with a 2-node cyclic graph" do
|
117
|
+
let(:graph) { { ?a => [?b], ?b => [?a] } }
|
118
|
+
it { should be == [?a, ?b] } # based on the explicit sort
|
119
|
+
end
|
120
|
+
|
121
|
+
context "with a 2-scc graph" do
|
122
|
+
let(:graph) { { ?a => [?b], ?b => [?a], ?c => [?d, ?b], ?d => [?c] } }
|
123
|
+
it { should be == [?a, ?b, ?c, ?d] }
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|