Skip to content

Commit

Permalink
renamed Source::Package to Source::Archive
Browse files Browse the repository at this point in the history
  • Loading branch information
hag committed Sep 21, 2016
1 parent f1ae581 commit d155619
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 38 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* [ENHANCEMENT] tests can now run against a real docker host, improving test depth
* [ENHANCEMENT] removed OsDb. This file contained some hardcoded Os versions which was not future proof. It was a workaround to get started more quickly.
* [FIX] patched sources now fail when the underlying patch fails
* [CHANGE] Renamed "Source::Package" to "Source::Archive" which is more striking. The term "package" is also used for build results.

# 0.2.2 / 2016.09.05

Expand Down
2 changes: 1 addition & 1 deletion lib/fpm/fry/recipe.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require 'fpm/fry/source'
require 'fpm/fry/source/package'
require 'fpm/fry/source/archive'
require 'fpm/fry/source/dir'
require 'fpm/fry/source/patched'
require 'fpm/fry/source/git'
Expand Down
2 changes: 1 addition & 1 deletion lib/fpm/fry/recipe/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def register_source_type( klass )

def register_default_source_types!
register_source_type Source::Git
register_source_type Source::Package
register_source_type Source::Archive
register_source_type Source::Dir
end

Expand Down
5 changes: 1 addition & 4 deletions lib/fpm/fry/source.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
require 'fpm/fry/with_data'
module FPM; module Fry ;

# h2. Interface
module Source
module FPM; module Fry ; module Source

# Raised when building a cache failed.
class CacheFailed < StandardError
Expand Down
74 changes: 62 additions & 12 deletions lib/fpm/fry/source/package.rb → lib/fpm/fry/source/archive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,62 @@
require 'fpm/fry/exec'
require 'cabin'
module FPM; module Fry ; module Source
class Package
# Used to build from an archive.
#
# @example in a recipe
# source 'http://curl.haxx.se/download/curl-7.36.0.tar.gz',
# checksum: '33015795d5650a2bfdd9a4a28ce4317cef944722a5cfca0d1563db8479840e90'
#
# It is highly advised to supply a checksum ( althought it's not mandatory ).
# This checksum will be used to test for cache validity and data integrity. The
# checksum algorithm is automatically guessed based on the length of the checksum.
#
# - 40 characters = sha1
# - 64 characters = sha256
#
# Let's be honest: all other checksum algorithms aren't or shouldn't be in use anyway.
class Archive

REGEX = %r!\Ahttps?:!

# @return [:archive]
def self.name
:package
end

def self.aliases
[:http]
[:package,:http]
end

# Guesses if the given url is an archive.
#
# @example not an archive
# FPM::Fry::Source::Archive.guess("bzr://something") # => nil
#
# @example an archive
# FPM::Fry::Source::Archive.guess("https://some/thing.tar.gz") #=> 6
#
# @return [nil] when it's not an archive
# @return [Numeric] number of characters used
def self.guess( url )
Source::guess_regex(REGEX, url)
end

# Raised when too many redirects happened.
class RedirectError < CacheFailed
end

# Raised when the archive type is not known.
class UnknownArchiveType < StandardError
include WithData
end

class Cache < Struct.new(:package,:tempdir)
extend Forwardable

def_delegators :package, :url, :checksum, :checksum_algorithm, :agent, :logger, :file_map
def_delegators :package, :url, :checksum, :checksum_algorithm, :logger, :file_map

# @return [String] cachekey which is equal to the checksum
def cachekey
@observed_checksum || checksum
end
Expand Down Expand Up @@ -93,7 +125,7 @@ def fetch_url( url, redirs = 3, &block)
case(resp)
when Net::HTTPRedirection
if redirs == 0
raise RedirectError, "Too many redirects"
raise RedirectError.new("Too many redirects", url: url.to_s, location: resp['location'])
end
logger.debug("Following redirect", url: url.to_s , location: resp['location'])
return fetch_url( resp['location'], redirs - 1, &block)
Expand Down Expand Up @@ -167,7 +199,7 @@ def copy_to(dst)
update!
Exec['unzip', tempfile, '-d', dst ]
end

private
def unpacked_tmpdir
File.join(tempdir, cachekey)
end
Expand Down Expand Up @@ -198,26 +230,44 @@ def copy_to(dst)
'.bundle' => PlainCache
}

attr :file_map, :data, :url, :extension, :checksum, :checksum_algorithm, :agent, :logger
attr :file_map, :data, :url, :checksum, :checksum_algorithm, :logger

# @param [URI] url
# @param [Hash] options
# @option options [Cabin::Channel] :logger (default cabin channel)
# @option options [String] :checksum a checksum of the archive
# @raise [UnknownArchiveType] when the archive type is unknown
def initialize( url, options = {} )
@url = URI(url)
@extension = options.fetch(:extension){
CACHE_CLASSES.keys.find{|ext|
@url.path.end_with?(ext)
}
}
@cache_class = guess_cache_class(@url)
@logger = options.fetch(:logger){ Cabin::Channel.get }
@checksum = options[:checksum]
@checksum_algorithm = guess_checksum_algorithm(options[:checksum])
@file_map = options.fetch(:file_map){ {'' => ''} }
end

# Creates a cache.
#
# @param [String] tempdir
# @return [TarCache] for plain .tar files
# @return [TarGzCache] for .tar.gz files
# @return [TarBz2Cache] for .tar.bz2 files
# @return [ZipCache] for .zip files
# @return [PlainCache] for .bin files
def build_cache(tempdir)
CACHE_CLASSES.fetch(extension).new(self, tempdir)
@cache_class.new(self, tempdir)
end
private

def guess_cache_class( url )
CACHE_CLASSES.each do |ext,klass|
if url.path.end_with?(ext)
return klass
end
end
raise UnknownArchiveType.new("Unknown archive type", url: url.to_s, known_extensions: CACHE_CLASSES.keys)
end

def guess_checksum_algorithm( checksum )
case(checksum)
when nil
Expand Down
2 changes: 1 addition & 1 deletion lib/fpm/fry/source/git.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Git

REGEX = %r!\A(?:git:|\S+@\S+:\S+\.git\z|https?:(?://git\.|.*\.git\z)|ssh:.*\.git\z|git\+[a-z0-9]+:)!

# @return :git
# @return [:git]
def self.name
:git
end
Expand Down
2 changes: 1 addition & 1 deletion spec/recipe_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def build(vars ={}, str)
subject{ FPM::Fry::Recipe::Builder.new({}) }

{
'http://foo.bar/baz.tar.gz' => FPM::Fry::Source::Package,
'http://foo.bar/baz.tar.gz' => FPM::Fry::Source::Archive,
'http://foo.bar/baz.git' => FPM::Fry::Source::Git,
'git@foo.bar:baz/baz.git' => FPM::Fry::Source::Git,
'git+ssh://foo.bar/baz' => FPM::Fry::Source::Git,
Expand Down
51 changes: 33 additions & 18 deletions spec/source/package_spec.rb → spec/source/archive_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
require 'fpm/fry/source/package'
require 'fpm/fry/source/archive'
require 'tempfile'
require 'fileutils'
require 'webmock/rspec'
require 'rubygems/package'
describe FPM::Fry::Source::Package do
describe FPM::Fry::Source::Archive do

let(:tmpdir){
Dir.mktmpdir("fpm-fry")
Expand All @@ -26,31 +26,31 @@

it "fetches a file" do
stub_request(:get,'http://example/file.tar').to_return(body: "doesn't matter", status: 200)
src = FPM::Fry::Source::Package.new("http://example/file.tar")
src = FPM::Fry::Source::Archive.new("http://example/file.tar")
src.build_cache(tmpdir)
expect( File.read(File.join(tmpdir, 'file.tar')) ).to eq("doesn't matter")
end

it "follows redirects" do
stub_request(:get,'http://example/fileA.tar').to_return(status: 302, headers: {'Location' => 'http://example/fileB.tar'} )
stub_request(:get,'http://example/fileB.tar').to_return(body: "doesn't matter", status: 200)
src = FPM::Fry::Source::Package.new("http://example/fileA.tar")
src = FPM::Fry::Source::Archive.new("http://example/fileA.tar")
src.build_cache(tmpdir)
expect( File.read(File.join(tmpdir, 'fileA.tar')) ).to eq("doesn't matter")
end

it "doesn't follow too many redirects" do
stub_request(:get,'http://example/fileA.tar').to_return(status: 302, headers: {'Location' => 'http://example/fileB.tar'} )
stub_request(:get,'http://example/fileB.tar').to_return(status: 302, headers: {'Location' => 'http://example/fileA.tar'} )
src = FPM::Fry::Source::Package.new("http://example/fileA.tar")
src = FPM::Fry::Source::Archive.new("http://example/fileA.tar")
expect{
src.build_cache(tmpdir)
}.to raise_error( FPM::Fry::Source::CacheFailed, "Too many redirects")
end

it "reports missing files" do
stub_request(:get,'http://example/file.tar').to_return(status: 404)
src = FPM::Fry::Source::Package.new("http://example/file.tar")
src = FPM::Fry::Source::Archive.new("http://example/file.tar")
expect{
src.build_cache(tmpdir)
}.to raise_error(FPM::Fry::Source::CacheFailed, "Unable to fetch file"){|e|
Expand All @@ -64,7 +64,7 @@

it "reports wrong checksums" do
stub_request(:get,'http://example/file.tar').to_return(body: "doesn't matter", status: 200)
src = FPM::Fry::Source::Package.new("http://example/file.tar", checksum: Digest::SHA256.hexdigest("something else"))
src = FPM::Fry::Source::Archive.new("http://example/file.tar", checksum: Digest::SHA256.hexdigest("something else"))
expect{
src.build_cache(tmpdir).tar_io
}.to raise_error(FPM::Fry::Source::CacheFailed, "Checksum failed"){|e|
Expand All @@ -77,14 +77,14 @@
end

it "returns checksum as cachekey if present" do
src = FPM::Fry::Source::Package.new("http://example/file.tar", checksum: "477c34d98f9e090a4441cf82d2f1f03e64c8eb730e8c1ef39a8595e685d4df65")
src = FPM::Fry::Source::Archive.new("http://example/file.tar", checksum: "477c34d98f9e090a4441cf82d2f1f03e64c8eb730e8c1ef39a8595e685d4df65")
cache = src.build_cache(tmpdir)
expect( cache.cachekey ).to eq("477c34d98f9e090a4441cf82d2f1f03e64c8eb730e8c1ef39a8595e685d4df65")
end

it "fetches file for cachekey if no checksum present" do
stub_request(:get,'http://example/file.tar').to_return(body: "doesn't matter", status: 200)
src = FPM::Fry::Source::Package.new("http://example/file.tar")
src = FPM::Fry::Source::Archive.new("http://example/file.tar")
cache = src.build_cache(tmpdir)
expect( cache.cachekey ).to eq("477c34d98f9e090a4441cf82d2f1f03e64c8eb730e8c1ef39a8595e685d4df65")
end
Expand All @@ -103,7 +103,7 @@

it "untars a file" do
stub_request(:get,'http://example/file.tar').to_return(body: body, status: 200)
src = FPM::Fry::Source::Package.new("http://example/file.tar")
src = FPM::Fry::Source::Archive.new("http://example/file.tar")
cache = src.build_cache(tmpdir)
cache.copy_to(destdir)
expect( Dir.new(destdir).each.to_a ).to contain_exactly('.','..','foo')
Expand All @@ -114,7 +114,7 @@
context '#tar_io' do
it "untars a file" do
stub_request(:get,'http://example/file.tar').to_return(body: body, status: 200)
src = FPM::Fry::Source::Package.new("http://example/file.tar")
src = FPM::Fry::Source::Archive.new("http://example/file.tar")
cache = src.build_cache(tmpdir)
expect( cache.tar_io.read ).to eq body
end
Expand All @@ -125,7 +125,7 @@
gz.write(body)
gz.close
stub_request(:get,'http://example/file.tar.gz').to_return(body: gzbody.string, status: 200)
src = FPM::Fry::Source::Package.new("http://example/file.tar.gz")
src = FPM::Fry::Source::Archive.new("http://example/file.tar.gz")
cache = src.build_cache(tmpdir)
expect( cache.tar_io.read ).to eq body
end
Expand All @@ -146,7 +146,7 @@
context '#tar_io' do
it "unzips a zip file" do
stub_request(:get,'http://example/file.zip').to_return(body: zipfile, status: 200)
src = FPM::Fry::Source::Package.new("http://example/file.zip")
src = FPM::Fry::Source::Archive.new("http://example/file.zip")
cache = src.build_cache(tmpdir)
io = cache.tar_io
begin
Expand All @@ -161,11 +161,11 @@

it "doesn't unzip twice" do
stub_request(:get,'http://example/file.zip').to_return(body: zipfile, status: 200)
src = FPM::Fry::Source::Package.new("http://example/file.zip")
src = FPM::Fry::Source::Archive.new("http://example/file.zip")
cache = src.build_cache(tmpdir)
cache.tar_io.close

src = FPM::Fry::Source::Package.new("http://example/file.zip")
src = FPM::Fry::Source::Archive.new("http://example/file.zip")
cache = src.build_cache(tmpdir)
expect(cache).not_to receive(:copy_to)
cache.tar_io.close
Expand All @@ -178,7 +178,7 @@
context '#tar_io' do
it "tars the file" do
stub_request(:get,'http://example/dir/plainfile.bin').to_return(body: "bar", status: 200)
src = FPM::Fry::Source::Package.new('http://example/dir/plainfile.bin')
src = FPM::Fry::Source::Archive.new('http://example/dir/plainfile.bin')
cache = src.build_cache(tmpdir)
io = cache.tar_io
begin
Expand All @@ -203,7 +203,7 @@

it "copies a file" do
stub_request(:get,'http://example/dir/plainfile.bin').to_return(body: "bar", status: 200)
src = FPM::Fry::Source::Package.new('http://example/dir/plainfile.bin')
src = FPM::Fry::Source::Archive.new('http://example/dir/plainfile.bin')
cache = src.build_cache(tmpdir)
cache.copy_to(destdir)
expect( Dir.new(destdir).each.to_a ).to contain_exactly '.','..','plainfile.bin'
Expand All @@ -226,7 +226,7 @@
context '#tar_io' do
it "untars a tar file" do
stub_request(:get,'http://example/file.tar.bz2').to_return(body: tarfile, status: 200)
src = FPM::Fry::Source::Package.new("http://example/file.tar.bz2")
src = FPM::Fry::Source::Archive.new("http://example/file.tar.bz2")
cache = src.build_cache(tmpdir)
io = cache.tar_io
begin
Expand All @@ -240,4 +240,19 @@

end
end

context 'with an unknown extension' do

it 'raises an error' do
expect{
FPM::Fry::Source::Archive.new("http://example/file.unknown")
}.to raise_error(FPM::Fry::Source::Archive::UnknownArchiveType,"Unknown archive type"){|e|
expect(e.data).to include(
url: "http://example/file.unknown",
known_extensions: include(".tar",".tar.gz")
)
}
end

end
end

0 comments on commit d155619

Please sign in to comment.