downlow 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|