Skip to content

Commit

Permalink
Added 'web' and 'browse' commands to serve and view repos via HTTP.
Browse files Browse the repository at this point in the history
  • Loading branch information
alexvollmer committed Mar 15, 2009
1 parent 60a8d13 commit bd843d2
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 356 deletions.
1 change: 1 addition & 0 deletions Manifest.txt
Expand Up @@ -4,5 +4,6 @@ README.txt
Rakefile
bin/gitjour
lib/gitjour.rb
lib/browser.rb
test/test_gitjour.rb
test/test_helper.rb
110 changes: 110 additions & 0 deletions lib/browser.rb
@@ -0,0 +1,110 @@
require "webrick"
require "erb"
require "set"
require "thread"

module Gitjour
class Browser

def initialize(*args)
@port = args.shift || 9850
@browser = args.shift
@services = Set.new
@mutex = Mutex.new
end

def start
DNSSD.browse("_http._tcp,git") do |reply|
begin
DNSSD.resolve reply.name, reply.type, reply.domain do |resolve_reply|
service = GitService.new(reply.name,
resolve_reply.target,
resolve_reply.port,
resolve_reply.text_record['description'].to_s)

@mutex.synchronize do
if @services.member? service
@services.delete service
else
@services << service
end
end
end
rescue ArgumentError # usually a jacked DNS text record
end
end

http = WEBrick::HTTPServer.new(:Port => @port.to_i)
http.mount_proc("/") { |req, res| index(req, res) }
http.mount_proc("/style.css") { |req, res| stylesheet(req, res) }
trap("INT") { http.shutdown }
t = Thread.new { http.start }

url = "http://localhost:#{@port}"
if @browser
`git web--browse -b '#{@browser}' http://localhost:9850`
else
`git web--browse -c "instaweb.browser" http://localhost:9850`
end
t.join
end

def index(req, res)
res['Content-Type'] = 'text/html'
res.body = index_html.result(binding)
end

def index_html
@index_html ||= ERB.new(<<-HTML)
<html>
<body>
<head>
<link rel="stylesheet" href="/style.css" type="text/css" media="screen"/>
<title>Browseable Git Repositories</title>
</head>
<h1>Browseable Git Repositories</h1>
<ul>
<% @mutex.synchronize do %>
<% @services.map do |s| %>
<li>
<a href='http://<%= s.host %>:<%= s.port %>' target="_new">
<%= s.name %>
</a>
<%= s.description unless s.description =~ /^Unnamed repository/ %>
</li>
<% end %>
<% end %>
</ul>
</body>
</html>
HTML
end

def stylesheet(req, res)
res['Content-Type'] = 'text/css'
res.body = css
end

def css
@css ||= <<-CSS
body {
font-family: sans-serif;
font-size: 12px;
background-color: #fff;
}
h1 {
font-size: 20px;
font-weight: bold;
}
ul {
border: 1px dashed #999;
padding: 10 10 10 20;
background-color: #ccc;
}
CSS
end
end

end
94 changes: 80 additions & 14 deletions lib/gitjour.rb
Expand Up @@ -23,13 +23,29 @@ def run(*args)
serve(*args)
when "remote"
remote(*args)
when "web"
web(*args)
when "browse"
browse(*args)
else
help
end
end

private

def service_name(name)
# If the name starts with ^, then don't apply the prefix
if name[0] == ?^
name = name[1..-1]
else
prefix = `git config --get gitjour.prefix`.chomp
prefix = ENV["USER"] if prefix.empty?
name = [prefix, name].compact.join("-")
end
name
end

def list
service_list.each do |service|
puts "=== #{service.name} on #{service.host}:#{service.port} ==="
Expand Down Expand Up @@ -74,32 +90,51 @@ def remote(repository_name, *rest)

def serve(path=Dir.pwd, *rest)
path = File.expand_path(path)
name = rest.shift || File.basename(path)
name = service_name(rest.shift || File.basename(path))
port = rest.shift || 9418

# If the name starts with ^, then don't apply the prefix
if name[0] == ?^
name = name[1..-1]
else
prefix = `git config --get gitjour.prefix`.chomp
prefix = ENV["USER"] if prefix.empty?
name = [prefix, name].compact.join("-")
end

if File.exists?("#{path}/.git")
announce_repo(path, name, port.to_i)
announce_git(path, name, port.to_i)
else
Dir["#{path}/*"].each do |dir|
if File.directory?(dir)
name = File.basename(dir)
announce_repo(dir, name, 9418)
announce_git(dir, name, 9418)
end
end
end

`git daemon --verbose --export-all --port=#{port} --base-path=#{path} --base-path-relaxed`
end

def web(path=Dir.pwd, *rest)
path = File.expand_path(path)
name = service_name(rest.shift || File.basename(path))
port = rest.shift || 1234
httpd = rest.shift || "webrick"

if File.exists?("#{path}/.git")
announce_web(path, name, port.to_i)
`git-instaweb --httpd=#{httpd} --port=#{port}`
if $? == 0
trap("INT") do
puts "Stopping instaweb..."
`git-instaweb stop`
exit 0
end
while true; sleep 30; end
else
$stderr.puts "Unable to launch git-instaweb. " +
"You may need to symlink $PREFIX/libexec/git-core/" +
"git-instaweb to a location in your path"
exit 1
end
else
$stderr.puts "You must specify a proper git project"
exit 1
end
end

def help
puts "Gitjour #{Gitjour::VERSION}"
puts "Serve up and use git repositories via ZeroConf."
Expand Down Expand Up @@ -127,6 +162,19 @@ def help
puts " Add a ZeroConf remote into your current repository."
puts " Optionally pass name to not use pwd."
puts
puts " web <path_to_project> [<name_of_project>] [<port>] [<httpd_daemon>]"
puts " Serve up the current directory via git instaweb for browsers."
puts " The default port is 1234 and the httpd_daemon is defaulted to"
puts " webrick. Other options are 'lighttpd' and 'apache2' (See the"
puts " git-instaweb man page for more details)"
puts
puts " browse [<port>] [<browser>]"
puts " Browse git repositories published with the 'web' command (see"
puts " above). This command takes two optional arguments: the first"
puts " is the port for the local web server (default 9850), the second"
puts " is the path to your web browser (see man git-web--browse for"
puts " details)."
puts
end

class Done < RuntimeError; end
Expand Down Expand Up @@ -173,16 +221,34 @@ def service_list
return list
end

def announce_repo(path, name, port)
def browse(*args)
require "browser"
Browser.new(*args).start
end

def announce_web(path, name, port)
announce_repo(path, name, port, "_http._tcp,git")
end

def announce_repo(path, name, port, type)
return unless File.exists?("#{path}/.git")

tr = DNSSD::TextRecord.new
tr['description'] = File.read("#{path}/.git/description") rescue "a git project"

DNSSD.register(name, "_git._tcp", 'local', port, tr.encode) do |rr|
DNSSD.register(name, type, 'local', port, tr.encode) do |rr|
puts "Registered #{name} on port #{port}. Starting service."
end
end

def announce_git(path, name, port)
announce_repo(path, name, port, "_git._tcp")
end

def announce_web(path, name, port)
announce_repo(path, name, port, "_http._tcp,git")
end

end
end
end

0 comments on commit bd843d2

Please sign in to comment.