Class: Babushka::SourcePool

Inherits:
Object show all
Includes:
LogHelpers
Defined in:
lib/babushka/source_pool.rb

Constant Summary collapse

SEPARATOR =
':'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from LogHelpers

debug, deprecated!, log, log_block, log_error, log_ok, log_stderr, log_warn, removed!

Constructor Details

#initialize(source_opts = {}) ⇒ SourcePool

Returns a new instance of SourcePool.


10
11
12
# File 'lib/babushka/source_pool.rb', line 10

def initialize source_opts = {}
  @source_opts = source_opts
end

Instance Attribute Details

#source_optsObject (readonly)

Returns the value of attribute source_opts


8
9
10
# File 'lib/babushka/source_pool.rb', line 8

def source_opts
  @source_opts
end

Instance Method Details

#all_presentObject


27
28
29
# File 'lib/babushka/source_pool.rb', line 27

def all_present
  default.dup.concat(Source.present)
end

#anonymousObject


31
32
33
# File 'lib/babushka/source_pool.rb', line 31

def anonymous
  @anonymous ||= ImplicitSource.new('anonymous')
end

#coreObject


35
36
37
# File 'lib/babushka/source_pool.rb', line 35

def core
  @core ||= Source.new(Path.path / 'deps', 'core')
end

#current_dirObject


39
40
41
# File 'lib/babushka/source_pool.rb', line 39

def current_dir
  @current_dir ||= Source.new('./babushka-deps', 'current dir')
end

#current_load_optsObject


159
160
161
# File 'lib/babushka/source_pool.rb', line 159

def current_load_opts
  current_load_context[:opts] || {}
end

#current_load_pathObject


154
155
156
157
# File 'lib/babushka/source_pool.rb', line 154

def current_load_path
  path = current_load_context[:path]
  path.p unless path.nil?
end

#current_load_sourceObject


150
151
152
# File 'lib/babushka/source_pool.rb', line 150

def current_load_source
  current_real_load_source || anonymous
end

#current_real_load_sourceObject


146
147
148
# File 'lib/babushka/source_pool.rb', line 146

def current_real_load_source
  current_load_context[:source]
end

#defaultObject


14
15
16
17
18
19
20
21
# File 'lib/babushka/source_pool.rb', line 14

def default
  [
    anonymous, # deps defined at the console, or otherwise not in a source
    core, # the deps bundled with babushka, for self-install
    current_dir, # the deps found in ./babushka-deps when babushka is run
    personal # the deps found in ~/.babushka/deps when babushka is run
  ].freeze
end

#default_namesObject


23
24
25
# File 'lib/babushka/source_pool.rb', line 23

def default_names
  default.map {|source| source.deps.names }.flatten.uniq
end

#dep_for(dep_spec, opts = {}) ⇒ Object

Raises:

  • (ArgumentError)

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/babushka/source_pool.rb', line 72

def dep_for dep_spec, opts = {}
  raise ArgumentError, "The dep spec #{dep_spec.inspect} isn't a String or Dep." unless [String, Dep].include?(dep_spec.class)

  if dep_spec.is_a?(Dep)
    dep_spec
  elsif dep_spec[SEPARATOR] # If a source was specified, that's where we load from.
    source_name, dep_name = dep_spec.split(SEPARATOR, 2)
    source_for(source_name).find(dep_name)
  elsif opts[:from] # Next, try opts[:from], the requiring dep's source.
    opts[:from].find(dep_spec) || dep_for(dep_spec)
  else # Otherwise, try the standard set.
    matches = default.map {|source| source.find(dep_spec) }.flatten.compact
    log_warn "Multiple sources (#{matches.map(&:dep_source).map(&:name).join(',')}) define '#{dep_spec}'; choosing '#{matches.first.full_name}'." if matches.length > 1
    matches.first
  end
end

#find_or_suggest(dep_name, opts = {}, &block) ⇒ Object

Look up the dep specified by dep_name, yielding it to the block if it was found.

If no such dep exists, suggest similarly spelt deps to the user.


60
61
62
63
64
65
66
67
68
69
70
# File 'lib/babushka/source_pool.rb', line 60

def find_or_suggest dep_name, opts = {}, &block
  if (dep = dep_for(dep_name, opts)).nil?
    log_stderr "#{dep_name.to_s.colorize 'grey'} #{"<- this dep isn't defined!".colorize('red')}"
    suggestions = Babushka::Spell.for(dep_name.to_s, choices: default_names)
    log "Perhaps you meant #{suggestions.map {|s| "'#{s}'" }.to_list(:conj => 'or')}?".colorize('grey') if suggestions.any?
  elsif block.nil?
    dep
  else
    block.call(dep)
  end
end

#list!Object


117
118
119
120
121
122
123
124
125
# File 'lib/babushka/source_pool.rb', line 117

def list!
  Logging.log_table(
    ['Name', 'Source path', 'Type', 'Last updated'],
    Source.present.tap {|sources|
      log "There #{sources.length == 1 ? 'is' : 'are'} #{sources.length} source#{'s' unless sources.length == 1} in #{Source.source_prefix}:"
      log ''
    }.map(&:description_pieces)
  )
end

#load_context(context, &block) ⇒ Object


139
140
141
142
143
144
# File 'lib/babushka/source_pool.rb', line 139

def load_context context, &block
  (@load_contexts ||= []).push context
  yield
ensure
  @load_contexts.pop
end

#local_only(&block) ⇒ Object


131
132
133
134
135
136
137
# File 'lib/babushka/source_pool.rb', line 131

def local_only &block
  previously = @local_only
  @local_only = true
  yield
ensure
  @local_only = previously
end

#local_only?Boolean

Returns:

  • (Boolean)

127
128
129
# File 'lib/babushka/source_pool.rb', line 127

def local_only?
  @local_only
end

#personalObject


43
44
45
# File 'lib/babushka/source_pool.rb', line 43

def personal
  @personal ||= Source.new('~/.babushka/deps', 'personal')
end

#source_for(name) ⇒ Object


47
48
49
50
51
52
53
54
# File 'lib/babushka/source_pool.rb', line 47

def source_for name
  (
    all_present.detect {|source| source.name == name } ||
    Source.for_remote(name)
  ).tap {|source|
    source.load!(source_opts[:update])
  }
end

#template_for(template_spec, opts = {}) ⇒ Object


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/babushka/source_pool.rb', line 89

def template_for template_spec, opts = {}
  if template_spec.nil?
    nil
  elsif template_spec[/#{SEPARATOR}/] # If a source was specified, that's where we load from.
    source_name, template_name = template_spec.split(SEPARATOR, 2)
    source_for(source_name).find_template(template_name)
  elsif opts[:from]
    opts[:from].find_template(template_spec) || template_for(template_spec)
  else
    matches = default.map {|source| source.find_template(template_spec) }.flatten.compact
    if matches.length > 1
      log "Multiple sources (#{matches.map(&:source).map(&:name).join(',')}) contain a template called '#{template_spec}'."
    else
      matches.first
    end
  end
end

#update!Object


107
108
109
110
111
112
113
114
115
# File 'lib/babushka/source_pool.rb', line 107

def update!
  all_present.select {|source|
    source.remote?
  }.tap {|sources|
    log "Updating #{sources.length} source#{'s' unless sources.length == 1}."
  }.map {|source|
    source.update!
  }.all?
end