"url" now has same features as "head"
Specifically, it can accept all the VCS tag specs that head could, making it more useful for defining stable versions that come from VCS instead of tarballs. A new "SoftwareSpecification" class was added to implement this. This new class holds a "spec" for downloading a software package. It combines the url (or head url) with the "specs" [1] that head has been able to take. This allows both the stable (url) and unstable (head) specification for a software package to co-exist without stomping on each others "specs". [1] "specs" contain instructions on which branch/tag/revision/etc. to use from the source repository URL.
This commit is contained in:
parent
a56466a4d3
commit
bbaac45e3e
@ -11,6 +11,50 @@ class FormulaUnavailableError <RuntimeError
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class SoftwareSpecification
|
||||||
|
attr_reader :url, :specs, :using
|
||||||
|
|
||||||
|
VCS_SYMBOLS = {
|
||||||
|
:bzr, BazaarDownloadStrategy,
|
||||||
|
:curl, CurlDownloadStrategy,
|
||||||
|
:cvs, CVSDownloadStrategy,
|
||||||
|
:git, GitDownloadStrategy,
|
||||||
|
:hg, MercurialDownloadStrategy,
|
||||||
|
:nounzip, NoUnzipCurlDownloadStrategy,
|
||||||
|
:post, CurlPostDownloadStrategy,
|
||||||
|
:svn, SubversionDownloadStrategy,
|
||||||
|
}
|
||||||
|
|
||||||
|
def initialize url, specs=nil
|
||||||
|
raise "No url provided" if url.nil?
|
||||||
|
@url = url
|
||||||
|
unless specs.nil?
|
||||||
|
# Get download strategy hint, if any
|
||||||
|
@using = specs.delete :using
|
||||||
|
# The rest of the specs are for source control
|
||||||
|
@specs = specs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns a suitable DownloadStrategy class that can be
|
||||||
|
# used to retreive this software package.
|
||||||
|
def download_strategy
|
||||||
|
return detect_download_strategy @url if @using.nil?
|
||||||
|
|
||||||
|
# If a class is passed, assume it is a download strategy
|
||||||
|
return @using if @using.kind_of? Class
|
||||||
|
|
||||||
|
detected = VCS_SYMBOLS[@using]
|
||||||
|
raise "Unknown strategy #{@using} was requested." unless detected
|
||||||
|
return detected
|
||||||
|
end
|
||||||
|
|
||||||
|
def detect_version
|
||||||
|
Pathname.new(@url).version
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# Derive and define at least @url, see Library/Formula for examples
|
# Derive and define at least @url, see Library/Formula for examples
|
||||||
class Formula
|
class Formula
|
||||||
include FileUtils
|
include FileUtils
|
||||||
@ -19,13 +63,24 @@ class Formula
|
|||||||
|
|
||||||
# Homebrew determines the name
|
# Homebrew determines the name
|
||||||
def initialize name='__UNKNOWN__'
|
def initialize name='__UNKNOWN__'
|
||||||
|
set_instance_variable 'homepage'
|
||||||
set_instance_variable 'url'
|
set_instance_variable 'url'
|
||||||
set_instance_variable 'head'
|
set_instance_variable 'head'
|
||||||
set_instance_variable 'specs'
|
set_instance_variable 'specs'
|
||||||
|
|
||||||
|
set_instance_variable 'stable'
|
||||||
|
set_instance_variable 'unstable'
|
||||||
|
|
||||||
if @head and (not @url or ARGV.build_head?)
|
if @head and (not @url or ARGV.build_head?)
|
||||||
@url=@head
|
@url = @head
|
||||||
@version='HEAD'
|
@version = 'HEAD'
|
||||||
|
@spec_to_use = @unstable
|
||||||
|
else
|
||||||
|
if @stable.nil?
|
||||||
|
@spec_to_use = SoftwareSpecification.new(@url, @specs)
|
||||||
|
else
|
||||||
|
@spec_to_use = @stable
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
raise "No url provided for formula #{name}" if @url.nil?
|
raise "No url provided for formula #{name}" if @url.nil?
|
||||||
@ -33,16 +88,12 @@ class Formula
|
|||||||
validate_variable :name
|
validate_variable :name
|
||||||
|
|
||||||
set_instance_variable 'version'
|
set_instance_variable 'version'
|
||||||
@version ||= Pathname.new(@url).version
|
@version ||= @spec_to_use.detect_version
|
||||||
validate_variable :version if @version
|
validate_variable :version if @version
|
||||||
|
|
||||||
set_instance_variable 'homepage'
|
CHECKSUM_TYPES.each { |type| set_instance_variable type }
|
||||||
|
|
||||||
CHECKSUM_TYPES.each do |type|
|
@downloader=download_strategy.new @spec_to_use.url, name, version, @spec_to_use.specs
|
||||||
set_instance_variable type
|
|
||||||
end
|
|
||||||
|
|
||||||
@downloader=download_strategy.new url, name, version, specs
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# if the dir is there, but it's empty we consider it not installed
|
# if the dir is there, but it's empty we consider it not installed
|
||||||
@ -52,18 +103,14 @@ class Formula
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
def prefix
|
|
||||||
validate_variable :name
|
|
||||||
validate_variable :version
|
|
||||||
HOMEBREW_CELLAR+@name+@version
|
|
||||||
end
|
|
||||||
|
|
||||||
def path
|
def path
|
||||||
self.class.path name
|
self.class.path name
|
||||||
end
|
end
|
||||||
|
|
||||||
def cached_download
|
def prefix
|
||||||
@downloader.cached_location
|
validate_variable :name
|
||||||
|
validate_variable :version
|
||||||
|
HOMEBREW_CELLAR+@name+@version
|
||||||
end
|
end
|
||||||
|
|
||||||
def bin; prefix+'bin' end
|
def bin; prefix+'bin' end
|
||||||
@ -77,33 +124,19 @@ class Formula
|
|||||||
def include; prefix+'include' end
|
def include; prefix+'include' end
|
||||||
def share; prefix+'share' end
|
def share; prefix+'share' end
|
||||||
|
|
||||||
# generally we don't want var stuff inside the keg
|
|
||||||
def var; HOMEBREW_PREFIX+'var' end
|
|
||||||
# configuration needs to be preserved past upgrades
|
# configuration needs to be preserved past upgrades
|
||||||
def etc; HOMEBREW_PREFIX+'etc' end
|
def etc; HOMEBREW_PREFIX+'etc' end
|
||||||
|
# generally we don't want var stuff inside the keg
|
||||||
|
def var; HOMEBREW_PREFIX+'var' end
|
||||||
|
|
||||||
# reimplement if we don't autodetect the download strategy you require
|
# Use the @spec_to_use to detect the download strategy.
|
||||||
|
# Can be overriden to force a custom download strategy
|
||||||
def download_strategy
|
def download_strategy
|
||||||
if @specs and @url == @head
|
@spec_to_use.download_strategy
|
||||||
vcs = @specs.delete :using
|
|
||||||
if vcs != nil
|
|
||||||
# If a class is passed, assume it is a download strategy
|
|
||||||
return vcs if vcs.kind_of? Class
|
|
||||||
|
|
||||||
case vcs
|
|
||||||
when :bzr then return BazaarDownloadStrategy
|
|
||||||
when :curl then return CurlDownloadStrategy
|
|
||||||
when :cvs then return CVSDownloadStrategy
|
|
||||||
when :git then return GitDownloadStrategy
|
|
||||||
when :hg then return MercurialDownloadStrategy
|
|
||||||
when :svn then return SubversionDownloadStrategy
|
|
||||||
end
|
end
|
||||||
|
|
||||||
raise "Unknown strategy #{vcs} was requested."
|
def cached_download
|
||||||
end
|
@downloader.cached_location
|
||||||
end
|
|
||||||
|
|
||||||
detect_download_strategy url
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# tell the user about any caveats regarding this package, return a string
|
# tell the user about any caveats regarding this package, return a string
|
||||||
@ -213,7 +246,7 @@ class Formula
|
|||||||
require self.path(name)
|
require self.path(name)
|
||||||
end
|
end
|
||||||
begin
|
begin
|
||||||
klass_name =self.class_s(name)
|
klass_name = self.class_s(name)
|
||||||
klass = eval(klass_name)
|
klass = eval(klass_name)
|
||||||
rescue NameError
|
rescue NameError
|
||||||
# TODO really this text should be encoded into the exception
|
# TODO really this text should be encoded into the exception
|
||||||
@ -284,10 +317,10 @@ protected
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
# creates a temporary directory then yields, when the block returns it
|
# Create a temporary directory then yield. When the block returns,
|
||||||
# recursively deletes the temporary directory
|
# recursively delete the temporary directory.
|
||||||
def mktemp
|
def mktemp
|
||||||
# I used /tmp rather than mktemp -td because that generates a directory
|
# I used /tmp rather than `mktemp -td` because that generates a directory
|
||||||
# name with exotic characters like + in it, and these break badly written
|
# name with exotic characters like + in it, and these break badly written
|
||||||
# scripts that don't escape strings before trying to regexp them :(
|
# scripts that don't escape strings before trying to regexp them :(
|
||||||
|
|
||||||
@ -336,11 +369,8 @@ EOF
|
|||||||
|
|
||||||
def stage
|
def stage
|
||||||
HOMEBREW_CACHE.mkpath
|
HOMEBREW_CACHE.mkpath
|
||||||
|
fetched = @downloader.fetch
|
||||||
downloaded_tarball = @downloader.fetch
|
verify_download_integrity fetched if fetched.kind_of? Pathname
|
||||||
if downloaded_tarball.kind_of? Pathname
|
|
||||||
verify_download_integrity downloaded_tarball
|
|
||||||
end
|
|
||||||
|
|
||||||
mktemp do
|
mktemp do
|
||||||
@downloader.stage
|
@downloader.stage
|
||||||
@ -427,6 +457,8 @@ EOF
|
|||||||
end
|
end
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
# The methods below define the formula DSL.
|
||||||
|
attr_reader :stable, :unstable
|
||||||
|
|
||||||
def self.attr_rw(*attrs)
|
def self.attr_rw(*attrs)
|
||||||
attrs.each do |attr|
|
attrs.each do |attr|
|
||||||
@ -438,13 +470,21 @@ EOF
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_rw :url, :version, :homepage, :specs, :deps, :external_deps, *CHECKSUM_TYPES
|
attr_rw :version, :homepage, :specs, :deps, :external_deps
|
||||||
|
attr_rw *CHECKSUM_TYPES
|
||||||
|
|
||||||
def head val=nil, specs=nil
|
def head val=nil, specs=nil
|
||||||
if specs
|
return @head if val.nil?
|
||||||
|
@unstable = SoftwareSpecification.new(val, specs)
|
||||||
|
@head = val
|
||||||
@specs = specs
|
@specs = specs
|
||||||
end
|
end
|
||||||
val.nil? ? @head : @head = val
|
|
||||||
|
def url val=nil, specs=nil
|
||||||
|
return @url if val.nil?
|
||||||
|
@stable = SoftwareSpecification.new(val, specs)
|
||||||
|
@url = val
|
||||||
|
@specs = specs
|
||||||
end
|
end
|
||||||
|
|
||||||
def depends_on name
|
def depends_on name
|
||||||
|
Loading…
x
Reference in New Issue
Block a user