lib/repertoire/media/media.rb in repertoire-0.1.0 vs lib/repertoire/media/media.rb in repertoire-0.1.1
- old
+ new
@@ -1,134 +1,242 @@
require 'repertoire/media/exceptions/unknown_media'
-require 'repertoire/media/exceptions/program_not_found'
+require 'repertoire/media/exceptions/repository_exists'
+require 'repertoire/media/exceptions/checkout_failed'
+require 'repertoire/media/exceptions/update_failed'
require 'repertoire/extensions/uri'
-require 'repertoire/compat'
require 'fileutils'
module Repertoire
- class Media
-
+ module Media
#
- # Returns the Hash of all registered Media types.
+ # Returns the +Hash+ of all registered Media types.
#
def Media.types
- @types ||= {}
+ @@media_types ||= {}
end
#
- # Returns +true+ if a Media type was registered for the specified
- # _scheme_, returns +false+ otherwise.
+ # Returns +true+ if there is a Media type registered with the matching
+ # _name_.
#
- def Media.supported?(scheme)
- Media.types.has_key?(scheme.to_s)
+ def Media.supports?(name)
+ Media.types.has_key?(name.to_sym)
end
#
- # Get the Media type that was registered for the specified _scheme_.
+ # Returns the Media type with the matching _name_.
#
- def Media.get(scheme)
- unless Media.supported?(scheme)
- raise(UnknownMedia,"media type #{scheme.dump} is unsupported",caller)
+ 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[scheme]
+ return Media.types[name]
end
#
- # Get the Media type that was registered for the scheme of the
- # specified _uri_.
+ # Returns the +Hash+ of all registered Media types and their associated
+ # URI schemes.
#
- def Media.get_for_uri(uri)
- Media.get(URI.parse(uri).scheme)
+ def Media.schemes
+ @@media_schemes ||= {}
end
#
- # Attempts to determine the correct Media type for the specified _path_.
+ # Returns an +Array+ of all registered URI schemes.
#
- def Media.guess(path)
- path = File.expand_path(path)
+ def Media.registered_schemes
+ Media.schemes.keys
+ end
- Media.types.values.uniq.each do |media|
- if media.respond_to?(:is_repo?)
- return media if media.is_repo?(path)
- 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
- raise(UnknownMedia,"the media type for #{path.dump} is unknown",caller)
+ return Media.schemes[name]
end
#
- # Checkout the repository at the specified _uri_ and the given _path_.
+ # Returns the +Hash+ of all registered Media types and their
+ # associated media storage directories.
#
- def Media.checkout(uri,path=nil)
- if path
- path = File.expand_path(path)
- else
- path = URI.repo_name(uri)
- end
+ def Media.directories
+ @@media_directories ||= {}
+ end
- return Media.get_for_uri(uri).checkout(uri,path)
+ #
+ # Returns an +Array+ of all registered directories.
+ #
+ def Media.registered_directories
+ Media.directories.keys
end
#
- # Update the repository at the specified _path_ and the given _uri_.
- # If _uri_ is not given Repertoire will attempt to guess the media
- # type of the repository, see Media.guess.
+ # Returns +true+ if a Media type was registered with the specified
+ # _directory_, returns +false+ otherwise.
#
- def Media.update(path,uri=nil)
- path = File.expand_path(path)
+ def Media.recognizes_directory?(name)
+ Media.directories.has_key?(name.to_s)
+ end
- if uri.nil?
- media = Media.guess(path)
- else
- media = Media.get_for_uri(uri)
+ #
+ # 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.update(path,uri)
+ return Media.directories[name]
end
#
- # Delete the repository at the specified _path_.
+ # Get the Media type that was registered for the scheme of the
+ # specified _uri_.
#
- def Media.delete(path)
- FileUtils.rm_r(path.to_s,:force => true, :secure => true)
+ def Media.guess_from_uri(uri)
+ scheme = URI(uri).scheme
+
+ return [scheme, Media.supports_scheme(scheme)]
end
- protected
+ #
+ # 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
+
#
- # Register a Media type for the specified _schemes_.
+ # 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.
#
- # uses_schemes 'cvs'
+ # _options_ must contain the following key:
+ # <tt>:uri</tt>:: The URI of the repository to checkout.
#
- # uses_schemes 'svn', 'svn+ssh'
+ # _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 self.uses_schemes(*schemes)
- schemes.each do |scheme|
- Media.types[scheme.to_s] = self
+ 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
#
- # Runs the command specified by _program_ and the given _args_.
- # If _program_ cannot be found on the system, a ProgramNotFound
- # exception will be raised.
+ # 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.
#
- # sh('ls','-la','/')
+ # _options_ must contain the following keys:
+ # <tt>:path</tt>:: The path of the repository to update.
#
- def self.sh(program,*args)
- program = program.to_s
+ # _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]
- program_path = Compat.find_program(program)
- unless program_path
- raise(ProgramNotFound,"the program #{program.dump} was not found",caller)
+ if media
+ handler = Media.get(media)
+ elsif uri
+ media, handler = Media.guess_from_uri(uri)
+ else
+ handler = Media.guess_from_path(path)
end
- # stringify the args
- args = args.map { |arg| arg.to_s }
+ begin
+ handler.update(path,uri)
+ rescue CommandFailed
+ raise(UpdateFailed,"failed to update the repository at #{path.dump}",caller)
+ end
- return system(program_path,*args)
+ 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