modulesync 0.6.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/.rubocop.yml +16 -0
- data/.rubocop_todo.yml +75 -0
- data/.travis.yml +16 -0
- data/CHANGELOG.md +44 -6
- data/Gemfile +5 -0
- data/README.md +21 -2
- data/Rakefile +14 -4
- data/bin/msync +3 -3
- data/features/cli.feature +18 -0
- data/features/hook.feature +28 -0
- data/features/step_definitions/git_steps.rb +24 -0
- data/features/update.feature +501 -37
- data/lib/modulesync.rb +96 -50
- data/lib/modulesync/cli.rb +47 -107
- data/lib/modulesync/constants.rb +5 -5
- data/lib/modulesync/git.rb +48 -54
- data/lib/modulesync/hook.rb +25 -21
- data/lib/modulesync/renderer.rb +5 -11
- data/lib/modulesync/settings.rb +41 -0
- data/lib/modulesync/util.rb +3 -9
- data/modulesync.gemspec +14 -11
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/modulesync/settings_spec.rb +25 -0
- metadata +80 -36
data/lib/modulesync.rb
CHANGED
@@ -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.
|
22
|
-
local_files = Find.find(path).collect { |file| file
|
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.
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
data/lib/modulesync/cli.rb
CHANGED
@@ -1,124 +1,64 @@
|
|
1
|
-
require '
|
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
|
-
|
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
|
-
|
10
|
-
|
11
|
-
:
|
12
|
-
:
|
13
|
-
|
14
|
-
|
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
|
-
|
22
|
-
|
23
|
-
'
|
24
|
-
|
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
|
-
|
29
|
-
|
30
|
-
puts message
|
31
|
-
exit
|
32
|
-
end
|
27
|
+
class Base < Thor
|
28
|
+
include Constants
|
33
29
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
-
|
110
|
-
|
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
|
-
|
114
|
-
|
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
|
data/lib/modulesync/constants.rb
CHANGED
@@ -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
|
data/lib/modulesync/git.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
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 !
|
40
|
-
puts
|
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.
|
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(
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
118
|
+
`#{script} #{module_root}`
|
127
119
|
end
|
128
120
|
repo.commit(message, opts_commit)
|
129
|
-
|
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 =
|
134
|
-
|
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
|
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
|
-
|
152
|
-
|
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
|
159
|
+
puts 'Files changed:'
|
166
160
|
repo.diff('HEAD', '--').each do |diff|
|
167
161
|
puts diff.patch
|
168
162
|
end
|
169
163
|
|
170
|
-
puts
|
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
|
|