class Autoproj::VCSDefinition

Representation of a VCS definition contained in a source.yml file or in autoproj/manifest

Constants

ABSOLUTE_PATH_OR_URI
HistoryEntry
RawEntry

Attributes

history[R]

This VCSDefinition history

i.e. the list of VCSDefinition objects that led to this one by means of calls to {#update}

@return [Array<HistoryEntry>]

options[R]

The VCS options

@return [Hash]

raw[R]

The original spec in hash form

@return [Array<RawEntry>]

type[R]

The VCS type

@return [Symbol]

url[R]

The VCS URL

@return [String]

Public Class Methods

from_raw(spec, from: nil, raw: [], history: []) click to toggle source

Converts a ‘raw’ VCS representation to a normalized hash.

The raw definition can have three forms:

* as a plain string, which is a relative/absolute path
* as a plain string, which is a vcs_type:url string
* as a hash

@return [VCSDefinition] @raise ArgumentError if the raw specification does not match an

expected format
# File lib/autoproj/vcs_definition.rb, line 204
def self.from_raw(spec, from: nil, raw: [], history: [])
    normalized_spec = normalize_vcs_hash(spec)
    unless (type = normalized_spec.delete(:type))
        raise ArgumentError,
              "the source specification #{raw_spec_to_s(spec)} normalizes "\
              "into #{raw_spec_to_s(normalized_spec)}, "\
              "which does not have a VCS type"
    end

    if !(url  = normalized_spec.delete(:url)) && type != "none"
        raise ArgumentError,
              "the source specification #{raw_spec_to_s(spec)} normalizes "\
              "into #{raw_spec_to_s(normalized_spec)}, "\
              "which does not have a URL. "\
              "Only VCS of type 'none' do not require one"
    end

    VCSDefinition.new(
        type, url, normalized_spec, from: from, history: history, raw: raw
    )
end
new(type, url, vcs_options, from: nil, raw: [], history: []) click to toggle source
# File lib/autoproj/vcs_definition.rb, line 36
def initialize(type, url, vcs_options, from: nil, raw: [], history: [])
    unless raw.respond_to?(:to_ary)
        raise ArgumentError, "wrong format for the raw field (#{raw.inspect})"
    end

    @type = type
    @url = url
    @options = vcs_options
    if type != "none" && type != "local" && !Autobuild.respond_to?(type)
        raise ConfigError.new, "version control #{type} is unknown to autoproj"
    end

    @history = history + [HistoryEntry.new(from, self)]
    @raw     = raw
end
none() click to toggle source

Create a null VCS object

# File lib/autoproj/vcs_definition.rb, line 53
def self.none
    from_raw({ type: "none" })
end
normalize_vcs_hash(spec, base_dir: nil) click to toggle source

Normalizes a VCS definition contained in a YAML file into a hash

It handles custom source handler expansion, as well as the bad habit of forgetting a ‘:’ at the end of a line:

- package_name
  branch: value

@raise ArgumentError if the given spec cannot be normalized

# File lib/autoproj/vcs_definition.rb, line 120
def self.normalize_vcs_hash(spec, base_dir: nil)
    plain = Array.new
    filtered_spec = Hash.new

    if spec.respond_to?(:to_str)
        plain << spec
        spec = Hash.new
    else
        Array(spec).each do |key, value|
            keys = key.to_s.split(/\s+/)
            plain.concat(keys[0..-2])
            filtered_spec[keys[-1].to_sym] = value
        end
        spec = filtered_spec
    end

    if plain.size > 1
        raise ArgumentError, "invalid syntax"
    elsif plain.size == 1
        short_url = plain.first
        vcs, *url = short_url.split(":")

        # Check if VCS is a known version control system or source handler
        # shortcut. If it is not, look for a local directory called
        # short_url
        if Autobuild.respond_to?(vcs)
            spec.merge!(type: vcs, url: url.join(":"))
        elsif Autoproj.has_source_handler?(vcs)
            spec = Autoproj.call_source_handler(vcs, url.join(":"), spec)
        else
            source_dir =
                if Pathname.new(short_url).absolute?
                    File.expand_path(short_url)
                elsif base_dir
                    File.expand_path(short_url, base_dir)
                else
                    raise ArgumentError,
                          "VCS path '#{short_url}' is relative and no "\
                          "base_dir was given"
                end
            unless File.directory?(source_dir)
                raise ArgumentError,
                      "'#{short_url}' is neither a remote source "\
                      "specification, nor an existing local directory"
            end
            spec.merge!(type: "local", url: source_dir)
        end
    end

    spec, vcs_options = Kernel.filter_options spec, type: nil, url: nil
    spec.merge!(vcs_options)
    unless spec[:url]
        # Verify that none of the keys are source handlers. If it is the
        # case, convert
        filtered_spec = Hash.new
        spec.dup.each do |key, value|
            if Autoproj.has_source_handler?(key)
                spec.delete(key)
                spec = Autoproj.call_source_handler(key, value, spec)
                break
            end
        end
    end

    spec
end
raw_spec_to_s(spec) click to toggle source

@api private

Converts a raw spec (a hash, really) into a nicely formatted string

# File lib/autoproj/vcs_definition.rb, line 190
def self.raw_spec_to_s(spec)
    "{ #{spec.sort_by(&:first).map { |k, v| "#{k}: #{v}" }.join(', ')} }"
end
to_absolute_url(url, root_dir) click to toggle source
# File lib/autoproj/vcs_definition.rb, line 254
def self.to_absolute_url(url, root_dir)
    url = File.expand_path(url, root_dir) if url && url !~ ABSOLUTE_PATH_OR_URI
    url
end
update_raw_vcs_spec(old, new) click to toggle source

Updates the VCS specification old by the information contained in new

Both old and new are supposed to be in hash form. It is assumed that old has already been normalized by a call to {.normalize_vcs_hash}. new can be in “raw” form.

# File lib/autoproj/vcs_definition.rb, line 99
def self.update_raw_vcs_spec(old, new)
    new = normalize_vcs_hash(new)
    if new.has_key?(:type) && (old[:type] != new[:type])
        # The type changed. We replace the old definition by the new one
        # completely, and we make sure that the new definition is valid
        from_raw(new)
        new
    else
        old.merge(new)
    end
end

Public Instance Methods

==(other_vcs) click to toggle source
# File lib/autoproj/vcs_definition.rb, line 226
def ==(other_vcs)
    return false unless other_vcs.kind_of?(VCSDefinition)

    if local?
        other_vcs.local? && url == other_vcs.url
    elsif other_vcs.local?
        false
    elsif none?
        other_vcs.none?
    elsif other_vcs.none?
        false
    else
        this_importer = create_autobuild_importer
        other_importer = other_vcs.create_autobuild_importer
        this_importer.source_id == other_importer.source_id
    end
end
create_autobuild_importer() click to toggle source

Returns a properly configured instance of a subclass of Autobuild::Importer that match this VCS definition

@return [Autobuild::Importer,nil] the autobuild importer

# File lib/autoproj/vcs_definition.rb, line 278
def create_autobuild_importer
    return unless needs_import?

    importer = Autobuild.send(type, url, options)
    if importer.respond_to?(:declare_alternate_repository)
        history.each do |entry|
            package_set = entry.package_set
            vcs         = entry.vcs
            next if !package_set || package_set.main?

            importer.declare_alternate_repository(package_set.name, vcs.url, vcs.options)
        end
    end
    importer
end
eql?(other_vcs) click to toggle source
# File lib/autoproj/vcs_definition.rb, line 248
def eql?(other_vcs)
    to_hash == other_vcs.to_hash
end
hash() click to toggle source
# File lib/autoproj/vcs_definition.rb, line 244
def hash
    to_hash.hash
end
local?() click to toggle source

Whether this points to a local directory

# File lib/autoproj/vcs_definition.rb, line 63
def local?
    @type == "local"
end
needs_import?() click to toggle source

Whether the underlying package needs to be imported

# File lib/autoproj/vcs_definition.rb, line 260
def needs_import?
    type != "none" && type != "local"
end
none?() click to toggle source

Whether there is actually a version control definition

# File lib/autoproj/vcs_definition.rb, line 58
def none?
    @type == "none"
end
overrides_key() click to toggle source
# File lib/autoproj/vcs_definition.rb, line 264
def overrides_key
    return if none?

    if local?
        "local:#{url}"
    else
        create_autobuild_importer.repository_id
    end
end
to_hash() click to toggle source

Converts self to a Hash description that could be passed to {.from_raw}

@return [Hash]

# File lib/autoproj/vcs_definition.rb, line 70
def to_hash
    Hash[type: type, url: url].merge(options)
end
to_s() click to toggle source

Returns a pretty representation of this VCS definition

# File lib/autoproj/vcs_definition.rb, line 295
def to_s
    if type == "none"
        "none"
    else
        desc = "#{type}:#{url}"
        unless options.empty?
            desc = "#{desc} #{options.to_a.sort_by { |key, _| key.to_s }.map { |key, value| "#{key}=#{value}" }.join(' ')}"
        end
        desc
    end
end
update(spec, from: nil, raw: Array.new) click to toggle source

Update this VCS definition with new information / options and return the updated definition

@return [VCSDefinition]

# File lib/autoproj/vcs_definition.rb, line 78
def update(spec, from: nil, raw: Array.new)
    new = self.class.normalize_vcs_hash(spec)
    new_raw = Array.new
    new_history = Array.new

    # If the type changed, we replace the old definition by the new one
    # completely. Otherwise, we append it to the current one
    if !new.has_key?(:type) || (type == new[:type])
        new = to_hash.merge(new)
        new_raw = self.raw + raw
        new_history = history
    end
    self.class.from_raw(new, from: from, history: new_history, raw: new_raw)
end