librarian 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +4 -0
- data/lib/librarian.rb +5 -178
- data/lib/librarian/action.rb +5 -0
- data/lib/librarian/action/base.rb +22 -0
- data/lib/librarian/action/clean.rb +56 -0
- data/lib/librarian/action/ensure.rb +24 -0
- data/lib/librarian/action/install.rb +101 -0
- data/lib/librarian/action/resolve.rb +81 -0
- data/lib/librarian/action/update.rb +76 -0
- data/lib/librarian/chef/cli.rb +7 -2
- data/lib/librarian/chef/dsl.rb +0 -3
- data/lib/librarian/chef/environment.rb +19 -0
- data/lib/librarian/chef/extension.rb +1 -16
- data/lib/librarian/chef/integration/knife.rb +9 -16
- data/lib/librarian/chef/source/git.rb +0 -2
- data/lib/librarian/chef/source/local.rb +1 -74
- data/lib/librarian/chef/source/local/manifest.rb +82 -0
- data/lib/librarian/chef/source/path.rb +0 -2
- data/lib/librarian/chef/source/site.rb +9 -89
- data/lib/librarian/chef/source/site/manifest.rb +94 -0
- data/lib/librarian/cli.rb +56 -17
- data/lib/librarian/dependency.rb +2 -2
- data/lib/librarian/dsl.rb +15 -5
- data/lib/librarian/dsl/receiver.rb +2 -0
- data/lib/librarian/dsl/target.rb +13 -1
- data/lib/librarian/environment.rb +94 -0
- data/lib/librarian/error.rb +4 -0
- data/lib/librarian/helpers/debug.rb +6 -6
- data/lib/librarian/lockfile.rb +7 -5
- data/lib/librarian/lockfile/compiler.rb +5 -4
- data/lib/librarian/lockfile/parser.rb +6 -5
- data/lib/librarian/manifest.rb +2 -2
- data/lib/librarian/mock/cli.rb +6 -1
- data/lib/librarian/mock/dsl.rb +0 -3
- data/lib/librarian/mock/environment.rb +24 -0
- data/lib/librarian/mock/extension.rb +1 -20
- data/lib/librarian/mock/source/mock.rb +7 -7
- data/lib/librarian/mock/source/mock/registry.rb +16 -12
- data/lib/librarian/resolver.rb +5 -116
- data/lib/librarian/resolver/implementation.rb +117 -0
- data/lib/librarian/source/git.rb +8 -7
- data/lib/librarian/source/git/repository.rb +7 -5
- data/lib/librarian/source/local.rb +1 -1
- data/lib/librarian/source/path.rb +7 -6
- data/lib/librarian/spec_change_set.rb +6 -5
- data/lib/librarian/specfile.rb +10 -4
- data/lib/librarian/version.rb +1 -1
- data/librarian.gemspec +1 -0
- data/spec/functional/chef/source/git_spec.rb +177 -89
- data/spec/functional/chef/source/site_spec.rb +111 -52
- data/spec/unit/action/base_spec.rb +18 -0
- data/spec/unit/action/clean_spec.rb +133 -0
- data/spec/unit/action/ensure_spec.rb +37 -0
- data/spec/unit/action/install_spec.rb +113 -0
- data/spec/unit/dsl_spec.rb +15 -13
- data/spec/unit/environment_spec.rb +9 -0
- data/spec/unit/lockfile_spec.rb +15 -4
- data/spec/unit/mock/source/mock.rb +22 -0
- data/spec/unit/resolver_spec.rb +24 -24
- data/spec/unit/spec_change_set_spec.rb +29 -25
- metadata +47 -19
- data/lib/librarian/chef/particularity.rb +0 -9
- data/lib/librarian/mock/particularity.rb +0 -9
- data/lib/librarian/particularity.rb +0 -7
@@ -0,0 +1,76 @@
|
|
1
|
+
require "librarian/error"
|
2
|
+
require "librarian/manifest_set"
|
3
|
+
require "librarian/resolver"
|
4
|
+
require "librarian/spec_change_set"
|
5
|
+
require "librarian/action/base"
|
6
|
+
|
7
|
+
module Librarian
|
8
|
+
module Action
|
9
|
+
class Update < Base
|
10
|
+
|
11
|
+
def run
|
12
|
+
unless lockfile_path.exist?
|
13
|
+
raise Error, "Lockfile missing!"
|
14
|
+
end
|
15
|
+
previous_resolution = lockfile.load(lockfile_path.read)
|
16
|
+
partial_manifests = ManifestSet.deep_strip(previous_resolution.manifests, dependency_names)
|
17
|
+
spec = specfile.read(previous_resolution.sources)
|
18
|
+
spec_changes = spec_change_set(spec, previous_resolution)
|
19
|
+
raise Error, "Cannot update when the specfile has been changed." unless spec_changes.same?
|
20
|
+
resolution = resolver.resolve(spec, partial_manifests)
|
21
|
+
unless resolution.correct?
|
22
|
+
raise Error, "Could not resolve the dependencies."
|
23
|
+
else
|
24
|
+
lockfile_text = lockfile.save(resolution)
|
25
|
+
debug { "Bouncing #{lockfile_name}" }
|
26
|
+
bounced_lockfile_text = lockfile.save(lockfile.load(lockfile_text))
|
27
|
+
unless bounced_lockfile_text == lockfile_text
|
28
|
+
debug { "lockfile_text: \n#{lockfile_text}"}
|
29
|
+
debug { "bounced_lockfile_text: \n#{bounced_lockfile_text}"}
|
30
|
+
raise Error, "Cannot bounce #{lockfile_name}!"
|
31
|
+
end
|
32
|
+
lockfile_path.open('wb') { |f| f.write(lockfile_text) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def dependency_names
|
39
|
+
options[:names]
|
40
|
+
end
|
41
|
+
|
42
|
+
def specfile_name
|
43
|
+
environment.specfile_name
|
44
|
+
end
|
45
|
+
|
46
|
+
def lockfile_name
|
47
|
+
environment.lockfile_name
|
48
|
+
end
|
49
|
+
|
50
|
+
def specfile_path
|
51
|
+
environment.specfile_path
|
52
|
+
end
|
53
|
+
|
54
|
+
def lockfile_path
|
55
|
+
environment.lockfile_path
|
56
|
+
end
|
57
|
+
|
58
|
+
def specfile
|
59
|
+
environment.specfile
|
60
|
+
end
|
61
|
+
|
62
|
+
def lockfile
|
63
|
+
environment.lockfile
|
64
|
+
end
|
65
|
+
|
66
|
+
def resolver
|
67
|
+
Resolver.new(environment)
|
68
|
+
end
|
69
|
+
|
70
|
+
def spec_change_set(spec, lock)
|
71
|
+
SpecChangeSet.new(environment, spec, lock)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/librarian/chef/cli.rb
CHANGED
@@ -2,19 +2,24 @@ require 'librarian/helpers'
|
|
2
2
|
|
3
3
|
require 'librarian/cli'
|
4
4
|
require 'librarian/chef'
|
5
|
-
require 'librarian/chef/particularity'
|
6
5
|
|
7
6
|
module Librarian
|
8
7
|
module Chef
|
9
8
|
class Cli < Librarian::Cli
|
10
9
|
|
10
|
+
module Particularity
|
11
|
+
def root_module
|
12
|
+
Chef
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
11
16
|
include Particularity
|
12
17
|
extend Particularity
|
13
18
|
|
14
19
|
source_root Pathname.new(__FILE__).dirname.join("templates")
|
15
20
|
|
16
21
|
def init
|
17
|
-
copy_file
|
22
|
+
copy_file environment.specfile_name
|
18
23
|
end
|
19
24
|
|
20
25
|
end
|
data/lib/librarian/chef/dsl.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "librarian/environment"
|
2
|
+
require "librarian/chef/dsl"
|
3
|
+
require "librarian/chef/source"
|
4
|
+
|
5
|
+
module Librarian
|
6
|
+
module Chef
|
7
|
+
class Environment < Environment
|
8
|
+
|
9
|
+
def specfile_name
|
10
|
+
"Cheffile"
|
11
|
+
end
|
12
|
+
|
13
|
+
def install_path
|
14
|
+
project_path.join("cookbooks")
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,24 +1,9 @@
|
|
1
|
-
require 'librarian/
|
2
|
-
require 'librarian/source'
|
3
|
-
require 'librarian/chef/dsl'
|
4
|
-
require 'librarian/chef/source'
|
1
|
+
require 'librarian/chef/environment'
|
5
2
|
|
6
3
|
module Librarian
|
7
4
|
module Chef
|
8
5
|
extend self
|
9
6
|
extend Librarian
|
10
7
|
|
11
|
-
module Overrides
|
12
|
-
def specfile_name
|
13
|
-
'Cheffile'
|
14
|
-
end
|
15
|
-
|
16
|
-
def install_path
|
17
|
-
project_path.join('cookbooks')
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
extend Overrides
|
22
|
-
|
23
8
|
end
|
24
9
|
end
|
@@ -1,13 +1,15 @@
|
|
1
|
+
require 'pathname'
|
1
2
|
require 'securerandom'
|
2
3
|
require 'highline'
|
3
4
|
|
4
5
|
require 'librarian'
|
6
|
+
require 'librarian/action/install'
|
5
7
|
require 'librarian/chef'
|
6
8
|
|
7
9
|
module Librarian
|
8
10
|
module Chef
|
9
11
|
|
10
|
-
|
12
|
+
class Environment
|
11
13
|
def install_path
|
12
14
|
@install_path ||= begin
|
13
15
|
has_home = ENV["HOME"] && File.directory?(ENV["HOME"])
|
@@ -22,28 +24,19 @@ module Librarian
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
raise Error, "#{specfile_name} missing!" unless specfile_path.exist?
|
29
|
-
raise Error, "#{lockfile_name} missing!" unless lockfile_path.exist?
|
27
|
+
def install_path
|
28
|
+
environment.install_path
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
spec = specfile.read(previous_resolution.sources)
|
33
|
-
spec_changes = spec_change_set(spec, previous_resolution)
|
34
|
-
raise Error, "#{specfile_name} and #{lockfile_name} are out of sync!" unless spec_changes.same?
|
31
|
+
hl = HighLine.new
|
35
32
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
33
|
+
begin
|
34
|
+
Action::Install.new(environment).run
|
39
35
|
rescue Error => e
|
40
|
-
hl = HighLine.new
|
41
36
|
message = hl.color(e.message, HighLine::RED)
|
42
37
|
hl.say(message)
|
43
38
|
Process.exit!(1)
|
44
39
|
end
|
45
40
|
|
46
|
-
install_consistent_resolution!
|
47
|
-
|
48
41
|
end
|
49
42
|
end
|
@@ -1,83 +1,10 @@
|
|
1
|
-
require '
|
2
|
-
require 'pathname'
|
3
|
-
|
4
|
-
require 'librarian/chef/manifest'
|
1
|
+
require 'librarian/chef/source/local/manifest'
|
5
2
|
|
6
3
|
module Librarian
|
7
4
|
module Chef
|
8
5
|
module Source
|
9
6
|
module Local
|
10
7
|
|
11
|
-
class Manifest < Manifest
|
12
|
-
|
13
|
-
class << self
|
14
|
-
|
15
|
-
def create(source, dependency, path)
|
16
|
-
new(source, dependency.name, path)
|
17
|
-
end
|
18
|
-
|
19
|
-
def manifest?(dependency, path)
|
20
|
-
path = Pathname.new(path)
|
21
|
-
!!manifest_path(path)
|
22
|
-
end
|
23
|
-
|
24
|
-
def check_manifest(dependency, manifest_path)
|
25
|
-
manifest = read_manifest(dependency.name, manifest_path)
|
26
|
-
manifest["name"] == dependency.name
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
attr_reader :path
|
32
|
-
|
33
|
-
def initialize(source, name, path)
|
34
|
-
super(source, name)
|
35
|
-
@path = Pathname.new(path)
|
36
|
-
@found_path = nil
|
37
|
-
end
|
38
|
-
|
39
|
-
def found_path
|
40
|
-
@found_path ||= source.manifest_search_paths(self).find{|p| self.class.manifest?(self, p)}
|
41
|
-
end
|
42
|
-
|
43
|
-
def manifest
|
44
|
-
@manifest ||= fetch_manifest!
|
45
|
-
end
|
46
|
-
|
47
|
-
def fetch_manifest!
|
48
|
-
expect_manifest
|
49
|
-
|
50
|
-
read_manifest(name, manifest_path(found_path))
|
51
|
-
end
|
52
|
-
|
53
|
-
def fetch_version!
|
54
|
-
manifest['version']
|
55
|
-
end
|
56
|
-
|
57
|
-
def fetch_dependencies!
|
58
|
-
manifest['dependencies']
|
59
|
-
end
|
60
|
-
|
61
|
-
def install!
|
62
|
-
debug { "Installing #{name}-#{version}" }
|
63
|
-
install_path = root_module.install_path.join(name)
|
64
|
-
if install_path.exist?
|
65
|
-
debug { "Deleting #{relative_path_to(install_path)}" }
|
66
|
-
install_path.rmtree
|
67
|
-
end
|
68
|
-
debug { "Copying #{relative_path_to(found_path)} to #{relative_path_to(install_path)}" }
|
69
|
-
FileUtils.cp_r(found_path, install_path)
|
70
|
-
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
def expect_manifest
|
75
|
-
return if found_path && manifest_path(found_path)
|
76
|
-
raise Error, "No metadata file found for #{name} from #{source}! If this should be a cookbook, you might consider contributing a metadata file upstream or forking the cookbook to add your own metadata file."
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
8
|
def manifest_class
|
82
9
|
Manifest
|
83
10
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
require 'librarian/chef/manifest'
|
5
|
+
|
6
|
+
module Librarian
|
7
|
+
module Chef
|
8
|
+
module Source
|
9
|
+
module Local
|
10
|
+
class Manifest < Manifest
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
def create(source, dependency, path)
|
15
|
+
new(source, dependency.name, path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def manifest?(dependency, path)
|
19
|
+
path = Pathname.new(path)
|
20
|
+
!!manifest_path(path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_manifest(dependency, manifest_path)
|
24
|
+
manifest = read_manifest(dependency.name, manifest_path)
|
25
|
+
manifest["name"] == dependency.name
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :path
|
31
|
+
|
32
|
+
def initialize(source, name, path)
|
33
|
+
super(source, name)
|
34
|
+
@path = Pathname.new(path)
|
35
|
+
@found_path = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def found_path
|
39
|
+
@found_path ||= source.manifest_search_paths(self).find{|p| self.class.manifest?(self, p)}
|
40
|
+
end
|
41
|
+
|
42
|
+
def manifest
|
43
|
+
@manifest ||= fetch_manifest!
|
44
|
+
end
|
45
|
+
|
46
|
+
def fetch_manifest!
|
47
|
+
expect_manifest
|
48
|
+
|
49
|
+
read_manifest(name, manifest_path(found_path))
|
50
|
+
end
|
51
|
+
|
52
|
+
def fetch_version!
|
53
|
+
manifest['version']
|
54
|
+
end
|
55
|
+
|
56
|
+
def fetch_dependencies!
|
57
|
+
manifest['dependencies']
|
58
|
+
end
|
59
|
+
|
60
|
+
def install!
|
61
|
+
debug { "Installing #{name}-#{version}" }
|
62
|
+
install_path = environment.install_path.join(name)
|
63
|
+
if install_path.exist?
|
64
|
+
debug { "Deleting #{relative_path_to(install_path)}" }
|
65
|
+
install_path.rmtree
|
66
|
+
end
|
67
|
+
debug { "Copying #{relative_path_to(found_path)} to #{relative_path_to(install_path)}" }
|
68
|
+
FileUtils.cp_r(found_path, install_path)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def expect_manifest
|
74
|
+
return if found_path && manifest_path(found_path)
|
75
|
+
raise Error, "No metadata file found for #{name} from #{source}! If this should be a cookbook, you might consider contributing a metadata file upstream or forking the cookbook to add your own metadata file."
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
require 'librarian/source/path'
|
2
2
|
require 'librarian/chef/source/local'
|
3
|
-
require 'librarian/chef/particularity'
|
4
3
|
|
5
4
|
module Librarian
|
6
5
|
module Chef
|
7
6
|
module Source
|
8
7
|
class Path < Librarian::Source::Path
|
9
|
-
include Particularity
|
10
8
|
include Local
|
11
9
|
end
|
12
10
|
end
|
@@ -7,111 +7,31 @@ require 'digest'
|
|
7
7
|
|
8
8
|
require 'librarian/helpers/debug'
|
9
9
|
|
10
|
-
require 'librarian/manifest'
|
11
|
-
require 'librarian/chef/manifest'
|
12
|
-
require 'librarian/chef/particularity'
|
10
|
+
require 'librarian/chef/source/site/manifest'
|
13
11
|
|
14
12
|
module Librarian
|
15
13
|
module Chef
|
16
14
|
module Source
|
17
15
|
class Site
|
18
16
|
|
19
|
-
class Manifest < Manifest
|
20
|
-
|
21
|
-
attr_reader :version_uri
|
22
|
-
attr_reader :install_path
|
23
|
-
|
24
|
-
def initialize(source, name, version_uri = nil)
|
25
|
-
super(source, name)
|
26
|
-
@version_uri = version_uri
|
27
|
-
|
28
|
-
@cache_path = nil
|
29
|
-
@metadata_cache_path = nil
|
30
|
-
@package_cache_path = nil
|
31
|
-
@install_path = root_module.install_path.join(name)
|
32
|
-
|
33
|
-
@version_metadata = nil
|
34
|
-
@version_manifest = nil
|
35
|
-
end
|
36
|
-
|
37
|
-
def fetch_version!
|
38
|
-
version_metadata['version']
|
39
|
-
end
|
40
|
-
|
41
|
-
def fetch_dependencies!
|
42
|
-
version_manifest['dependencies'].map{|k, v| Dependency.new(k, v, nil)}
|
43
|
-
end
|
44
|
-
|
45
|
-
def version_uri
|
46
|
-
@version_uri ||= begin
|
47
|
-
source.cache!([self])
|
48
|
-
source.manifests(self).find{|m| m.version == version}.version_uri
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def version_uri=(version_uri)
|
53
|
-
@version_uri = version_uri
|
54
|
-
end
|
55
|
-
|
56
|
-
def cache_path
|
57
|
-
@cache_path ||= source.version_cache_path(self, version_uri)
|
58
|
-
end
|
59
|
-
def metadata_cache_path
|
60
|
-
@metadata_cache_path ||= cache_path.join('version.json')
|
61
|
-
end
|
62
|
-
def package_cache_path
|
63
|
-
@package_cache_path ||= cache_path.join('package')
|
64
|
-
end
|
65
|
-
|
66
|
-
def version_metadata
|
67
|
-
@version_metadata ||= fetch_version_metadata!
|
68
|
-
end
|
69
|
-
|
70
|
-
def fetch_version_metadata!
|
71
|
-
source.cache_version_metadata!(self, version_uri)
|
72
|
-
JSON.parse(metadata_cache_path.read)
|
73
|
-
end
|
74
|
-
|
75
|
-
def version_manifest
|
76
|
-
@version_manifest ||= fetch_version_manifest!
|
77
|
-
end
|
78
|
-
|
79
|
-
def fetch_version_manifest!
|
80
|
-
source.cache_version_package!(self, version_uri, version_metadata['file'])
|
81
|
-
manifest_path = manifest_path(package_cache_path)
|
82
|
-
read_manifest(name, manifest_path)
|
83
|
-
end
|
84
|
-
|
85
|
-
def install!
|
86
|
-
debug { "Installing #{self}" }
|
87
|
-
version_manifest # make sure it's cached
|
88
|
-
if install_path.exist?
|
89
|
-
debug { "Deleting #{relative_path_to(install_path)}" }
|
90
|
-
install_path.rmtree
|
91
|
-
end
|
92
|
-
package_cache_path = source.version_package_cache_path(self, version_uri)
|
93
|
-
debug { "Copying #{relative_path_to(package_cache_path)} to #{relative_path_to(install_path)}" }
|
94
|
-
FileUtils.cp_r(package_cache_path, install_path)
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
98
|
-
|
99
17
|
include Helpers::Debug
|
100
|
-
include Particularity
|
101
18
|
|
102
19
|
class << self
|
103
20
|
LOCK_NAME = 'SITE'
|
104
21
|
def lock_name
|
105
22
|
LOCK_NAME
|
106
23
|
end
|
107
|
-
def from_lock_options(options)
|
108
|
-
new(options[:remote], options.reject{|k, v| k == :remote})
|
24
|
+
def from_lock_options(environment, options)
|
25
|
+
new(environment, options[:remote], options.reject{|k, v| k == :remote})
|
109
26
|
end
|
110
27
|
end
|
111
28
|
|
29
|
+
attr_accessor :environment
|
30
|
+
private :environment=
|
112
31
|
attr_reader :uri
|
113
32
|
|
114
|
-
def initialize(uri, options = {})
|
33
|
+
def initialize(environment, uri, options = {})
|
34
|
+
self.environment = environment
|
115
35
|
@uri = uri
|
116
36
|
@cache_path = nil
|
117
37
|
end
|
@@ -156,13 +76,13 @@ module Librarian
|
|
156
76
|
end
|
157
77
|
|
158
78
|
def install_path(dependency)
|
159
|
-
|
79
|
+
environment.install_path.join(dependency.name)
|
160
80
|
end
|
161
81
|
|
162
82
|
def cache_path
|
163
83
|
@cache_path ||= begin
|
164
84
|
dir = Digest::MD5.hexdigest(uri)
|
165
|
-
|
85
|
+
environment.cache_path.join("source/chef/site/#{dir}")
|
166
86
|
end
|
167
87
|
end
|
168
88
|
|