technomancy-gitjour 6.4.0 → 6.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +9 -0
- data/Manifest.txt +2 -1
- data/{README.txt → README.rdoc} +30 -1
- data/Rakefile +3 -1
- data/lib/gitjour/browser.rb +111 -0
- data/lib/gitjour.rb +70 -15
- metadata +13 -12
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
data/{README.txt → README.rdoc}
RENAMED
|
@@ -4,18 +4,28 @@
|
|
|
4
4
|
|
|
5
5
|
== DESCRIPTION:
|
|
6
6
|
|
|
7
|
-
Automates
|
|
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
|
@@ -5,11 +5,13 @@ require 'hoe'
|
|
|
5
5
|
require './lib/gitjour.rb'
|
|
6
6
|
|
|
7
7
|
Hoe.new('gitjour', Gitjour::VERSION) do |p|
|
|
8
|
-
p.extra_deps << ['dnssd', "~>
|
|
8
|
+
p.extra_deps << ['dnssd', "~> 1.3"]
|
|
9
9
|
p.developer('Chad Fowler', 'chad@chadfowler.com')
|
|
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
|
|
@@ -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
|
data/lib/gitjour.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
2
|
require 'dnssd'
|
|
3
3
|
require 'set'
|
|
4
|
+
require 'timeout'
|
|
4
5
|
|
|
5
6
|
Thread.abort_on_exception = true
|
|
6
7
|
|
|
7
8
|
module Gitjour
|
|
8
|
-
VERSION = "6.
|
|
9
|
+
VERSION = "6.5.0"
|
|
9
10
|
GitService = Struct.new(:name, :host, :port, :description)
|
|
10
11
|
|
|
11
12
|
class Application
|
|
@@ -23,6 +24,10 @@ module Gitjour
|
|
|
23
24
|
serve(*args)
|
|
24
25
|
when "remote"
|
|
25
26
|
remote(*args)
|
|
27
|
+
when "web"
|
|
28
|
+
web(*args)
|
|
29
|
+
when "browse"
|
|
30
|
+
browse(*args)
|
|
26
31
|
else
|
|
27
32
|
help
|
|
28
33
|
end
|
|
@@ -30,6 +35,18 @@ module Gitjour
|
|
|
30
35
|
|
|
31
36
|
private
|
|
32
37
|
|
|
38
|
+
def service_name(name)
|
|
39
|
+
# If the name starts with ^, then don't apply the prefix
|
|
40
|
+
if name[0] == ?^
|
|
41
|
+
name = name[1..-1]
|
|
42
|
+
else
|
|
43
|
+
prefix = `git config --get gitjour.prefix`.chomp
|
|
44
|
+
prefix = ENV["USER"] if prefix.empty?
|
|
45
|
+
name = [prefix, name].compact.join("-")
|
|
46
|
+
end
|
|
47
|
+
name
|
|
48
|
+
end
|
|
49
|
+
|
|
33
50
|
def list
|
|
34
51
|
service_list.each do |service|
|
|
35
52
|
puts "=== #{service.name} on #{service.host}:#{service.port} ==="
|
|
@@ -74,25 +91,16 @@ module Gitjour
|
|
|
74
91
|
|
|
75
92
|
def serve(path=Dir.pwd, *rest)
|
|
76
93
|
path = File.expand_path(path)
|
|
77
|
-
name = rest.shift || File.basename(path)
|
|
94
|
+
name = service_name(rest.shift || File.basename(path))
|
|
78
95
|
port = rest.shift || 9418
|
|
79
96
|
|
|
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
97
|
if File.exists?("#{path}/.git")
|
|
90
|
-
|
|
98
|
+
announce_git(path, name, port.to_i)
|
|
91
99
|
else
|
|
92
100
|
Dir["#{path}/*"].each do |dir|
|
|
93
101
|
if File.directory?(dir)
|
|
94
102
|
name = File.basename(dir)
|
|
95
|
-
|
|
103
|
+
announce_git(dir, name, 9418)
|
|
96
104
|
end
|
|
97
105
|
end
|
|
98
106
|
end
|
|
@@ -100,6 +108,26 @@ module Gitjour
|
|
|
100
108
|
`git daemon --verbose --export-all --port=#{port} --base-path=#{path} --base-path-relaxed`
|
|
101
109
|
end
|
|
102
110
|
|
|
111
|
+
def web(path=Dir.pwd, *rest)
|
|
112
|
+
path = File.expand_path(path)
|
|
113
|
+
name = service_name(rest.shift || File.basename(path))
|
|
114
|
+
port = rest.shift || 1234
|
|
115
|
+
httpd = rest.shift || "webrick"
|
|
116
|
+
|
|
117
|
+
system("git instaweb --httpd=#{httpd} --port=#{port}") or
|
|
118
|
+
abort "Unable to launch git instaweb."
|
|
119
|
+
|
|
120
|
+
announce_web(path, name, port.to_i)
|
|
121
|
+
|
|
122
|
+
trap("INT") do
|
|
123
|
+
puts "Stopping instaweb..."
|
|
124
|
+
system "git instaweb stop"
|
|
125
|
+
exit
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
Thread.stop
|
|
129
|
+
end
|
|
130
|
+
|
|
103
131
|
def help
|
|
104
132
|
puts "Gitjour #{Gitjour::VERSION}"
|
|
105
133
|
puts "Serve up and use git repositories via ZeroConf."
|
|
@@ -127,6 +155,19 @@ module Gitjour
|
|
|
127
155
|
puts " Add a ZeroConf remote into your current repository."
|
|
128
156
|
puts " Optionally pass name to not use pwd."
|
|
129
157
|
puts
|
|
158
|
+
puts " web <path_to_project> [<name_of_project>] [<port>] [<httpd_daemon>]"
|
|
159
|
+
puts " Serve up the current directory via git instaweb for browsers."
|
|
160
|
+
puts " The default port is 1234 and the httpd_daemon is defaulted to"
|
|
161
|
+
puts " webrick. Other options are 'lighttpd' and 'apache2' (See the"
|
|
162
|
+
puts " git-instaweb man page for more details)"
|
|
163
|
+
puts
|
|
164
|
+
puts " browse [<port>] [<browser>]"
|
|
165
|
+
puts " Browse git repositories published with the 'web' command (see"
|
|
166
|
+
puts " above). This command takes two optional arguments: the first"
|
|
167
|
+
puts " is the port for the local web server (default 9850), the second"
|
|
168
|
+
puts " is the path to your web browser (see man git-web--browse for"
|
|
169
|
+
puts " details)."
|
|
170
|
+
puts
|
|
130
171
|
end
|
|
131
172
|
|
|
132
173
|
class Done < RuntimeError; end
|
|
@@ -173,16 +214,30 @@ module Gitjour
|
|
|
173
214
|
return list
|
|
174
215
|
end
|
|
175
216
|
|
|
176
|
-
def
|
|
217
|
+
def browse(*args)
|
|
218
|
+
require "gitjour/browser"
|
|
219
|
+
Browser.new(*args).start
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def announce_repo(path, name, port, type)
|
|
177
223
|
return unless File.exists?("#{path}/.git")
|
|
178
224
|
|
|
179
225
|
tr = DNSSD::TextRecord.new
|
|
180
226
|
tr['description'] = File.read("#{path}/.git/description") rescue "a git project"
|
|
227
|
+
tr['gitjour'] = 'true' # distinguish instaweb from other HTTP servers
|
|
181
228
|
|
|
182
|
-
DNSSD.register(name,
|
|
229
|
+
DNSSD.register(name, type, 'local', port, tr) do |rr|
|
|
183
230
|
puts "Registered #{name} on port #{port}. Starting service."
|
|
184
231
|
end
|
|
185
232
|
end
|
|
233
|
+
|
|
234
|
+
def announce_git(path, name, port)
|
|
235
|
+
announce_repo(path, name, port, "_git._tcp")
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def announce_web(path, name, port)
|
|
239
|
+
announce_repo(path, name, port, "_http._tcp")
|
|
240
|
+
end
|
|
186
241
|
end
|
|
187
242
|
end
|
|
188
243
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: technomancy-gitjour
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.
|
|
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-
|
|
15
|
+
date: 2009-08-18 00:00:00 -07:00
|
|
16
16
|
default_executable: gitjour
|
|
17
17
|
dependencies:
|
|
18
18
|
- !ruby/object:Gem::Dependency
|
|
@@ -23,7 +23,7 @@ dependencies:
|
|
|
23
23
|
requirements:
|
|
24
24
|
- - ~>
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
26
|
+
version: "1.3"
|
|
27
27
|
version:
|
|
28
28
|
- !ruby/object:Gem::Dependency
|
|
29
29
|
name: hoe
|
|
@@ -33,9 +33,9 @@ dependencies:
|
|
|
33
33
|
requirements:
|
|
34
34
|
- - ">="
|
|
35
35
|
- !ruby/object:Gem::Version
|
|
36
|
-
version:
|
|
36
|
+
version: 2.3.3
|
|
37
37
|
version:
|
|
38
|
-
description: Automates
|
|
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,22 +48,23 @@ 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.
|
|
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
|
-
has_rdoc:
|
|
61
|
+
has_rdoc: false
|
|
62
62
|
homepage: http://github.com/technomancy/gitjour
|
|
63
|
+
licenses:
|
|
63
64
|
post_install_message:
|
|
64
65
|
rdoc_options:
|
|
65
66
|
- --main
|
|
66
|
-
- README.
|
|
67
|
+
- README.rdoc
|
|
67
68
|
require_paths:
|
|
68
69
|
- lib
|
|
69
70
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
@@ -81,10 +82,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
81
82
|
requirements: []
|
|
82
83
|
|
|
83
84
|
rubyforge_project: gitjour
|
|
84
|
-
rubygems_version: 1.
|
|
85
|
+
rubygems_version: 1.3.5
|
|
85
86
|
signing_key:
|
|
86
87
|
specification_version: 3
|
|
87
|
-
summary: Automates
|
|
88
|
+
summary: Automates ZeroConf-powered serving and cloning of git repositories.
|
|
88
89
|
test_files:
|
|
89
|
-
- test/test_helper.rb
|
|
90
90
|
- test/test_gitjour.rb
|
|
91
|
+
- test/test_helper.rb
|