dotum 0.0.0

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.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.groc.json +6 -0
  4. data/.rspec +4 -0
  5. data/.simplecov +5 -0
  6. data/.travis.yml +15 -0
  7. data/CONTRIBUTING.md +63 -0
  8. data/Gemfile +59 -0
  9. data/Guardfile +30 -0
  10. data/MIT-LICENSE.md +21 -0
  11. data/README.md +24 -0
  12. data/Rakefile +15 -0
  13. data/bin/dotum +7 -0
  14. data/data/default_rules.dotum +44 -0
  15. data/dotum.gemspec +19 -0
  16. data/extern/json/CHANGES.md +9 -0
  17. data/extern/json/COPYING +58 -0
  18. data/extern/json/README.rdoc +358 -0
  19. data/extern/json/lib/json.rb +62 -0
  20. data/extern/json/lib/json/.DS_Store +0 -0
  21. data/extern/json/lib/json/add/bigdecimal.rb +28 -0
  22. data/extern/json/lib/json/add/complex.rb +22 -0
  23. data/extern/json/lib/json/add/core.rb +11 -0
  24. data/extern/json/lib/json/add/date.rb +34 -0
  25. data/extern/json/lib/json/add/date_time.rb +50 -0
  26. data/extern/json/lib/json/add/exception.rb +31 -0
  27. data/extern/json/lib/json/add/ostruct.rb +31 -0
  28. data/extern/json/lib/json/add/range.rb +29 -0
  29. data/extern/json/lib/json/add/rational.rb +22 -0
  30. data/extern/json/lib/json/add/regexp.rb +30 -0
  31. data/extern/json/lib/json/add/struct.rb +30 -0
  32. data/extern/json/lib/json/add/symbol.rb +25 -0
  33. data/extern/json/lib/json/add/time.rb +38 -0
  34. data/extern/json/lib/json/common.rb +487 -0
  35. data/extern/json/lib/json/generic_object.rb +70 -0
  36. data/extern/json/lib/json/pure.rb +21 -0
  37. data/extern/json/lib/json/pure/generator.rb +522 -0
  38. data/extern/json/lib/json/pure/parser.rb +359 -0
  39. data/extern/json/lib/json/version.rb +8 -0
  40. data/lib/dotum.rb +11 -0
  41. data/lib/dotum/abstract_rules.rb +5 -0
  42. data/lib/dotum/abstract_rules/base.rb +56 -0
  43. data/lib/dotum/abstract_rules/globbable_files.rb +51 -0
  44. data/lib/dotum/abstract_rules/options_base.rb +33 -0
  45. data/lib/dotum/autoload_convention.rb +34 -0
  46. data/lib/dotum/cli.rb +35 -0
  47. data/lib/dotum/context.rb +55 -0
  48. data/lib/dotum/externs/json.rb +9 -0
  49. data/lib/dotum/logger.rb +50 -0
  50. data/lib/dotum/options_context.rb +21 -0
  51. data/lib/dotum/rule_dsl.rb +73 -0
  52. data/lib/dotum/rule_options_dsl.rb +116 -0
  53. data/lib/dotum/rule_runner.rb +16 -0
  54. data/lib/dotum/rules.rb +5 -0
  55. data/lib/dotum/rules/cd.rb +23 -0
  56. data/lib/dotum/rules/download.rb +32 -0
  57. data/lib/dotum/rules/link.rb +22 -0
  58. data/lib/dotum/rules/repo.rb +65 -0
  59. data/lib/dotum/rules/require_extension.rb +42 -0
  60. data/lib/dotum/rules/run.rb +23 -0
  61. data/lib/dotum/rules/use.rb +33 -0
  62. data/lib/dotum/rules/use_repo.rb +58 -0
  63. data/lib/dotum/standard_options.rb +5 -0
  64. data/lib/dotum/standard_options/destination.rb +22 -0
  65. data/lib/dotum/util.rb +5 -0
  66. data/lib/dotum/util/ansi_colors.rb +26 -0
  67. data/lib/dotum/util/path.rb +120 -0
  68. data/lib/dotum/version.rb +5 -0
  69. data/spec/fixtures/autoload_convention/abc_one_two_three.rb +7 -0
  70. data/spec/fixtures/autoload_convention/allcaps.rb +7 -0
  71. data/spec/fixtures/autoload_convention/mismatched.rb +3 -0
  72. data/spec/fixtures/autoload_convention/multi_token.rb +7 -0
  73. data/spec/fixtures/autoload_convention/single.rb +7 -0
  74. data/spec/fixtures/autoload_convention/string.rb +7 -0
  75. data/spec/spec_helper.rb +76 -0
  76. data/spec/unit/dotum/autoload_convention/const_missing_spec.rb +57 -0
  77. data/tasks/console.rake +9 -0
  78. data/tasks/spec.rake +7 -0
  79. data/tasks/spec/ci.rake +16 -0
  80. data/tasks/spec/coverage.rake +19 -0
  81. data/tasks/spec/mutate.rake +71 -0
  82. metadata +123 -0
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::AbstractRules::OptionsBase < Dotum::AbstractRules::Base
4
+
5
+ def self.exec(context, *args, &block)
6
+ options = option_defaults.merge(expand_shorthand(*args))
7
+ options.merge! eval_options_block(&block) if block
8
+
9
+ if errors = validate_options(options)
10
+ raise "Validation errors: #{errors.inspect}"
11
+ end
12
+
13
+ if respond_to? :expand_options
14
+ expand_options(context, options).map { |rule_options|
15
+ new(context, rule_options).exec
16
+ }
17
+ else
18
+ new(context, options).exec
19
+ end
20
+ end
21
+
22
+ def initialize(context, options)
23
+ super(context)
24
+
25
+ options.each do |option, value|
26
+ filter = self.class.option_configs[option][:filter]
27
+ value = instance_exec(value, &filter) if filter && !value.nil?
28
+
29
+ instance_variable_set(:"@#{option}", value)
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ # Autoload Convention
4
+ # ===================
5
+ # We adhere to a strict convention for the constants in this library:
6
+ #
7
+ # `Camel::Caps::BasedConstants` map to their underscore variants of
8
+ # `camel/caps/based_constants`.
9
+ #
10
+ # Each autoloadable parent module/class only needs to to `extend` the
11
+ # `AutoloadConvention` to bootstrap this behavior.
12
+ module Dotum
13
+ module AutoloadConvention
14
+
15
+ # `autoload` is dead, and we don't want to deal with its removal in 2.0,
16
+ # so here's a thread-unsafe poor man's solution.
17
+ def const_missing(sym)
18
+ full_sym = "#{name}::#{sym}"
19
+ path_parts = full_sym.split("::").map { |part|
20
+ part.gsub! /([^A-Z])([A-Z]+)/, "\\1_\\2" # OneTwo -> One_Two
21
+ part.gsub! /([A-Z]+)([A-Z][^A-Z]+)/, "\\1_\\2" # ABCOne -> ABC_One
22
+
23
+ part.downcase
24
+ }
25
+
26
+ require File.join(path_parts)
27
+
28
+ # Make sure that we don't get stuck in an endless loop. `const_get` calls
29
+ # into `const_missing`, so we can't use that.
30
+ eval "defined?(#{full_sym}) ? #{full_sym} : super"
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::CLI
4
+
5
+ def self.exec(args)
6
+ new(args).exec!
7
+ end
8
+
9
+ def initialize(args)
10
+ @args = args
11
+
12
+ @state_dir = Dotum::Util::Path.new("~/.dotum")
13
+ @target_dir = Dotum::Util::Path.new("~")
14
+ @package_dir = Dotum::Util::Path.new("~/.dotum/local")
15
+ end
16
+
17
+ def exec!
18
+ context = Dotum::Context.new(
19
+ # :no_remote => true,
20
+ :state_dir => @state_dir,
21
+ :target_dir => @target_dir,
22
+ :logger => Dotum::Logger.new
23
+ )
24
+
25
+ unless @package_dir.directory?
26
+ puts
27
+ puts "#{@package_dir.pretty} doesn't exist! Creating for now..."
28
+ @package_dir.mkpath!
29
+ end
30
+
31
+ Dotum::Rules::UseRepo.exec(context, @package_dir)
32
+ print "\n\n"
33
+ end
34
+
35
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::Context
4
+
5
+ def initialize(attributes={})
6
+ set_attributes(attributes)
7
+ end
8
+
9
+ attr_reader :package_dir
10
+ attr_reader :target_dir
11
+ attr_reader :state_dir
12
+
13
+ attr_reader :logger
14
+ attr_reader :depth
15
+
16
+ def no_remote?
17
+ @no_remote
18
+ end
19
+
20
+ def attributes
21
+ result = {}
22
+ instance_variables.each do |var_name|
23
+ result[var_name[1..-1].to_sym] = instance_variable_get(var_name)
24
+ end
25
+
26
+ result
27
+ end
28
+
29
+ def fork(new_attributes={})
30
+ self.class.new(attributes.merge(new_attributes || {}))
31
+ end
32
+
33
+ def child(new_attributes={})
34
+ new_attributes ||= {}
35
+ new_attributes[:depth] = (@depth || 0) + 1
36
+
37
+ fork(new_attributes)
38
+ end
39
+
40
+ private
41
+
42
+ def set_attributes(attributes)
43
+ attributes.each_pair do |key, value|
44
+ case key
45
+ when :package_dir then @package_dir = Dotum::Util::Path.new(value)
46
+ when :target_dir then @target_dir = Dotum::Util::Path.new(value)
47
+ when :state_dir then @state_dir = Dotum::Util::Path.new(value)
48
+ when :logger then @logger = value
49
+ when :no_remote then @no_remote = value
50
+ when :depth then @depth = value
51
+ end
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require "json"
5
+ rescue LoadError
6
+ # Fall back to the embedded pure-Ruby JSON implementation.
7
+ $LOAD_PATH.unshift(Dotum::EXTERN_PATH.join("json", "lib").to_s)
8
+ require "json"
9
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::Logger
4
+ include Dotum::Util::ANSIColors
5
+
6
+ INDENT = " "
7
+
8
+ def start_rule(rule)
9
+ @last_rule = rule
10
+ @last_rule_start = Time.now
11
+
12
+ print "\n"
13
+ print rule_line(rule)
14
+ end
15
+
16
+ def finish_rule(rule, status, reason)
17
+ message = "#{rule_line(rule)} - #{status.inspect} - #{reason.inspect}"
18
+ if @last_rule == rule
19
+ delta = (Time.now - @last_rule_start) * 1000.0
20
+ message += " (%.2fms)" % delta
21
+
22
+ print "\r"
23
+ else
24
+ print "\n\n"
25
+ end
26
+
27
+ print message
28
+ end
29
+
30
+ private
31
+
32
+ def rule_line(rule)
33
+ indent = INDENT * rule.context.depth
34
+ action = rule.class.pretty
35
+ subject = rule.pretty_subject
36
+
37
+ action = c_cyan(action)
38
+ subject = colorize_subject(subject)
39
+
40
+ "#{indent}#{action}: #{subject}"
41
+ end
42
+
43
+ SUBJECT_MATCHER = /^(.*?)( \(.+\))?$/
44
+ def colorize_subject(subject)
45
+ match = SUBJECT_MATCHER.match(subject)
46
+
47
+ "#{c_magenta(match[1])}#{match[2]}"
48
+ end
49
+
50
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ require "set"
4
+
5
+ class Dotum::OptionsContext < Hash
6
+
7
+ def initialize(option_configs)
8
+ @known_options = Set.new(option_configs.keys)
9
+ end
10
+
11
+ def method_missing(sym, *args)
12
+ super if args.size != 1
13
+
14
+ unless @known_options.include? sym
15
+ raise ArgumentError, "Unknown option '#{sym}'"
16
+ end
17
+
18
+ self[sym] = args[0]
19
+ end
20
+
21
+ end
@@ -0,0 +1,73 @@
1
+ # encoding: utf-8
2
+
3
+ require "rbconfig"
4
+
5
+ module Dotum::RuleDSL
6
+
7
+ def success!(reason=nil)
8
+ throw :finish_rule, [:success, reason]
9
+ end
10
+
11
+ def failure!(reason=nil)
12
+ throw :finish_rule, [:failure, reason]
13
+ end
14
+
15
+ def skip!(reason=nil)
16
+ throw :finish_rule, [:skip, reason]
17
+ end
18
+
19
+ def platform?(name)
20
+ os = RbConfig::CONFIG["host_os"].downcase
21
+
22
+ case name
23
+ when /os\s?x/i then /mac|darwin/ === os
24
+ when /win(dows)?/i then /mswin|win|mingw/ === os
25
+ when /linux/i then /linux|cygwin/ === os
26
+ when /bsd/i then /bsd/ === os
27
+ when /solaris/i then /solaris|sunos/ === os
28
+ else
29
+ if name.is_a? Regexp
30
+ name === os
31
+ else
32
+ Regexp.new(name, "i") === os
33
+ end
34
+ end
35
+ end
36
+
37
+ def available?(command)
38
+ # TODO: Windows friendly.
39
+ `which "#{command}"`
40
+ $?.success?
41
+ end
42
+
43
+ def package_dir
44
+ context.package_dir
45
+ end
46
+
47
+ def target_dir
48
+ context.target_dir
49
+ end
50
+
51
+ def state_dir
52
+ context.state_dir
53
+ end
54
+
55
+ def method_missing(sym, *args, &block)
56
+ rule_class_name = sym.to_s.split("_").map(&:capitalize).join.to_sym
57
+
58
+ begin
59
+ rule_class = Dotum::Rules.const_get(rule_class_name)
60
+ rescue LoadError
61
+ raise NoMethodError, "Unknown rule #{sym}. Tried to load Dotum::Rules::#{rule_class_name}: #{$!.message}"
62
+ end
63
+
64
+ Dotum::RuleDSL.module_eval <<-end_eval, __FILE__, __LINE__
65
+ def #{sym}(*args, &block)
66
+ Dotum::Rules::#{rule_class_name}.exec(context, *args, &block)
67
+ end
68
+ end_eval
69
+
70
+ send(sym, *args, &block)
71
+ end
72
+
73
+ end
@@ -0,0 +1,116 @@
1
+ # encoding: utf-8
2
+
3
+ module Dotum::RuleOptionsDSL
4
+
5
+ OptionConfig = Struct.new(:filter, :validator, :default)
6
+
7
+
8
+ # DSL
9
+ # ---
10
+
11
+ def shorthand(*args)
12
+ @shorthand_config ||= args
13
+ end
14
+
15
+ def required(option, &block)
16
+ (@option_configs ||= {})[option] = OptionConfig.new(
17
+ block,
18
+ proc { |v| "Option '#{option}' is required." if v.nil? }
19
+ )
20
+ end
21
+
22
+ def optional(option, default=nil, &block)
23
+ (@option_configs ||= {})[option] = OptionConfig.new(block, nil, default)
24
+ end
25
+
26
+ def standard(option)
27
+ option_module_name = option.to_s.split("_").map(&:capitalize).join.to_sym
28
+
29
+ begin
30
+ option_module = Dotum::StandardOptions.const_get(option_module_name)
31
+ rescue LoadError
32
+ raise "Unknown standard option '#{option}'. Tried to load Dotum::StandardOptions::#{option_module_name}: #{$!.message}"
33
+ end
34
+
35
+ module_configs = option_module.instance_variable_get(:@option_configs)
36
+ unless module_configs && module_configs[option]
37
+ raise "Dotum::StandardOptions::#{option_module_name} is misconfigured; expected it to define the option '#{option}'"
38
+ end
39
+
40
+ include option_module
41
+ end
42
+
43
+ def register_preprocessor(sym)
44
+ @preprocessors ||= []
45
+ @preprocessors.push(sym)
46
+ end
47
+
48
+
49
+ # Configuration Management
50
+ # ------------------------
51
+
52
+ def option_configs
53
+ @memoized_option_configs ||= ancestors.reverse_each.reduce({}) { |result, ancestor|
54
+ result.merge(ancestor.instance_variable_get(:@option_configs) || {})
55
+ }
56
+ end
57
+
58
+ def option_defaults
59
+ @memoized_option_defaults ||= {}.tap do |defaults|
60
+ option_configs.each do |option, config|
61
+ defaults[option] = config[:default] unless config[:default].nil?
62
+ end
63
+ end
64
+ end
65
+
66
+ def preprocessor_methods
67
+ @memoized_preprocessor_methods ||= ancestors.map { |ancestor|
68
+ ancestor.instance_variable_get(:@preprocessors)
69
+ }.compact.flatten
70
+ end
71
+
72
+ def shorthand_config
73
+ return @shorthand_config if defined? @shorthand_config
74
+ return superclass.shorthand_config if superclass.respond_to? :shorthand_config
75
+
76
+ []
77
+ end
78
+
79
+ def expand_shorthand(*args)
80
+ result = {}
81
+ shorthand_config.zip(args).each do |config, value|
82
+ case config
83
+ when Symbol then result[config] = value
84
+ when Hash
85
+ if value.is_a? Hash
86
+ result[config.keys.first] = value.keys.first
87
+ result[config.values.first] = value.values.first
88
+ else
89
+ result[config.keys.first] = value
90
+ end
91
+ end
92
+ end
93
+
94
+ result
95
+ end
96
+
97
+ def eval_options_block(&block)
98
+ options = Dotum::OptionsContext.new(option_configs)
99
+ options.instance_eval(&block)
100
+
101
+ options
102
+ end
103
+
104
+ def validate_options(options)
105
+ errors = []
106
+ option_configs.each do |option, config|
107
+ next unless validator = config[:validator]
108
+ next unless error = validator.call(options[option])
109
+
110
+ errors.push(error)
111
+ end
112
+
113
+ errors.size > 0 ? errors : nil
114
+ end
115
+
116
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::RuleRunner
4
+ include Dotum::RuleDSL
5
+
6
+ def self.eval(context, *args, &block)
7
+ new(context).instance_eval(*args, &block)
8
+ end
9
+
10
+ def initialize(context)
11
+ @context = context
12
+ end
13
+
14
+ attr_reader :context
15
+
16
+ end