downlow 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +23 -0
- data/LICENSE +20 -0
- data/README.rdoc +58 -0
- data/Rakefile +63 -0
- data/downlow.gemspec +80 -0
- data/lib/downlow.rb +48 -0
- data/lib/downlow/ext/pathname.rb +201 -0
- data/lib/downlow/extractor.rb +42 -0
- data/lib/downlow/extractors/dir.rb +18 -0
- data/lib/downlow/extractors/tar_gz.rb +17 -0
- data/lib/downlow/extractors/zip.rb +18 -0
- data/lib/downlow/fetcher.rb +43 -0
- data/lib/downlow/fetchers/git.rb +22 -0
- data/lib/downlow/fetchers/github.rb +17 -0
- data/lib/downlow/fetchers/http.rb +26 -0
- data/lib/downlow/fetchers/local.rb +13 -0
- data/test/fixtures/gist_response +0 -0
- data/test/fixtures/location_response +13 -0
- data/test/fixtures/test.tar.gz +0 -0
- data/test/fixtures/test.zip +0 -0
- data/test/helper.rb +26 -0
- data/test/test_downlow.rb +50 -0
- data/test/test_downlow_extractor.rb +131 -0
- data/test/test_downlow_fetcher.rb +161 -0
- metadata +122 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Aaron Quint
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
= downlow
|
2
|
+
|
3
|
+
Downloading files on the DL
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
gem install downlow
|
8
|
+
|
9
|
+
Tested against Ruby 1.8.7 and 1.9.1
|
10
|
+
|
11
|
+
== Usage
|
12
|
+
|
13
|
+
Why is downloading and extracting files such a pain in Ruby?
|
14
|
+
|
15
|
+
Downlow to the rescue.
|
16
|
+
|
17
|
+
$ irb -rubygems -rdownlow
|
18
|
+
>> DL('http://gist.github.com/gists/290151/download', '~/Desktop/gist')
|
19
|
+
=> #<Pathname:/Users/aaronquint/Desktop/gist>
|
20
|
+
|
21
|
+
$ ls -l ~/Desktop/gist/
|
22
|
+
total 8
|
23
|
+
drwxrwxr-x 3 aaronquint aaronquint 102 Jan 30 00:17 gist290151-4d195b0fc72a4b5e52f8e2b5d1670d078c03a018
|
24
|
+
|
25
|
+
>> DL('git://github.com/quirkey/resque-status.git', '~/Desktop')
|
26
|
+
Initialized empty Git repository in /Users/aaronquint/Sites/__active/downlow/tmp/resque-status/.git/
|
27
|
+
remote: Counting objects: 323, done.
|
28
|
+
remote: Compressing objects: 100% (186/186), done.
|
29
|
+
remote: Total 323 (delta 166), reused 169 (delta 83)
|
30
|
+
Receiving objects: 100% (323/323), 42.84 KiB, done.
|
31
|
+
Resolving deltas: 100% (166/166), done.
|
32
|
+
=> #<Pathname:/Users/aaronquint/Desktop/resque-status>
|
33
|
+
|
34
|
+
Sweet.
|
35
|
+
|
36
|
+
BONUS BEATS FOR GITHUB
|
37
|
+
Downloads the tarball and extracts.
|
38
|
+
|
39
|
+
>> DL('gh://quirkey/sammy', ~/Desktop')
|
40
|
+
|
41
|
+
== Thanks
|
42
|
+
|
43
|
+
Thanks to @mxcl for the awesome pathname extensions in homebrew/
|
44
|
+
Thanks to @defunkt as I took some ideas from rip.
|
45
|
+
|
46
|
+
== Note on Patches/Pull Requests
|
47
|
+
|
48
|
+
* Fork the project.
|
49
|
+
* Make your feature addition or bug fix.
|
50
|
+
* Add tests for it. This is important so I don't break it in a
|
51
|
+
future version unintentionally.
|
52
|
+
* Commit, do not mess with rakefile, version, or history.
|
53
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
54
|
+
* Send me a pull request. Bonus points for topic branches.
|
55
|
+
|
56
|
+
== Copyright
|
57
|
+
|
58
|
+
Copyright (c) 2010 Aaron Quint. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
5
|
+
|
6
|
+
require 'downlow'
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'jeweler'
|
10
|
+
Jeweler::Tasks.new do |gem|
|
11
|
+
gem.name = "downlow"
|
12
|
+
gem.version = Downlow::VERSION
|
13
|
+
gem.summary = %Q{easy downloading and extracting API}
|
14
|
+
gem.description = %Q{Downlow provides an easy way to fetch files or archives and extract them with minimal hassle.}
|
15
|
+
gem.email = "aaron@quirkey.com"
|
16
|
+
gem.homepage = "http://github.com/quirkey/downlow"
|
17
|
+
gem.authors = ["Aaron Quint"]
|
18
|
+
|
19
|
+
gem.add_dependency "rubyzip", ">=0.9.4"
|
20
|
+
gem.add_dependency "archive-tar-minitar", ">=0.5.2"
|
21
|
+
|
22
|
+
gem.add_development_dependency "shoulda", ">= 0"
|
23
|
+
gem.add_development_dependency "fakeweb", ">= 1.2"
|
24
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
25
|
+
end
|
26
|
+
Jeweler::GemcutterTasks.new
|
27
|
+
rescue LoadError
|
28
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
29
|
+
end
|
30
|
+
|
31
|
+
require 'rake/testtask'
|
32
|
+
Rake::TestTask.new(:test) do |test|
|
33
|
+
test.libs << 'lib' << 'test'
|
34
|
+
test.pattern = 'test/**/test_*.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
|
38
|
+
begin
|
39
|
+
require 'rcov/rcovtask'
|
40
|
+
Rcov::RcovTask.new do |test|
|
41
|
+
test.libs << 'test'
|
42
|
+
test.pattern = 'test/**/test_*.rb'
|
43
|
+
test.verbose = true
|
44
|
+
end
|
45
|
+
rescue LoadError
|
46
|
+
task :rcov do
|
47
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
task :test => :check_dependencies
|
52
|
+
|
53
|
+
task :default => :test
|
54
|
+
|
55
|
+
require 'rake/rdoctask'
|
56
|
+
Rake::RDocTask.new do |rdoc|
|
57
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
58
|
+
|
59
|
+
rdoc.rdoc_dir = 'rdoc'
|
60
|
+
rdoc.title = "downlow #{version}"
|
61
|
+
rdoc.rdoc_files.include('README*')
|
62
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
63
|
+
end
|
data/downlow.gemspec
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{downlow}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Aaron Quint"]
|
12
|
+
s.date = %q{2010-01-31}
|
13
|
+
s.description = %q{Downlow provides an easy way to fetch files or archives and extract them with minimal hassle.}
|
14
|
+
s.email = %q{aaron@quirkey.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"downlow.gemspec",
|
26
|
+
"lib/downlow.rb",
|
27
|
+
"lib/downlow/ext/pathname.rb",
|
28
|
+
"lib/downlow/extractor.rb",
|
29
|
+
"lib/downlow/extractors/dir.rb",
|
30
|
+
"lib/downlow/extractors/tar_gz.rb",
|
31
|
+
"lib/downlow/extractors/zip.rb",
|
32
|
+
"lib/downlow/fetcher.rb",
|
33
|
+
"lib/downlow/fetchers/git.rb",
|
34
|
+
"lib/downlow/fetchers/github.rb",
|
35
|
+
"lib/downlow/fetchers/http.rb",
|
36
|
+
"lib/downlow/fetchers/local.rb",
|
37
|
+
"test/fixtures/gist_response",
|
38
|
+
"test/fixtures/location_response",
|
39
|
+
"test/fixtures/test.tar.gz",
|
40
|
+
"test/fixtures/test.zip",
|
41
|
+
"test/helper.rb",
|
42
|
+
"test/test_downlow.rb",
|
43
|
+
"test/test_downlow_extractor.rb",
|
44
|
+
"test/test_downlow_fetcher.rb"
|
45
|
+
]
|
46
|
+
s.homepage = %q{http://github.com/quirkey/downlow}
|
47
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
48
|
+
s.require_paths = ["lib"]
|
49
|
+
s.rubygems_version = %q{1.3.5}
|
50
|
+
s.summary = %q{easy downloading and extracting API}
|
51
|
+
s.test_files = [
|
52
|
+
"test/helper.rb",
|
53
|
+
"test/test_downlow.rb",
|
54
|
+
"test/test_downlow_extractor.rb",
|
55
|
+
"test/test_downlow_fetcher.rb"
|
56
|
+
]
|
57
|
+
|
58
|
+
if s.respond_to? :specification_version then
|
59
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
60
|
+
s.specification_version = 3
|
61
|
+
|
62
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
63
|
+
s.add_runtime_dependency(%q<rubyzip>, [">= 0.9.4"])
|
64
|
+
s.add_runtime_dependency(%q<archive-tar-minitar>, [">= 0.5.2"])
|
65
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
66
|
+
s.add_development_dependency(%q<fakeweb>, [">= 1.2"])
|
67
|
+
else
|
68
|
+
s.add_dependency(%q<rubyzip>, [">= 0.9.4"])
|
69
|
+
s.add_dependency(%q<archive-tar-minitar>, [">= 0.5.2"])
|
70
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
71
|
+
s.add_dependency(%q<fakeweb>, [">= 1.2"])
|
72
|
+
end
|
73
|
+
else
|
74
|
+
s.add_dependency(%q<rubyzip>, [">= 0.9.4"])
|
75
|
+
s.add_dependency(%q<archive-tar-minitar>, [">= 0.5.2"])
|
76
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
77
|
+
s.add_dependency(%q<fakeweb>, [">= 1.2"])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
data/lib/downlow.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'downlow/ext/pathname'
|
2
|
+
|
3
|
+
module Downlow
|
4
|
+
VERSION = '0.1.0'
|
5
|
+
|
6
|
+
def self.get(url, *args)
|
7
|
+
options = {}
|
8
|
+
first = args.shift
|
9
|
+
if first.is_a?(Hash)
|
10
|
+
# hash as argument means were setting the options
|
11
|
+
options = first
|
12
|
+
elsif first.to_s != ''
|
13
|
+
# string as argument means we're setting the destination
|
14
|
+
options[:destination] = first
|
15
|
+
end
|
16
|
+
# merge the rest as options
|
17
|
+
args.inject(options) {|o, arg| o = o.merge(arg) } if !args.empty?
|
18
|
+
# fetch to a temp dir
|
19
|
+
fetch_options = options.dup
|
20
|
+
fetch_options.delete(:destination)
|
21
|
+
path = fetch(url, fetch_options)
|
22
|
+
final_path = extract(path, options)
|
23
|
+
FileUtils.rm_r(path) # delete tmp path
|
24
|
+
final_path
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.fetch(*args)
|
28
|
+
Downlow::Fetcher.fetch(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.extract(*args)
|
32
|
+
Downlow::Extractor.extract(*args)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def DL(*args) Downlow.get(*args); end
|
38
|
+
|
39
|
+
require 'downlow/fetcher'
|
40
|
+
require 'downlow/fetchers/git'
|
41
|
+
require 'downlow/fetchers/http'
|
42
|
+
require 'downlow/fetchers/github'
|
43
|
+
require 'downlow/fetchers/local'
|
44
|
+
|
45
|
+
require 'downlow/extractor'
|
46
|
+
require 'downlow/extractors/tar_gz'
|
47
|
+
require 'downlow/extractors/zip'
|
48
|
+
require 'downlow/extractors/dir'
|
@@ -0,0 +1,201 @@
|
|
1
|
+
# Copyright 2009 Max Howell and other contributors.
|
2
|
+
#
|
3
|
+
# Redistribution and use in source and binary forms, with or without
|
4
|
+
# modification, are permitted provided that the following conditions
|
5
|
+
# are met:
|
6
|
+
#
|
7
|
+
# 1. Redistributions of source code must retain the above copyright
|
8
|
+
# notice, this list of conditions and the following disclaimer.
|
9
|
+
# 2. Redistributions in binary form must reproduce the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer in the
|
11
|
+
# documentation and/or other materials provided with the distribution.
|
12
|
+
#
|
13
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
14
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
15
|
+
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
16
|
+
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
17
|
+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
18
|
+
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
19
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
20
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
21
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
22
|
+
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
23
|
+
#
|
24
|
+
require 'pathname'
|
25
|
+
|
26
|
+
# we enhance pathname to make our code more readable
|
27
|
+
class Pathname
|
28
|
+
def install src
|
29
|
+
if src.is_a? Array
|
30
|
+
src.collect {|src| install src }
|
31
|
+
else
|
32
|
+
raise "#{src} does not exist" unless File.exist? src
|
33
|
+
mkpath
|
34
|
+
if File.symlink? src
|
35
|
+
# we use the BSD mv command because FileUtils copies the target and
|
36
|
+
# not the link! I'm beginning to wish I'd used Python quite honestly!
|
37
|
+
raise unless Kernel.system 'mv', src, to_s and $? == 0
|
38
|
+
else
|
39
|
+
# we mv when possible as it is faster and you should only be using
|
40
|
+
# this function when installing from the temporary build directory
|
41
|
+
FileUtils.mv src, to_s
|
42
|
+
end
|
43
|
+
src=Pathname.new src
|
44
|
+
return self+src.basename
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# we assume this pathname object is a file obviously
|
49
|
+
def write content
|
50
|
+
raise "Will not overwrite #{to_s}" if exist? and not ARGV.force?
|
51
|
+
dirname.mkpath
|
52
|
+
File.open(self, 'w') {|f| f.write content }
|
53
|
+
end
|
54
|
+
|
55
|
+
def cp dst
|
56
|
+
if file?
|
57
|
+
FileUtils.cp to_s, dst
|
58
|
+
else
|
59
|
+
FileUtils.cp_r to_s, dst
|
60
|
+
end
|
61
|
+
return dst
|
62
|
+
end
|
63
|
+
|
64
|
+
# extended to support the double extensions .tar.gz and .tar.bz2
|
65
|
+
def extname
|
66
|
+
/(\.tar\.(gz|bz2))$/.match to_s
|
67
|
+
return $1 if $1
|
68
|
+
return File.extname(to_s)
|
69
|
+
end
|
70
|
+
|
71
|
+
# for filetypes we support, basename without extension
|
72
|
+
def stem
|
73
|
+
return File.basename(to_s, extname)
|
74
|
+
end
|
75
|
+
|
76
|
+
# I don't trust the children.length == 0 check particularly, not to mention
|
77
|
+
# it is slow to enumerate the whole directory just to see if it is empty,
|
78
|
+
# instead rely on good ol' libc and the filesystem
|
79
|
+
def rmdir_if_possible
|
80
|
+
rmdir
|
81
|
+
true
|
82
|
+
rescue SystemCallError => e
|
83
|
+
raise unless e.errno == Errno::ENOTEMPTY::Errno or e.errno == Errno::EACCES::Errno
|
84
|
+
false
|
85
|
+
end
|
86
|
+
|
87
|
+
def chmod_R perms
|
88
|
+
require 'fileutils'
|
89
|
+
FileUtils.chmod_R perms, to_s
|
90
|
+
end
|
91
|
+
|
92
|
+
def abv
|
93
|
+
out=''
|
94
|
+
n=`find #{to_s} -type f | wc -l`.to_i
|
95
|
+
out<<"#{n} files, " if n > 1
|
96
|
+
out<<`/usr/bin/du -hd0 #{to_s} | cut -d"\t" -f1`.strip
|
97
|
+
end
|
98
|
+
|
99
|
+
# attempts to retrieve the version component of this path, so generally
|
100
|
+
# you'll call it on tarballs or extracted tarball directories, if you add
|
101
|
+
# to this please provide amend the unittest
|
102
|
+
def version
|
103
|
+
if directory?
|
104
|
+
# directories don't have extnames
|
105
|
+
stem=basename.to_s
|
106
|
+
else
|
107
|
+
stem=self.stem
|
108
|
+
end
|
109
|
+
|
110
|
+
# github tarballs are special
|
111
|
+
# we only support numbered tagged downloads
|
112
|
+
%r[github.com/.*/tarball/((\d\.)+\d)$].match to_s
|
113
|
+
return $1 if $1
|
114
|
+
|
115
|
+
# eg. boost_1_39_0
|
116
|
+
/((\d+_)+\d+)$/.match stem
|
117
|
+
return $1.gsub('_', '.') if $1
|
118
|
+
|
119
|
+
# eg. foobar-4.5.1-1
|
120
|
+
# eg. ruby-1.9.1-p243
|
121
|
+
/-((\d+\.)*\d\.\d+-(p|rc)?\d+)$/.match stem
|
122
|
+
return $1 if $1
|
123
|
+
|
124
|
+
# eg. lame-398-1
|
125
|
+
/-((\d)+-\d)/.match stem
|
126
|
+
return $1 if $1
|
127
|
+
|
128
|
+
# eg. foobar-4.5.1
|
129
|
+
/-((\d+\.)*\d+)$/.match stem
|
130
|
+
return $1 if $1
|
131
|
+
|
132
|
+
# eg. foobar-4.5.1b
|
133
|
+
/-((\d+\.)*\d+([abc]|rc\d))$/.match stem
|
134
|
+
return $1 if $1
|
135
|
+
|
136
|
+
# eg foobar-4.5.0-beta1
|
137
|
+
/-((\d+\.)*\d+-beta\d+)$/.match stem
|
138
|
+
return $1 if $1
|
139
|
+
|
140
|
+
# eg. foobar4.5.1
|
141
|
+
/((\d+\.)*\d+)$/.match stem
|
142
|
+
return $1 if $1
|
143
|
+
|
144
|
+
# eg foobar-4.5.0-bin
|
145
|
+
/-((\d+\.)+\d+[abc]?)[-.](bin|src|sources?)$/.match stem
|
146
|
+
return $1 if $1
|
147
|
+
|
148
|
+
# eg. otp_src_R13B (this is erlang's style)
|
149
|
+
# eg. astyle_1.23_macosx.tar.gz
|
150
|
+
stem.scan /_([^_]+)/ do |match|
|
151
|
+
return match.first if /\d/.match $1
|
152
|
+
end
|
153
|
+
|
154
|
+
nil
|
155
|
+
end
|
156
|
+
|
157
|
+
def md5
|
158
|
+
require 'digest'
|
159
|
+
Digest::MD5.hexdigest(File.read(self))
|
160
|
+
end
|
161
|
+
|
162
|
+
if '1.9' <= RUBY_VERSION
|
163
|
+
alias_method :to_str, :to_s
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# sets $n and $d so you can observe creation of stuff
|
168
|
+
module ObserverPathnameExtension
|
169
|
+
def unlink
|
170
|
+
super
|
171
|
+
puts "rm #{to_s}" if ARGV.verbose?
|
172
|
+
$n+=1
|
173
|
+
end
|
174
|
+
def rmdir
|
175
|
+
super
|
176
|
+
puts "rmdir #{to_s}" if ARGV.verbose?
|
177
|
+
$d+=1
|
178
|
+
end
|
179
|
+
def resolved_path_exists?
|
180
|
+
(dirname+readlink).exist?
|
181
|
+
end
|
182
|
+
def mkpath
|
183
|
+
super
|
184
|
+
puts "mkpath #{to_s}" if ARGV.verbose?
|
185
|
+
$d+=1
|
186
|
+
end
|
187
|
+
def make_relative_symlink src
|
188
|
+
dirname.mkpath
|
189
|
+
Dir.chdir dirname do
|
190
|
+
# TODO use Ruby function so we get exceptions
|
191
|
+
# NOTE Ruby functions may work, but I had a lot of problems
|
192
|
+
rv=system 'ln', '-sf', src.relative_path_from(dirname)
|
193
|
+
raise "Could not create symlink #{to_s}" unless rv and $? == 0
|
194
|
+
puts "ln #{to_s}" if ARGV.verbose?
|
195
|
+
$n+=1
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
$n=0
|
201
|
+
$d=0
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Downlow
|
2
|
+
class Extractor
|
3
|
+
|
4
|
+
def self.handles(which)
|
5
|
+
@@handlers ||= []
|
6
|
+
@@handlers << [which, self]
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.extractor_for(path)
|
10
|
+
@@handlers.each do |matcher, klass|
|
11
|
+
return klass if matcher.match path
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.extract(url, options = {})
|
16
|
+
klass = extractor_for(url)
|
17
|
+
extractor = klass.new(url, options)
|
18
|
+
extractor.extract
|
19
|
+
extractor.final_path
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :path, :options, :final_path
|
23
|
+
attr_accessor :tmp_dir, :destination
|
24
|
+
|
25
|
+
def initialize(path, options = {})
|
26
|
+
@path = Pathname.new(path)
|
27
|
+
@options = options
|
28
|
+
@tmp_dir = Pathname.new(options[:tmp_dir] || 'tmp').expand_path
|
29
|
+
@tmp_dir.mkpath
|
30
|
+
@destination = Pathname.new(options[:destination] || tmp_dir + self.path.stem).expand_path
|
31
|
+
end
|
32
|
+
|
33
|
+
def extract
|
34
|
+
raise "Should be overridden by subclass"
|
35
|
+
end
|
36
|
+
|
37
|
+
def extracted?
|
38
|
+
!!@final_path
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Downlow
|
2
|
+
class Dir < Extractor
|
3
|
+
|
4
|
+
handles(/.*$/)
|
5
|
+
|
6
|
+
def extract
|
7
|
+
if path.directory?
|
8
|
+
self.destination = destination + path.basename
|
9
|
+
destination.dirname.mkpath
|
10
|
+
else
|
11
|
+
destination.dirname.mkpath
|
12
|
+
end
|
13
|
+
path.cp destination
|
14
|
+
@final_path = destination
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
require 'archive/tar/minitar'
|
3
|
+
|
4
|
+
module Downlow
|
5
|
+
class TarGz < Extractor
|
6
|
+
|
7
|
+
handles(/\.tar\.gz$/)
|
8
|
+
|
9
|
+
def extract
|
10
|
+
destination.mkpath
|
11
|
+
tgz = ::Zlib::GzipReader.new(File.open(path, 'rb'))
|
12
|
+
::Archive::Tar::Minitar.unpack(tgz, destination.to_s)
|
13
|
+
@final_path = destination
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'zip/zip'
|
2
|
+
|
3
|
+
module Downlow
|
4
|
+
class Zip < Extractor
|
5
|
+
|
6
|
+
handles(/\.zip$/)
|
7
|
+
|
8
|
+
def extract
|
9
|
+
::Zip::ZipFile.foreach(path) do |file|
|
10
|
+
path = destination + file.name
|
11
|
+
path.dirname.mkpath
|
12
|
+
file.extract(path)
|
13
|
+
end
|
14
|
+
@final_path = destination
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Downlow
|
2
|
+
class Fetcher
|
3
|
+
|
4
|
+
def self.handles(which)
|
5
|
+
@@handlers ||= []
|
6
|
+
@@handlers << [which, self]
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.fetcher_for(url)
|
10
|
+
@@handlers.each do |matcher, klass|
|
11
|
+
return klass if matcher.match url
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.fetch(url, options = {})
|
16
|
+
klass = fetcher_for(url)
|
17
|
+
fetcher = klass.new(url, options)
|
18
|
+
fetcher.fetch
|
19
|
+
fetcher.local_path
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :url, :options, :local_path
|
23
|
+
attr_accessor :tmp_dir, :destination
|
24
|
+
|
25
|
+
def initialize(url, options = {})
|
26
|
+
@url = Pathname.new(url)
|
27
|
+
@options = options
|
28
|
+
@tmp_dir = Pathname.new(options[:tmp_dir] || 'tmp').expand_path
|
29
|
+
@tmp_dir.mkpath
|
30
|
+
@destination = Pathname.new(options[:destination] || tmp_dir + self.url.basename ).expand_path
|
31
|
+
@destination.dirname.mkpath
|
32
|
+
end
|
33
|
+
|
34
|
+
def fetch
|
35
|
+
raise "Should be overridden by subclass"
|
36
|
+
end
|
37
|
+
|
38
|
+
def fetched?
|
39
|
+
!!@local_path
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Downlow
|
2
|
+
class Git < Fetcher
|
3
|
+
|
4
|
+
handles(/^git\:\/\//)
|
5
|
+
|
6
|
+
def fetch
|
7
|
+
self.destination = destination.dirname + destination.stem
|
8
|
+
git_clone
|
9
|
+
rm_dot_git unless options[:keep_git]
|
10
|
+
@local_path = destination
|
11
|
+
end
|
12
|
+
|
13
|
+
def git_clone
|
14
|
+
system "`which git` clone #{url} #{destination.expand_path}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def rm_dot_git
|
18
|
+
FileUtils.rm_rf(destination + '.git')
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Downlow
|
2
|
+
class Github < Http
|
3
|
+
|
4
|
+
handles(/^gh\:\/\//)
|
5
|
+
|
6
|
+
def fetch
|
7
|
+
# change
|
8
|
+
# gh://quirkey/sammy
|
9
|
+
# to:
|
10
|
+
# http://github.com/quirkey/sammy/tarball/master
|
11
|
+
project = url.to_s.gsub(/^(gh\:\/\/)/, '')
|
12
|
+
@url = "http://github.com/#{project}/tarball/master"
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module Downlow
|
4
|
+
class Http < Fetcher
|
5
|
+
|
6
|
+
handles(/^http\:\/\//)
|
7
|
+
|
8
|
+
def fetch
|
9
|
+
data = ""
|
10
|
+
filename = destination.basename
|
11
|
+
open(url.to_s) do |u|
|
12
|
+
if disposition = u.meta['content-disposition'] and
|
13
|
+
disposition.match(/filename=\"([^\"]+)\"/)
|
14
|
+
filename = $1
|
15
|
+
else
|
16
|
+
filename = Pathname.new(u.base_uri.to_s).basename
|
17
|
+
end
|
18
|
+
data << u.read
|
19
|
+
end
|
20
|
+
self.destination = destination.dirname + filename
|
21
|
+
File.open(destination, 'w') {|f| f << data }
|
22
|
+
@local_path = destination
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
Binary file
|
@@ -0,0 +1,13 @@
|
|
1
|
+
HTTP/1.1 302 Found
|
2
|
+
Server: nginx/0.7.61
|
3
|
+
Date: Sun, 31 Jan 2010 01:32:51 GMT
|
4
|
+
Content-Type: text/html; charset=utf-8
|
5
|
+
Connection: keep-alive
|
6
|
+
Status: 302 Found
|
7
|
+
Location: http://github.com/quirkey-lighthouse_stats-e9012c9.tar.gz
|
8
|
+
X-Runtime: 75ms
|
9
|
+
Content-Length: 133
|
10
|
+
Set-Cookie: _github_ses=BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7AA%3D%3D--884981fc5aa85daf318eeff084d98e2cff92578f; path=/; expires=Wed, 01 Jan 2020 08:00:00 GMT; HttpOnly
|
11
|
+
Cache-Control: no-cache
|
12
|
+
|
13
|
+
<html><body>You are being <a href="http://waitdownload.github.com/quirkey-lighthouse_stats-e9012c9.zip">redirected</a>.</body></html>
|
Binary file
|
Binary file
|
data/test/helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'fakeweb'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
require 'downlow'
|
9
|
+
|
10
|
+
class Test::Unit::TestCase
|
11
|
+
|
12
|
+
def tmp_dir
|
13
|
+
dir = File.join('/tmp', 'downlow')
|
14
|
+
FileUtils.mkdir_p(dir)
|
15
|
+
dir
|
16
|
+
end
|
17
|
+
|
18
|
+
def fixture_path(path)
|
19
|
+
full_path = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', path))
|
20
|
+
end
|
21
|
+
|
22
|
+
def fixture(path)
|
23
|
+
File.read(fixture_path(path))
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestDownlow < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "Downlow" do
|
6
|
+
setup do
|
7
|
+
FileUtils.rm_rf(tmp_dir) if File.readable?(tmp_dir)
|
8
|
+
end
|
9
|
+
|
10
|
+
context ".get" do
|
11
|
+
should "fetch a gzip then extract it" do
|
12
|
+
url = 'http://example.org/example.tar.gz'
|
13
|
+
FakeWeb.register_uri(:get, url, :body => fixture('test.tar.gz'))
|
14
|
+
path = Downlow.get(url, :destination => File.join(tmp_dir, 'final'))
|
15
|
+
assert path.is_a?(Pathname)
|
16
|
+
assert_match(/final/, path.to_s)
|
17
|
+
assert (path + 'test/test.jpg').readable?
|
18
|
+
end
|
19
|
+
|
20
|
+
should "assume string as second arg is destination" do
|
21
|
+
url = 'http://example.org/example.tar.gz'
|
22
|
+
FakeWeb.register_uri(:get, url, :body => fixture('test.tar.gz'))
|
23
|
+
path = Downlow.get(url, File.join(tmp_dir, 'final'))
|
24
|
+
assert path.is_a?(Pathname)
|
25
|
+
assert_match(/final/, path.to_s)
|
26
|
+
assert (path + 'test/test.jpg').readable?
|
27
|
+
end
|
28
|
+
|
29
|
+
should "fetch a single file to a destination" do
|
30
|
+
url = 'http://example.org/example.js'
|
31
|
+
FakeWeb.register_uri(:get, url, :body => fixture('sammy.git/lib/sammy.js'))
|
32
|
+
path = Downlow.get(url, File.join(tmp_dir, 'final'))
|
33
|
+
assert path.is_a?(Pathname)
|
34
|
+
assert_match(/final/, path.to_s)
|
35
|
+
assert path.file?
|
36
|
+
end
|
37
|
+
|
38
|
+
should "move a single file to a destination" do
|
39
|
+
path = Downlow.get(fixture_path('sammy.git/lib/sammy.js'), File.join(tmp_dir, 'final'))
|
40
|
+
assert path.is_a?(Pathname)
|
41
|
+
assert_match(/final/, path.to_s)
|
42
|
+
assert path.file?
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestDownlowExtractor < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "Downlow::Extractor" do
|
6
|
+
setup do
|
7
|
+
FileUtils.rm_rf(tmp_dir) if File.readable?(tmp_dir)
|
8
|
+
end
|
9
|
+
|
10
|
+
context ".extract" do
|
11
|
+
setup do
|
12
|
+
@path = fixture_path('test.zip')
|
13
|
+
@final_path = Downlow::Extractor.extract(@path, {:destination => tmp_dir})
|
14
|
+
end
|
15
|
+
|
16
|
+
should "extract the files" do
|
17
|
+
assert @final_path.is_a?(Pathname)
|
18
|
+
assert @final_path.directory?
|
19
|
+
assert_match(/tmp/, @final_path.to_s)
|
20
|
+
assert File.readable?(@final_path + 'test/test.jpg')
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
context ".extractor_for" do
|
26
|
+
|
27
|
+
should 'determine the fetcher by path' do
|
28
|
+
assert_equal Downlow::TarGz, Downlow::Extractor.extractor_for(fixture_path('test.tar.gz'))
|
29
|
+
assert_equal Downlow::Zip, Downlow::Extractor.extractor_for(fixture_path('test.zip'))
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
context "initializing" do
|
35
|
+
setup do
|
36
|
+
@path = fixture_path('test.zip')
|
37
|
+
@extractor = Downlow::Zip.new(@path, {:tmp_dir => tmp_dir})
|
38
|
+
end
|
39
|
+
|
40
|
+
should "set the path" do
|
41
|
+
assert_equal @path, @extractor.path.to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
should "set the options" do
|
45
|
+
assert_equal tmp_dir, @extractor.options[:tmp_dir]
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
context "extract" do
|
51
|
+
|
52
|
+
context "zip" do
|
53
|
+
setup do
|
54
|
+
@extractor = Downlow::Zip.new(fixture_path('test.zip'), :destination => tmp_dir)
|
55
|
+
@path = @extractor.extract
|
56
|
+
end
|
57
|
+
|
58
|
+
should 'extract to the destination' do
|
59
|
+
assert @path.is_a?(Pathname)
|
60
|
+
assert @path.directory?
|
61
|
+
assert_match(/tmp/, @path.to_s)
|
62
|
+
assert (@path + 'test/test.jpg').readable?
|
63
|
+
end
|
64
|
+
|
65
|
+
should "set the local path" do
|
66
|
+
assert_equal @path, @extractor.final_path
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
context "tar.gz" do
|
73
|
+
setup do
|
74
|
+
@extractor = Downlow::TarGz.new(fixture_path('test.tar.gz'), :destination => tmp_dir)
|
75
|
+
@path = @extractor.extract
|
76
|
+
end
|
77
|
+
|
78
|
+
should 'extract to the destination' do
|
79
|
+
assert @path.is_a?(Pathname)
|
80
|
+
assert @path.directory?
|
81
|
+
assert_match(/tmp/, @path.to_s)
|
82
|
+
assert (@path + 'test/test.jpg').readable?
|
83
|
+
end
|
84
|
+
|
85
|
+
should "set the final_path" do
|
86
|
+
assert_equal @path, @extractor.final_path
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "dir" do
|
91
|
+
setup do
|
92
|
+
@extractor = Downlow::Dir.new(fixture_path(''), :destination => tmp_dir)
|
93
|
+
@path = @extractor.extract
|
94
|
+
end
|
95
|
+
|
96
|
+
should 'extract to the destination' do
|
97
|
+
assert @path.is_a?(Pathname)
|
98
|
+
assert @path.directory?
|
99
|
+
assert_match(/tmp/, @path.to_s)
|
100
|
+
assert (@path + 'test.tar.gz').readable?
|
101
|
+
end
|
102
|
+
|
103
|
+
should "set the final_path" do
|
104
|
+
assert_equal @path, @extractor.final_path
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "single file" do
|
109
|
+
setup do
|
110
|
+
@destination = File.join(tmp_dir, "sammy.js")
|
111
|
+
@extractor = Downlow::Dir.new(fixture_path('sammy.git/lib/sammy.js'), :destination => @destination)
|
112
|
+
@path = @extractor.extract
|
113
|
+
end
|
114
|
+
|
115
|
+
should 'extract to the exact destination' do
|
116
|
+
assert @path.is_a?(Pathname)
|
117
|
+
assert @path.file?
|
118
|
+
assert_match(/tmp/, @path.to_s)
|
119
|
+
assert @path.readable?
|
120
|
+
assert_equal @destination, @path.to_s
|
121
|
+
end
|
122
|
+
|
123
|
+
should "set the final_path" do
|
124
|
+
assert_equal @path, @extractor.final_path
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestDownlowFetcher < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "Downlow::Fetcher" do
|
6
|
+
setup do
|
7
|
+
FileUtils.rm_rf(tmp_dir) if File.readable?(tmp_dir)
|
8
|
+
@url = 'http://github.com/quirkey/sammy/'
|
9
|
+
FakeWeb.register_uri(:get, @url, :body => 'quirkey.com Sammy')
|
10
|
+
end
|
11
|
+
|
12
|
+
context ".fetch" do
|
13
|
+
setup do
|
14
|
+
@path = Downlow::Fetcher.fetch(@url, {:tmp_dir => tmp_dir})
|
15
|
+
end
|
16
|
+
|
17
|
+
should "fetch the files" do
|
18
|
+
assert @path.is_a?(Pathname)
|
19
|
+
assert @path.file?
|
20
|
+
assert_match(/tmp/, @path.to_s)
|
21
|
+
assert_match(/quirkey/, @path.read)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
context ".fetcher_for" do
|
27
|
+
|
28
|
+
should 'determine the fetcher by URL' do
|
29
|
+
assert_equal Downlow::Git, Downlow::Fetcher.fetcher_for('git://github.com/quirkey/sammy.git')
|
30
|
+
assert_equal Downlow::Http, Downlow::Fetcher.fetcher_for('http://github.com/quirkey/sammy/')
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
context "initializing" do
|
36
|
+
setup do
|
37
|
+
@url = 'http://github.com/quirkey/sammy/'
|
38
|
+
@fetcher = Downlow::Http.new(@url, {:tmp_dir => tmp_dir})
|
39
|
+
end
|
40
|
+
|
41
|
+
should "set the url" do
|
42
|
+
assert_equal @url, @fetcher.url.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
should "set the options" do
|
46
|
+
assert_equal tmp_dir, @fetcher.options[:tmp_dir]
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
context "fetch" do
|
52
|
+
|
53
|
+
context "git" do
|
54
|
+
setup do
|
55
|
+
class Downlow::Git
|
56
|
+
def git_clone
|
57
|
+
FileUtils.cp_r(File.join(File.dirname(__FILE__), 'fixtures', 'sammy.git'), destination)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
@fetcher = Downlow::Git.new('git://github.com/quirkey/sammy.git', :tmp_dir => tmp_dir)
|
61
|
+
@path = @fetcher.fetch
|
62
|
+
end
|
63
|
+
|
64
|
+
should 'clone a git repo to the temp dir' do
|
65
|
+
assert @path.is_a?(Pathname)
|
66
|
+
assert @path.directory?
|
67
|
+
assert_match(/tmp/, @path.to_s)
|
68
|
+
assert (@path + 'lib/sammy.js').readable?
|
69
|
+
end
|
70
|
+
|
71
|
+
should "set the local path" do
|
72
|
+
assert_equal @path, @fetcher.local_path
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
context "http" do
|
78
|
+
setup do
|
79
|
+
@fetcher = Downlow::Http.new(@url, :tmp_dir => tmp_dir)
|
80
|
+
@path = @fetcher.fetch
|
81
|
+
end
|
82
|
+
|
83
|
+
should 'download the file to the temp dir' do
|
84
|
+
assert @path.is_a?(Pathname)
|
85
|
+
assert @path.file?
|
86
|
+
assert_match(/tmp/, @path.to_s)
|
87
|
+
assert_match(/quirkey/, @path.read)
|
88
|
+
end
|
89
|
+
|
90
|
+
should "set the local path" do
|
91
|
+
assert_equal @path, @fetcher.local_path
|
92
|
+
end
|
93
|
+
|
94
|
+
should "respect content-disposition headers" do
|
95
|
+
gist_url = "http://gist.github.com/gists/290151/download"
|
96
|
+
FakeWeb.register_uri(:get, gist_url, :response => fixture('gist_response'))
|
97
|
+
@fetcher = Downlow::Http.new(gist_url, :tmp_dir => tmp_dir)
|
98
|
+
@path = @fetcher.fetch
|
99
|
+
assert @path.is_a?(Pathname)
|
100
|
+
assert @path.file?
|
101
|
+
assert_match(/\.tar\.gz$/, @path.to_s)
|
102
|
+
end
|
103
|
+
|
104
|
+
should "respect location headers" do
|
105
|
+
url = "http://github.com/quirkey/lighthouse_stats/tarball/master"
|
106
|
+
location_url = "http://github.com/quirkey-lighthouse_stats-e9012c9.tar.gz"
|
107
|
+
FakeWeb.register_uri(:get, url, :response => fixture('location_response'))
|
108
|
+
FakeWeb.register_uri(:get, location_url, :body => "BODY")
|
109
|
+
@fetcher = Downlow::Http.new(url, :tmp_dir => tmp_dir)
|
110
|
+
@path = @fetcher.fetch
|
111
|
+
assert @path.is_a?(Pathname)
|
112
|
+
assert @path.file?
|
113
|
+
assert_match(/\.tar\.gz$/, @path.to_s)
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
context "github" do
|
119
|
+
|
120
|
+
setup do
|
121
|
+
@url = 'gh://quirkey/sammy'
|
122
|
+
@real_url = "http://github.com/quirkey/sammy/tarball/master"
|
123
|
+
FakeWeb.register_uri(:get, @real_url, :response => fixture('gist_response'))
|
124
|
+
@fetcher = Downlow::Github.new(@url, :tmp_dir => tmp_dir)
|
125
|
+
@path = @fetcher.fetch
|
126
|
+
end
|
127
|
+
|
128
|
+
should "reset the url to the tarball url" do
|
129
|
+
assert_equal @real_url, @fetcher.url
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "file" do
|
134
|
+
setup do
|
135
|
+
@fetcher = Downlow::Local.new(File.join(File.dirname(__FILE__), '..', 'lib'), :tmp_dir => tmp_dir)
|
136
|
+
@path = @fetcher.fetch
|
137
|
+
end
|
138
|
+
|
139
|
+
should "move directory into temp dir" do
|
140
|
+
assert @path.is_a?(Pathname)
|
141
|
+
assert @path.directory?
|
142
|
+
assert_match(/tmp/, @path.to_s)
|
143
|
+
assert (@path + 'downlow.rb').readable?
|
144
|
+
end
|
145
|
+
|
146
|
+
should "set the local path" do
|
147
|
+
assert_equal @path, @fetcher.local_path
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
context "ftp" do
|
153
|
+
should_eventually "download via ftp" do
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: downlow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aaron Quint
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-31 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rubyzip
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.9.4
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: archive-tar-minitar
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.5.2
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: shoulda
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: fakeweb
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "1.2"
|
54
|
+
version:
|
55
|
+
description: Downlow provides an easy way to fetch files or archives and extract them with minimal hassle.
|
56
|
+
email: aaron@quirkey.com
|
57
|
+
executables: []
|
58
|
+
|
59
|
+
extensions: []
|
60
|
+
|
61
|
+
extra_rdoc_files:
|
62
|
+
- LICENSE
|
63
|
+
- README.rdoc
|
64
|
+
files:
|
65
|
+
- .document
|
66
|
+
- .gitignore
|
67
|
+
- LICENSE
|
68
|
+
- README.rdoc
|
69
|
+
- Rakefile
|
70
|
+
- downlow.gemspec
|
71
|
+
- lib/downlow.rb
|
72
|
+
- lib/downlow/ext/pathname.rb
|
73
|
+
- lib/downlow/extractor.rb
|
74
|
+
- lib/downlow/extractors/dir.rb
|
75
|
+
- lib/downlow/extractors/tar_gz.rb
|
76
|
+
- lib/downlow/extractors/zip.rb
|
77
|
+
- lib/downlow/fetcher.rb
|
78
|
+
- lib/downlow/fetchers/git.rb
|
79
|
+
- lib/downlow/fetchers/github.rb
|
80
|
+
- lib/downlow/fetchers/http.rb
|
81
|
+
- lib/downlow/fetchers/local.rb
|
82
|
+
- test/fixtures/gist_response
|
83
|
+
- test/fixtures/location_response
|
84
|
+
- test/fixtures/test.tar.gz
|
85
|
+
- test/fixtures/test.zip
|
86
|
+
- test/helper.rb
|
87
|
+
- test/test_downlow.rb
|
88
|
+
- test/test_downlow_extractor.rb
|
89
|
+
- test/test_downlow_fetcher.rb
|
90
|
+
has_rdoc: true
|
91
|
+
homepage: http://github.com/quirkey/downlow
|
92
|
+
licenses: []
|
93
|
+
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options:
|
96
|
+
- --charset=UTF-8
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: "0"
|
104
|
+
version:
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: "0"
|
110
|
+
version:
|
111
|
+
requirements: []
|
112
|
+
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 1.3.5
|
115
|
+
signing_key:
|
116
|
+
specification_version: 3
|
117
|
+
summary: easy downloading and extracting API
|
118
|
+
test_files:
|
119
|
+
- test/helper.rb
|
120
|
+
- test/test_downlow.rb
|
121
|
+
- test/test_downlow_extractor.rb
|
122
|
+
- test/test_downlow_fetcher.rb
|