Class: Qrpm::Rpm

Inherits:
Object
  • Object
show all
Defined in:
lib/qrpm/rpm.rb

Overview

Knows the following RPM fields:

name        Package name (mandatory)
version     Version (mandatory)
release     Release
summary     Short one-line description of package (mandatory)
description Description
packager    Name of the packager (defaults to the name of the user or
            $USER@$HOSTNAME if not found)
license     License (defaults to GPL)
require     Array of required packages
make        Controls the build process:
              true    Expect the top-level directory to contain
                      configure or make files and runs them. It is an
                      error if the Makefile is missing
              (possibly multiline command)
                      Runs the command to build the project

Each field has a dynamically generated accessor method that can be referenced in the template file

Constant Summary collapse

MANDATORY_FIELDS =
%w(name version summary)
FIELDS =

Maps from field name to array of allowed types for that field

MANDATORY_FIELDS.map { |f| [f, [String]] }.to_h.merge({
  "release" => [String],
  "description" => [String],
  "packager" => [String],
  "license" => [String],
  "group" => [String],
  "include" => [Array, String],
  "require" => [Array, String],
  "make" => [String]
})
RPM_DIRS =
%w(SOURCES BUILD RPMS SPECS SRPMS tmp)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(srcdir, fields, nodes, template: QRPM_ERB_FILE) ⇒ Rpm

Returns a new instance of Rpm.



78
79
80
81
82
83
84
85
# File 'lib/qrpm/rpm.rb', line 78

def initialize(srcdir, fields, nodes, template: QRPM_ERB_FILE)
  constrain srcdir, String
  constrain fields, { String => Node }
  constrain nodes, [FileNode]
  @fields, @nodes = fields, nodes
  @srcdir = srcdir
  @template = template
end

Instance Attribute Details

#fieldsObject (readonly)

Returns the value of attribute fields.



64
65
66
# File 'lib/qrpm/rpm.rb', line 64

def fields
  @fields
end

#nodesObject (readonly)

Returns the value of attribute nodes.



65
66
67
# File 'lib/qrpm/rpm.rb', line 65

def nodes
  @nodes
end

#specObject (readonly)

The content of the SPEC file



71
72
73
# File 'lib/qrpm/rpm.rb', line 71

def spec
  @spec
end

#srcdirObject (readonly)

The source directory



68
69
70
# File 'lib/qrpm/rpm.rb', line 68

def srcdir
  @srcdir
end

Instance Method Details

#build(target: :rpm, file: nil, verbose: false, destdir: ".", builddir: nil) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/qrpm/rpm.rb', line 90

def build(target: :rpm, file: nil, verbose: false, destdir: ".", builddir: nil)
  verb = verbose ? "" : "&>/dev/null"
  begin
    if builddir
      rootdir = builddir
      FileUtils.rm_rf(rootdir)
      FileUtils.mkdir_p(rootdir)
    else
      rootdir = Dir.mktmpdir
    end

    spec_file = file || "#{name}.spec"
    tar_file = "#{name}.tar.gz"
    spec_path = "#{rootdir}/SPECS/#{spec_file}"
    tar_path = "#{rootdir}/SOURCES/#{tar_file}"

    # Create directories
    RPM_DIRS.each { |dir| FileUtils.mkdir_p "#{rootdir}/#{dir}" }

    # Roll tarball
    #
    # It is a bad idea to use git-archive to roll a tarball because we may
    # have configuration files/scripts that are not included in the git
    # repository. If needed then see
    # https://gist.github.com/arteymix/03702e3eb05c2c161a86b49d4626d21f
    #
    # Alternatively use the --add-file option? Then we need to know if
    # files are in the git repo or not
    system "tar zcf #{tar_path} --transform=s%^\./%#{name}/% ." # FIXME FIXME

    # Create spec file. Initial blanks are removed from each line in the file
    renderer = ERB.new(IO.read(@template).sub(/^__END__\n.*/m, ""), trim_mode: "-")
    @spec = renderer.result(binding).gsub(/^[[:blank:]]*/, "")

    # Emit spec or build RPM
    if target == :spec
      destfiles = ["#{destdir}/#{spec_file}"]
      IO.write(destfiles.first, @spec)
    else
      IO.write(spec_path, @spec)
      rpm_build_options = [
          "-v -ba",
          "-D 'debug_package %{nil}'",
          "--define \"_topdir #{rootdir}\"",
      ].join(" ")
      system "rpmbuild #{rpm_build_options} #{rootdir}/SPECS/#{name}.spec #{verb}" or
          raise "Failed building RPM file. Re-run with -v option to see errors"
      if target == :srpm
        destfiles = Dir["#{rootdir}/SRPMS/*"]
        !destfiles.empty? or raise Error, "No SRPM file found"
      elsif target == :rpm
        destfiles = Dir["#{rootdir}/RPMS/*/#{name}-[0-9]*"]
        !destfiles.empty? or raise Error, "No RPM file found"
      else
        raise ArgumentError, "Not a valid value for :target - #{target.inspect}"
      end
      system "cp #{destfiles.join " "} #{destdir}" or raise "Failed copying SRPM file"
    end
    return destfiles
  ensure
    FileUtils.remove_entry_secure rootdir if !builddir
  end
end

#dumpObject



154
155
156
157
158
159
160
161
162
# File 'lib/qrpm/rpm.rb', line 154

def dump
  puts self.class
  indent {
    puts "fields"
    indent { fields.sort_by(&:first).each { |k,v| puts "#{k}: #{v.value}" } }
    puts "nodes"
    indent { nodes.map(&:dump) }
  }
end

#filesObject



73
# File 'lib/qrpm/rpm.rb', line 73

def files() @files ||= nodes.select(&:file?) end

#has_configure?Boolean

Returns:

  • (Boolean)


87
# File 'lib/qrpm/rpm.rb', line 87

def has_configure?() ::File.exist? "#{srcdir}/configure" end

#has_make?Boolean

Returns:

  • (Boolean)


88
# File 'lib/qrpm/rpm.rb', line 88

def has_make?() ::File.exist? "#{srcdir}/Makefile" end


74
# File 'lib/qrpm/rpm.rb', line 74

def links() @links ||= nodes.select(&:link?) end


75
# File 'lib/qrpm/rpm.rb', line 75

def reflinks() @reflinks ||= nodes.select(&:reflink?) end


76
# File 'lib/qrpm/rpm.rb', line 76

def symlinks() @symlinks ||= nodes.select(&:symlink?) end