require 'repertoire/media/exceptions/unknown_media' require 'repertoire/media/exceptions/repository_exists' require 'repertoire/media/exceptions/checkout_failed' require 'repertoire/media/exceptions/update_failed' require 'repertoire/extensions/uri' require 'fileutils' module Repertoire module Media # # Returns the +Hash+ of all registered Media types. # def Media.types @@media_types ||= {} end # # Returns +true+ if there is a Media type registered with the matching # _name_. # def Media.supports?(name) Media.types.has_key?(name.to_sym) end # # Returns the Media type with the matching _name_. # def Media.get(name) name = name.to_sym unless Media.supports?(name) raise(UnknownMedia,"media type #{name.dump} is not registered",caller) end return Media.types[name] end # # Returns the +Hash+ of all registered Media types and their associated # URI schemes. # def Media.schemes @@media_schemes ||= {} end # # Returns an +Array+ of all registered URI schemes. # def Media.registered_schemes Media.schemes.keys end # # Returns +true+ if a Media type was registered for the specified # _scheme_, returns +false+ otherwise. # def Media.supports_scheme?(scheme) Media.schemes.has_key?(scheme.to_s) end # # Returns the Media type that was registered for the specified _scheme_. # def Media.supports_scheme(name) name = name.to_s unless Media.supports_scheme?(name) raise(UnknownMedia,"media type for scheme #{name.dump} is not registered",caller) end return Media.schemes[name] end # # Returns the +Hash+ of all registered Media types and their # associated media storage directories. # def Media.directories @@media_directories ||= {} end # # Returns an +Array+ of all registered directories. # def Media.registered_directories Media.directories.keys end # # Returns +true+ if a Media type was registered with the specified # _directory_, returns +false+ otherwise. # def Media.recognizes_directory?(name) Media.directories.has_key?(name.to_s) end # # Returns the Media type that was registered for the specified # _directory_. # def Media.recognizes_directory(name) name = name.to_s unless Media.recognizes_directory?(name) raise(UnknownMedia,"media type for directory #{name.dump} is not registered",caller) end return Media.directories[name] end # # Get the Media type that was registered for the scheme of the # specified _uri_. # def Media.guess_from_uri(uri) scheme = URI(uri).scheme return [scheme, Media.supports_scheme(scheme)] end # # Attempts to determine the correct Media type for the specified _path_. # def Media.guess_from_path(path) path = File.expand_path(path) Media.directories.each do |directory,media| if File.directory?(File.join(path,directory)) return media end end raise(UnknownMedia,"the media type for #{path.dump} is unknown",caller) end # # Checkout the repository at the specified _options_. If a _block_ # is given, it will be passed the path of the local repository # after the repository is successfully checked out. # # _options_ must contain the following key: # <tt>:uri</tt>:: The URI of the repository to checkout. # # _options_ may also contain the additional keys: # <tt>:path</tt>:: Path to checkout the repository to. # <tt>:media</tt>:: The media type of the repository. Defaults to the # value of Media.get_for_uri. # <tt>:into</tt>:: Checkout the repository into the given directory. # Cannot be used with <tt>:path</tt>. # def Media.checkout(options={},&block) uri = options[:uri].to_s path = options[:path] into = options[:into] media = options[:media] unless path if into into = File.expand_path(into) unless File.directory?(into) FileUtils.mkdir_p(into) end path = File.join(into,URI.repo_name(uri)) else path = URI.repo_name(uri) end end path = File.expand_path(path) if File.exists?(path) raise(RepositoryExists,"the repository #{path.dump} already exists",caller) end if media handler = Media.get(media) else media, handler = Media.guess_from_uri(uri) end begin handler.checkout(uri,path) rescue CommandFailed raise(CheckoutFailed,"failed to checkout the repository located at #{uri.dump}",caller) end block.call(path,media,uri) if block return {:path => path, :media => media, :uri => uri} end # # Update the repository with the specified _options_. If a _block_ # is given, it will be passed the path of the local repository # after the repository is successfully updated. # # _options_ must contain the following keys: # <tt>:path</tt>:: The path of the repository to update. # # _options_ may also contain the additional keys: # <tt>:uri</tt>:: The URI to update against. # <tt>:media</tt>:: The type of the repository. Defaults to # Media.guess_from_uri if <tt>:uri</tt> is given, # otherwise Media.guess_from_path. # def Media.update(options={},&block) path = File.expand_path(options[:path]) uri = options[:uri] media = options[:media] if media handler = Media.get(media) elsif uri media, handler = Media.guess_from_uri(uri) else handler = Media.guess_from_path(path) end begin handler.update(path,uri) rescue CommandFailed raise(UpdateFailed,"failed to update the repository at #{path.dump}",caller) end block.call(media,path,uri) if block return {:media => media, :path => path, :uri => uri} end # # Delete the repository at the specified _path_. If a _block_ is # given, it will be passed the _path_ before it is deleted. # def Media.delete(path,&block) path = File.expand_path(path) block.call(path) if block FileUtils.rm_r(path.to_s,:force => true, :secure => true) return nil end end end