gitjour 6.4.0 → 6.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ == 6.5.0 2009-03-17
2
+
3
+ * Added web command to launch and announce instaweb
4
+ * Added browse command to see all available instawebs
5
+
1
6
  == 6.4.0 2009-03-13
2
7
 
3
8
  * Add pull command
@@ -1,8 +1,9 @@
1
1
  History.txt
2
2
  Manifest.txt
3
- README.txt
3
+ README.rdoc
4
4
  Rakefile
5
5
  bin/gitjour
6
6
  lib/gitjour.rb
7
+ lib/gitjour/browser.rb
7
8
  test/test_gitjour.rb
8
9
  test/test_helper.rb
@@ -4,18 +4,28 @@
4
4
 
5
5
  == DESCRIPTION:
6
6
 
7
- Automates zeroconf-powered serving and cloning of git repositories.
7
+ Automates ZeroConf-powered serving and cloning of git repositories.
8
8
 
9
9
  == SYNOPSIS:
10
10
 
11
+ === THE BASICS
12
+
13
+ To serve a project, identified via ZeroConf:
14
+
11
15
  % gitjour serve [project_dir] [name_to_advertise_as]
12
16
  Registered phil-gitjour on port 9418. Starting service.
13
17
 
18
+ To find advertised git projects:
19
+
14
20
  % gitjour list
15
21
  Gathering for up to 5 seconds...
16
22
  === phil-gitjour on pdp10.local.:9418 ===
17
23
  gitjour (clone|pull) phil-gitjour
18
24
 
25
+ === CLONING & PULLING
26
+
27
+ To clone an advertised git repo:
28
+
19
29
  % gitjour clone phil-gitjour
20
30
  Gathering for up to 5 seconds...
21
31
  Connecting to pdp10.local.:9418
@@ -23,6 +33,9 @@ Automates zeroconf-powered serving and cloning of git repositories.
23
33
  [...]
24
34
  Resolving deltas: 100% (342/342), done.
25
35
 
36
+
37
+ To pull from an advertised git repo:
38
+
26
39
  % gitjour pull phil-gitjour
27
40
  Gathering for up to 5 seconds...
28
41
  Connecting to pdp10.local.:9418
@@ -32,8 +45,24 @@ Automates zeroconf-powered serving and cloning of git repositories.
32
45
  [...]
33
46
  4 files changed, 35 insertions(+), 80 deletions(-)
34
47
 
48
+ === BROWSING GIT REPOS WITH YOUR BROWSER
49
+
50
+ To serve up your repo via 'git instaweb':
51
+
52
+ % gitjour web phil-gitjour
53
+ [2009-03-17 19:27:20] INFO WEBrick 1.3.1
54
+ [2009-03-17 19:27:20] INFO ruby 1.8.6 (2008-03-03) [universal-darwin9.0]
55
+ # Starts git-instaweb in webrick, publishes ZeroConf DNS record
56
+
57
+ To see all advertised git repos in your browser:
58
+
59
+ % gitjour browse
60
+ # Starts a small web-app to find all
61
+
62
+
35
63
  == REQUIREMENTS:
36
64
 
65
+ * git
37
66
  * dnssd, which requires development headers to bonjour or avahi
38
67
  See dnssd documentation for details.
39
68
 
data/Rakefile CHANGED
@@ -10,6 +10,8 @@ Hoe.new('gitjour', Gitjour::VERSION) do |p|
10
10
  p.developer('Evan Phoenix', 'evan@fallingsnow.net')
11
11
  p.developer('Rich Kilmer', 'rich@example.com')
12
12
  p.developer('Phil Hagelberg', 'technomancy@gmail.com')
13
+
14
+ p.readme_file = 'README.rdoc'
13
15
  end
14
16
 
15
17
  # vim: syntax=Ruby
@@ -5,7 +5,7 @@ require 'set'
5
5
  Thread.abort_on_exception = true
6
6
 
7
7
  module Gitjour
8
- VERSION = "6.4.0"
8
+ VERSION = "6.5.0"
9
9
  GitService = Struct.new(:name, :host, :port, :description)
10
10
 
11
11
  class Application
@@ -23,6 +23,10 @@ module Gitjour
23
23
  serve(*args)
24
24
  when "remote"
25
25
  remote(*args)
26
+ when "web"
27
+ web(*args)
28
+ when "browse"
29
+ browse(*args)
26
30
  else
27
31
  help
28
32
  end
@@ -30,6 +34,18 @@ module Gitjour
30
34
 
31
35
  private
32
36
 
37
+ def service_name(name)
38
+ # If the name starts with ^, then don't apply the prefix
39
+ if name[0] == ?^
40
+ name = name[1..-1]
41
+ else
42
+ prefix = `git config --get gitjour.prefix`.chomp
43
+ prefix = ENV["USER"] if prefix.empty?
44
+ name = [prefix, name].compact.join("-")
45
+ end
46
+ name
47
+ end
48
+
33
49
  def list
34
50
  service_list.each do |service|
35
51
  puts "=== #{service.name} on #{service.host}:#{service.port} ==="
@@ -74,25 +90,16 @@ module Gitjour
74
90
 
75
91
  def serve(path=Dir.pwd, *rest)
76
92
  path = File.expand_path(path)
77
- name = rest.shift || File.basename(path)
93
+ name = service_name(rest.shift || File.basename(path))
78
94
  port = rest.shift || 9418
79
95
 
80
- # If the name starts with ^, then don't apply the prefix
81
- if name[0] == ?^
82
- name = name[1..-1]
83
- else
84
- prefix = `git config --get gitjour.prefix`.chomp
85
- prefix = ENV["USER"] if prefix.empty?
86
- name = [prefix, name].compact.join("-")
87
- end
88
-
89
96
  if File.exists?("#{path}/.git")
90
- announce_repo(path, name, port.to_i)
97
+ announce_git(path, name, port.to_i)
91
98
  else
92
99
  Dir["#{path}/*"].each do |dir|
93
100
  if File.directory?(dir)
94
101
  name = File.basename(dir)
95
- announce_repo(dir, name, 9418)
102
+ announce_git(dir, name, 9418)
96
103
  end
97
104
  end
98
105
  end
@@ -100,6 +107,26 @@ module Gitjour
100
107
  `git daemon --verbose --export-all --port=#{port} --base-path=#{path} --base-path-relaxed`
101
108
  end
102
109
 
110
+ def web(path=Dir.pwd, *rest)
111
+ path = File.expand_path(path)
112
+ name = service_name(rest.shift || File.basename(path))
113
+ port = rest.shift || 1234
114
+ httpd = rest.shift || "webrick"
115
+
116
+ system("git instaweb --httpd=#{httpd} --port=#{port}") or
117
+ abort "Unable to launch git instaweb."
118
+
119
+ announce_web(path, name, port.to_i)
120
+
121
+ trap("INT") do
122
+ puts "Stopping instaweb..."
123
+ system "git instaweb stop"
124
+ exit
125
+ end
126
+
127
+ Thread.stop
128
+ end
129
+
103
130
  def help
104
131
  puts "Gitjour #{Gitjour::VERSION}"
105
132
  puts "Serve up and use git repositories via ZeroConf."
@@ -127,6 +154,19 @@ module Gitjour
127
154
  puts " Add a ZeroConf remote into your current repository."
128
155
  puts " Optionally pass name to not use pwd."
129
156
  puts
157
+ puts " web <path_to_project> [<name_of_project>] [<port>] [<httpd_daemon>]"
158
+ puts " Serve up the current directory via git instaweb for browsers."
159
+ puts " The default port is 1234 and the httpd_daemon is defaulted to"
160
+ puts " webrick. Other options are 'lighttpd' and 'apache2' (See the"
161
+ puts " git-instaweb man page for more details)"
162
+ puts
163
+ puts " browse [<port>] [<browser>]"
164
+ puts " Browse git repositories published with the 'web' command (see"
165
+ puts " above). This command takes two optional arguments: the first"
166
+ puts " is the port for the local web server (default 9850), the second"
167
+ puts " is the path to your web browser (see man git-web--browse for"
168
+ puts " details)."
169
+ puts
130
170
  end
131
171
 
132
172
  class Done < RuntimeError; end
@@ -173,16 +213,30 @@ module Gitjour
173
213
  return list
174
214
  end
175
215
 
176
- def announce_repo(path, name, port)
216
+ def browse(*args)
217
+ require "gitjour/browser"
218
+ Browser.new(*args).start
219
+ end
220
+
221
+ def announce_repo(path, name, port, type)
177
222
  return unless File.exists?("#{path}/.git")
178
223
 
179
224
  tr = DNSSD::TextRecord.new
180
225
  tr['description'] = File.read("#{path}/.git/description") rescue "a git project"
226
+ tr['gitjour'] = 'true' # distinguish instaweb from other HTTP servers
181
227
 
182
- DNSSD.register(name, "_git._tcp", 'local', port, tr.encode) do |rr|
228
+ DNSSD.register(name, type, 'local', port, tr.encode) do |rr|
183
229
  puts "Registered #{name} on port #{port}. Starting service."
184
230
  end
185
231
  end
232
+
233
+ def announce_git(path, name, port)
234
+ announce_repo(path, name, port, "_git._tcp")
235
+ end
236
+
237
+ def announce_web(path, name, port)
238
+ announce_repo(path, name, port, "_http._tcp")
239
+ end
186
240
  end
187
241
  end
188
242
  end
@@ -0,0 +1,111 @@
1
+ require "webrick"
2
+ require "erb"
3
+ require "set"
4
+ require "thread"
5
+
6
+ module Gitjour
7
+ class Browser
8
+
9
+ def initialize(*args)
10
+ @port = args.shift || 9850
11
+ @browser = args.shift
12
+ @services = Set.new
13
+ @mutex = Mutex.new
14
+ end
15
+
16
+ def start
17
+ DNSSD.browse("_http._tcp") do |reply|
18
+ begin
19
+ DNSSD.resolve reply.name, reply.type, reply.domain do |resolve_reply|
20
+ next unless resolve_reply.text_record['gitjour']
21
+ service = GitService.new(reply.name,
22
+ resolve_reply.target,
23
+ resolve_reply.port,
24
+ resolve_reply.text_record['description'].to_s)
25
+
26
+ @mutex.synchronize do
27
+ if @services.member? service
28
+ @services.delete service
29
+ else
30
+ @services << service
31
+ end
32
+ end
33
+ end
34
+ rescue ArgumentError # usually a jacked DNS text record
35
+ end
36
+ end
37
+
38
+ http = WEBrick::HTTPServer.new(:Port => @port.to_i)
39
+ http.mount_proc("/") { |req, res| index(req, res) }
40
+ http.mount_proc("/style.css") { |req, res| stylesheet(req, res) }
41
+ trap("INT") { http.shutdown }
42
+ t = Thread.new { http.start }
43
+
44
+ url = "http://localhost:#{@port}"
45
+ if @browser
46
+ `git web--browse -b '#{@browser}' http://localhost:9850`
47
+ else
48
+ `git web--browse -c "instaweb.browser" http://localhost:9850`
49
+ end
50
+ t.join
51
+ end
52
+
53
+ def index(req, res)
54
+ res['Content-Type'] = 'text/html'
55
+ res.body = index_html.result(binding)
56
+ end
57
+
58
+ def index_html
59
+ @index_html ||= ERB.new(<<-HTML)
60
+ <html>
61
+ <body>
62
+ <head>
63
+ <link rel="stylesheet" href="/style.css" type="text/css" media="screen"/>
64
+ <title>Browseable Git Repositories</title>
65
+ </head>
66
+ <h1>Browseable Git Repositories</h1>
67
+ <ul>
68
+ <% @mutex.synchronize do %>
69
+ <% @services.map do |s| %>
70
+ <li>
71
+ <a href='http://<%= s.host %>:<%= s.port %>' target="_new">
72
+ <%= s.name %>
73
+ </a>
74
+ <%= s.description unless s.description =~ /^Unnamed repository/ %>
75
+ </li>
76
+ <% end %>
77
+ <% end %>
78
+ </ul>
79
+ </body>
80
+ </html>
81
+ HTML
82
+ end
83
+
84
+ def stylesheet(req, res)
85
+ res['Content-Type'] = 'text/css'
86
+ res.body = css
87
+ end
88
+
89
+ def css
90
+ @css ||= <<-CSS
91
+ body {
92
+ font-family: sans-serif;
93
+ font-size: 12px;
94
+ background-color: #fff;
95
+ }
96
+
97
+ h1 {
98
+ font-size: 20px;
99
+ font-weight: bold;
100
+ }
101
+
102
+ ul {
103
+ border: 1px dashed #999;
104
+ padding: 10 10 10 20;
105
+ background-color: #ccc;
106
+ }
107
+ CSS
108
+ end
109
+ end
110
+
111
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitjour
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.4.0
4
+ version: 6.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chad Fowler
@@ -12,7 +12,7 @@ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
14
 
15
- date: 2009-03-16 00:00:00 -07:00
15
+ date: 2009-03-17 00:00:00 -07:00
16
16
  default_executable:
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
@@ -35,7 +35,7 @@ dependencies:
35
35
  - !ruby/object:Gem::Version
36
36
  version: 1.9.0
37
37
  version:
38
- description: Automates zeroconf-powered serving and cloning of git repositories.
38
+ description: Automates ZeroConf-powered serving and cloning of git repositories.
39
39
  email:
40
40
  - chad@chadfowler.com
41
41
  - evan@fallingsnow.net
@@ -48,14 +48,14 @@ extensions: []
48
48
  extra_rdoc_files:
49
49
  - History.txt
50
50
  - Manifest.txt
51
- - README.txt
52
51
  files:
53
52
  - History.txt
54
53
  - Manifest.txt
55
- - README.txt
54
+ - README.rdoc
56
55
  - Rakefile
57
56
  - bin/gitjour
58
57
  - lib/gitjour.rb
58
+ - lib/gitjour/browser.rb
59
59
  - test/test_gitjour.rb
60
60
  - test/test_helper.rb
61
61
  has_rdoc: true
@@ -65,7 +65,7 @@ licenses: []
65
65
  post_install_message:
66
66
  rdoc_options:
67
67
  - --main
68
- - README.txt
68
+ - README.rdoc
69
69
  require_paths:
70
70
  - lib
71
71
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -83,10 +83,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
83
  requirements: []
84
84
 
85
85
  rubyforge_project: gitjour
86
- rubygems_version: 1.3.1.2403
86
+ rubygems_version: 1.3.1
87
87
  signing_key:
88
88
  specification_version: 3
89
- summary: Automates zeroconf-powered serving and cloning of git repositories.
89
+ summary: Automates ZeroConf-powered serving and cloning of git repositories.
90
90
  test_files:
91
- - test/test_helper.rb
92
91
  - test/test_gitjour.rb
92
+ - test/test_helper.rb