Skip to content

Instantly share code, notes, and snippets.

@ku1ik
Created September 23, 2009 10:12
Show Gist options
  • Save ku1ik/191894 to your computer and use it in GitHub Desktop.
Save ku1ik/191894 to your computer and use it in GitHub Desktop.
# Copyright 2009 Marcin Kulik (sickill)
require 'nokogiri'
module Rack
class RevisionInfo
INJECT_ACTIONS = [:after, :before, :append, :prepend, :swap, :inner_html]
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S %Z"
def initialize(app, opts={})
@app = app
path = opts[:path] or raise ArgumentError, "You must specify directory of your local repository!"
revision, date = get_revision_info(path)
@revision_info = "Revision #{revision || 'unknown'}"
@revision_info << " (#{date.strftime(DATETIME_FORMAT)})" if date
@action = (opts.keys & INJECT_ACTIONS).first
if @action
@selector = opts[@action]
@action = :inner_html= if @action == :inner_html
end
end
def call(env)
status, headers, body = @app.call(env)
if headers['Content-Type'].include?('text/html') && !Rack::Request.new(env).xhr?
html = ""
body.each { |s| html << s }
body = html
begin
if @action
doc = Nokogiri.parse(body)
elements = doc.css(@selector)
if elements.size > 0
elements.each { |e| e.send(@action, @revision_info) }
body = doc.to_s
end
end
rescue => e
puts e
puts e.backtrace
end
body << %(\n<!-- #{@revision_info} -->\n)
body = [body]
end
[status, headers, body]
end
protected
def get_revision_info(path)
case detect_type(path)
when :git
info = `cd #{path}; LC_ALL=C git log -1 --pretty=medium`
revision = info[/commit\s([a-z0-9]+)/, 1]
date = (d = info[/Date:\s+(.+)$/, 1]) && (DateTime.parse(d) rescue nil)
when :svn
info = `cd #{path}; LC_ALL=C svn info`
revision = info[/Revision:\s(\d+)$/, 1]
date = (d = info[/Last Changed Date:\s([^\(]+)/, 1]) && (DateTime.parse(d.strip) rescue nil)
else
revision, date = nil, nil
end
[revision, date]
end
def detect_type(path)
return :git if ::File.directory?(::File.join(path, ".git"))
return :svn if ::File.directory?(::File.join(path, ".svn"))
:unknown
end
end
end
# extending Nokogiri with 'append' and 'prepend' methods
class Nokogiri::XML::Element
def append(data)
self.inner_html = inner_html + data
end
def prepend(data)
self.inner_html = data + inner_html
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment