dolt 0.1.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/.gitmodules +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +53 -0
- data/Rakefile +10 -0
- data/Readme.md +25 -0
- data/bin/dolt +46 -0
- data/dolt.gemspec +39 -0
- data/lib/dolt/async/deferrable_child_process.rb +49 -0
- data/lib/dolt/async/when.rb +87 -0
- data/lib/dolt/disk_repo_resolver.rb +41 -0
- data/lib/dolt/git/blob.rb +31 -0
- data/lib/dolt/git/repository.rb +47 -0
- data/lib/dolt/git/shell.rb +39 -0
- data/lib/dolt/repo_actions.rb +41 -0
- data/lib/dolt/sinatra/actions.rb +38 -0
- data/lib/dolt/sinatra/base.rb +36 -0
- data/lib/dolt/sinatra/multi_repo_browser.rb +37 -0
- data/lib/dolt/sinatra/single_repo_browser.rb +44 -0
- data/lib/dolt/template_renderer.rb +60 -0
- data/lib/dolt/version.rb +21 -0
- data/lib/dolt/view.rb +58 -0
- data/lib/dolt/view/breadcrumb.rb +45 -0
- data/lib/dolt/view/highlighter.rb +49 -0
- data/test/dolt/git/blob_test.rb +49 -0
- data/test/dolt/git/repository_test.rb +70 -0
- data/test/dolt/git/shell_test.rb +78 -0
- data/test/dolt/repo_actions_test.rb +73 -0
- data/test/dolt/sinatra/actions_test.rb +81 -0
- data/test/dolt/template_renderer_test.rb +80 -0
- data/test/dolt/view_test.rb +88 -0
- data/test/dolt/views/blob_test.rb +96 -0
- data/test/test_helper.rb +43 -0
- data/vendor/ui/bootstrap/css/bootstrap-responsive.min.css +9 -0
- data/vendor/ui/bootstrap/css/bootstrap.min.css +9 -0
- data/vendor/ui/bootstrap/img/glyphicons-halflings-white.png +0 -0
- data/vendor/ui/bootstrap/img/glyphicons-halflings.png +0 -0
- data/vendor/ui/bootstrap/js/bootstrap.min.js +6 -0
- data/vendor/ui/css/gitorious.css +535 -0
- data/vendor/ui/css/pygments.css +133 -0
- data/vendor/ui/iconic/lock_stroke.svg +17 -0
- data/vendor/ui/images/f5f5f5-980x1.png +0 -0
- data/vendor/ui/images/gitorious.png +0 -0
- data/vendor/ui/images/powered-by.png +0 -0
- data/vendor/ui/images/white-980x1.png +0 -0
- data/vendor/ui/js/gitorious.js +87 -0
- data/views/blob.erb +43 -0
- data/views/layout.erb +42 -0
- metadata +263 -0
data/.gitmodules
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
dolt (0.1.1)
|
5
|
+
async_sinatra (~> 1.0)
|
6
|
+
eventmachine (~> 0.12)
|
7
|
+
pygments.rb (~> 0.2)
|
8
|
+
sinatra (~> 1.3)
|
9
|
+
thin (~> 1.4)
|
10
|
+
tilt (~> 1.3)
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: http://rubygems.org/
|
14
|
+
specs:
|
15
|
+
async_sinatra (1.0.0)
|
16
|
+
rack (>= 1.4.1)
|
17
|
+
sinatra (>= 1.3.2)
|
18
|
+
blankslate (2.1.2.4)
|
19
|
+
daemons (1.1.9)
|
20
|
+
em-minitest-spec (1.1.1)
|
21
|
+
eventmachine
|
22
|
+
eventmachine (0.12.10)
|
23
|
+
ffi (1.0.11)
|
24
|
+
minitest (2.1.0)
|
25
|
+
mocha (0.9.12)
|
26
|
+
pygments.rb (0.2.13)
|
27
|
+
rubypython (~> 0.5.3)
|
28
|
+
rack (1.4.1)
|
29
|
+
rack-protection (1.2.0)
|
30
|
+
rack
|
31
|
+
rake (0.9.2.2)
|
32
|
+
rubypython (0.5.3)
|
33
|
+
blankslate (>= 2.1.2.3)
|
34
|
+
ffi (~> 1.0.7)
|
35
|
+
sinatra (1.3.3)
|
36
|
+
rack (~> 1.3, >= 1.3.6)
|
37
|
+
rack-protection (~> 1.2)
|
38
|
+
tilt (~> 1.3, >= 1.3.3)
|
39
|
+
thin (1.4.1)
|
40
|
+
daemons (>= 1.0.9)
|
41
|
+
eventmachine (>= 0.12.6)
|
42
|
+
rack (>= 1.0.0)
|
43
|
+
tilt (1.3.3)
|
44
|
+
|
45
|
+
PLATFORMS
|
46
|
+
ruby
|
47
|
+
|
48
|
+
DEPENDENCIES
|
49
|
+
dolt!
|
50
|
+
em-minitest-spec (~> 1.1)
|
51
|
+
minitest (~> 2.0)
|
52
|
+
mocha
|
53
|
+
rake (~> 0.9)
|
data/Rakefile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Dolt - The Git project browser
|
2
|
+
|
3
|
+
Dolt is a stand-alone server that allows you to browse git repositories in your
|
4
|
+
browser. It uses Pygments to syntax highlight code, and displays blame as well
|
5
|
+
as git history for individual files.
|
6
|
+
|
7
|
+
Dolt can also be used as a library to serve git trees from e.g. a Rails app. It
|
8
|
+
is the blob viewer implementation that will be used in the Gitorious application
|
9
|
+
(gitorious.org) when it is ready.
|
10
|
+
|
11
|
+
## Blobs
|
12
|
+
|
13
|
+
Dolt currenly only serves blobs. The sample Rack application that comes with
|
14
|
+
Dolt allows you to surf repos locally on your disk:
|
15
|
+
|
16
|
+
env REPO_ROOT=/where/git/repos/reside rackup -Ilib
|
17
|
+
|
18
|
+
That command will start the server, and allow you to view blobs in repos
|
19
|
+
available in the `/where/git/repos/reside` directory. For example, on my machine,
|
20
|
+
when I issue:
|
21
|
+
|
22
|
+
env REPO_ROOT=/home/christian/projects rackup -Ilib
|
23
|
+
|
24
|
+
I can go to [http://localhost:9292/gitorious/blob/master:app/models/repository.rb](http://localhost:9292/gitorious/blob/master:app/models/repository.rb)
|
25
|
+
to view Gitorious blobs.
|
data/bin/dolt
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "thin"
|
3
|
+
require "sinatra/base"
|
4
|
+
require "dolt/repo_actions"
|
5
|
+
require "dolt/template_renderer"
|
6
|
+
require "dolt/view"
|
7
|
+
require "dolt/git/file_system_repository_resolver"
|
8
|
+
|
9
|
+
if ARGV.length == 0
|
10
|
+
puts("Dolt should be run with a directory as its sole argument")
|
11
|
+
puts("The directory should either be a Git repository or a directory")
|
12
|
+
puts("that holds Git repositories.")
|
13
|
+
exit(1)
|
14
|
+
end
|
15
|
+
|
16
|
+
### TODO: Extract this into a testable API
|
17
|
+
|
18
|
+
def is_git_repo?(dir)
|
19
|
+
File.exists?(File.join(dir, ".git"))
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_app(dir, view)
|
23
|
+
if is_git_repo?(dir)
|
24
|
+
require "dolt/sinatra/single_repo_browser"
|
25
|
+
dir = File.expand_path(dir)
|
26
|
+
resolver = Dolt::DiskRepoResolver.new(File.dirname(dir))
|
27
|
+
actions = Dolt::RepoActions.new(resolver)
|
28
|
+
Dolt::Sinatra::SingleRepoBrowser.new(File.basename(dir), actions, view)
|
29
|
+
else
|
30
|
+
resolver = Dolt::DiskRepoResolver.new(dir)
|
31
|
+
actions = Dolt::RepoActions.new(resolver)
|
32
|
+
require "dolt/sinatra/multi_repo_browser"
|
33
|
+
Dolt::Sinatra::MultiRepoBrowser.new(actions, view)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
base = File.join(File.dirname(__FILE__), "..")
|
38
|
+
|
39
|
+
template_root = File.join(base, "views")
|
40
|
+
options = { :cache => false, :layout => "layout" }
|
41
|
+
view = Dolt::TemplateRenderer.new(template_root, options)
|
42
|
+
view.helper(Dolt::View)
|
43
|
+
|
44
|
+
Sinatra::Base.set(:public_folder, File.join(base, "vendor/ui"))
|
45
|
+
server = create_app(ARGV[0], view)
|
46
|
+
Thin::Server.start("0.0.0.0", 3000, server)
|
data/dolt.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.join("lib/dolt/version")
|
3
|
+
|
4
|
+
module GemSpecHelper
|
5
|
+
def self.files(path)
|
6
|
+
`cd #{path} && git ls-files`.split("\n").map do |p|
|
7
|
+
File.join(path, p)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
Gem::Specification.new do |s|
|
13
|
+
s.name = "dolt"
|
14
|
+
s.version = Dolt::VERSION
|
15
|
+
s.authors = ["Christian Johansen"]
|
16
|
+
s.email = ["christian@gitorious.org"]
|
17
|
+
s.homepage = "http://gitorious.org/gitorious/dolt"
|
18
|
+
s.summary = %q{Dolt serves git trees and syntax highlighted blobs}
|
19
|
+
s.description = %q{Dolt serves git trees and syntax highlighted blobs}
|
20
|
+
|
21
|
+
s.rubyforge_project = "dolt"
|
22
|
+
|
23
|
+
s.add_dependency "eventmachine", "~>0.12"
|
24
|
+
s.add_dependency "thin", "~>1.4"
|
25
|
+
s.add_dependency "sinatra", "~>1.3"
|
26
|
+
s.add_dependency "async_sinatra", "~>1.0"
|
27
|
+
s.add_dependency "tilt", "~>1.3"
|
28
|
+
s.add_dependency "pygments.rb", "~>0.2"
|
29
|
+
|
30
|
+
s.add_development_dependency "minitest", "~> 2.0"
|
31
|
+
s.add_development_dependency "em-minitest-spec", "~> 1.1"
|
32
|
+
s.add_development_dependency "rake", "~> 0.9"
|
33
|
+
s.add_development_dependency "mocha"
|
34
|
+
|
35
|
+
s.files = GemSpecHelper.files(".") + GemSpecHelper.files("vendor/ui")
|
36
|
+
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
37
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#--
|
3
|
+
# Copyright (C) 2012 Gitorious AS
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Affero General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#++
|
18
|
+
require "eventmachine"
|
19
|
+
|
20
|
+
module Dolt
|
21
|
+
# A deferrable child process implementation that actually considers
|
22
|
+
# the not uncommon situation where the command fails.
|
23
|
+
#
|
24
|
+
class DeferrableChildProcess < EventMachine::Connection
|
25
|
+
include EventMachine::Deferrable
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
super
|
29
|
+
@data = []
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.open cmd
|
33
|
+
EventMachine.popen(cmd, DeferrableChildProcess)
|
34
|
+
end
|
35
|
+
|
36
|
+
def receive_data data
|
37
|
+
@data << data
|
38
|
+
end
|
39
|
+
|
40
|
+
def unbind
|
41
|
+
status = get_status
|
42
|
+
if status.exitstatus != 0
|
43
|
+
fail(status)
|
44
|
+
else
|
45
|
+
succeed(@data.join, status)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require "eventmachine"
|
2
|
+
|
3
|
+
module When
|
4
|
+
class Promise
|
5
|
+
def initialize(deferred = EM::DefaultDeferrable.new)
|
6
|
+
@deferred = deferred
|
7
|
+
end
|
8
|
+
|
9
|
+
def callback(&block)
|
10
|
+
@deferred.callback(&block)
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def errback(&block)
|
15
|
+
@deferred.errback(&block)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Resolver
|
21
|
+
def initialize(deferred = EM::DefaultDeferrable.new)
|
22
|
+
@deferred = deferred
|
23
|
+
@resolved = false
|
24
|
+
end
|
25
|
+
|
26
|
+
def resolve(*args)
|
27
|
+
mark_resolved
|
28
|
+
@deferred.succeed(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
def reject(*args)
|
32
|
+
mark_resolved
|
33
|
+
@deferred.fail(*args)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def mark_resolved
|
38
|
+
raise StandardError.new("Already resolved") if @resolved
|
39
|
+
@resolved = true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Deferred
|
44
|
+
attr_reader :resolver, :promise
|
45
|
+
|
46
|
+
def initialize
|
47
|
+
deferred = EM::DefaultDeferrable.new
|
48
|
+
@resolver = Resolver.new(deferred)
|
49
|
+
@promise = Promise.new(deferred)
|
50
|
+
end
|
51
|
+
|
52
|
+
def resolve(*args)
|
53
|
+
@resolver.resolve(*args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def reject(*args)
|
57
|
+
@resolver.reject(*args)
|
58
|
+
end
|
59
|
+
|
60
|
+
def callback(&block)
|
61
|
+
@promise.callback(&block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def errback(&block)
|
65
|
+
@promise.errback(&block)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.resolved(value)
|
69
|
+
d = self.new
|
70
|
+
d.resolve(vaule)
|
71
|
+
d
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.rejected(value)
|
75
|
+
d = self.new
|
76
|
+
d.reject(vaule)
|
77
|
+
d
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
module Functions
|
82
|
+
def deferred(val)
|
83
|
+
return val if val.respond_to?(:callback) && val.respond_to?(:errback)
|
84
|
+
Deferred.resolved(val).promise
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#--
|
3
|
+
# Copyright (C) 2012 Gitorious AS
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Affero General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#++
|
18
|
+
require "dolt/git/shell"
|
19
|
+
require "dolt/git/repository"
|
20
|
+
|
21
|
+
module Dolt
|
22
|
+
class DiskRepoResolver
|
23
|
+
def initialize(root)
|
24
|
+
@root = root
|
25
|
+
end
|
26
|
+
|
27
|
+
def resolve(repo)
|
28
|
+
git = Dolt::Git::Shell.new(File.join(root, repo))
|
29
|
+
Dolt::Git::Repository.new(repo, git)
|
30
|
+
end
|
31
|
+
|
32
|
+
def all
|
33
|
+
Dir.entries(root).reject do |e|
|
34
|
+
e =~ /^\.+$/ || File.file?(File.join(root, e))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def root; @root; end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#--
|
3
|
+
# Copyright (C) 2012 Gitorious AS
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Affero General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#++
|
18
|
+
module Dolt
|
19
|
+
class Blob
|
20
|
+
attr_reader :path, :raw, :repo
|
21
|
+
|
22
|
+
def initialize(path, raw)
|
23
|
+
@path = path
|
24
|
+
@raw = raw
|
25
|
+
end
|
26
|
+
|
27
|
+
def lines
|
28
|
+
raw.split("\n")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#--
|
3
|
+
# Copyright (C) 2012 Gitorious AS
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Affero General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#++
|
18
|
+
require "dolt/async/when"
|
19
|
+
require "dolt/git/blob"
|
20
|
+
|
21
|
+
module Dolt
|
22
|
+
module Git
|
23
|
+
class Repository
|
24
|
+
attr_reader :name
|
25
|
+
|
26
|
+
def initialize(name, git = nil)
|
27
|
+
@name = name
|
28
|
+
@git = git
|
29
|
+
end
|
30
|
+
|
31
|
+
def blob(path, ref = "HEAD")
|
32
|
+
gitop = git.show(path, ref)
|
33
|
+
deferred = When::Deferred.new
|
34
|
+
|
35
|
+
gitop.callback do |data, status|
|
36
|
+
deferred.resolve(Dolt::Blob.new(path, data))
|
37
|
+
end
|
38
|
+
|
39
|
+
gitop.errback { |err| deferred.reject(err) }
|
40
|
+
deferred.promise
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def git; @git; end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|