Class: Boson::RepoIndex

Inherits:
Object
  • Object
show all
Defined in:
lib/boson/repo_index.rb

Overview

This class provides an index for commands and libraries of a given a Repo. When this index updates, it detects library files whose md5 hash have changed and reindexes them. The index is stored with Marshal at config/index.marshal (relative to a Repo’s root directory). Since the index is marshaled, putting lambdas/procs in it will break it.If an index gets corrupted, simply delete it and next time Boson needs it, the index will be recreated.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(repo) ⇒ RepoIndex

Returns a new instance of RepoIndex.



11
12
13
# File 'lib/boson/repo_index.rb', line 11

def initialize(repo)
  @repo = repo
end

Instance Attribute Details

#commandsObject (readonly)

Returns the value of attribute commands.



10
11
12
# File 'lib/boson/repo_index.rb', line 10

def commands
  @commands
end

#librariesObject (readonly)

Returns the value of attribute libraries.



10
11
12
# File 'lib/boson/repo_index.rb', line 10

def libraries
  @libraries
end

#repoObject (readonly)

Returns the value of attribute repo.



10
11
12
# File 'lib/boson/repo_index.rb', line 10

def repo
  @repo
end

Instance Method Details

#all_main_methodsObject



92
93
94
# File 'lib/boson/repo_index.rb', line 92

def all_main_methods
  @commands.reject {|e| e.namespace }.map {|e| [e.name, e.alias]}.flatten.compact + namespaces
end

#changed_librariesObject



110
111
112
113
# File 'lib/boson/repo_index.rb', line 110

def changed_libraries
  read
  latest_hashes.select {|lib, hash| @lib_hashes[lib] != hash}.map {|e| e[0]}
end

#delete_stale_libraries_and_commandsObject



69
70
71
72
73
74
75
# File 'lib/boson/repo_index.rb', line 69

def delete_stale_libraries_and_commands
  cached_libraries = @lib_hashes.keys
  libs_to_delete = @libraries.select {|e| !cached_libraries.include?(e.name) && e.is_a?(FileLibrary) }
  names_to_delete = libs_to_delete.map {|e| e.name }
  libs_to_delete.each {|e| @libraries.delete(e) }
  @commands.delete_if {|e| names_to_delete.include? e.lib }
end

#exists?Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/boson/repo_index.rb', line 61

def exists?
  File.exists? marshal_file
end

#find_library(command, object = false) ⇒ Object



100
101
102
103
104
105
106
107
108
# File 'lib/boson/repo_index.rb', line 100

def find_library(command, object=false)
  read
  namespace_command = command.split(NAMESPACE)[0]
  if (lib = @libraries.find {|e| e.namespace == namespace_command })
    object ? lib : lib.name
  elsif (cmd = Command.find(command, @commands))
    object ? @libraries.find {|e| e.name == cmd.lib} : cmd.lib
  end
end

#latest_hashesObject



115
116
117
118
119
120
121
# File 'lib/boson/repo_index.rb', line 115

def latest_hashes
  repo.all_libraries.inject({}) {|h, e|
    lib_file = FileLibrary.library_file(e, repo.dir)
    h[e] = Digest::MD5.hexdigest(File.read(lib_file)) if File.exists?(lib_file)
    h
  }
end

#marshal_fileObject



96
97
98
# File 'lib/boson/repo_index.rb', line 96

def marshal_file
  File.join(repo.config_dir, 'index.marshal')
end

#namespacesObject



86
87
88
89
90
# File 'lib/boson/repo_index.rb', line 86

def namespaces
  nsps = @libraries.map {|e| e.namespace }.compact
  nsps.delete(false)
  nsps
end

#readObject

Reads and initializes index.



35
36
37
38
39
40
41
42
# File 'lib/boson/repo_index.rb', line 35

def read
  return if @read
  @libraries, @commands, @lib_hashes = exists? ?
    File.open( marshal_file, 'rb' ){|f| Marshal.load( f.read ) } : [[], [], {}]
  delete_stale_libraries_and_commands
  set_command_namespaces
  @read = true
end

#read_and_transfer(ignored_libraries = []) ⇒ Object

:stopdoc:



52
53
54
55
56
57
58
59
# File 'lib/boson/repo_index.rb', line 52

def read_and_transfer(ignored_libraries=[])
  read
  existing_libraries = (Boson.libraries.map {|e| e.name} + ignored_libraries).uniq
  libraries_to_add = @libraries.select {|e| !existing_libraries.include?(e.name)}
  Boson.libraries += libraries_to_add
  # depends on saved commands being correctly associated with saved libraries
  Boson.commands += libraries_to_add.map {|e| e.command_objects(e.commands, @commands) }.flatten
end

#save_marshal_index(marshal_string) ⇒ Object



65
66
67
# File 'lib/boson/repo_index.rb', line 65

def save_marshal_index(marshal_string)
  File.open(marshal_file, 'wb') {|f| f.write marshal_string }
end

#set_command_namespacesObject

set namespaces for commands



78
79
80
81
82
83
84
# File 'lib/boson/repo_index.rb', line 78

def set_command_namespaces
  lib_commands = @commands.inject({}) {|t,e| (t[e.lib] ||= []) << e; t }
  namespace_libs = @libraries.select {|e| e.namespace(e.indexed_namespace) }
  namespace_libs.each {|lib|
    (lib_commands[lib.name] || []).each {|e| e.namespace = lib.namespace }
  }
end

#update(options = {}) ⇒ Object

Updates the index.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/boson/repo_index.rb', line 16

def update(options={})
  libraries_to_update = !exists? ? repo.all_libraries : options[:libraries] || changed_libraries
  read_and_transfer(libraries_to_update)
  if options[:verbose]
    puts !exists? ? "Generating index for all #{libraries_to_update.size} libraries. Patience ... is a bitch" :
      (libraries_to_update.empty? ? "No libraries indexed" :
      "Indexing the following libraries: #{libraries_to_update.join(', ')}")
  end
  Manager.failed_libraries = []
  unless libraries_to_update.empty?
    Manager.load(libraries_to_update, options.merge(:index=>true))
    unless Manager.failed_libraries.empty?
      $stderr.puts("Error: These libraries failed to load while indexing: #{Manager.failed_libraries.join(', ')}")
    end
  end
  write(Manager.failed_libraries)
end

#write(failed_libraries = []) ⇒ Object

Writes/saves current index to config/index.marshal.



45
46
47
48
49
# File 'lib/boson/repo_index.rb', line 45

def write(failed_libraries=[])
  latest = latest_hashes
  failed_libraries.each {|e| latest.delete(e) }
  save_marshal_index Marshal.dump([Boson.libraries, Boson.commands, latest])
end