tardotgz 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9acd07e3ea9d916e486115af4896ff6429134978
4
+ data.tar.gz: 88cfd8afdb870471c0bda5c470369594570840fc
5
+ SHA512:
6
+ metadata.gz: f62e00b6fb2d2459ef105959a8fb1ffcab87573f16fc3cab9ea8a3d56e4fd1066a4ef4914c53f8a30fa5b7b4899b57ec8950402035e8bd8c9242d440dea09244
7
+ data.tar.gz: 5e7ebb7f89d0fe411acb368633a78fe1037620b0c497901fbfa2091ee22149e1c5fc6ff80f3e4dad5878283a73eb4aea58fc6025acaa470a2ec37b2b1e3a2452
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ scratchpad
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ..gemspec
4
+ gemspec
@@ -0,0 +1,163 @@
1
+ # Tardotgz
2
+
3
+ Tardotgz is an extraction of a few archive utility methods I wrote while working on a project at GitHub. These methods simplify the creation of gzipped tarball archives and the reading and extraction of files from those archives.
4
+
5
+ One of the unique features of the #read_from_archive and #extract_from_archive utility methods is the ability to pass them a block (in fact `#extract_from_archive` just calls `#read_from_archive` and passes it a block).
6
+
7
+ And in case you were wondering, I've been pronouncing it "tar-dot-jeez" :grin:
8
+
9
+ ## Installation
10
+
11
+ You can install at the command line:
12
+
13
+ ```bash
14
+ $ gem install tardotgz
15
+ ```
16
+
17
+ Or add the gem to your Gemfile:
18
+
19
+ ```ruby
20
+ source "https://rubygems.org"
21
+
22
+ gem "tardotgz"
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ Start by including the module into the class where you'll use it.
28
+
29
+ ```ruby
30
+ require "tardotgz"
31
+
32
+ class FruitRollup
33
+ include Tardotgz
34
+ end
35
+ ```
36
+
37
+ ### Create an archive
38
+
39
+ Create an archive from a folder by calling `#create_archive` with the source path (the directory or file you want to archive) and the target path (the path and filename for the archive that it creates).
40
+
41
+ ```ruby
42
+ > fr = FruitRollup.new
43
+ => #<FruitRollup:0x007fc0e4acf538>
44
+ > source_path = File.expand_path("~/Notes")
45
+ => "/Users/jonmagic/Notes"
46
+ > archive_path = File.expand_path("~/Dropbox/notes.tar.gz")
47
+ => "/Users/jonmagic/Dropbox/notes.tar.gz"
48
+ > fr.create_archive(source_path, archive_path)
49
+ => "/Users/jonmagic/Dropbox/notes.tar.gz"
50
+ ```
51
+
52
+ ### Read file(s) from an archive
53
+
54
+ You can read the contents of a file (or files) in an archive without unzipping or untarring the archive by using the `#read_from_archive` method. It's use is also fairly flexible.
55
+
56
+ #### Read the contents of a single file
57
+
58
+ ```ruby
59
+ > fr.read_from_archive(archive_path, "testing1.md")
60
+ => "hello world\n"
61
+ ```
62
+
63
+ #### Read the contents of files matching a pattern
64
+
65
+ ```ruby
66
+ > fr.read_from_archive(archive_path, /testing\d.md/) # read all files matching pattern
67
+ => "hello world\nfoobarbaz\n"
68
+ ```
69
+
70
+ #### Passing a block yields the block with each tarfile that matches the pattern
71
+
72
+ ```ruby
73
+ > fr.read_from_archive(archive_path, /testing\d.md/) do |tarfile| # pass a block
74
+ * puts tarfile.read.upcase
75
+ * end
76
+ HELLO WORLD
77
+
78
+ FOOBARBAZ
79
+
80
+ => nil
81
+ ```
82
+
83
+ ### Extract file(s) from an archive
84
+
85
+ You can extract the contents of an archive with #extract_from_archive.
86
+
87
+ #### Extract a single file
88
+
89
+ ```ruby
90
+ > destination_path = File.expand_path("~/Restored notes")
91
+ => "/Users/jonmagic/Restored notes"
92
+ > fr.extract_from_archive(archive_path, destination_path, "testing1.md")
93
+ => "/Users/jonmagic/Restored notes"
94
+ > File.exist?("#{destination_path}/testing1.md")
95
+ => true
96
+ > File.exist?("#{destination_path}/testing2.md")
97
+ => false
98
+ ```
99
+
100
+ #### Extract all files matching a pattern
101
+
102
+ ```ruby
103
+ > fr.extract_from_archive(archive_path, destination_path, /testing\d\.md/)
104
+ => "/Users/jonmagic/Restored notes"
105
+ > File.exist?("#{destination_path}/testing1.md")
106
+ => true
107
+ > File.exist?("#{destination_path}/testing2.md")
108
+ => true
109
+ ```
110
+
111
+ #### Passing a block cleans up extracted files after extracting and then yielding the block
112
+
113
+ ```ruby
114
+ > fr.extract_from_archive(archive_path, destination_path, /testing\d\.md/) do
115
+ * puts File.exist?("#{destination_path}/testing1.md")
116
+ * puts File.exist?("#{destination_path}/testing2.md")
117
+ * end
118
+ true
119
+ true
120
+ => nil
121
+ > File.exist?(destination_path)
122
+ => false
123
+ ```
124
+
125
+ ## Contribute
126
+
127
+ If you'd like to hack on Tardotgz, start by forking the repo on GitHub:
128
+
129
+ https://github.com/jonmagic/tardotgz
130
+
131
+ The best way to get your changes merged back into core is as follows:
132
+
133
+ 1. Clone down your fork
134
+ 1. Create a thoughtfully named topic branch to contain your change
135
+ 1. Hack away
136
+ 1. If you are adding new functionality, document it in the README
137
+ 1. If necessary, rebase your commits into logical chunks, without errors
138
+ 1. Push the branch up to GitHub
139
+ 1. Send a pull request for your branch
140
+
141
+ ## LICENSE
142
+
143
+ The MIT License (MIT)
144
+
145
+ Copyright (c) 2015 Jonathan Hoyt
146
+
147
+ Permission is hereby granted, free of charge, to any person obtaining a copy
148
+ of this software and associated documentation files (the "Software"), to deal
149
+ in the Software without restriction, including without limitation the rights
150
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
151
+ copies of the Software, and to permit persons to whom the Software is
152
+ furnished to do so, subject to the following conditions:
153
+
154
+ The above copyright notice and this permission notice shall be included in all
155
+ copies or substantial portions of the Software.
156
+
157
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
158
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
159
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
160
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
161
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
162
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
163
+ SOFTWARE.
@@ -0,0 +1,8 @@
1
+ require "rake/testtask"
2
+
3
+ Rake::TestTask.new(:test) do |t|
4
+ t.libs << "test"
5
+ t.test_files = FileList["test/**/*_test.rb"]
6
+ end
7
+
8
+ task :default => :test
@@ -0,0 +1,135 @@
1
+ require "fileutils"
2
+ require "pathname"
3
+ require "rubygems/package"
4
+ require "tempfile"
5
+ require "zlib"
6
+
7
+ module Tardotgz
8
+ # Public: Create a gzipped archive with the contents of source_path.
9
+ #
10
+ # source_path - Pathname or String path to files that need archived.
11
+ # archive_path - Pathname or String path and filename for created archive.
12
+ #
13
+ # Returns Pathname or String archive_path.
14
+ def create_archive(source_path, archive_path)
15
+ unless File.readable?(source_path)
16
+ raise Errno::ENOENT.new(source_path.to_s)
17
+ end
18
+
19
+ unless File.writable?(Pathname(archive_path).dirname)
20
+ raise Errno::EACCES.new(archive_path.to_s)
21
+ end
22
+
23
+ tarfile = Tempfile.new(Pathname(archive_path).basename.to_s)
24
+
25
+ Gem::Package::TarWriter.new(tarfile) do |tar|
26
+ Dir[File.join(source_path.to_s, "**/*")].each do |file|
27
+ mode = File.stat(file).mode
28
+ relative_file = file.sub /^#{Regexp::escape source_path.to_s}\/?/, ''
29
+
30
+ if File.directory?(file)
31
+ tar.mkdir relative_file, mode
32
+ else
33
+ tar.add_file relative_file, mode do |tf|
34
+ File.open(file, "rb") { |f| tf.write f.read }
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ tarfile.rewind
41
+
42
+ File.open(archive_path, "wb") do |gz|
43
+ z = Zlib::GzipWriter.new(gz)
44
+ z.write tarfile.read
45
+ z.close
46
+ tarfile.close
47
+ end
48
+
49
+ return archive_path
50
+ end
51
+
52
+ # Public: Read and return file(s) contents from archive or yield block
53
+ # with each files contents as it is read.
54
+ #
55
+ # archive_path - Pathname or String path to archive.
56
+ # pattern - String relative file path or Regexp pattern for selecting
57
+ # multiple files.
58
+ #
59
+ # Returns a String (or NilClass if block given).
60
+ def read_from_archive(archive_path, pattern)
61
+ results = []
62
+
63
+ Zlib::GzipReader.open(archive_path) do |gz|
64
+ Gem::Package::TarReader.new(gz) do |tar|
65
+ case pattern
66
+ when String
67
+ tarfile = tar.detect do |tarfile|
68
+ tarfile.full_name == pattern
69
+ end
70
+
71
+ if tarfile
72
+ if block_given?
73
+ yield(tarfile)
74
+ return nil
75
+ else
76
+ results << tarfile.read
77
+ end
78
+ end
79
+ when Regexp
80
+ tar.each do |tarfile|
81
+ if tarfile.full_name =~ pattern
82
+ if block_given?
83
+ yield(tarfile)
84
+ else
85
+ results << tarfile.read
86
+ end
87
+ end
88
+ end
89
+
90
+ return nil if block_given?
91
+ end
92
+ end
93
+ end
94
+
95
+ if results.empty?
96
+ message = pattern.is_a?(Regexp) ? pattern.inspect : pattern
97
+ raise Errno::ENOENT.new(message)
98
+ end
99
+
100
+ results.join
101
+ end
102
+
103
+ # Public: Extract file(s) from archive to destination path and optionally
104
+ # cleanup extracted files after yielding a block if it is provided.
105
+ #
106
+ # archive_path - Pathname or String path to archive.
107
+ # destination_path - Pathname or String destination path for files.
108
+ # pattern - String relative file path or Regexp pattern for
109
+ # selecting multiple files.
110
+ #
111
+ # Returns Pathname or String destination_path (or NilClass if block given).
112
+ def extract_from_archive(archive_path, destination_path, pattern=/.*/, &block)
113
+ read_from_archive(archive_path, pattern) do |tarfile|
114
+ destination_file = File.join(destination_path, tarfile.full_name)
115
+
116
+ if tarfile.directory?
117
+ FileUtils.mkdir_p(destination_file)
118
+ else
119
+ destination_directory = File.dirname(destination_file)
120
+ FileUtils.mkdir_p(destination_directory) unless File.directory?(destination_directory)
121
+ File.open(destination_file, "wb") do |f|
122
+ f.write(tarfile.read)
123
+ end
124
+ end
125
+ end
126
+
127
+ if block_given? && File.exist?(destination_path)
128
+ yield
129
+ FileUtils.rm_rf(destination_path, :secure => true)
130
+ return nil
131
+ else
132
+ return destination_path
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "tardotgz"
5
+ spec.version = "1.0.2"
6
+ spec.platform = Gem::Platform::RUBY
7
+ spec.date = "2015-02-22"
8
+ spec.summary = "Archive utility module"
9
+ spec.description = "Methods for creating, reading, and extracting gzipped tarballs."
10
+ spec.authors = ["Jonathan Hoyt"]
11
+ spec.email = "jonmagic@gmail.com"
12
+ spec.files = ["lib/tardotgz.rb"]
13
+ spec.homepage = "https://github.com/jonmagic/tardotgz"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split("\n")
17
+ spec.test_files = `git ls-files -- {test}/*`.split("\n")
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.6"
21
+ spec.add_development_dependency "rake", "~> 10.4"
22
+ spec.add_development_dependency "minitest", "~> 5.5"
23
+ end
@@ -0,0 +1,127 @@
1
+ require_relative "../test_helper"
2
+
3
+ class TardotgzTest < Minitest::Test
4
+ include Tardotgz
5
+
6
+ def test_that_constant_is_defined
7
+ assert_equal "constant", defined?(Tardotgz)
8
+ end
9
+
10
+ def test_that_it_is_a_module
11
+ assert_equal Module, Tardotgz.class
12
+ end
13
+
14
+ def test_create_archive_creates_archive
15
+ source_path = path_helper("lib")
16
+ archive_path = path_helper("lib.tar.gz")
17
+ assert_equal archive_path, create_archive(source_path, archive_path)
18
+
19
+ assert File.exist?(archive_path)
20
+ File.delete(archive_path)
21
+ end
22
+
23
+ def test_create_archive_raises_error_if_source_path_is_not_readable
24
+ source_path = path_helper("foobarbaz")
25
+ archive_path = path_helper("lib.tar.gz")
26
+
27
+ assert_raises(Errno::ENOENT) do
28
+ create_archive(source_path, archive_path)
29
+ end
30
+ end
31
+
32
+ def test_create_archive_raises_error_if_archive_path_is_not_writable
33
+ source_path = path_helper("lib")
34
+ archive_path = "/foo.tar.gz"
35
+
36
+ assert_raises(Errno::EACCES) do
37
+ create_archive(source_path, archive_path)
38
+ end
39
+ end
40
+
41
+ def test_read_from_archive_returns_contents_of_file_matching_pattern_string
42
+ archive_path = path_helper("test/fixtures/archive.tar.gz")
43
+ pattern = "testing1.md"
44
+
45
+ assert_equal "hello world\n", read_from_archive(archive_path, pattern)
46
+ end
47
+
48
+ def test_read_from_archive_returns_contents_of_files_matching_pattern_regexp
49
+ archive_path = path_helper("test/fixtures/archive.tar.gz")
50
+ pattern = /testing\d\.md/
51
+
52
+ assert_equal "hello world\nfoobarbaz\n", read_from_archive(archive_path, pattern)
53
+ end
54
+
55
+ def test_read_from_archive_yields_block_for_each_file_matching_pattern
56
+ archive_path = path_helper("test/fixtures/archive.tar.gz")
57
+ pattern = /testing\d\.md/
58
+ expected_results = [
59
+ "hello world\n",
60
+ "foobarbaz\n"
61
+ ]
62
+
63
+ result = read_from_archive(archive_path, pattern) do |tarfile|
64
+ assert expected_results.include?(tarfile.read)
65
+ end
66
+
67
+ assert_nil result
68
+ end
69
+
70
+ def test_read_from_archive_raises_error_if_archive_does_not_exist
71
+ archive_path = path_helper("foobarbaz.tar.gz")
72
+
73
+ assert_raises(Errno::ENOENT) do
74
+ read_from_archive(archive_path, "foo")
75
+ end
76
+ end
77
+
78
+ def test_read_from_archive_raises_error_if_pattern_does_not_match_any_files
79
+ archive_path = path_helper("test/fixtures/archive.tar.gz")
80
+
81
+ assert_raises(Errno::ENOENT) do
82
+ read_from_archive(archive_path, "foobarbaz")
83
+ end
84
+
85
+ assert_raises(Errno::ENOENT) do
86
+ read_from_archive(archive_path, /drunken\/noodle/)
87
+ end
88
+ end
89
+
90
+ def test_extract_from_archive_writes_archive_contents_for_string_pattern_to_disk
91
+ archive_path = path_helper("test/fixtures/archive.tar.gz")
92
+ destination_path = path_helper(".tarball-extract-tmp")
93
+ pattern = "testing1.md"
94
+
95
+ assert_equal destination_path, extract_from_archive(archive_path, destination_path, pattern)
96
+ assert File.exist?(destination_path.join("testing1.md"))
97
+
98
+ FileUtils.rm_rf(destination_path, :secure => true)
99
+ end
100
+
101
+ def test_extract_from_archive_writes_archive_contents_for_regexp_pattern_to_disk
102
+ archive_path = path_helper("test/fixtures/archive.tar.gz")
103
+ destination_path = path_helper(".tarball-extract-tmp")
104
+ pattern = /testing\d\.md/
105
+
106
+ assert_equal destination_path, extract_from_archive(archive_path, destination_path, pattern)
107
+ assert File.exist?(destination_path.join("testing1.md"))
108
+ assert File.exist?(destination_path.join("testing2.md"))
109
+
110
+ FileUtils.rm_rf(destination_path, :secure => true)
111
+ end
112
+
113
+ def test_extract_from_archive_accepts_a_block_and_cleans_up_after_yield
114
+ archive_path = path_helper("test/fixtures/archive.tar.gz")
115
+ destination_path = path_helper(".tarball-extract-tmp")
116
+ pattern = /testing\d\.md/
117
+
118
+ result = extract_from_archive(archive_path, destination_path, pattern) do
119
+ assert File.exist?(destination_path.join("testing1.md"))
120
+ assert File.exist?(destination_path.join("testing2.md"))
121
+ end
122
+
123
+ assert_nil result
124
+ refute File.exist?(destination_path)
125
+ end
126
+
127
+ end
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ require "tardotgz"
3
+ require "minitest/autorun"
4
+ require "pathname"
5
+
6
+ def path_helper(path_relative_to_project_root)
7
+ project_root = File.expand_path("../", File.dirname(__FILE__))
8
+ Pathname(project_root).join(path_relative_to_project_root)
9
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tardotgz
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Jonathan Hoyt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.5'
55
+ description: Methods for creating, reading, and extracting gzipped tarballs.
56
+ email: jonmagic@gmail.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - ".gitignore"
62
+ - Gemfile
63
+ - README.md
64
+ - Rakefile
65
+ - lib/tardotgz.rb
66
+ - tardotgz.gemspec
67
+ - test/fixtures/archive.tar.gz
68
+ - test/lib/tardotgz_test.rb
69
+ - test/test_helper.rb
70
+ homepage: https://github.com/jonmagic/tardotgz
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.2.2
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Archive utility module
94
+ test_files: []