Basic "Box2" implementation.

This is the beginning of the new box internals. The basic idea is that
the new box has a new field: provider. The provider will describe what
provider that box was built with and what provider it is made to work
with.
This commit is contained in:
Mitchell Hashimoto 2012-06-27 16:55:12 -07:00
parent 933b0b3101
commit 42826356ad
6 changed files with 172 additions and 2 deletions

View File

@ -63,6 +63,7 @@ require "vagrant/registry"
module Vagrant
autoload :Action, 'vagrant/action'
autoload :Box, 'vagrant/box'
autoload :Box2, 'vagrant/box2'
autoload :BoxCollection, 'vagrant/box_collection'
autoload :CLI, 'vagrant/cli'
autoload :Command, 'vagrant/command'

58
lib/vagrant/box2.rb Normal file
View File

@ -0,0 +1,58 @@
module Vagrant
# Represents a "box," which is a package Vagrant environment that is used
# as a base image when creating a new guest machine.
#
# XXX: This will be renamed to "Box" when it is more stable and functional,
# and the old Box will be removed.
class Box2
include Comparable
# The box name. This is the logical name used when adding the box.
#
# @return [String]
attr_reader :name
# This is the provider that this box is built for.
#
# @return [Symbol]
attr_reader :provider
# This is the directory on disk where this box exists.
#
# @return [Pathname]
attr_reader :directory
# This is used to initialize a box.
#
# @param [String] name Logical name of the box.
# @param [Symbol] provider The provider that this box implements.
# @param [Pathname] directory The directory where this box exists on
# disk.
def initialize(name, provider, directory)
@name = name
@provider = provider
@directory = directory
end
# This deletes the box. This is NOT undoable.
def destroy!
# Delete the directory to delete the box.
FileUtils.rm_r(@directory)
# Just return true always
true
rescue Errno::ENOENT
# This means the directory didn't exist. Not a problem.
return true
end
# Implemented for comparison with other boxes. Comparison is
# implemented by comparing names and providers.
def <=>(other)
return super if !other.is_a?(self.class)
# Comparison is done by composing the name and provider
"#{@name}-#{@provider}" <=> "#{other.name}-#{other.provider}"
end
end
end

View File

@ -0,0 +1,25 @@
module Vagrant
# Represents a collection a boxes found on disk. This provides methods
# for accessing/finding individual boxes, adding new boxes, or deleting
# boxes.
#
# XXX: This will be renamed to "BoxCollection" when it is more stable
# and functional, and the old BoxCollection will be removed.
class BoxCollection2
# Initializes the collection.
#
# @param [Pathname] directory The directory that contains the collection
# of boxes.
def initialize(directory)
@directory = directory
end
# Find a box in the collection with the given name and provider.
#
# @param [String] name Name of the box (logical name).
# @Param [String] provider Provider that the box implements.
# @return [Box] The box found, or `nil` if not found.
def find(name, provider)
end
end
end

View File

@ -1,5 +1,6 @@
require "tempfile"
require "support/tempdir"
require "unit/support/isolated_environment"
shared_context "unit" do
@ -23,6 +24,8 @@ shared_context "unit" do
# This helper creates a temporary file and returns a Pathname
# object pointed to it.
#
# @return [Pathname]
def temporary_file(contents=nil)
f = Tempfile.new("vagrant-unit")
@ -38,6 +41,20 @@ shared_context "unit" do
return Pathname.new(f.path)
end
# This creates a temporary directory and returns a {Pathname}
# pointing to it.
#
# @return [Pathname]
def temporary_dir
# Create a temporary directory and append it to the instance
# variabe so that it isn't garbage collected and deleted
d = Tempdir.new("vagrant-unit")
@_temp_files << d
# Return the pathname
return Pathname.new(d.path)
end
# This helper provides temporary environmental variable changes.
def with_temp_env(environment)
# Build up the new environment, preserving the old values so we

View File

@ -0,0 +1,69 @@
require File.expand_path("../../base", __FILE__)
require "pathname"
describe Vagrant::Box2 do
include_context "unit"
let(:name) { "foo" }
let(:provider) { :virtualbox }
let(:directory) { temporary_dir }
let(:instance) { described_class.new(name, provider, directory) }
it "provides the name" do
instance.name.should == name
end
it "provides the provider" do
instance.provider.should == provider
end
it "provides the directory" do
instance.directory.should == directory
end
describe "destroying" do
it "should destroy an existing box" do
# Verify that our "box" exists
directory.exist?.should be
# Destroy it
instance.destroy!.should be
# Verify that it is "destroyed"
directory.exist?.should_not be
end
it "should not error destroying a non-existent box" do
# Delete the directory
directory.rmtree
# Destroy it
instance.destroy!.should be
end
end
describe "comparison and ordering" do
it "should be equal if the name and provider match" do
a = described_class.new("a", :foo, directory)
b = described_class.new("a", :foo, directory)
a.should == b
end
it "should not be equal if the name and provider do not match" do
a = described_class.new("a", :foo, directory)
b = described_class.new("b", :foo, directory)
a.should_not == b
end
it "should sort them in order of name then provider" do
a = described_class.new("a", :foo, directory)
b = described_class.new("b", :foo, directory)
c = described_class.new("c", :foo2, directory)
[c, a, b].sort.should == [a, b, c]
end
end
end

View File

@ -3,9 +3,9 @@ require File.expand_path("../../base", __FILE__)
describe Vagrant::BoxCollection do
include_context "unit"
let(:environment) { isolated_environment }
let(:environment) { isolated_environment }
let(:action_runner) { double("action runner") }
let(:instance) { described_class.new(environment.boxes_dir, action_runner) }
let(:instance) { described_class.new(environment.boxes_dir, action_runner) }
it "should list all available boxes" do
# No boxes yet.