Class: Babushka::Source

Inherits:
Object show all
Extended by:
LogHelpers, PathHelpers, ShellHelpers
Includes:
GitHelpers, LogHelpers, PathHelpers
Defined in:
lib/babushka/source.rb

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from PathHelpers

cd, in_build_dir, in_dir, in_download_dir

Methods included from ShellHelpers

cmd_dir, failable_shell, log_shell, login_shell, raw_shell, shell, shell!, shell?, sudo, which

Methods included from LogHelpers

debug, log, log_block, log_error, log_ok, log_verbose, log_warn

Methods included from GitHelpers

#git

Constructor Details

- (Source) initialize(path, opts = {})

A new instance of Source

Raises:

  • (ArgumentError)


62
63
64
65
66
67
68
69
# File 'lib/babushka/source.rb', line 62

def initialize path, opts = {}
  raise ArgumentError, "Source.new options must be passed as a hash, not as #{opts.inspect}." unless opts.is_a?(Hash)
  @uri, @type = self.class.discover_uri_and_type(path)
  @name = (opts[:name] || self.class.default_name_for_uri(@uri)).to_s
  @deps = DepPool.new self
  @templates = DepPool.new self
  @loaded = @currently_loading = false
end

Instance Attribute Details

- (Object) deps (readonly)

Returns the value of attribute deps



12
13
14
# File 'lib/babushka/source.rb', line 12

def deps
  @deps
end

- (Object) name (readonly)

Returns the value of attribute name



12
13
14
# File 'lib/babushka/source.rb', line 12

def name
  @name
end

- (Object) templates (readonly)

Returns the value of attribute templates



12
13
14
# File 'lib/babushka/source.rb', line 12

def templates
  @templates
end

- (Object) uri (readonly)

Returns the value of attribute uri



12
13
14
# File 'lib/babushka/source.rb', line 12

def uri
  @uri
end

Class Method Details

+ (Object) default_name_for_uri(uri)



54
55
56
57
58
59
60
# File 'lib/babushka/source.rb', line 54

def self.default_name_for_uri uri
  if uri.nil?
    nil
  else
    File.basename(uri.to_s).chomp('.git')
  end
end

+ (Object) default_remote_for(name)



37
38
39
# File 'lib/babushka/source.rb', line 37

def self.default_remote_for name
  "git://github.com/#{name}/babushka-deps.git"
end

+ (Object) discover_uri_and_type(path)



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/babushka/source.rb', line 42

def self.discover_uri_and_type path
  if path.nil?
    [nil, :implicit]
  elsif path.to_s[/^(git|http|file):\/\//]
    [path.to_s, :public]
  elsif path.to_s[/^(\w+@)?[a-zA-Z0-9.\-]+:/]
    [path.to_s, :private]
  else
    [path.p, :local]
  end
end

+ (Object) for_path(path)



24
25
26
27
28
29
30
31
# File 'lib/babushka/source.rb', line 24

def self.for_path path
  remote = cd(path) { shell "git config remote.origin.url" }
  if remote.nil?
    Source.new path # local source
  else
    Source.new remote, :name => path.basename # remote source with custom path
  end
end

+ (Object) for_remote(name)



33
34
35
# File 'lib/babushka/source.rb', line 33

def self.for_remote name
  Source.new(default_remote_for(name), :name => name)
end

+ (Object) present



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

def self.present
  source_prefix.glob('*').map(&:p).select {|path|
    path.directory?
  }.map {|path|
    Source.for_path path
  }.select {|source|
    source.present?
  }
end

Instance Method Details

- (Object) ==(other)



130
131
132
133
134
135
# File 'lib/babushka/source.rb', line 130

def == other
  [:name, :uri, :type].all? {|method_name| other.respond_to? method_name } &&
  name == other.name &&
  uri == other.uri &&
  type == other.type
end

- (Object) add!



137
138
139
140
141
142
143
144
145
146
# File 'lib/babushka/source.rb', line 137

def add!
  if !cloneable?
    log "Nothing to add for #{name}."
  else
    raise_unless_addable!
    log_block "Adding #{name} from #{uri}" do
      update!
    end
  end
end

- (Boolean) cloneable?

Returns:

  • (Boolean)


114
115
116
# File 'lib/babushka/source.rb', line 114

def cloneable?
  [:public, :private].include? type
end

- (Boolean) cloned?

Returns:

  • (Boolean)


117
118
119
# File 'lib/babushka/source.rb', line 117

def cloned?
  File.directory? path / '.git'
end

- (Object) description_pieces



103
104
105
106
107
108
109
110
# File 'lib/babushka/source.rb', line 103

def description_pieces
  [
    name,
    uri.to_s,
    type,
    ("#{updated_at.round.xsecs} ago" if cloneable?)
  ]
end

- (Object) find(dep_spec)



75
76
77
78
# File 'lib/babushka/source.rb', line 75

def find dep_spec
  load!
  deps.for(dep_spec)
end

- (Object) find_template(template_spec)



80
81
82
83
# File 'lib/babushka/source.rb', line 80

def find_template template_spec
  load!
  templates.for(template_spec)
end

- (Boolean) implicit?

Returns:

  • (Boolean)


126
127
128
# File 'lib/babushka/source.rb', line 126

def implicit?
  type == :implicit
end

- (Object) inspect



212
213
214
# File 'lib/babushka/source.rb', line 212

def inspect
  "#<Source:#{object_id} '#{name}' (#{deps.count} dep#{'s' unless deps.count == 1})>"
end

- (Object) load!



148
149
150
151
152
153
154
155
# File 'lib/babushka/source.rb', line 148

def load!
  unless @currently_loading
    @currently_loading = true
    update! if cloneable?
    load_deps! unless implicit? # implicit sources can't be loaded.
    @currently_loading = false
  end
end

- (Object) load_deps!



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/babushka/source.rb', line 157

def load_deps!
  unless @loaded
    path.p.glob('**/*.rb').each {|f|
      Base.sources.load_context :source => self, :path => f do
        begin
          load f
        rescue Exception => e
          log_error "#{e.backtrace.first}: #{e.message}"
          log "Check #{(e.backtrace.detect {|l| l[f] } || f).sub(/\:in [^:]+$/, '')}."
          debug e.backtrace * "\n"
        end
      end
    }
    debug "Loaded #{deps.count} deps from #{path}." unless deps.count.zero?
    @loaded = true
  end
end

- (Boolean) local?

Returns:

  • (Boolean)


123
124
125
# File 'lib/babushka/source.rb', line 123

def local?
  type == :local
end

- (Object) path



88
89
90
91
92
93
94
# File 'lib/babushka/source.rb', line 88

def path
  if implicit? || local?
    @uri
  else
    prefix / name
  end
end

- (Object) prefix



85
86
87
# File 'lib/babushka/source.rb', line 85

def prefix
  self.class.source_prefix
end

- (Boolean) present?

Returns:

  • (Boolean)


120
121
122
# File 'lib/babushka/source.rb', line 120

def present?
  cloneable? ? cloned? : path.exists?
end

- (Object) repo



96
97
98
# File 'lib/babushka/source.rb', line 96

def repo
  @repo ||= GitRepo.new(path) if cloneable?
end

- (Object) type



111
112
113
# File 'lib/babushka/source.rb', line 111

def type
  @type
end

- (Object) update!



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/babushka/source.rb', line 175

def update!
  if @updated
    debug "Already pulled #{name} (#{uri}) this session."
    true
  elsif @updated == false
    debug "Not updating #{name} (#{uri}) - it's offline."
  elsif Base.sources.local_only?
    debug "Not pulling #{name} (#{uri}) - in local-only mode."
    true
  elsif repo.exists? && repo.dirty?
    log "Not updating #{name} (#{path}) because there are local changes."
  elsif repo.exists? && repo.ahead?
    log "Not updating #{name} (#{path}) because it's ahead of origin."
  else
    git(uri, :to => path, :log => true).tap {|result|
      log "Marking #{uri} as offline for this run." unless result
      @updated = result || false
    }
  end
end

- (Object) updated_at



100
101
102
# File 'lib/babushka/source.rb', line 100

def updated_at
  Time.now - File.mtime(path)
end

- (Boolean) uri_matches?(path)

Returns:

  • (Boolean)


71
72
73
# File 'lib/babushka/source.rb', line 71

def uri_matches? path
  self.class.discover_uri_and_type(path).first == uri
end