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.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +10 -0
  5. data/CHANGELOG.md +255 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +235 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +55 -0
  10. data/Rakefile +28 -0
  11. data/VERSION +1 -0
  12. data/lib/librarian/action/base.rb +24 -0
  13. data/lib/librarian/action/clean.rb +44 -0
  14. data/lib/librarian/action/ensure.rb +24 -0
  15. data/lib/librarian/action/install.rb +95 -0
  16. data/lib/librarian/action/persist_resolution_mixin.rb +51 -0
  17. data/lib/librarian/action/resolve.rb +46 -0
  18. data/lib/librarian/action/update.rb +44 -0
  19. data/lib/librarian/action.rb +5 -0
  20. data/lib/librarian/algorithms.rb +133 -0
  21. data/lib/librarian/cli/manifest_presenter.rb +89 -0
  22. data/lib/librarian/cli.rb +225 -0
  23. data/lib/librarian/config/database.rb +205 -0
  24. data/lib/librarian/config/file_source.rb +47 -0
  25. data/lib/librarian/config/hash_source.rb +33 -0
  26. data/lib/librarian/config/source.rb +149 -0
  27. data/lib/librarian/config.rb +7 -0
  28. data/lib/librarian/dependency.rb +153 -0
  29. data/lib/librarian/dsl/receiver.rb +42 -0
  30. data/lib/librarian/dsl/target.rb +171 -0
  31. data/lib/librarian/dsl.rb +102 -0
  32. data/lib/librarian/environment/runtime_cache.rb +101 -0
  33. data/lib/librarian/environment.rb +230 -0
  34. data/lib/librarian/error.rb +4 -0
  35. data/lib/librarian/helpers.rb +29 -0
  36. data/lib/librarian/linter/source_linter.rb +55 -0
  37. data/lib/librarian/lockfile/compiler.rb +66 -0
  38. data/lib/librarian/lockfile/parser.rb +123 -0
  39. data/lib/librarian/lockfile.rb +29 -0
  40. data/lib/librarian/logger.rb +46 -0
  41. data/lib/librarian/manifest.rb +146 -0
  42. data/lib/librarian/manifest_set.rb +150 -0
  43. data/lib/librarian/mock/cli.rb +19 -0
  44. data/lib/librarian/mock/dsl.rb +15 -0
  45. data/lib/librarian/mock/environment.rb +21 -0
  46. data/lib/librarian/mock/extension.rb +9 -0
  47. data/lib/librarian/mock/source/mock/registry.rb +83 -0
  48. data/lib/librarian/mock/source/mock.rb +80 -0
  49. data/lib/librarian/mock/source.rb +1 -0
  50. data/lib/librarian/mock/version.rb +5 -0
  51. data/lib/librarian/mock.rb +1 -0
  52. data/lib/librarian/posix.rb +129 -0
  53. data/lib/librarian/resolution.rb +46 -0
  54. data/lib/librarian/resolver/implementation.rb +238 -0
  55. data/lib/librarian/resolver.rb +94 -0
  56. data/lib/librarian/rspec/support/cli_macro.rb +120 -0
  57. data/lib/librarian/source/basic_api.rb +45 -0
  58. data/lib/librarian/source/git/repository.rb +193 -0
  59. data/lib/librarian/source/git.rb +172 -0
  60. data/lib/librarian/source/local.rb +54 -0
  61. data/lib/librarian/source/path.rb +56 -0
  62. data/lib/librarian/source.rb +2 -0
  63. data/lib/librarian/spec.rb +13 -0
  64. data/lib/librarian/spec_change_set.rb +173 -0
  65. data/lib/librarian/specfile.rb +19 -0
  66. data/lib/librarian/support/abstract_method.rb +21 -0
  67. data/lib/librarian/ui.rb +64 -0
  68. data/lib/librarian/version.rb +3 -0
  69. data/lib/librarian.rb +11 -0
  70. data/librarian.gemspec +47 -0
  71. data/spec/functional/cli_spec.rb +27 -0
  72. data/spec/functional/posix_spec.rb +32 -0
  73. data/spec/functional/source/git/repository_spec.rb +199 -0
  74. data/spec/functional/source/git_spec.rb +174 -0
  75. data/spec/support/fakefs.rb +37 -0
  76. data/spec/support/method_patch_macro.rb +30 -0
  77. data/spec/support/project_path_macro.rb +14 -0
  78. data/spec/support/with_env_macro.rb +22 -0
  79. data/spec/unit/action/base_spec.rb +18 -0
  80. data/spec/unit/action/clean_spec.rb +102 -0
  81. data/spec/unit/action/ensure_spec.rb +37 -0
  82. data/spec/unit/action/install_spec.rb +111 -0
  83. data/spec/unit/algorithms_spec.rb +131 -0
  84. data/spec/unit/config/database_spec.rb +320 -0
  85. data/spec/unit/dependency/requirement_spec.rb +12 -0
  86. data/spec/unit/dependency_spec.rb +212 -0
  87. data/spec/unit/dsl_spec.rb +173 -0
  88. data/spec/unit/environment/runtime_cache_spec.rb +73 -0
  89. data/spec/unit/environment_spec.rb +209 -0
  90. data/spec/unit/lockfile/parser_spec.rb +162 -0
  91. data/spec/unit/lockfile_spec.rb +65 -0
  92. data/spec/unit/manifest/version_spec.rb +11 -0
  93. data/spec/unit/manifest_set_spec.rb +202 -0
  94. data/spec/unit/manifest_spec.rb +36 -0
  95. data/spec/unit/mock/environment_spec.rb +25 -0
  96. data/spec/unit/mock/source/mock_spec.rb +22 -0
  97. data/spec/unit/resolver_spec.rb +299 -0
  98. data/spec/unit/source/git_spec.rb +29 -0
  99. data/spec/unit/spec_change_set_spec.rb +169 -0
  100. 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