Class: Babushka::Dep
- Inherits:
-
Object
- Object
- Babushka::Dep
- Extended by:
- LogHelpers, SuggestHelpers
- Includes:
- LogHelpers, PathHelpers
- Defined in:
- lib/babushka/dep.rb
Defined Under Namespace
Classes: BaseTemplate, Requirement
Instance Attribute Summary (collapse)
-
- (Object) args
readonly
Returns the value of attribute args.
-
- (Object) dep_source
readonly
Returns the value of attribute dep_source.
-
- (Object) load_path
readonly
Returns the value of attribute load_path.
-
- (Object) name
readonly
Returns the value of attribute name.
-
- (Object) opts
readonly
Returns the value of attribute opts.
-
- (Object) params
readonly
Returns the value of attribute params.
-
- (Object) result_message
Returns the value of attribute result_message.
-
- (Object) vars
readonly
Returns the value of attribute vars.
Class Method Summary (collapse)
-
+ (Object) find_or_suggest(dep_name, opts = {}, &block)
Look up the dep specified by dep_name, yielding it to the block if it was found.
Instance Method Summary (collapse)
-
- (Object) basename
Return this dep's name, first removing the template suffix if one is present.
- - (Object) context
-
- (Object) contextual_name
Returns this dep's name, including the source name as a prefix if this dep is in a cloneable source.
- - (Object) defined_info
-
- (Boolean) dep_defined?
Returns true if #define! has aready successfully run on this dep.
-
- (Dep) initialize(name, source, params, opts, block)
constructor
Create a new dep named name within source, whose implementation is found in block.
- - (Object) inspect
-
- (Object) meet(*args)
Entry point for a full met?/meet #process run.
-
- (Boolean) met?(*args)
Entry point for a dry #process run, where only met? blocks will be evaluated.
-
- (Object) process(with_opts = {})
Trigger a dep run with this dep at the top of the tree.
-
- (Object) suffix
Returns the portion of the end of the dep name that looks like a template suffix, if any.
- - (Object) template
- - (Object) with(*args)
Methods included from SuggestHelpers
Methods included from LogHelpers
debug, log, log_block, log_error, log_ok, log_verbose, log_warn
Methods included from PathHelpers
#cd, #in_build_dir, #in_dir, #in_download_dir
Constructor Details
- (Dep) initialize(name, source, params, opts, block)
Create a new dep named name within source, whose implementation is found in block. To define deps yourself, you should call dep (which is Dep::Helpers#dep).
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/babushka/dep.rb', line 42 def initialize name, source, params, opts, block if name.empty? raise InvalidDepName, "Deps can't have empty names." elsif /\A[[:print:]]+\z/i !~ name raise InvalidDepName, "The dep name '#{name}' contains nonprintable characters." elsif /\// =~ name raise InvalidDepName, "The dep name '#{name}' contains '/', which isn't allowed (logs are named after deps, and filenames can't contain '/')." elsif /\:/ =~ name raise InvalidDepName, "The dep name '#{name}' contains ':', which isn't allowed (colons separate dep and template names from source prefixes)." elsif !params.all? {|param| param.is_a?(Symbol) } non_symbol_params = params.reject {|p| p.is_a?(Symbol) } raise DepParameterError, "The dep '#{name}' has #{'a ' if non_symbol_params.length == 1}non-symbol param#{'s' if non_symbol_params.length > 1} #{non_symbol_params.map(&:inspect).to_list}, which #{non_symbol_params.length == 1 ? "isn't" : "aren't"} allowed." else @name = name.to_s @params = params @args = {} @opts = Base.sources.current_load_opts.merge(opts) @block = block @dep_source = source @load_path = Base.sources.current_load_path @dep_source.deps.register self assign_template if Base.sources.current_real_load_source.nil? @dep_defined = @_cached_process = nil # false represents failure for these two. end end |
Instance Attribute Details
- (Object) args (readonly)
Returns the value of attribute args
36 37 38 |
# File 'lib/babushka/dep.rb', line 36 def args @args end |
- (Object) dep_source (readonly)
Returns the value of attribute dep_source
36 37 38 |
# File 'lib/babushka/dep.rb', line 36 def dep_source @dep_source end |
- (Object) load_path (readonly)
Returns the value of attribute load_path
36 37 38 |
# File 'lib/babushka/dep.rb', line 36 def load_path @load_path end |
- (Object) name (readonly)
Returns the value of attribute name
36 37 38 |
# File 'lib/babushka/dep.rb', line 36 def name @name end |
- (Object) opts (readonly)
Returns the value of attribute opts
36 37 38 |
# File 'lib/babushka/dep.rb', line 36 def opts @opts end |
- (Object) params (readonly)
Returns the value of attribute params
36 37 38 |
# File 'lib/babushka/dep.rb', line 36 def params @params end |
- (Object) result_message
Returns the value of attribute result_message
37 38 39 |
# File 'lib/babushka/dep.rb', line 37 def @result_message end |
- (Object) vars (readonly)
Returns the value of attribute vars
36 37 38 |
# File 'lib/babushka/dep.rb', line 36 def vars @vars end |
Class Method Details
+ (Object) find_or_suggest(dep_name, opts = {}, &block)
Look up the dep specified by dep_name, yielding it to the block if it was found.
If no such dep exists, search for other similarly spelt deps and re-call this same method on the one chosen by the user, if any.
88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/babushka/dep.rb', line 88 def self.find_or_suggest dep_name, opts = {}, &block if (dep = Dep(dep_name, opts)).nil? log "#{dep_name.to_s.colorize 'grey'} #{"<- this dep isn't defined!".colorize('red')}" suggestion = suggest_value_for(dep_name, Base.sources.current_names) Dep.find_or_suggest suggestion, opts, &block unless suggestion.nil? elsif block.nil? dep else block.call dep end end |
Instance Method Details
- (Object) basename
Return this dep's name, first removing the template suffix if one is present.
Note that this only removes the suffix when it was used to define the dep. Dep names that end in something that looks like a template suffix, but didn't match a template and result in a templated dep, won't be touched.
Some examples:
Dep('benhoskings:Chromium.app').basename #=> 'Chromium'
Dep('generated report.pdf').basename #=> "generated report.pdf"
124 125 126 |
# File 'lib/babushka/dep.rb', line 124 def basename suffixed? ? name.sub(/\.#{Regexp.escape(template.name)}$/, '') : name end |
- (Object) context
68 69 70 71 |
# File 'lib/babushka/dep.rb', line 68 def context define! if @context.nil? @context end |
- (Object) contextual_name
Returns this dep's name, including the source name as a prefix if this dep is in a cloneable source.
A cloneable source is one that babushka knows how to automatically update; i.e. a source that babushka could have installed itself.
In effect, a cloneable source is one whose deps you prefix when you run them, so this method returns the dep's name in the same form as you would refer to it on the commandline or within a require call in another dep.
109 110 111 |
# File 'lib/babushka/dep.rb', line 109 def contextual_name dep_source.cloneable? ? "#{dep_source.name}:#{name}" : name end |
- (Object) defined_info
448 449 450 451 452 453 454 |
# File 'lib/babushka/dep.rb', line 448 def defined_info if dep_defined? "#{"(#{'un' unless cached_process}met) " if cached?}<- [#{context.requires.join(', ')}]" else "(not defined yet)" end end |
- (Boolean) dep_defined?
Returns true if #define! has aready successfully run on this dep.
79 80 81 |
# File 'lib/babushka/dep.rb', line 79 def dep_defined? @dep_defined end |
- (Object) inspect
444 445 446 |
# File 'lib/babushka/dep.rb', line 444 def inspect "#<Dep:#{object_id} #{"#{dep_source.name}:" unless dep_source.nil?}'#{name}' #{defined_info}>" end |
- (Object) meet(*args)
Entry point for a full met?/meet #process run.
160 161 162 |
# File 'lib/babushka/dep.rb', line 160 def meet *args with(*args).process :dry_run => false, :top_level => true end |
- (Boolean) met?(*args)
Entry point for a dry #process run, where only met? blocks will be evaluated.
This is useful to inspect the current state of a dep tree, without altering the system. It can cause failures, though, because some deps have requirements that need to be met before the dep can perform its met? check.
TODO: In future, there will be support for specifying that in the DSL.
155 156 157 |
# File 'lib/babushka/dep.rb', line 155 def met? *args with(*args).process :dry_run => true, :top_level => true end |
- (Object) process(with_opts = {})
Trigger a dep run with this dep at the top of the tree.
Running the dep involves the following:
-
First, the setup block is run.
-
Next, the dep's dependencies (i.e. the contents of requires) are run recursively by calling #process on each; this dep's #process early-exits if any of the subdeps fail.
-
Next, the met? block is run. If met? returns true, or any true-like value, the dep is already met and there is nothing to do. Otherwise, the dep is unmet, and the following happens:
- The +prepare+ task is run - The +before+ task is run - If +before+ returned a true-like value, the +meet+ task is run. This is where the actual work of achieving the dep's aim is done. - If +meet+ returned a true-like value, the +after+ task is run. - Finally, the +met?+ task is run again, to check whether running +meet+ has achieved the dep's goal.
The final step is important to understand. The meet block is run unconditionally, and its return value is ignored, apart from it determining whether to run the after block. The result of a dep is always taken from its met? block, whether it was already met, unmeetable, or met during the run.
Sometimes there are conditions under which a dep can't be met. For example, if a dep detects that the existing version of a package is broken in some way that requires manual intervention, then there's no use running the meet block. In this circumstance, you can call #unmeetable, which raises an UnmeetableDep exception. Babushka will rescue it and consider the dep unmeetable (that is, it will just allow the dep to fail without attempting to meet it).
The following describes the return values of a few components, and of the dep itself.
-
A '-' means the corresponding block wouldn't be run at all.
-
An 'X' means the corresponding return value doesn't matter, and is discarded.
Initial state | initial met? | meet | subsequent met? | dep returns ----------------+----------------------+-------+-----------------+------------ already met | true | - | - | true unmeetable | UnmeetableDep raised | - | - | false couldn't be met | false | X | false | false met during run | false | X | true | true
Wherever possible, the met? test shouldn't directly test that the meet block performed specific tasks; only that its overall purpose has been achieved. For example, if the purpose of a given dep is to make sure the webserver is running, the contents of the meet block would probably involve `/etc/init.d/nginx start` or similar, on a Linux system at least. In this case, the met? block shouldn't test anything involving `/etc/init.d` directly; instead, it should separately test that the webserver is running, for example by using `netstat` to check that something is listening on port 80.
218 219 220 221 222 223 |
# File 'lib/babushka/dep.rb', line 218 def process with_opts = {} task.opts.update with_opts (cached? ? cached_result : process_and_cache).tap { Base.sources.uncache! if with_opts[:top_level] } end |
- (Object) suffix
Returns the portion of the end of the dep name that looks like a template suffix, if any. Unlike #basename, this method will return anything that looks like a template suffix, even if it doesn't match a template.
131 132 133 |
# File 'lib/babushka/dep.rb', line 131 def suffix name.scan(MetaDep::TEMPLATE_NAME_MATCH).flatten.first end |
- (Object) template
73 74 75 76 |
# File 'lib/babushka/dep.rb', line 73 def template assign_template if @template.nil? @template end |
- (Object) with(*args)
135 136 137 138 139 140 141 142 143 144 |
# File 'lib/babushka/dep.rb', line 135 def with *args @args = if args.map(&:class) == [Hash] parse_named_arguments(args.first) else parse_positional_arguments(args) end.map_values {|k,v| Parameter.for(k, v) } self end |