repo_manager 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemfiles +115 -0
- data/.gitattributes +1 -0
- data/.gitignore +7 -0
- data/.rspec +3 -0
- data/.yardopts +11 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +99 -0
- data/Guardfile +63 -0
- data/HISTORY.markdown +12 -0
- data/LICENSE +20 -0
- data/README.markdown +192 -0
- data/Rakefile +94 -0
- data/TODO.markdown +15 -0
- data/VERSION +1 -0
- data/bin/repo +151 -0
- data/cucumber.yml +28 -0
- data/examples/pc_saved_game_backup/.gitignore +2 -0
- data/examples/pc_saved_game_backup/INSTALL.markdown +420 -0
- data/examples/pc_saved_game_backup/README.markdown +108 -0
- data/examples/pc_saved_game_backup/remote/.gitignore +2 -0
- data/examples/pc_saved_game_backup/repo_manager/Gemfile +12 -0
- data/examples/pc_saved_game_backup/repo_manager/Gemfile.lock +66 -0
- data/examples/pc_saved_game_backup/repo_manager/assets/.gitignore +2 -0
- data/examples/pc_saved_game_backup/repo_manager/features/support/aruba.rb +15 -0
- data/examples/pc_saved_game_backup/repo_manager/features/support/env.rb +11 -0
- data/examples/pc_saved_game_backup/repo_manager/features/support/steps.rb +3 -0
- data/examples/pc_saved_game_backup/repo_manager/features/tasks/update.feature +144 -0
- data/examples/pc_saved_game_backup/repo_manager/global/default/asset.conf +2 -0
- data/examples/pc_saved_game_backup/repo_manager/repo.conf +64 -0
- data/examples/pc_saved_game_backup/repo_manager/tasks/.gitignore +0 -0
- data/examples/pc_saved_game_backup/repo_manager/tasks/remote.rb +57 -0
- data/examples/pc_saved_game_backup/repo_manager/tasks/update.rb +65 -0
- data/examples/pc_saved_game_backup/saved_games/hearts/save1 +1 -0
- data/examples/pc_saved_game_backup/saved_games/hearts/save2 +1 -0
- data/examples/pc_saved_game_backup/saved_games/mines/my_profile.ini +1 -0
- data/examples/pc_saved_game_backup/saved_games/mines/saves/save1 +1 -0
- data/examples/pc_saved_game_backup/saved_games/mines/saves/save2 +1 -0
- data/features/actions/git.feature +296 -0
- data/features/actions/help.feature +53 -0
- data/features/actions/list.feature +624 -0
- data/features/actions/path.feature +195 -0
- data/features/actions/status.feature +261 -0
- data/features/actions/task.feature +127 -0
- data/features/assets/configuration.feature +204 -0
- data/features/assets/rendering.feature +42 -0
- data/features/assets/user_attributes.feature +98 -0
- data/features/bin.feature +42 -0
- data/features/logger.feature +218 -0
- data/features/settings.feature +240 -0
- data/features/support/aruba.rb +15 -0
- data/features/support/env.rb +11 -0
- data/features/support/steps.rb +3 -0
- data/features/tasks/add/asset.feature +178 -0
- data/features/tasks/generate/init.feature +56 -0
- data/lib/repo_manager.rb +36 -0
- data/lib/repo_manager/actions.rb +8 -0
- data/lib/repo_manager/actions/action_helper.rb +39 -0
- data/lib/repo_manager/actions/app_action.rb +30 -0
- data/lib/repo_manager/actions/base_action.rb +296 -0
- data/lib/repo_manager/actions/git_action.rb +113 -0
- data/lib/repo_manager/actions/help_action.rb +52 -0
- data/lib/repo_manager/actions/list_action.rb +123 -0
- data/lib/repo_manager/actions/path_action.rb +22 -0
- data/lib/repo_manager/actions/status_action.rb +192 -0
- data/lib/repo_manager/actions/task_action.rb +71 -0
- data/lib/repo_manager/app.rb +116 -0
- data/lib/repo_manager/assets.rb +3 -0
- data/lib/repo_manager/assets/app_asset.rb +15 -0
- data/lib/repo_manager/assets/asset_accessors.rb +67 -0
- data/lib/repo_manager/assets/asset_configuration.rb +137 -0
- data/lib/repo_manager/assets/asset_manager.rb +72 -0
- data/lib/repo_manager/assets/base_asset.rb +199 -0
- data/lib/repo_manager/assets/repo_asset.rb +30 -0
- data/lib/repo_manager/core.rb +2 -0
- data/lib/repo_manager/core/array.rb +21 -0
- data/lib/repo_manager/core/hash.rb +83 -0
- data/lib/repo_manager/errors.rb +10 -0
- data/lib/repo_manager/extensions/hash.rb +86 -0
- data/lib/repo_manager/git.rb +2 -0
- data/lib/repo_manager/git/lib.rb +69 -0
- data/lib/repo_manager/git/status.rb +196 -0
- data/lib/repo_manager/logger.rb +39 -0
- data/lib/repo_manager/settings.rb +98 -0
- data/lib/repo_manager/tasks.rb +3 -0
- data/lib/repo_manager/tasks/add/asset.rb +213 -0
- data/lib/repo_manager/tasks/generate/init.rb +42 -0
- data/lib/repo_manager/tasks/generate/templates/config/repo.conf.tt +61 -0
- data/lib/repo_manager/tasks/generate/templates/init/assets/.gitignore +0 -0
- data/lib/repo_manager/tasks/generate/templates/init/global/default/asset.conf +2 -0
- data/lib/repo_manager/tasks/generate/templates/init/tasks/.gitignore +0 -0
- data/lib/repo_manager/tasks/task_manager.rb +166 -0
- data/lib/repo_manager/tasks/thor_helper.rb +29 -0
- data/lib/repo_manager/test/asset_steps.rb +19 -0
- data/lib/repo_manager/test/base_steps.rb +152 -0
- data/lib/repo_manager/test/repo_api.rb +41 -0
- data/lib/repo_manager/test/repo_steps.rb +83 -0
- data/lib/repo_manager/test/test_api.rb +88 -0
- data/lib/repo_manager/views.rb +2 -0
- data/lib/repo_manager/views/app_view.rb +15 -0
- data/lib/repo_manager/views/base_view.rb +137 -0
- data/lib/repo_manager/views/templates/css/basic.css +26 -0
- data/lib/repo_manager/views/templates/default.erb +40 -0
- data/lib/repo_manager/views/templates/default.slim +37 -0
- data/lib/repo_manager/views/view_helper.rb +55 -0
- data/repo_manager.gemspec +75 -0
- data/spec/basic_app/actions/action_helper_spec.rb +54 -0
- data/spec/basic_app/assets/base_asset_spec.rb +210 -0
- data/spec/basic_app/core_spec.rb +78 -0
- data/spec/basic_app/settings_spec.rb +64 -0
- data/spec/basic_app/views/view_helper_spec.rb +28 -0
- data/spec/basic_gem/aruba_helper_spec.rb +33 -0
- data/spec/basic_gem/basic_gem_spec.rb +84 -0
- data/spec/basic_gem/gemspec_spec.rb +68 -0
- data/spec/repo_manager/git_spec.rb +31 -0
- data/spec/spec_helper.rb +25 -0
- metadata +472 -0
@@ -0,0 +1,196 @@
|
|
1
|
+
module RepoManager
|
2
|
+
|
3
|
+
# Simplified version of ruby-git's class that uses Git's 'status --porcelain' command
|
4
|
+
#
|
5
|
+
# The --porcelain switch is useful since it handles ignored files and ignores
|
6
|
+
# non-commitable changes. Speed is not a big concern. There is only one
|
7
|
+
# call needed to the Git binary. No plumbing commands are used.
|
8
|
+
class Status
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
# repo status unchanged/clean
|
12
|
+
CLEAN = 0
|
13
|
+
|
14
|
+
# bitfields for status
|
15
|
+
NOPATH = 1
|
16
|
+
INVALID = 2
|
17
|
+
CHANGED = 4
|
18
|
+
ADDED = 8
|
19
|
+
DELETED = 16
|
20
|
+
UNTRACKED = 32
|
21
|
+
UNMERGED = 64
|
22
|
+
|
23
|
+
attr_reader :files
|
24
|
+
|
25
|
+
def initialize(scm)
|
26
|
+
@files = {}
|
27
|
+
@scm = scm
|
28
|
+
construct_status
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Numeric] 0 if CLEAN or bitfield with status: CHANGED | UNTRACKED | ADDED | DELETED | UNMERGED
|
32
|
+
def bitfield
|
33
|
+
# M ? A D U
|
34
|
+
(changed? ? CHANGED : 0) |
|
35
|
+
(untracked? ? UNTRACKED : 0) |
|
36
|
+
(added? ? ADDED : 0) |
|
37
|
+
(deleted? ? DELETED : 0) |
|
38
|
+
(unmerged? ? UNMERGED : 0)
|
39
|
+
end
|
40
|
+
|
41
|
+
def changed
|
42
|
+
@files.select { |k, f| f.type == 'M' }
|
43
|
+
end
|
44
|
+
|
45
|
+
def added
|
46
|
+
@files.select { |k, f| f.type == 'A' }
|
47
|
+
end
|
48
|
+
|
49
|
+
def deleted
|
50
|
+
@files.select { |k, f| f.type == 'D' }
|
51
|
+
end
|
52
|
+
|
53
|
+
def untracked
|
54
|
+
@files.select { |k, f| f.type == '?' }
|
55
|
+
end
|
56
|
+
|
57
|
+
def unmerged
|
58
|
+
@files.select { |k, f| f.type == 'U' }
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [Boolean] false unless a file has been modified/changed
|
62
|
+
def changed?
|
63
|
+
!changed.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [Boolean] false unless a file has been added
|
67
|
+
def added?
|
68
|
+
!added.empty?
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Boolean] false unless a file has been deleted
|
72
|
+
def deleted?
|
73
|
+
!deleted.empty?
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [Boolean] false unless there is a new/untracked file
|
77
|
+
def untracked?
|
78
|
+
!untracked.empty?
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [Boolean] false unless there is an unmerged file
|
82
|
+
def unmerged?
|
83
|
+
!unmerged.empty?
|
84
|
+
end
|
85
|
+
|
86
|
+
def [](file)
|
87
|
+
@files[file]
|
88
|
+
end
|
89
|
+
|
90
|
+
def each
|
91
|
+
@files.each do |k, file|
|
92
|
+
yield file
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class StatusFile
|
97
|
+
attr_accessor :path, :type
|
98
|
+
|
99
|
+
def initialize(hash)
|
100
|
+
@path = hash[:path]
|
101
|
+
@type = hash[:type]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def construct_status
|
108
|
+
# XY filename
|
109
|
+
# Y = working tree
|
110
|
+
#
|
111
|
+
# From git 1.7+ documentation
|
112
|
+
#
|
113
|
+
# X Y Meaning
|
114
|
+
# -------------------------------------------------
|
115
|
+
# [MD] not updated
|
116
|
+
# M [ MD] updated in index
|
117
|
+
# A [ MD] added to index
|
118
|
+
# D [ MD] deleted from index
|
119
|
+
# R [ MD] renamed in index
|
120
|
+
# C [ MD] copied in index
|
121
|
+
# [MARC] index and work tree matches
|
122
|
+
# [ MARC] M work tree changed since index
|
123
|
+
# [ MARC] D deleted in work tree
|
124
|
+
# -------------------------------------------------
|
125
|
+
# D D unmerged, both deleted
|
126
|
+
# A U unmerged, added by us
|
127
|
+
# U D unmerged, deleted by them
|
128
|
+
# U A unmerged, added by them
|
129
|
+
# D U unmerged, deleted by us
|
130
|
+
# A A unmerged, both added
|
131
|
+
# U U unmerged, both modified
|
132
|
+
# -------------------------------------------------
|
133
|
+
# ? ? untracked
|
134
|
+
# -------------------------------------------------
|
135
|
+
#
|
136
|
+
#
|
137
|
+
# simplify porcelain output:
|
138
|
+
#
|
139
|
+
# combine X and Y and boil down status returns to just five types,
|
140
|
+
# M ? A D U
|
141
|
+
#
|
142
|
+
# example output:
|
143
|
+
#
|
144
|
+
# output = [" M .gitignore", "R testing s.txt", "test space.txt", "?? new_file1.txt"]
|
145
|
+
#
|
146
|
+
# show working folder status with just five status condtions
|
147
|
+
#
|
148
|
+
# exact matches for untracked and unmerged
|
149
|
+
#
|
150
|
+
# '??' => 'untracked' [untracked.blue]
|
151
|
+
# 'DD', 'AU', 'UD', 'UA', 'DU', 'AA', 'UU' => 'unmerged' [unmerged.red.bold]
|
152
|
+
#
|
153
|
+
# added with working folder clear
|
154
|
+
#
|
155
|
+
# /R./ => 'renamed' [added.green], special handling required
|
156
|
+
# /A /, /M /, /D /, /R /, /C / => 'added' [added.green]
|
157
|
+
#
|
158
|
+
# everything else can be described by working folder status character
|
159
|
+
#
|
160
|
+
# /.D/ => 'deleted', [deleted.yellow]
|
161
|
+
# /.M/ => 'modified', [changed.red]
|
162
|
+
|
163
|
+
output = @scm.lib.native('status', ['--porcelain', '-z']).split("\000")
|
164
|
+
while line = output.shift
|
165
|
+
next unless line && line.length > 3
|
166
|
+
file_hash = nil
|
167
|
+
# first two chars, XY format
|
168
|
+
st = line[0..1]
|
169
|
+
# skip the space
|
170
|
+
filename = line[3..-1]
|
171
|
+
|
172
|
+
# renamed/copied files 'to -> from', 'from' will be on the next line,
|
173
|
+
# shift it off as we don't track this
|
174
|
+
output.shift if st.match(/[R|C]/)
|
175
|
+
|
176
|
+
case st
|
177
|
+
when '??'
|
178
|
+
file_hash = {:type => '?', :path => filename}
|
179
|
+
when 'DD', 'AU', 'UD', 'UA', 'DU', 'AA', 'UU'
|
180
|
+
file_hash = {:type => 'U', :path => filename}
|
181
|
+
when 'A ', 'M ', 'D ', 'R ', 'C '
|
182
|
+
file_hash = {:type => 'A', :path => filename}
|
183
|
+
when /.D/
|
184
|
+
file_hash = {:type => 'D', :path => filename}
|
185
|
+
when /.M/
|
186
|
+
file_hash = {:type => 'M', :path => filename}
|
187
|
+
else
|
188
|
+
raise "fatal error: unknown git status condition: '#{st}'"
|
189
|
+
end
|
190
|
+
|
191
|
+
@files[filename] = StatusFile.new(file_hash) if (file_hash && filename)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'logging'
|
2
|
+
include Logging.globally
|
3
|
+
|
4
|
+
module RepoManager
|
5
|
+
module Logger
|
6
|
+
|
7
|
+
class Manager
|
8
|
+
|
9
|
+
def initialize(config_filename=nil, yaml_key=nil, configuration={})
|
10
|
+
|
11
|
+
options = configuration[:options] || {}
|
12
|
+
|
13
|
+
if config_filename && yaml_key && configuration.has_key?(yaml_key)
|
14
|
+
Logging::Config::YamlConfigurator.load(config_filename, yaml_key.to_s)
|
15
|
+
else
|
16
|
+
# setup a default root level STDOUT logger
|
17
|
+
format = {:pattern => '%-5l %c: %m\n'}
|
18
|
+
format = format.merge(:color_scheme => 'default') if options[:color]
|
19
|
+
Logging.appenders.stdout('stdout', :layout => Logging.layouts.pattern(format), :level => :info)
|
20
|
+
Logging.logger.root.add_appenders('stdout')
|
21
|
+
end
|
22
|
+
|
23
|
+
# if verbose, all defined loggers are set to debug level
|
24
|
+
if options[:verbose]
|
25
|
+
Logging.appenders.each do |appender|
|
26
|
+
appender.level = :debug
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# debug
|
31
|
+
#Logging.show_configuration
|
32
|
+
#logger.error "error"
|
33
|
+
#logger.warn "warn"
|
34
|
+
#logger.info "info"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'erb'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'repo_manager/extensions/hash'
|
5
|
+
|
6
|
+
module RepoManager
|
7
|
+
|
8
|
+
# Access setting via symbolized keys or using accessor methods
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# settings = Settings.new(FileUtils.pwd, {:config => 'some/file.yml'})
|
13
|
+
#
|
14
|
+
# verbose = settings.to_hash[:options] ? settings.to_hash[:options][:verbose] : false
|
15
|
+
#
|
16
|
+
# equivalent to:
|
17
|
+
#
|
18
|
+
# verbose = settings.options ? settings.options.verbose : false
|
19
|
+
#
|
20
|
+
# @return [Hash], for pure hash use 'to_hash' instead
|
21
|
+
class Settings < Hash
|
22
|
+
include RepoManager::Extensions::MethodReader
|
23
|
+
include RepoManager::Extensions::MethodWriter
|
24
|
+
|
25
|
+
def initialize(working_dir=nil, options={})
|
26
|
+
@working_dir = working_dir || FileUtils.pwd
|
27
|
+
@configuration = configure(options)
|
28
|
+
|
29
|
+
# call super without args
|
30
|
+
super *[]
|
31
|
+
|
32
|
+
self.merge!(@configuration)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# read options from YAML config
|
38
|
+
def configure(options)
|
39
|
+
|
40
|
+
# config file default options
|
41
|
+
configuration = {
|
42
|
+
:options => {
|
43
|
+
:verbose => false,
|
44
|
+
:color => 'AUTO',
|
45
|
+
:short => false,
|
46
|
+
:unmodified => 'HIDE',
|
47
|
+
:match => 'ALL',
|
48
|
+
:list => 'ALL'
|
49
|
+
},
|
50
|
+
:commands => [
|
51
|
+
'diff',
|
52
|
+
'grep',
|
53
|
+
'log',
|
54
|
+
'ls-files',
|
55
|
+
'show',
|
56
|
+
'status'
|
57
|
+
]
|
58
|
+
}
|
59
|
+
|
60
|
+
# set default config if not given on command line
|
61
|
+
config = options[:config]
|
62
|
+
if config.nil?
|
63
|
+
config = [
|
64
|
+
File.join(@working_dir, "repo.conf"),
|
65
|
+
File.join(@working_dir, ".repo.conf"),
|
66
|
+
File.join(@working_dir, "repo_manager", "repo.conf"),
|
67
|
+
File.join(@working_dir, ".repo_manager", "repo.conf"),
|
68
|
+
File.join(@working_dir, "config", "repo.conf"),
|
69
|
+
File.expand_path(File.join("~", ".repo.conf")),
|
70
|
+
File.expand_path(File.join("~", "repo.conf")),
|
71
|
+
File.expand_path(File.join("~", "repo_manager", "repo.conf")),
|
72
|
+
File.expand_path(File.join("~", ".repo_manager", "repo.conf"))
|
73
|
+
].detect { |filename| File.exists?(filename) }
|
74
|
+
end
|
75
|
+
|
76
|
+
if config && File.exists?(config)
|
77
|
+
# load options from the config file, overwriting hard-coded defaults
|
78
|
+
logger.debug "reading configuration file: #{config}"
|
79
|
+
config_contents = YAML.load(ERB.new(File.open(config, "rb").read).result)
|
80
|
+
configuration.merge!(config_contents.symbolize_keys!) if config_contents && config_contents.is_a?(Hash)
|
81
|
+
else
|
82
|
+
# user specified a config file?, no error if user did not specify config file
|
83
|
+
raise "config file not found" if options[:config]
|
84
|
+
end
|
85
|
+
|
86
|
+
# store the original full config filename for later use
|
87
|
+
configuration[:configuration_filename] = config
|
88
|
+
|
89
|
+
configuration.recursively_symbolize_keys!
|
90
|
+
|
91
|
+
# the command line options override options read from the config file
|
92
|
+
configuration[:options].merge!(options)
|
93
|
+
configuration
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'repo_manager'
|
2
|
+
require 'repo_manager/tasks/task_manager'
|
3
|
+
require 'repo_manager/actions/action_helper'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module RepoManager
|
7
|
+
|
8
|
+
module GenerateHelper
|
9
|
+
|
10
|
+
def asset_name_to_config_file(name=nil)
|
11
|
+
raise ArgumentError, "missing name" unless name
|
12
|
+
raise "unable to find configuration key ':folders'" unless configuration[:folders]
|
13
|
+
raise "unable to find configuration key ':folders => :assets'" unless configuration[:folders][:assets]
|
14
|
+
|
15
|
+
folder = configuration.folders[:assets]
|
16
|
+
unless folder
|
17
|
+
say "unable to find folder conf key ':folders => :assets', please set key"
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
unless Pathname.new(folder).absolute?
|
22
|
+
base_folder = File.dirname(configuration[:configuration_filename])
|
23
|
+
end
|
24
|
+
|
25
|
+
file = File.join(base_folder, folder, name, "asset.conf")
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
module AddHelper
|
31
|
+
|
32
|
+
def process_discovered_assets(discovered_assets=[])
|
33
|
+
|
34
|
+
say_status "configuring", "setting discovered asset attributes"
|
35
|
+
discovered_assets.each do |discovered_asset|
|
36
|
+
folder = File.dirname(asset_name_to_config_file(discovered_asset.name))
|
37
|
+
discovered_asset.configuration.folder = folder
|
38
|
+
end
|
39
|
+
|
40
|
+
if options[:refresh]
|
41
|
+
if existing_assets.any? && discovered_assets.any?
|
42
|
+
say_status "merging", "merging existing asset attributes"
|
43
|
+
discovered_assets.each do |discovered_asset|
|
44
|
+
existing_asset = existing_assets.detect do |existing_asset|
|
45
|
+
existing_asset.name == discovered_asset.name
|
46
|
+
end
|
47
|
+
discovered_asset.attributes.merge!(existing_asset.attributes) if existing_asset
|
48
|
+
end
|
49
|
+
end
|
50
|
+
else
|
51
|
+
say_status "comparing", "looking at existing asset names"
|
52
|
+
discovered_assets.delete_if do |asset|
|
53
|
+
result = false
|
54
|
+
if File.exists?(asset.configuration.folder)
|
55
|
+
logger.debug "#{asset.name} asset name already exists, skipping"
|
56
|
+
result = true
|
57
|
+
end
|
58
|
+
result
|
59
|
+
end
|
60
|
+
|
61
|
+
say_status "comparing", "looking at existing asset paths"
|
62
|
+
discovered_assets.delete_if do |asset|
|
63
|
+
result = false
|
64
|
+
existing_asset = existing_assets.detect do |existing_asset|
|
65
|
+
existing_asset.path && asset.path && (File.expand_path(existing_asset.path) == File.expand_path(asset.path))
|
66
|
+
end
|
67
|
+
if (existing_asset)
|
68
|
+
logger.debug "#{asset.name} path matches existing asset #{existing_asset.name}, skipping"
|
69
|
+
result = true
|
70
|
+
end
|
71
|
+
result
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
unless discovered_assets.any?
|
76
|
+
say "no assets found for updating"
|
77
|
+
exit 0
|
78
|
+
end
|
79
|
+
|
80
|
+
# list the new assets found
|
81
|
+
say "Discovered assets"
|
82
|
+
discovered_assets.each do |asset|
|
83
|
+
say_status :found, "%-40s path => '%s'" % [asset.name, relative_path(asset.path)] , :green
|
84
|
+
end
|
85
|
+
|
86
|
+
# prompt the user
|
87
|
+
say
|
88
|
+
unless options[:force]
|
89
|
+
exit 0 unless (ask("Found #{discovered_assets.size} asset(s), write the configuration file(s) (y/n)?") == 'y')
|
90
|
+
end
|
91
|
+
|
92
|
+
# write the assets
|
93
|
+
say
|
94
|
+
discovered_assets.each do |asset|
|
95
|
+
|
96
|
+
say_status :creating, "repo_manager configuration file for #{asset.name}", :green
|
97
|
+
logger.debug "writing asset #{asset.name} to #{asset.configuration.folder}"
|
98
|
+
asset.attributes.merge!(:parent => "../global/default")
|
99
|
+
save_writable_attributes(asset, asset.attributes)
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
class Add < Thor
|
108
|
+
namespace :add
|
109
|
+
include Thor::Actions
|
110
|
+
include RepoManager::ThorHelper
|
111
|
+
include RepoManager::GenerateHelper
|
112
|
+
include RepoManager::AddHelper
|
113
|
+
include ::RepoManager::ActionHelper
|
114
|
+
|
115
|
+
# adds :quiet, :skip, :pretent, :force
|
116
|
+
add_runtime_options!
|
117
|
+
|
118
|
+
method_option :filter, :type => :array, :aliases => "-f", :desc => "List of regex folder name filters"
|
119
|
+
method_option :refresh, :type => :boolean, :aliases => "-r", :desc => "Refresh existing blank attributes"
|
120
|
+
|
121
|
+
desc "assets FOLDER", "generate multiple config files by searching a folder, one level deep, for git repositories"
|
122
|
+
def assets(folder)
|
123
|
+
say_status "collecting", "collecting top level folder names"
|
124
|
+
discovered_assets = []
|
125
|
+
filters = options[:filter] || ['.*']
|
126
|
+
# Thor does not allow comma separated array options, fix that here
|
127
|
+
filters = filters.first.to_s.split(',') if filters.length == 1
|
128
|
+
Dir.glob( File.join(folder, '*/') ).each do |repo_folder|
|
129
|
+
logger.debug "filters: #{filters.inspect}"
|
130
|
+
next unless filters.find {|filter| repo_folder.match(/#{filter}/)}
|
131
|
+
next unless File.exists?(File.join(repo_folder, '.git/'))
|
132
|
+
|
133
|
+
# check existing assets for path match, if found, use existing name instead of the generated name
|
134
|
+
existing = existing_assets.detect do |existing_asset|
|
135
|
+
existing_asset.path && repo_folder && (File.expand_path(existing_asset.path) == File.expand_path(repo_folder))
|
136
|
+
end
|
137
|
+
|
138
|
+
if (existing)
|
139
|
+
name = existing.name
|
140
|
+
else
|
141
|
+
name = File.basename(repo_folder)
|
142
|
+
end
|
143
|
+
|
144
|
+
asset = ::RepoManager::RepoAsset.new(name)
|
145
|
+
asset.path = File.expand_path(repo_folder)
|
146
|
+
|
147
|
+
discovered_assets << asset
|
148
|
+
end
|
149
|
+
|
150
|
+
process_discovered_assets(discovered_assets)
|
151
|
+
end
|
152
|
+
|
153
|
+
method_option :name, :type => :string, :aliases => "-n", :desc => "given the asset a specific name"
|
154
|
+
|
155
|
+
desc "asset FOLDER", "generate a single repo asset file given a working folder"
|
156
|
+
def asset(folder)
|
157
|
+
discovered_assets = []
|
158
|
+
unless File.exists?(File.join(folder, '.git/'))
|
159
|
+
say_status :error, "unable to find '.git' folder in working folder '#{folder}'", :red
|
160
|
+
exit 1
|
161
|
+
end
|
162
|
+
|
163
|
+
# check existing assets for path match, if found, use existing name instead of the generated name
|
164
|
+
existing = existing_assets.detect do |existing_asset|
|
165
|
+
existing_asset.path && folder && (File.expand_path(existing_asset.path) == File.expand_path(folder))
|
166
|
+
end
|
167
|
+
|
168
|
+
if (existing)
|
169
|
+
name = existing.name
|
170
|
+
if options[:name]
|
171
|
+
say_status :error, "asset already exists under a different name '#{name}'", :red
|
172
|
+
exit 1
|
173
|
+
end
|
174
|
+
else
|
175
|
+
name = options[:name]
|
176
|
+
name ||= File.basename(folder)
|
177
|
+
end
|
178
|
+
|
179
|
+
asset = ::RepoManager::RepoAsset.new(name)
|
180
|
+
asset.path = File.expand_path(folder)
|
181
|
+
|
182
|
+
discovered_assets << asset
|
183
|
+
process_discovered_assets(discovered_assets)
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
# where to start looking, required by the template method
|
189
|
+
def self.source_root
|
190
|
+
File.dirname(__FILE__)
|
191
|
+
end
|
192
|
+
|
193
|
+
# write only the attributes that we have set
|
194
|
+
def save_writable_attributes(asset, attributes)
|
195
|
+
valid_keys = [:parent, :path]
|
196
|
+
accessable_attributes = {}
|
197
|
+
attributes.each do |key, value|
|
198
|
+
accessable_attributes[key] = value.dup if valid_keys.include?(key)
|
199
|
+
end
|
200
|
+
asset.configuration.save(accessable_attributes)
|
201
|
+
end
|
202
|
+
|
203
|
+
def existing_assets
|
204
|
+
return @existing_assets if @existing_assets
|
205
|
+
asset_options = {}
|
206
|
+
asset_options.merge!(:assets_folder => configuration[:folders][:assets]) if configuration[:folders]
|
207
|
+
asset_options.merge!(:base_folder => File.dirname(configuration[:configuration_filename])) if configuration[:configuration_filename]
|
208
|
+
|
209
|
+
@existing_assets = ::RepoManager::AssetManager.new.assets(asset_options)
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
end
|