librarian 0.0.20 → 0.0.21

Sign up to get free protection for your applications and to get access to all the features.
@@ -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