corundum 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/doc/README +2 -0
  2. data/doc/Specifications +6 -0
  3. data/doc/coverage/assets/0.5.3/app.js +88 -0
  4. data/doc/coverage/assets/0.5.3/fancybox/blank.gif +0 -0
  5. data/doc/coverage/assets/0.5.3/fancybox/fancy_close.png +0 -0
  6. data/doc/coverage/assets/0.5.3/fancybox/fancy_loading.png +0 -0
  7. data/doc/coverage/assets/0.5.3/fancybox/fancy_nav_left.png +0 -0
  8. data/doc/coverage/assets/0.5.3/fancybox/fancy_nav_right.png +0 -0
  9. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_e.png +0 -0
  10. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_n.png +0 -0
  11. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png +0 -0
  12. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png +0 -0
  13. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_s.png +0 -0
  14. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_se.png +0 -0
  15. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png +0 -0
  16. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_w.png +0 -0
  17. data/doc/coverage/assets/0.5.3/fancybox/fancy_title_left.png +0 -0
  18. data/doc/coverage/assets/0.5.3/fancybox/fancy_title_main.png +0 -0
  19. data/doc/coverage/assets/0.5.3/fancybox/fancy_title_over.png +0 -0
  20. data/doc/coverage/assets/0.5.3/fancybox/fancy_title_right.png +0 -0
  21. data/doc/coverage/assets/0.5.3/fancybox/fancybox-x.png +0 -0
  22. data/doc/coverage/assets/0.5.3/fancybox/fancybox-y.png +0 -0
  23. data/doc/coverage/assets/0.5.3/fancybox/fancybox.png +0 -0
  24. data/doc/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css +363 -0
  25. data/doc/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js +44 -0
  26. data/doc/coverage/assets/0.5.3/favicon_green.png +0 -0
  27. data/doc/coverage/assets/0.5.3/favicon_red.png +0 -0
  28. data/doc/coverage/assets/0.5.3/favicon_yellow.png +0 -0
  29. data/doc/coverage/assets/0.5.3/highlight.css +129 -0
  30. data/doc/coverage/assets/0.5.3/highlight.pack.js +1 -0
  31. data/doc/coverage/assets/0.5.3/jquery-1.6.2.min.js +18 -0
  32. data/doc/coverage/assets/0.5.3/jquery.dataTables.min.js +152 -0
  33. data/doc/coverage/assets/0.5.3/jquery.timeago.js +141 -0
  34. data/doc/coverage/assets/0.5.3/jquery.url.js +174 -0
  35. data/doc/coverage/assets/0.5.3/loading.gif +0 -0
  36. data/doc/coverage/assets/0.5.3/magnify.png +0 -0
  37. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  38. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  39. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  40. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  41. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  42. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  43. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  44. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  45. data/doc/coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png +0 -0
  46. data/doc/coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  47. data/doc/coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png +0 -0
  48. data/doc/coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png +0 -0
  49. data/doc/coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  50. data/doc/coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css +295 -0
  51. data/doc/coverage/assets/0.5.3/stylesheet.css +383 -0
  52. data/doc/coverage/index.html +6511 -0
  53. data/lib/corundum.rb +130 -0
  54. data/lib/corundum/email.rb +92 -0
  55. data/lib/corundum/gem_building.rb +34 -0
  56. data/lib/corundum/gemcutter.rb +110 -0
  57. data/lib/corundum/gemspec_sanity.rb +32 -0
  58. data/lib/corundum/rspec.rb +135 -0
  59. data/lib/corundum/rubyforge.rb +95 -0
  60. data/lib/corundum/simplecov.rb +123 -0
  61. data/lib/corundum/tasklib.rb +57 -0
  62. data/lib/corundum/tasklibs.rb +8 -0
  63. data/lib/corundum/version_control.rb +36 -0
  64. data/lib/corundum/version_control/monotone.rb +126 -0
  65. data/lib/corundum/yardoc.rb +33 -0
  66. data/spec/bogus_spec.rb +3 -0
  67. data/spec/smoking_spec.rb +29 -0
  68. data/spec_help/file-sandbox.rb +164 -0
  69. data/spec_help/gem_test_suite.rb +17 -0
  70. data/spec_help/spec_helper.rb +4 -0
  71. data/spec_help/ungemmer.rb +36 -0
  72. metadata +292 -0
@@ -0,0 +1,95 @@
1
+ require 'corundum/tasklib'
2
+
3
+
4
+ #Big XXX: this totally isn't done. It's some notes against ever wanting to
5
+ #publish announcements to rubyforge ever again
6
+
7
+ module Corundum
8
+ class Publishing < TaskLib
9
+ def default_namespace
10
+ :email
11
+ end
12
+
13
+ def receive_tasklibs(toolkit)
14
+ @toolkit = toolkit
15
+ end
16
+
17
+ def default_configuration(namespace, toolkit_config)
18
+ end
19
+
20
+ def initialize(ns = :publish)
21
+ @ns = ns
22
+ @rubyforge = OpenStruct.new(:package_id => nil, :group_id => nil, :release_name => nil)
23
+ @package_dir = nil
24
+ @gemspec = nil
25
+ yield self if block_given?
26
+ define
27
+ end
28
+
29
+ attr_accessor :ns, :rubyforge, :package_dir, :gemspec
30
+
31
+ def define
32
+ desc "Publish the gem and its documentation to Rubyforge and Gemcutter"
33
+ task @ns => ["#{@ns.to_s}:docs", "#{@ns.to_s}:rubyforge"]
34
+
35
+ namespace @ns do
36
+ desc 'Publish RDoc to RubyForge'
37
+ task :docs do
38
+ config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
39
+ host = "#{config["username"]}@rubyforge.org"
40
+ remote_dir = "/var/www/gforge-projects/#{@rubyforge[:group_id]}"
41
+ local_dir = 'rubydoc'
42
+ sh %{rsync -av --delete #{local_dir}/ #{host}:#{remote_dir}}
43
+ end
44
+
45
+ task :scrape_rubyforge do
46
+ require 'rubyforge'
47
+ forge = RubyForge.new
48
+ forge.configure
49
+ forge.scrape_project(@rubyforge[:package_id])
50
+ end
51
+
52
+ desc "Publishes to RubyForge"
53
+ task :rubyforge => [:docs, :scrape_rubyforge] do |t|
54
+ require 'rubyforge'
55
+ forge = RubyForge.new
56
+ forge.configure
57
+ files = [".gem", ".tar.gz", ".tar.bz2"].map do |extension|
58
+ File::join(@package_dir, @gemspec.full_name) + extension
59
+ end
60
+ release = forge.lookup("release", @rubyforge[:package_id])[@rubyforge[:release_name]] rescue nil
61
+ if release.nil?
62
+ forge.add_release(@rubyforge[:group_id], @rubyforge[:package_id], @rubyforge[:release_name], *files)
63
+ else
64
+ files.each do |file|
65
+ forge.add_file(@rubyforge[:group_id], @rubyforge[:package_id], @rubyforge[:release_name], file)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+
75
+
76
+ module Corundum
77
+ class Email < TaskLib
78
+ def define
79
+ desc 'Announce release on RubyForge and email'
80
+ task @configuration.namespace => ["#{@configuration.namespace.to_s}:rubyforge", "#{@configuration.namespace.to_s}:email"]
81
+ namespace @configuration.namespace do
82
+ desc 'Post announcement to rubyforge.'
83
+ task :rubyforge do
84
+ require 'rubyforge'
85
+ subject, title, body = announcement
86
+
87
+ forge = RubyForge.new
88
+ forge.configure
89
+ forge.post_news(@configuration.rubyforge[:group_id], subject, "#{title}\n\n#{body}")
90
+ puts "Posted to rubyforge"
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,123 @@
1
+ require 'corundum/tasklib'
2
+
3
+ module Corundum
4
+ class SimpleCov < TaskLib
5
+ def default_namespace
6
+ :coverage
7
+ end
8
+
9
+ def default_configuration(namespace, toolkit_config, testlib_config)
10
+ @configuration.namespace = namespace
11
+ @configuration.test_lib = nil
12
+ @configuration.browser = toolkit_config.browser
13
+ @configuration.report_dir = "doc/coverage"
14
+ @configuration.report_path = nil
15
+ @configuration.config_file = ".simplecov"
16
+ @configuration.config_path = nil
17
+ @configuration.filters = ["./spec"]
18
+
19
+ @configuration.threshold = 80
20
+ @configuration.files = OpenStruct.new(
21
+ :code => toolkit_config.files.code
22
+ )
23
+ @configuration.groups = {}
24
+
25
+ @configuration.all_files = toolkit_config.file_lists.code + toolkit_config.file_lists.test
26
+ end
27
+
28
+ def resolve_configuration
29
+ @configuration.config_path ||= File::expand_path(@configuration.config_file, Rake::original_dir)
30
+ @configuration.report_path ||= File::join(@configuration.report_dir, "index.html")
31
+ end
32
+
33
+ def receive_tasklibs(toolkit, test_lib)
34
+ @toolkit,@test_lib = toolkit, test_lib
35
+ end
36
+
37
+ def filters
38
+ @configuration.filters.map do |pattern|
39
+ "add_filter \"#{pattern}\""
40
+ end
41
+ end
42
+
43
+ def groups
44
+ @configuration.groups.each_pair do |group, pattern|
45
+ "add_group \"#{group}\", \"#{pattern}\""
46
+ end
47
+ end
48
+
49
+ def config_file_contents
50
+ contents = ["SimpleCov.start do"]
51
+ contents << " coverage_dir \"#{@configuration.report_dir}\""
52
+ contents += filters.map{|line| " " + line}
53
+ contents += groups.map{|line| " " + line}
54
+ contents << "end"
55
+ return contents.join("\n")
56
+ end
57
+
58
+ def define
59
+ in_namespace do
60
+ file "Rakefile"
61
+
62
+ task :example_config do
63
+ $stderr.puts "Try this in #{@configuration.config_path}"
64
+ $stderr.puts
65
+ puts config_file_contents
66
+ end
67
+
68
+ task :config_exists do
69
+ File::exists?(File::join(Rake::original_dir, ".simplecov")) or fail "No .simplecov"
70
+ end
71
+
72
+ directory File::dirname(@configuration.report_path)
73
+ file @configuration.report_path => @configuration.all_files do
74
+ options = @test_lib.custom_options do |options|
75
+ options.rspec_opts += %w{-r simplecov}
76
+ end
77
+ sh @test_lib.full_command(options)
78
+ end
79
+
80
+ task :generate_report => [:preflight, @configuration.report_path]
81
+
82
+ desc "View coverage in browser"
83
+ task :view => :generate_report do
84
+ sh "#{@configuration.browser} #{@configuration.report_path}"
85
+ end
86
+
87
+ task :verify_coverage => :generate_report do
88
+ require 'nokogiri'
89
+
90
+ doc = Nokogiri::parse(File::read(@configuration.report_path))
91
+
92
+ coverage_total_xpath = "//span[@class='covered_percent']/span"
93
+ percentage = doc.xpath(coverage_total_xpath).first.content.to_f
94
+
95
+ raise "Coverage must be at least #{@configuration.threshold} but was #{percentage}" if percentage < @configuration.threshold
96
+ puts "Coverage is #{percentage}% (required: #{@configuration.threshold}%)"
97
+ end
98
+
99
+ task :find_stragglers => :generate_report do
100
+ require 'nokogiri'
101
+
102
+ doc = Nokogiri::parse(File::read(@configuration.report_path))
103
+
104
+ covered_files = doc.xpath(
105
+ "//table[@class='file_list']//td//a[@class='src_link']").map do |link|
106
+ link.content
107
+ end
108
+
109
+ not_listed = covered_files - @configuration.files.code
110
+ not_covered = @configuration.files.code - covered_files
111
+ unless not_listed.empty? and not_covered.empty?
112
+ raise ["Covered files and gemspec manifest don't match:",
113
+ "Not in gemspec: #{not_listed.inspect}",
114
+ "Not covered: #{not_covered.inspect}"].join("\n")
115
+ end
116
+ end
117
+ end
118
+ task :preflight => in_namespace(:config_exists)
119
+
120
+ task :qa => in_namespace(:verify_coverage, :find_stragglers)
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,57 @@
1
+ require 'ostruct'
2
+ require 'rake/tasklib'
3
+
4
+ module Corundum
5
+ class TaskLib < Rake::TaskLib
6
+ attr_accessor :configuration
7
+
8
+ def receive_tasklibs(*tasklibs)
9
+ end
10
+
11
+ def default_configuration(namespace, *tasklib_configs)
12
+ end
13
+
14
+ def resolve_configuration
15
+ end
16
+
17
+ def in_namespace(*tasknames)
18
+ if tasknames.empty?
19
+ if block_given?
20
+ if @configuration.namespace.nil?
21
+ yield
22
+ else
23
+ namespace @configuration.namespace do
24
+ yield
25
+ end
26
+ end
27
+ end
28
+ else
29
+ tasknames.map do |taskname|
30
+ [@configuration.namespace, taskname].compact.join(":")
31
+ end
32
+ end
33
+ end
34
+
35
+ def default_namespace
36
+ nil
37
+ end
38
+
39
+ def initialize(*tasklibs)
40
+ @configuration = OpenStruct.new(:namespace => default_namespace)
41
+
42
+ receive_tasklibs(*tasklibs)
43
+
44
+ configs = tasklibs.map do |tl|
45
+ tl.configuration
46
+ end
47
+ default_configuration(default_namespace, *configs)
48
+
49
+
50
+ yield @configuration if block_given?
51
+
52
+ resolve_configuration
53
+
54
+ define
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,8 @@
1
+ require 'corundum/rspec'
2
+ require 'corundum/simplecov'
3
+ require 'corundum/gemspec_sanity'
4
+ require 'corundum/gem_building'
5
+ require 'corundum/gemcutter'
6
+ require 'corundum/email'
7
+ require 'corundum/version_control/monotone'
8
+ require 'corundum/yardoc'
@@ -0,0 +1,36 @@
1
+ require 'corundum/tasklib'
2
+
3
+ module Corundum
4
+ class VersionControl < TaskLib
5
+ def default_namespace
6
+ :version_control
7
+ end
8
+
9
+ def receive_tasklibs(toolkit)
10
+ @toolkit = toolkit
11
+ end
12
+
13
+ def default_configuration(namespace, toolkit_config)
14
+ @configuration.namespace = namespace
15
+ @configuration.gemspec = toolkit_config.gemspec
16
+ @configuration.build_finished_file = toolkit_config.finished_files.build
17
+ @configuration.tag = toolkit_config.gemspec.version
18
+ end
19
+
20
+ def define
21
+ in_namespace do
22
+ task :not_tagged
23
+ task :is_checked_in
24
+ task :tag
25
+ task :check_in => :tag
26
+ end
27
+
28
+ task :preflight => in_namespace(:not_tagged)
29
+ task :build => in_namespace(:is_checked_in)
30
+ in_namespace(:tag, :check_in).each do |taskname|
31
+ task taskname => @configuration.build_finished_file
32
+ end
33
+ task :release => in_namespace(:tag, :check_in)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,126 @@
1
+ require 'corundum/version_control'
2
+ require 'strscan'
3
+
4
+ module Corundum
5
+ class Monotone < VersionControl
6
+ def default_namespace
7
+ :monotone
8
+ end
9
+
10
+ def default_configuration(*args)
11
+ super
12
+ @configuration.branch = nil
13
+ end
14
+
15
+ def resolve_configuration
16
+ @configuration.branch ||= guess_branch
17
+ end
18
+
19
+ def mtn_automate(cmd, *args)
20
+ result = ""
21
+ IO.popen("mtn automate #{cmd} #{args.join(" ")}") do |pipe|
22
+ result = pipe.read
23
+ end
24
+ result
25
+ end
26
+
27
+ def parse_basic_io(string)
28
+ items = []
29
+ scanner = StringScanner.new(string)
30
+ scanner.scan(/\s*/m)
31
+ until scanner.eos? do
32
+ symbol = scanner.scan(/[a-z_]*/)
33
+ scanner.scan(/\s*/)
34
+ value = ""
35
+ case scanner.scan(/["\[]/)
36
+ when '"'
37
+ while (value += scanner.scan(/[^"]*/)) =~ /\\$/
38
+ end
39
+ scanner.scan(/"/)
40
+ when '['
41
+ value = scanner.scan(/[^\]]*/)
42
+ scanner.scan(/]/)
43
+ else
44
+ raise "Improperly formatted basic_io: \
45
+ \n Got: #{items.inspect} + #{symbol}\
46
+ \n Rest:\
47
+ \n #{scanner.rest}"
48
+ end
49
+ items << [symbol, value]
50
+ scanner.scan(/\s*/m)
51
+ end
52
+ return items
53
+ end
54
+
55
+ def parse_certs(string)
56
+ items = parse_basic_io(string)
57
+ pair = []
58
+ hash = Hash.new do |h,k|
59
+ h[k] = []
60
+ end
61
+ items.each do |name, value|
62
+ case name
63
+ when "name"
64
+ pair[0] = value
65
+ when "value"
66
+ pair[1] = value
67
+ when "trust"
68
+ if value == "trusted"
69
+ hash[pair[0]] << pair[1]
70
+ end
71
+ pair = []
72
+ end
73
+ end
74
+ hash
75
+ end
76
+
77
+ def base_revision
78
+ mtn_automate("get_base_revision_id")
79
+ end
80
+
81
+ def guess_branch
82
+ puts "Guessing branch - configure Monotone > branch"
83
+ certs = parse_certs(mtn_automate("certs", base_revision))
84
+ puts " Guessed: #{certs["branch"].first}"
85
+ certs["branch"].first
86
+ end
87
+
88
+ def define
89
+ super
90
+
91
+ in_namespace do
92
+ task :not_tagged do
93
+ items = parse_basic_io(mtn_automate("tags", @configuration.branch))
94
+ tags = items.find{|pair| pair[0] == "tag" && pair[1] == @configuration.tag}
95
+ unless tags.nil?
96
+ fail "Tag #{@configuration.tag} already exists in branch #{@configuration.branch}"
97
+ end
98
+ end
99
+
100
+ task :is_committed do
101
+ items = parse_basic_io(mtn_automate("inventory"))
102
+ changed = items.find{|pair| pair[0] == "changes"}
103
+ unless changed.nil?
104
+ fail "Uncommitted changes exist in workspace"
105
+ end
106
+ end
107
+
108
+ task :tag do
109
+ mtn_automate("cert", base_revision, "tag", @configuration.tag)
110
+ end
111
+
112
+ task :commit do
113
+ run "mtn commit --branch #{@configuration.branch} --message \"Automatic commit: gem built at version #{@configuration.gemspec.version}\""
114
+ end
115
+
116
+ task :sync do
117
+ mtn_automate("sync")
118
+ end
119
+
120
+ task :check_in => %w{commit sync}
121
+
122
+ task :is_checked_in => [:is_committed]
123
+ end
124
+ end
125
+ end
126
+ end