Skip to content

Commit

Permalink
Merge pull request #88 from DavidS/add-v
Browse files Browse the repository at this point in the history
Add -x to skip specified repositories
  • Loading branch information
bastelfreak committed Nov 23, 2016
2 parents 80b56b0 + 1a83083 commit 7968d70
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 58 deletions.
2 changes: 2 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--color
--format=documentation
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,22 @@ pre_commit_script: openstack-commit-msg-hook.sh

#### Filtering Repositories

If you only want to sync some of the repositories in your managed_modules.yml, use the -f flag to filter by a regex:
If you only want to sync some of the repositories in your managed_modules.yml, use the `-f` flag to filter by a regex:

```
msync update -f augeas -m "Commit message"
msync update -f augeas -m "Commit message" # acts only on the augeas module
msync update -f puppet-a..o "Commit message"
```

If you want to skip syncing some of the repositories in your managed_modules.yml, use the `-x` flag to filter by a regex:

```
msync update -x augeas -m "Commit message" # acts on all modules except the augeas module
msync update -x puppet-a..o "Commit message"
```

If no `-f` is specified, all repository are processed, if no `-x` is specified no repository is skipped. If a repository matches both `-f` and `-x` it is skipped.

#### Pushing to a different remote branch

If you want to push the modified branch to a different remote branch, you can use the -r flag:
Expand Down
9 changes: 8 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ require 'rake/clean'
require 'cucumber/rake/task'
require 'rubocop/rake_task'

begin
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
rescue LoadError
puts 'rspec not installed - skipping unit test task setup'
end

RuboCop::RakeTask.new

CLEAN.include('pkg/', 'tmp/')
Expand All @@ -11,4 +18,4 @@ Cucumber::Rake::Task.new do |t|
t.cucumber_opts << '--format pretty'
end

task :test => [:clean, :cucumber, :rubocop]
task :test => [:clean, :spec, :cucumber, :rubocop]
36 changes: 36 additions & 0 deletions features/update.feature
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,42 @@ Feature: update
Then the output should contain "aruba"
And a directory named "modules/puppet-blacksmith" should not exist

Scenario: When specifying configurations in managed_modules.yml and using a negative filter
Given a file named "managed_modules.yml" with:
"""
---
puppet-blacksmith:
puppet-test:
module_name: test
"""
And a file named "modulesync.yml" with:
"""
---
namespace: maestrodev
git_base: https://github.com/
"""
And a file named "config_defaults.yml" with:
"""
---
test:
name: aruba
"""
And a directory named "moduleroot"
And a file named "moduleroot/test" with:
"""
<%= @configs['name'] %>
"""
When I run `msync update --noop -x puppet-blacksmith`
Then the exit status should be 0
And the output should match:
"""
Files added:\s+
test
"""
Given I run `cat modules/puppet-test/test`
Then the output should contain "aruba"
And a directory named "modules/puppet-blacksmith" should not exist

Scenario: Updating a module with a .sync.yml file
Given a file named "managed_modules.yml" with:
"""
Expand Down
73 changes: 34 additions & 39 deletions lib/modulesync.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require 'modulesync/git'
require 'modulesync/hook'
require 'modulesync/renderer'
require 'modulesync/settings'
require 'modulesync/util'

module ModuleSync
Expand Down Expand Up @@ -40,13 +41,14 @@ def self.module_files(local_files, path)
local_files.map { |file| file.sub(/#{path}/, '') }
end

def self.managed_modules(path, filter)
def self.managed_modules(path, filter, negative_filter)
managed_modules = Util.parse_config(path)
if managed_modules.empty?
puts "No modules found at #{path}. Check that you specified the right configs directory containing managed_modules.yml."
exit
end
managed_modules.select! { |m| m =~ Regexp.new(filter) } unless filter.nil?
managed_modules.select! { |m| m !~ Regexp.new(negative_filter) } unless negative_filter.nil?
managed_modules
end

Expand All @@ -66,16 +68,22 @@ def self.hook(options)
end
end

def self.module_configs(filename, global_defaults, defaults, module_defaults, module_configs)
global_defaults.merge(defaults[filename] || {}).merge(module_defaults).merge(module_configs[filename] || {})
end

def self.unmanaged?(filename, global_defaults, defaults, module_defaults, module_configs)
Pathname.new(filename).ascend do |v|
configs = module_configs(v.to_s, global_defaults, defaults, module_defaults, module_configs)
return true if configs['unmanaged']
def self.manage_file(filename, settings, options)
module_name = settings.additional_settings[:puppet_module]
configs = settings.build_file_configs(filename)
if configs['delete']
Renderer.remove(module_file(options['project_root'], module_name, filename))
else
templatename = local_file(options[:configs], filename)
begin
erb = Renderer.build(templatename)
template = Renderer.render(erb, configs)
Renderer.sync(template, "#{options[:project_root]}/#{module_name}/#{filename}")
rescue
STDERR.puts "Error while rendering #{filename}"
raise
end
end
false
end

def self.update(options)
Expand All @@ -86,45 +94,32 @@ def self.update(options)
local_files = self.local_files(path)
module_files = self.module_files(local_files, path)

managed_modules = self.managed_modules("#{options[:configs]}/managed_modules.yml", options[:filter])
managed_modules = self.managed_modules("#{options[:configs]}/managed_modules.yml", options[:filter], options[:negative_filter])

# managed_modules is either an array or a hash
managed_modules.each do |puppet_module, opts|
managed_modules.each do |puppet_module, module_options|
puts "Syncing #{puppet_module}"
namespace, module_name = self.module_name(puppet_module, options[:namespace])
unless options[:offline]
git_base = options[:git_base]
git_uri = "#{git_base}#{namespace}"
Git.pull(git_uri, module_name, options[:branch], options[:project_root], opts || {})
Git.pull(git_uri, module_name, options[:branch], options[:project_root], module_options || {})
end
module_configs = Util.parse_config("#{options[:project_root]}/#{module_name}/#{MODULE_CONF_FILE}")
global_defaults = defaults[GLOBAL_DEFAULTS_KEY] || {}
module_defaults = module_configs[GLOBAL_DEFAULTS_KEY] || {}
files_to_manage = (module_files | defaults.keys | module_configs.keys) - [GLOBAL_DEFAULTS_KEY]
unmanaged_files = []
files_to_manage.each do |filename|
configs = module_configs(filename, global_defaults, defaults, module_defaults, module_configs)
configs[:puppet_module] = module_name
configs[:git_base] = git_base
configs[:namespace] = namespace
if unmanaged?(filename, global_defaults, defaults, module_defaults, module_configs)
puts "Not managing #{filename} in #{module_name}"
unmanaged_files << filename
elsif configs['delete']
Renderer.remove(module_file(options['project_root'], module_name, filename))
else
templatename = local_file(options[:configs], filename)
begin
erb = Renderer.build(templatename)
template = Renderer.render(erb, configs)
Renderer.sync(template, "#{options[:project_root]}/#{module_name}/#{filename}")
rescue
STDERR.puts "Error while rendering #{filename}"
raise
end
end
settings = Settings.new(defaults[GLOBAL_DEFAULTS_KEY] || {},
defaults,
module_configs[GLOBAL_DEFAULTS_KEY] || {},
module_configs,
:puppet_module => module_name,
:git_base => git_base,
:namespace => namespace)
settings.unmanaged_files(module_files).each do |filename|
puts "Not managing #{filename} in #{module_name}"
end
files_to_manage -= unmanaged_files

files_to_manage = settings.managed_files(module_files)
files_to_manage.each { |filename| manage_file(filename, settings, options) }

if options[:noop]
Git.update_noop(module_name, options)
elsif !options[:offline]
Expand Down
3 changes: 2 additions & 1 deletion lib/modulesync/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class Base < Thor
class_option :project_root, :aliases => '-c', :desc => 'Path used by git to clone modules into. Defaults to "modules"', :default => 'modules'
class_option :git_base, :desc => 'Specify the base part of a git URL to pull from', :default => 'git@github.com:'
class_option :namespace, :aliases => '-n', :desc => 'Remote github namespace (user or organization) to clone from and push to. Defaults to puppetlabs', :default => 'puppetlabs'
class_option :filter, :aliases => '-f', :desc => 'A regular expression to filter repositories to update.'
class_option :filter, :aliases => '-f', :desc => 'A regular expression to select repositories to update.'
class_option :negative_filter, :aliases => '-x', :desc => 'A regular expression to skip repositories.'
class_option :branch, :aliases => '-b', :desc => 'Branch name to make the changes in. Defaults to master.', :default => 'master'

desc 'update', 'Update the modules in managed_modules.yml'
Expand Down
26 changes: 13 additions & 13 deletions lib/modulesync/git.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ def self.local_branch_exists?(repo, branch)
end

def self.switch_branch(repo, branch)
unless repo.branch.name == branch
if local_branch_exists?(repo, branch)
puts "Switching to branch #{branch}"
repo.checkout(branch)
elsif remote_branch_exists?(repo, branch)
puts "Creating local branch #{branch} from origin/#{branch}"
repo.checkout("origin/#{branch}")
repo.branch(branch).checkout
else
repo.checkout('origin/master')
puts "Creating new branch #{branch}"
repo.branch(branch).checkout
end
return if repo.branch.name == branch

if local_branch_exists?(repo, branch)
puts "Switching to branch #{branch}"
repo.checkout(branch)
elsif remote_branch_exists?(repo, branch)
puts "Creating local branch #{branch} from origin/#{branch}"
repo.checkout("origin/#{branch}")
repo.branch(branch).checkout
else
repo.checkout('origin/master')
puts "Creating new branch #{branch}"
repo.branch(branch).checkout
end
end

Expand Down
41 changes: 41 additions & 0 deletions lib/modulesync/settings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

module ModuleSync
# Encapsulate a configs for a module, providing easy access to its parts
class Settings
attr_reader :global_defaults, :defaults, :module_defaults, :module_configs, :additional_settings

def initialize(global_defaults, defaults, module_defaults, module_configs, additional_settings)
@global_defaults = global_defaults
@defaults = defaults
@module_defaults = module_defaults
@module_configs = module_configs
@additional_settings = additional_settings
end

def build_file_configs(filename)
global_defaults.merge(defaults[filename] || {}).merge(module_defaults).merge(module_configs[filename] || {}).merge(additional_settings)
end

def managed?(filename)
Pathname.new(filename).ascend do |v|
configs = build_file_configs(v.to_s)
return false if configs['unmanaged']
end
true
end

# given a list of existing files in the repo, return everything that we might want to act on
def managed_files(file_list)
(file_list | defaults.keys | module_configs.keys).select do |f|
managed?(f) && (f != ModuleSync::GLOBAL_DEFAULTS_KEY)
end
end

# returns a list of files that should not be touched
def unmanaged_files(file_list)
(file_list | defaults.keys | module_configs.keys).select do |f|
!managed?(f) && (f != ModuleSync::GLOBAL_DEFAULTS_KEY)
end
end
end
end
5 changes: 3 additions & 2 deletions modulesync.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib']

spec.add_development_dependency 'aruba'
spec.add_development_dependency 'bundler', '~> 1.6'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'aruba'
spec.add_development_dependency 'rspec'
spec.add_development_dependency 'rubocop'

spec.add_runtime_dependency 'thor'
spec.add_runtime_dependency 'git', '~>1.2'
spec.add_runtime_dependency 'puppet-blacksmith', '~>3.0'
spec.add_runtime_dependency 'thor'
end
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require 'modulesync'
24 changes: 24 additions & 0 deletions spec/unit/modulesync/settings_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'spec_helper'

describe ModuleSync::Settings do
subject do
ModuleSync::Settings.new(
{},
{},
{},
{ 'Rakefile' => { 'unmanaged' => true },
'Gemfile' => { 'key' => 'value' }, },
{}
)
end

it { is_expected.not_to eq nil }
it { expect(subject.managed?('Rakefile')).to eq false }
it { expect(subject.managed?('Rakefile/foo')).to eq false }
it { expect(subject.managed?('Gemfile')).to eq true }
it { expect(subject.managed?('Gemfile/foo')).to eq true }
it { expect(subject.managed_files([])).to eq ['Gemfile'] }
it { expect(subject.managed_files(%w(Rakefile Gemfile other_file))).to eq %w(Gemfile other_file) }
it { expect(subject.unmanaged_files([])).to eq ['Rakefile'] }
it { expect(subject.unmanaged_files(%w(Rakefile Gemfile other_file))).to eq ['Rakefile'] }
end

0 comments on commit 7968d70

Please sign in to comment.