Class: Vendorificator::Environment

Inherits:
Object
  • Object
show all
Defined in:
lib/vendorificator/environment.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(shell, verbosity = :default, vendorfile = nil, &block) ⇒ Environment

Returns a new instance of Environment.



10
11
12
13
14
15
16
17
18
# File 'lib/vendorificator/environment.rb', line 10

def initialize(shell, verbosity = :default, vendorfile = nil, &block)
  @segments = []
  @io = IOProxy.new(shell, verbosity)
  @vendorfile = find_vendorfile(vendorfile)
  @vendor_block = block

  @config = Vendorificator::Config.new
  @config.environment = self
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



7
8
9
# File 'lib/vendorificator/environment.rb', line 7

def config
  @config
end

#ioObject

Returns the value of attribute io.



8
9
10
# File 'lib/vendorificator/environment.rb', line 8

def io
  @io
end

#segmentsObject

Returns the value of attribute segments.



8
9
10
# File 'lib/vendorificator/environment.rb', line 8

def segments
  @segments
end

Instance Method Details

#[](name) ⇒ Object

Public: Returns module with given name



245
246
247
# File 'lib/vendorificator/environment.rb', line 245

def [](name)
  segments.find { |v| v.name == name }
end

#clean?Boolean

Public: Checks if the repository is clean.

Returns boolean answer to the question.

Returns:

  • (Boolean)


218
219
220
221
222
223
224
225
226
# File 'lib/vendorificator/environment.rb', line 218

def clean?
  # copy code from http://stackoverflow.com/a/3879077/16390
  git.update_index '-q', '--ignore-submodules', '--refresh'
  git.diff_files '--quiet', '--ignore-submodules', '--'
  git.diff_index '--cached', '--quiet', 'HEAD', '--ignore-submodules', '--'
  true
rescue MiniGit::GitError
  false
end

#current_branchObject



42
43
44
# File 'lib/vendorificator/environment.rb', line 42

def current_branch
  git.capturing.rev_parse({:abbrev_ref => true}, 'HEAD').strip
end

#each_segment(*segments) ⇒ Object

Public: Goes through all the Vendor instances and runs the block

segments - An Array of vendor segments to yield the block for.

Returns nothing.



202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/vendorificator/environment.rb', line 202

def each_segment(*segments)
  # We don't use @segments.each here, because Vendor#run! is
  # explicitly allowed to append to instantiate new dependencies, and #each
  # fails to catch up on some Ruby implementations.
  i = 0
  while true
    break if i >= @segments.length
    mod = @segments[i]
    yield mod if segments.empty? || mod.included_in_list?(segments)
    i += 1
  end
end

#fast_forwardable?(to, from) ⇒ Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/vendorificator/environment.rb', line 46

def fast_forwardable?(to, from)
  git.capturing.merge_base(to, from).strip == from
end

#gitObject

Main MiniGit instance



33
34
35
# File 'lib/vendorificator/environment.rb', line 33

def git
  @git ||= MiniGit::new(config[:vendorfile_path])
end

#info(mod_name, options = {}) ⇒ Object

Public: Displays info about the last merged version of module.

mod - String with the module name options - Hash containing options

Returns nothing.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/vendorificator/environment.rb', line 118

def info(mod_name, options = {})
  load_vendorfile

  if vendor = find_module_by_name(mod_name)
    say :default, "Module name: #{vendor.name}\n"
    say :default, "Module group: #{vendor.group}\n"
    say :default, "Module merged version: #{vendor.merged_version}\n"
    say :default, "Module merged notes: #{vendor.merged_notes.ai}\n"
  elsif (commit = Commit.new(mod_name, git)).exists?
    say :default, "Branches that contain this commit: #{commit.branches.join(', ')}\n"
    say :default, "Vendorificator notes on this commit: #{commit.notes.ai}\n"
  else
    say :default, "Module or ref #{mod_name.inspect} not found."
  end
end

#listObject

Public: Displays info about current segments.

Returns nothing.



137
138
139
140
141
142
143
# File 'lib/vendorificator/environment.rb', line 137

def list
  load_vendorfile

  each_segment do |mod|
    shell.say "Module: #{mod.name}, version: #{mod.version}"
  end
end

#load_vendorfileObject

Public: Loads the vendorfile.

Returns nothing.

Raises:

  • (RuntimeError)


252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/vendorificator/environment.rb', line 252

def load_vendorfile
  raise RuntimeError, 'Vendorfile has been already loaded!' if @vendorfile_loaded

  if @vendorfile
    @config.read_file @vendorfile.to_s
  else
    raise MissingVendorfileError unless @vendor_block
  end
  @config.instance_eval(&@vendor_block) if @vendor_block

  each_segment{ |mod| mod.compute_dependencies! }

  @vendorfile_loaded = true
end

#metadata_snapshotObject



228
229
230
231
232
233
234
235
# File 'lib/vendorificator/environment.rb', line 228

def 
  {
    :vendorificator_version => ::Vendorificator::VERSION,
    :current_branch => git.capturing.rev_parse({:abbrev_ref => true}, 'HEAD').strip,
    :current_sha => git.capturing.rev_parse('HEAD').strip,
    :git_describe => (git.capturing.describe(:always => true).strip rescue '')
  }
end

#outdatedObject

Public: Displays info about outdated segments.

Returns nothing.



148
149
150
151
152
153
154
155
156
157
# File 'lib/vendorificator/environment.rb', line 148

def outdated
  load_vendorfile

  outdated = []
  each_segment do |mod|
    outdated << mod if [:unpulled, :unmerged, :outdated].include? mod.status
  end

  outdated.each { |mod| say_status :quiet, 'outdated', mod.name }
end

#pull(remote, options = {}) ⇒ Object

Public: Pulls a single remote and updates the branches.

options - The Hash of options.

Returns nothing.

Raises:

  • (RuntimeError)


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/vendorificator/environment.rb', line 72

def pull(remote, options={})
  raise RuntimeError, "Unknown remote #{remote}" unless remotes.include?(remote)

  git.fetch(remote)
  git.fetch({:tags => true}, remote)
  begin
    git.fetch(remote, 'refs/notes/vendor:refs/notes/vendor')
  rescue MiniGit::GitError  # ignore
  end

  ref_rx = /^refs\/remotes\/#{Regexp.quote(remote)}\//
  remote_branches = Hash[ git.capturing.show_ref.
    lines.
    map(&:split).
    map { |sha, name| name =~ ref_rx ? [$', sha] : nil }.
    compact ]

  each_segment do |mod|
    ours = mod.head
    theirs = remote_branches[mod.branch_name]
    if theirs
      if not ours
        say_status :default, 'new', mod.branch_name, :yellow
        git.branch({:track => true}, mod.branch_name, theirs) unless options[:dry_run]
      elsif ours == theirs
        say_status :default, 'unchanged', mod.branch_name
      elsif fast_forwardable?(theirs, ours)
        say_status :default, 'updated', mod.name, :yellow
        mod.fast_forward theirs unless options[:dry_run]
      elsif fast_forwardable?(ours, theirs)
        say_status :default, 'older', mod.branch_name
      else
        say_status :default, 'complicated', mod.branch_name, :red
      end
    else
      say_status :default, 'unknown', mod.branch_name
    end
  end
end

#pull_all(options = {}) ⇒ Object

Public: Pulls all the remotes specified in options or the config.

options - The Hash of options.

Returns nothing.



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/vendorificator/environment.rb', line 55

def pull_all(options = {})
  load_vendorfile

  ensure_clean!
  remotes = options[:remote] ? options[:remote].split(',') : config[:remotes]
  remotes.each do |remote|
    indent :default, 'remote', remote do
      pull(remote, options)
    end
  end
end

#push(options = {}) ⇒ Object

Public: Push changes on module branches.

options - The Hash containing options

Returns nothing.



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/vendorificator/environment.rb', line 164

def push(options = {})
  load_vendorfile

  ensure_clean!

  pushable = []
  each_segment { |mod| pushable += mod.pushable_refs }

  pushable << 'refs/notes/vendor' if has_notes?

  remotes = options[:remote] ? options[:remote].split(',') : config[:remotes]
  remotes.each do |remote|
    git.push remote, pushable
  end
end

#relative_root_dirObject

Public: returns ‘config` relative to Git repository root



238
239
240
241
242
# File 'lib/vendorificator/environment.rb', line 238

def relative_root_dir
  @relative_root_dir ||= config[:root_dir].relative_path_from(
    Pathname.new(git.git_work_tree)
  )
end

#remotesObject

Git helpers



38
39
40
# File 'lib/vendorificator/environment.rb', line 38

def remotes
  @remotes ||= git.capturing.remote.lines.map(&:strip)
end

#say(*args) ⇒ Object



24
25
26
# File 'lib/vendorificator/environment.rb', line 24

def say(*args)
  io.say(*args)
end

#say_status(*args) ⇒ Object



28
29
30
# File 'lib/vendorificator/environment.rb', line 28

def say_status(*args)
  io.say_status(*args)
end

#shellObject



20
21
22
# File 'lib/vendorificator/environment.rb', line 20

def shell
  io.shell
end

#sync(options = {}) ⇒ Object

Public: Runs all the vendor segments.

options - The Hash of options.

Returns nothing.



185
186
187
188
189
190
191
192
193
194
195
# File 'lib/vendorificator/environment.rb', line 185

def sync(options = {})
  load_vendorfile

  ensure_clean!
  config[:use_upstream_version] = options[:update]
   = 

  each_segment(*options[:segments]) do |mod|
    mod.run!(:metadata => )
  end
end

#vendorfile_loaded?Boolean

Public: Checks if vendorfile has been already loaded.

Returns boolean.

Returns:

  • (Boolean)


270
271
272
# File 'lib/vendorificator/environment.rb', line 270

def vendorfile_loaded?
  defined?(@vendorfile_loaded) && @vendorfile_loaded
end