def commit
      flags = RPM::C::TransFlags[:none]

      callback = proc do |hdr, type, amount, total, key_ptr, data_ignored|
        key_id = key_ptr.address
        key = @keys.include?(key_id) ? @keys[key_id] : nil

        if block_given?
          package = hdr.null? ? nil : Package.new(hdr)
          data = CallbackData.new(type, key, package, amount, total)
          yield(data)
        else
          RPM::C.rpmShowProgress(hdr, type, amount, total, key, data_ignored)
        end
      end
      # We create a callback to pass to the C method and we
      # call the user supplied callback from there
      #
      # The C callback expects you to return a file handle,
      # We expect from the user to get a File, which we
      # then convert to a file handle to return.
      callback = proc do |hdr, type, amount, total, key_ptr, data_ignored|
        key_id = key_ptr.address
        key = @keys.include?(key_id) ? @keys[key_id] : nil

        if block_given?
          package = hdr.null? ? nil : Package.new(hdr)
          data = CallbackData.new(type, key, package, amount, total)
          ret = yield(data)

          # For OPEN_FILE we need to do some type conversion
          # for certain callback types we need to do some
          case type
          when :inst_open_file
            # For :inst_open_file the user callback has to
            # return the open file
            unless ret.is_a?(::File)
              raise TypeError, "illegal return value type #{ret.class}. Expected File."
            end
            fdt = RPM::C.fdDup(ret.to_i)
            if fdt.null? || RPM::C.Ferror(fdt) != 0
              raise "Can't use opened file #{data.key}: #{RPM::C.Fstrerror(fdt)}"
              RPM::C.Fclose(fdt) unless fdt.nil?
            else
              fdt = RPM::C.fdLink(fdt)
              @fdt = fdt
            end
            # return the (RPM type) file handle
            fdt
          when :inst_close_file
            fdt = @fdt
            RPM::C.Fclose(fdt)
            @fdt = nil
          else
            ret
          end
        else
          # No custom callback given, use the default to show progress
          RPM::C.rpmShowProgress(hdr, type, amount, total, key, data_ignored)
        end
      end

      rc = RPM::C.rpmtsSetNotifyCallback(@ptr, callback, nil)
      raise "Can't set commit callback" if rc != 0

      rc = RPM::C.rpmtsRun(@ptr, nil, :none)

      raise "#{self}: #{RPM::C.rpmlogMessage}" if rc < 0

      if rc > 0
        ps = RPM::C.rpmtsProblems(@ptr)
        psi = RPM::C.rpmpsInitIterator(ps)
        while RPM::C.rpmpsNextIterator(psi) >= 0
          problem = Problem.from_ptr(RPM::C.rpmpsGetProblem(psi))
          STDERR.puts problem
        end
        RPM::C.rpmpsFree(ps)
      end
    end
def commit
      flags = RPM::C::TransFlags[:none]

      callback = proc do |hdr, type, amount, total, key_ptr, data_ignored|
        key_id = key_ptr.address
        key = @keys.include?(key_id) ? @keys[key_id] : nil

        if block_given?
          package = hdr.null? ? nil : Package.new(hdr)
          data = CallbackData.new(type, key, package, amount, total)
          yield(data)
        else
          RPM::C.rpmShowProgress(hdr, type, amount, total, key, data_ignored)
        end
      end
      # We create a callback to pass to the C method and we
      # call the user supplied callback from there
      #
      # The C callback expects you to return a file handle,
      # We expect from the user to get a File, which we
      # then convert to a file handle to return.
      callback = proc do |hdr, type, amount, total, key_ptr, data_ignored|
        key_id = key_ptr.address
        key = @keys.include?(key_id) ? @keys[key_id] : nil

        if block_given?
          package = hdr.null? ? nil : Package.new(hdr)
          data = CallbackData.new(type, key, package, amount, total)
          ret = yield(data)

          # For OPEN_FILE we need to do some type conversion
          # for certain callback types we need to do some
          case type
          when :inst_open_file
            # For :inst_open_file the user callback has to
            # return the open file
            unless ret.is_a?(::File)
              raise TypeError, "illegal return value type #{ret.class}. Expected File."
            end
            fdt = RPM::C.fdDup(ret.to_i)
            if fdt.null? || RPM::C.Ferror(fdt) != 0
              raise "Can't use opened file #{data.key}: #{RPM::C.Fstrerror(fdt)}"
              RPM::C.Fclose(fdt) unless fdt.nil?
            else
              fdt = RPM::C.fdLink(fdt)
              @fdt = fdt
            end
            # return the (RPM type) file handle
            fdt
          when :inst_close_file
            fdt = @fdt
            RPM::C.Fclose(fdt)
            @fdt = nil
          else
            ret
          end
        else
          # No custom callback given, use the default to show progress
          RPM::C.rpmShowProgress(hdr, type, amount, total, key, data_ignored)
        end
      end

      rc = RPM::C.rpmtsSetNotifyCallback(@ptr, callback, nil)
      raise "Can't set commit callback" if rc != 0

      rc = RPM::C.rpmtsRun(@ptr, nil, :none)

      raise "#{self}: #{RPM::C.rpmlogMessage}" if rc < 0

      if rc > 0
        ps = RPM::C.rpmtsProblems(@ptr)
        psi = RPM::C.rpmpsInitIterator(ps)
        while RPM::C.rpmpsNextIterator(psi) >= 0
          problem = Problem.from_ptr(RPM::C.rpmpsGetProblem(psi))
          STDERR.puts problem
        end
        RPM::C.rpmpsFree(ps)
      end
    end
Performs the transaction.
 @param [Number] flag Transaction flags, default +RPM::TRANS_FLAG_NONE+
 @param [Number] filter Transaction filter, default +RPM::PROB_FILTER_NONE+
 @example
   transaction.commit
 You can supply your own callback
 @example
   transaction.commit do |data|
   end
 end
 @yield [CallbackData] sig Transaction progress