Class: Origen::ImportManager
Overview
Responsible for ensuring that all dependencies defined in config.imports are available.
Workspaces will automatically be created and updated to the correct version as required.
An instance of this class is hooked up to:
Origen.import_manager
Constant Summary collapse
- SHARED_CONTENTS_TYPES =
[:pattern, :templates, :command_launcher, :program]
Instance Method Summary collapse
-
#all_symlinks ⇒ Object
Returns all symlinks created by adding plugins Usage right now is to mask these links in unmanaged files.
- #command_launcher ⇒ Object
-
#create_symlink(from, to) ⇒ Object
private
Handles all symlink creation since Ruby/Windows is ropey.
-
#delete_symlink(path) ⇒ Object
private
Manually handle symlink deletion to support windows.
-
#delete_symlinks_of_plugin(plugin) ⇒ Object
Deletes any symlink pointing to the shared content of the specified plugin.
-
#initialize ⇒ ImportManager
constructor
A new instance of ImportManager.
-
#named_imports ⇒ Object
Returns a hash containing all imports.
-
#names ⇒ Object
Returns an array of symbols that represent the names of all imports.
-
#origen_root(name) ⇒ Object
Returns the path to origen root for the given import name.
-
#path_within_a_plugin(path) ⇒ Object
Return the plugin name if the path specified is from that plugin.
-
#plugin_instance(name) ⇒ Object
Returns the app instance of the given plugin name.
-
#plugin_version(plugin_name) ⇒ Object
Returns the version of the given plugin that is installed.
-
#require! ⇒ Object
This will fetch all imports (if required), add the libs to the load path, and require the environments.
- #required=(value) ⇒ Object
-
#required? ⇒ Boolean
Returns true if the imports have already been required and added to the load path of the current thread.
-
#symlink?(path) ⇒ Boolean
private
Returns true if the given path is a symlink.
-
#symlink_to_imports_dir?(path) ⇒ Boolean
Returns true if the given file is a symlink and a link to a file within the application’s imports directory, generally this can be used to identify symlinks which have been added by the imports/plugin manager to expose the pattern/program/templates directories of plugins.
-
#symlinks_in_dir(dir) ⇒ Object
Returns a list of paths which are symlinks within the supplied dir.
- #validate_production_status(force = false) ⇒ Object
Constructor Details
#initialize ⇒ ImportManager
Returns a new instance of ImportManager.
13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/origen/import_manager.rb', line 13 def initialize @required = false # These will be updated as plugins are imported. # Min and required are treated the same here, basically we don't allow plugins # to dictate a specific version and this will be taken as a minimum requirement. # Plugins can however block execution by specifying a max required version # that must not be exceeded. @required_origen_version = Origen.config.required_origen_version || Origen.config.min_required_origen_version @max_required_origen_version = Origen.config.max_required_origen_version end |
Instance Method Details
#all_symlinks ⇒ Object
Returns all symlinks created by adding plugins Usage right now is to mask these links in unmanaged files.
225 226 227 228 229 230 231 |
# File 'lib/origen/import_manager.rb', line 225 def all_symlinks links = [] SHARED_CONTENTS_TYPES.each do |type| links << symlinks_in_dir("#{type}") unless type == :command_launcher end links.flatten.uniq.compact end |
#command_launcher ⇒ Object
246 247 248 |
# File 'lib/origen/import_manager.rb', line 246 def command_launcher @command_launcher ||= [] end |
#create_symlink(from, to) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Handles all symlink creation since Ruby/Windows is ropey. On windows it will create an additional flag file to easily tell us a symlink is active later.
147 148 149 150 151 152 153 154 |
# File 'lib/origen/import_manager.rb', line 147 def create_symlink(from, to) if Origen.running_on_windows? system("call mklink /D #{to.to_s.gsub('/', '\\')} #{from.to_s.gsub('/', '\\')}") File.new("#{to}_is_a_symlink", 'w') {} else FileUtils.symlink from, to end end |
#delete_symlink(path) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Manually handle symlink deletion to support windows
158 159 160 161 162 163 164 165 166 |
# File 'lib/origen/import_manager.rb', line 158 def delete_symlink(path) if Origen.running_on_windows? # Don't use regular rm on windows symlink, will delete into the remote dir! system("call cmd /c rmdir #{path.to_s.gsub('/', '\\')}") FileUtils.rm_f("#{path}_is_a_symlink") else FileUtils.rm_f(path) end end |
#delete_symlinks_of_plugin(plugin) ⇒ Object
Deletes any symlink pointing to the shared content of the specified plugin
235 236 237 238 239 240 241 242 243 244 |
# File 'lib/origen/import_manager.rb', line 235 def delete_symlinks_of_plugin(plugin) SHARED_CONTENTS_TYPES.each do |type| unless type == :command_launcher link = "#{Origen.root}/#{type}/#{plugin.name}" if File.exist?(link) delete_symlink(link) if symlink?(link) end end end end |
#named_imports ⇒ Object
Returns a hash containing all imports
135 136 137 |
# File 'lib/origen/import_manager.rb', line 135 def named_imports imports end |
#names ⇒ Object
Returns an array of symbols that represent the names of all imports
126 127 128 129 130 131 132 |
# File 'lib/origen/import_manager.rb', line 126 def names return @names if @names names = Origen.plugins.map(&:name) # Had a bug where this was caching too early, don't cache until all plugins are loaded @names = names if Origen.app_loaded? names end |
#origen_root(name) ⇒ Object
Returns the path to origen root for the given import name
140 141 142 |
# File 'lib/origen/import_manager.rb', line 140 def origen_root(name) origen_root_for(named_imports[name]) end |
#path_within_a_plugin(path) ⇒ Object
Return the plugin name if the path specified is from that plugin
198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/origen/import_manager.rb', line 198 def path_within_a_plugin(path) ret_value = nil names.each do |plugin| subpath = path.slice(/.*\/#{plugin.to_s}/) if subpath && symlink?(subpath) ret_value = (plugin.to_sym if plugin.class != Symbol) || plugin break end end ret_value end |
#plugin_instance(name) ⇒ Object
Returns the app instance of the given plugin name
121 122 123 |
# File 'lib/origen/import_manager.rb', line 121 def plugin_instance(name) Origen.application_instance(origen_root_for(imports[name])) end |
#plugin_version(plugin_name) ⇒ Object
Returns the version of the given plugin that is installed
115 116 117 118 |
# File 'lib/origen/import_manager.rb', line 115 def plugin_version(plugin_name) load File.join(origen_root_for(imports[plugin_name]), 'config', 'version.rb') Origen::VersionString.new(Origen.import_manager.plugin_instance(plugin_name).class::VERSION) end |
#require! ⇒ Object
This will fetch all imports (if required), add the libs to the load path, and require the environments.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 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 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/origen/import_manager.rb', line 27 def require! unless required? while updates_required? puts 'The following imports need to be updated, this will now happen automatically:' puts '' dirty_imports.each do |name, import| if import[:path] puts " #{name} - #{import[:path]}" else puts " #{name} - #{import[:version]}" end end puts '' update! end if @required_origen_version if @max_required_origen_version if Origen::VersionString.new(@required_origen_version).greater_than?(@max_required_origen_version) puts '' puts "Your application needs to run Origen version #{@required_origen_version}, however" puts "the version of the #{@max_lib} plugin required by your import tree is not" puts "permitted to run above Origen version #{@max_required_origen_version}." puts 'You may need to consult with the plugin owner to see if this restriction can be' puts 'removed or if a newer version of the plugin without this restriction already' puts 'exists.' puts '' exit 0 end end if Origen.version.less_than?(@required_origen_version) if Origen.config.required_origen_version puts '' puts "A dependent plugin requires at least Origen version #{@required_origen_version}, however" puts "your main application currently specifies #{Origen.config.required_origen_version}." puts 'To proceed you must update the required_origen_version in config/application.rb' puts "to be: #{@required_origen_version}" puts '' exit 0 else Origen.version_checker.update_origen(@required_origen_version) end end end add_libs_to_load_path! require_environments! add_shared_contents! remove_unwanted_symlinks! @required = true end end |
#required=(value) ⇒ Object
84 85 86 |
# File 'lib/origen/import_manager.rb', line 84 def required=(value) @required = value end |
#required? ⇒ Boolean
Returns true if the imports have already been required and added to the load path of the current thread
80 81 82 |
# File 'lib/origen/import_manager.rb', line 80 def required? @required end |
#symlink?(path) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns true if the given path is a symlink. Since Ruby’s handling of symlinks is ropey we will manually maintain a flag (an empty file that means true when present) to indicate when an import is currently setup as a symlink to a path.
172 173 174 175 176 177 178 |
# File 'lib/origen/import_manager.rb', line 172 def symlink?(path) if Origen.running_on_windows? File.exist?("#{path}_is_a_symlink") else File.symlink?(path) end end |
#symlink_to_imports_dir?(path) ⇒ Boolean
Returns true if the given file is a symlink and a link to a file within the application’s imports directory, generally this can be used to identify symlinks which have been added by the imports/plugin manager to expose the pattern/program/templates directories of plugins
184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/origen/import_manager.rb', line 184 def symlink_to_imports_dir?(path) if Origen.running_on_windows? # Not sure how to do this yet on windows, for now just defaulting # to the original behavior of testing if it is a symlink symlink?(path) else if File.symlink?(path) !!(File.readlink(path) =~ /^#{ws.imports_directory}/) end end end |
#symlinks_in_dir(dir) ⇒ Object
Returns a list of paths which are symlinks within the supplied dir
211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/origen/import_manager.rb', line 211 def symlinks_in_dir(dir) list = [] if File.exist?(dir) Dir.entries(dir).each do |file| if symlink_to_imports_dir?("#{dir}/#{file}") list << "#{dir}/#{file}" end end end list end |
#validate_production_status(force = false) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/origen/import_manager.rb', line 88 def validate_production_status(force = false) if Origen.mode.production? || force imports.each do |_name, import| if import[:path] fail "The following import is defined as a path, but that is not allowed in production: #{import}" end version = Origen::VersionString.new(import[:version]) unless version.valid? fail "The following import version is not in a valid format: #{import}" end if version.latest? fail "Latest is not allowed as an import version in production: #{import}" end end if File.exist?("#{Origen.root}/Gemfile") File.readlines("#{Origen.root}/Gemfile").each do |line| # http://rubular.com/r/yNGDGB6M2r if line =~ /^\s*gem\s+(("|')\w+("|')),.*(:path\s*=>|path:)/ fail "The following gem is defined as a path in your Gemfile, but that is not allowed in production: #{Regexp.last_match[1]}" end end end end end |