class Gem::Package::TarWriter - Documentation for Ruby 3.3

# class Gem::Package::TarWriter

Allows writing of tar files

### Public Class Methods

new(io) { |writer| ... } click to toggle source

Creates a new `TarWriter`, yielding it if a block is given

Calls superclass method `BasicObject::new`

    # File lib/rubygems/package/tar_writer.rb, line 75
    def self.new(io)
      writer = super

      return writer unless block_given?

      begin
        yield writer
      ensure
        writer.close
      end

      nil
    end

new(io) click to toggle source

Creates a new `TarWriter` that will write to `io`

    # File lib/rubygems/package/tar_writer.rb, line 92
    def initialize(io)
      @io = io
      @closed = false
    end

### Public Instance Methods

add_file(name, mode) { |io| ... } click to toggle source

Adds file `name` with permissions `mode`, and yields an `IO` for writing the file to

    # File lib/rubygems/package/tar_writer.rb, line 101
    def add_file(name, mode) # :yields: io
      check_closed

      name, prefix = split_name name

      init_pos = @io.pos
      @io.write Gem::Package::TarHeader::EMPTY_HEADER # placeholder for the header

      yield RestrictedStream.new(@io) if block_given?

      size = @io.pos - init_pos - 512

      remainder = (512 - (size % 512)) % 512
      @io.write "\0" * remainder

      final_pos = @io.pos
      @io.pos = init_pos

      header = Gem::Package::TarHeader.new name: name, mode: mode,
                                           size: size, prefix: prefix,
                                           mtime: Gem.source_date_epoch

      @io.write header
      @io.pos = final_pos

      self
    end

add_file_digest(name, mode, digest_algorithms) { |io| ... } click to toggle source

Adds `name` with permissions `mode` to the tar, yielding `io` for writing the file. The `digest_algorithm` is written to a read-only `name`.sum file following the given file contents containing the digest name and hexdigest separated by a tab.

The created digest object is returned.

    # File lib/rubygems/package/tar_writer.rb, line 137
    def add_file_digest(name, mode, digest_algorithms) # :yields: io
      digests = digest_algorithms.map do |digest_algorithm|
        digest = digest_algorithm.new
        digest_name =
          if digest.respond_to? :name
            digest.name
          else
            digest_algorithm.class.name[/::([^:]+)\z/, 1]
          end

        [digest_name, digest]
      end

      digests = Hash[*digests.flatten]

      add_file name, mode do |io|
        Gem::Package::DigestIO.wrap io, digests do |digest_io|
          yield digest_io
        end
      end

      digests
    end

add_file_signed(name, mode, signer) { |io| ... } click to toggle source

Adds `name` with permissions `mode` to the tar, yielding `io` for writing the file. The `signer` is used to add a digest file using its digest_algorithm per `add_file_digest` and a cryptographic signature in `name`.sig. If the signer has no key only the checksum file is added.

Returns the digest.

    # File lib/rubygems/package/tar_writer.rb, line 169
    def add_file_signed(name, mode, signer)
      digest_algorithms = [
        signer.digest_algorithm,
        Gem::Security.create_digest("SHA512"),
      ].compact.uniq

      digests = add_file_digest name, mode, digest_algorithms do |io|
        yield io
      end

      signature_digest = digests.values.compact.find do |digest|
        digest_name =
          if digest.respond_to? :name
            digest.name
          else
            digest.class.name[/::([^:]+)\z/, 1]
          end

        digest_name == signer.digest_name
      end

      raise "no #{signer.digest_name} in #{digests.values.compact}" unless signature_digest

      if signer.key
        signature = signer.sign signature_digest.digest

        add_file_simple "#{name}.sig", 0o444, signature.length do |io|
          io.write signature
        end
      end

      digests
    end

add_file_simple(name, mode, size) { |io| ... } click to toggle source

Add file `name` with permissions `mode` `size` bytes long. Yields an `IO` to write the file to.

    # File lib/rubygems/package/tar_writer.rb, line 207
    def add_file_simple(name, mode, size) # :yields: io
      check_closed

      name, prefix = split_name name

      header = Gem::Package::TarHeader.new(name: name, mode: mode,
                                           size: size, prefix: prefix,
                                           mtime: Gem.source_date_epoch).to_s

      @io.write header
      os = BoundedStream.new @io, size

      yield os if block_given?

      min_padding = size - os.written
      @io.write("\0" * min_padding)

      remainder = (512 - (size % 512)) % 512
      @io.write("\0" * remainder)

      self
    end

add_symlink(name, target, mode) click to toggle source

Adds symlink `name` with permissions `mode`, linking to `target`.

    # File lib/rubygems/package/tar_writer.rb, line 233
    def add_symlink(name, target, mode)
      check_closed

      name, prefix = split_name name

      header = Gem::Package::TarHeader.new(name: name, mode: mode,
                                           size: 0, typeflag: "2",
                                           linkname: target,
                                           prefix: prefix,
                                           mtime: Gem.source_date_epoch).to_s

      @io.write header

      self
    end

check_closed() click to toggle source

Raises `IOError` if the `TarWriter` is closed

    # File lib/rubygems/package/tar_writer.rb, line 252
    def check_closed
      raise IOError, "closed #{self.class}" if closed?
    end

close() click to toggle source

Closes the `TarWriter`

    # File lib/rubygems/package/tar_writer.rb, line 259
    def close
      check_closed

      @io.write "\0" * 1024
      flush

      @closed = true
    end

closed?() click to toggle source

Is the `TarWriter` closed?

    # File lib/rubygems/package/tar_writer.rb, line 271
    def closed?
      @closed
    end

flush() click to toggle source

Flushes the TarWriter’s `IO`

    # File lib/rubygems/package/tar_writer.rb, line 278
    def flush
      check_closed

      @io.flush if @io.respond_to? :flush
    end

mkdir(name, mode) click to toggle source

Creates a new directory in the tar file `name` with `mode`

    # File lib/rubygems/package/tar_writer.rb, line 287
    def mkdir(name, mode)
      check_closed

      name, prefix = split_name(name)

      header = Gem::Package::TarHeader.new name: name, mode: mode,
                                           typeflag: "5", size: 0,
                                           prefix: prefix,
                                           mtime: Gem.source_date_epoch

      @io.write header

      self
    end