Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a mode parameter to manage repository root directory permission #599

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org).

## UNRELEASED

### Added

- support for directory modes for repos [\#599](https://github.com/puppetlabs/puppetlabs-vcsrepo/issues/599) ([robbat2](https://github.com/robbat2))

## [v6.1.0](https://github.com/puppetlabs/puppetlabs-vcsrepo/tree/v6.1.0) - 2023-06-13

[Full Changelog](https://github.com/puppetlabs/puppetlabs-vcsrepo/compare/v6.0.1...v6.1.0)
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -797,37 +797,37 @@ For information on the classes and types, see the [REFERENCE.md](https://github.

Features: `bare_repositories`, `depth`, `multiple_remotes`, `reference_tracking`, `ssh_identity`, `submodules`, `user`

Parameters: `depth`, `ensure`, `excludes`, `force`, `group`, `identity`, `owner`, `path`, `provider`, `remote`, `revision`, `source`, `user`
Parameters: `depth`, `ensure`, `excludes`, `force`, `group`, `identity`, `owner`, `path`, `provider`, `remote`, `revision`, `source`, `user`, `mode`

##### `bzr` - Supports the Bazaar VCS.

Features: `reference_tracking`

Parameters: `ensure`, `excludes`, `force`, `group`, `owner`, `path`, `provider`, `revision`, `source`
Parameters: `ensure`, `excludes`, `force`, `group`, `owner`, `path`, `provider`, `revision`, `source`, `mode`

##### `cvs` - Supports the CVS VCS.

Features: `cvs_rsh`, `gzip_compression`, `modules`, `reference_tracking`, `user`

Parameters: `compression`, `cvs_rsh`, `ensure`, `excludes`, `force`, `group`, `module`, `owner`, `path`, `provider`
Parameters: `compression`, `cvs_rsh`, `ensure`, `excludes`, `force`, `group`, `module`, `owner`, `path`, `provider`, `mode`

##### `hg` - Supports the Mercurial VCS.

Features: `reference_tracking`, `ssh_identity`, `user`

Parameters: `ensure`, `excludes`, `force`, `group`, `identity`, `owner`, `path`, `provider`, `revision`, `source`, `user`
Parameters: `ensure`, `excludes`, `force`, `group`, `identity`, `owner`, `path`, `provider`, `revision`, `source`, `user`, `mode`

##### `p4` - Supports the Perforce VCS.

Features: `p4config`, `reference_tracking`

Parameters: `ensure`, `excludes`, `force`, `group`, `owner`, `p4config`, `path`, `provider`, `revision`, `source`
Parameters: `ensure`, `excludes`, `force`, `group`, `owner`, `p4config`, `path`, `provider`, `revision`, `source`, `mode`

##### `svn` - Supports the Subversion VCS.

Features: `basic_auth`, `configuration`, `conflict`, `depth`, `filesystem_types`, `reference_tracking`

Parameters: `basic_auth_password`, `basic_auth_username`, `configuration`, `conflict`, `ensure`, `excludes`, `force`, `fstype`, `group`, `includes`, `owner`, `path`, `provider`, `revision`, `source`, `trust_server_cert`
Parameters: `basic_auth_password`, `basic_auth_username`, `configuration`, `conflict`, `ensure`, `excludes`, `force`, `fstype`, `group`, `includes`, `owner`, `path`, `provider`, `revision`, `source`, `trust_server_cert`, `mode`

<a id="features"></a>
#### Features
Expand Down
4 changes: 4 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ The following parameters are available in the `vcsrepo` type.
* [`trust_server_cert`](#trust_server_cert)
* [`umask`](#umask)
* [`user`](#user)
* [`mode`](#mode)

##### <a name="basic_auth_password"></a>`basic_auth_password`

Expand Down Expand Up @@ -280,3 +281,6 @@ Sets the umask to be used for all repo operations

The user to run for repository operations

##### <a name="mode"></a>`mode`

Sets the mode for the repository directory (non-recursive).
16 changes: 16 additions & 0 deletions lib/puppet/provider/vcsrepo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,25 @@ def check_force

private

def set_ownership_and_permissions
set_ownership
set_permissions
end

def set_ownership
mode = @resource.value(:mode) || nil
# Change the permission on the repo itself.
# The VCS should maintain permissions on files within the checkout.
FileUtils.chmod(mode, @resource.value(:path)) unless mode.nil?
end

def set_permissions
owner = @resource.value(:owner) || nil
group = @resource.value(:group) || nil
excludes = @resource.value(:excludes) || nil
# We might have no work to do, and this makes it easier for the callers.
return if owner.nil? && group.nil?

if excludes.nil? || excludes.empty?
FileUtils.chown_R(owner, group, @resource.value(:path))
else
Expand All @@ -28,6 +43,7 @@ def set_ownership
end

def files
# Expensive on large repos
excludes = @resource.value(:excludes)
path = @resource.value(:path)
Dir["#{path}/**/*"].reject { |f| excludes.any? { |p| f.start_with?("#{path}/#{p}") } }
Expand Down
2 changes: 1 addition & 1 deletion lib/puppet/provider/vcsrepo/bzr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,6 @@ def clone_repository(revision)
end

def update_owner
set_ownership if @resource.value(:owner) || @resource.value(:group)
set_ownership_and_permissions
end
end
2 changes: 1 addition & 1 deletion lib/puppet/provider/vcsrepo/cvs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def create_repository(path)
end

def update_owner
set_ownership if @resource.value(:owner) || @resource.value(:group)
set_ownership_and_permissions
end

def runcvs(*args)
Expand Down
19 changes: 12 additions & 7 deletions lib/puppet/provider/vcsrepo/git.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def create
init_repository
self.skip_hooks = @resource.value(:skip_hooks) unless @resource.value(:skip_hooks).nil?
end
update_owner_and_excludes
update_owner_permission_and_excludes
end

def destroy
Expand Down Expand Up @@ -88,7 +88,7 @@ def revision=(desired)
end
# TODO: Would this ever reach here if it is bare?
update_submodules if !ensure_bare_or_mirror? && @resource.value(:submodules) == :true
update_owner_and_excludes
update_owner_permission_and_excludes
end

def bare_exists?
Expand Down Expand Up @@ -228,7 +228,7 @@ def update_references
at_path do
git_remote_action('fetch', @resource.value(:remote))
git_remote_action(*fetch_tags_args, @resource.value(:remote))
update_owner_and_excludes
update_owner_permission_and_excludes
end
end

Expand All @@ -246,6 +246,8 @@ def convert_working_copy_to_bare
FileUtils.mv(File.join(@resource.value(:path), '.git'), tempdir)
FileUtils.rm_rf(@resource.value(:path))
FileUtils.mv(tempdir, @resource.value(:path))
FileUtils.chown(@resource.value(:user), @resource.value(:group), @resource.value(:path)) if @resource.value(:user) || @resource.value(:group)
FileUtils.chmod(@resource.value(:mode), @resource.value(:path)) if @resource.value(:mode)
at_path do
exec_git('config', '--local', '--bool', 'core.bare', 'true')
return unless @resource.value(:ensure) == :mirror
Expand All @@ -266,13 +268,15 @@ 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.chown(@resource.value(:user), @resource.value(:group), @resource.value(:path)) if @resource.value(:user) || @resource.value(:group)
FileUtils.chmod(@resource.value(:mode), @resource.value(:path)) if @resource.value(:mode)
FileUtils.mv(tempdir, File.join(@resource.value(:path), '.git'))
if commits?
at_path do
exec_git('config', '--local', '--bool', 'core.bare', 'false')
reset('HEAD')
git_with_identity('checkout', '--force')
update_owner_and_excludes
update_owner_permission_and_excludes
end
end
set_no_mirror if mirror?
Expand Down Expand Up @@ -398,7 +402,8 @@ def init_repository
else
# normal init
FileUtils.mkdir(@resource.value(:path))
FileUtils.chown(@resource.value(:user), nil, @resource.value(:path)) if @resource.value(:user)
FileUtils.chown(@resource.value(:user), @resource.value(:group), @resource.value(:path)) if @resource.value(:user) || @resource.value(:group)
FileUtils.chmod(@resource.value(:mode), @resource.value(:path)) if @resource.value(:mode)
args = ['init']
args << '--bare' if @resource.value(:ensure) == :bare
at_path do
Expand Down Expand Up @@ -580,8 +585,8 @@ def get_revision(rev = 'HEAD')
end

# @!visibility private
def update_owner_and_excludes
set_ownership if @resource.value(:owner) || @resource.value(:group)
def update_owner_permission_and_excludes
set_ownership_and_permissions
set_excludes if @resource.value(:excludes)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/puppet/provider/vcsrepo/hg.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def clone_repository(revision)
end

def update_owner
set_ownership if @resource.value(:owner) || @resource.value(:group)
set_ownership_and_permissions
end

def sensitive?
Expand Down
2 changes: 1 addition & 1 deletion lib/puppet/provider/vcsrepo/p4.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def source=(_desired)
private

def update_owner
set_ownership if @resource.value(:owner) || @resource.value(:group)
set_ownership_and_permissions
end

# Sync the client workspace files to head or specified revision.
Expand Down
2 changes: 1 addition & 1 deletion lib/puppet/provider/vcsrepo/svn.rb
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def create_repository(path)
end

def update_owner
set_ownership if @resource.value(:owner) || @resource.value(:group)
set_ownership_and_permissions
end

def update_includes(paths)
Expand Down
4 changes: 4 additions & 0 deletions lib/puppet/type/vcsrepo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ def insync?(is)
desc 'The group/gid that owns the repository files'
end

newparam :mode do
desc 'The permission for the repository directory itself (not recursive)'
end

newparam :user do
desc 'The user to run for repository operations'
end
Expand Down
21 changes: 21 additions & 0 deletions spec/acceptance/clone_repo_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -636,4 +636,25 @@
it { is_expected.to be_mode '664' }
end
end

context 'with mode' do
pp = <<-MANIFEST
vcsrepo { "#{tmpdir}/testrepo_mode":
ensure => present,
provider => git,
source => "file://#{tmpdir}/testrepo.git",
mode => 'u=rwX,g=rX,o=X',
}
MANIFEST
it 'clones a repo' do
# Run it twice and test for idempotency
idempotent_apply(pp)
end

describe file("#{tmpdir}/testrepo_mode") do
# NOTE: '0664' is not supported by 'be_mode'; this must be three digits
# unless the first octet is non-zero.
it { is_expected.to be_mode '751' }
end
end
end
4 changes: 2 additions & 2 deletions spec/unit/puppet/provider/vcsrepo/git_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ def branch_a_list(include_branch = nil?)
.with('config', '--local', '--bool', 'core.bare', 'false').and_return(true)
expect(provider).to receive(:reset).with('HEAD').and_return(true)
expect(provider).to receive(:git_with_identity).with('checkout', '--force').and_return(true)
expect(provider).to receive(:update_owner_and_excludes).and_return(true)
expect(provider).to receive(:update_owner_permission_and_excludes).and_return(true)
expect(provider).to receive(:mirror?).and_return(false)
provider.instance_eval { convert_bare_to_working_copy }
end
Expand All @@ -330,7 +330,7 @@ def branch_a_list(include_branch = nil?)
.with('config', '--local', '--bool', 'core.bare', 'false').and_return(true)
expect(provider).to receive(:reset).with('HEAD').and_return(true)
expect(provider).to receive(:git_with_identity).with('checkout', '--force').and_return(true)
expect(provider).to receive(:update_owner_and_excludes).and_return(true)
expect(provider).to receive(:update_owner_permission_and_excludes).and_return(true)
expect(provider).to receive(:exec_git).with('config', '--unset', 'remote.origin.mirror')
expect(provider).to receive(:mirror?).and_return(true)
provider.instance_eval { convert_bare_to_working_copy }
Expand Down