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,5 @@
1
+ # encoding: utf-8
2
+
3
+ module Dotum::Rules
4
+ extend Dotum::AutoloadConvention
5
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::Rules::Cd < Dotum::AbstractRules::Base
4
+
5
+ # Special case; we don't accept an options block.
6
+ def initialize(context, destination, &block)
7
+ super(context)
8
+
9
+ @destination = @context.target_dir.join(destination)
10
+ @block = block
11
+ end
12
+
13
+ def pretty_subject
14
+ @destination.pretty
15
+ end
16
+
17
+ private
18
+
19
+ def execute
20
+ Dir.chdir(@destination, &@block)
21
+ end
22
+
23
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::Rules::Download < Dotum::AbstractRules::OptionsBase
4
+
5
+ shorthand :uri => :destination
6
+
7
+ required :uri
8
+ standard :destination
9
+ optional :mode
10
+ optional :owner
11
+ optional :group
12
+
13
+ def pretty_subject
14
+ "#{@destination.pretty} (#{@uri})"
15
+ end
16
+
17
+ private
18
+
19
+ def execute
20
+ if @destination.exists? && !@destination.file?
21
+ failure! "#{@destination} already exists and is not a file!"
22
+ end
23
+
24
+ # TODO: ETag support!
25
+ run "curl", "--output", @destination, @uri
26
+
27
+ run "chmod", @mode, @destination if @mode
28
+ run "chown", @owner, @destination if @owner
29
+ run "chgrp", @group, @destination if @group
30
+ end
31
+
32
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::Rules::Link < Dotum::AbstractRules::GlobbableFiles
4
+
5
+ private
6
+
7
+ def execute
8
+ link_path = @destination.symlink? ? @destination.link_path : nil
9
+
10
+ success! "Already linked" if link_path == @source
11
+ if @destination.exists?
12
+ if link_path
13
+ failure! "Target already exists as a symlink to #{link_path}"
14
+ else
15
+ failure! "Target already exists"
16
+ end
17
+ end
18
+
19
+ run "ln", "-s", @source, @destination
20
+ end
21
+
22
+ end
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::Rules::Repo < Dotum::AbstractRules::OptionsBase
4
+
5
+ shorthand :repo_uri => :destination
6
+
7
+ required :repo_uri
8
+ standard :destination
9
+ optional :branch
10
+
11
+ attr_reader :destination
12
+
13
+ def pretty_subject
14
+ @repo_uri
15
+ end
16
+
17
+ private
18
+
19
+ def execute
20
+ @destination ||= default_destination
21
+ @repo_exists = @destination.join(".git").directory?
22
+
23
+ if !is_local? && context.no_remote?
24
+ if @repo_exists
25
+ skip! "Remote interactions are disabled."
26
+ else
27
+ failure! "Remote interactions are disabled; cannot clone!"
28
+ end
29
+ end
30
+
31
+ if @repo_exists
32
+ update_repo
33
+ else
34
+ clone_repo
35
+ end
36
+ end
37
+
38
+ def clone_repo
39
+ command = ["git", "clone"]
40
+ command += ["--branch", @branch] if @branch
41
+ command += [@repo_uri, @destination]
42
+
43
+ run *command
44
+ end
45
+
46
+ def update_repo
47
+ cd @destination do
48
+ run "git", "add", "--all"
49
+ run "git", "commit", "--quiet", "--allow-empty", "--message", "Temporary Dotum Commit"
50
+ run "git", "pull", "--rebase"
51
+ run "git", "reset", "HEAD^"
52
+ end
53
+ end
54
+
55
+ def default_destination
56
+ basename = [@repo_uri, @branch].compact.join("-").gsub(/[\/:]+/, "-")
57
+
58
+ context.state_dir.join("repo", basename)
59
+ end
60
+
61
+ def is_local?
62
+ @repo_uri.start_with? "file://"
63
+ end
64
+
65
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ require "uri"
4
+
5
+ class Dotum::Rules::RequireExtension < Dotum::AbstractRules::OptionsBase
6
+
7
+ shorthand :extension_uri
8
+
9
+ required :extension_uri
10
+ optional :legacy
11
+ optional :branch
12
+
13
+ def pretty_subject
14
+ @extension_uri
15
+ end
16
+
17
+ private
18
+
19
+ def execute
20
+ # Does it look like a URI?
21
+ if URI.parse(@extension_uri).scheme
22
+ rule = repo @extension_uri, {:branch => @branch}
23
+ @destination = rule.destination
24
+ # Nope, we're just treating a local directory like a repo.
25
+ else
26
+ @destination = Dotum::Util::Path.new(@extension_uri)
27
+ end
28
+
29
+ failure! "Failed to clone repo to #{@destination}" unless @destination.directory?
30
+
31
+ # Dotum extensions are practically gems, but we don't want the overhead of
32
+ # building a gemspec. Also, `require_extension` is the only supported
33
+ # means of loading them. We don't want magic extensions to be already
34
+ # loaded via gems. Explicit is good here!
35
+
36
+ # So, just load all files in the extension and be done with it.
37
+ @destination.glob("lib/**/*.rb").each do |path|
38
+ Kernel.load(path)
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::Rules::Run < Dotum::AbstractRules::Base
4
+
5
+ def initialize(context, *command)
6
+ super(context)
7
+
8
+ @command = command
9
+ end
10
+
11
+ def pretty_subject
12
+ @command.join(" ")
13
+ end
14
+
15
+ private
16
+
17
+ def execute
18
+ Kernel.system(*@command)
19
+
20
+ failure! unless $?.success?
21
+ end
22
+
23
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ class Dotum::Rules::Use < Dotum::AbstractRules::OptionsBase
4
+
5
+ shorthand :path
6
+
7
+ required(:path) { |v| package_dir.join(v) }
8
+
9
+ def self.expand_options(context, options)
10
+ paths = context.package_dir.glob(options[:path], &:directory?)
11
+ paths.reject! &:hidden?
12
+
13
+ paths.map { |p| options.merge(:path => p) }
14
+ end
15
+
16
+ def pretty_subject
17
+ @path.pretty
18
+ end
19
+
20
+ private
21
+
22
+ def execute
23
+ failure! "Expected #{@path} to be a directory!" unless @path.directory?
24
+
25
+ rule_file = @path.join("rules.dotum")
26
+ rule_file = Dotum::DATA_PATH.join("default_rules.dotum") unless rule_file.file?
27
+
28
+ new_context = context.fork(:package_dir => @path)
29
+
30
+ Dotum::RuleRunner.eval(new_context, rule_file.read, rule_file)
31
+ end
32
+
33
+ end
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+
3
+ require "uri"
4
+
5
+ class Dotum::Rules::UseRepo < Dotum::AbstractRules::OptionsBase
6
+
7
+ shorthand :repo_uri
8
+
9
+ required :repo_uri
10
+ optional :legacy
11
+ optional :branch
12
+
13
+ def pretty_subject
14
+ @repo_uri
15
+ end
16
+
17
+ private
18
+
19
+ def execute
20
+ # Does it look like a URI?
21
+ if URI.parse(@repo_uri).scheme
22
+ rule = repo @repo_uri, {:branch => @branch}
23
+ @destination = rule.destination
24
+ # Nope, we're just treating a local directory like a repo.
25
+ else
26
+ @destination = Dotum::Util::Path.new(@repo_uri)
27
+ end
28
+
29
+ failure! "Failed to clone repo to #{@destination}" unless @destination.directory?
30
+ # We are now located within the repo.
31
+ @context = context.fork(:package_dir => @destination)
32
+
33
+ if @legacy
34
+ execute_legacy
35
+ else
36
+ execute_dotum
37
+ end
38
+ end
39
+
40
+ def execute_dotum
41
+ # Straight up `use` the repo if it is rooted with a `rules.dotum`.
42
+ if @destination.join('rules.dotum').file?
43
+ use "."
44
+
45
+ # Otherwise, this is a 'meta-package' that contains child packages.
46
+ else
47
+ @destination.relative_glob("*", &:directory?).each do |package_path|
48
+ use package_path
49
+ end
50
+ end
51
+ end
52
+
53
+ def execute_legacy
54
+ # In legacy mode, we just symlink everything
55
+ link "**/*"
56
+ end
57
+
58
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ module Dotum::StandardOptions
4
+ extend Dotum::AutoloadConvention
5
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ module Dotum::StandardOptions::Destination
4
+ extend Dotum::RuleOptionsDSL
5
+
6
+ optional(:destination) { |v| context.target_dir.join(v) }
7
+
8
+ def preprocess_for_destination
9
+ # It's required by the time you reach the preprocessing step; but not
10
+ # necessarily required for the shorthand.
11
+ failure! "Option 'destination' is required." if @destination.nil?
12
+
13
+ parent_dir = @destination.dirname
14
+ if parent_dir.exists? && !parent_dir.directory?
15
+ failure! "Parent path #{parent_dir} is not a directory; cannot write into it!"
16
+ end
17
+
18
+ run "mkdir", "-p", parent_dir unless parent_dir.directory?
19
+ end
20
+ register_preprocessor :preprocess_for_destination
21
+
22
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ module Dotum::Util
4
+ extend Dotum::AutoloadConvention
5
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ module Dotum::Util::ANSIColors
4
+
5
+ def ansi_color(text, code)
6
+ "\e[#{code}m#{text}\e[0m"
7
+ end
8
+
9
+ colors = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white]
10
+ colors.each_with_index do |color, i|
11
+ color_code = 30 + i
12
+
13
+ module_eval <<-end_eval, __FILE__, __LINE__
14
+
15
+ def c_#{color}(text)
16
+ ansi_color(text, "#{color_code}")
17
+ end
18
+
19
+ def c_bright_#{color}(text)
20
+ ansi_color(text, "#{color_code};1")
21
+ end
22
+
23
+ end_eval
24
+ end
25
+
26
+ end
@@ -0,0 +1,120 @@
1
+ # encoding: utf-8
2
+
3
+ require "fileutils"
4
+
5
+ # **Very** similar to `Pathname`.
6
+ class Dotum::Util::Path
7
+
8
+ ABSOLUTE_PATH_MATCHER = /^(~?\/|\w+\:\\)/
9
+
10
+ def initialize(path, relative=nil)
11
+ path = path.to_str.gsub(/[\/\\]/, File::Separator)
12
+
13
+ @path = File.expand_path(path, relative)
14
+ end
15
+
16
+ def join(*components)
17
+ (components.size - 1).downto(0) do |i|
18
+ # Do we have absolute paths? Stop at the last one.
19
+ if components[i].to_str =~ ABSOLUTE_PATH_MATCHER
20
+ return self.class.new(File.join(*components[i..-1]))
21
+ end
22
+ end
23
+
24
+ self.class.new(File.join(@path, *components))
25
+ end
26
+
27
+ def exists?
28
+ File.exist? @path
29
+ end
30
+
31
+ def file?
32
+ File.file? @path
33
+ end
34
+
35
+ def directory?
36
+ File.directory? @path
37
+ end
38
+
39
+ def symlink?
40
+ File.symlink? @path
41
+ end
42
+
43
+ def hidden?
44
+ File.split(@path).any? { |p| p.start_with? "." }
45
+ end
46
+
47
+ def link_path
48
+ self.class.new(File.readlink(@path))
49
+ end
50
+
51
+ def to_s
52
+ @path
53
+ end
54
+
55
+ def to_str
56
+ @path
57
+ end
58
+
59
+ def self.home_dir
60
+ @home_dir ||= File.expand_path("~")
61
+ end
62
+
63
+ def pretty
64
+ home_dir = File.expand_path("~")
65
+ if @path.start_with? home_dir
66
+ return "~" + @path[home_dir.size..-1]
67
+ end
68
+
69
+ @path
70
+ end
71
+
72
+ def read
73
+ File.read(@path)
74
+ end
75
+
76
+ def write(content)
77
+ File.open(@path, "w") do |file|
78
+ file.write(content)
79
+ end
80
+ end
81
+
82
+ def dirname
83
+ self.class.new(File.dirname(@path))
84
+ end
85
+
86
+ def basename
87
+ File.basename(@path)
88
+ end
89
+
90
+ def glob(expression, &filter)
91
+ matches = Dir.glob(join(expression), File::FNM_DOTMATCH)
92
+
93
+ if filter
94
+ matches.reject! { |p| !filter.call(self.class.new(p)) }
95
+ end
96
+
97
+ matches.reject! { |path|
98
+ basename = File.basename(path)
99
+
100
+ basename == "." || basename == ".."
101
+ }
102
+
103
+ matches.map { |p| self.class.new(p) }
104
+ end
105
+
106
+ def relative_glob(expression, &filter)
107
+ glob(expression, &filter).map { |path|
108
+ path.to_str[(@path.size + 1)..-1] || "."
109
+ }
110
+ end
111
+
112
+ def ==(other)
113
+ to_str == other.to_str
114
+ end
115
+
116
+ def mkpath!
117
+ FileUtils.mkpath(@path)
118
+ end
119
+
120
+ end