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, #http_request_code, #http_request_generic, #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:



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/vanagon/project.rb', line 146

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 = []
  @extra_files_to_sign = []
  @signing_hostname = ''
  @signing_username = ''
  @signing_command = ''
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



175
176
177
178
179
180
# File 'lib/vanagon/project.rb', line 175

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.



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

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



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

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



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

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



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

def compiled_archive
  @compiled_archive
end

#componentsObject

Returns the value of attribute components.



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

def components
  @components
end

#configdirObject

Returns the value of attribute configdir.



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

def configdir
  @configdir
end

#conflictsObject

Returns the value of attribute conflicts.



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

def conflicts
  @conflicts
end

#descriptionObject

Returns the value of attribute description.



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

def description
  @description
end

#directoriesObject

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



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

def directories
  @directories
end

#environmentObject

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



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

def environment
  @environment
end

#extra_files_to_signObject

Extra files to sign Right now just supported on windows, useful for signing powershell scripts that need to be signed between build and MSI creation



115
116
117
# File 'lib/vanagon/project.rb', line 115

def extra_files_to_sign
  @extra_files_to_sign
end

#generate_packagesObject

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



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

def generate_packages
  @generate_packages
end

#homepageObject

Returns the value of attribute homepage.



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

def homepage
  @homepage
end

#identifierObject

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



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

def identifier
  @identifier
end

#licenseObject

Returns the value of attribute license.



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

def license
  @license
end

#nameObject

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



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

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.



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

def no_packaging
  @no_packaging
end

#noarchObject

Mark a project as being architecture independent



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

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!



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

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.



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

def platform
  @platform
end

#providesObject

Returns the value of attribute provides.



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

def provides
  @provides
end

#releaseObject

Returns the value of attribute release.



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

def release
  @release
end

#replacesObject

Returns the value of attribute replaces.



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

def replaces
  @replaces
end

#repoObject

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



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

def repo
  @repo
end

#requiresObject

Returns the value of attribute requires.



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

def requires
  @requires
end

#retry_countObject

Returns the value of attribute retry_count.



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

def retry_count
  @retry_count
end

#settingsObject

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



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

def settings
  @settings
end

#signing_commandObject

Returns the value of attribute signing_command.



118
119
120
# File 'lib/vanagon/project.rb', line 118

def signing_command
  @signing_command
end

#signing_hostnameObject

Returns the value of attribute signing_hostname.



116
117
118
# File 'lib/vanagon/project.rb', line 116

def signing_hostname
  @signing_hostname
end

#signing_usernameObject

Returns the value of attribute signing_username.



117
118
119
# File 'lib/vanagon/project.rb', line 117

def signing_username
  @signing_username
end

#source_artifactsObject

Should we include source packages?



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

def source_artifacts
  @source_artifacts
end

#timeoutObject

Returns the value of attribute timeout.



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

def timeout
  @timeout
end

#userObject

This will define any new users that a project should create



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

def user
  @user
end

#vendorObject

Returns the value of attribute vendor.



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

def vendor
  @vendor
end

#versionObject

Returns the value of attribute version.



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

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



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

def version_file
  @version_file
end

#yaml_settingsObject

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



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

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



128
129
130
131
132
133
134
135
136
137
138
# File 'lib/vanagon/project.rb', line 128

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
  VanagonLogger.error "Error loading project '#{name}' using '#{projfile}':"
  VanagonLogger.error(e)
  VanagonLogger.error 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.



715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
# File 'lib/vanagon/project.rb', line 715

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



392
393
394
395
396
# File 'lib/vanagon/project.rb', line 392

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

#cli_manifest_json(platform) ⇒ Object

Writes a json file to STDOUT containing information about what will go into an artifact

Parameters:

  • platform (String)

    platform we’re writing metadata for



781
782
783
784
785
786
# File 'lib/vanagon/project.rb', line 781

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

  puts JSON.pretty_generate()
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



582
583
584
# File 'lib/vanagon/project.rb', line 582

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



228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/vanagon/project.rb', line 228

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



270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/vanagon/project.rb', line 270

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



629
630
631
# File 'lib/vanagon/project.rb', line 629

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.



703
704
705
706
707
# File 'lib/vanagon/project.rb', line 703

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



679
680
681
682
683
684
685
686
687
688
# File 'lib/vanagon/project.rb', line 679

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



694
695
696
# File 'lib/vanagon/project.rb', line 694

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



477
478
479
# File 'lib/vanagon/project.rb', line 477

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



450
451
452
453
454
455
# File 'lib/vanagon/project.rb', line 450

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:



290
291
292
293
294
# File 'lib/vanagon/project.rb', line 290

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



544
545
546
# File 'lib/vanagon/project.rb', line 544

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

#get_conflictsObject

Collects all of the conflicts for the project and its components



331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/vanagon/project.rb', line 331

def get_conflicts
  conflicts = []
  conflicts << @conflicts.flatten
  conflicts << components.flat_map(&:conflicts)
  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



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

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



246
247
248
249
250
251
# File 'lib/vanagon/project.rb', line 246

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



434
435
436
437
# File 'lib/vanagon/project.rb', line 434

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



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

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)



488
489
490
491
492
493
494
495
# File 'lib/vanagon/project.rb', line 488

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_postinstall_required_actions(pkg_state) ⇒ String

Collects the postinstall packaging actions that must exit successfully 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)



504
505
506
507
508
# File 'lib/vanagon/project.rb', line 504

def get_postinstall_required_actions(pkg_state)
  scripts = components.flat_map(&:postinstall_required_actions).compact.select { |s| s.pkg_state.include? pkg_state }.map(&:scripts)
  return ': no postinstall required scripts provided' if scripts.empty?
  scripts.join("\n")
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)



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

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)



405
406
407
408
409
410
411
412
413
# File 'lib/vanagon/project.rb', line 405

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)



516
517
518
519
520
521
522
523
# File 'lib/vanagon/project.rb', line 516

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



371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/vanagon/project.rb', line 371

def get_provides
  provides = []
  provides << @provides.flatten
  provides << 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



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

def get_replaces
  replaces = []
  replaces << @replaces.flatten
  replaces << 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



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

def get_requires
  requires = []
  requires << @requires.flatten
  requires << components.flat_map(&:requires)
  requires.flatten!
  requires.each do |requirement|
    requirement.version = @platform.version_munger(requirement.version, default: '<') if requirement.version
  end
  requires.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



565
566
567
568
569
570
571
572
573
574
575
576
# File 'lib/vanagon/project.rb', line 565

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.



257
258
259
260
261
# File 'lib/vanagon/project.rb', line 257

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, or array of services if there’s more than one



356
357
358
359
360
361
362
363
364
365
366
# File 'lib/vanagon/project.rb', line 356

def get_service(name)
  components.each do |component|
    if component.name == name
      if component.service.size == 1
        return component.service.first
      end
      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



589
590
591
# File 'lib/vanagon/project.rb', line 589

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



605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
# File 'lib/vanagon/project.rb', line 605

def get_tarball_files
  # 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)



421
422
423
424
425
426
427
428
429
# File 'lib/vanagon/project.rb', line 421

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



442
443
444
445
# File 'lib/vanagon/project.rb', line 442

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

#has_configfiles?Boolean

Returns:

  • (Boolean)


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

def has_configfiles?
  !get_configfiles.empty?
end

#has_conflicts?Boolean

Returns:

  • (Boolean)


344
345
346
# File 'lib/vanagon/project.rb', line 344

def has_conflicts?
  !get_conflicts.empty?
end

#has_provides?Boolean

Returns:

  • (Boolean)


384
385
386
# File 'lib/vanagon/project.rb', line 384

def has_provides?
  !get_provides.empty?
end

#has_replaces?Boolean

Returns:

  • (Boolean)


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

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



597
598
599
# File 'lib/vanagon/project.rb', line 597

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



665
666
667
# File 'lib/vanagon/project.rb', line 665

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

#load_upstream_metadata(metadata_uri) ⇒ Object



891
892
893
894
895
896
897
898
899
900
901
902
# File 'lib/vanagon/project.rb', line 891

def ()
  VanagonLogger.info "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



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

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:



846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
# File 'lib/vanagon/project.rb', line 846

def load_yaml_settings(settings_uri, settings_sha1_uri = nil)
  source_type = yaml_settings_source_type(settings_uri, settings_sha1_uri)

  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 = if source_type == :http
                  File.join(working_directory, source.file)
                else
                  source.file
                end

    @settings.merge!(YAML.safe_load(File.read(yaml_path), permitted_classes: [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



657
658
659
# File 'lib/vanagon/project.rb', line 657

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



648
649
650
# File 'lib/vanagon/project.rb', line 648

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.



193
194
195
# File 'lib/vanagon/project.rb', line 193

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)


738
739
740
741
742
743
744
745
746
# File 'lib/vanagon/project.rb', line 738

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



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

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



672
673
674
# File 'lib/vanagon/project.rb', line 672

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:



794
795
796
797
798
799
800
801
802
803
804
805
806
807
# File 'lib/vanagon/project.rb', line 794

def publish_yaml_settings(platform)
  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)


182
183
184
# File 'lib/vanagon/project.rb', line 182

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

#save_manifest_json(platform, additional_directories = nil) ⇒ Object

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

Parameters:

  • platform (String)

    platform we’re writing metadata for

  • additional_directories (String|Array[String]) (defaults to: nil)

    additional directories to write build_metadata.<project>.<platform>.json to



754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
# File 'lib/vanagon/project.rb', line 754

def save_manifest_json(platform, additional_directories = nil) # rubocop:disable Metrics/AbcSize
  manifest = build_manifest_json
   = (manifest, @upstream_metadata)

  ext_directory = 'ext'
  FileUtils.mkdir_p ext_directory

  directories = [ext_directory, additional_directories].compact
   = "build_metadata.#{name}.#{platform.name}.json"
  directories.each do |directory|
    File.open(File.join(directory, ), 'w') do |f|
      f.write(JSON.pretty_generate())
    end
  end

  ## VANAGON-132 Backwards compatibility: make a 'build_metadata.json' file
  # No need to propagate this backwards compatibility to the new additional
  # directories
  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



218
219
220
# File 'lib/vanagon/project.rb', line 218

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



210
211
212
# File 'lib/vanagon/project.rb', line 210

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

#yaml_settings_source_type(settings_uri, settings_sha1_uri) ⇒ Object

Get the source_type of the settings_uri. Complain if we don’t like stuff about it.



870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
# File 'lib/vanagon/project.rb', line 870

def yaml_settings_source_type(settings_uri, settings_sha1_uri)
  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, 'The sha1sum URI for the YAML file must be provided ' \
                          'when inheriting YAML settings over http'
  end

  source_type
end