Class: Vanagon::Project

Inherits:
Object
  • Object
show all
Includes:
Utilities
Defined in:
lib/vanagon/project.rb,
lib/vanagon/project/dsl.rb

Defined Under Namespace

Classes: DSL

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utilities

#erb_file, #erb_string, #ex, #find_program_on_path, #get_md5sum, #get_sum, #http_request, #local_command, #remote_ssh_command, #retry_with_timeout, #rsync_from, #rsync_to, #ssh_command

Constructor Details

#initialize(name, platform) ⇒ Vanagon::Project

Project constructor. Takes just the name. Also sets the @name and @platform, and initializes @components, @directories and @settings.

Parameters:



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/vanagon/project.rb', line 137

def initialize(name, platform) # rubocop:disable Metrics/AbcSize
  @name = name
  @components = []
  @requires = []
  @directories = []
  @settings = platform.settings
  # Environments are like Hashes but with specific constraints
  # around their keys and values.
  @environment = Vanagon::Environment.new
  @platform = platform
  @release = "1"
  @replaces = []
  @provides = []
  @conflicts = []
  @package_overrides = []
  @source_artifacts = false
  @compiled_archive = false
  @generate_packages = true
  @yaml_settings = false
  @upstream_metadata = {}
  @no_packaging = false
  @artifacts_to_fetch = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args) ⇒ Object

Magic getter to retrieve settings in the project



162
163
164
165
166
167
# File 'lib/vanagon/project.rb', line 162

def method_missing(method_name, *args)
  if @settings.key?(method_name)
    return @settings[method_name]
  end
  super
end

Instance Attribute Details

#artifacts_to_fetchObject

Additional File(s) to retrieve from the system after the installation steps are all complete.



102
103
104
# File 'lib/vanagon/project.rb', line 102

def artifacts_to_fetch
  @artifacts_to_fetch
end

#bill_of_materialsObject

Stores the location for the bill-of-materials (a receipt of all files written during) project package assembly



73
74
75
# File 'lib/vanagon/project.rb', line 73

def bill_of_materials
  @bill_of_materials
end

#cleanupObject

Stores whether or not a project should cleanup as it builds because the target builder is space-constrained



60
61
62
# File 'lib/vanagon/project.rb', line 60

def cleanup
  @cleanup
end

#compiled_archiveObject

Should we include platform-specific archives as final outputs probably gzipped tarball for *nix, and probably 7z for win



95
96
97
# File 'lib/vanagon/project.rb', line 95

def compiled_archive
  @compiled_archive
end

#componentsObject

Returns the value of attribute components.



25
26
27
# File 'lib/vanagon/project.rb', line 25

def components
  @components
end

#configdirObject

Returns the value of attribute configdir.



35
36
37
# File 'lib/vanagon/project.rb', line 35

def configdir
  @configdir
end

#conflictsObject

Returns the value of attribute conflicts.



26
27
28
# File 'lib/vanagon/project.rb', line 26

def conflicts
  @conflicts
end

#descriptionObject

Returns the value of attribute description.



24
25
26
# File 'lib/vanagon/project.rb', line 24

def description
  @description
end

#directoriesObject

Store any target directories that should be packed up into the resultant artifact produced by a given Vanagon project.



41
42
43
# File 'lib/vanagon/project.rb', line 41

def directories
  @directories
end

#environmentObject

The overall Environment that a given Vanagon project should pass to each platform



81
82
83
# File 'lib/vanagon/project.rb', line 81

def environment
  @environment
end

#generate_packagesObject

Should we generate platform-specific packages (rpm, deb, dmg, msi, etc)



98
99
100
# File 'lib/vanagon/project.rb', line 98

def generate_packages
  @generate_packages
end

#homepageObject

Returns the value of attribute homepage.



22
23
24
# File 'lib/vanagon/project.rb', line 22

def homepage
  @homepage
end

#identifierObject

This is macOS specific, and defines the Identifier that macOS should use when it builds a .pkg



56
57
58
# File 'lib/vanagon/project.rb', line 56

def identifier
  @identifier
end

#licenseObject

Returns the value of attribute license.



21
22
23
# File 'lib/vanagon/project.rb', line 21

def license
  @license
end

#nameObject

Numerous attributes related to the artifact that a given Vanagon project will produce



18
19
20
# File 'lib/vanagon/project.rb', line 18

def name
  @name
end

#no_packagingObject

Specify that the project should not perform the packaging steps in vanagon and instead just stop after installation.

Useful alongside fetch_artifact when you don’t need vanagon’s packaging system and you just want to perform installation and pull down a file.



109
110
111
# File 'lib/vanagon/project.rb', line 109

def no_packaging
  @no_packaging
end

#noarchObject

Mark a project as being architecture independent



52
53
54
# File 'lib/vanagon/project.rb', line 52

def noarch
  @noarch
end

#package_overridesObject

Extra vars to be set in the spec file or debian rules. Good for setting extra %define or %global things for RPM, or env variables needed in the debian rules file No extra munging will be performed, so these should be set as you want them to appear in your spec/rules files!



88
89
90
# File 'lib/vanagon/project.rb', line 88

def package_overrides
  @package_overrides
end

#platformObject

Platform’s abstraction is kind of backwards – we should refactor how this works, and make it possible for Vanagon to default to all defined platforms if nothing is specified.



34
35
36
# File 'lib/vanagon/project.rb', line 34

def platform
  @platform
end

#providesObject

Returns the value of attribute provides.



29
30
31
# File 'lib/vanagon/project.rb', line 29

def provides
  @provides
end

#releaseObject

Returns the value of attribute release.



20
21
22
# File 'lib/vanagon/project.rb', line 20

def release
  @release
end

#replacesObject

Returns the value of attribute replaces.



28
29
30
# File 'lib/vanagon/project.rb', line 28

def replaces
  @replaces
end

#repoObject

This is entirely too Puppet centric, and should be refactored out !depreciate !refactor



49
50
51
# File 'lib/vanagon/project.rb', line 49

def repo
  @repo
end

#requiresObject

Returns the value of attribute requires.



27
28
29
# File 'lib/vanagon/project.rb', line 27

def requires
  @requires
end

#retry_countObject

Returns the value of attribute retry_count.



36
37
38
# File 'lib/vanagon/project.rb', line 36

def retry_count
  @retry_count
end

#settingsObject

Stores individual settings related to a given Vanagon project, not necessarily the artifact that the project produces



77
78
79
# File 'lib/vanagon/project.rb', line 77

def settings
  @settings
end

#source_artifactsObject

Should we include source packages?



91
92
93
# File 'lib/vanagon/project.rb', line 91

def source_artifacts
  @source_artifacts
end

#timeoutObject

Returns the value of attribute timeout.



37
38
39
# File 'lib/vanagon/project.rb', line 37

def timeout
  @timeout
end

#userObject

This will define any new users that a project should create



44
45
46
# File 'lib/vanagon/project.rb', line 44

def user
  @user
end

#vendorObject

Returns the value of attribute vendor.



23
24
25
# File 'lib/vanagon/project.rb', line 23

def vendor
  @vendor
end

#versionObject

Returns the value of attribute version.



19
20
21
# File 'lib/vanagon/project.rb', line 19

def version
  @version
end

#version_fileObject

Stores whether or not Vanagon should write the project’s version out into a file inside the package – do we really need this? !depreciate !refactor



66
67
68
# File 'lib/vanagon/project.rb', line 66

def version_file
  @version_file
end

#yaml_settingsObject

Store whether Vanagon should write the project’s settings to a yaml file during builds



69
70
71
# File 'lib/vanagon/project.rb', line 69

def yaml_settings
  @yaml_settings
end

Class Method Details

.load_project(name, configdir, platform, include_components = []) ⇒ Vanagon::Project

Loads a given project from the configdir

Parameters:

  • name (String)

    the name of the project

  • configdir (String)

    the path to the project config file

  • platform (Vanagon::Platform)

    platform to build against

  • include_components (List) (defaults to: [])

    optional list restricting the loaded components

Returns:

Raises:

  • if the instance_eval on Project fails, the exception is reraised



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/vanagon/project.rb', line 119

def self.load_project(name, configdir, platform, include_components = [])
  projfile = File.join(configdir, "#{name}.rb")
  dsl = Vanagon::Project::DSL.new(name, File.dirname(configdir), platform, include_components)
  dsl.instance_eval(File.read(projfile), projfile, 1)
  dsl._project
rescue StandardError => e
  warn "Error loading project '#{name}' using '#{projfile}':"
  warn e
  warn e.backtrace.join("\n")
  raise e
end

Instance Method Details

#build_manifest_json(pretty = false) ⇒ Hash

Generate a hash which contains relevant information regarding components of a package, what vanagon built the package, time of build, as well as version of the thing we were building.

Returns:

  • (Hash)

    of information which is useful to know about how a package was built and what went into the package.



681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
# File 'lib/vanagon/project.rb', line 681

def build_manifest_json(pretty = false)
  manifest = {
    "packaging_type" => {
      "vanagon" => VANAGON_VERSION,
    },
    "version" => version,
    "components" => generate_dependencies_info,
    "build_time" => BUILD_TIME,
  }
  if pretty
    JSON.pretty_generate(manifest)
  else
    manifest
  end
end

#check_pkg_state_string(pkg_state) ⇒ Object

Checks that the string pkg_state is valid (install OR upgrade). Return vanagon error if invalid

Parameters:

  • pkg_state (String)

    package state input



370
371
372
373
374
# File 'lib/vanagon/project.rb', line 370

def check_pkg_state_string(pkg_state)
  unless ["install", "upgrade"].include? pkg_state
    raise Vanagon::Error, "#{pkg_state} should be a string containing one of 'install' or 'upgrade'"
  end
end

#dirnamesArray

This originally lived in the Makefile.erb template, but it’s pretty domain-inspecific and we should try to minimize assignment inside an ERB template

Returns:

  • (Array)

    all of the paths produced by #get_directories



548
549
550
# File 'lib/vanagon/project.rb', line 548

def dirnames
  get_directories.map(&:path)
end

#fetch_sources(workdir, retry_count = 1, timeout = 7200) ⇒ Object

Collects all sources and patches into the provided workdir

Parameters:

  • workdir (String)

    directory to stage sources into

  • retry_count (Integer) (defaults to: 1)

    number of times to retry each fetch

  • timeout (Integer) (defaults to: 7200)

    How long to wait (in seconds) for each fetch before aborting



215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/vanagon/project.rb', line 215

def fetch_sources(workdir, retry_count = 1, timeout = 7200)
  @components.each do |component|
    Vanagon::Utilities.retry_with_timeout(retry_count, timeout) do
      component.get_source(workdir)
    end
    # Fetch secondary sources
    Vanagon::Utilities.retry_with_timeout(retry_count, timeout) do
      component.get_sources(workdir)
    end
    Vanagon::Utilities.retry_with_timeout(retry_count, timeout) do
      component.get_patches(workdir)
    end
  end
end

#filter_component(name) ⇒ Array

Returns a filtered out set of components only including those components necessary to build a specific component. This is a recursive function that will call itself until it gets to a component with no build requirements

Parameters:

  • name (String)

    name of component to add. must be present in configdir/components and named $name.rb currently

Returns:

  • (Array)

    array of Vanagon::Component including only those required to build “name”, or [] if there are none



257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/vanagon/project.rb', line 257

def filter_component(name)
  filtered_component = get_component(name)
  return [] if filtered_component.nil?
  included_components = [filtered_component]

  unless filtered_component.build_requires.empty?
    filtered_component.build_requires.each do |build_requirement|
      unless get_component(build_requirement).nil?
        included_components += filter_component(build_requirement)
      end
    end
  end
  included_components.uniq
end

#generate_bill_of_materialsArray

Generate a bill-of-materials: a listing of the components and their versions in the current project

Returns:

  • (Array)

    a listing of component names and versions



595
596
597
# File 'lib/vanagon/project.rb', line 595

def generate_bill_of_materials
  components.map { |comp| "#{comp.name} #{comp.version}" }.sort
end

#generate_dependencies_infoHash

Generate a json hash which lists all of the dependant components of the project.

Returns:

  • (Hash)

    where the top level keys are components and their values are hashes with additional information on the component.



669
670
671
672
673
# File 'lib/vanagon/project.rb', line 669

def generate_dependencies_info
  components.each_with_object({}) do |component, hsh|
    hsh.merge!(component.get_dependency_hash)
  end
end

#generate_packageString, Array

Ascertain how to build a package for the current platform

Returns:

  • (String, Array)

    commands to build a package for the current project as defined by the platform



645
646
647
648
649
650
651
652
653
654
# File 'lib/vanagon/project.rb', line 645

def generate_package
  cmds = []
  if generate_packages
    cmds << @platform.generate_package(self)
  end
  if compiled_archive
    cmds << @platform.generate_compiled_archive(self)
  end
  cmds.flatten
end

#generate_packaging_artifacts(workdir) ⇒ Object

Generate any required files to build a package for this project on the current platform into the provided workdir

Parameters:

  • workdir (String)

    workdir to put the packaging files into



660
661
662
# File 'lib/vanagon/project.rb', line 660

def generate_packaging_artifacts(workdir)
  @platform.generate_packaging_artifacts(workdir, @name, binding, self)
end

#get_activate_triggersArray

Collects activate triggers for the project and its components

Returns:

  • (Array)

    of activate triggers



455
456
457
# File 'lib/vanagon/project.rb', line 455

def get_activate_triggers()
  components.flat_map(&:activate_triggers).compact.map(&:activate_name)
end

#get_all_trigger_pkgsArray

Grabs all pkgs that have trigger scripts for ‘install’ and ‘upgrade’

Returns:

  • (Array)

    a list of all the pkgs that have trigger scripts



428
429
430
431
432
433
# File 'lib/vanagon/project.rb', line 428

def get_all_trigger_pkgs()
  install_triggers = get_trigger_scripts("install")
  upgrade_triggers = get_trigger_scripts("upgrade")
  packages = (install_triggers.keys + upgrade_triggers.keys).uniq
  return packages
end

#get_component(name) ⇒ Vanagon::Component

Gets the component with component.name = “name” from the list of project.components

Parameters:

Returns:



277
278
279
280
281
# File 'lib/vanagon/project.rb', line 277

def get_component(name)
  comps = @components.select { |comp| comp.name.to_s == name.to_s }
  raise "ERROR: two or more components with the same name: #{comps.first.name}" if comps.size > 1
  comps.first
end

#get_configfilesArray

Collects any configfiles supplied by components

Returns:

  • (Array)

    array of configfiles installed by components of the project



510
511
512
# File 'lib/vanagon/project.rb', line 510

def get_configfiles
  components.flat_map(&:configfiles).uniq
end

#get_conflictsObject

Collects all of the conflicts for the project and its components



314
315
316
317
318
319
320
321
322
323
324
# File 'lib/vanagon/project.rb', line 314

def get_conflicts
  conflicts = components.flat_map(&:conflicts) + @conflicts
  # Mash the whole thing down into a flat Array
  conflicts.flatten!
  conflicts.each do |conflict|
    # TODO: Make this a more reasonable default before 1.0.0
    # but in the interim, maintain the current behavior
    conflict.version = @platform.version_munger(conflict.version, default: '<') if conflict.version
  end
  conflicts.uniq
end

#get_directoriesArray

Collects any directories declared by the project and components

Returns:

  • (Array)

    the directories in the project and components



521
522
523
524
525
526
# File 'lib/vanagon/project.rb', line 521

def get_directories
  dirs = []
  dirs.push @directories
  dirs.push components.flat_map(&:directories)
  dirs.flatten.uniq
end

#get_filesArray

Collects any additional files supplied by components

Returns:

  • (Array)

    array of files installed by components of the project



233
234
235
236
237
238
# File 'lib/vanagon/project.rb', line 233

def get_files
  files = []
  files.push @version_file if @version_file
  files.push components.flat_map(&:files)
  files.flatten.uniq
end

#get_install_trigger_scripts(pkg) ⇒ Object

Grabs the install trigger scripts for the specified pkg

Parameters:

  • pkg (String)

    the pkg we watch for being installed



412
413
414
415
# File 'lib/vanagon/project.rb', line 412

def get_install_trigger_scripts(pkg)
  scripts = get_trigger_scripts("install")
  return scripts[pkg].join("\n")
end

#get_interest_triggers(pkg_state) ⇒ Array

Collects the interest triggers for the project and its scripts for the

specified packaging state

Parameters:

  • pkg_state (String)

    the package state we want to run the given scripts for. Can be one of ‘install’ or ‘upgrade’

Returns:

  • (Array)

    of OpenStructs of all interest triggers for the pkg_state Use array of openstructs because we need both interest_name and the scripts



442
443
444
445
446
447
448
449
450
# File 'lib/vanagon/project.rb', line 442

def get_interest_triggers(pkg_state)
  interest_triggers = []
  check_pkg_state_string(pkg_state)
  interests = components.flat_map(&:interest_triggers).compact.select { |s| s.pkg_state.include? pkg_state }
  interests.each do |interest|
    interest_triggers.push(interest)
  end
  interest_triggers.flatten.compact
end

#get_postinstall_actions(pkg_state) ⇒ String

Collects the postinstall packaging actions for the project and it’s components

for the specified packaging state

Parameters:

  • pkg_state (String)

    the package state we want to run the given scripts for. Can be one of ‘install’ or ‘upgrade’

Returns:

  • (String)

    string of Bourne shell compatible scriptlets to execute during the postinstall phase of packaging during the state of the system defined by pkg_state (either install or upgrade)



466
467
468
469
470
471
472
473
# File 'lib/vanagon/project.rb', line 466

def get_postinstall_actions(pkg_state)
  scripts = components.flat_map(&:postinstall_actions).compact.select { |s| s.pkg_state.include? pkg_state }.map(&:scripts)
  if scripts.empty?
    return ': no postinstall scripts provided'
  else
    return scripts.join("\n")
  end
end

#get_postremove_actions(pkg_state) ⇒ String

Collects the postremove packaging actions for the project and it’s components for the specified packaging state

Parameters:

  • pkg_state (String)

    the package state we want to run the given scripts for. Can be one or more of ‘removal’ or ‘upgrade’

Returns:

  • (String)

    string of Bourne shell compatible scriptlets to execute during the postremove phase of packaging during the state of the system defined by pkg_state (either removal or upgrade)



498
499
500
501
502
503
504
505
# File 'lib/vanagon/project.rb', line 498

def get_postremove_actions(pkg_state)
  scripts = components.flat_map(&:postremove_actions).compact.select { |s| s.pkg_state.include? pkg_state }.map(&:scripts)
  if scripts.empty?
    return ': no postremove scripts provided'
  else
    return scripts.join("\n")
  end
end

#get_preinstall_actions(pkg_state) ⇒ String

Collects the preinstall packaging actions for the project and its components

for the specified packaging state

Parameters:

  • pkg_state (String)

    the package state we want to run the given scripts for. Can be one of ‘install’ or ‘upgrade’

Returns:

  • (String)

    string of Bourne shell compatible scriptlets to execute during the preinstall phase of packaging during the state of the system defined by pkg_state (either install or upgrade)



383
384
385
386
387
388
389
390
391
# File 'lib/vanagon/project.rb', line 383

def get_preinstall_actions(pkg_state)
  check_pkg_state_string(pkg_state)
  scripts = components.flat_map(&:preinstall_actions).compact.select { |s| s.pkg_state.include? pkg_state }.map(&:scripts)
  if scripts.empty?
    return ': no preinstall scripts provided'
  else
    return scripts.join("\n")
  end
end

#get_preremove_actions(pkg_state) ⇒ String

Collects the preremove packaging actions for the project and it’s components for the specified packaging state

Parameters:

  • pkg_state (String)

    the package state we want to run the given scripts for. Can be one or more of ‘removal’ or ‘upgrade’

Returns:

  • (String)

    string of Bourne shell compatible scriptlets to execute during the preremove phase of packaging during the state of the system defined by pkg_state (either removal or upgrade)



482
483
484
485
486
487
488
489
# File 'lib/vanagon/project.rb', line 482

def get_preremove_actions(pkg_state)
  scripts = components.flat_map(&:preremove_actions).compact.select { |s| s.pkg_state.include? pkg_state }.map(&:scripts)
  if scripts.empty?
    return ': no preremove scripts provided'
  else
    return scripts.join("\n")
  end
end

#get_providesArray

Collects all of the provides for the project and its components

Returns:

  • (Array)

    array of package level provides for the project



349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/vanagon/project.rb', line 349

def get_provides
  provides = []
  provides.push @provides.flatten
  provides.push components.flat_map(&:provides)
  provides.flatten!
  provides.each do |provide|
    # TODO: Make this a more reasonable default before 1.0.0
    # but in the interim, maintain the current behavior
    provide.version = @platform.version_munger(provide.version, default: '>=') if provide.version
  end
  provides.uniq
end

#get_replacesArray

Collects all of the replacements for the project and its components

Returns:

  • (Array)

    array of package level replacements for the project



296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/vanagon/project.rb', line 296

def get_replaces
  replaces = []
  replaces.push @replaces.flatten
  replaces.push components.flat_map(&:replaces)
  replaces.flatten!
  replaces.each do |replace|
    # TODO: Make this a more reasonable default before 1.0.0
    # but in the interim, maintain the current behavior
    replace.version = @platform.version_munger(replace.version, default: '<') if replace.version
  end
  replaces.uniq
end

#get_requiresArray

Collects all of the requires for both the project and its components

Returns:

  • (Array)

    array of runtime requirements for the project



286
287
288
289
290
291
# File 'lib/vanagon/project.rb', line 286

def get_requires
  req = []
  req << components.flat_map(&:requires)
  req << @requires
  req.flatten.uniq
end

#get_root_directoriesArray

Gets the highest level directories declared by the project

Returns:

  • (Array)

    the highest level directories that have been declared by the project



531
532
533
534
535
536
537
538
539
540
541
542
# File 'lib/vanagon/project.rb', line 531

def get_root_directories # rubocop:disable Metrics/AbcSize
  dirs = get_directories.map { |dir| dir.path.split('/') }
  dirs.sort! { |dir1, dir2| dir1.length <=> dir2.length }
  ret_dirs = []

  dirs.each do |dir|
    unless ret_dirs.include?(dir.first(dir.length - 1).join('/'))
      ret_dirs << dir.join('/')
    end
  end
  ret_dirs
end

#get_rpm_ghost_filesArray

Collects any rpm %ghost files supplied by components

Returns:

  • (Array)

    array of all files to be specified as %ghost entries in an rpm %files section.



244
245
246
247
248
# File 'lib/vanagon/project.rb', line 244

def get_rpm_ghost_files
  files = []
  files.push components.flat_map(&:rpm_ghost_files)
  files.flatten.uniq
end

#get_service(name) ⇒ @component.service obj

Grabs a specific service based on which name is passed in note that if the name is wrong or there was no will return nil

Parameters:

  • name (string)

    of service to grab

Returns:

  • (@component.service obj)

    specific service



337
338
339
340
341
342
343
344
# File 'lib/vanagon/project.rb', line 337

def get_service(name)
  components.each do |component|
    if component.name == name
      return component.service
    end
  end
  return nil
end

#get_servicesArray

Get any services registered by components in the project

Returns:

  • (Array)

    the services provided by components in the project



555
556
557
# File 'lib/vanagon/project.rb', line 555

def get_services
  components.flat_map(&:service).compact
end

#get_tarball_filesArray

Generate a list of all files and directories to be included in a tarball for the project

Returns:

  • (Array)

    all the files and directories that should be included in the tarball



571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
# File 'lib/vanagon/project.rb', line 571

def get_tarball_files # rubocop:disable Metrics/AbcSize
  # It is very important that 'file-list' remains the first element in this
  # array, lest the tar command be malformed and the package creation fail
  files = ['file-list']

  if bill_of_materials
    files.push "#{bill_of_materials.path}/bill-of-materials"
  else
    files.push 'bill-of-materials'
  end

  files.push get_files.map(&:path)
  files.push get_configfiles.map(&:path)
  if @platform.is_windows?
    files.flatten.map { |f| "$(shell cygpath --mixed --long-name '#{f}')" }
  else
    files.flatten
  end
end

#get_trigger_scripts(pkg_state) ⇒ Hash

Collects the install trigger scripts for the project for the specified packing state

Parameters:

  • pkg_state (String)

    the package state we want to run the given scripts for. Can be one of the ‘install’ or ‘upgrade’

Returns:

  • (Hash)

    of scriptlets to execute during the pkg_state (install or upgrade) there can be more than one script for each package (key)



399
400
401
402
403
404
405
406
407
# File 'lib/vanagon/project.rb', line 399

def get_trigger_scripts(pkg_state)
  triggers = Hash.new { |hsh, key| hsh[key] = [] }
  check_pkg_state_string(pkg_state)
  pkgs = components.flat_map(&:install_triggers).compact.select { |s| s.pkg_state.include? pkg_state }
  pkgs.each do |package|
    triggers[package.pkg].push package.scripts
  end
  triggers
end

#get_upgrade_trigger_scripts(pkg) ⇒ Object

Grabs the upgrade trigger scripts for the specified pkg

Parameters:

  • pkg (String)

    the pkg we watch for being upgraded



420
421
422
423
# File 'lib/vanagon/project.rb', line 420

def get_upgrade_trigger_scripts(pkg)
  scripts = get_trigger_scripts("upgrade")
  return scripts[pkg].join("\n")
end

#has_configfiles?Boolean

Returns:

  • (Boolean)


514
515
516
# File 'lib/vanagon/project.rb', line 514

def has_configfiles?
  !get_configfiles.empty?
end

#has_conflicts?Boolean

Returns:

  • (Boolean)


326
327
328
# File 'lib/vanagon/project.rb', line 326

def has_conflicts?
  !get_conflicts.empty?
end

#has_provides?Boolean

Returns:

  • (Boolean)


362
363
364
# File 'lib/vanagon/project.rb', line 362

def has_provides?
  !get_provides.empty?
end

#has_replaces?Boolean

Returns:

  • (Boolean)


309
310
311
# File 'lib/vanagon/project.rb', line 309

def has_replaces?
  !get_replaces.empty?
end

#has_services?True, False

Simple utility for determining if the components in the project declare any services

Returns:

  • (True, False)

    Whether or not there are services declared for this project or not



563
564
565
# File 'lib/vanagon/project.rb', line 563

def has_services?
  !get_services.empty?
end

#list_component_dependencies(component) ⇒ Array

Return a list of the build_dependencies that are satisfied by an internal component

Parameters:

  • component (Vanagon::Component)

    component to check for already satisfied build dependencies

Returns:

  • (Array)

    a list of the build dependencies for the given component that are satisfied by other components in the project



631
632
633
# File 'lib/vanagon/project.rb', line 631

def list_component_dependencies(component)
  component.build_requires.select { |dep| components.map(&:name).include?(dep) }
end

#load_upstream_metadata(metadata_uri) ⇒ Object



824
825
826
827
828
829
830
831
832
833
834
835
# File 'lib/vanagon/project.rb', line 824

def ()
  warn "Loading metadata from #{}"
  case 
  when /^http/
    @upstream_metadata = JSON.parse(Net::HTTP.get(URI()))
  when /^file/
    filename = .sub(/^file:\/\//, '')
    @upstream_metadata = JSON.parse(File.read(filename))
  else
    raise Vanagon::Error, "Metadata URI must be 'file://' or 'http://', don't know how to parse #{}"
  end
end

#load_upstream_settings(upstream_project_name, upstream_git_url, upstream_git_branch) ⇒ Object

Load the settings hash from an upstream vanagon project. This will clone a git repo at a specified branch and load the specified vanagon project (with no components). The settings hash of the upstream project will be merged with the existing settings hash, overriding any duplicates at the time of calling with the value from upstream. To override settings from upstream, you need to set the ‘proj.setting` after `proj.inherit_settings`.

As the settings are not lazy-loaded, if you need to override a setting from upstream that is used in later settings, you’ll need to override all of the settings based on the one you’re overriding.

Parameters:

  • upstream_project_name (String)

    The name of the vanagon project to load

  • upstream_git_url (URI)

    The URL to clone this vanagon project from

  • upstream_git_branch (String)

    The branch of the vanagon project to clone from



772
773
774
775
776
777
778
779
780
781
782
783
784
785
# File 'lib/vanagon/project.rb', line 772

def load_upstream_settings(upstream_project_name, upstream_git_url, upstream_git_branch) # rubocop:disable Metrics/AbcSize
  Dir.mktmpdir do |working_directory|
    upstream_source = Vanagon::Component::Source::Git.new(upstream_git_url, workdir: working_directory, ref: upstream_git_branch)
    upstream_source.fetch

    Dir.chdir(File.join(working_directory, upstream_source.dirname)) do
      upstream_platform = Vanagon::Platform.load_platform(platform.name, File.join(working_directory, upstream_source.dirname, "configs", "platforms"))
      upstream_project = Vanagon::Project.load_project(upstream_project_name, File.join(working_directory, upstream_source.dirname, "configs", "projects"), upstream_platform)
      @settings.merge!(upstream_project.settings)
      @upstream_metadata = upstream_project.build_manifest_json
      upstream_project.cleanup
    end
  end
end

#load_yaml_settings(settings_uri, settings_sha1_uri = nil) ⇒ Object

Load the settings hash for the current project/platform combination from a yaml file as produced by ‘publish_yaml_settings`. file:// and http:// URIs are accepted. If the URI uses http://, a sha1 URI is also required.

Parameters:

  • settings_uri (String)

    A URI to a yaml settings file

  • settings_sha1_uri (String) (defaults to: nil)

    A URI to a sha1sum file for the yaml settings file

Raises:



794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
# File 'lib/vanagon/project.rb', line 794

def load_yaml_settings(settings_uri, settings_sha1_uri = nil) # rubocop:disable Metrics/AbcSize
  source_type = Vanagon::Component::Source.determine_source_type(settings_uri)

  if %i[unknown git].include?(source_type)
    message = "Can't inherit settings from '#{settings_uri}'. Only http and file URIs are valid."
    if settings_uri =~ /^file/
      message = "Tried to load YAML settings from '#{settings_uri}', but the file doesn't exist."
    end
    raise Vanagon::Error, message
  end

  if (source_type == :http) && !settings_sha1_uri
    raise Vanagon::Error, "You must provide a sha1sum URI for the YAML file when inheriting YAML settings over http"
  end

  Dir.mktmpdir do |working_directory|
    source = Vanagon::Component::Source.source(settings_uri,
                                               workdir: working_directory,
                                               sum: settings_sha1_uri,
                                               sum_type: 'sha1')
    source.fetch
    source.verify
    yaml_path = source.file
    if source_type == :http
      yaml_path = File.join(working_directory, source.file)
    end
    @settings.merge!(YAML.safe_load(File.read(yaml_path), [Symbol]))
  end
end

#make_bill_of_materials(workdir) ⇒ String

Generates a bill-of-materials and writes the contents to the workdir for use in building the project

Parameters:

  • workdir (String)

    full path to the workdir to send the bill-of-materials

Returns:

  • (String)

    full path to the generated bill-of-materials



623
624
625
# File 'lib/vanagon/project.rb', line 623

def make_bill_of_materials(workdir)
  File.open(File.join(workdir, 'bill-of-materials'), 'w') { |f| f.puts(generate_bill_of_materials.join("\n")) }
end

#make_makefile(workdir) ⇒ String

Evaluates the makefile template and writes the contents to the workdir for use in building the project

Parameters:

  • workdir (String)

    full path to the workdir to send the evaluated template

Returns:

  • (String)

    full path to the generated Makefile



614
615
616
# File 'lib/vanagon/project.rb', line 614

def make_makefile(workdir)
  erb_file(File.join(VANAGON_ROOT, "resources/Makefile.erb"), File.join(workdir, "Makefile"))
end

#merged_environmentEnvironment

Merge the platform’s Environment into the project’s Environment and return the result. This will produce the top-level Environment in the Makefile, that all components (and their Make targets) will inherit from.

Returns:

  • (Environment)

    a new Environment, constructed from merging @platform’s Environment with the project’s environment.



180
181
182
# File 'lib/vanagon/project.rb', line 180

def merged_environment
  environment.merge(@platform.environment)
end

#metadata_merge(original, upstream) ⇒ Hash

Recursive merge of metadata hashes Input is not modified In case of duplicate keys, original value is kept

Parameters:

  • original (Hash)

    Metadata hash from original project

  • upstream (Hash)

    Metadata hash from upstream project

Returns:

  • (Hash)


704
705
706
707
708
709
710
711
712
# File 'lib/vanagon/project.rb', line 704

def (original, upstream)
  upstream.merge(original) do |key, upstream_value, original_value|
    if original_value.is_a?(Hash)
      (original_value, upstream_value)
    else
      original_value
    end
  end
end

#pack_tarball_commandString

Method to generate the command to create a tarball of the project

Returns:

  • (String)

    cross platform command to generate a tarball of the project



602
603
604
605
606
607
# File 'lib/vanagon/project.rb', line 602

def pack_tarball_command
  tar_root = "#{@name}-#{@version}"
  ["mkdir -p '#{tar_root}'",
   %('#{@platform.tar}' -cf - -T "#{get_tarball_files.join('" "')}" | ( cd '#{tar_root}/'; '#{@platform.tar}' xfp -)),
   %('#{@platform.tar}' -cf - #{tar_root}/ | gzip -9c > #{tar_root}.tar.gz)].join("\n\t")
end

#package_nameString

Get the package name for the project on the current platform

Returns:

  • (String)

    package name for the current project as defined by the platform



638
639
640
# File 'lib/vanagon/project.rb', line 638

def package_name
  @platform.package_name(self)
end

#publish_yaml_settings(platform) ⇒ Object

Writes a yaml file at ‘output/<name>-<version>.<platform>.settings.yaml` containing settings used to build the current project on the platform provided (and a corresponding sha1sum file) if `yaml_settings` has been set in the project definition.

Parameters:

Raises:



742
743
744
745
746
747
748
749
750
751
752
753
754
755
# File 'lib/vanagon/project.rb', line 742

def publish_yaml_settings(platform) # rubocop:disable Metrics/AbcSize
  return unless yaml_settings
  raise(Vanagon::Error, "You must specify a project version") unless version

  filename = "#{name}-#{version}.#{platform.name}.settings.yaml"
  filepath = File.expand_path(File.join('output', filename))

  File.open(filepath, 'w') do |f|
    f.write(@settings.to_yaml)
  end

  sha1 = Digest::SHA1.file(filepath).hexdigest
  File.open("#{filepath}.sha1", 'w') { |f| f.puts(sha1) }
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


169
170
171
# File 'lib/vanagon/project.rb', line 169

def respond_to_missing?(method_name, include_private = false)
  @settings.key?(method_name) || super
end

#save_manifest_json(platform) ⇒ Hash

Writes a json file at ‘ext/build_metadata.<project>.<platform>.json` containing information about what went into a built artifact

Returns:

  • (Hash)

    of build information



718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
# File 'lib/vanagon/project.rb', line 718

def save_manifest_json(platform)
  manifest = build_manifest_json
   = (manifest, @upstream_metadata)

  ext_directory = 'ext'
  FileUtils.mkdir_p ext_directory

   = "build_metadata.#{name}.#{platform.name}.json"
  File.open(File.join(ext_directory, ), 'w') do |f|
    f.write(JSON.pretty_generate())
  end

  ## VANAGON-132 Backwards compatibility: make a 'build_metadata.json' file
  File.open(File.join(ext_directory, 'build_metadata.json'), 'w') do |f|
    f.write(JSON.pretty_generate())
  end
end

#vendor_email_onlyString

Parses the vendor for the project by taking only the email address field (e.g. ‘<[email protected]>`).

Returns:

  • (String)

    Vendor email address



205
206
207
# File 'lib/vanagon/project.rb', line 205

def vendor_email_only
  return @vendor.match(VENDOR_REGEX)[2]
end

#vendor_name_onlyString

Parses the vendor for the project by cutting off the email address field (e.g. ‘<[email protected]>`).

Returns:

  • (String)

    Vendor name without email address



197
198
199
# File 'lib/vanagon/project.rb', line 197

def vendor_name_only
  return @vendor.match(VENDOR_REGEX)[1]
end