bananajour 2.1.9
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +66 -0
- data/Readme.md +86 -0
- data/bin/bananajour +58 -0
- data/lib/bananajour.rb +99 -0
- data/lib/bananajour/bonjour.rb +9 -0
- data/lib/bananajour/bonjour/advertiser.rb +57 -0
- data/lib/bananajour/bonjour/bananajour_browser.rb +24 -0
- data/lib/bananajour/bonjour/browser.rb +52 -0
- data/lib/bananajour/bonjour/person.rb +21 -0
- data/lib/bananajour/bonjour/repository.rb +39 -0
- data/lib/bananajour/bonjour/repository_browser.rb +36 -0
- data/lib/bananajour/commands.rb +80 -0
- data/lib/bananajour/gem_dependencies.rb +34 -0
- data/lib/bananajour/grit_extensions.rb +11 -0
- data/lib/bananajour/helpers.rb +100 -0
- data/lib/bananajour/repository.rb +85 -0
- data/lib/bananajour/version.rb +3 -0
- data/sinatra/app.rb +87 -0
- data/sinatra/lib/browsers.rb +2 -0
- data/sinatra/lib/diff_helpers.rb +92 -0
- data/sinatra/lib/mock_browsers.rb +55 -0
- data/sinatra/public/jquery-1.3.2.min.js +19 -0
- data/sinatra/public/loader.gif +0 -0
- data/sinatra/public/logo.png +0 -0
- data/sinatra/public/pbjt.swf +0 -0
- data/sinatra/public/peanut.png +0 -0
- data/sinatra/views/commit.haml +112 -0
- data/sinatra/views/home.haml +305 -0
- data/sinatra/views/layout.haml +119 -0
- data/sinatra/views/readme.haml +52 -0
- metadata +183 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
class Bananajour::Bonjour::Person
|
2
|
+
|
3
|
+
attr_accessor :name, :email, :uri , :gravatar
|
4
|
+
|
5
|
+
def initialize(name, email, uri, gravatar)
|
6
|
+
@name, @email, @uri, @gravatar = name, email, uri, gravatar
|
7
|
+
end
|
8
|
+
|
9
|
+
def ==(other)
|
10
|
+
self.uri == other.uri
|
11
|
+
end
|
12
|
+
|
13
|
+
def hash
|
14
|
+
to_hash.hash
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_hash
|
18
|
+
{"name" => name, "email" => email, "uri" => uri, "gravatar" => gravatar}
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class Bananajour::Bonjour::Repository
|
2
|
+
|
3
|
+
attr_accessor :name, :uri, :person
|
4
|
+
|
5
|
+
def initialize(name, uri, person)
|
6
|
+
@name, @uri, @person = name, uri, person
|
7
|
+
end
|
8
|
+
|
9
|
+
def html_id
|
10
|
+
Bananajour::Repository.html_id(name)
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(other)
|
14
|
+
self.uri == other.uri
|
15
|
+
end
|
16
|
+
|
17
|
+
def hash
|
18
|
+
to_hash.hash
|
19
|
+
end
|
20
|
+
|
21
|
+
def json_uri
|
22
|
+
"#{person.uri}#{name}.json"
|
23
|
+
end
|
24
|
+
|
25
|
+
def web_uri
|
26
|
+
"#{person.uri}##{html_id}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_hash
|
30
|
+
{
|
31
|
+
"name" => name,
|
32
|
+
"uri" => uri,
|
33
|
+
"json_uri" => json_uri,
|
34
|
+
"web_uri" => web_uri,
|
35
|
+
"person" => person.to_hash
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Bananajour::Bonjour
|
2
|
+
class RepositoryBrowser
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@browser = Browser.new('_bananajour._git._tcp')
|
6
|
+
end
|
7
|
+
|
8
|
+
def repositories
|
9
|
+
@browser.replies.map do |reply|
|
10
|
+
Repository.new(
|
11
|
+
reply.text_record["name"],
|
12
|
+
reply.text_record["uri"],
|
13
|
+
Person.new(
|
14
|
+
reply.text_record["bjour-name"],
|
15
|
+
reply.text_record["bjour-email"],
|
16
|
+
reply.text_record["bjour-uri"],
|
17
|
+
reply.text_record["bjour-gravatar"]
|
18
|
+
)
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def other_repositories
|
24
|
+
repositories.reject {|r| Bananajour.repositories.any? {|my_rep| my_rep.name == r.name}}
|
25
|
+
end
|
26
|
+
|
27
|
+
def repositories_similar_to(repository)
|
28
|
+
repositories.select {|r| r.name == repository.name}
|
29
|
+
end
|
30
|
+
|
31
|
+
def repositories_for(person)
|
32
|
+
repositories.select {|r| r.person == person}
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Bananajour::Commands
|
2
|
+
|
3
|
+
def check_git!
|
4
|
+
if (version = `git --version`.strip) =~ /git version 1\.[12345]/
|
5
|
+
abort "You have #{version}, you need at least 1.6"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def check_git_config!
|
10
|
+
config_message = lambda {|key, example| "You haven't set your #{key} in your git config yet. To set it: git config --global #{key} '#{example}'"}
|
11
|
+
abort(config_message["user.name", "My Name"]) if config.name.empty?
|
12
|
+
abort(config_message["user.email", "name@domain.com"]) if config.email.empty?
|
13
|
+
end
|
14
|
+
|
15
|
+
def serve_web!
|
16
|
+
fork { exec "/usr/bin/env ruby #{File.dirname(__FILE__)}/../../sinatra/app.rb -p #{web_port} -e production" }
|
17
|
+
puts "* Started " + web_uri.foreground(:yellow)
|
18
|
+
end
|
19
|
+
|
20
|
+
def serve_git!
|
21
|
+
fork { exec "git daemon --base-path=#{repositories_path} --export-all" }
|
22
|
+
puts "* Started " + "#{git_uri}".foreground(:yellow)
|
23
|
+
end
|
24
|
+
|
25
|
+
def advertise!
|
26
|
+
fork { Bananajour::Bonjour::Advertiser.new.go! }
|
27
|
+
end
|
28
|
+
|
29
|
+
def add!(dir, name = nil)
|
30
|
+
dir = Fancypath(dir)
|
31
|
+
|
32
|
+
unless dir.join(".git").directory?
|
33
|
+
abort "Can't init project #{dir}, no .git directory found."
|
34
|
+
end
|
35
|
+
|
36
|
+
if name.nil?
|
37
|
+
default_name = dir.basename.to_s
|
38
|
+
print "Project Name?".foreground(:yellow) + " [#{default_name}] "
|
39
|
+
name = (STDIN.gets || "").strip
|
40
|
+
name = default_name if name.empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
repo = Bananajour::Repository.for_name(name)
|
44
|
+
|
45
|
+
if repo.exists?
|
46
|
+
abort "You've already a project #{repo}."
|
47
|
+
end
|
48
|
+
|
49
|
+
repo.init!
|
50
|
+
Dir.chdir(dir) { `git remote add banana #{repo.path.expand_path}` }
|
51
|
+
puts init_success_message(repo.dirname)
|
52
|
+
|
53
|
+
repo
|
54
|
+
end
|
55
|
+
|
56
|
+
def init_success_message(repo_dirname)
|
57
|
+
plain_init_success_message(repo_dirname).gsub("git push banana master", "git push banana master".foreground(:yellow))
|
58
|
+
end
|
59
|
+
|
60
|
+
def plain_init_success_message(repo_dirname)
|
61
|
+
"Bananajour repository #{repo_dirname} initialised and remote banana added.\nNext: git push banana master"
|
62
|
+
end
|
63
|
+
|
64
|
+
def clone!(url, clone_name)
|
65
|
+
dir = clone_name || File.basename(url).chomp('.git')
|
66
|
+
|
67
|
+
if File.exists?(dir)
|
68
|
+
abort "Can't clone #{url} to #{dir}, the directory already exists."
|
69
|
+
end
|
70
|
+
|
71
|
+
`git clone #{url} #{dir}`
|
72
|
+
if $? != 0
|
73
|
+
abort "Failed to clone bananajour repository #{url} to #{dir}."
|
74
|
+
else
|
75
|
+
puts "Bananajour repository #{url} cloned to #{dir}."
|
76
|
+
add!(dir, dir)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Bananajour
|
2
|
+
# DRYs version number dependencies and provides a simple way require them
|
3
|
+
module GemDependencies
|
4
|
+
DEPENDENCIES = [
|
5
|
+
%w( sinatra 0.9.2 ),
|
6
|
+
%w( json 1.1.7 ),
|
7
|
+
%w( chrislloyd-fancypath 0.5.8 ),
|
8
|
+
%w( rainbow 1.0.1 ),
|
9
|
+
%w( mojombo-grit 1.1.1 ),
|
10
|
+
%w( dnssd 0.7.1 ),
|
11
|
+
%w( rack 1.0.0 ),
|
12
|
+
%w( thin 1.0.0 ),
|
13
|
+
%w( haml 2.0.9 ),
|
14
|
+
%w( activesupport 2.3.2 )
|
15
|
+
]
|
16
|
+
class Dependency < Struct.new(:name, :version)
|
17
|
+
def require_gem; gem name, version end
|
18
|
+
end
|
19
|
+
def self.all
|
20
|
+
DEPENDENCIES.map {|(name, version)| Dependency.new(name, version)}
|
21
|
+
end
|
22
|
+
def self.for_name(name)
|
23
|
+
all.find {|d| d.name == name }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.gem(name)
|
28
|
+
Bananajour::GemDependencies.for_name(name).require_gem
|
29
|
+
end
|
30
|
+
def self.require_gem(name, lib=nil)
|
31
|
+
self.gem(name)
|
32
|
+
Kernel.require(lib || name)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'md5'
|
2
|
+
|
3
|
+
module Bananajour
|
4
|
+
module GravatarHelpers
|
5
|
+
def gravatar
|
6
|
+
gravatar_uri(self.config.email)
|
7
|
+
end
|
8
|
+
def gravatar_uri(email)
|
9
|
+
"http://gravatar.com/avatar/#{MD5.md5(email)}.png"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Lifted from Rails
|
14
|
+
module DateHelpers
|
15
|
+
# Reports the approximate distance in time between two Time or Date objects or integers as seconds.
|
16
|
+
# Set <tt>include_seconds</tt> to true if you want more detailed approximations when distance < 1 min, 29 secs
|
17
|
+
# Distances are reported based on the following table:
|
18
|
+
#
|
19
|
+
# 0 <-> 29 secs # => less than a minute
|
20
|
+
# 30 secs <-> 1 min, 29 secs # => 1 minute
|
21
|
+
# 1 min, 30 secs <-> 44 mins, 29 secs # => [2..44] minutes
|
22
|
+
# 44 mins, 30 secs <-> 89 mins, 29 secs # => about 1 hour
|
23
|
+
# 89 mins, 29 secs <-> 23 hrs, 59 mins, 29 secs # => about [2..24] hours
|
24
|
+
# 23 hrs, 59 mins, 29 secs <-> 47 hrs, 59 mins, 29 secs # => 1 day
|
25
|
+
# 47 hrs, 59 mins, 29 secs <-> 29 days, 23 hrs, 59 mins, 29 secs # => [2..29] days
|
26
|
+
# 29 days, 23 hrs, 59 mins, 30 secs <-> 59 days, 23 hrs, 59 mins, 29 secs # => about 1 month
|
27
|
+
# 59 days, 23 hrs, 59 mins, 30 secs <-> 1 yr minus 1 sec # => [2..12] months
|
28
|
+
# 1 yr <-> 2 yrs minus 1 secs # => about 1 year
|
29
|
+
# 2 yrs <-> max time or date # => over [2..X] years
|
30
|
+
#
|
31
|
+
# With <tt>include_seconds</tt> = true and the difference < 1 minute 29 seconds:
|
32
|
+
# 0-4 secs # => less than 5 seconds
|
33
|
+
# 5-9 secs # => less than 10 seconds
|
34
|
+
# 10-19 secs # => less than 20 seconds
|
35
|
+
# 20-39 secs # => half a minute
|
36
|
+
# 40-59 secs # => less than a minute
|
37
|
+
# 60-89 secs # => 1 minute
|
38
|
+
#
|
39
|
+
# ==== Examples
|
40
|
+
# from_time = Time.now
|
41
|
+
# distance_of_time_in_words(from_time, from_time + 50.minutes) # => about 1 hour
|
42
|
+
# distance_of_time_in_words(from_time, 50.minutes.from_now) # => about 1 hour
|
43
|
+
# distance_of_time_in_words(from_time, from_time + 15.seconds) # => less than a minute
|
44
|
+
# distance_of_time_in_words(from_time, from_time + 15.seconds, true) # => less than 20 seconds
|
45
|
+
# distance_of_time_in_words(from_time, 3.years.from_now) # => over 3 years
|
46
|
+
# distance_of_time_in_words(from_time, from_time + 60.hours) # => about 3 days
|
47
|
+
# distance_of_time_in_words(from_time, from_time + 45.seconds, true) # => less than a minute
|
48
|
+
# distance_of_time_in_words(from_time, from_time - 45.seconds, true) # => less than a minute
|
49
|
+
# distance_of_time_in_words(from_time, 76.seconds.from_now) # => 1 minute
|
50
|
+
# distance_of_time_in_words(from_time, from_time + 1.year + 3.days) # => about 1 year
|
51
|
+
# distance_of_time_in_words(from_time, from_time + 4.years + 15.days + 30.minutes + 5.seconds) # => over 4 years
|
52
|
+
#
|
53
|
+
# to_time = Time.now + 6.years + 19.days
|
54
|
+
# distance_of_time_in_words(from_time, to_time, true) # => over 6 years
|
55
|
+
# distance_of_time_in_words(to_time, from_time, true) # => over 6 years
|
56
|
+
# distance_of_time_in_words(Time.now, Time.now) # => less than a minute
|
57
|
+
#
|
58
|
+
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)
|
59
|
+
from_time = from_time.to_time if from_time.respond_to?(:to_time)
|
60
|
+
to_time = to_time.to_time if to_time.respond_to?(:to_time)
|
61
|
+
distance_in_minutes = (((to_time - from_time).abs)/60).round
|
62
|
+
distance_in_seconds = ((to_time - from_time).abs).round
|
63
|
+
|
64
|
+
case distance_in_minutes
|
65
|
+
when 0..1
|
66
|
+
return (distance_in_minutes == 0) ? 'less than a minute' : '1 minute' unless include_seconds
|
67
|
+
case distance_in_seconds
|
68
|
+
when 0..4 then 'less than 5 seconds'
|
69
|
+
when 5..9 then 'less than 10 seconds'
|
70
|
+
when 10..19 then 'less than 20 seconds'
|
71
|
+
when 20..39 then 'half a minute'
|
72
|
+
when 40..59 then 'less than a minute'
|
73
|
+
else '1 minute'
|
74
|
+
end
|
75
|
+
|
76
|
+
when 2..44 then "#{distance_in_minutes} minutes"
|
77
|
+
when 45..89 then 'about 1 hour'
|
78
|
+
when 90..1439 then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
|
79
|
+
when 1440..2879 then '1 day'
|
80
|
+
when 2880..43199 then "#{(distance_in_minutes / 1440).round} days"
|
81
|
+
when 43200..86399 then 'about 1 month'
|
82
|
+
when 86400..525599 then "#{(distance_in_minutes / 43200).round} months"
|
83
|
+
when 525600..1051199 then 'about 1 year'
|
84
|
+
else "over #{(distance_in_minutes / 525600).round} years"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Like distance_of_time_in_words, but where <tt>to_time</tt> is fixed to <tt>Time.now</tt>.
|
89
|
+
#
|
90
|
+
# ==== Examples
|
91
|
+
# time_ago_in_words(3.minutes.from_now) # => 3 minutes
|
92
|
+
# time_ago_in_words(Time.now - 15.hours) # => 15 hours
|
93
|
+
# time_ago_in_words(Time.now) # => less than a minute
|
94
|
+
#
|
95
|
+
# from_time = Time.now - 3.days - 14.minutes - 25.seconds # => 3 days
|
96
|
+
def time_ago_in_words(from_time, include_seconds = false)
|
97
|
+
distance_of_time_in_words(from_time, Time.now, include_seconds)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
Bananajour.require_gem 'mojombo-grit', 'grit'
|
2
|
+
|
3
|
+
module Bananajour
|
4
|
+
class Repository
|
5
|
+
def self.for_name(name)
|
6
|
+
new(Bananajour.repositories_path.join(name + ".git"))
|
7
|
+
end
|
8
|
+
def self.html_id(name)
|
9
|
+
name.gsub(/[^A-Za-z-]+/, '').downcase
|
10
|
+
end
|
11
|
+
def initialize(path)
|
12
|
+
@path = Fancypath(path)
|
13
|
+
end
|
14
|
+
def ==(other)
|
15
|
+
other.respond_to?(:path) && self.path == other.path
|
16
|
+
end
|
17
|
+
attr_reader :path
|
18
|
+
def exists?
|
19
|
+
path.exists?
|
20
|
+
end
|
21
|
+
def init!
|
22
|
+
path.create_dir
|
23
|
+
Dir.chdir(path) { `git init --bare` }
|
24
|
+
end
|
25
|
+
def name
|
26
|
+
dirname.sub(".git",'')
|
27
|
+
end
|
28
|
+
def html_id
|
29
|
+
self.class.html_id(name)
|
30
|
+
end
|
31
|
+
def dirname
|
32
|
+
path.split.last.to_s
|
33
|
+
end
|
34
|
+
def to_s
|
35
|
+
name
|
36
|
+
end
|
37
|
+
def uri
|
38
|
+
Bananajour.git_uri + dirname
|
39
|
+
end
|
40
|
+
def web_uri
|
41
|
+
Bananajour.web_uri + "#" + html_id
|
42
|
+
end
|
43
|
+
def grit_repo
|
44
|
+
@grit_repo ||= Grit::Repo.new(path)
|
45
|
+
end
|
46
|
+
def recent_commits
|
47
|
+
@commits ||= grit_repo.commits(nil, 10)
|
48
|
+
end
|
49
|
+
def readme_file
|
50
|
+
grit_repo.tree.contents.find {|c| c.name =~ /readme/i}
|
51
|
+
end
|
52
|
+
def rendered_readme
|
53
|
+
case File.extname(readme_file.name)
|
54
|
+
when /\.md/i, /\.markdown/i
|
55
|
+
require 'rdiscount'
|
56
|
+
RDiscount.new(readme_file.data).to_html
|
57
|
+
when /\.textile/i
|
58
|
+
require 'redcloth'
|
59
|
+
RedCloth.new(readme_file.data).to_html(:textile)
|
60
|
+
end
|
61
|
+
rescue LoadError
|
62
|
+
""
|
63
|
+
end
|
64
|
+
def remove!
|
65
|
+
path.rmtree
|
66
|
+
end
|
67
|
+
def to_hash
|
68
|
+
heads = grit_repo.heads
|
69
|
+
{
|
70
|
+
"name" => name,
|
71
|
+
"html_friendly_name" => html_id, # TODO: Deprecate in v3. Renamed to html_id since 2.1.4
|
72
|
+
"html_id" => html_id,
|
73
|
+
"uri" => uri,
|
74
|
+
"heads" => heads.map {|h| h.name},
|
75
|
+
"recent_commits" => recent_commits.collect do |c|
|
76
|
+
c.to_hash.merge(
|
77
|
+
"head" => (head = heads.find {|h| h.commit == c}) && head.name,
|
78
|
+
"gravatar" => c.author.gravatar_uri
|
79
|
+
)
|
80
|
+
end,
|
81
|
+
"bananajour" => Bananajour.to_hash
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/sinatra/app.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
Thread.abort_on_exception = true
|
2
|
+
|
3
|
+
__DIR__ = File.dirname(__FILE__)
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
|
7
|
+
require "#{__DIR__}/../lib/bananajour"
|
8
|
+
|
9
|
+
Bananajour.require_gem 'rack'
|
10
|
+
|
11
|
+
# Must require 'sinatra' from this file for Sinatra's magic to pick up lots of free stuff
|
12
|
+
Bananajour::GemDependencies.for_name('sinatra').require_gem
|
13
|
+
require 'sinatra'
|
14
|
+
|
15
|
+
Bananajour.require_gem 'haml'
|
16
|
+
Bananajour.require_gem 'json'
|
17
|
+
|
18
|
+
Bananajour.gem 'activesupport'
|
19
|
+
require 'active_support/core_ext/enumerable'
|
20
|
+
require 'active_support/core_ext/array'
|
21
|
+
|
22
|
+
require 'forwardable' # Fix for issue #8 - Thin borking on uninitialized constant Forwardable
|
23
|
+
|
24
|
+
set :server, 'thin' # Things go weird with anything else - let's lock it down to thin
|
25
|
+
set :haml, {:format => :html5, :attr_wrapper => '"'}
|
26
|
+
set :logging, false
|
27
|
+
|
28
|
+
require "#{__DIR__}/lib/browsers" # to prevent reloading
|
29
|
+
require "#{__DIR__}/lib/mock_browsers" if Sinatra::Application.development?
|
30
|
+
before do
|
31
|
+
@bananajour_browser = BANANAJOUR_BROWSER
|
32
|
+
@repository_browser = REPO_BROWSER
|
33
|
+
end
|
34
|
+
|
35
|
+
load "#{__DIR__}/lib/diff_helpers.rb"
|
36
|
+
helpers DiffHelpers
|
37
|
+
|
38
|
+
require "bananajour/helpers"
|
39
|
+
helpers Bananajour::GravatarHelpers, Bananajour::DateHelpers
|
40
|
+
|
41
|
+
helpers do
|
42
|
+
def json(body)
|
43
|
+
content_type "application/json"
|
44
|
+
params[:callback] ? "#{params[:callback]}(#{body});" : body
|
45
|
+
end
|
46
|
+
def local?
|
47
|
+
[
|
48
|
+
"0.0.0.0",
|
49
|
+
"127.0.0.1",
|
50
|
+
Socket.getaddrinfo(request.env["SERVER_NAME"], nil).map {|a| a[3]}
|
51
|
+
].flatten.include? request.env["REMOTE_ADDR"]
|
52
|
+
end
|
53
|
+
def pluralize(number, singular, plural)
|
54
|
+
"#{number} #{number == 1 ? singular : plural}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
get "/" do
|
59
|
+
@my_repositories = Bananajour.repositories
|
60
|
+
@other_repos_by_name = @repository_browser.other_repositories.group_by {|r| r.name}
|
61
|
+
@people = @bananajour_browser.other_bananajours
|
62
|
+
haml :home
|
63
|
+
end
|
64
|
+
|
65
|
+
get "/:repository/readme" do
|
66
|
+
@repository = Bananajour::Repository.for_name(params[:repository])
|
67
|
+
readme_file = @repository.readme_file
|
68
|
+
@rendered_readme = @repository.rendered_readme
|
69
|
+
@plain_readme = readme_file.data
|
70
|
+
haml :readme
|
71
|
+
end
|
72
|
+
|
73
|
+
get "/:repository/:commit" do
|
74
|
+
@repository = Bananajour::Repository.for_name(params[:repository])
|
75
|
+
@commit = @repository.grit_repo.commit(params[:commit])
|
76
|
+
haml :commit
|
77
|
+
end
|
78
|
+
|
79
|
+
get "/index.json" do
|
80
|
+
json Bananajour.to_hash.to_json
|
81
|
+
end
|
82
|
+
|
83
|
+
get "/:repository.json" do
|
84
|
+
response = Bananajour::Repository.for_name(params[:repository]).to_hash
|
85
|
+
response["recent_commits"].map! { |c| c["committed_date_pretty"] = time_ago_in_words(Time.parse(c["committed_date"])).gsub("about ","") + " ago"; c }
|
86
|
+
json response.to_json
|
87
|
+
end
|