diff options
-rw-r--r-- | Gemfile | 21 | ||||
-rw-r--r-- | README.markdown | 108 | ||||
-rw-r--r-- | lib/puppet/provider/vcsrepo/git.rb | 8 | ||||
-rw-r--r-- | lib/puppet/provider/vcsrepo/svn.rb | 7 | ||||
-rw-r--r-- | lib/puppet/type/vcsrepo.rb | 14 | ||||
-rw-r--r-- | spec/unit/puppet/provider/vcsrepo/git_spec.rb | 2 | ||||
-rw-r--r-- | spec/unit/puppet/provider/vcsrepo/svn_spec.rb | 43 |
7 files changed, 135 insertions, 68 deletions
@@ -1,5 +1,15 @@ source ENV['GEM_SOURCE'] || "https://rubygems.org" +def location_for(place, fake_version = nil) + if place =~ /^(git:[^#]*)#(.*)/ + [fake_version, { :git => $1, :branch => $2, :require => false }].compact + elsif place =~ /^file:\/\/(.*)/ + ['>= 0', { :path => File.expand_path($1), :require => false }] + else + [place, { :require => false }] + end +end + group :development, :unit_tests do gem 'rspec-core', '3.1.7', :require => false gem 'puppetlabs_spec_helper', :require => false @@ -8,8 +18,17 @@ group :development, :unit_tests do gem 'json', :require => false end +beaker_version = ENV['BEAKER_VERSION'] +beaker_rspec_version = ENV['BEAKER_RSPEC_VERSION'] group :system_tests do - gem 'beaker-rspec', :require => false + if beaker_version + gem 'beaker', *location_for(beaker_version) + end + if beaker_rspec_version + gem 'beaker-rspec', *location_for(beaker_rspec_version) + else + gem 'beaker-rspec', :require => false + end gem 'serverspec', :require => false end diff --git a/README.markdown b/README.markdown index 9671fc5..2433d99 100644 --- a/README.markdown +++ b/README.markdown @@ -49,7 +49,7 @@ Also, this module, like Puppet generally, will not create parent directories for To get started with the vcsrepo module, you must simply define the type `vcsrepo` with a path to your repository and the [type of VCS](#Usage) you're using in `provider` (in the below example, Git). - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, } @@ -75,14 +75,14 @@ The vcsrepo module works with the following VCSs: To create a blank repository suitable for use as a central repository, define `vcsrepo` without `source` or `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, } If you're defining `vcsrepo` for a central or official repository, you may want to make it a bare repository. You do this by setting `ensure` to 'bare' rather than 'present'. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => bare, provider => git, } @@ -91,17 +91,17 @@ If you're defining `vcsrepo` for a central or official repository, you may want To get the current HEAD on the master branch, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, - source => "git://example.com/repo.git", + source => 'git://example.com/repo.git', } To get a specific revision or branch (can be a commit SHA, tag, or branch name), **SHA** - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, source => 'git://example.com/repo.git', @@ -110,7 +110,7 @@ To get a specific revision or branch (can be a commit SHA, tag, or branch name), **Tag** - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, source => 'git://example.com/repo.git', @@ -119,7 +119,7 @@ To get a specific revision or branch (can be a commit SHA, tag, or branch name), **Branch name** - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, source => 'git://example.com/repo.git', @@ -128,7 +128,7 @@ To get a specific revision or branch (can be a commit SHA, tag, or branch name), To check out a branch as a specific user, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, source => 'git://example.com/repo.git', @@ -138,7 +138,7 @@ To check out a branch as a specific user, To keep the repository at the latest revision (**WARNING:** this will always overwrite local changes to the repository), - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => latest, provider => git, source => 'git://example.com/repo.git', @@ -147,7 +147,7 @@ To keep the repository at the latest revision (**WARNING:** this will always ove To clone the repository but skip initialiazing submodules, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => latest, provider => git, source => 'git://example.com/repo.git', @@ -157,12 +157,12 @@ To clone the repository but skip initialiazing submodules, ##### Using multiple remotes with a repository Instead of specifying a single string in the 'source' property, you can specify a hash with multiple name => URL mappings, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, source => { - "origin" => "https://github.com/puppetlabs/puppetlabs-vcsrepo.git", - "other_remote" => "https://github.com/other_user/puppetlabs-vcsrepo.git" + origin => 'https://github.com/puppetlabs/puppetlabs-vcsrepo.git', + other_remote => 'https://github.com/other_user/puppetlabs-vcsrepo.git' }, } @@ -187,7 +187,7 @@ For more examples using Git, see `examples/git/`. To create a blank repository suitable for use as a central repository, define `vcsrepo` without `source` or `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => bzr, } @@ -196,7 +196,7 @@ define `vcsrepo` without `source` or `revision`. Provide the `source` location to branch from an existing repository. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => bzr, source => 'lp:myproj', @@ -205,7 +205,7 @@ Provide the `source` location to branch from an existing repository. For a specific revision, use `revision` with a valid revisionspec (see `bzr help revisionspec` for more information on formatting a revision). - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => bzr, source => 'lp:myproj', @@ -228,7 +228,7 @@ For more examples using Bazaar, see `examples/bzr/`. To create a blank repository suitable for use as a central repository, define `vcsrepo` without `source` or `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => cvs, } @@ -237,39 +237,39 @@ define `vcsrepo` without `source` or `revision`. To get the current mainline, - vcsrepo { "/path/to/workspace": + vcsrepo { '/path/to/workspace': ensure => present, provider => cvs, - source => ":pserver:anonymous@example.com:/sources/myproj", + source => ':pserver:anonymous@example.com:/sources/myproj', } To get a specific module on the current mainline, - vcsrepo {"/vagrant/lockss-daemon-source": + vcsrepo {'/vagrant/lockss-daemon-source': ensure => present, provider => cvs, - source => ":pserver:anonymous@lockss.cvs.sourceforge.net:/cvsroot/lockss", - module => "lockss-daemon", + source => ':pserver:anonymous@lockss.cvs.sourceforge.net:/cvsroot/lockss', + module => 'lockss-daemon', } You can use the `compression` parameter to set the GZIP compression levels for your repository history. - vcsrepo { "/path/to/workspace": + vcsrepo { '/path/to/workspace': ensure => present, provider => cvs, compression => 3, - source => ":pserver:anonymous@example.com:/sources/myproj", + source => ':pserver:anonymous@example.com:/sources/myproj', } For a specific tag, use `revision`. - vcsrepo { "/path/to/workspace": + vcsrepo { '/path/to/workspace': ensure => present, provider => cvs, compression => 3, - source => ":pserver:anonymous@example.com:/sources/myproj", - revision => "SOMETAG", + source => ':pserver:anonymous@example.com:/sources/myproj', + revision => 'SOMETAG', } #####Sources that use SSH @@ -287,7 +287,7 @@ For for more examples using CVS, see `examples/cvs/`. To create a blank repository suitable for use as a central repository, define `vcsrepo` without `source` or `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, } @@ -296,51 +296,51 @@ define `vcsrepo` without `source` or `revision`. To get the default branch tip, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, - source => "http://hg.example.com/myrepo", + source => 'http://hg.example.com/myrepo', } For a specific changeset, use `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, - source => "http://hg.example.com/myrepo", + source => 'http://hg.example.com/myrepo', revision => '21ea4598c962', } You can also set `revision` to a tag. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, - source => "http://hg.example.com/myrepo", + source => 'http://hg.example.com/myrepo', revision => '1.1.2', } To check out as a specific user, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, - source => "http://hg.example.com/myrepo", + source => 'http://hg.example.com/myrepo', user => 'user', } To specify an SSH identity key, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, - source => "ssh://hg@hg.example.com/myrepo", - identity => "/home/user/.ssh/id_dsa, + source => 'ssh://hg@hg.example.com/myrepo', + identity => '/home/user/.ssh/id_dsa', } To specify a username and password for HTTP Basic authentication, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => latest, provider => hg, source => 'http://hg.example.com/myrepo', @@ -364,7 +364,7 @@ To create an empty Workspace, define a `vcsrepo` without a `source` or `revision Environment variables P4PORT, P4USER, etc... are used to define the Perforce server connection settings. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => p4 } @@ -378,7 +378,7 @@ A Perforce configuration file can be used by setting the `P4CONFIG` environment defining `p4config`. If a configuration is defined, then the environment variable for `P4CLIENT` is replaced. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => p4, p4config => '.p4config' @@ -388,7 +388,7 @@ defining `p4config`. If a configuration is defined, then the environment variab To sync a depot path to head, ensure `latest`: - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => latest, provider => p4, source => '//depot/branch/...' @@ -396,7 +396,7 @@ To sync a depot path to head, ensure `latest`: For a specific changelist, ensure `present` and specify a `revision`: - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => p4, source => '//depot/branch/...', @@ -405,7 +405,7 @@ For a specific changelist, ensure `present` and specify a `revision`: You can also set `revision` to a label: - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => p4, source => '//depot/branch/...', @@ -428,7 +428,7 @@ For examples you can run, see `examples/p4/` To create a blank repository suitable for use as a central repository, define `vcsrepo` without `source` or `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => svn, } @@ -437,18 +437,18 @@ define `vcsrepo` without `source` or `revision`. Provide a `source` pointing to the branch/tag you want to check out from a repository. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => svn, - source => "svn://svnrepo/hello/branches/foo", + source => 'svn://svnrepo/hello/branches/foo', } You can also provide a specific revision. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => svn, - source => "svn://svnrepo/hello/branches/foo", + source => 'svn://svnrepo/hello/branches/foo', revision => '1234', } @@ -456,11 +456,11 @@ You can also provide a specific revision. To use a specific configuration directory, provide a `configuration` parameter which should be a directory path on the local system where your svn configuration files are. Typically, it is '/path/to/.subversion'. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => svn, - source => "svn://svnrepo/hello/branches/foo", - configuration => "/path/to/.subversion", + source => 'svn://svnrepo/hello/branches/foo', + configuration => '/path/to/.subversion', } #####Sources that use SSH diff --git a/lib/puppet/provider/vcsrepo/git.rb b/lib/puppet/provider/vcsrepo/git.rb index 9d3f7f3..8101253 100644 --- a/lib/puppet/provider/vcsrepo/git.rb +++ b/lib/puppet/provider/vcsrepo/git.rb @@ -5,7 +5,7 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo) commands :git => 'git' - has_features :bare_repositories, :reference_tracking, :ssh_identity, :multiple_remotes, :user, :depth, :submodules + has_features :bare_repositories, :reference_tracking, :ssh_identity, :multiple_remotes, :user, :depth, :branch, :submodules def create if @resource.value(:revision) and @resource.value(:ensure) == :bare @@ -142,7 +142,8 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo) # we loop around the hash. Otherwise, we assume single url specified # in source property if @resource.value(:source).is_a?(Hash) - @resource.value(:source).each do |remote_name, remote_url| + @resource.value(:source).keys.sort.each do |remote_name| + remote_url = @resource.value(:source)[remote_name] at_path { do_update |= update_remote_url(remote_name, remote_url) } end else @@ -180,6 +181,9 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo) if @resource.value(:depth) and @resource.value(:depth).to_i > 0 args.push('--depth', @resource.value(:depth).to_s) end + if @resource.value(:branch) + args.push('--branch', @resource.value(:branch).to_s) + end if @resource.value(:ensure) == :bare args << '--bare' end diff --git a/lib/puppet/provider/vcsrepo/svn.rb b/lib/puppet/provider/vcsrepo/svn.rb index a1b1714..905d5ad 100644 --- a/lib/puppet/provider/vcsrepo/svn.rb +++ b/lib/puppet/provider/vcsrepo/svn.rb @@ -7,7 +7,7 @@ Puppet::Type.type(:vcsrepo).provide(:svn, :parent => Puppet::Provider::Vcsrepo) :svnadmin => 'svnadmin', :svnlook => 'svnlook' - has_features :filesystem_types, :reference_tracking, :basic_auth, :configuration + has_features :filesystem_types, :reference_tracking, :basic_auth, :configuration, :conflict def create if !@resource.value(:source) @@ -92,6 +92,11 @@ Puppet::Type.type(:vcsrepo).provide(:svn, :parent => Puppet::Provider::Vcsrepo) else buildargs.push('update', '-r', desired) end + + if @resource.value(:conflict) + args.push('--accept', @resource.value(:conflict)) + end + at_path do svn(*args) end diff --git a/lib/puppet/type/vcsrepo.rb b/lib/puppet/type/vcsrepo.rb index 3bf4029..e5dfbb5 100644 --- a/lib/puppet/type/vcsrepo.rb +++ b/lib/puppet/type/vcsrepo.rb @@ -40,12 +40,18 @@ Puppet::Type.newtype(:vcsrepo) do feature :depth, "The provider can do shallow clones" + feature :branch, + "The name of the branch" + feature :p4config, "The provider understands Perforce Configuration" feature :submodules, "The repository contains submodules which can be optionally initialized" + feature :conflict, + "The provider supports automatic conflict resolution" + ensurable do attr_accessor :latest @@ -204,6 +210,10 @@ Puppet::Type.newtype(:vcsrepo) do desc "The value to be used to do a shallow clone." end + newparam :branch, :required_features => [:branch] do + desc "The name of the branch to clone." + end + newparam :p4config, :required_features => [:p4config] do desc "The Perforce P4CONFIG environment." end @@ -214,6 +224,10 @@ Puppet::Type.newtype(:vcsrepo) do defaultto true end + newparam :conflict do + desc "The action to take if conflicts exist between repository and working copy" + end + autorequire(:package) do ['git', 'git-core'] end diff --git a/spec/unit/puppet/provider/vcsrepo/git_spec.rb b/spec/unit/puppet/provider/vcsrepo/git_spec.rb index d0153a1..d33c98a 100644 --- a/spec/unit/puppet/provider/vcsrepo/git_spec.rb +++ b/spec/unit/puppet/provider/vcsrepo/git_spec.rb @@ -263,7 +263,7 @@ branches context "when multiple sources are modified" do it "should update the urls" do resource[:source] = {"origin" => "git://git@foo.com/bar.git", "new_remote" => "git://git@foo.com/baz.git"} - provider.expects(:git).at_least_once.with('config', '-l').returns("remote.origin.url=git://git@foo.com/foo.git\n", "remote.origin.url=git://git@foo.com/bar.git\n") + provider.expects(:git).at_least_once.with('config', '-l').returns("remote.origin.url=git://git@foo.com/bar.git\n", "remote.origin.url=git://git@foo.com/foo.git\n") provider.expects(:git).with('remote', 'set-url', 'origin', 'git://git@foo.com/bar.git') provider.expects(:git).with('remote', 'add', 'new_remote', 'git://git@foo.com/baz.git') provider.expects(:git).with('remote','update') diff --git a/spec/unit/puppet/provider/vcsrepo/svn_spec.rb b/spec/unit/puppet/provider/vcsrepo/svn_spec.rb index 494da52..77f0e03 100644 --- a/spec/unit/puppet/provider/vcsrepo/svn_spec.rb +++ b/spec/unit/puppet/provider/vcsrepo/svn_spec.rb @@ -83,10 +83,22 @@ describe Puppet::Type.type(:vcsrepo).provider(:svn) do before do @revision = '30' end - it "should use 'svn update'" do - expects_chdir - provider.expects(:svn).with('--non-interactive', 'update', '-r', @revision) - provider.revision = @revision + context 'with conflict' do + it "should use 'svn update'" do + resource[:conflict] = 'theirs-full' + expects_chdir + provider.expects(:svn).with('--non-interactive', 'update', + '-r', @revision, + '--accept', resource.value(:conflict)) + provider.revision = @revision + end + end + context 'without conflict' do + it "should use 'svn update'" do + expects_chdir + provider.expects(:svn).with('--non-interactive', 'update', '-r', @revision) + provider.revision = @revision + end end end @@ -94,11 +106,24 @@ describe Puppet::Type.type(:vcsrepo).provider(:svn) do before do @revision = '30' end - it "should use 'svn switch'" do - resource[:source] = 'an-unimportant-value' - expects_chdir - provider.expects(:svn).with('--non-interactive', 'switch', '-r', @revision, 'an-unimportant-value') - provider.revision = @revision + context 'with conflict' do + it "should use 'svn switch'" do + resource[:source] = 'an-unimportant-value' + resource[:conflict] = 'theirs-full' + expects_chdir + provider.expects(:svn).with('--non-interactive', 'switch', + '-r', @revision, 'an-unimportant-value', + '--accept', resource.value(:conflict)) + provider.revision = @revision + end + end + context 'without conflict' do + it "should use 'svn switch'" do + resource[:source] = 'an-unimportant-value' + expects_chdir + provider.expects(:svn).with('--non-interactive', 'switch', '-r', @revision, 'an-unimportant-value') + provider.revision = @revision + end end end |