diff --git a/lib/puppet/provider/vcsrepo.rb b/lib/puppet/provider/vcsrepo.rb deleted file mode 100644 index 2c026ba86..000000000 --- a/lib/puppet/provider/vcsrepo.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'tmpdir' -require 'digest/md5' -require 'fileutils' - -# Abstract -class Puppet::Provider::Vcsrepo < Puppet::Provider - - private - - def set_ownership - owner = @resource.value(:owner) || nil - group = @resource.value(:group) || nil - FileUtils.chown_R(owner, group, @resource.value(:path)) - end - - def path_exists? - File.directory?(@resource.value(:path)) - end - - # Note: We don't rely on Dir.chdir's behavior of automatically returning the - # value of the last statement -- for easier stubbing. - def at_path(&block) #:nodoc: - value = nil - Dir.chdir(@resource.value(:path)) do - value = yield - end - value - end - - def tempdir - @tempdir ||= File.join(Dir.tmpdir, 'vcsrepo-' + Digest::MD5.hexdigest(@resource.value(:path))) - end - -end diff --git a/lib/puppet/provider/vcsrepo/bzr.rb b/lib/puppet/provider/vcsrepo/bzr.rb deleted file mode 100644 index a0605624b..000000000 --- a/lib/puppet/provider/vcsrepo/bzr.rb +++ /dev/null @@ -1,64 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', 'vcsrepo') - -Puppet::Type.type(:vcsrepo).provide(:bzr, :parent => Puppet::Provider::Vcsrepo) do - desc "Supports Bazaar repositories" - - commands :bzr => 'bzr' - defaultfor :bzr => :exists - has_features :reference_tracking - - def create - if !@resource.value(:source) - create_repository(@resource.value(:path)) - else - clone_repository(@resource.value(:revision)) - end - end - - def exists? - File.directory?(File.join(@resource.value(:path), '.bzr')) - end - - def destroy - FileUtils.rm_rf(@resource.value(:path)) - end - - def revision - at_path do - current_revid = bzr('version-info')[/^revision-id:\s+(\S+)/, 1] - desired = @resource.value(:revision) - begin - desired_revid = bzr('revision-info', desired).strip.split(/\s+/).last - rescue Puppet::ExecutionFailure - # Possible revid available during update (but definitely not current) - desired_revid = nil - end - if current_revid == desired_revid - desired - else - current_revid - end - end - end - - def revision=(desired) - bzr('update', '-r', desired, @resource.value(:path)) - end - - private - - def create_repository(path) - bzr('init', path) - end - - def clone_repository(revision) - args = ['branch'] - if revision - args.push('-r', revision) - end - args.push(@resource.value(:source), - @resource.value(:path)) - bzr(*args) - end - -end diff --git a/lib/puppet/provider/vcsrepo/cvs.rb b/lib/puppet/provider/vcsrepo/cvs.rb deleted file mode 100644 index e82c23afe..000000000 --- a/lib/puppet/provider/vcsrepo/cvs.rb +++ /dev/null @@ -1,80 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', 'vcsrepo') - -Puppet::Type.type(:vcsrepo).provide(:cvs, :parent => Puppet::Provider::Vcsrepo) do - desc "Supports CVS repositories/workspaces" - - commands :cvs => 'cvs' - defaultfor :cvs => :exists - has_features :gzip_compression, :reference_tracking - - def create - if !@resource.value(:source) - create_repository(@resource.value(:path)) - else - checkout_repository - end - end - - def exists? - if @resource.value(:source) - directory = File.join(@resource.value(:path), 'CVS') - else - directory = File.join(@resource.value(:path), 'CVSROOT') - end - File.directory?(directory) - end - - def destroy - FileUtils.rm_rf(@resource.value(:path)) - end - - def revision - if File.exist?(tag_file) - contents = File.read(tag_file) - # Note: Doesn't differentiate between N and T entries - contents[1..-1] - else - 'MAIN' - end - end - - def revision=(desired) - at_path do - cvs('update', '-r', desired, '.') - end - end - - private - - def tag_file - File.join(@resource.value(:path), 'CVS', 'Tag') - end - - def checkout_repository - dirname, basename = File.split(@resource.value(:path)) - Dir.chdir(dirname) do - args = ['-d', @resource.value(:source)] - if @resource.value(:compression) - args.push('-z', @resource.value(:compression)) - end - args.push('checkout', '-d', basename, module_name) - cvs(*args) - end - if @resource.value(:revision) - self.revision = @resource.value(:revision) - end - end - - # When the source: - # * Starts with ':' (eg, :pserver:...) - def module_name - if (source = @resource.value(:source)) - source[0, 1] == ':' ? File.basename(source) : '.' - end - end - - def create_repository(path) - cvs('-d', path, 'init') - end - -end diff --git a/lib/puppet/provider/vcsrepo/git.rb b/lib/puppet/provider/vcsrepo/git.rb deleted file mode 100644 index fa7e492cf..000000000 --- a/lib/puppet/provider/vcsrepo/git.rb +++ /dev/null @@ -1,264 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', 'vcsrepo') - -Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo) do - desc "Supports Git repositories" - - ##TODO modify the commands below so that the su - is included - commands :git => 'git' - defaultfor :git => :exists - has_features :bare_repositories, :reference_tracking - - def create - if !@resource.value(:source) - init_repository(@resource.value(:path)) - else - clone_repository(@resource.value(:source), @resource.value(:path)) - if @resource.value(:revision) - if @resource.value(:ensure) == :bare - notice "Ignoring revision for bare repository" - else - checkout_or_reset - end - end - if @resource.value(:ensure) != :bare - update_submodules - end - end - update_owner_and_excludes - end - - def destroy - FileUtils.rm_rf(@resource.value(:path)) - end - - def latest? - at_path do - return self.revision == self.latest - end - end - - def latest - branch = on_branch? - if branch == 'master' - return get_revision('origin/HEAD') - else - return get_revision('origin/%s' % branch) - end - end - - def revision - update_references - current = at_path { git('rev-parse', 'HEAD') } - canonical = at_path { git('rev-parse', @resource.value(:revision)) } - if current == canonical - @resource.value(:revision) - else - current - end - end - - def revision=(desired) - checkout_or_reset(desired) - if local_branch_revision?(desired) - # reset instead of pull to avoid merge conflicts. assuming remote is - # authoritative. - # might be worthwhile to have an allow_local_changes param to decide - # whether to reset or pull when we're ensuring latest. - at_path { git('reset', '--hard', "origin/#{desired}") } - end - if @resource.value(:ensure) != :bare - update_submodules - end - update_owner_and_excludes - end - - 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 exists? - working_copy_exists? || bare_exists? - end - - def update_references - at_path do - git('fetch', '--tags', 'origin') - end - end - - private - - def bare_git_config_exists? - File.exist?(File.join(@resource.value(:path), 'config')) - end - - def clone_repository(source, path) - check_force - args = ['clone'] - if @resource.value(:ensure) == :bare - args << '--bare' - end - if !File.exist?(File.join(@resource.value(:path), '.git')) - args.push(source, path) - git(*args) - else - notice "Repo has already been cloned" - end - end - - def check_force - if path_exists? - if @resource.value(:force) - notice "Removing %s to replace with vcsrepo." % @resource.value(:path) - destroy - else - raise Puppet::Error, "Could not create repository (non-repository at path)" - end - end - end - - def init_repository(path) - check_force - 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 - else - # normal init - FileUtils.mkdir(@resource.value(:path)) - args = ['init'] - if @resource.value(:ensure) == :bare - args << '--bare' - end - at_path do - git(*args) - end - end - end - - # Convert working copy to bare - # - # Moves: - # /.git - # to: - # / - def convert_working_copy_to_bare - notice "Converting working copy repository to bare repository" - FileUtils.mv(File.join(@resource.value(:path), '.git'), tempdir) - FileUtils.rm_rf(@resource.value(:path)) - FileUtils.mv(tempdir, @resource.value(:path)) - end - - # Convert bare to working copy - # - # Moves: - # / - # to: - # /.git - def convert_bare_to_working_copy - notice "Converting bare repository to working copy repository" - FileUtils.mv(@resource.value(:path), tempdir) - FileUtils.mkdir(@resource.value(:path)) - FileUtils.mv(tempdir, File.join(@resource.value(:path), '.git')) - if commits_in?(File.join(@resource.value(:path), '.git')) - reset('HEAD') - git('checkout', '-f') - update_owner_and_excludes - end - end - - def commits_in?(dot_git) - Dir.glob(File.join(dot_git, 'objects/info/*'), File::FNM_DOTMATCH) do |e| - return true unless %w(. ..).include?(File::basename(e)) - end - false - end - - def checkout_or_reset(revision = @resource.value(:revision)) - if local_branch_revision? - reset(revision) - elsif tag_revision? - at_path { git('checkout', '-b', revision) } - elsif remote_branch_revision? - at_path { git('checkout', '-b', revision, '--track', "origin/#{revision}") } - end - end - - def reset(desired) - at_path do - git('reset', '--hard', desired) - end - end - - def update_submodules - at_path do - git('submodule', 'init') - git('submodule', 'update') - git('submodule', 'foreach', 'git', 'submodule', 'init') - git('submodule', 'foreach', 'git', 'submodule', 'update') - end - end - - def remote_branch_revision?(revision = @resource.value(:revision)) - # git < 1.6 returns 'origin/#{revision}' - # git 1.6+ returns 'remotes/origin/#{revision}' - at_path { branches.grep /(remotes\/)?origin\/#{revision}/ } - end - - def local_branch_revision?(revision = @resource.value(:revision)) - at_path { branches.include?(revision) } - end - - def tag_revision?(revision = @resource.value(:revision)) - at_path { tags.include?(revision) } - end - - def branches - at_path { git('branch', '-a') }.gsub('*', ' ').split(/\n/).map { |line| line.strip } - end - - def on_branch? - at_path { git('branch', '-a') }.split(/\n/).grep(/\*/).to_s.gsub('*', '').strip - end - - def tags - at_path { git('tag', '-l') }.split(/\n/).map { |line| line.strip } - end - - def set_excludes - at_path { open('.git/info/exclude', 'w') { |f| @resource.value(:excludes).each { |ex| f.write(ex + "\n") }}} - end - - def get_revision(rev) - if !working_copy_exists? - create - end - at_path do - git('fetch', 'origin') - git('fetch', '--tags', 'origin') - end - current = at_path { git('rev-parse', rev).strip } - if @resource.value(:revision) - if local_branch_revision? - canonical = at_path { git('rev-parse', @resource.value(:revision)).strip } - elsif remote_branch_revision? - canonical = at_path { git('rev-parse', 'origin/' + @resource.value(:revision)).strip } - end - current = @resource.value(:revision) if current == canonical - end - return current - end - - def update_owner_and_excludes - if @resource.value(:owner) or @resource.value(:group) - set_ownership - end - if @resource.value(:excludes) - set_excludes - end - end -end diff --git a/lib/puppet/provider/vcsrepo/hg.rb b/lib/puppet/provider/vcsrepo/hg.rb deleted file mode 100644 index f96758612..000000000 --- a/lib/puppet/provider/vcsrepo/hg.rb +++ /dev/null @@ -1,101 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', 'vcsrepo') - -Puppet::Type.type(:vcsrepo).provide(:hg, :parent => Puppet::Provider::Vcsrepo) do - desc "Supports Mercurial repositories" - - commands :hg => 'hg' - defaultfor :hg => :exists - has_features :reference_tracking - - def create - if !@resource.value(:source) - create_repository(@resource.value(:path)) - else - clone_repository(@resource.value(:revision)) - end - update_owner - end - - def working_copy_exists? - File.directory?(File.join(@resource.value(:path), '.hg')) - end - - def exists? - working_copy_exists? - end - - def destroy - FileUtils.rm_rf(@resource.value(:path)) - end - - def latest? - at_path do - return self.revision == self.latest - end - end - - def latest - at_path do - begin - hg('incoming', '--branch', '.', '--newest-first', '--limit', '1')[/^changeset:\s+(?:-?\d+):(\S+)/m, 1] - rescue Puppet::ExecutionFailure - # If there are no new changesets, return the current nodeid - self.revision - end - end - end - - def revision - at_path do - current = hg('parents')[/^changeset:\s+(?:-?\d+):(\S+)/m, 1] - desired = @resource.value(:revision) - if desired - # Return the tag name if it maps to the current nodeid - mapped = hg('tags')[/^#{Regexp.quote(desired)}\s+\d+:(\S+)/m, 1] - if current == mapped - desired - else - current - end - else - current - end - end - end - - def revision=(desired) - at_path do - hg('pull') - begin - hg('merge') - rescue Puppet::ExecutionFailure - # If there's nothing to merge, just skip - end - hg('update', '--clean', '-r', desired) - end - update_owner - end - - private - - def create_repository(path) - hg('init', path) - end - - def clone_repository(revision) - args = ['clone'] - if revision - args.push('-u', revision) - end - args.push(@resource.value(:source), - @resource.value(:path)) - hg(*args) - end - - def update_owner - if @resource.value(:owner) or @resource.value(:group) - set_ownership - end - end - -end diff --git a/lib/puppet/provider/vcsrepo/svn.rb b/lib/puppet/provider/vcsrepo/svn.rb deleted file mode 100644 index 680188c1e..000000000 --- a/lib/puppet/provider/vcsrepo/svn.rb +++ /dev/null @@ -1,82 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', 'vcsrepo') - -Puppet::Type.type(:vcsrepo).provide(:svn, :parent => Puppet::Provider::Vcsrepo) do - desc "Supports Subversion repositories" - - commands :svn => 'svn', - :svnadmin => 'svnadmin' - - defaultfor :svn => :exists - has_features :filesystem_types, :reference_tracking - - def create - if !@resource.value(:source) - create_repository(@resource.value(:path)) - else - checkout_repository(@resource.value(:source), - @resource.value(:path), - @resource.value(:revision)) - end - end - - def working_copy_exists? - File.directory?(File.join(@resource.value(:path), '.svn')) - end - - def exists? - working_copy_exists? - end - - def destroy - FileUtils.rm_rf(@resource.value(:path)) - end - - def latest? - at_path do - if self.revision < self.latest then - return false - else - return true - end - end - end - - def latest - at_path do - svn('info', '-r', 'HEAD')[/^Revision:\s+(\d+)/m, 1] - end - end - - def revision - at_path do - svn('info')[/^Revision:\s+(\d+)/m, 1] - end - end - - def revision=(desired) - at_path do - svn('update', '-r', desired) - end - end - - private - - def checkout_repository(source, path, revision = nil) - args = ['checkout'] - if revision - args.push('-r', revision) - end - args.push(source, path) - svn(*args) - end - - def create_repository(path) - args = ['create'] - if @resource.value(:fstype) - args.push('--fs-type', @resource.value(:fstype)) - end - args << path - svnadmin(*args) - end - -end diff --git a/lib/puppet/type/vcsrepo.rb b/lib/puppet/type/vcsrepo.rb deleted file mode 100644 index f0d2613ca..000000000 --- a/lib/puppet/type/vcsrepo.rb +++ /dev/null @@ -1,138 +0,0 @@ -require 'pathname' - -Puppet::Type.newtype(:vcsrepo) do - desc "A local version control repository" - - feature :gzip_compression, - "The provider supports explicit GZip compression levels" - - feature :bare_repositories, - "The provider differentiates between bare repositories - and those with working copies", - :methods => [:bare_exists?, :working_copy_exists?] - - feature :filesystem_types, - "The provider supports different filesystem types" - - feature :reference_tracking, - "The provider supports tracking revision references that can change - over time (eg, some VCS tags and branch names)" - - ensurable do - attr_accessor :latest - - def insync?(is) - @should ||= [] - - case should - when :present - return true unless [:absent, :purged, :held].include?(is) - when :latest - if is == :latest - return true - else - self.debug "%s repo revision is %s, latest is %s" % - [@resource.name, provider.revision, provider.latest] - return false - end - end - end - - newvalue :present do - provider.create - end - - newvalue :bare, :required_features => [:bare_repositories] do - provider.create - end - - newvalue :absent do - provider.destroy - end - - newvalue :latest, :required_features => [:reference_tracking] do - if provider.exists? - if provider.respond_to?(:update_references) - provider.update_references - end - if provider.respond_to?(:latest?) - reference = provider.latest || provider.revision - else - reference = resource.value(:revision) || provider.revision - end - notice "Updating to latest '#{reference}' revision" - provider.revision = reference - else - provider.create - end - end - - def retrieve - prov = @resource.provider - if prov - if prov.working_copy_exists? - prov.latest? ? :latest : :present - elsif prov.class.feature?(:bare_repositories) and prov.bare_exists? - :bare - else - :absent - end - else - raise Puppet::Error, "Could not find provider" - end - end - - end - - newparam(:path) do - desc "Absolute path to repository" - isnamevar - validate do |value| - path = Pathname.new(value) - unless path.absolute? - raise ArgumentError, "Path must be absolute: #{path}" - end - end - end - - newparam(:source) do - desc "The source URI for the repository" - end - - newparam(:fstype, :required_features => [:filesystem_types]) do - desc "Filesystem type" - end - - newproperty(:revision) do - desc "The revision of the repository" - newvalue(/^\S+$/) - end - - newparam(:owner) do - desc "The user/uid that owns the repository files" - end - - newparam(:group) do - desc "The group/gid that owns the repository files" - end - - newparam(:excludes) do - desc "Files to be excluded from the repository" - end - - newparam(:force) do - desc "Force repository creation, destroying any files on the path in the process." - newvalues(:true, :false) - defaultto false - end - - newparam :compression, :required_features => [:gzip_compression] do - desc "Compression level" - validate do |amount| - unless Integer(amount).between?(0, 6) - raise ArgumentError, "Unsupported compression level: #{amount} (expected 0-6)" - end - end - end - -end