Permalink
Browse files

Added 'web' and 'browse' commands to serve and view repos via HTTP.

  • Loading branch information...
1 parent 60a8d13 commit bd843d2aaeae4a5b721dbefd3725d5868645903c @alexvollmer committed Mar 15, 2009
Showing with 191 additions and 356 deletions.
  1. +1 −0 Manifest.txt
  2. +110 −0 lib/browser.rb
  3. +80 −14 lib/gitjour.rb
  4. +0 −342 lib/gitjour/application.rb
View
@@ -4,5 +4,6 @@ README.txt
Rakefile
bin/gitjour
lib/gitjour.rb
+lib/browser.rb
test/test_gitjour.rb
test/test_helper.rb
View
@@ -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
View
@@ -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} ==="
@@ -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."
@@ -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
@@ -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
Oops, something went wrong.

0 comments on commit bd843d2

Please sign in to comment.