gorp 0.16.0 → 0.16.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +9 -0
- data/gorp.gemspec +1 -1
- data/lib/gorp.rb +2 -266
- data/lib/gorp/edit.rb +64 -44
- data/lib/gorp/test.rb +12 -8
- data/lib/version.rb +1 -1
- metadata +1 -1
data/Manifest
CHANGED
data/gorp.gemspec
CHANGED
data/lib/gorp.rb
CHANGED
@@ -5,14 +5,13 @@
|
|
5
5
|
|
6
6
|
require 'fileutils'
|
7
7
|
require 'open3'
|
8
|
-
require 'net/http'
|
9
8
|
require 'builder'
|
10
|
-
require 'stringio'
|
11
9
|
require 'time'
|
12
|
-
require 'cgi'
|
13
10
|
|
14
11
|
require 'gorp/env'
|
15
12
|
require 'gorp/edit'
|
13
|
+
require 'gorp/net'
|
14
|
+
require 'gorp/rails'
|
16
15
|
|
17
16
|
require 'rbconfig'
|
18
17
|
$ruby = File.join(Config::CONFIG["bindir"], Config::CONFIG["RUBY_INSTALL_NAME"])
|
@@ -32,12 +31,6 @@ def section number, title, &steps
|
|
32
31
|
$sections << [number, title, steps]
|
33
32
|
end
|
34
33
|
|
35
|
-
# verify that port is available for testing
|
36
|
-
if (Net::HTTP.get_response('localhost','/',$PORT).code == '200' rescue false)
|
37
|
-
STDERR.puts "local server already running on port #{$PORT}"
|
38
|
-
exit
|
39
|
-
end
|
40
|
-
|
41
34
|
$x = Builder::XmlMarkup.new(:indent => 2)
|
42
35
|
$toc = Builder::XmlMarkup.new(:indent => 2)
|
43
36
|
$todos = Builder::XmlMarkup.new(:indent => 2)
|
@@ -289,263 +282,6 @@ rescue LoadError
|
|
289
282
|
Comment = REXML::Comment
|
290
283
|
end
|
291
284
|
|
292
|
-
def snap response, form=nil
|
293
|
-
if response.content_type == 'text/plain' or response.content_type =~ /xml/
|
294
|
-
$x.div :class => 'body' do
|
295
|
-
response.body.split("\n").each do |line|
|
296
|
-
$x.pre line.chomp, :class=>'stdout'
|
297
|
-
end
|
298
|
-
end
|
299
|
-
return
|
300
|
-
end
|
301
|
-
|
302
|
-
if response.body =~ /<body/
|
303
|
-
body = response.body
|
304
|
-
else
|
305
|
-
body = "<body>#{response.body}</body>"
|
306
|
-
end
|
307
|
-
|
308
|
-
begin
|
309
|
-
doc = xhtmlparse(body)
|
310
|
-
rescue
|
311
|
-
body.split("\n").each {|line| $x.pre line.chomp, :class=>'hilight'}
|
312
|
-
raise
|
313
|
-
end
|
314
|
-
|
315
|
-
title = doc.at('html/head/title').text rescue ''
|
316
|
-
body = doc.at('//body')
|
317
|
-
doc.search('//link[@rel="stylesheet"]').each do |sheet|
|
318
|
-
body.children.first.add_previous_sibling(sheet)
|
319
|
-
end
|
320
|
-
|
321
|
-
if form
|
322
|
-
body.search('//input[@name]').each do |input|
|
323
|
-
input['value'] ||= form[input['name']].to_s
|
324
|
-
end
|
325
|
-
body.search('//textarea[@name]').each do |textarea|
|
326
|
-
textarea.text = form[textarea['name']].to_s if textarea.text.to_s.empty?
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
%w{ a[@href] form[@action] }.each do |xpath|
|
331
|
-
name = xpath[/@(\w+)/,1]
|
332
|
-
body.search("//#{xpath}").each do |element|
|
333
|
-
next if element[name] =~ /^http:\/\//
|
334
|
-
element[name] = URI.join("http://localhost:#{$PORT}/", element[name]).to_s
|
335
|
-
end
|
336
|
-
end
|
337
|
-
|
338
|
-
%w{ img[@src] }.each do |xpath|
|
339
|
-
name = xpath[/@(\w+)/,1]
|
340
|
-
body.search("//#{xpath}").each do |element|
|
341
|
-
if element[name][0] == ?/
|
342
|
-
element[name] = 'data' + element[name]
|
343
|
-
end
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
body.search('//textarea').each do |element|
|
348
|
-
element.content=''
|
349
|
-
end
|
350
|
-
|
351
|
-
attrs = {:class => 'body', :title => title}
|
352
|
-
attrs[:class] = 'traceback' if response.code == '500'
|
353
|
-
attrs[:id] = body['id'] if body['id']
|
354
|
-
$x.div(attrs) do
|
355
|
-
body.children.each do |child|
|
356
|
-
$x << child.to_xml unless child.instance_of?(Comment)
|
357
|
-
end
|
358
|
-
end
|
359
|
-
$x.div '', :style => "clear: both"
|
360
|
-
end
|
361
|
-
|
362
|
-
def get path
|
363
|
-
post path, nil
|
364
|
-
end
|
365
|
-
|
366
|
-
def post path, form, options={}
|
367
|
-
$x.pre "get #{path}", :class=>'stdin' unless options[:snapget] == false
|
368
|
-
|
369
|
-
if path.include? ':'
|
370
|
-
host, port, path = URI.parse(path).select(:host, :port, :path)
|
371
|
-
else
|
372
|
-
host, port = '127.0.0.1', $PORT
|
373
|
-
end
|
374
|
-
|
375
|
-
Net::HTTP.start(host, port) do |http|
|
376
|
-
get = Net::HTTP::Get.new(path)
|
377
|
-
get['Cookie'] = $COOKIE if $COOKIE
|
378
|
-
response = http.request(get)
|
379
|
-
snap response, form unless options[:snapget] == false
|
380
|
-
$COOKIE = response.response['set-cookie'] if response.response['set-cookie']
|
381
|
-
|
382
|
-
if form
|
383
|
-
body = xhtmlparse(response.body).at('//body')
|
384
|
-
body = xhtmlparse(response.body).root unless body
|
385
|
-
xforms = body.search('//form')
|
386
|
-
|
387
|
-
# find matching button by action
|
388
|
-
xform = xforms.find do |element|
|
389
|
-
next unless element.attribute('action').to_s.include?('?')
|
390
|
-
query = CGI.parse(URI.parse(element.attribute('action').to_s).query)
|
391
|
-
query.all? {|key,values| values.include?(form[key].to_s)}
|
392
|
-
end
|
393
|
-
|
394
|
-
# find matching button by input names
|
395
|
-
xform ||= xforms.find do |element|
|
396
|
-
form.all? do |name, value|
|
397
|
-
element.search('.//input | .//textarea | ..//select').any? do |input|
|
398
|
-
input.attribute('name').to_s==name.to_s
|
399
|
-
end
|
400
|
-
end
|
401
|
-
end
|
402
|
-
|
403
|
-
# match based on action itself
|
404
|
-
xform ||= xforms.find do |element|
|
405
|
-
form.all? do |name, value|
|
406
|
-
element.attribute('action').to_s.include?(path)
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
|
-
# look for a commit button
|
411
|
-
xform ||= xforms.find {|element| element.at('.//input[@name="commit"]')}
|
412
|
-
|
413
|
-
return unless xform
|
414
|
-
|
415
|
-
path = xform.attribute('action').to_s unless
|
416
|
-
xform.attribute('action').to_s.empty?
|
417
|
-
$x.pre "post #{path}", :class=>'stdin'
|
418
|
-
|
419
|
-
$x.ul do
|
420
|
-
form.each do |name, value|
|
421
|
-
$x.li "#{name} => #{value}"
|
422
|
-
end
|
423
|
-
|
424
|
-
xform.search('.//input[@type="hidden"]').each do |element|
|
425
|
-
# $x.li "#{element['name']} => #{element['value']}"
|
426
|
-
form[element['name']] ||= element['value']
|
427
|
-
end
|
428
|
-
end
|
429
|
-
|
430
|
-
post = Net::HTTP::Post.new(path)
|
431
|
-
post.form_data = form
|
432
|
-
post['Cookie'] = $COOKIE
|
433
|
-
response=http.request(post)
|
434
|
-
snap response
|
435
|
-
end
|
436
|
-
|
437
|
-
if response.code == '302'
|
438
|
-
$COOKIE=response.response['set-cookie'] if response.response['set-cookie']
|
439
|
-
path = response['Location']
|
440
|
-
$x.pre "get #{path}", :class=>'stdin'
|
441
|
-
get = Net::HTTP::Get.new(path)
|
442
|
-
get['Cookie'] = $COOKIE if $COOKIE
|
443
|
-
response = http.request(get)
|
444
|
-
snap response
|
445
|
-
$COOKIE=response.response['set-cookie'] if response.response['set-cookie']
|
446
|
-
end
|
447
|
-
end
|
448
|
-
end
|
449
|
-
|
450
|
-
# select a version of Rails
|
451
|
-
if ARGV.first =~ /^_\d[.\d]*_$/
|
452
|
-
$rails = "rails #{ARGV.first}"
|
453
|
-
elsif File.directory?(ARGV.first.to_s)
|
454
|
-
$rails = ARGV.first
|
455
|
-
$rails = File.join($rails,'rails') if
|
456
|
-
File.directory?(File.join($rails,'rails'))
|
457
|
-
$rails = File.expand_path($rails)
|
458
|
-
else
|
459
|
-
$rails = 'rails'
|
460
|
-
end
|
461
|
-
|
462
|
-
def which_rails rails
|
463
|
-
railties = File.join(rails, 'railties', 'bin', 'rails')
|
464
|
-
rails = railties if File.exists?(railties)
|
465
|
-
if File.exists?(rails)
|
466
|
-
firstline = open(rails) {|file| file.readlines.first}
|
467
|
-
rails = 'ruby ' + rails unless firstline =~ /^#!/
|
468
|
-
end
|
469
|
-
rails
|
470
|
-
end
|
471
|
-
|
472
|
-
def rails name, app=nil
|
473
|
-
Dir.chdir($WORK)
|
474
|
-
FileUtils.rm_rf name
|
475
|
-
log :rails, name
|
476
|
-
|
477
|
-
# determine how to invoke rails
|
478
|
-
rails = which_rails $rails
|
479
|
-
|
480
|
-
$x.pre "#{rails} #{name}", :class=>'stdin'
|
481
|
-
popen3 "#{rails} #{name}"
|
482
|
-
|
483
|
-
# canonicalize the reference to Ruby
|
484
|
-
Dir["#{name}/script/**/*"].each do |script|
|
485
|
-
next if File.directory? script
|
486
|
-
code = open(script) {|file| file.read}
|
487
|
-
code.sub! /^#!.*/, '#!/usr/bin/env ruby'
|
488
|
-
open(script,'w') {|file| file.write code}
|
489
|
-
end
|
490
|
-
|
491
|
-
cmd "mkdir #{name}" unless File.exist?(name)
|
492
|
-
Dir.chdir(name)
|
493
|
-
FileUtils.rm_rf 'public/.htaccess'
|
494
|
-
|
495
|
-
cmd 'rake rails:freeze:edge' if ARGV.include? 'edge'
|
496
|
-
|
497
|
-
if $rails != 'rails' and File.directory?($rails)
|
498
|
-
cmd "mkdir vendor" unless File.exist?('vendor')
|
499
|
-
cmd "ln -s #{$rails} vendor/rails"
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
|
-
def restart_server
|
504
|
-
log :server, 'restart'
|
505
|
-
if $server
|
506
|
-
$x.h3 'Restart the server.'
|
507
|
-
Process.kill "INT", $server
|
508
|
-
Process.wait($server)
|
509
|
-
else
|
510
|
-
$x.h3 'Start the server.'
|
511
|
-
end
|
512
|
-
|
513
|
-
$server = fork
|
514
|
-
if $server
|
515
|
-
# wait for server to start
|
516
|
-
60.times do
|
517
|
-
sleep 0.5
|
518
|
-
begin
|
519
|
-
status = Net::HTTP.get_response('localhost','/',$PORT).code
|
520
|
-
break if %(200 404).include? status
|
521
|
-
rescue Errno::ECONNREFUSED
|
522
|
-
end
|
523
|
-
end
|
524
|
-
else
|
525
|
-
begin
|
526
|
-
if File.exist?('config.ru')
|
527
|
-
require 'rack'
|
528
|
-
server = Rack::Builder.new {eval open('config.ru').read}
|
529
|
-
Rack::Handler::WEBrick.run(server, :Port => $PORT)
|
530
|
-
else
|
531
|
-
# start server, redirecting stdout to a string
|
532
|
-
$stdout = StringIO.open('','w')
|
533
|
-
require './config/boot'
|
534
|
-
if Rails::VERSION::MAJOR == 2
|
535
|
-
require 'commands/server'
|
536
|
-
else
|
537
|
-
require 'rails/commands/server'
|
538
|
-
end
|
539
|
-
end
|
540
|
-
rescue
|
541
|
-
STDERR.puts $!
|
542
|
-
$!.backtrace.each {|method| STDERR.puts "\tfrom " + method}
|
543
|
-
ensure
|
544
|
-
Process.exit!
|
545
|
-
end
|
546
|
-
end
|
547
|
-
end
|
548
|
-
|
549
285
|
def secsplit section
|
550
286
|
section.to_s.split('.').map {|n| n.to_i}
|
551
287
|
end
|
data/lib/gorp/edit.rb
CHANGED
@@ -7,61 +7,81 @@ class String
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
module
|
11
|
-
|
12
|
-
|
13
|
-
self[
|
14
|
-
|
15
|
-
|
10
|
+
module Gorp
|
11
|
+
module StringEditingFunctions
|
12
|
+
def highlight
|
13
|
+
if self =~ /^\s*<[%!\w].*>/
|
14
|
+
start = '<!-- START_HIGHLIGHT -->'
|
15
|
+
close = '<!-- END_HIGHLIGHT -->'
|
16
|
+
else
|
17
|
+
start = '#START_HIGHLIGHT'
|
18
|
+
close = '#END_HIGHLIGHT'
|
19
|
+
end
|
20
|
+
|
21
|
+
if self =~ /\n\z/
|
22
|
+
self[/(.*)/m,1] = "#{start}\n#{self}#{close}\n"
|
23
|
+
else
|
24
|
+
self[/(.*)/m,1] = "#{start}\n#{self}\n#{close}"
|
25
|
+
end
|
16
26
|
end
|
17
|
-
end
|
18
27
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
28
|
+
def mark name
|
29
|
+
return unless name
|
30
|
+
|
31
|
+
if self =~ /^\s*<[%!\w].*>/
|
32
|
+
start = "<!-- START:#{name} -->"
|
33
|
+
close = "<!-- END:#{name} -->"
|
34
|
+
else
|
35
|
+
start = "#START:#{name}"
|
36
|
+
close = "#END:#{name}"
|
37
|
+
end
|
23
38
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
from = Regexp.new('.*' + Regexp.escape(from) + '.*')
|
39
|
+
if self =~ /\n\z/
|
40
|
+
self[/(.*)/m,1] = "#{start}\n#{self}#{close}\n"
|
41
|
+
else
|
42
|
+
self[/(.*)/m,1] = "#{start}\n#{self}\n#{close}"
|
43
|
+
end
|
30
44
|
end
|
31
45
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
base
|
46
|
+
def edit(from, *options)
|
47
|
+
if from.instance_of? String
|
48
|
+
from = Regexp.new('.*' + Regexp.escape(from) + '.*')
|
49
|
+
end
|
50
|
+
|
51
|
+
sub!(from) do |base|
|
52
|
+
base.extend Gorp::StringEditingFunctions
|
53
|
+
yield base if block_given?
|
54
|
+
base.highlight if options.include? :highlight
|
55
|
+
base.mark(options.last[:mark]) if options.last.respond_to? :key
|
56
|
+
base
|
57
|
+
end
|
38
58
|
end
|
39
|
-
end
|
40
59
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
60
|
+
def dcl(name, *options)
|
61
|
+
self.sub!(/(\s*)(class|def|test)\s+"?#{name}"?.*?\n\1end\n/mo) do |lines|
|
62
|
+
lines.extend Gorp::StringEditingFunctions
|
63
|
+
yield lines
|
64
|
+
lines.mark(options.last[:mark]) if options.last.respond_to? :[]
|
65
|
+
lines
|
66
|
+
end
|
47
67
|
end
|
48
|
-
end
|
49
68
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
69
|
+
def clear_highlights
|
70
|
+
self.gsub! /^\s*(#|<!--)\s*(START|END)_HIGHLIGHT(\s*-->)?\n/, ''
|
71
|
+
self.gsub! /^\s*(#|<!--)\s*(START|END)_HIGHLIGHT(\s*-->)?\n/, ''
|
72
|
+
end
|
54
73
|
|
55
|
-
|
56
|
-
|
57
|
-
|
74
|
+
def clear_all_marks
|
75
|
+
self.gsub! /^ *#\s?(START|END)(_HIGHLIGHT|:\w+)\n/, ''
|
76
|
+
end
|
58
77
|
|
59
|
-
|
60
|
-
|
61
|
-
|
78
|
+
def msub pattern, replacement
|
79
|
+
self[pattern, 1] = replacement
|
80
|
+
end
|
62
81
|
|
63
|
-
|
64
|
-
|
82
|
+
def all=replacement
|
83
|
+
self[/(.*)/m,1]=replacement
|
84
|
+
end
|
65
85
|
end
|
66
86
|
end
|
67
87
|
|
@@ -73,7 +93,7 @@ def edit filename, tag=nil
|
|
73
93
|
before = data.split("\n")
|
74
94
|
|
75
95
|
begin
|
76
|
-
data.extend
|
96
|
+
data.extend Gorp::StringEditingFunctions
|
77
97
|
yield data
|
78
98
|
|
79
99
|
now = Time.now
|
data/lib/gorp/test.rb
CHANGED
@@ -34,7 +34,18 @@ class Book::TestCase < ActiveSupport::TestCase
|
|
34
34
|
return if @@omit.include? number.to_s
|
35
35
|
test "#{number} #{title}" do
|
36
36
|
instance_eval {select number}
|
37
|
-
|
37
|
+
begin
|
38
|
+
instance_eval &tests
|
39
|
+
ensure
|
40
|
+
unless $!.instance_of? RuntimeError
|
41
|
+
@raw =~ /<pre\sclass="stdin">edit\s([\w\/.]+)<\/pre>\s+
|
42
|
+
<pre\sclass="traceback">\s+
|
43
|
+
\#<IndexError:\sregexp\snot\smatched>\s+
|
44
|
+
(.*gorp\/lib\/gorp\/edit.rb.*\n\s+)*
|
45
|
+
([\w\/.]+:\d+)/x
|
46
|
+
fail "Edit #{$1} failed at #{$3}" if $1
|
47
|
+
end
|
48
|
+
end
|
38
49
|
end
|
39
50
|
end
|
40
51
|
|
@@ -91,13 +102,6 @@ class Book::TestCase < ActiveSupport::TestCase
|
|
91
102
|
raise "Section #{number} not found" unless @@sections.has_key? number.to_s
|
92
103
|
@raw = @@sections[number.to_s]
|
93
104
|
@selected = HTML::Document.new(@raw).root.children
|
94
|
-
|
95
|
-
@raw =~ /<pre\sclass="stdin">edit\s([\w\/.]+)<\/pre>\s+
|
96
|
-
<pre\sclass="traceback">\s+
|
97
|
-
\#<IndexError:\sregexp\snot\smatched>\s+
|
98
|
-
(.*gorp\/lib\/gorp\/edit.rb.*\n\s+)*
|
99
|
-
([\w\/.]+:\d+)/x
|
100
|
-
fail "Edit #{$1} failed at #{$3}" if $1
|
101
105
|
end
|
102
106
|
|
103
107
|
attr_reader :raw
|
data/lib/version.rb
CHANGED