modulesync 0.6.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|