asha79-rack_revision_info 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,87 @@
1
+ module Rack
2
+ class RevisionInfo
3
+ INJECT_ACTIONS = [:after, :before, :append, :prepend, :swap, :inner_html]
4
+
5
+ def initialize(app, opts={})
6
+ @app = app
7
+ path = opts[:path] or raise ArgumentError, "You must specify directory of your local repository!"
8
+ revision, date = get_revision_info(path, opts)
9
+ @revision_info = "#{get_revision_label(opts)} #{revision || 'unknown'}"
10
+ @revision_info << " (#{date.strftime(get_date_format(opts))})" if date
11
+ @action = (opts.keys & INJECT_ACTIONS).first
12
+ if @action
13
+ require 'hpricot'
14
+ @selector = opts[@action]
15
+ end
16
+ end
17
+
18
+ def call(env)
19
+ status, headers, body = @app.call(env)
20
+ if headers['Content-Type'].include?('text/html') && !Rack::Request.new(env).xhr?
21
+ html = ""
22
+ body.each { |s| html << s }
23
+ body = html
24
+ begin
25
+ if @action
26
+ doc = Hpricot(body)
27
+ elements = doc.search(@selector).compact
28
+ if elements.size > 0
29
+ elements = elements.first if @action == :swap
30
+ elements.send(@action, @revision_info)
31
+ body = doc.to_s
32
+ end
33
+ end
34
+ rescue => e
35
+ puts e
36
+ puts e.backtrace
37
+ end
38
+ body << %(\n<!-- #{@revision_info} -->\n)
39
+ body = [body]
40
+ end
41
+ [status, headers, body]
42
+ end
43
+
44
+ protected
45
+
46
+ def get_revision_label(opts={})
47
+ revision_label = 'Revision'
48
+ unless opts[:revision_label].nil?
49
+ revision_label = opts[:revision_label]
50
+ end
51
+ end
52
+
53
+ def get_date_format(opts={})
54
+ date_format = "%Y-%m-%d %H:%M:%S %Z"
55
+ unless opts[:date_format].nil?
56
+ date_format = opts[:date_format]
57
+ end
58
+ end
59
+
60
+ def get_revision_info(path, opts={})
61
+ case detect_type(path)
62
+ when :git
63
+ revision_regex_extra = '+'
64
+ if not opts[:short_git_revisions].nil? and opts[:short_git_revisions]
65
+ revision_regex_extra = '{8}'
66
+ end
67
+ info = `cd #{path}; LC_ALL=C git log -1 --pretty=medium`
68
+ revision = info[/commit\s([a-z0-9]#{revision_regex_extra})/, 1]
69
+ date = (d = info[/Date:\s+(.+)$/, 1]) && (DateTime.parse(d) rescue nil)
70
+ when :svn
71
+ info = `cd #{path}; LC_ALL=C svn info`
72
+ revision = info[/Revision:\s(\d+)$/, 1]
73
+ date = (d = info[/Last Changed Date:\s([^\(]+)/, 1]) && (DateTime.parse(d.strip) rescue nil)
74
+ else
75
+ revision, date = nil, nil
76
+ end
77
+ [revision, date]
78
+ end
79
+
80
+ def detect_type(path)
81
+ return :git if ::File.directory?(::File.join(path, ".git"))
82
+ return :svn if ::File.directory?(::File.join(path, ".svn"))
83
+ :unknown
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,102 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'rack/builder'
4
+ require 'rack/mock'
5
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'rack_revision_info.rb')
6
+
7
+ class Rack::RevisionInfo
8
+ DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S %Z"
9
+ def get_revision_info(path, opts={})
10
+ [(opts[:short_git_revisions] ? SHORT_GIT_REV : REV), DATE]
11
+ end
12
+ def get_revision_label(opts={})
13
+ opts[:revision_label] or REV_LABEL
14
+ end
15
+ def get_date_format(opts={})
16
+ opts[:date_format] or DATETIME_FORMAT
17
+ end
18
+ end
19
+
20
+ describe "Rack::RevisionInfo" do
21
+ REV = "a4jf64jf4hff"
22
+ SHORT_GIT_REV = "a4jf64jf"
23
+ REV_LABEL = "Revision"
24
+ DATE = DateTime.now
25
+
26
+ it "should append revision info in html comment" do
27
+ app = Rack::Builder.new do
28
+ use Rack::RevisionInfo, :path => "/some/path/to/repo"
29
+ run lambda { |env| [200, { 'Content-Type' => 'text/html' }, ["<html><head></head><body>Hello, World!</body></html>"]] }
30
+ end
31
+ response = Rack::MockRequest.new(app).get('/')
32
+ response.body.should match(/#{Regexp.escape("<!-- Revision #{REV} (#{DATE.strftime(Rack::RevisionInfo::DATETIME_FORMAT)}) -->")}/)
33
+ end
34
+
35
+ it "should append customised revision info in html comment" do
36
+ custom_date_format = "%d-%m-%Y %H:%M:%S"
37
+ app = Rack::Builder.new do
38
+ use Rack::RevisionInfo, :path => "/some/path/to/repo", :revision_label => "Rev", :date_format => custom_date_format
39
+ run lambda { |env| [200, { 'Content-Type' => 'text/html' }, ["<html><head></head><body>Hello, World!</body></html>"]] }
40
+ end
41
+ response = Rack::MockRequest.new(app).get('/')
42
+ response.body.should match(/#{Regexp.escape("<!-- Rev #{REV} (#{DATE.strftime(custom_date_format)}) -->")}/)
43
+ end
44
+
45
+ it "should append customised git specific revision info in html comment" do
46
+ custom_date_format = "%d-%m-%Y %H:%M:%S"
47
+ app = Rack::Builder.new do
48
+ use Rack::RevisionInfo, :path => "/some/path/to/repo", :revision_label => "Rev", :date_format => custom_date_format, :short_git_revisions => true
49
+ run lambda { |env| [200, { 'Content-Type' => 'text/html' }, ["<html><head></head><body>Hello, World!</body></html>"]] }
50
+ end
51
+ response = Rack::MockRequest.new(app).get('/')
52
+ response.body.should match(/#{Regexp.escape("<!-- Rev #{SHORT_GIT_REV} (#{DATE.strftime(custom_date_format)}) -->")}/)
53
+ end
54
+
55
+ it "shouldn't append revision info for non-html content-types" do
56
+ app = Rack::Builder.new do
57
+ use Rack::RevisionInfo, :path => "/some/path/to/repo"
58
+ run lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ["Hello, World!"]] }
59
+ end
60
+ response = Rack::MockRequest.new(app).get('/')
61
+ response.body.should_not match(/#{Regexp.escape('<!-- Revision ')}/)
62
+ end
63
+
64
+ it "shouldn't append revision info for xhr requests" do
65
+ app = Rack::Builder.new do
66
+ use Rack::RevisionInfo, :path => "/some/path/to/repo"
67
+ run lambda { |env| [200, { 'Content-Type' => 'text/html' }, ["<html><head></head><body>Hello, World!</body></html>"]] }
68
+ end
69
+ response = Rack::MockRequest.new(app).get('/', "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest")
70
+ response.body.should_not match(/#{Regexp.escape('<!-- Revision ')}/)
71
+ end
72
+
73
+ it "should raise exeption when no path given" do
74
+ app = Rack::Builder.new do
75
+ use Rack::RevisionInfo
76
+ run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
77
+ end
78
+ lambda do
79
+ response = Rack::MockRequest.new(app).get('/')
80
+ end.should raise_error(ArgumentError)
81
+ end
82
+
83
+ it "should inject revision info into DOM" do
84
+ Rack::RevisionInfo::INJECT_ACTIONS.each do |action|
85
+ app = Rack::Builder.new do
86
+ use Rack::RevisionInfo, :path => "/some/path/to/repo", action => "#footer"
87
+ run lambda { |env| [200, { 'Content-Type' => 'text/html' }, ["<html><head></head><body>Hello, World!<div id='footer'>Foota</div></body></html>"]] }
88
+ end
89
+ response = Rack::MockRequest.new(app).get('/')
90
+ response.body.should match(/#{Regexp.escape("Revision #{REV} (#{DATE.strftime(Rack::RevisionInfo::DATETIME_FORMAT)})")}.*#{Regexp.escape("</body>")}/)
91
+ end
92
+ end
93
+
94
+ it "shouldn't inject revision info into DOM if unknown action" do
95
+ app = Rack::Builder.new do
96
+ use Rack::RevisionInfo, :path => "/some/path/to/repo", :what_what => "#footer"
97
+ run lambda { |env| [200, { 'Content-Type' => 'text/html' }, ["<html><head></head><body>Hello, World!<div id='footer'>Foota</div></body></html>"]] }
98
+ end
99
+ response = Rack::MockRequest.new(app).get('/')
100
+ response.body.should_not match(/#{Regexp.escape("Revision #{REV} (#{DATE.strftime(Rack::RevisionInfo::DATETIME_FORMAT)})")}.*#{Regexp.escape("</body>")}/)
101
+ end
102
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: asha79-rack_revision_info
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.2
5
+ platform: ruby
6
+ authors:
7
+ - Marcin Kulik
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-18 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: marcin.kulik@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/rack_revision_info.rb
26
+ - spec/spec_rack_revision_info.rb
27
+ has_rdoc: false
28
+ homepage: http://sickill.net
29
+ post_install_message:
30
+ rdoc_options: []
31
+
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: "0"
39
+ version:
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ requirements: []
47
+
48
+ rubyforge_project:
49
+ rubygems_version: 1.2.0
50
+ signing_key:
51
+ specification_version: 2
52
+ summary: Rack middleware showing current git (or svn) revision number of application
53
+ test_files: []
54
+