def source(val = NULL)
      unless null?(val)
        unless val.is_a?(Hash)
          raise InvalidValue.new(:source,
            "be a kind of `Hash', but was `#{val.class.inspect}'")
        end

        val = canonicalize_source(val)

        extra_keys = val.keys - [
          :git, :file, :path, :url, # fetcher types
          :md5, :sha1, :sha256, :sha512, # hash type - common to all fetchers
          :cookie, :warning, :unsafe, :extract, :cached_name, :authorization, # used by net_fetcher
          :options, # used by path_fetcher
          :submodules # used by git_fetcher
        ]
        unless extra_keys.empty?
          raise InvalidValue.new(:source,
            "only include valid keys. Invalid keys: #{extra_keys.inspect}")
        end

        duplicate_keys = val.keys & [:git, :file, :path, :url]
        unless duplicate_keys.size < 2
          raise InvalidValue.new(:source,
            "not include duplicate keys. Duplicate keys: #{duplicate_keys.inspect}")
        end

        @source ||= {}
        @source.merge!(val)
      end

      override = canonicalize_source(overrides[:source])
      apply_overrides(:source, override)
    end
def source(val = NULL)
      unless null?(val)
        unless val.is_a?(Hash)
          raise InvalidValue.new(:source,
            "be a kind of `Hash', but was `#{val.class.inspect}'")
        end

        val = canonicalize_source(val)

        extra_keys = val.keys - [
          :git, :file, :path, :url, # fetcher types
          :md5, :sha1, :sha256, :sha512, # hash type - common to all fetchers
          :cookie, :warning, :unsafe, :extract, :cached_name, :authorization, # used by net_fetcher
          :options, # used by path_fetcher
          :submodules # used by git_fetcher
        ]
        unless extra_keys.empty?
          raise InvalidValue.new(:source,
            "only include valid keys. Invalid keys: #{extra_keys.inspect}")
        end

        duplicate_keys = val.keys & [:git, :file, :path, :url]
        unless duplicate_keys.size < 2
          raise InvalidValue.new(:source,
            "not include duplicate keys. Duplicate keys: #{duplicate_keys.inspect}")
        end

        @source ||= {}
        @source.merge!(val)
      end

      override = canonicalize_source(overrides[:source])
      apply_overrides(:source, override)
    end
Set or retrieve the source for the software.

 @raise [InvalidValue]
   if the parameter is not a Hash
 @raise [InvalidValue]
   if the hash includes extraneous keys
 @raise [InvalidValue]
   if the hash declares keys that cannot work together
   (like +:git+ and +:path+)

 @example
   source url: 'http://ftp.gnu.org/gnu/autoconf/autoconf-2.68.tar.gz',
          md5: 'c3b5247592ce694f7097873aa07d66fe'

 @param [Hash<Symbol, String>] val
   a single key/pair that defines the kind of source and a path specifier

 @option val [String] :git (nil)
   a git URL
 @option val [String] :github (nil)
   a github ORG/REPO pair (e.g. chef/chef) that will be transformed to https://github.com/ORG/REPO.git
 @option val [String] :url (nil)
   general URL
 @option val [String] :path (nil)
   a fully-qualified local file system path
 @option val [String] :md5 (nil)
   the MD5 checksum of the downloaded artifact
 @option val [String] :sha1 (nil)
   the SHA1 checksum of the downloaded artifact
 @option val [String] :sha256 (nil)
   the SHA256 checksum of the downloaded artifact
 @option val [String] :sha512 (nil)
   the SHA512 checksum of the downloaded artifact

 Only used in net_fetcher:

 @option val [String] :cookie (nil)
   a cookie to set
 @option val [String] :authorization (nil)
   an authorization header to set
 @option val [String] :warning (nil)
   a warning message to print when downloading
 @option val [Symbol] :extract (nil)
   either :tar, :lax_tar :seven_zip

 Only used in path_fetcher:

 @option val [Hash] :options (nil)
   flags/options that are passed through to file_syncer in path_fetcher

 Only used in git_fetcher:

 @option val [Boolean] :submodules (false)
   clone git submodules

 If multiple checksum types are provided, only the strongest will be used.

 @return [Hash]