Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pack_as_file method would allow the creation of a tar archive from data in memory (rather than reading files from disk) #7

Closed
halostatue opened this issue Jul 31, 2011 · 1 comment
Assignees

Comments

@halostatue
Copy link
Owner

Originally submitted by John Prince (http://rubyforge.org/users/jtprince).

The method 'pack_file' only works on real files (on disk). I implemented a method (which is very similar to pack_file)
that allows the creation of a tar archive from data in memory. To use it to create a .tgz file from data in memory:

require 'zlib'
require 'archive/tar/minitar'

file_names = ['wiley/dorky1', 'dorky2', 'an_empty_dir']
file_data_strings = ['my data', 'my data also', nil]

tgz = Zlib::GzipWriter.new(File.open('dorky_tar.tgz', 'wb'))

Archive::Tar::Minitar::Output.open(tgz) do |outp|
  file_names.zip(file_data_strings) do |name, data|
    Archive::Tar::Minitar.pack_as_file(name, data, outp)
  end
end

Index: minitar/trunk/lib/archive/tar/minitar.rb

--- minitar/trunk/lib/archive/tar/minitar.rb    (revision 215)
+++ minitar/trunk/lib/archive/tar/minitar.rb    (working copy)
@@ -12,6 +12,8 @@
 # $Id$
 #++

+require 'stringio'
+
 module Archive; end
 module Archive::Tar; end

@@ -847,6 +849,64 @@
       end
     end

+
+    # entry may be a string (the name), or it may be a hash specifying the
+    # following (showing defaults below): 
+    #   <tt>:name</tt>    *REQUIRED*
+    #   <tt>:mode</tt>    33188 (rw-r--r--) for files, 16877 (rwxr-xr-x) for dirs
+    #           (0O100644)                   (0O40755)
+    #   <tt>:uid</tt>    nil
+    #   <tt>:gid</tt>    nil
+    #   <tt>:mtime</tt>  Time.now
+    #
+    # if data == nil, then it will be created as a directory (use an empty
+    # string for a normal empty file) 
+    # note that data should be something that can be opened by StringIO
+    def pack_as_file(entry, data, outputter) #:yields action, name, stats:
+      outputter = outputter.tar if outputter.kind_of?(Archive::Tar::Minitar::Output)
+
+      stats = {}
+      stats[:uid] = nil
+      stats[:gid] = nil
+      stats[:mtime] = Time.now
+
+      if data.nil?
+        # a directory
+        stats[:size] = 4096   # is this OK???
+        stats[:mode] = 16877  # rwxr-xr-x
+      else
+        stats[:size] = data.size
+        stats[:mode] = 33188  # rw-r--r--
+      end
+
+      if entry.kind_of?(Hash)
+        name = entry[:name]
+
+        entry.each { |kk, vv| stats[kk] = vv unless vv.nil? }
+      else
+        name = entry
+      end
+
+      if data.nil?  # a directory
+        yield :dir, name, stats if block_given?
+        outputter.mkdir(name, stats)
+      else          # a file
+        outputter.add_file_simple(name, stats) do |os|
+          stats[:current] = 0
+          yield :file_start, name, stats if block_given?
+          StringIO.open(data, "rb") do |ff|
+            until ff.eof?
+              stats[:currinc] = os.write(ff.read(4096))
+              stats[:current] += stats[:currinc]
+              yield :file_progress, name, stats if block_given?
+            end
+          end
+          yield :file_done, name, stats if block_given?
+        end
+      end
+    end
+
+
       # A convenience method to packs the file provided. +entry+ may either be
       # a filename (in which case various values for the file (see below) will
       # be obtained from <tt>File#stat(entry)</tt> or a Hash with the fields:
@halostatue halostatue added this to the 1.0 milestone Jul 1, 2016
@halostatue halostatue self-assigned this Jul 1, 2016
@halostatue halostatue removed this from the 1.0 milestone Aug 6, 2024
@halostatue
Copy link
Owner Author

Added with #53

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant