tardotgz 1.0.2

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.
@@ -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: []