asha79-rack_revision_info 0.3.2

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.
@@ -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
+