modulesync 0.6.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,14 +1,25 @@
1
1
  require 'fileutils'
2
+ require 'pathname'
2
3
  require 'modulesync/cli'
3
4
  require 'modulesync/constants'
4
5
  require 'modulesync/git'
5
6
  require 'modulesync/hook'
6
7
  require 'modulesync/renderer'
8
+ require 'modulesync/settings'
7
9
  require 'modulesync/util'
8
10
 
9
11
  module ModuleSync
10
12
  include Constants
11
13
 
14
+ def self.config_defaults
15
+ {
16
+ :project_root => 'modules/',
17
+ :managed_modules_conf => 'managed_modules.yml',
18
+ :configs => '.',
19
+ :tag_pattern => '%s'
20
+ }
21
+ end
22
+
12
23
  def self.local_file(config_path, file)
13
24
  "#{config_path}/#{MODULE_FILES_DIR}/#{file}"
14
25
  end
@@ -18,8 +29,8 @@ module ModuleSync
18
29
  end
19
30
 
20
31
  def self.local_files(path)
21
- if File.exists?(path)
22
- local_files = Find.find(path).collect { |file| file if !File.directory?(file) }.compact
32
+ if File.exist?(path)
33
+ local_files = Find.find(path).collect { |file| file unless File.directory?(file) }.compact
23
34
  else
24
35
  puts "#{path} does not exist. Check that you are working in your module configs directory or that you have passed in the correct directory with -c."
25
36
  exit
@@ -30,65 +41,100 @@ module ModuleSync
30
41
  local_files.map { |file| file.sub(/#{path}/, '') }
31
42
  end
32
43
 
33
- def self.managed_modules(path, filter)
44
+ def self.managed_modules(path, filter, negative_filter)
34
45
  managed_modules = Util.parse_config(path)
35
46
  if managed_modules.empty?
36
47
  puts "No modules found at #{path}. Check that you specified the right configs directory containing managed_modules.yml."
37
48
  exit
38
49
  end
39
50
  managed_modules.select! { |m| m =~ Regexp.new(filter) } unless filter.nil?
51
+ managed_modules.select! { |m| m !~ Regexp.new(negative_filter) } unless negative_filter.nil?
40
52
  managed_modules
41
53
  end
42
54
 
43
- def self.run(args)
44
- cli = CLI.new
45
- cli.parse_opts(args)
46
- options = cli.options
47
- if options[:command] == 'update'
48
- defaults = Util.parse_config("#{options[:configs]}/#{CONF_FILE}")
49
-
50
- path = "#{options[:configs]}/#{MODULE_FILES_DIR}"
51
- local_files = self.local_files(path)
52
- module_files = self.module_files(local_files, path)
53
-
54
- managed_modules = self.managed_modules("#{options[:configs]}/managed_modules.yml", options[:filter])
55
-
56
- # managed_modules is either an array or a hash
57
- managed_modules.each do |puppet_module, opts|
58
- puts "Syncing #{puppet_module}"
59
- unless options[:offline]
60
- git_base = "#{options[:git_base]}#{options[:namespace]}"
61
- Git.pull(git_base, puppet_module, options[:branch], options[:project_root], opts || {})
62
- end
63
- module_configs = Util.parse_config("#{options[:project_root]}/#{puppet_module}/#{MODULE_CONF_FILE}")
64
- global_defaults = defaults[GLOBAL_DEFAULTS_KEY] || {}
65
- module_defaults = module_configs[GLOBAL_DEFAULTS_KEY] || {}
66
- files_to_manage = (module_files | defaults.keys | module_configs.keys) - [GLOBAL_DEFAULTS_KEY]
67
- files_to_delete = []
68
- files_to_manage.each do |file|
69
- file_configs = global_defaults.merge(defaults[file] || {}).merge(module_defaults).merge(module_configs[file] || {})
70
- file_configs[:puppet_module] = puppet_module
71
- if file_configs['unmanaged']
72
- puts "Not managing #{file} in #{puppet_module}"
73
- files_to_delete << file
74
- elsif file_configs['delete']
75
- Renderer.remove(module_file(options['project_root'], puppet_module, file))
76
- else
77
- erb = Renderer.build(local_file(options[:configs], file))
78
- template = Renderer.render(erb, file_configs)
79
- Renderer.sync(template, "#{options[:project_root]}/#{puppet_module}/#{file}")
80
- end
81
- end
82
- files_to_manage -= files_to_delete
83
- if options[:noop]
84
- Git.update_noop(puppet_module, options)
85
- elsif not options[:offline]
86
- Git.update(puppet_module, files_to_manage, options)
87
- end
55
+ def self.module_name(module_name, default_namespace)
56
+ return [default_namespace, module_name] unless module_name.include?('/')
57
+ ns, mod = module_name.split('/')
58
+ end
59
+
60
+ def self.hook(options)
61
+ hook = Hook.new(HOOK_FILE, options)
62
+
63
+ case options[:hook]
64
+ when 'activate'
65
+ hook.activate
66
+ when 'deactivate'
67
+ hook.deactivate
68
+ end
69
+ end
70
+
71
+ def self.manage_file(filename, settings, options)
72
+ module_name = settings.additional_settings[:puppet_module]
73
+ configs = settings.build_file_configs(filename)
74
+ if configs['delete']
75
+ Renderer.remove(module_file(options[:project_root], module_name, filename))
76
+ else
77
+ templatename = local_file(options[:configs], filename)
78
+ begin
79
+ erb = Renderer.build(templatename)
80
+ template = Renderer.render(erb, configs)
81
+ Renderer.sync(template, module_file(options[:project_root], module_name, filename))
82
+ rescue
83
+ STDERR.puts "Error while rendering #{filename}"
84
+ raise
88
85
  end
89
- elsif options[:command] == 'hook'
90
- Hook.hook(args[1], options)
91
86
  end
92
87
  end
93
88
 
89
+ def self.manage_module(puppet_module, module_files, module_options, defaults, options)
90
+ puts "Syncing #{puppet_module}"
91
+ namespace, module_name = self.module_name(puppet_module, options[:namespace])
92
+ unless options[:offline]
93
+ git_base = options[:git_base]
94
+ git_uri = "#{git_base}#{namespace}"
95
+ Git.pull(git_uri, module_name, options[:branch], options[:project_root], module_options || {})
96
+ end
97
+ module_configs = Util.parse_config("#{options[:project_root]}/#{module_name}/#{MODULE_CONF_FILE}")
98
+ settings = Settings.new(defaults[GLOBAL_DEFAULTS_KEY] || {},
99
+ defaults,
100
+ module_configs[GLOBAL_DEFAULTS_KEY] || {},
101
+ module_configs,
102
+ :puppet_module => module_name,
103
+ :git_base => git_base,
104
+ :namespace => namespace)
105
+ settings.unmanaged_files(module_files).each do |filename|
106
+ puts "Not managing #{filename} in #{module_name}"
107
+ end
108
+
109
+ files_to_manage = settings.managed_files(module_files)
110
+ files_to_manage.each { |filename| manage_file(filename, settings, options) }
111
+
112
+ if options[:noop]
113
+ Git.update_noop(module_name, options)
114
+ elsif !options[:offline]
115
+ Git.update(module_name, files_to_manage, options)
116
+ end
117
+ end
118
+
119
+ def self.update(options)
120
+ options = config_defaults.merge(options)
121
+ defaults = Util.parse_config("#{options[:configs]}/#{CONF_FILE}")
122
+
123
+ path = "#{options[:configs]}/#{MODULE_FILES_DIR}"
124
+ local_files = self.local_files(path)
125
+ module_files = self.module_files(local_files, path)
126
+
127
+ managed_modules = self.managed_modules("#{options[:configs]}/managed_modules.yml", options[:filter], options[:negative_filter])
128
+
129
+ # managed_modules is either an array or a hash
130
+ managed_modules.each do |puppet_module, module_options|
131
+ begin
132
+ manage_module(puppet_module, module_files, module_options, defaults, options)
133
+ rescue
134
+ STDERR.puts "Error while updating #{puppet_module}"
135
+ raise unless options[:skip_broken]
136
+ puts "Skipping #{puppet_module} as update process failed"
137
+ end
138
+ end
139
+ end
94
140
  end
@@ -1,124 +1,64 @@
1
- require 'optparse'
1
+ require 'thor'
2
+ require 'modulesync'
2
3
  require 'modulesync/constants'
3
4
  require 'modulesync/util'
4
5
 
5
6
  module ModuleSync
6
7
  class CLI
7
- include Constants
8
+ class Hook < Thor
9
+ class_option :project_root, :aliases => '-c', :desc => 'Path used by git to clone modules into. Defaults to "modules"', :default => 'modules'
10
+ class_option :hook_args, :aliases => '-a', :desc => 'Arguments to pass to msync in the git hook'
8
11
 
9
- def defaults
10
- {
11
- :namespace => 'puppetlabs',
12
- :branch => 'master',
13
- :git_base => 'git@github.com:',
14
- :managed_modules_conf => 'managed_modules.yml',
15
- :configs => '.',
16
- :tag_pattern => '%s',
17
- :project_root => './modules',
18
- }
19
- end
12
+ desc 'activate', 'Activate the git hook.'
13
+ def activate
14
+ config = { :command => 'hook' }.merge(options)
15
+ config[:hook] = 'activate'
16
+ ModuleSync.hook(config)
17
+ end
20
18
 
21
- def commands_available
22
- [
23
- 'update',
24
- 'hook',
25
- ]
19
+ desc 'deactivate', 'Deactivate the git hook.'
20
+ def deactivate
21
+ config = { :command => 'hook' }.merge(options)
22
+ config[:hook] = 'deactivate'
23
+ ModuleSync.hook(config)
24
+ end
26
25
  end
27
26
 
28
- def fail(message)
29
- puts @options[:help]
30
- puts message
31
- exit
32
- end
27
+ class Base < Thor
28
+ include Constants
33
29
 
34
- def parse_opts(args)
35
- @options = defaults
36
- @options.merge!(Hash.transform_keys_to_symbols(Util.parse_config(MODULESYNC_CONF_FILE)))
37
- @options[:command] = args[0] if commands_available.include?(args[0])
38
- opt_parser = OptionParser.new do |opts|
39
- opts.banner = "Usage: msync update [-m <commit message>] [-c <directory> ] [--offline] [--noop] [--bump] [--changelog] [--tag] [--tag-pattern <tag_pattern>] [-p <project_root> [-n <namespace>] [-b <branch>] [-r <branch>] [-f <filter>] | hook activate|deactivate [-c <directory> ] [-n <namespace>] [-b <branch>]"
40
- opts.on('-m', '--message <msg>',
41
- 'Commit message to apply to updated modules') do |msg|
42
- @options[:message] = msg
43
- end
44
- opts.on('-n', '--namespace <url>',
45
- 'Remote github namespace (user or organization) to clone from and push to. Defaults to puppetlabs') do |namespace|
46
- @options[:namespace] = namespace
47
- end
48
- opts.on('-c', '--configs <directory>',
49
- 'The local directory or remote repository to define the list of managed modules, the file templates, and the default values for template variables.') do |configs|
50
- @options[:configs] = configs
51
- end
52
- opts.on('-b', '--branch <branch>',
53
- 'Branch name to make the changes in. Defaults to "master"') do |branch|
54
- @options[:branch] = branch
55
- end
56
- opts.on('-p', '--project-root <path>',
57
- 'Path used by git to clone modules into. Defaults to "modules"') do |project_root|
58
- @options[:project_root] = project_root
59
- end
60
- opts.on('-r', '--remote-branch <branch>',
61
- 'Remote branch name to push the changes to. Defaults to the branch name') do |branch|
62
- @options[:remote_branch] = branch
63
- end
64
- opts.on('-f', '--filter <filter>',
65
- 'A regular expression to filter repositories to update.') do |filter|
66
- @options[:filter] = filter
67
- end
68
- opts.on('--amend',
69
- 'Amend previous commit') do |msg|
70
- @options[:amend] = true
71
- end
72
- opts.on('--force',
73
- 'Force push amended commit') do |msg|
74
- @options[:force] = true
75
- end
76
- opts.on('--noop',
77
- 'No-op mode') do |msg|
78
- @options[:noop] = true
79
- end
80
- opts.on('--offline',
81
- 'Do not run git command. Helpful if you have existing repositories locally.') do |msg|
82
- @options[:offline] = true
83
- end
84
- opts.on('--bump',
85
- 'Bump module version to the next minor') do |msg|
86
- @options[:bump] = true
87
- end
88
- opts.on('--changelog',
89
- 'Update CHANGELOG.md if version was bumped') do |msg|
90
- @options[:changelog] = true
91
- end
92
- opts.on('--tag',
93
- 'Git tag with the current module version') do |msg|
94
- @options[:tag] = true
95
- end
96
- opts.on('--tag-pattern',
97
- 'The pattern to use when tagging releases.') do |pattern|
98
- @options[:tag_pattern] = pattern
99
- end
100
- @options[:help] = opts.help
101
- end.parse!
30
+ class_option :project_root, :aliases => '-c', :desc => 'Path used by git to clone modules into. Defaults to "modules"', :default => 'modules'
31
+ class_option :git_base, :desc => 'Specify the base part of a git URL to pull from', :default => 'git@github.com:'
32
+ class_option :namespace, :aliases => '-n', :desc => 'Remote github namespace (user or organization) to clone from and push to. Defaults to puppetlabs', :default => 'puppetlabs'
33
+ class_option :filter, :aliases => '-f', :desc => 'A regular expression to select repositories to update.'
34
+ class_option :negative_filter, :aliases => '-x', :desc => 'A regular expression to skip repositories.'
35
+ class_option :branch, :aliases => '-b', :desc => 'Branch name to make the changes in. Defaults to master.', :default => 'master'
102
36
 
103
- @options.fetch(:message) do
104
- if @options[:command] == 'update' && ! @options[:noop] && ! @options[:amend] && ! @options[:offline]
105
- fail("A commit message is required unless using noop or offline.")
106
- end
107
- end
37
+ desc 'update', 'Update the modules in managed_modules.yml'
38
+ option :message, :aliases => '-m', :desc => 'Commit message to apply to updated modules. Required unless running in noop mode.'
39
+ option :configs, :aliases => '-c', :desc => 'The local directory or remote repository to define the list of managed modules, the file templates, and the default values for template variables.'
40
+ option :remote_branch, :aliases => '-r', :desc => 'Remote branch name to push the changes to. Defaults to the branch name.'
41
+ option :skip_broken, :type => :boolean, :aliases => '-s', :desc => 'Process remaining modules if an error is found', :default => false
42
+ option :amend, :type => :boolean, :desc => 'Amend previous commit', :default => false
43
+ option :force, :type => :boolean, :desc => 'Force push amended commit', :default => false
44
+ option :noop, :type => :boolean, :desc => 'No-op mode', :default => false
45
+ option :offline, :type => :boolean, :desc => 'Do not run any Git commands. Allows the user to manage Git outside of ModuleSync.', :default => false
46
+ option :bump, :type => :boolean, :desc => 'Bump module version to the next minor', :default => false
47
+ option :changelog, :type => :boolean, :desc => 'Update CHANGELOG.md if version was bumped', :default => false
48
+ option :tag, :type => :boolean, :desc => 'Git tag with the current module version', :default => false
49
+ option :tag_pattern, :desc => 'The pattern to use when tagging releases.'
108
50
 
109
- @options.fetch(:command) do
110
- fail("A command is required.")
51
+ def update
52
+ config = { :command => 'update' }.merge(options)
53
+ config.merge!(Util.parse_config(MODULESYNC_CONF_FILE))
54
+ config = Util.symbolize_keys(config)
55
+ raise Thor::Error, 'No value provided for required option "--message"' unless config[:noop] || config[:message] || config[:offline]
56
+ config[:git_opts] = { 'amend' => config[:amend], 'force' => config[:force] }
57
+ ModuleSync.update(config)
111
58
  end
112
59
 
113
- if @options[:command] == 'hook' &&
114
- (! args.include?('activate') && ! args.include?('deactivate'))
115
- fail("You must activate or deactivate the hook.")
116
- end
117
-
118
- end
119
-
120
- def options
121
- @options
60
+ desc 'hook', 'Activate or deactivate a git hook.'
61
+ subcommand 'hook', ModuleSync::CLI::Hook
122
62
  end
123
63
  end
124
64
  end
@@ -1,10 +1,10 @@
1
1
  module ModuleSync
2
2
  module Constants
3
- MODULE_FILES_DIR = 'moduleroot/'
4
- CONF_FILE = 'config_defaults.yml'
5
- MODULE_CONF_FILE = '.sync.yml'
6
- MODULESYNC_CONF_FILE = 'modulesync.yml'
7
- HOOK_FILE = '.git/hooks/pre-push'
3
+ MODULE_FILES_DIR = 'moduleroot/'.freeze
4
+ CONF_FILE = 'config_defaults.yml'.freeze
5
+ MODULE_CONF_FILE = '.sync.yml'.freeze
6
+ MODULESYNC_CONF_FILE = 'modulesync.yml'.freeze
7
+ HOOK_FILE = '.git/hooks/pre-push'.freeze
8
8
  GLOBAL_DEFAULTS_KEY = :global
9
9
  end
10
10
  end
@@ -6,38 +6,41 @@ module ModuleSync
6
6
  include Constants
7
7
 
8
8
  def self.remote_branch_exists?(repo, branch)
9
- repo.branches.remote.collect { |b| b.name }.include?(branch)
9
+ repo.branches.remote.collect(&:name).include?(branch)
10
10
  end
11
11
 
12
12
  def self.local_branch_exists?(repo, branch)
13
- repo.branches.local.collect { |b| b.name }.include?(branch)
13
+ repo.branches.local.collect(&:name).include?(branch)
14
+ end
15
+
16
+ def self.remote_branch_differ?(repo, local_branch, remote_branch)
17
+ !remote_branch_exists?(repo, remote_branch) ||
18
+ repo.diff("#{local_branch}..origin/#{remote_branch}").any?
14
19
  end
15
20
 
16
21
  def self.switch_branch(repo, branch)
17
- unless repo.branch.name == branch
18
- if local_branch_exists?(repo, branch)
19
- puts "Switching to branch #{branch}"
20
- repo.checkout(branch)
21
- elsif remote_branch_exists?(repo, branch)
22
- puts "Creating local branch #{branch} from origin/#{branch}"
23
- repo.checkout("origin/#{branch}")
24
- repo.branch(branch).checkout
25
- else
26
- repo.checkout('origin/master')
27
- puts "Creating new branch #{branch}"
28
- repo.branch(branch).checkout
29
- end
22
+ return if repo.branch.name == branch
23
+
24
+ if local_branch_exists?(repo, branch)
25
+ puts "Switching to branch #{branch}"
26
+ repo.checkout(branch)
27
+ elsif remote_branch_exists?(repo, branch)
28
+ puts "Creating local branch #{branch} from origin/#{branch}"
29
+ repo.checkout("origin/#{branch}")
30
+ repo.branch(branch).checkout
31
+ else
32
+ repo.checkout('origin/master')
33
+ puts "Creating new branch #{branch}"
34
+ repo.branch(branch).checkout
30
35
  end
31
36
  end
32
37
 
33
38
  def self.pull(git_base, name, branch, project_root, opts)
34
- if ! Dir.exists?(project_root)
35
- Dir.mkdir(project_root)
36
- end
39
+ Dir.mkdir(project_root) unless Dir.exist?(project_root)
37
40
 
38
41
  # Repo needs to be cloned in the cwd
39
- if ! Dir.exists?("#{project_root}/#{name}") || ! Dir.exists?("#{project_root}/#{name}/.git")
40
- puts "Cloning repository fresh"
42
+ if !Dir.exist?("#{project_root}/#{name}") || !Dir.exist?("#{project_root}/#{name}/.git")
43
+ puts 'Cloning repository fresh'
41
44
  remote = opts[:remote] || (git_base.start_with?('file://') ? "#{git_base}/#{name}" : "#{git_base}/#{name}.git")
42
45
  local = "#{project_root}/#{name}"
43
46
  puts "Cloning from #{remote}"
@@ -52,20 +55,18 @@ module ModuleSync
52
55
  repo.fetch
53
56
  repo.reset_hard
54
57
  switch_branch(repo, branch)
55
- if remote_branch_exists?(repo, branch)
56
- repo.pull('origin', branch)
57
- end
58
+ repo.pull('origin', branch) if remote_branch_exists?(repo, branch)
58
59
  end
59
60
  end
60
61
  end
61
62
 
62
63
  def self.update_changelog(repo, version, message, module_root)
63
64
  changelog = "#{module_root}/CHANGELOG.md"
64
- if File.exists?(changelog)
65
+ if File.exist?(changelog)
65
66
  puts "Updating #{changelog} for version #{version}"
66
67
  changes = File.readlines(changelog)
67
68
  File.open(changelog, 'w') do |f|
68
- date = Time.now.strftime("%Y-%m-%d")
69
+ date = Time.now.strftime('%Y-%m-%d')
69
70
  f.puts "## #{date} - Release #{version}\n\n"
70
71
  f.puts "#{message}\n\n"
71
72
  # Add old lines again
@@ -73,15 +74,15 @@ module ModuleSync
73
74
  end
74
75
  repo.add('CHANGELOG.md')
75
76
  else
76
- puts "No CHANGELOG.md file found, not updating."
77
+ puts 'No CHANGELOG.md file found, not updating.'
77
78
  end
78
79
  end
79
80
 
80
- def self.bump(repo, m, message, module_root, changelog=false)
81
+ def self.bump(repo, m, message, module_root, changelog = false)
81
82
  new = m.bump!
82
83
  puts "Bumped to version #{new}"
83
84
  repo.add('metadata.json')
84
- self.update_changelog(repo, new, message, module_root) if changelog
85
+ update_changelog(repo, new, message, module_root) if changelog
85
86
  repo.commit("Release version #{new}")
86
87
  repo.push
87
88
  new
@@ -98,43 +99,40 @@ module ModuleSync
98
99
  def self.update(name, files, options)
99
100
  module_root = "#{options[:project_root]}/#{name}"
100
101
  message = options[:message]
101
- if options[:remote_branch]
102
- branch = "#{options[:branch]}:#{options[:remote_branch]}"
103
- else
104
- branch = options[:branch]
105
- end
106
102
  repo = ::Git.open(module_root)
107
103
  repo.branch(options[:branch]).checkout
108
104
  files.each do |file|
109
105
  if repo.status.deleted.include?(file)
110
106
  repo.remove(file)
111
- else
107
+ elsif File.exist?("#{module_root}/#{file}")
112
108
  repo.add(file)
113
109
  end
114
110
  end
115
111
  begin
116
112
  opts_commit = {}
117
113
  opts_push = {}
118
- if options[:amend]
119
- opts_commit = {:amend => true}
120
- end
121
- if options[:force]
122
- opts_push = {:force => true}
123
- end
114
+ opts_commit = { :amend => true } if options[:amend]
115
+ opts_push = { :force => true } if options[:force]
124
116
  if options[:pre_commit_script]
125
117
  script = "#{File.dirname(File.dirname(__FILE__))}/../contrib/#{options[:pre_commit_script]}"
126
- %x[#{script} #{module_root}]
118
+ `#{script} #{module_root}`
127
119
  end
128
120
  repo.commit(message, opts_commit)
129
- repo.push('origin', branch, opts_push)
121
+ if options[:remote_branch]
122
+ if remote_branch_differ?(repo, options[:branch], options[:remote_branch])
123
+ repo.push('origin', "#{options[:branch]}:#{options[:remote_branch]}", opts_push)
124
+ end
125
+ else
126
+ repo.push('origin', options[:branch], opts_push)
127
+ end
130
128
  # Only bump/tag if pushing didn't fail (i.e. there were changes)
131
129
  m = Blacksmith::Modulefile.new("#{module_root}/metadata.json")
132
130
  if options[:bump]
133
- new = self.bump(repo, m, message, module_root, options[:changelog])
134
- self.tag(repo, new, options[:tag_pattern]) if options[:tag]
131
+ new = bump(repo, m, message, module_root, options[:changelog])
132
+ tag(repo, new, options[:tag_pattern]) if options[:tag]
135
133
  end
136
134
  rescue ::Git::GitExecuteError => git_error
137
- if git_error.message.include? "nothing to commit, working directory clean"
135
+ if git_error.message =~ /working (directory|tree) clean/
138
136
  puts "There were no files to update in #{name}. Not committing."
139
137
  else
140
138
  puts git_error
@@ -148,12 +146,8 @@ module ModuleSync
148
146
  # https://github.com/schacon/ruby-git/issues/130
149
147
  def self.untracked_unignored_files(repo)
150
148
  ignore_path = "#{repo.dir.path}/.gitignore"
151
- if File.exists?(ignore_path)
152
- ignored = File.open(ignore_path).read.split
153
- else
154
- ignored = []
155
- end
156
- repo.status.untracked.keep_if{|f,_| !ignored.any?{|i| File.fnmatch(i, f)}}
149
+ ignored = File.exist?(ignore_path) ? File.open(ignore_path).read.split : []
150
+ repo.status.untracked.keep_if { |f, _| !ignored.any? { |i| File.fnmatch(i, f) } }
157
151
  end
158
152
 
159
153
  def self.update_noop(name, options)
@@ -162,13 +156,13 @@ module ModuleSync
162
156
  repo = ::Git.open("#{options[:project_root]}/#{name}")
163
157
  repo.branch(options[:branch]).checkout
164
158
 
165
- puts "Files changed: "
159
+ puts 'Files changed:'
166
160
  repo.diff('HEAD', '--').each do |diff|
167
161
  puts diff.patch
168
162
  end
169
163
 
170
- puts "Files added: "
171
- untracked_unignored_files(repo).each do |file,_|
164
+ puts 'Files added:'
165
+ untracked_unignored_files(repo).each do |file, _|
172
166
  puts file
173
167
  end
174
168