sparklines 0.4.0 → 0.4.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/CHANGELOG +7 -0
- data/Manifest.txt +7 -0
- data/Rakefile +17 -0
- data/lib/sparklines.rb +89 -19
- data/test/{all_test.rb → test_all.rb} +20 -1
- metadata +25 -15
- data/MIT-LICENSE +0 -21
- data/rakefile +0 -213
data/CHANGELOG
CHANGED
data/Manifest.txt
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'hoe'
|
4
|
+
$:.unshift(File.dirname(__FILE__) + "/lib")
|
5
|
+
require 'sparklines'
|
6
|
+
|
7
|
+
Hoe.new('Sparklines', Sparklines::VERSION) do |p|
|
8
|
+
p.name = "sparklines"
|
9
|
+
p.author = "Geoffrey Grosenbach"
|
10
|
+
p.description = "Tiny graphs."
|
11
|
+
p.email = 'boss@topfunky.com'
|
12
|
+
p.summary = "Tiny graphs."
|
13
|
+
p.url = "http://nubyonrails.com/pages/sparklines"
|
14
|
+
p.clean_globs = ['test/output/*']
|
15
|
+
|
16
|
+
# * extra_deps - An array of rubygem dependencies.
|
17
|
+
end
|
data/lib/sparklines.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'RMagick'
|
4
|
-
require 'mathn'
|
5
4
|
|
6
5
|
=begin rdoc
|
7
6
|
|
@@ -56,6 +55,7 @@ Graph types:
|
|
56
55
|
pie
|
57
56
|
smooth
|
58
57
|
bar
|
58
|
+
whisker
|
59
59
|
|
60
60
|
General Defaults:
|
61
61
|
|
@@ -74,7 +74,7 @@ Licensed under the MIT license.
|
|
74
74
|
=end
|
75
75
|
class Sparklines
|
76
76
|
|
77
|
-
VERSION = '0.4.
|
77
|
+
VERSION = '0.4.1'
|
78
78
|
|
79
79
|
@@label_margin = 5.0
|
80
80
|
@@pointsize = 10.0
|
@@ -109,7 +109,7 @@ class Sparklines
|
|
109
109
|
:label => nil
|
110
110
|
}
|
111
111
|
|
112
|
-
#
|
112
|
+
# HACK for HashWithIndifferentAccess
|
113
113
|
options_sym = Hash.new
|
114
114
|
options.keys.each do |key|
|
115
115
|
options_sym[key.to_sym] = options[key]
|
@@ -119,7 +119,7 @@ class Sparklines
|
|
119
119
|
|
120
120
|
# Call the appropriate method for actual plotting.
|
121
121
|
sparkline = self.new(data, options_sym)
|
122
|
-
if %w(area bar pie smooth discrete).include? options_sym[:type]
|
122
|
+
if %w(area bar pie smooth discrete whisker).include? options_sym[:type]
|
123
123
|
sparkline.send options_sym[:type]
|
124
124
|
else
|
125
125
|
sparkline.plot_error options_sym
|
@@ -133,7 +133,7 @@ class Sparklines
|
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
|
-
end
|
136
|
+
end # class methods
|
137
137
|
|
138
138
|
def initialize(data=[], options={})
|
139
139
|
@data = Array(data)
|
@@ -141,6 +141,7 @@ class Sparklines
|
|
141
141
|
normalize_data
|
142
142
|
end
|
143
143
|
|
144
|
+
##
|
144
145
|
# Creates a continuous area sparkline. Relevant options.
|
145
146
|
#
|
146
147
|
# :step - An integer that determines the distance between each point on the sparkline. Defaults to 2.
|
@@ -164,6 +165,7 @@ class Sparklines
|
|
164
165
|
# :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red.
|
165
166
|
#
|
166
167
|
# :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray.
|
168
|
+
|
167
169
|
def area
|
168
170
|
|
169
171
|
step = @options[:step].to_i
|
@@ -231,9 +233,9 @@ class Sparklines
|
|
231
233
|
@canvas.to_blob
|
232
234
|
end
|
233
235
|
|
236
|
+
##
|
237
|
+
# A bar graph.
|
234
238
|
|
235
|
-
# Draws a bar graph.
|
236
|
-
#
|
237
239
|
def bar
|
238
240
|
step = @options[:step].to_i
|
239
241
|
height = @options[:height].to_f
|
@@ -260,6 +262,7 @@ class Sparklines
|
|
260
262
|
end
|
261
263
|
|
262
264
|
|
265
|
+
##
|
263
266
|
# Creates a discretized sparkline
|
264
267
|
#
|
265
268
|
# :height - An integer that determines what the height of the sparkline will be. Defaults to 14
|
@@ -269,6 +272,7 @@ class Sparklines
|
|
269
272
|
# :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red.
|
270
273
|
#
|
271
274
|
# :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray.
|
275
|
+
|
272
276
|
def discrete
|
273
277
|
|
274
278
|
height = @options[:height].to_i
|
@@ -295,6 +299,7 @@ class Sparklines
|
|
295
299
|
end
|
296
300
|
|
297
301
|
|
302
|
+
##
|
298
303
|
# Creates a pie-chart sparkline
|
299
304
|
#
|
300
305
|
# :diameter - An integer that determines what the size of the sparkline will be. Defaults to 20
|
@@ -302,8 +307,8 @@ class Sparklines
|
|
302
307
|
# :share_color - A string or color code representing the color to draw the share of the pie represented by percent. Defaults to red.
|
303
308
|
#
|
304
309
|
# :remain_color - A string or color code representing the color to draw the pie not taken by the share color. Defaults to lightgrey.
|
305
|
-
def pie
|
306
310
|
|
311
|
+
def pie
|
307
312
|
diameter = @options[:diameter].to_i
|
308
313
|
background_color = @options[:background_color]
|
309
314
|
|
@@ -362,6 +367,7 @@ class Sparklines
|
|
362
367
|
end
|
363
368
|
|
364
369
|
|
370
|
+
##
|
365
371
|
# Creates a smooth sparkline.
|
366
372
|
#
|
367
373
|
# :step - An integer that determines the distance between each point on the sparkline. Defaults to 2.
|
@@ -379,6 +385,7 @@ class Sparklines
|
|
379
385
|
# :max_color - A string or color code representing the color that the dot drawn at the largest value will be displayed as. Defaults to green.
|
380
386
|
#
|
381
387
|
# :last_color - A string or color code representing the color that the dot drawn at the last value will be displayed as. Defaults to red.
|
388
|
+
|
382
389
|
def smooth
|
383
390
|
|
384
391
|
step = @options[:step].to_i
|
@@ -416,7 +423,65 @@ class Sparklines
|
|
416
423
|
end
|
417
424
|
|
418
425
|
|
426
|
+
##
|
427
|
+
# Creates a whisker sparkline to track on/off type data. There are five states:
|
428
|
+
# on, off, no value, exceptional on, exceptional off. On values create an up
|
429
|
+
# whisker and off values create a down whisker. Exceptional values may be
|
430
|
+
# colored differently than regular values to indicate, for example, a shut out.
|
431
|
+
# No value produces an empty row to indicate a tie.
|
432
|
+
#
|
433
|
+
# * results - an array of integer values between -2 and 2. -2 is exceptional
|
434
|
+
# down, 1 is regular down, 0 is no value, 1 is up, and 2 is exceptional up.
|
435
|
+
# * options - a hash that takes parameters
|
436
|
+
#
|
437
|
+
# :height - height of the sparkline
|
438
|
+
#
|
439
|
+
# :whisker_color - the color of regular whiskers; defaults to black
|
440
|
+
#
|
441
|
+
# :exception_color - the color of exceptional whiskers; defaults to red
|
442
|
+
|
443
|
+
def whisker
|
444
|
+
|
445
|
+
# step = @options[:step].to_i
|
446
|
+
height = @options[:height].to_i
|
447
|
+
background_color = @options[:background_color]
|
448
|
+
|
449
|
+
create_canvas((@data.size - 1) * 2, height, background_color)
|
450
|
+
|
451
|
+
whisker_color = @options[:whisker_color] || 'black'
|
452
|
+
exception_color = @options[:exception_color] || 'red'
|
453
|
+
|
454
|
+
i = 0
|
455
|
+
@data.each do |r|
|
456
|
+
color = whisker_color
|
457
|
+
|
458
|
+
if ( (r == 2 || r == -2) && exception_color )
|
459
|
+
color = exception_color
|
460
|
+
end
|
461
|
+
|
462
|
+
y_mid_point = (r >= 1) ? (@canvas.rows/2.0 - 1).ceil : (@canvas.rows/2.0).floor
|
463
|
+
|
464
|
+
y_end_point = y_mid_point
|
465
|
+
if ( r > 0)
|
466
|
+
y_end_point = 0
|
467
|
+
end
|
468
|
+
|
469
|
+
if ( r < 0 )
|
470
|
+
y_end_point = @canvas.rows
|
471
|
+
end
|
472
|
+
|
473
|
+
@draw.stroke( color )
|
474
|
+
@draw.line( i, y_mid_point, i, y_end_point )
|
475
|
+
i += 2
|
476
|
+
end
|
477
|
+
|
478
|
+
@draw.draw(@canvas)
|
479
|
+
@canvas.to_blob
|
480
|
+
end
|
481
|
+
|
482
|
+
##
|
419
483
|
# Draw the error Sparkline.
|
484
|
+
|
420
485
|
def plot_error(options={})
|
421
486
|
create_canvas(40, 15, 'white')
|
422
487
|
|
@@ -439,23 +504,27 @@ private
|
|
439
504
|
end
|
440
505
|
end
|
441
506
|
|
442
|
-
|
507
|
+
##
|
508
|
+
# * :arr - an array of points (represented as two element arrays)
|
509
|
+
|
443
510
|
def open_ended_polyline(arr)
|
444
511
|
0.upto(arr.length - 2) { |i|
|
445
512
|
@draw.line(arr[i][0], arr[i][1], arr[i+1][0], arr[i+1][1])
|
446
513
|
}
|
447
514
|
end
|
448
515
|
|
516
|
+
##
|
449
517
|
# Create an image to draw on and a drawable to do the drawing with.
|
450
518
|
#
|
451
|
-
# TODO Refactor into smaller
|
519
|
+
# TODO Refactor into smaller methods
|
520
|
+
|
452
521
|
def create_canvas(w, h, bkg_col)
|
453
522
|
@draw = Magick::Draw.new
|
454
523
|
@draw.pointsize = @@pointsize # TODO Use height
|
455
524
|
@canvas = Magick::Image.new(w , h) { self.background_color = bkg_col }
|
456
|
-
|
525
|
+
|
457
526
|
# Make room for label and last value
|
458
|
-
|
527
|
+
unless @options[:label].nil?
|
459
528
|
@options[:has_last] = true
|
460
529
|
@label_width = calculate_width(@options[:label])
|
461
530
|
@data_last_width = calculate_width(@data.last)
|
@@ -463,19 +532,19 @@ private
|
|
463
532
|
@label_and_data_last_width = @label_width + @data_last_width + @@label_margin * 7.0
|
464
533
|
w += @label_and_data_last_width
|
465
534
|
end
|
466
|
-
|
535
|
+
|
467
536
|
@canvas = Magick::Image.new(w , h) { self.background_color = bkg_col }
|
468
537
|
@canvas.format = "PNG"
|
469
|
-
|
538
|
+
|
470
539
|
# Draw label and last value
|
471
|
-
|
540
|
+
unless @options[:label].nil?
|
472
541
|
if ENV.has_key?('MAGICK_FONT_PATH')
|
473
542
|
vera_font_path = File.expand_path('Vera.ttf', ENV['MAGICK_FONT_PATH'])
|
474
543
|
@font = File.exists?(vera_font_path) ? vera_font_path : nil
|
475
544
|
else
|
476
545
|
@font = nil
|
477
546
|
end
|
478
|
-
|
547
|
+
|
479
548
|
@draw.fill = 'black'
|
480
549
|
@draw.font = @font if @font
|
481
550
|
@draw.gravity = Magick::WestGravity
|
@@ -483,7 +552,7 @@ private
|
|
483
552
|
@label_width, 1.0,
|
484
553
|
w - @label_and_data_last_width + @@label_margin, h - calculate_caps_height/2.0,
|
485
554
|
@options[:label])
|
486
|
-
|
555
|
+
|
487
556
|
@draw.fill = 'red'
|
488
557
|
@draw.annotate( @canvas,
|
489
558
|
@data_last_width, 1.0,
|
@@ -491,9 +560,11 @@ private
|
|
491
560
|
@data.last.to_s)
|
492
561
|
end
|
493
562
|
end
|
494
|
-
|
563
|
+
|
564
|
+
##
|
495
565
|
# Utility to draw a coloured box
|
496
566
|
# Centred on pt, offset off in each direction, fill color is col
|
567
|
+
|
497
568
|
def drawbox(pt, offset, color)
|
498
569
|
@draw.stroke 'transparent'
|
499
570
|
@draw.fill(color)
|
@@ -508,5 +579,4 @@ private
|
|
508
579
|
@draw.get_type_metrics(@canvas, 'X').height
|
509
580
|
end
|
510
581
|
|
511
|
-
|
512
582
|
end
|
@@ -21,10 +21,29 @@ class SparklinesTest < Test::Unit::TestCase
|
|
21
21
|
|
22
22
|
def test_each_graph_with_label
|
23
23
|
%w{pie area discrete smooth bar}.each do |type|
|
24
|
-
quick_graph("labeled_#{type}", :type => type, :label => '
|
24
|
+
quick_graph("labeled_#{type}", :type => type, :label => 'Glucose')
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
def test_whisker_random
|
29
|
+
# Need data ranging from -2 to +2
|
30
|
+
@data = (1..40).map { |i| rand(3) * (rand(2) == 1 ? -1 : 1) }
|
31
|
+
quick_graph("whisker", :type => 'whisker')
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_whisker_non_exceptional
|
35
|
+
@data = [1,1,1,1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]
|
36
|
+
quick_graph("whisker_non_exceptional", :type => 'whisker')
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Send random values in the range (-9..9)
|
41
|
+
|
42
|
+
def test_whisker_junk
|
43
|
+
@data = (1..40).map { |i| rand(10) * (rand(2) == 1 ? -1 : 1) }
|
44
|
+
quick_graph("whisker_junk", :type => 'whisker')
|
45
|
+
end
|
46
|
+
|
28
47
|
def test_pie
|
29
48
|
# Test extremes which previously did not work right
|
30
49
|
[0, 1, 45, 95, 99, 100].each do |value|
|
metadata
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.
|
2
|
+
rubygems_version: 0.9.0
|
3
3
|
specification_version: 1
|
4
4
|
name: sparklines
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.4.
|
7
|
-
date: 2006-
|
8
|
-
summary: Tiny graphs
|
6
|
+
version: 0.4.1
|
7
|
+
date: 2006-10-20 00:00:00 -07:00
|
8
|
+
summary: Tiny graphs.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
|
+
- test
|
11
12
|
email: boss@topfunky.com
|
12
|
-
homepage: http://
|
13
|
+
homepage: http://nubyonrails.com/pages/sparklines
|
13
14
|
rubyforge_project: sparklines
|
14
|
-
description:
|
15
|
-
autorequire:
|
15
|
+
description: Tiny graphs.
|
16
|
+
autorequire:
|
16
17
|
default_executable:
|
17
18
|
bindir: bin
|
18
19
|
has_rdoc: true
|
@@ -25,18 +26,19 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
26
|
platform: ruby
|
26
27
|
signing_key:
|
27
28
|
cert_chain:
|
29
|
+
post_install_message:
|
28
30
|
authors:
|
29
31
|
- Geoffrey Grosenbach
|
30
32
|
files:
|
31
|
-
-
|
33
|
+
- Rakefile
|
34
|
+
- Manifest.txt
|
32
35
|
- README
|
33
36
|
- CHANGELOG
|
34
|
-
- MIT-LICENSE
|
35
37
|
- lib/sparklines.rb
|
36
|
-
- test/
|
38
|
+
- test/test_all.rb
|
37
39
|
- test/output
|
38
|
-
test_files:
|
39
|
-
|
40
|
+
test_files:
|
41
|
+
- test/test_all.rb
|
40
42
|
rdoc_options: []
|
41
43
|
|
42
44
|
extra_rdoc_files: []
|
@@ -45,7 +47,15 @@ executables: []
|
|
45
47
|
|
46
48
|
extensions: []
|
47
49
|
|
48
|
-
requirements:
|
49
|
-
- none
|
50
|
-
dependencies: []
|
50
|
+
requirements: []
|
51
51
|
|
52
|
+
dependencies:
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: hoe
|
55
|
+
version_requirement:
|
56
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.1.1
|
61
|
+
version:
|
data/MIT-LICENSE
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
Copyright (c) 2005 Geoffrey Grosenbach boss@topfunky.com
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
a copy of this software and associated documentation files (the
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
included in all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
-
|
data/rakefile
DELETED
@@ -1,213 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rake'
|
3
|
-
require 'rake/testtask'
|
4
|
-
require 'rake/rdoctask'
|
5
|
-
require 'rake/packagetask'
|
6
|
-
require 'rake/gempackagetask'
|
7
|
-
require 'rake/contrib/rubyforgepublisher'
|
8
|
-
|
9
|
-
$:.unshift(File.dirname(__FILE__) + "/lib")
|
10
|
-
require 'sparklines'
|
11
|
-
|
12
|
-
PKG_NAME = 'sparklines'
|
13
|
-
PKG_VERSION = Sparklines::VERSION
|
14
|
-
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
15
|
-
|
16
|
-
RELEASE_NAME = "REL #{PKG_VERSION}"
|
17
|
-
|
18
|
-
RUBY_FORGE_PROJECT = "sparklines"
|
19
|
-
RUBY_FORGE_USER = "topfunky"
|
20
|
-
|
21
|
-
desc "Default Task"
|
22
|
-
task :default => [ :clean, :test ]
|
23
|
-
|
24
|
-
desc "Clean images generated by tests"
|
25
|
-
task :clean do
|
26
|
-
rm FileList['test/output/*.png']
|
27
|
-
rm_rf "pkg"
|
28
|
-
end
|
29
|
-
|
30
|
-
# Build a graphic file by running a single test.
|
31
|
-
#
|
32
|
-
# rake bar_extreme_values.png
|
33
|
-
# => Runs test_extreme_values
|
34
|
-
|
35
|
-
rule ".png" do |t|
|
36
|
-
test_name = t.name.gsub(/\.png/, '')
|
37
|
-
Rake::Task[:clean].invoke
|
38
|
-
sh "ruby -Ilib:test test/all_test.rb -n /^test_#{test_name}/"
|
39
|
-
end
|
40
|
-
|
41
|
-
# Run the unit tests
|
42
|
-
Rake::TestTask.new { |t|
|
43
|
-
t.libs << "test"
|
44
|
-
t.pattern = 'test/*_test.rb'
|
45
|
-
t.verbose = true
|
46
|
-
}
|
47
|
-
|
48
|
-
|
49
|
-
# Genereate the RDoc documentation
|
50
|
-
Rake::RDocTask.new { |rdoc|
|
51
|
-
rdoc.rdoc_dir = 'doc'
|
52
|
-
rdoc.title = "Sparklines -- Tiny graphs"
|
53
|
-
rdoc.options << '--line-numbers --inline-source --main README --accessor adv_attr_accessor=M'
|
54
|
-
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
55
|
-
rdoc.rdoc_files.include('README', 'CHANGELOG')
|
56
|
-
rdoc.rdoc_files.include('lib/sparklines.rb')
|
57
|
-
rdoc.rdoc_files.include('lib/sparklines/*.rb')
|
58
|
-
}
|
59
|
-
|
60
|
-
|
61
|
-
# Create compressed packages
|
62
|
-
spec = Gem::Specification.new do |s|
|
63
|
-
s.platform = Gem::Platform::RUBY
|
64
|
-
s.name = PKG_NAME
|
65
|
-
s.summary = "Tiny graphs for concise data."
|
66
|
-
s.description = %q{Make tiny graphs for use on websites or documents.}
|
67
|
-
s.version = PKG_VERSION
|
68
|
-
|
69
|
-
s.author = "Geoffrey Grosenbach"
|
70
|
-
s.email = "boss@topfunky.com"
|
71
|
-
s.rubyforge_project = RUBY_FORGE_PROJECT
|
72
|
-
s.homepage = "http://www.topfunky.com"
|
73
|
-
|
74
|
-
s.has_rdoc = true
|
75
|
-
s.requirements << 'none'
|
76
|
-
s.require_path = 'lib'
|
77
|
-
s.autorequire = 'gruff'
|
78
|
-
|
79
|
-
s.files = [ "rakefile", "README", "CHANGELOG", "MIT-LICENSE" ]
|
80
|
-
s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
81
|
-
s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) || item.include?("\.png") }
|
82
|
-
end
|
83
|
-
|
84
|
-
Rake::GemPackageTask.new(spec) do |p|
|
85
|
-
p.gem_spec = spec
|
86
|
-
p.need_tar = true
|
87
|
-
p.need_zip = true
|
88
|
-
end
|
89
|
-
|
90
|
-
desc "Hackish copy to sparklines plugin for Rails"
|
91
|
-
task :update_plugin do
|
92
|
-
cp "lib/sparklines.rb", "../plugins/sparklines/lib/sparklines.rb"
|
93
|
-
end
|
94
|
-
|
95
|
-
desc "Publish the API documentation"
|
96
|
-
task :pgem => [:package] do
|
97
|
-
Rake::SshFilePublisher.new("boss@topfunky.com", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
|
98
|
-
end
|
99
|
-
|
100
|
-
desc "Publish the release files to RubyForge."
|
101
|
-
task :release => [:package] do
|
102
|
-
files = ["gem", "tgz", "zip"].map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
|
103
|
-
|
104
|
-
if RUBY_FORGE_PROJECT then
|
105
|
-
require 'net/http'
|
106
|
-
require 'open-uri'
|
107
|
-
|
108
|
-
project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
|
109
|
-
project_data = open(project_uri) { |data| data.read }
|
110
|
-
group_id = project_data[/[?&]group_id=(\d+)/, 1]
|
111
|
-
raise "Couldn't get group id" unless group_id
|
112
|
-
|
113
|
-
# This echos password to shell which is a bit sucky
|
114
|
-
if ENV["RUBY_FORGE_PASSWORD"]
|
115
|
-
password = ENV["RUBY_FORGE_PASSWORD"]
|
116
|
-
else
|
117
|
-
print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
|
118
|
-
password = STDIN.gets.chomp
|
119
|
-
end
|
120
|
-
|
121
|
-
login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
122
|
-
data = [
|
123
|
-
"login=1",
|
124
|
-
"form_loginname=#{RUBY_FORGE_USER}",
|
125
|
-
"form_pw=#{password}"
|
126
|
-
].join("&")
|
127
|
-
http.post("/account/login.php", data)
|
128
|
-
end
|
129
|
-
|
130
|
-
cookie = login_response["set-cookie"]
|
131
|
-
raise "Login failed" unless cookie
|
132
|
-
headers = { "Cookie" => cookie }
|
133
|
-
|
134
|
-
release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
|
135
|
-
release_data = open(release_uri, headers) { |data| data.read }
|
136
|
-
package_id = release_data[/[?&]package_id=(\d+)/, 1]
|
137
|
-
raise "Couldn't get package id" unless package_id
|
138
|
-
|
139
|
-
first_file = true
|
140
|
-
release_id = ""
|
141
|
-
|
142
|
-
files.each do |filename|
|
143
|
-
basename = File.basename(filename)
|
144
|
-
file_ext = File.extname(filename)
|
145
|
-
file_data = File.open(filename, "rb") { |file| file.read }
|
146
|
-
|
147
|
-
puts "Releasing #{basename}..."
|
148
|
-
|
149
|
-
release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
150
|
-
release_date = Time.now.strftime("%Y-%m-%d %H:%M")
|
151
|
-
type_map = {
|
152
|
-
".zip" => "3000",
|
153
|
-
".tgz" => "3110",
|
154
|
-
".gz" => "3110",
|
155
|
-
".gem" => "1400"
|
156
|
-
}; type_map.default = "9999"
|
157
|
-
type = type_map[file_ext]
|
158
|
-
boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
|
159
|
-
|
160
|
-
query_hash = if first_file then
|
161
|
-
{
|
162
|
-
"group_id" => group_id,
|
163
|
-
"package_id" => package_id,
|
164
|
-
"release_name" => RELEASE_NAME,
|
165
|
-
"release_date" => release_date,
|
166
|
-
"type_id" => type,
|
167
|
-
"processor_id" => "8000", # Any
|
168
|
-
"release_notes" => "",
|
169
|
-
"release_changes" => "",
|
170
|
-
"preformatted" => "1",
|
171
|
-
"submit" => "1"
|
172
|
-
}
|
173
|
-
else
|
174
|
-
{
|
175
|
-
"group_id" => group_id,
|
176
|
-
"release_id" => release_id,
|
177
|
-
"package_id" => package_id,
|
178
|
-
"step2" => "1",
|
179
|
-
"type_id" => type,
|
180
|
-
"processor_id" => "8000", # Any
|
181
|
-
"submit" => "Add This File"
|
182
|
-
}
|
183
|
-
end
|
184
|
-
|
185
|
-
query = "?" + query_hash.map do |(name, value)|
|
186
|
-
[name, URI.encode(value)].join("=")
|
187
|
-
end.join("&")
|
188
|
-
|
189
|
-
data = [
|
190
|
-
"--" + boundary,
|
191
|
-
"Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
|
192
|
-
"Content-Type: application/octet-stream",
|
193
|
-
"Content-Transfer-Encoding: binary",
|
194
|
-
"", file_data, ""
|
195
|
-
].join("\x0D\x0A")
|
196
|
-
|
197
|
-
release_headers = headers.merge(
|
198
|
-
"Content-Type" => "multipart/form-data; boundary=#{boundary}"
|
199
|
-
)
|
200
|
-
|
201
|
-
target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
|
202
|
-
http.post(target + query, data, release_headers)
|
203
|
-
end
|
204
|
-
|
205
|
-
if first_file then
|
206
|
-
release_id = release_response.body[/release_id=(\d+)/, 1]
|
207
|
-
raise("Couldn't get release id") unless release_id
|
208
|
-
end
|
209
|
-
|
210
|
-
first_file = false
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|