Convert bare repos to working copy repos and vice-versa

This commit is contained in:
Bruce Williams 2010-03-13 00:00:11 -08:00
parent abd9730802
commit a42116b096
8 changed files with 261 additions and 32 deletions

2
Modulefile Normal file
View File

@ -0,0 +1,2 @@
name 'puppetlabs/vcsrepo'
version '0.0.1'

20
README.GIT.markdown Normal file
View File

@ -0,0 +1,20 @@
Using vcsrepo with Git
======================
To create a blank repository
----------------------------
Define a `vcsrepo` without a `source` or `revision`:
vcsrepo { "/path/to/repo":
ensure: present
}
If you're defining this for a central/"official" repository, you'll
probably want to make it a "bare" repository. Do this by setting
`ensure` to `bare` instead of `present`:
vcsrepo { "/path/to/repo":
ensure: bare
}

2
README.SVN.markdown Normal file
View File

@ -0,0 +1,2 @@
Using vcsrepo with Subversion
=============================

30
README.markdown Normal file
View File

@ -0,0 +1,30 @@
vcsrepo
=======
Purpose
-------
This provides a single type, `vcsrepo`.
This type can be used to describe:
* A working copy checked out from a (remote or local) source, at an
arbitrary revision
* A "blank" working copy not associated with a source (when it makes
sense for the VCS being used)
* A "blank" central repository (when the distinction makes sense for the VCS
being used)
Supported Version Control Systems
---------------------------------
This module supports a wide range of VCS types, each represented by a
separate provider.
For information on how to use this module with a specific VCS, see
`README.<VCS>.markdown`.
License
-------
See LICENSE.

View File

@ -1,3 +1,6 @@
require 'tmpdir'
require 'digest/md5'
Puppet::Type.type(:vcsrepo).provide(:git) do
desc "Supports Git repositories"
@ -13,7 +16,14 @@ Puppet::Type.type(:vcsrepo).provide(:git) do
end
def exists?
File.directory?(@resource.value(:path))
case @resource.value(:ensure)
when 'present'
working_copy_exists?
when 'bare'
bare_exists?
else
path_exists?
end
end
def destroy
@ -37,6 +47,22 @@ Puppet::Type.type(:vcsrepo).provide(:git) do
private
def bare_exists?
bare_git_config_exists? && !working_copy_exists?
end
def working_copy_exists?
File.directory?(File.join(@resource.value(:path), '.git'))
end
def path_exists?
File.directory?(@resource.value(:path))
end
def bare_git_config_exists?
File.exist?(File.join(@resource.value(:path), 'config'))
end
def clone_repository(source, path)
git('clone', source, path)
end
@ -48,9 +74,51 @@ Puppet::Type.type(:vcsrepo).provide(:git) do
end
def init_repository(path)
FileUtils.mkdir_p(path)
if @resource.value(:ensure) == 'bare' && working_copy_exists?
convert_working_copy_to_bare
elsif @resource.value(:ensure) == 'present' && bare_exists?
convert_bare_to_working_copy
elsif File.directory?(@resource.value(:path))
raise Puppet::Error, "Could not create repository (non-repository at path)"
else
normal_init
end
end
# Convert working copy to bare
#
# Moves:
# <path>/.git
# to:
# <path>/
def convert_working_copy_to_bare
FileUtils.mv(File.join(@resource.value(:path), '.git'), tempdir)
FileUtils.rm_rf(@resource.value(:path))
FileUtils.cp_r(tempdir, @resource.value(:path))
end
# Convert bare to working copy
#
# Moves:
# <path>/
# to:
# <path>/.git
def convert_bare_to_working_copy
FileUtils.mv(@resource.value(:path), tempdir)
FileUtils.mkdir(@resource.value(:path))
FileUtils.cp_r(tempdir, File.join(@resource.value(:path), '.git'))
reset('HEAD')
git('checkout', '-f')
end
def normal_init
FileUtils.mkdir(@resource.value(:path))
args = ['init']
if @resource.value(:ensure) == 'bare'
args << '--bare'
end
at_path do
git('init')
git(*args)
end
end
@ -70,4 +138,8 @@ Puppet::Type.type(:vcsrepo).provide(:git) do
value
end
def tempdir
@tempdir ||= File.join(Dir.tmpdir, 'vcsrepo-' + Digest::MD5.hexdigest(@resource.value(:path)))
end
end

View File

@ -3,7 +3,13 @@ require 'pathname'
Puppet::Type.newtype(:vcsrepo) do
desc "A local version control repository"
ensurable
ensurable do
defaultvalues
newvalue :bare do
provider.create
end
end
newparam(:path) do
desc "Absolute path to repository"

View File

@ -34,12 +34,67 @@ describe provider_class do
end
end
context "when a source is not given" do
it "should execute 'git init'" do
before do
@resource.expects(:value).with(:path).returns(@path).at_least_once
@resource.expects(:value).with(:source).returns(nil)
Dir.expects(:chdir).with(@path).yields
@provider.expects(:git).with('init')
@provider.create
end
context "when ensure = present" do
before { @resource.expects(:value).with(:ensure).returns('present').at_least_once }
context "when the path does not exist" do
it "should execute 'git init'" do
Dir.expects(:mkdir).with(@path)
Dir.expects(:chdir).with(@path).yields
@provider.expects(:bare_exists?).returns(false)
File.expects(:directory?).with(@path).returns(false)
@provider.expects(:git).with('init')
@provider.create
end
end
context "when the path is a bare repository" do
it "should convert it to a working copy" do
@provider.expects(:bare_exists?).returns(true)
@provider.expects(:convert_bare_to_working_copy)
@provider.create
end
end
context "when the path is not a repository" do
it "should raise an exception" do
File.expects(:directory?).with(@path).returns(true)
@provider.expects(:bare_exists?).returns(false)
proc {
@provider.create
}.should raise_error(Puppet::Error)
end
end
end
context "when ensure = bare" do
before { @resource.expects(:value).with(:ensure).returns('bare').at_least_once }
context "when the path does not exist" do
it "should execute 'git init --bare'" do
Dir.expects(:chdir).with(@path).yields
File.expects(:directory?).with(@path).returns(false)
FileUtils.expects(:mkdir).with(@path)
@provider.expects(:working_copy_exists?).returns(false)
@provider.expects(:git).with('init', '--bare')
@provider.create
end
end
context "when the path is a working copy repository" do
it "should convert it to a bare repository" do
@provider.expects(:working_copy_exists?).returns(true)
@provider.expects(:convert_working_copy_to_bare)
@provider.create
end
end
context "when the path is not a repository" do
it "should raise an exception" do
File.expects(:directory?).with(@path).returns(true)
@provider.expects(:working_copy_exists?).returns(false)
proc {
@provider.create
}.should raise_error(Puppet::Error)
end
end
end
end
end
@ -53,10 +108,54 @@ describe provider_class do
end
describe "when checking existence" do
it "should check for the directory" do
@resource.expects(:value).with(:path).returns(@path)
File.expects(:directory?).with(@path)
@provider.exists?
context "when ensure = present" do
context "when a working copy exists" do
it "should be true" do
@resource.expects(:value).with(:ensure).returns('present').at_least_once
@provider.expects(:working_copy_exists?).returns(true)
@provider.should be_exists
end
end
context "when a bare repo exists" do
it "should be " do
@resource.expects(:value).with(:ensure).returns('present').at_least_once
@provider.expects(:working_copy_exists?).returns(false)
@provider.should_not be_exists
end
end
end
context "when ensure = bare" do
context "when a working copy exists" do
it "should be false" do
@resource.expects(:value).with(:ensure).returns('bare').at_least_once
@provider.expects(:bare_exists?).returns(false)
@provider.should_not be_exists
end
end
context "when a bare repo exists" do
it "should be true" do
@resource.expects(:value).with(:ensure).returns('bare').at_least_once
@provider.expects(:bare_exists?).returns(true)
@provider.should be_exists
end
end
end
context "when ensure = absent" do
before { @resource.expects(:value).with(:ensure).returns('absent') }
context "when the path exists" do
it "should be true" do
@resource.expects(:value).with(:path).returns(@path)
File.expects(:directory?).with(@path).returns(true)
@provider.should be_exists
end
end
context "when the path does not exist" do
it "should be false" do
@resource.expects(:value).with(:path).returns(@path)
File.expects(:directory?).with(@path).returns(false)
@provider.should_not be_exists
end
end
end
end
@ -106,7 +205,7 @@ describe provider_class do
end
end
end
describe "when setting the revision property" do
it "should use 'git fetch' and 'git reset'" do
@resource.expects(:value).with(:path).returns(@path).at_least_once

View File

@ -10,7 +10,7 @@ describe provider_class do
@path = '/tmp/vcsrepo'
end
context 'when creating' do
describe 'when creating' do
context "when a source is given" do
context "and when a revision is given" do
it "should execute 'svn checkout' with a revision" do
@ -53,7 +53,7 @@ describe provider_class do
end
end
context 'when destroying' do
describe 'when destroying' do
it "it should remove the directory" do
@resource.expects(:value).with(:path).returns(@path).at_least_once
FileUtils.expects(:rm_rf).with(@path)
@ -61,7 +61,7 @@ describe provider_class do
end
end
context "when checking existence" do
describe "when checking existence" do
it "should check for the directory" do
@resource.expects(:value).with(:path).returns(@path)
File.expects(:directory?).with(@path)
@ -69,23 +69,21 @@ describe provider_class do
end
end
describe "revision property" do
context "when checking" do
it "should use 'svn info'" do
@resource.expects(:value).with(:path).returns(@path)
p fixture(:svn_info)[/^Revision:\s+(\d+)/m, 1]
@provider.expects('svn').with('info').returns(fixture(:svn_info))
Dir.expects(:chdir).with(@path).yields
@provider.revision.should == '4'
end
describe "when checking the revision property" do
it "should use 'svn info'" do
@resource.expects(:value).with(:path).returns(@path)
@provider.expects('svn').with('info').returns(fixture(:svn_info))
Dir.expects(:chdir).with(@path).yields
@provider.revision.should == '4'
end
context "when setting" do
it "should use 'svn update'" do
@resource.expects(:value).with(:path).returns(@path)
@provider.expects('svn').with('update', '-r', '30')
Dir.expects(:chdir).with(@path).yields
@provider.revision = '30'
end
end
describe "when setting the revision property" do
it "should use 'svn update'" do
@resource.expects(:value).with(:path).returns(@path)
@provider.expects('svn').with('update', '-r', '30')
Dir.expects(:chdir).with(@path).yields
@provider.revision = '30'
end
end