From cc076e5ee566fe2f35d8dd1f3e5638ce50d607df Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 10 Jul 2012 22:16:43 -0700 Subject: [PATCH] Box#repackage to repackage a box. --- lib/vagrant/box.rb | 43 +++++++++++++++++++++++ test/unit/support/isolated_environment.rb | 5 ++- test/unit/vagrant/box_test.rb | 23 ++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/lib/vagrant/box.rb b/lib/vagrant/box.rb index aa122d93d..320ecdcfd 100644 --- a/lib/vagrant/box.rb +++ b/lib/vagrant/box.rb @@ -1,4 +1,10 @@ +require 'fileutils' + +require 'archive/tar/minitar' require "json" +require "log4r" + +require "vagrant/util/platform" module Vagrant # Represents a "box," which is a package Vagrant environment that is used @@ -38,6 +44,8 @@ module Vagrant @provider = provider @directory = directory @metadata = JSON.parse(directory.join("metadata.json").read) + + @logger = Log4r::Logger.new("vagrant::box") end # This deletes the box. This is NOT undoable. @@ -52,6 +60,41 @@ module Vagrant return true end + # This repackages this box and outputs it to the given path. + # + # @param [Pathname] path The full path (filename included) of where + # to output this box. + # @return [Boolean] true if this succeeds. + def repackage(path) + @logger.debug("Repackaging box '#{@name}' to: #{path}") + + path.open(Util::Platform.tar_file_options) do |f| + Archive::Tar::Minitar::Output.open(f) do |output| + # Store the current working directory since we need to change + # for the tar library. + current_dir = FileUtils.pwd + + begin + FileUtils.cd(@directory) + + # Find all the files in our current directory and tar it up! + Dir.glob(File.join(".", "**", "*")).each do |entry| + @logger.debug("Packing file: #{entry}") + Archive::Tar::Minitar.pack_file(entry, output) + end + ensure + # Make sure we always cd back into our previous working + # directory. + FileUtils.cd(current_dir) + end + end + end + + @logger.info("Repackaged box '#{@name}' successfully: #{path}") + + true + end + # Implemented for comparison with other boxes. Comparison is # implemented by comparing names and providers. def <=>(other) diff --git a/test/unit/support/isolated_environment.rb b/test/unit/support/isolated_environment.rb index 9b8735369..e2bf71e18 100644 --- a/test/unit/support/isolated_environment.rb +++ b/test/unit/support/isolated_environment.rb @@ -3,6 +3,7 @@ require "pathname" require "tempfile" require "archive/tar/minitar" +require "json" require "log4r" require "vagrant/util/platform" @@ -73,7 +74,9 @@ module Unit # Create a metadata.json file box_metadata_file = box_dir.join("metadata.json") box_metadata_file.open("w") do |f| - f.write("{}") + f.write(JSON.generate({ + :provider => provider.to_s + })) end # Create a Vagrantfile diff --git a/test/unit/vagrant/box_test.rb b/test/unit/vagrant/box_test.rb index 3c0e6e5b0..e7eb81485 100644 --- a/test/unit/vagrant/box_test.rb +++ b/test/unit/vagrant/box_test.rb @@ -7,6 +7,8 @@ describe Vagrant::Box do let(:environment) { isolated_environment } + let(:box_collection) { Vagrant::BoxCollection.new(environment.boxes_dir) } + let(:name) { "foo" } let(:provider) { :virtualbox } let(:directory) { environment.box2("foo", :virtualbox) } @@ -60,6 +62,27 @@ describe Vagrant::Box do end end + describe "repackaging" do + it "should repackage the box" do + test_file_contents = "hello, world!" + + # Put a file in the box directory to verify it is packaged properly + # later. + directory.join("test_file").open("w") do |f| + f.write(test_file_contents) + end + + # Repackage our box to some temporary directory + box_output_path = temporary_dir.join("package.box") + instance.repackage(box_output_path).should be + + # Let's now add this box again under a different name, and then + # verify that we get the proper result back. + new_box = box_collection.add(box_output_path, "foo2") + new_box.directory.join("test_file").read.should == test_file_contents + 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)