Class: Drupid::Project
- Includes:
- Comparable
- Defined in:
- lib/drupid/project.rb
Overview
Base class for projects.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#core ⇒ Object
readonly
Returns the value of attribute core.
-
#l10n_path ⇒ Object
Returns the value of attribute l10n_path.
-
#l10n_url ⇒ Object
Returns the value of attribute l10n_url.
-
#location ⇒ Object
Returns the value of attribute location.
-
#proj_type ⇒ Object
The type of this project, which is one among ‘drupal’, ‘module’, ‘theme’ and ‘profile’, or nil if the type has not been determined or assigned.
Attributes inherited from Component
#download_specs, #download_type, #download_url, #ignore_paths, #local_path, #name, #overwrite
Class Method Summary collapse
-
.from_s(p) ⇒ Object
Creates a new Project instance from the specified string.
Instance Method Summary collapse
-
#<=>(other) ⇒ Object
Compares this project with another to determine which is newer.
-
#==(other) ⇒ Object
See Version for the reason why we define == explicitly.
-
#best_release(version_list) ⇒ Object
Returns the current version of the project when version_list is empty.
- #core_project=(c) ⇒ Object
-
#core_project? ⇒ Boolean
Returns true if this is a core project; returns false otherwise.
-
#dependencies(options = {}) ⇒ Object
Returns a list of the names of the extensions (modules and themes) upon which this project and its subprojects (the projects contained within this one) depend.
-
#drupal? ⇒ Boolean
Returns true if this object corresponds to Drupal core; returns false otherwise.
-
#extended_name ⇒ Object
Returns the name and the version of this project as a string, e.g., ‘media-7.x-2.0-unstable2’ or ‘drupal-7.14’.
-
#extensions ⇒ Object
Returns a list of the names of the extensions (modules and themes) contained in this project.
- #fetch ⇒ Object
-
#fetch_release_history ⇒ Object
Fetches the release history for this project from updates.drupal.org.
-
#file_level_compare_with(tgt) ⇒ Object
Compares this project with another, returning an array of differences.
-
#has_version? ⇒ Boolean
Returns true if a version is specified for this project, false otherwise.
-
#initialize(name, core_num, vers = nil) ⇒ Project
constructor
Creates a new project with a given name and compatibility number.
-
#makefile ⇒ Object
Returns the path to a makefile contained in this project, if any.
-
#profile? ⇒ Boolean
Returns true if this is a profile; returns false otherwise.
- #reload_project_info ⇒ Object
-
#target_path ⇒ Object
Returns the relative path where this project should be installed within a platform.
-
#update_download_url ⇒ Object
Updates the download URL for the current version of this project.
-
#update_version ⇒ Object
Updates the version of this project to the latest (stable) release.
-
#version ⇒ Object
Returns the version of this project as a Drupid::Version object, or nil if this project has not been assigned a version.
-
#version=(new_version) ⇒ Object
Assigns a version to this project.
Methods inherited from Component
#add_download_spec, #add_patch, #cached_location, #clear_patches, #clone, #directory_name, #directory_name=, #each_patch, #exist?, #get_patch, #has_patches?, #ignore_path, #patch, #patched?, #patched_location, #subdir, #subdir=, #to_s
Methods included from Utils
#blah, #bzr, #compare_paths, #curl, #cvs, #debug, #dont_debug, #git, #hg, #ignore_interrupts, #interactive_shell, #odie, #ofail, #ohai, #owarn, #runBabyRun, #svn, #tempdir, #uncompress, #which, #writeFile
Constructor Details
#initialize(name, core_num, vers = nil) ⇒ Project
Creates a new project with a given name and compatibility number. Optionally, specify a short version string (i.e., a version string without core compatibility number).
Examples:
p = Drupid::Project.new('cck', 6)
p = Drupid::Project.new('views', 7, '1.2')
270 271 272 273 274 275 276 277 278 |
# File 'lib/drupid/project.rb', line 270 def initialize name, core_num, vers = nil super(name) @core = VersionCore.new(core_num) @core_project = ('drupal' == @name) ? true : nil @version = (vers.nil? or vers.empty?) ? nil : Version.from_s(@core.to_s + '-' + vers) @proj_type = ('drupal' == @name) ? 'drupal' : nil @info_file = nil @release_xml = nil end |
Instance Attribute Details
#core ⇒ Object (readonly)
Returns the value of attribute core.
253 254 255 |
# File 'lib/drupid/project.rb', line 253 def core @core end |
#l10n_path ⇒ Object
Returns the value of attribute l10n_path.
260 261 262 |
# File 'lib/drupid/project.rb', line 260 def l10n_path @l10n_path end |
#l10n_url ⇒ Object
Returns the value of attribute l10n_url.
261 262 263 |
# File 'lib/drupid/project.rb', line 261 def l10n_url @l10n_url end |
#location ⇒ Object
Returns the value of attribute location.
254 255 256 |
# File 'lib/drupid/project.rb', line 254 def location @location end |
#proj_type ⇒ Object
The type of this project, which is one among ‘drupal’, ‘module’, ‘theme’ and ‘profile’, or nil if the type has not been determined or assigned. Note that this does not coincide with the ‘type’ field in a Drush makefile, whose feasible values are ‘core’, ‘module’, ‘theme’, ‘profile’.
259 260 261 |
# File 'lib/drupid/project.rb', line 259 def proj_type @proj_type end |
Class Method Details
.from_s(p) ⇒ Object
Creates a new Project instance from the specified string. Note that the string must at least contain the core version of the project.
Raises a Drupid::NotDrupalVersionError if the string cannot be parsed.
Examples:
proj = Drupid::Project.from_s 'drupal-7.23'
proj = Drupid::Project.from_s 'drupal-8.x'
proj = Drupid::Project.from_s 'media-7.x'
proj = Drupid::Project.from_s 'tao-7.x-3.0-beta4'
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
# File 'lib/drupid/project.rb', line 290 def self.from_s p matchdata = p.match(/^([^-\/]+)[-\/](\d+.*)$/) raise NotDrupalVersionError if matchdata.nil? name = matchdata[1] vers = nil if ('drupal' == name) and (matchdata[2] =~ /^(\d+)\.(\d+)/) # e.g., drupal-8.0-dev core = $1.to_i vers = matchdata[2] else matchversion = matchdata[2].match(/^(\d+)\.x-?(.*)/) raise NotDrupalVersionError if matchversion.nil? core = matchversion[1].to_i vers = matchversion[2] end Project.new(name, core, vers) end |
Instance Method Details
#<=>(other) ⇒ Object
Compares this project with another to determine which is newer. The comparison returns nil if the two projects have different names or at least one of them has no version; otherwise, returns -1 if this project is older than the other, 1 if this project is more recent than the other, 0 if this project has the same version as the other.
432 433 434 435 436 437 438 439 440 441 |
# File 'lib/drupid/project.rb', line 432 def <=>(other) return nil if @name != other.name c = core <=> other.core if 0 == c return nil unless has_version? and other.has_version? return version <=> other.version else return c end end |
#==(other) ⇒ Object
See Version for the reason why we define == explicitly.
420 421 422 423 424 |
# File 'lib/drupid/project.rb', line 420 def ==(other) @name == other.name and @core == other.core and @version == other.version end |
#best_release(version_list) ⇒ Object
Returns the current version of the project when version_list is empty.
607 608 609 610 611 612 613 614 615 616 617 618 |
# File 'lib/drupid/project.rb', line 607 def best_release version_list if self.has_version? # Exclude releases older than the current one version_list = version_list.select { |v| v >= self.version } end return self.version if version_list.empty? stable_releases = version_list.select { |v| v.stable? } if stable_releases.empty? version_list.max { |a,b| a.better b } else stable_releases.max { |a,b| a.better b } end end |
#core_project=(c) ⇒ Object
415 416 417 |
# File 'lib/drupid/project.rb', line 415 def core_project=(c) @core_project = c end |
#core_project? ⇒ Boolean
Returns true if this is a core project; returns false otherwise.
411 412 413 |
# File 'lib/drupid/project.rb', line 411 def core_project? @core_project end |
#dependencies(options = {}) ⇒ Object
Returns a list of the names of the extensions (modules and themes) upon which this project and its subprojects (the projects contained within this one) depend. Returns an empty list if no local copy of this project exists.
If :subprojects is set to false, subprojects’ dependencies are not computed.
Options: subprojects
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 |
# File 'lib/drupid/project.rb', line 463 def dependencies = {} return [] unless exist? deps = Array.new if .has_key?(:subprojects) and (not [:subprojects]) reload_project_info unless @info_file and @info_file.exist? info_files = [@info_file] else info_files = Dir["#{local_path}/**/*.info"] end info_files.each do |info| f = File.open(info, "r").read f.each_line do |l| matchdata = l.match(/^\s*dependencies\s*\[\s*\]\s*=\s*["']?([^\s("']+)/) if nil != matchdata deps << matchdata[1].strip end matchdata = l.match(/^\s*base +theme\s*=\s*(.+)$/) if nil != matchdata d = matchdata[1].strip deps << d.gsub(/\A["']|["']\Z/, '') # Strip leading and trailing quotes end end end # Remove duplicates and self-dependency deps.uniq! deps.delete(name) return deps end |
#drupal? ⇒ Boolean
Returns true if this object corresponds to Drupal core; returns false otherwise.
401 402 403 |
# File 'lib/drupid/project.rb', line 401 def drupal? 'drupal' == proj_type end |
#extended_name ⇒ Object
Returns the name and the version of this project as a string, e.g., ‘media-7.x-2.0-unstable2’ or ‘drupal-7.14’. If no version is specified for this project, returns only the project’s name and core compatibility number.
447 448 449 450 451 452 453 |
# File 'lib/drupid/project.rb', line 447 def extended_name if has_version? return name + '-' + ((drupal?) ? version.short : version.long) else return name + '-' + core.to_s end end |
#extensions ⇒ Object
Returns a list of the names of the extensions (modules and themes) contained in this project. Returns a list containing only the project’s name if no local copy of this project exists.
496 497 498 499 500 501 502 503 504 505 |
# File 'lib/drupid/project.rb', line 496 def extensions return [name] unless exist? # Note that the project's name may be different from the name of the .info file. ext = [name] Dir["#{local_path}/**/*.info"].map do |p| ext << File.basename(p, '.info') end ext.uniq! return ext end |
#fetch ⇒ Object
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 |
# File 'lib/drupid/project.rb', line 517 def fetch if self.version.nil? and download_url.nil? and download_type.nil? debug "Updating version of #{self.extended_name}" self.update_version end # If the project has no version we fetch it even if it is cached. # If the project has a download type, we fetch it even if it is cached # (say the download type is 'git' and the revision is changed in the # makefile, then the cached project must be updated accordingly). if self.has_version? and self.download_type.nil? and self.cached_location.exist? @local_path = self.cached_location debug "#{self.extended_name} is cached" else blah "Fetching #{self.extended_name}" if 'git' == self.download_type and self.download_url.nil? self.download_url = "http://git.drupal.org/project/#{name}.git" end self.update_download_url if self.download_url.nil? raise "No download URL defined for #{self.extended_name}" unless self.download_url downloader = Drupid.makeDownloader self.download_url.to_s, self.cached_location.dirname.to_s, self.cached_location.basename.to_s, self.download_specs.merge({:type => download_type}) downloader.fetch downloader.stage @local_path = downloader.staged_path end self.reload_project_info unless self.drupal? end |
#fetch_release_history ⇒ Object
Fetches the release history for this project from updates.drupal.org.
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
# File 'lib/drupid/project.rb', line 380 def fetch_release_history begin debug "Getting release history from http://updates.drupal.org/release-history/#{self.name}/#{self.core}" dont_debug do @release_xml = Nokogiri::XML(open("http://updates.drupal.org/release-history/#{self.name}/#{self.core}")) end if @release_xml.at_xpath('/error') debug "No release history for the given project" @relese_xml = nil else debug "Release history retrieved" end rescue => ex owarn "Could not fetch release history for #{self.extended_name}" debug "fetch_release_history: #{ex}" @release_xml = nil end end |
#file_level_compare_with(tgt) ⇒ Object
Compares this project with another, returning an array of differences. If this project contains a makefile, ignore the content of the following directories inside the project: libraries, modules, profiles and themes.
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 |
# File 'lib/drupid/project.rb', line 583 def file_level_compare_with tgt args = Array.new if makefile args << '-f' << '- /libraries/***' # this syntax requires rsync >=2.6.7. args << '-f' << '- /modules/***' args << '-f' << '- /profiles/***' args << '-f' << '- /themes/***' end if drupal? args << '-f' << '+ /profiles/default/***' # D6 args << '-f' << '+ /profiles/minimal/***' # D7 args << '-f' << '+ /profiles/standard/***' # D7 args << '-f' << '+ /profiles/testing/***' # D7 args << '-f' << '- /profiles/***' args << '-f' << '+ /sites/all/README.txt' args << '-f' << '+ /sites/default/default.settings.php' args << '-f' << '- /sites/***' end super(tgt, args) end |
#has_version? ⇒ Boolean
Returns true if a version is specified for this project, false otherwise.
308 309 310 |
# File 'lib/drupid/project.rb', line 308 def has_version? nil != @version end |
#makefile ⇒ Object
Returns the path to a makefile contained in this project, if any. Returns nil if this project does not contain any makefile. For an embedded makefile to be recognized, the makefile itself must be named ‘#name.make’ or ‘drupal-org.make’.
Requires: a local copy of this project.
568 569 570 571 572 573 574 575 576 577 578 |
# File 'lib/drupid/project.rb', line 568 def makefile return nil unless self.exist? paths = [ local_path + "#{name}.make", local_path + 'drupal-org.make' # Used in Drupal distributions ] paths.each do |p| return p if p.exist? end return nil end |
#profile? ⇒ Boolean
Returns true if this is a profile; returns false otherwise.
406 407 408 |
# File 'lib/drupid/project.rb', line 406 def profile? 'profile' == proj_type end |
#reload_project_info ⇒ Object
507 508 509 510 511 512 513 514 515 |
# File 'lib/drupid/project.rb', line 507 def reload_project_info project_info = ProjectInfo.new(@local_path) raise "Inconsistent naming: expected #{@name}, got #{project_info.project_name}" unless @name == project_info.project_name raise "Inconsistent core: expected #{@core}, got #{project_info.project_core}" unless @core == project_info.project_core @proj_type = project_info.project_type @core_project = project_info.core_project? @version = project_info.project_version @info_file = project_info.info_file end |
#target_path ⇒ Object
Returns the relative path where this project should be installed within a platform. For example, for a module called ‘Foo’, it might be something like ‘modules/contrib/foo’.
551 552 553 554 555 556 557 558 559 560 |
# File 'lib/drupid/project.rb', line 551 def target_path case proj_type when 'drupal' return Pathname.new('.') when nil raise "Undefined project type for #{name}." else return Pathname.new(proj_type + 's') + subdir + directory_name end end |
#update_download_url ⇒ Object
Updates the download URL for the current version of this project.
Retrieves the release information for this project from updates.drupal.org.
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/drupid/project.rb', line 361 def update_download_url return unless self.has_version? self.fetch_release_history if @release_xml.nil? return if @release_xml.nil? if @release_xml.at_xpath('/project/releases/release/files/file/variant').nil? variant = '' else variant = "[variant='profile-only']" end v = self.drupal? ? self.version.short : self.version.long url_node = @release_xml.at_xpath("/project/releases/release[status='published'][version='#{v}']/files/file#{variant}/url") if url_node.nil? owarn "Could not get download URL from http://updates.drupal.org for #{extended_name}" else self.download_url = url_node.child.to_s end end |
#update_version ⇒ Object
Updates the version of this project to the latest (stable) release.
Retrieves the release information for this project from updates.drupal.org.
See also: Drupid::Project.best_release
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
# File 'lib/drupid/project.rb', line 340 def update_version self.fetch_release_history if @release_xml.nil? return self.version unless @release_xml version_list = [] version_nodes = @release_xml.xpath("/project/releases/release[status='published']/version") version_nodes.each do |n| v = n.child.to_s # Remove version specifications that do not start with self.core. # This seemingly superfluous test is needed because, for example, # imce-7.x has a 'master' version (oh my!). next if v !~ /^#{self.core.to_i}\./ v.sub!("#{self.core}-", '') unless self.drupal? version_list.push(Version.new(self.core, v)) end self.version = self.best_release(version_list) debug "Version updated: #{extended_name}" end |
#version ⇒ Object
Returns the version of this project as a Drupid::Version object, or nil if this project has not been assigned a version.
314 315 316 |
# File 'lib/drupid/project.rb', line 314 def version @version end |
#version=(new_version) ⇒ Object
Assigns a version to this project. The argument must be a String object or a Drupid::Version object. For the syntax of the String argument, see Drupid::Version.
321 322 323 324 325 326 327 328 329 330 331 332 333 |
# File 'lib/drupid/project.rb', line 321 def version=(new_version) return @version = nil if new_version.nil? if new_version.is_a?(Version) temp_version = new_version elsif new_version.is_a?(String) v = new_version temp_version = Version.from_s(v) else raise NotDrupalVersionError end raise NotDrupalVersionError, "Incompatible version for project #{self.extended_name}: #{temp_version.long}" if temp_version.core != self.core @version = temp_version end |