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.
@@ -9,6 +9,8 @@ require "librarian/ui"
9
9
  module Librarian
10
10
  class Cli < Thor
11
11
 
12
+ autoload :ManifestPresenter, "librarian/cli/manifest_presenter"
13
+
12
14
  include Thor::Actions
13
15
 
14
16
  module Particularity
@@ -50,17 +52,17 @@ module Librarian
50
52
  end
51
53
 
52
54
  desc "clean", "Cleans out the cache and install paths."
53
- method_option "verbose"
54
- method_option "line-numbers"
55
+ option "verbose"
56
+ option "line-numbers"
55
57
  def clean
56
58
  ensure!
57
59
  clean!
58
60
  end
59
61
 
60
62
  desc "install", "Resolves and installs all of the dependencies you specify."
61
- method_option "verbose"
62
- method_option "line-numbers"
63
- method_option "clean"
63
+ option "verbose"
64
+ option "line-numbers"
65
+ option "clean"
64
66
  def install
65
67
  ensure!
66
68
  clean! if options["clean"]
@@ -69,8 +71,8 @@ module Librarian
69
71
  end
70
72
 
71
73
  desc "update", "Updates and installs the dependencies you specify."
72
- method_option "verbose"
73
- method_option "line-numbers"
74
+ option "verbose"
75
+ option "line-numbers"
74
76
  def update(*names)
75
77
  ensure!
76
78
  if names.empty?
@@ -82,8 +84,8 @@ module Librarian
82
84
  end
83
85
 
84
86
  desc "outdated", "Lists outdated dependencies."
85
- method_option "verbose"
86
- method_option "line-numbers"
87
+ option "verbose"
88
+ option "line-numbers"
87
89
  def outdated
88
90
  ensure!
89
91
  resolution = environment.lock
@@ -96,6 +98,15 @@ module Librarian
96
98
  end
97
99
  end
98
100
 
101
+ desc "show", "Shows dependencies"
102
+ option "verbose"
103
+ option "line-numbers"
104
+ option "detailed", :type => :boolean
105
+ def show(*names)
106
+ ensure!
107
+ manifest_presenter.present(names, :detailed => options["detailed"])
108
+ end
109
+
99
110
  desc "init", "Initializes the current directory."
100
111
  def init
101
112
  puts "Nothing to do."
@@ -127,5 +138,9 @@ module Librarian
127
138
  Action::Update.new(environment, options).run
128
139
  end
129
140
 
141
+ def manifest_presenter
142
+ ManifestPresenter.new(self, environment.lock.manifests)
143
+ end
144
+
130
145
  end
131
146
  end
@@ -0,0 +1,79 @@
1
+ module Librarian
2
+ class Cli
3
+ class ManifestPresenter
4
+
5
+ attr_accessor :cli, :manifests
6
+ private :cli=, :manifests=
7
+
8
+ def initialize(cli, manifests)
9
+ self.cli = cli or raise ArgumentError, "cli required"
10
+ self.manifests = manifests or raise ArgumentError, "manifests required"
11
+ self.manifests_index = Hash[manifests.map{|m| [m.name, m]}]
12
+
13
+ self.scope_level = 0
14
+ end
15
+
16
+ def present(names = [], options = { })
17
+ full = options[:detailed]
18
+ full = !names.empty? if full.nil?
19
+
20
+ if names.empty?
21
+ names = manifests.map(&:name).sort if names.empty?
22
+ else
23
+ missing_names = names.reject{|name| manifest(name)}
24
+ unless missing_names.empty?
25
+ raise Error, "not found: #{missing_names.map(&:inspect).join(', ')}"
26
+ end
27
+ end
28
+
29
+ names.each do |name|
30
+ manifest = manifest(name)
31
+ present_one(manifest, :detailed => full)
32
+ end
33
+ end
34
+
35
+ def present_one(manifest, options = { })
36
+ full = options[:detailed]
37
+
38
+ say "#{manifest.name} (#{manifest.version})" do
39
+ if full
40
+ say "source: #{manifest.source}"
41
+ unless manifest.dependencies.empty?
42
+ say "dependencies:" do
43
+ manifest.dependencies.sort_by(&:name).each do |dependency|
44
+ say "#{dependency.name} (#{dependency.requirement})"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ attr_accessor :scope_level, :manifests_index
55
+
56
+ def manifest(name)
57
+ manifests_index[name]
58
+ end
59
+
60
+ def say(string)
61
+ cli.say " " * scope_level << string
62
+ if block_given?
63
+ scope do
64
+ yield
65
+ end
66
+ end
67
+ end
68
+
69
+ def scope
70
+ original_scope_level = scope_level
71
+ self.scope_level = scope_level + 1
72
+ yield
73
+ ensure
74
+ self.scope_level = original_scope_level
75
+ end
76
+
77
+ end
78
+ end
79
+ end
@@ -60,8 +60,8 @@ module Librarian
60
60
  end
61
61
 
62
62
  def cache_manifests!
63
- source.cache!([self])
64
- source.manifests(self)
63
+ source.cache!([name])
64
+ source.manifests(name)
65
65
  end
66
66
 
67
67
  def satisfied_by?(manifest)
@@ -146,7 +146,7 @@ module Librarian
146
146
  def source_from_params(name, param, options)
147
147
  source_cache[[name, param, options]] ||= begin
148
148
  type = source_types_map[name]
149
- type.new(environment, param, options)
149
+ type.from_spec_args(environment, param, options)
150
150
  end
151
151
  end
152
152
 
@@ -8,6 +8,7 @@ require "librarian/lockfile"
8
8
  require "librarian/specfile"
9
9
  require "librarian/resolver"
10
10
  require "librarian/dsl"
11
+ require "librarian/source"
11
12
 
12
13
  module Librarian
13
14
  class Environment
@@ -106,12 +107,12 @@ module Librarian
106
107
  lockfile.read
107
108
  end
108
109
 
109
- def dsl(&block)
110
- dsl_class.run(self, &block)
110
+ def dsl(*args, &block)
111
+ dsl_class.run(self, *args, &block)
111
112
  end
112
113
 
113
114
  def dsl_class
114
- self.class.name.split("::")[0 ... -1].inject(Object) { |constant, fragment| constant.const_get(fragment) }::Dsl
115
+ self.class.name.split("::")[0 ... -1].inject(Object, &:const_get)::Dsl
115
116
  end
116
117
 
117
118
  private
@@ -42,22 +42,17 @@ module Librarian
42
42
  include Support::AbstractMethod
43
43
  include Helpers::Debug
44
44
 
45
- attr_accessor :source, :name
46
- private :source=, :name=
45
+ attr_accessor :source, :name, :extra
46
+ private :source=, :name=, :extra=
47
47
 
48
48
  abstract_method :fetch_version!, :fetch_dependencies!
49
- abstract_method :install!
50
49
 
51
- def initialize(source, name)
50
+ def initialize(source, name, extra = nil)
52
51
  assert_name_valid! name
53
52
 
54
53
  self.source = source
55
54
  self.name = name
56
-
57
- @fetched_version = nil
58
- @defined_version = nil
59
- @fetched_dependencies = nil
60
- @defined_dependencies = nil
55
+ self.extra = extra
61
56
  end
62
57
 
63
58
  def to_s
@@ -65,35 +60,32 @@ module Librarian
65
60
  end
66
61
 
67
62
  def version
68
- @defined_version || @fetched_version ||= _normalize_version(fetch_version!)
63
+ defined_version || fetched_version
69
64
  end
70
65
 
71
66
  def version=(version)
72
- @defined_version = _normalize_version(version)
67
+ self.defined_version = _normalize_version(version)
73
68
  end
74
69
 
75
70
  def version?
76
- if @defined_version
77
- @fetched_version ||= _normalize_version(fetch_version!)
78
- @defined_version == @fetched_version
79
- end
71
+ return unless defined_version
72
+
73
+ defined_version == fetched_version
80
74
  end
81
75
 
82
76
  def dependencies
83
- @defined_dependencies || @fetched_dependencies ||= _normalize_dependencies(fetch_dependencies!)
77
+ defined_dependencies || fetched_dependencies
84
78
  end
85
79
 
86
80
  def dependencies=(dependencies)
87
- @defined_dependencies = _normalize_dependencies(dependencies)
81
+ self.defined_dependencies = _normalize_dependencies(dependencies)
88
82
  end
89
83
 
90
84
  def dependencies?
91
- if @defined_dependencies
92
- @fetched_dependencies ||= _normalize_dependencies(fetch_dependencies!)
93
- @defined_dependencies.zip(@fetched_dependencies).all? do |pair|
94
- a, b = *pair
95
- a.name == b.name && a.requirement == b.requirement
96
- end
85
+ return unless defined_dependencies
86
+
87
+ defined_dependencies.zip(fetched_dependencies).all? do |(a, b)|
88
+ a.name == b.name && a.requirement == b.requirement
97
89
  end
98
90
  end
99
91
 
@@ -101,12 +93,34 @@ module Librarian
101
93
  dependency.requirement.satisfied_by?(version)
102
94
  end
103
95
 
96
+ def install!
97
+ source.install!(self)
98
+ end
99
+
104
100
  private
105
101
 
102
+ attr_accessor :defined_version, :defined_dependencies
103
+
106
104
  def environment
107
105
  source.environment
108
106
  end
109
107
 
108
+ def fetched_version
109
+ @fetched_version ||= _normalize_version(fetch_version!)
110
+ end
111
+
112
+ def fetched_dependencies
113
+ @fetched_dependencies ||= _normalize_dependencies(fetch_dependencies!)
114
+ end
115
+
116
+ def fetch_version!
117
+ source.fetch_version(name, extra)
118
+ end
119
+
120
+ def fetch_dependencies!
121
+ source.fetch_dependencies(name, version, extra)
122
+ end
123
+
110
124
  def _normalize_version(version)
111
125
  Version.new(version)
112
126
  end
@@ -115,7 +129,7 @@ module Librarian
115
129
  if Hash === dependencies
116
130
  dependencies = dependencies.map{|k, v| Dependency.new(k, v, nil)}
117
131
  end
118
- dependencies.sort_by{|d| d.name}
132
+ dependencies.sort_by(&:name)
119
133
  end
120
134
 
121
135
  def assert_name_valid!(name)
@@ -63,6 +63,8 @@ module Librarian
63
63
  end
64
64
 
65
65
  def shallow_strip!(names)
66
+ assert_strings!(names)
67
+
66
68
  names.each do |name|
67
69
  index.delete(name)
68
70
  end
@@ -75,15 +77,11 @@ module Librarian
75
77
 
76
78
  def deep_strip!(names)
77
79
  names = Array === names ? names.dup : names.to_a
78
- until names.empty?
79
- name = names.shift
80
- manifest = index.delete(name)
81
- if manifest
82
- manifest.dependencies.each do |dependency|
83
- names << dependency.name
84
- end
85
- end
86
- end
80
+ assert_strings!(names)
81
+
82
+ strippables = dependencies_of(names)
83
+ shallow_strip!(strippables)
84
+
87
85
  self
88
86
  end
89
87
 
@@ -92,6 +90,8 @@ module Librarian
92
90
  end
93
91
 
94
92
  def shallow_keep!(names)
93
+ assert_strings!(names)
94
+
95
95
  names = Set.new(names) unless Set === names
96
96
  index.reject! { |k, v| !names.include?(k) }
97
97
  self
@@ -103,17 +103,12 @@ module Librarian
103
103
 
104
104
  def deep_keep!(names)
105
105
  names = Array === names ? names.dup : names.to_a
106
- marks = Set.new
107
- until names.empty?
108
- keep = names.shift
109
- unless marks.include?(keep)
110
- marks << keep
111
- index[keep].dependencies.each do |d|
112
- names << d.name
113
- end
114
- end
115
- end
116
- shallow_keep!(marks)
106
+ assert_strings!(names)
107
+
108
+ keepables = dependencies_of(names)
109
+ shallow_keep!(keepables)
110
+
111
+ self
117
112
  end
118
113
 
119
114
  def consistent?
@@ -129,5 +124,26 @@ module Librarian
129
124
 
130
125
  attr_accessor :index
131
126
 
127
+ def assert_strings!(names)
128
+ non_strings = names.reject{|name| String === name}
129
+ non_strings.empty? or raise TypeError, "names must all be strings"
130
+ end
131
+
132
+ # Straightforward breadth-first graph traversal algorithm.
133
+ def dependencies_of(names)
134
+ names = Array === names ? names.dup : names.to_a
135
+ assert_strings!(names)
136
+
137
+ deps = Set.new
138
+ until names.empty?
139
+ name = names.shift
140
+ next if deps.include?(name)
141
+
142
+ deps << name
143
+ names.concat index[name].dependencies.map(&:name)
144
+ end
145
+ deps.to_a
146
+ end
147
+
132
148
  end
133
149
  end
@@ -6,30 +6,26 @@ module Librarian
6
6
  module Source
7
7
  class Mock
8
8
 
9
- class Manifest < Manifest
10
- attr_reader :manifest
11
- def initialize(source, name, manifest)
12
- super(source, name)
13
- @manifest = manifest
14
- end
15
- def fetch_version!
16
- manifest[:version]
17
- end
18
- def fetch_dependencies!
19
- manifest[:dependencies]
20
- end
21
- def install!
22
- end
23
- end
24
-
25
9
  class << self
10
+
26
11
  LOCK_NAME = 'MOCK'
12
+
27
13
  def lock_name
28
14
  LOCK_NAME
29
15
  end
16
+
30
17
  def from_lock_options(environment, options)
31
18
  new(environment, options[:remote], options.reject{|k, v| k == :remote})
32
19
  end
20
+
21
+ def from_spec_args(environment, name, 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, name, options)
27
+ end
28
+
33
29
  end
34
30
 
35
31
  attr_accessor :environment
@@ -64,24 +60,40 @@ module Librarian
64
60
  end
65
61
 
66
62
  def manifest(name, version, dependencies)
67
- Manifest.new(self, name, {:version => version, :dependencies => dependencies})
63
+ manifest = Manifest.new(self, name)
64
+ manifest.version = version
65
+ manifest.dependencies = dependencies
66
+ manifest
68
67
  end
69
68
 
70
- def manifests(dependency)
71
- if d = registry[dependency.name]
72
- d.map{|v| Manifest.new(self, dependency.name, v)}
69
+ def manifests(name)
70
+ if d = registry[name]
71
+ d.map{|v| manifest(name, v[:version], v[:dependencies])}
73
72
  else
74
73
  nil
75
74
  end
76
75
  end
77
76
 
78
- def cache!(dependencies)
77
+ def cache!(names)
78
+ end
79
+
80
+ def install!(manifest)
79
81
  end
80
82
 
81
83
  def to_s
82
84
  name
83
85
  end
84
86
 
87
+ def fetch_version(name, extra)
88
+ extra
89
+ end
90
+
91
+ def fetch_dependencies(name, version, extra)
92
+ d = registry[name]
93
+ m = d.find{|v| v[:version] == version.to_s}
94
+ m[:dependencies]
95
+ end
96
+
85
97
  end
86
98
  end
87
99
  end