StringBlockEditor to help plugins with owning parts of files

This commit is contained in:
Mitchell Hashimoto 2013-01-15 17:49:46 -08:00
parent ec47d214f0
commit 335503a688
2 changed files with 144 additions and 0 deletions

View File

@ -0,0 +1,66 @@
module Vagrant
module Util
# This class modifies strings by creating and managing Vagrant-owned
# "blocks" via wrapping them in specially formed comments.
#
# This is useful when modifying a file that someone else owns and adding
# automatic entries into it. Example: /etc/exports or some other
# configuration file.
#
# Vagrant marks ownership of a block in the string by wrapping it in
# VAGRANT-BEGIN and VAGRANT-END comments with a unique ID. Example:
#
# foo
# # VAGRANT-BEGIN: id
# some contents
# created by vagrant
# # VAGRANT-END: id
#
# The goal of this class is to be able to insert and remove these
# blocks without modifying anything else in the string.
#
# The strings usually come from files but it is up to the caller to
# manage the file resource.
class StringBlockEditor
# The current string value. This is the value that is modified by
# the methods below.
#
# @return [String]
attr_reader :value
def initialize(string)
@value = string
end
# This returns the keys (or ids) that are in the string.
#
# @return [<Array<String>]
def keys
regexp = /^#\s*VAGRANT-BEGIN:\s*(.+?)$(.*)^#\s*VAGRANT-END:\s(\1)$/m
@value.scan(regexp).map do |match|
match[0]
end
end
# This deletes the block with the given key if it exists.
def delete(key)
regexp = /^#\s*VAGRANT-BEGIN:\s*#{key}$.*^#\s*VAGRANT-END:\s*#{key}$\r?\n?/m
@value.gsub!(regexp, "")
end
# This inserts a block with the given key and value.
#
# @param [String] key
# @param [String] value
def insert(key, value)
new_block = <<BLOCK
# VAGRANT-BEGIN: #{key}
#{value}
# VAGRANT-END: #{key}
BLOCK
@value << "\n#{new_block}"
end
end
end
end

View File

@ -0,0 +1,78 @@
require File.expand_path("../../../base", __FILE__)
require "vagrant/util/string_block_editor"
describe Vagrant::Util::StringBlockEditor do
describe "#keys" do
it "should return all the keys" do
data = <<DATA
# VAGRANT-BEGIN: foo
value
# VAGRANT-END: foo
another
# VAGRANT-BEGIN: bar
content
# VAGRANT-END: bar
DATA
described_class.new(data).keys.should == ["foo", "bar"]
end
end
describe "#delete" do
it "should delete nothing if the key doesn't exist" do
data = "foo"
instance = described_class.new(data)
instance.delete("key")
instance.value.should == data
end
it "should delete the matching blocks if they exist" do
data = <<DATA
# VAGRANT-BEGIN: foo
value
# VAGRANT-END: foo
# VAGRANT-BEGIN: foo
another
# VAGRANT-END: foo
another
# VAGRANT-BEGIN: bar
content
# VAGRANT-END: bar
DATA
new_data = <<DATA
another
# VAGRANT-BEGIN: bar
content
# VAGRANT-END: bar
DATA
instance = described_class.new(data)
instance.delete("foo")
instance.value.should == new_data
end
end
describe "#insert" do
it "should insert the given key and value" do
data = <<DATA
# VAGRANT-BEGIN: bar
content
# VAGRANT-END: bar
DATA
new_data = <<DATA
#{data}
# VAGRANT-BEGIN: foo
value
# VAGRANT-END: foo
DATA
instance = described_class.new(data)
instance.insert("foo", "value")
instance.value.should == new_data
end
end
end