repo_manager 0.7.1
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.
- 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,71 @@
|
|
|
1
|
+
module RepoManager
|
|
2
|
+
|
|
3
|
+
# @group CLI actions
|
|
4
|
+
#
|
|
5
|
+
# Invoke external tasks, normally Thor tasks
|
|
6
|
+
#
|
|
7
|
+
# @example Usage: repo task TASK [args]
|
|
8
|
+
#
|
|
9
|
+
# repo task repo_manager:sweep:screenshots /to/some/folder
|
|
10
|
+
# repo repo_manager:sweep:screenshots /to/some/folder
|
|
11
|
+
#
|
|
12
|
+
# @example General task help:
|
|
13
|
+
#
|
|
14
|
+
# repo help task
|
|
15
|
+
#
|
|
16
|
+
# @example Help for specific task
|
|
17
|
+
#
|
|
18
|
+
# repo task help repo_manager:sweep:screenshots
|
|
19
|
+
# repo help repo_manager:sweep:screenshots
|
|
20
|
+
#
|
|
21
|
+
# @example Display a list of tasks
|
|
22
|
+
#
|
|
23
|
+
# repo task -T
|
|
24
|
+
# repo -T
|
|
25
|
+
#
|
|
26
|
+
# repo task --tasks
|
|
27
|
+
# repo --tasks
|
|
28
|
+
#
|
|
29
|
+
# @return [Number] exit code from task
|
|
30
|
+
class TaskAction < AppAction
|
|
31
|
+
|
|
32
|
+
# Add action specific options
|
|
33
|
+
def parse_options
|
|
34
|
+
super(:raise_on_invalid_option => false, :parse_base_options => false) do |opts|
|
|
35
|
+
|
|
36
|
+
opts.on("-T", "--tasks", "List tasks") do |t|
|
|
37
|
+
options[:tasks] = t
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def process
|
|
44
|
+
# Thor actions can include toxic side effects,
|
|
45
|
+
# keep the namespace clean until needed
|
|
46
|
+
require 'repo_manager/tasks/task_manager'
|
|
47
|
+
task_manager = RepoManager::TaskManager.new(configuration)
|
|
48
|
+
|
|
49
|
+
if options[:tasks]
|
|
50
|
+
task_manager.list_tasks
|
|
51
|
+
return 0
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
raise "task name required" if args.empty?
|
|
55
|
+
|
|
56
|
+
target = args.shift
|
|
57
|
+
|
|
58
|
+
if target == "help"
|
|
59
|
+
target = args.shift
|
|
60
|
+
task_manager.task_help(target)
|
|
61
|
+
else
|
|
62
|
+
task_manager.invoke(target, args)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def help
|
|
67
|
+
super(:comment_starting_with => "Invoke", :located_in_file => __FILE__)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
require 'term/ansicolor'
|
|
2
|
+
|
|
3
|
+
class String
|
|
4
|
+
include Term::ANSIColor
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module RepoManager
|
|
8
|
+
|
|
9
|
+
AVAILABLE_ACTIONS = %w[help list task path status git]
|
|
10
|
+
|
|
11
|
+
# Commands that don't need to have the 'git' arg precede them. These are not
|
|
12
|
+
# necessarily the same as the allowed 'commands' specified in the repo.conf
|
|
13
|
+
# file.
|
|
14
|
+
# NOTE: `git help --all` for a full list of git supported commands
|
|
15
|
+
GIT_NATIVE_SUPPORT = %w[add config commit diff fetch log pull push show ls-files grep]
|
|
16
|
+
|
|
17
|
+
class App
|
|
18
|
+
|
|
19
|
+
# bin wrapper option parser object
|
|
20
|
+
attr_accessor :option_parser
|
|
21
|
+
|
|
22
|
+
def initialize(argv=[], configuration={})
|
|
23
|
+
@configuration = configuration
|
|
24
|
+
@options = configuration[:options] || {}
|
|
25
|
+
@argv = argv
|
|
26
|
+
$stdout.sync = true
|
|
27
|
+
|
|
28
|
+
config_filename = configuration[:configuration_filename]
|
|
29
|
+
RepoManager::Logger::Manager.new(config_filename, :logging, configuration)
|
|
30
|
+
|
|
31
|
+
logger.debug "configuration: #{@configuration.inspect}"
|
|
32
|
+
logger.debug "argv: #{@argv.inspect}"
|
|
33
|
+
logger.debug "config file: #{configuration[:configuration_filename]}" if configuration[:configuration_filename]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def execute
|
|
37
|
+
begin
|
|
38
|
+
|
|
39
|
+
args = @argv
|
|
40
|
+
if action_argument_required?
|
|
41
|
+
action = @argv.shift
|
|
42
|
+
|
|
43
|
+
# push action back to args if this is a native pass-through command
|
|
44
|
+
if GIT_NATIVE_SUPPORT.include?(action)
|
|
45
|
+
args.unshift(action)
|
|
46
|
+
action = 'git'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# special case: actionless tasks
|
|
50
|
+
action = 'task' if action.nil? && @options.include?(:tasks)
|
|
51
|
+
|
|
52
|
+
# special case: `repo sweep:screenshots` is an acceptable task action
|
|
53
|
+
if action && action.match(/[a-zA-Z]+:+/)
|
|
54
|
+
args.unshift(action)
|
|
55
|
+
action = 'task'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# special case: `repo help sweep:screenshots` is an acceptable task help action
|
|
59
|
+
if action == 'help' && args.any?
|
|
60
|
+
target = args[0]
|
|
61
|
+
if target.match(/[a-zA-Z]+:+/)
|
|
62
|
+
args.unshift(action)
|
|
63
|
+
action = 'task'
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
unless AVAILABLE_ACTIONS.include?(action)
|
|
68
|
+
if action.nil?
|
|
69
|
+
puts "repo action required"
|
|
70
|
+
else
|
|
71
|
+
puts "repo invalid action: #{action}"
|
|
72
|
+
end
|
|
73
|
+
puts "repo --help for more information"
|
|
74
|
+
exit 1
|
|
75
|
+
end
|
|
76
|
+
logger.debug "execute action: #{action} #{args.join(' ')}"
|
|
77
|
+
klass = Object.const_get('RepoManager').const_get("#{action.capitalize}Action")
|
|
78
|
+
app_action = klass.new(args, @configuration)
|
|
79
|
+
app_action.option_parser = self.option_parser
|
|
80
|
+
result = app_action.execute
|
|
81
|
+
else
|
|
82
|
+
#
|
|
83
|
+
# default action if action_argument_required? is false
|
|
84
|
+
#
|
|
85
|
+
result = 0
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
if result.is_a?(Numeric)
|
|
89
|
+
exit(result)
|
|
90
|
+
else
|
|
91
|
+
# handle all other return types
|
|
92
|
+
exit(result ? 0 : 1)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
rescue SystemExit => e
|
|
96
|
+
# This is the normal exit point
|
|
97
|
+
logger.debug "repo run system exit: #{e}, status code: #{e.status}"
|
|
98
|
+
exit(e.status)
|
|
99
|
+
rescue Exception => e
|
|
100
|
+
logger.fatal("repo fatal exception: #{e.message}")
|
|
101
|
+
STDERR.puts("repo failed: #{e.message}".red)
|
|
102
|
+
STDERR.puts("Command failed, use '--verbose' for backtrace.") unless @options[:verbose]
|
|
103
|
+
STDERR.puts(e.backtrace.join("\n")) if @options[:verbose]
|
|
104
|
+
exit(1)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
# true if application requires an action to be specified on the command line
|
|
111
|
+
def action_argument_required?
|
|
112
|
+
!AVAILABLE_ACTIONS.empty?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
####################################################
|
|
2
|
+
# The file is was originally cloned from "Basic App"
|
|
3
|
+
# More information on "Basic App" can be found in the
|
|
4
|
+
# "Basic App" repository.
|
|
5
|
+
#
|
|
6
|
+
# See http://github.com/robertwahler
|
|
7
|
+
####################################################
|
|
8
|
+
module RepoManager
|
|
9
|
+
|
|
10
|
+
# An abstract superclass for basic asset functionality specific to an
|
|
11
|
+
# application implementation. Put application specific code here.
|
|
12
|
+
class AppAsset < BaseAsset
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module RepoManager
|
|
2
|
+
|
|
3
|
+
module AssetAccessors
|
|
4
|
+
|
|
5
|
+
# Given an array, create accessors
|
|
6
|
+
# NOTE: This is similar to using method_missing with a whitelist
|
|
7
|
+
#
|
|
8
|
+
# @return [void]
|
|
9
|
+
def create_accessors(*attrs)
|
|
10
|
+
return unless attrs
|
|
11
|
+
raise ArgumentError, "Expected 'user_attributes' to be an array" unless attrs.is_a? Array
|
|
12
|
+
|
|
13
|
+
# Define each of the attributes
|
|
14
|
+
attrs.flatten.each do |attr|
|
|
15
|
+
create_accessor(attr)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create_accessor(attr)
|
|
20
|
+
create_reader(attr)
|
|
21
|
+
create_writer(attr)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def create_reader(attr)
|
|
25
|
+
return unless attr
|
|
26
|
+
|
|
27
|
+
method = "#{attr}".to_sym
|
|
28
|
+
|
|
29
|
+
if self.kind_of? RepoManager::BaseAsset
|
|
30
|
+
return if self.respond_to? method
|
|
31
|
+
|
|
32
|
+
self.class.send(:define_method, method) do
|
|
33
|
+
render(attributes[method])
|
|
34
|
+
end
|
|
35
|
+
else
|
|
36
|
+
return if respond_to? method
|
|
37
|
+
|
|
38
|
+
define_method(method) do
|
|
39
|
+
render(attributes[method])
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def create_writer(attr)
|
|
45
|
+
return unless attr
|
|
46
|
+
|
|
47
|
+
method = "#{attr}=".to_sym
|
|
48
|
+
|
|
49
|
+
if self.kind_of? RepoManager::BaseAsset
|
|
50
|
+
return if self.respond_to? method
|
|
51
|
+
|
|
52
|
+
self.class.send(:define_method, method) do |value|
|
|
53
|
+
attributes[attr] = value
|
|
54
|
+
end
|
|
55
|
+
else
|
|
56
|
+
return if respond_to? method
|
|
57
|
+
|
|
58
|
+
define_method(method) do |value|
|
|
59
|
+
attributes[attr] = value
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require 'erb'
|
|
3
|
+
require 'pathname'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
|
|
6
|
+
module RepoManager
|
|
7
|
+
|
|
8
|
+
# asset_configuration saves just the user data by subtracting out the
|
|
9
|
+
# global hash and writing just the result
|
|
10
|
+
#
|
|
11
|
+
# An asset requires a global template but doesn't require a user datafile.
|
|
12
|
+
#
|
|
13
|
+
# LOADING:
|
|
14
|
+
#
|
|
15
|
+
# Load up the master template YAML file first, evaluate the ERB, save this
|
|
16
|
+
# hash for later use.
|
|
17
|
+
#
|
|
18
|
+
# Copy the results to the asset attributes and then load the user data. The
|
|
19
|
+
# user data doesn't contain ERB.
|
|
20
|
+
#
|
|
21
|
+
# SAVING:
|
|
22
|
+
#
|
|
23
|
+
# Compare existing asset attributes to the saved and eval'd master hash and write
|
|
24
|
+
# just the change assets to the user file.
|
|
25
|
+
#
|
|
26
|
+
class AssetConfiguration
|
|
27
|
+
|
|
28
|
+
# user datastore folder, can override parent datastore
|
|
29
|
+
attr_accessor :folder
|
|
30
|
+
|
|
31
|
+
# parent datastore defaults folder, read asset from here first if exists
|
|
32
|
+
attr_accessor :parent
|
|
33
|
+
|
|
34
|
+
attr_reader :asset
|
|
35
|
+
|
|
36
|
+
def initialize(asset)
|
|
37
|
+
#logger.debug "initializing new AssetConfiguration with asset class: #{asset.class.to_s}"
|
|
38
|
+
@asset = asset
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Save specific attributes to an asset configuration file. Only the param
|
|
42
|
+
# 'attrs' and the current contents of the config file are saved. Parent
|
|
43
|
+
# asset configurations are not saved.
|
|
44
|
+
#
|
|
45
|
+
def save(attrs=nil)
|
|
46
|
+
raise "a Hash of attributes to save must be specified" unless attrs && attrs.is_a?(Hash)
|
|
47
|
+
raise "folder must be set prior to saving attributes" unless folder
|
|
48
|
+
|
|
49
|
+
# merge attributes to asset that contains parent attributes
|
|
50
|
+
@asset.attributes.merge!(attrs)
|
|
51
|
+
|
|
52
|
+
# load contents of the user folder and merge in attributes passed to save
|
|
53
|
+
# so that we don't save parent attributes
|
|
54
|
+
contents = {}
|
|
55
|
+
if File.exists?(folder)
|
|
56
|
+
contents = load_contents(folder)
|
|
57
|
+
raise "expected contents to be a hash" unless contents.is_a?(Hash)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
contents = contents.merge!(attrs)
|
|
61
|
+
write_contents(folder, contents)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# load an asset from a configuration folder
|
|
65
|
+
def load(ds=nil)
|
|
66
|
+
@folder ||= ds
|
|
67
|
+
|
|
68
|
+
contents = load_contents(folder)
|
|
69
|
+
|
|
70
|
+
# if a global parent folder is defined, load it first
|
|
71
|
+
parent = contents.delete(:parent) || parent
|
|
72
|
+
if parent
|
|
73
|
+
parent_folder = File.join(parent)
|
|
74
|
+
unless Pathname.new(parent_folder).absolute?
|
|
75
|
+
base_folder = File.dirname(folder)
|
|
76
|
+
parent_folder = File.join(base_folder, parent_folder)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
logger.debug "AssetConfiguration loading parent: #{parent_folder}"
|
|
80
|
+
parent_configuration = RepoManager::AssetConfiguration.new(asset)
|
|
81
|
+
|
|
82
|
+
begin
|
|
83
|
+
parent_configuration.load(parent_folder)
|
|
84
|
+
rescue Exception => e
|
|
85
|
+
logger.warn "AssetConfiguration parent configuration load failed on: '#{parent_folder}' with: '#{e.message}'"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Load all attributes as hash 'attributes' so that merging
|
|
90
|
+
# and adding new attributes doesn't require code changes. Note
|
|
91
|
+
# that the 'parent' setting is not merged to attributes
|
|
92
|
+
@asset.attributes.merge!(contents)
|
|
93
|
+
@asset.create_accessors(@asset.attributes[:user_attributes])
|
|
94
|
+
@asset
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def to_hash
|
|
98
|
+
result = {}
|
|
99
|
+
result.merge!(:parent => parent.folder) if parent
|
|
100
|
+
result.merge!(:attributes => @asset.attributes)
|
|
101
|
+
result
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
# load the raw contents from an asset_folder, ignore parents
|
|
107
|
+
#
|
|
108
|
+
# @return [Hash] of the raw text contents
|
|
109
|
+
def load_contents(asset_folder)
|
|
110
|
+
file = File.join(asset_folder, 'asset.conf')
|
|
111
|
+
if File.exists?(file)
|
|
112
|
+
contents = YAML.load(ERB.new(File.open(file, "rb").read).result(@asset.get_binding))
|
|
113
|
+
if contents && contents.is_a?(Hash)
|
|
114
|
+
contents.recursively_symbolize_keys!
|
|
115
|
+
else
|
|
116
|
+
{}
|
|
117
|
+
end
|
|
118
|
+
else
|
|
119
|
+
{}
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# write raw contents to an asset_folder
|
|
124
|
+
def write_contents(asset_folder, contents)
|
|
125
|
+
contents.recursively_stringify_keys!
|
|
126
|
+
|
|
127
|
+
FileUtils.mkdir(asset_folder) unless File.exists?(asset_folder)
|
|
128
|
+
filename = File.join(asset_folder, 'asset.conf')
|
|
129
|
+
|
|
130
|
+
#TODO, use "wb" and write CRLF on Windows
|
|
131
|
+
File.open(filename, "w") do |f|
|
|
132
|
+
f.write(contents.to_conf)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
####################################################
|
|
2
|
+
# The file is was originally cloned from "Basic App"
|
|
3
|
+
# More information on "Basic App" can be found in the
|
|
4
|
+
# "Basic App" repository.
|
|
5
|
+
#
|
|
6
|
+
# See http://github.com/robertwahler
|
|
7
|
+
####################################################
|
|
8
|
+
|
|
9
|
+
require 'pathname'
|
|
10
|
+
require 'fileutils'
|
|
11
|
+
|
|
12
|
+
module RepoManager
|
|
13
|
+
|
|
14
|
+
class AssetManager
|
|
15
|
+
|
|
16
|
+
# @raise [Exception] unless asset_options contains base_folder or :assets if an absolute path
|
|
17
|
+
#
|
|
18
|
+
# @return [Array] of Asset
|
|
19
|
+
def assets(asset_options={})
|
|
20
|
+
logger.debug "asset_options: #{asset_options.inspect}"
|
|
21
|
+
# type of asset to create, used to guess the asset_folder name
|
|
22
|
+
type = asset_options[:type] || :app_asset
|
|
23
|
+
|
|
24
|
+
assets = []
|
|
25
|
+
filters = asset_options[:filter] || ['.*']
|
|
26
|
+
match_count = 0
|
|
27
|
+
logger.debug "generating assets array with filter array: #{filters.join(',')}"
|
|
28
|
+
|
|
29
|
+
assets_folder = asset_options[:assets_folder] || "assets"
|
|
30
|
+
pattern = File.join(assets_folder, '*/')
|
|
31
|
+
logger.debug "reading from asset type: '#{type}' from assets_folder:'#{assets_folder}' "
|
|
32
|
+
|
|
33
|
+
# asset folder can be relative to main config file
|
|
34
|
+
unless Pathname.new(pattern).absolute?
|
|
35
|
+
# base_folder is determined from the configuration file
|
|
36
|
+
# location, if it is not set, then the configuration file wasn't not found
|
|
37
|
+
raise "configuration file not found" unless asset_options[:base_folder]
|
|
38
|
+
base_folder = asset_options[:base_folder]
|
|
39
|
+
pattern = File.expand_path(File.join(base_folder, pattern))
|
|
40
|
+
end
|
|
41
|
+
logger.debug "asset glob pattern: #{pattern}"
|
|
42
|
+
folders = Dir.glob(pattern)
|
|
43
|
+
logger.debug "user assets folder is empty: #{pattern}" if folders.empty?
|
|
44
|
+
|
|
45
|
+
folders.sort.each do |folder|
|
|
46
|
+
folder_basename = Pathname.new(folder).basename.to_s
|
|
47
|
+
#logger.debug "matching folder: #{folder} using basename: #{folder_basename}"
|
|
48
|
+
if filters.find {|filter| matches?(folder_basename, filter, asset_options)}
|
|
49
|
+
logger.debug "match found for: #{folder_basename}"
|
|
50
|
+
match_count += 1
|
|
51
|
+
asset = RepoManager::AppAsset.create(type, folder, {})
|
|
52
|
+
assets << asset
|
|
53
|
+
break if ((asset_options[:match] == 'FIRST') || (asset_options[:match] == 'EXACT'))
|
|
54
|
+
raise "match mode = ONE, multiple matching assets found filter" if (asset_options[:match] == 'ONE' && match_count > 1)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
assets
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def matches?(str, filter, match_options={})
|
|
64
|
+
if (match_options[:match] == 'EXACT')
|
|
65
|
+
str == filter
|
|
66
|
+
else
|
|
67
|
+
str.match(/#{filter}/)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|