autoproj 2.8.8 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/alog +5 -3
- data/lib/autoproj.rb +2 -0
- data/lib/autoproj/cli/base.rb +8 -1
- data/lib/autoproj/cli/build.rb +5 -3
- data/lib/autoproj/cli/locate.rb +5 -1
- data/lib/autoproj/cli/osdeps.rb +1 -0
- data/lib/autoproj/cli/status.rb +13 -4
- data/lib/autoproj/cli/update.rb +9 -5
- data/lib/autoproj/default.osdeps +14 -0
- data/lib/autoproj/manifest.rb +7 -9
- data/lib/autoproj/ops/build.rb +48 -2
- data/lib/autoproj/ops/configuration.rb +18 -0
- data/lib/autoproj/os_package_installer.rb +27 -0
- data/lib/autoproj/os_repository_installer.rb +53 -0
- data/lib/autoproj/os_repository_resolver.rb +137 -0
- data/lib/autoproj/package_managers/apt_dpkg_manager.rb +70 -10
- data/lib/autoproj/package_managers/bundler_manager.rb +9 -2
- data/lib/autoproj/package_managers/debian_version.rb +123 -0
- data/lib/autoproj/package_managers/manager.rb +9 -0
- data/lib/autoproj/package_managers/pip_manager.rb +4 -0
- data/lib/autoproj/package_selection.rb +36 -10
- data/lib/autoproj/package_set.rb +39 -4
- data/lib/autoproj/repository_managers/apt.rb +289 -0
- data/lib/autoproj/repository_managers/manager.rb +26 -0
- data/lib/autoproj/repository_managers/unknown_os_manager.rb +30 -0
- data/lib/autoproj/test.rb +1 -0
- data/lib/autoproj/version.rb +1 -1
- data/lib/autoproj/workspace.rb +21 -7
- metadata +8 -2
| @@ -50,6 +50,35 @@ def empty? | |
| 50 50 | 
             
                            selection.empty?
         | 
| 51 51 | 
             
                        end
         | 
| 52 52 |  | 
| 53 | 
            +
                        # Returns the source packages selected explicitely or through
         | 
| 54 | 
            +
                        # dependencies
         | 
| 55 | 
            +
                        #
         | 
| 56 | 
            +
                        # @param [Manifest] manifest
         | 
| 57 | 
            +
                        # @return [Array<PackageDefinition>]
         | 
| 58 | 
            +
                        def all_selected_source_packages(manifest)
         | 
| 59 | 
            +
                            names = Set.new
         | 
| 60 | 
            +
                            roots = each_source_package_name.to_set
         | 
| 61 | 
            +
                            roots.each do |pkg_name|
         | 
| 62 | 
            +
                                manifest.find_autobuild_package(pkg_name).all_dependencies(names)
         | 
| 63 | 
            +
                            end
         | 
| 64 | 
            +
                            names.merge(roots).map do |pkg_name|
         | 
| 65 | 
            +
                                manifest.find_package_definition(pkg_name)
         | 
| 66 | 
            +
                            end
         | 
| 67 | 
            +
                        end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                        # Returns the source packages selected explicitely or through
         | 
| 70 | 
            +
                        # dependencies
         | 
| 71 | 
            +
                        #
         | 
| 72 | 
            +
                        # @param [Manifest] manifest
         | 
| 73 | 
            +
                        # @return [Array<String>]
         | 
| 74 | 
            +
                        def all_selected_osdep_packages(manifest)
         | 
| 75 | 
            +
                            all_sources = all_selected_source_packages(manifest)
         | 
| 76 | 
            +
                            from_source = all_sources.each_with_object(Set.new) do |pkg, s|
         | 
| 77 | 
            +
                                s.merge(pkg.autobuild.os_packages)
         | 
| 78 | 
            +
                            end
         | 
| 79 | 
            +
                            from_source | osdeps
         | 
| 80 | 
            +
                        end
         | 
| 81 | 
            +
             | 
| 53 82 | 
             
                        def each(&block)
         | 
| 54 83 | 
             
                            Autoproj.warn_deprecated "PackageSelection#each", "use PackageSelection#each_source_package_name instead", 0
         | 
| 55 84 | 
             
                            each_source_package_name(&block)
         | 
| @@ -78,27 +107,24 @@ def packages | |
| 78 107 | 
             
                            source_packages
         | 
| 79 108 | 
             
                        end
         | 
| 80 109 |  | 
| 81 | 
            -
                        def select(sel, packages,  | 
| 82 | 
            -
                             | 
| 110 | 
            +
                        def select(sel, packages, *_backward, weak: false, osdep: false)
         | 
| 111 | 
            +
                            unless _backward.empty?
         | 
| 83 112 | 
             
                                Autoproj.warn_deprecated "calling PackageSelection#select with a boolean as third argument", "use e.g. weak: true instead", 0
         | 
| 84 | 
            -
                                 | 
| 113 | 
            +
                                weak = _backward.first
         | 
| 85 114 | 
             
                            end
         | 
| 86 | 
            -
                            options = Kernel.validate_options options,
         | 
| 87 | 
            -
                                weak: false,
         | 
| 88 | 
            -
                                osdep: false
         | 
| 89 115 |  | 
| 90 116 | 
             
                            packages = Array(packages).to_set
         | 
| 91 117 | 
             
                            matches[sel].merge(packages)
         | 
| 92 118 | 
             
                            packages.each do |pkg_name|
         | 
| 93 119 | 
             
                                selection[pkg_name] << sel
         | 
| 94 120 | 
             
                            end
         | 
| 95 | 
            -
                            if  | 
| 121 | 
            +
                            if osdep
         | 
| 96 122 | 
             
                                osdeps.merge(packages)
         | 
| 97 123 | 
             
                            else
         | 
| 98 124 | 
             
                                source_packages.merge(packages)
         | 
| 99 125 | 
             
                            end
         | 
| 100 126 |  | 
| 101 | 
            -
                            weak_dependencies[sel] =  | 
| 127 | 
            +
                            weak_dependencies[sel] = weak
         | 
| 102 128 | 
             
                        end
         | 
| 103 129 |  | 
| 104 130 | 
             
                        def initialize_copy(old)
         | 
| @@ -160,10 +186,10 @@ def filter_excluded_and_ignored_packages(manifest) | |
| 160 186 | 
             
                                end
         | 
| 161 187 | 
             
                            end
         | 
| 162 188 |  | 
| 163 | 
            -
                            source_packages.delete_if do |pkg_name| | 
| 189 | 
            +
                            source_packages.delete_if do |pkg_name|
         | 
| 164 190 | 
             
                                manifest.excluded?(pkg_name) || manifest.ignored?(pkg_name)
         | 
| 165 191 | 
             
                            end
         | 
| 166 | 
            -
                            osdeps.delete_if do |pkg_name| | 
| 192 | 
            +
                            osdeps.delete_if do |pkg_name|
         | 
| 167 193 | 
             
                                manifest.excluded?(pkg_name) || manifest.ignored?(pkg_name)
         | 
| 168 194 | 
             
                            end
         | 
| 169 195 | 
             
                            selection.delete_if do |pkg_name, _|
         | 
    
        data/lib/autoproj/package_set.rb
    CHANGED
    
    | @@ -5,7 +5,7 @@ module Autoproj | |
| 5 5 | 
             
                # dependencies that are provided by the operating system (.osdeps file).
         | 
| 6 6 | 
             
                class PackageSet
         | 
| 7 7 | 
             
                    # Exception raised when an operation that needs the source.yml to be
         | 
| 8 | 
            -
                    # loaded is called before {PackageSet#load_description_file} is called | 
| 8 | 
            +
                    # loaded is called before {PackageSet#load_description_file} is called
         | 
| 9 9 | 
             
                    class NotLoaded < RuntimeError
         | 
| 10 10 | 
             
                        attr_reader :package_set
         | 
| 11 11 | 
             
                        def initialize(package_set)
         | 
| @@ -34,7 +34,7 @@ def add_source_file(name) | |
| 34 34 |  | 
| 35 35 | 
             
                    # The manifest this package set is registered on
         | 
| 36 36 | 
             
                    #
         | 
| 37 | 
            -
                    # @return [Manifest] | 
| 37 | 
            +
                    # @return [Manifest]
         | 
| 38 38 | 
             
                    def manifest
         | 
| 39 39 | 
             
                        ws.manifest
         | 
| 40 40 | 
             
                    end
         | 
| @@ -64,10 +64,21 @@ def manifest | |
| 64 64 | 
             
                    #   and the corresponding OSPackageResolver object
         | 
| 65 65 | 
             
                    attr_reader :all_osdeps
         | 
| 66 66 |  | 
| 67 | 
            +
                    # The set of OSRepositoryResolver object that represent the osrepos files
         | 
| 68 | 
            +
                    # available in this package set
         | 
| 69 | 
            +
                    #
         | 
| 70 | 
            +
                    # @return [Array<(String,OSRepositoryResolver)>] the list of osdep files
         | 
| 71 | 
            +
                    #   and the corresponding OSRepositoryResolver object
         | 
| 72 | 
            +
                    attr_reader :all_osrepos
         | 
| 73 | 
            +
             | 
| 67 74 | 
             
                    # The OSPackageResolver which is a merged version of all OSdeps in
         | 
| 68 75 | 
             
                    # {#all_osdeps}
         | 
| 69 76 | 
             
                    attr_reader :os_package_resolver
         | 
| 70 77 |  | 
| 78 | 
            +
                    # The OSRepositoryResolver which is a merged version of all OSrepos in
         | 
| 79 | 
            +
                    # {#all_osrepos}
         | 
| 80 | 
            +
                    attr_reader :os_repository_resolver
         | 
| 81 | 
            +
             | 
| 71 82 | 
             
                    # If this package set has been imported from another package set, this
         | 
| 72 83 | 
             
                    # is the other package set object
         | 
| 73 84 | 
             
                    attr_accessor :imported_from
         | 
| @@ -144,12 +155,14 @@ def initialize( | |
| 144 155 | 
             
                            raise ArgumentError, "cannot create a package set with a nil vcs, create a null VCS using VCSDefinition.none"
         | 
| 145 156 | 
             
                        end
         | 
| 146 157 | 
             
                        @name = name
         | 
| 158 | 
            +
                        @os_repository_resolver = OSRepositoryResolver.new
         | 
| 147 159 | 
             
                        @os_package_resolver = OSPackageResolver.new(
         | 
| 148 160 | 
             
                            operating_system: ws.os_package_resolver.operating_system,
         | 
| 149 161 | 
             
                            package_managers: ws.os_package_resolver.package_managers,
         | 
| 150 162 | 
             
                            os_package_manager: ws.os_package_resolver.os_package_manager)
         | 
| 151 163 | 
             
                        @importer_definitions_cache = Hash.new
         | 
| 152 164 | 
             
                        @all_osdeps = []
         | 
| 165 | 
            +
                        @all_osrepos = []
         | 
| 153 166 | 
             
                        @constants_definitions = Hash.new
         | 
| 154 167 | 
             
                        @required_autoproj_version = '0'
         | 
| 155 168 | 
             
                        @version_control = Array.new
         | 
| @@ -175,11 +188,24 @@ def load_osdeps(file, **options) | |
| 175 188 | 
             
                        new_osdeps
         | 
| 176 189 | 
             
                    end
         | 
| 177 190 |  | 
| 191 | 
            +
                    # Load a new osrepos file for this package set
         | 
| 192 | 
            +
                    def load_osrepos(file)
         | 
| 193 | 
            +
                        new_osrepos = OSRepositoryResolver.load(file)
         | 
| 194 | 
            +
                        all_osrepos << new_osrepos
         | 
| 195 | 
            +
                        os_repository_resolver.merge(all_osrepos.last)
         | 
| 196 | 
            +
                        new_osrepos
         | 
| 197 | 
            +
                    end
         | 
| 198 | 
            +
             | 
| 178 199 | 
             
                    # Enumerate all osdeps package names from this package set
         | 
| 179 200 | 
             
                    def each_osdep(&block)
         | 
| 180 201 | 
             
                        os_package_resolver.all_package_names.each(&block)
         | 
| 181 202 | 
             
                    end
         | 
| 182 203 |  | 
| 204 | 
            +
                    # Enumerate all osrepos entries from this package set
         | 
| 205 | 
            +
                    def each_osrepo(&block)
         | 
| 206 | 
            +
                        os_repository_resolver.all_entries.each(&block)
         | 
| 207 | 
            +
                    end
         | 
| 208 | 
            +
             | 
| 183 209 | 
             
                    # True if this source has already been checked out on the local autoproj
         | 
| 184 210 | 
             
                    # installation
         | 
| 185 211 | 
             
                    def present?; File.directory?(raw_local_dir) end
         | 
| @@ -302,7 +328,7 @@ def repository_id | |
| 302 328 | 
             
                    # For local sources, is simply returns the path to the source directory.
         | 
| 303 329 | 
             
                    def user_local_dir
         | 
| 304 330 | 
             
                        if local?
         | 
| 305 | 
            -
                            return vcs.url | 
| 331 | 
            +
                            return vcs.url
         | 
| 306 332 | 
             
                        else
         | 
| 307 333 | 
             
                            File.join(ws.config_dir, 'remotes', name)
         | 
| 308 334 | 
             
                        end
         | 
| @@ -714,7 +740,7 @@ def overrides_for(package, vcs, require_existing: true) | |
| 714 740 | 
             
                    # This is a helper for {#overrides_for}
         | 
| 715 741 | 
             
                    def resolve_overrides(key, vcs)
         | 
| 716 742 | 
             
                        overrides.each do |file, file_overrides|
         | 
| 717 | 
            -
                            new_spec, new_raw_entry = | 
| 743 | 
            +
                            new_spec, new_raw_entry =
         | 
| 718 744 | 
             
                                Autoproj.in_file file do
         | 
| 719 745 | 
             
                                    version_control_field(key, file_overrides, validate: false, file: file)
         | 
| 720 746 | 
             
                                end
         | 
| @@ -762,6 +788,15 @@ def each_osdeps_file | |
| 762 788 | 
             
                            yield(file)
         | 
| 763 789 | 
             
                        end
         | 
| 764 790 | 
             
                    end
         | 
| 791 | 
            +
             | 
| 792 | 
            +
                    # Yields each osdeps definition files that are present in this package
         | 
| 793 | 
            +
                    # set
         | 
| 794 | 
            +
                    def each_osrepos_file
         | 
| 795 | 
            +
                        return enum_for(__method__) if !block_given?
         | 
| 796 | 
            +
                        Dir.glob(File.join(local_dir, "*.osrepos")).each do |file|
         | 
| 797 | 
            +
                            yield(file)
         | 
| 798 | 
            +
                        end
         | 
| 799 | 
            +
                    end
         | 
| 765 800 | 
             
                end
         | 
| 766 801 | 
             
            end
         | 
| 767 802 |  | 
| @@ -0,0 +1,289 @@ | |
| 1 | 
            +
            # frozen_string_literal: false
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'open3'
         | 
| 4 | 
            +
            require 'pathname'
         | 
| 5 | 
            +
            require 'open-uri'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Autoproj
         | 
| 8 | 
            +
                module RepositoryManagers
         | 
| 9 | 
            +
                    # Apt repository manager class
         | 
| 10 | 
            +
                    class APT < Manager
         | 
| 11 | 
            +
                        attr_reader :source_files
         | 
| 12 | 
            +
                        attr_reader :source_entries
         | 
| 13 | 
            +
                        attr_reader :sources_dir
         | 
| 14 | 
            +
                        attr_reader :autoproj_sources
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                        SOURCES_DIR = '/etc/apt'.freeze
         | 
| 17 | 
            +
                        SOURCE_TYPES = ['deb', 'deb-src'].freeze
         | 
| 18 | 
            +
                        AUTOPROJ_SOURCES = '/etc/apt/sources.list.d/autoproj.list'.freeze
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                        def initialize(ws, sources_dir: SOURCES_DIR, autoproj_sources: AUTOPROJ_SOURCES)
         | 
| 21 | 
            +
                            @sources_dir = sources_dir
         | 
| 22 | 
            +
                            @autoproj_sources = autoproj_sources
         | 
| 23 | 
            +
                            @source_files = Dir[File.join(sources_dir, '**', '*.list')]
         | 
| 24 | 
            +
                            @source_entries = {}
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                            source_files.each { |file| load_sources_from_file(file) }
         | 
| 27 | 
            +
                            super(ws)
         | 
| 28 | 
            +
                        end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                        def os_dependencies
         | 
| 31 | 
            +
                            super + ['archive-keyring', 'gnupg', 'apt-transport-https']
         | 
| 32 | 
            +
                        end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                        def load_sources_from_file(file)
         | 
| 35 | 
            +
                            contents = File.open(file).read
         | 
| 36 | 
            +
                            contents.gsub!(/\r\n?/, "\n")
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                            contents.each_line do |line|
         | 
| 39 | 
            +
                                @source_entries[file] ||= []
         | 
| 40 | 
            +
                                @source_entries[file] << parse_source_line(line, raise_if_invalid: false)
         | 
| 41 | 
            +
                            end
         | 
| 42 | 
            +
                        end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                        def parse_source_line(line, raise_if_invalid: true)
         | 
| 45 | 
            +
                            entry = {}
         | 
| 46 | 
            +
                            entry[:valid] = false
         | 
| 47 | 
            +
                            entry[:enabled] = true
         | 
| 48 | 
            +
                            entry[:source] = ''
         | 
| 49 | 
            +
                            entry[:comment] = ''
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                            line.strip!
         | 
| 52 | 
            +
                            if line.start_with?('#')
         | 
| 53 | 
            +
                                entry[:enabled] = false
         | 
| 54 | 
            +
                                line = line[1..-1]
         | 
| 55 | 
            +
                            end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                            i = line.index('#')
         | 
| 58 | 
            +
                            if i&.positive?
         | 
| 59 | 
            +
                                entry[:comment] = line[(i + 1)..-1].strip
         | 
| 60 | 
            +
                                line = line[0..(i - 1)]
         | 
| 61 | 
            +
                            end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                            entry[:source] = line.strip
         | 
| 64 | 
            +
                            chunks = entry[:source].split
         | 
| 65 | 
            +
                            entry[:valid] = true if SOURCE_TYPES.include?(chunks[0])
         | 
| 66 | 
            +
                            entry[:source] = chunks.join(' ')
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                            if raise_if_invalid && (!entry[:valid] || !entry[:enabled])
         | 
| 69 | 
            +
                                raise ConfigError, "Invalid source line: #{entry[:source]}"
         | 
| 70 | 
            +
                            end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                            entry
         | 
| 73 | 
            +
                        end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                        def add_source(source, file = nil)
         | 
| 76 | 
            +
                            file = if file
         | 
| 77 | 
            +
                                       File.join(sources_dir, 'sources.list.d', file)
         | 
| 78 | 
            +
                                   else
         | 
| 79 | 
            +
                                       autoproj_sources
         | 
| 80 | 
            +
                                   end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                            new_entry = parse_source_line(source)
         | 
| 83 | 
            +
                            found = entry_exist?(new_entry)
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                            if found
         | 
| 86 | 
            +
                                file = found.first
         | 
| 87 | 
            +
                                entry = found.last
         | 
| 88 | 
            +
                                return false if entry[:enabled]
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                                enable_entry_in_file(file, entry)
         | 
| 91 | 
            +
                            else
         | 
| 92 | 
            +
                                add_entry_to_file(file, new_entry)
         | 
| 93 | 
            +
                            end
         | 
| 94 | 
            +
                        end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                        def append_entry(contents, entry)
         | 
| 97 | 
            +
                            unless entry[:enabled]
         | 
| 98 | 
            +
                                contents << '#'
         | 
| 99 | 
            +
                                contents << ' ' unless entry[:source].start_with?('#')
         | 
| 100 | 
            +
                            end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                            contents << entry[:source]
         | 
| 103 | 
            +
                            contents << "# #{entry[:comment]}" unless entry[:comment].empty?
         | 
| 104 | 
            +
                            contents << "\n"
         | 
| 105 | 
            +
                        end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                        def enable_entry_in_file(file, enable_entry)
         | 
| 108 | 
            +
                            contents = ''
         | 
| 109 | 
            +
                            source_entries[file].each do |entry|
         | 
| 110 | 
            +
                                entry[:enabled] = true if enable_entry[:source] == entry[:source]
         | 
| 111 | 
            +
                                append_entry(contents, entry)
         | 
| 112 | 
            +
                            end
         | 
| 113 | 
            +
                            run_tee_command(['sudo', 'tee', file], contents)
         | 
| 114 | 
            +
                            true
         | 
| 115 | 
            +
                        end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                        def add_entry_to_file(file, entry)
         | 
| 118 | 
            +
                            run_tee_command(['sudo', 'tee', '-a', file], entry[:source])
         | 
| 119 | 
            +
                            @source_entries[file] ||= []
         | 
| 120 | 
            +
                            @source_entries[file] << entry
         | 
| 121 | 
            +
                            true
         | 
| 122 | 
            +
                        end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                        def run_tee_command(command, contents)
         | 
| 125 | 
            +
                            contents = StringIO.new("#{contents}\n")
         | 
| 126 | 
            +
                            Autobuild::Subprocess.run('autoproj', 'osrepos', *command, input_streams: [contents])
         | 
| 127 | 
            +
                        end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                        def entry_exist?(new_entry)
         | 
| 130 | 
            +
                            source_entries.each_pair do |file, entries|
         | 
| 131 | 
            +
                                entry = entries.find { |e| e[:source] == new_entry[:source] }
         | 
| 132 | 
            +
                                return [file, entry] if entry
         | 
| 133 | 
            +
                            end
         | 
| 134 | 
            +
                            nil
         | 
| 135 | 
            +
                        end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                        def source_exist?(source)
         | 
| 138 | 
            +
                            entry_exist?(parse_source_line(source))
         | 
| 139 | 
            +
                        end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                        def key_exist?(key)
         | 
| 142 | 
            +
                            exist = false
         | 
| 143 | 
            +
                            Open3.popen3("apt-key export #{key}") do |_, _, stderr, wait_thr|
         | 
| 144 | 
            +
                                exist = true if wait_thr.value.success? && stderr.read.empty?
         | 
| 145 | 
            +
                            end
         | 
| 146 | 
            +
                            exist
         | 
| 147 | 
            +
                        end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                        def apt_update
         | 
| 150 | 
            +
                            Autobuild::Subprocess.run(
         | 
| 151 | 
            +
                                'autoproj',
         | 
| 152 | 
            +
                                'osrepos',
         | 
| 153 | 
            +
                                'sudo',
         | 
| 154 | 
            +
                                'apt-get',
         | 
| 155 | 
            +
                                'update'
         | 
| 156 | 
            +
                            )
         | 
| 157 | 
            +
                        end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                        def add_apt_key(id, origin, type: :keyserver)
         | 
| 160 | 
            +
                            if type == :keyserver
         | 
| 161 | 
            +
                                Autobuild::Subprocess.run(
         | 
| 162 | 
            +
                                    'autoproj',
         | 
| 163 | 
            +
                                    'osrepos',
         | 
| 164 | 
            +
                                    'sudo',
         | 
| 165 | 
            +
                                    'apt-key',
         | 
| 166 | 
            +
                                    'adv',
         | 
| 167 | 
            +
                                    '--keyserver',
         | 
| 168 | 
            +
                                    origin,
         | 
| 169 | 
            +
                                    '--recv-key',
         | 
| 170 | 
            +
                                    id
         | 
| 171 | 
            +
                                )
         | 
| 172 | 
            +
                            else
         | 
| 173 | 
            +
                                open(origin) do |io|
         | 
| 174 | 
            +
                                    Autobuild::Subprocess.run(
         | 
| 175 | 
            +
                                        'autoproj',
         | 
| 176 | 
            +
                                        'osrepos',
         | 
| 177 | 
            +
                                        'sudo',
         | 
| 178 | 
            +
                                        'apt-key',
         | 
| 179 | 
            +
                                        'add',
         | 
| 180 | 
            +
                                        '-',
         | 
| 181 | 
            +
                                        input_streams: [io]
         | 
| 182 | 
            +
                                    )
         | 
| 183 | 
            +
                                end
         | 
| 184 | 
            +
                            end
         | 
| 185 | 
            +
                        rescue Errno::ENOENT, SocketError => e
         | 
| 186 | 
            +
                            raise ConfigError, e.message
         | 
| 187 | 
            +
                        end
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                        def filter_installed_definitions(definitions)
         | 
| 190 | 
            +
                            definitions = definitions.dup.reject do |definition|
         | 
| 191 | 
            +
                                if definition['type'] == 'repo'
         | 
| 192 | 
            +
                                    _, entry = source_exist?(definition['repo'])
         | 
| 193 | 
            +
                                    entry && entry[:enabled]
         | 
| 194 | 
            +
                                else
         | 
| 195 | 
            +
                                    key_exist?(definition['id'])
         | 
| 196 | 
            +
                                end
         | 
| 197 | 
            +
                            end
         | 
| 198 | 
            +
                            definitions
         | 
| 199 | 
            +
                        end
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                        def print_installing_definitions(definitions)
         | 
| 202 | 
            +
                            repos = definitions.select { |definition| definition['type'] == 'repo' }
         | 
| 203 | 
            +
                            keys = definitions.select { |definition| definition['type'] == 'key' }
         | 
| 204 | 
            +
             | 
| 205 | 
            +
                            unless repos.empty?
         | 
| 206 | 
            +
                                Autoproj.message '  adding apt repositories:'
         | 
| 207 | 
            +
                                repos.each do |repo|
         | 
| 208 | 
            +
                                    if repo['file']
         | 
| 209 | 
            +
                                        Autoproj.message "    #{repo['repo']}, file: #{repo['file']}"
         | 
| 210 | 
            +
                                    else
         | 
| 211 | 
            +
                                        Autoproj.message "    #{repo['repo']}"
         | 
| 212 | 
            +
                                    end
         | 
| 213 | 
            +
                                end
         | 
| 214 | 
            +
                            end
         | 
| 215 | 
            +
                            return if keys.empty?
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                            Autoproj.message '  adding apt keys:'
         | 
| 218 | 
            +
                            keys.each do |key|
         | 
| 219 | 
            +
                                if key['keyserver']
         | 
| 220 | 
            +
                                    Autoproj.message "    id: #{key['id']}, keyserver: #{key['keyserver']}"
         | 
| 221 | 
            +
                                else
         | 
| 222 | 
            +
                                    Autoproj.message "    id: #{key['id']}, url: #{key['url']}"
         | 
| 223 | 
            +
                                end
         | 
| 224 | 
            +
                            end
         | 
| 225 | 
            +
                        end
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                        # Validates repositories definitions from .osrepos files
         | 
| 228 | 
            +
                        #
         | 
| 229 | 
            +
                        # Examples:
         | 
| 230 | 
            +
                        #
         | 
| 231 | 
            +
                        # - ubuntu:
         | 
| 232 | 
            +
                        #   - xenial:
         | 
| 233 | 
            +
                        #     type: repo
         | 
| 234 | 
            +
                        #     repo: 'deb http://archive.ubuntu.com/ubuntu/ xenial main restricted'
         | 
| 235 | 
            +
                        #
         | 
| 236 | 
            +
                        # - ubuntu:
         | 
| 237 | 
            +
                        #   - xenial:
         | 
| 238 | 
            +
                        #     type: key
         | 
| 239 | 
            +
                        #     id: 630239CC130E1A7FD81A27B140976EAF437D05B5
         | 
| 240 | 
            +
                        #     keyserver: 'hkp://ha.pool.sks-keyservers.net:80'
         | 
| 241 | 
            +
                        #
         | 
| 242 | 
            +
                        # - ubuntu:
         | 
| 243 | 
            +
                        #   - xenial:
         | 
| 244 | 
            +
                        #     type: key
         | 
| 245 | 
            +
                        #     id: D2486D2DD83DB69272AFE98867170598AF249743
         | 
| 246 | 
            +
                        #     url: 'http://packages.osrfoundation.org/gazebo.key'
         | 
| 247 | 
            +
                        #
         | 
| 248 | 
            +
                        def validate_definitions(definitions)
         | 
| 249 | 
            +
                            invalid_string = 'Invalid apt repository definition'
         | 
| 250 | 
            +
                            definitions.each do |definition|
         | 
| 251 | 
            +
                                raise ConfigError, "#{invalid_string} type: #{definition['type']}" unless %w[repo key].include?(definition['type'])
         | 
| 252 | 
            +
             | 
| 253 | 
            +
                                if definition['type'] == 'repo'
         | 
| 254 | 
            +
                                    raise ConfigError, "#{invalid_string}: 'repo' key missing" if definition['repo'].nil?
         | 
| 255 | 
            +
                                    raise ConfigError, "#{invalid_string}: 'repo' should be a String" unless definition['repo'].is_a?(String)
         | 
| 256 | 
            +
                                    raise ConfigError, "#{invalid_string}: 'file' should be a String" if definition['file'] && !definition['file'].is_a?(String)
         | 
| 257 | 
            +
                                    if definition['file'] && Pathname.new(definition['file']).absolute?
         | 
| 258 | 
            +
                                        raise ConfigError, "#{invalid_string}: 'file' should be a relative to #{File.join(SOURCES_DIR, 'sources.list.d')}"
         | 
| 259 | 
            +
                                    end
         | 
| 260 | 
            +
                                else
         | 
| 261 | 
            +
                                    raise ConfigError, "#{invalid_string}: 'id' key missing" if definition['id'].nil?
         | 
| 262 | 
            +
                                    raise ConfigError, "#{invalid_string}: 'id' should be a String" unless definition['id'].is_a?(String)
         | 
| 263 | 
            +
                                    raise ConfigError, "#{invalid_string}: 'url' conflicts with 'keyserver'" if definition['url'] && definition['keyserver']
         | 
| 264 | 
            +
                                    raise ConfigError, "#{invalid_string}: 'url' should be a String" if definition['url'] && !definition['url'].is_a?(String)
         | 
| 265 | 
            +
                                    raise ConfigError, "#{invalid_string}: 'keyserver' should be a String" if definition['keyserver'] && !definition['keyserver'].is_a?(String)
         | 
| 266 | 
            +
                                end
         | 
| 267 | 
            +
                            end
         | 
| 268 | 
            +
                        end
         | 
| 269 | 
            +
             | 
| 270 | 
            +
                        def install(definitions)
         | 
| 271 | 
            +
                            super
         | 
| 272 | 
            +
                            validate_definitions(definitions)
         | 
| 273 | 
            +
                            definitions = filter_installed_definitions(definitions)
         | 
| 274 | 
            +
                            print_installing_definitions(definitions)
         | 
| 275 | 
            +
             | 
| 276 | 
            +
                            definitions.each do |definition|
         | 
| 277 | 
            +
                                if definition['type'] == 'repo'
         | 
| 278 | 
            +
                                    add_source(definition['repo'], definition['file'])
         | 
| 279 | 
            +
                                else
         | 
| 280 | 
            +
                                    type = definition['url'] ? 'url' : 'keyserver'
         | 
| 281 | 
            +
                                    origin = definition[type]
         | 
| 282 | 
            +
                                    add_apt_key(definition['id'], origin, type: type.to_sym)
         | 
| 283 | 
            +
                                end
         | 
| 284 | 
            +
                            end
         | 
| 285 | 
            +
                            apt_update unless definitions.empty?
         | 
| 286 | 
            +
                        end
         | 
| 287 | 
            +
                    end
         | 
| 288 | 
            +
                end
         | 
| 289 | 
            +
            end
         |