dolt 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/dolt +7 -3
- data/lib/dolt/git/blob.rb +10 -8
- data/lib/dolt/git/repository.rb +17 -5
- data/lib/dolt/git/shell.rb +4 -0
- data/lib/dolt/git/tree.rb +65 -0
- data/lib/dolt/repo_actions.rb +13 -1
- data/lib/dolt/sinatra/actions.rb +13 -2
- data/lib/dolt/sinatra/multi_repo_browser.rb +15 -2
- data/lib/dolt/sinatra/single_repo_browser.rb +16 -3
- data/lib/dolt/template_renderer.rb +3 -0
- data/lib/dolt/version.rb +1 -1
- data/lib/dolt/view.rb +25 -2
- data/lib/dolt/view/breadcrumb.rb +11 -2
- data/lib/dolt/view/highlighter.rb +3 -0
- data/test/dolt/git/blob_test.rb +5 -5
- data/test/dolt/git/repository_test.rb +40 -1
- data/test/dolt/git/shell_test.rb +73 -39
- data/test/dolt/git/tree_test.rb +120 -0
- data/test/dolt/repo_actions_test.rb +36 -7
- data/test/dolt/template_renderer_test.rb +8 -0
- data/test/dolt/views/blob_test.rb +19 -7
- data/views/blob.erb +5 -4
- data/views/tree.erb +44 -0
- metadata +6 -3
data/bin/dolt
CHANGED
@@ -4,7 +4,7 @@ require "sinatra/base"
|
|
4
4
|
require "dolt/repo_actions"
|
5
5
|
require "dolt/template_renderer"
|
6
6
|
require "dolt/view"
|
7
|
-
require "dolt/
|
7
|
+
require "dolt/disk_repo_resolver"
|
8
8
|
|
9
9
|
if ARGV.length == 0
|
10
10
|
puts("Dolt should be run with a directory as its sole argument")
|
@@ -37,8 +37,12 @@ end
|
|
37
37
|
base = File.join(File.dirname(__FILE__), "..")
|
38
38
|
|
39
39
|
template_root = File.join(base, "views")
|
40
|
-
|
41
|
-
|
40
|
+
view = Dolt::TemplateRenderer.new(template_root, {
|
41
|
+
:cache => false,
|
42
|
+
:layout => "layout",
|
43
|
+
:attributes => { :multi_repo_mode => !is_git_repo?(ARGV[0]) }
|
44
|
+
})
|
45
|
+
|
42
46
|
view.helper(Dolt::View)
|
43
47
|
|
44
48
|
Sinatra::Base.set(:public_folder, File.join(base, "vendor/ui"))
|
data/lib/dolt/git/blob.rb
CHANGED
@@ -16,16 +16,18 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
#++
|
18
18
|
module Dolt
|
19
|
-
|
20
|
-
|
19
|
+
module Git
|
20
|
+
class Blob
|
21
|
+
attr_reader :path, :raw, :repo
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
def initialize(path, raw)
|
24
|
+
@path = path
|
25
|
+
@raw = raw
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
28
|
+
def lines
|
29
|
+
raw.split("\n")
|
30
|
+
end
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
data/lib/dolt/git/repository.rb
CHANGED
@@ -17,6 +17,7 @@
|
|
17
17
|
#++
|
18
18
|
require "dolt/async/when"
|
19
19
|
require "dolt/git/blob"
|
20
|
+
require "dolt/git/tree"
|
20
21
|
|
21
22
|
module Dolt
|
22
23
|
module Git
|
@@ -29,19 +30,30 @@ module Dolt
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def blob(path, ref = "HEAD")
|
32
|
-
|
33
|
+
async_git(git.show(path, ref)) do |data, status|
|
34
|
+
Dolt::Git::Blob.new(path, data)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def tree(path, ref = "HEAD")
|
39
|
+
async_git(git.ls_tree(path, ref)) do |data, status|
|
40
|
+
Dolt::Git::Tree.parse(path, data)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def git; @git; end
|
46
|
+
|
47
|
+
def async_git(gitop, &block)
|
33
48
|
deferred = When::Deferred.new
|
34
49
|
|
35
50
|
gitop.callback do |data, status|
|
36
|
-
deferred.resolve(
|
51
|
+
deferred.resolve(block.call(data, status))
|
37
52
|
end
|
38
53
|
|
39
54
|
gitop.errback { |err| deferred.reject(err) }
|
40
55
|
deferred.promise
|
41
56
|
end
|
42
|
-
|
43
|
-
private
|
44
|
-
def git; @git; end
|
45
57
|
end
|
46
58
|
end
|
47
59
|
end
|
data/lib/dolt/git/shell.rb
CHANGED
@@ -29,6 +29,10 @@ module Dolt
|
|
29
29
|
git("show", "#{ref}:#{path}")
|
30
30
|
end
|
31
31
|
|
32
|
+
def ls_tree(path, ref)
|
33
|
+
git("ls-tree", ref, path.sub(/(^\.?\/)?/, "./").sub(/\/?$/, "/"))
|
34
|
+
end
|
35
|
+
|
32
36
|
def git(command, *args)
|
33
37
|
base = "git --git-dir #{@git_dir} --work-tree #{@work_tree}"
|
34
38
|
cmd = "#{base} #{command} #{args.join(' ')}".strip
|
@@ -0,0 +1,65 @@
|
|
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
|
+
module Git
|
20
|
+
class Tree
|
21
|
+
attr_reader :path, :entries
|
22
|
+
|
23
|
+
def initialize(path, entries)
|
24
|
+
@path = path
|
25
|
+
@entries = entries
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.parse(path, ls_tree_payload)
|
29
|
+
path = path == "" ? "./" : path
|
30
|
+
|
31
|
+
entries = ls_tree_payload.split("\n").collect do |line|
|
32
|
+
pieces = line.split(/\s+/)
|
33
|
+
klass = pieces[1] == "blob" ? File : Dir
|
34
|
+
klass.new(pieces[3], pieces[2], pieces[0])
|
35
|
+
end
|
36
|
+
|
37
|
+
dirs = entries.reject { |e| e.file? }.sort_by(&:path)
|
38
|
+
files = entries.reject { |e| e.dir? }.sort_by(&:path)
|
39
|
+
new(path, dirs + files)
|
40
|
+
end
|
41
|
+
|
42
|
+
class Entry
|
43
|
+
attr_reader :full_path, :path, :sha, :mode
|
44
|
+
|
45
|
+
def initialize(path, sha, mode)
|
46
|
+
@full_path = path
|
47
|
+
@path = ::File.basename(path)
|
48
|
+
@sha = sha
|
49
|
+
@mode = mode
|
50
|
+
end
|
51
|
+
|
52
|
+
def file?; false; end
|
53
|
+
def dir?; false; end
|
54
|
+
end
|
55
|
+
|
56
|
+
class File < Entry
|
57
|
+
def file?; true; end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Dir < Entry
|
61
|
+
def dir?; true; end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/dolt/repo_actions.rb
CHANGED
@@ -23,7 +23,7 @@ module Dolt
|
|
23
23
|
@repo_resolver = repo_resolver
|
24
24
|
end
|
25
25
|
|
26
|
-
def blob(repo,
|
26
|
+
def blob(repo, path, ref, &block)
|
27
27
|
repository = repo_resolver.resolve(repo)
|
28
28
|
d = repository.blob(path, ref)
|
29
29
|
d.callback do |blob, status|
|
@@ -35,6 +35,18 @@ module Dolt
|
|
35
35
|
d.errback { |err| block.call(err, nil) }
|
36
36
|
end
|
37
37
|
|
38
|
+
def tree(repo, path, ref, &block)
|
39
|
+
repository = repo_resolver.resolve(repo)
|
40
|
+
d = repository.tree(path, ref)
|
41
|
+
d.callback do |tree, status|
|
42
|
+
block.call(nil, {
|
43
|
+
:tree => tree,
|
44
|
+
:repository => repository,
|
45
|
+
:ref => ref })
|
46
|
+
end
|
47
|
+
d.errback { |err| block.call(err, nil) }
|
48
|
+
end
|
49
|
+
|
38
50
|
private
|
39
51
|
def repo_resolver; @repo_resolver; end
|
40
52
|
end
|
data/lib/dolt/sinatra/actions.rb
CHANGED
@@ -23,8 +23,8 @@ module Dolt
|
|
23
23
|
body("Process failed with exit code \n#{status.exitstatus}")
|
24
24
|
end
|
25
25
|
|
26
|
-
def blob(repo,
|
27
|
-
actions.blob(repo,
|
26
|
+
def blob(repo, path, ref)
|
27
|
+
actions.blob(repo, path, ref) do |status, data|
|
28
28
|
if status.nil?
|
29
29
|
response["Content-Type"] = "text/html"
|
30
30
|
body(renderer.render(:blob, data))
|
@@ -33,6 +33,17 @@ module Dolt
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
def tree(repo, path, ref)
|
38
|
+
actions.tree(repo, path, ref) do |status, data|
|
39
|
+
if status.nil?
|
40
|
+
response["Content-Type"] = "text/html"
|
41
|
+
body(renderer.render(:tree, data))
|
42
|
+
else
|
43
|
+
error(status)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
36
47
|
end
|
37
48
|
end
|
38
49
|
end
|
@@ -25,12 +25,25 @@ module Dolt
|
|
25
25
|
body("<h1>Welcome to Dolt</h1>")
|
26
26
|
end
|
27
27
|
|
28
|
+
aget "/*/tree/*:*" do
|
29
|
+
tree(params[:splat][0], params[:splat][2], params[:splat][1])
|
30
|
+
end
|
31
|
+
|
32
|
+
aget "/*/tree/*" do
|
33
|
+
force_ref(params[:splat], "tree", "master")
|
34
|
+
end
|
35
|
+
|
28
36
|
aget "/*/blob/*:*" do
|
29
|
-
blob(
|
37
|
+
blob(params[:splat][0], params[:splat][2], params[:splat][1])
|
30
38
|
end
|
31
39
|
|
32
40
|
aget "/*/blob/*" do
|
33
|
-
|
41
|
+
force_ref(params[:splat], "blob", "master")
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def force_ref(args, action, ref)
|
46
|
+
redirect(args.shift + "/#{action}/#{ref}:" + args.join)
|
34
47
|
end
|
35
48
|
end
|
36
49
|
end
|
@@ -28,16 +28,29 @@ module Dolt
|
|
28
28
|
end
|
29
29
|
|
30
30
|
aget "/" do
|
31
|
-
redirect("/
|
31
|
+
redirect("/tree/master:")
|
32
|
+
end
|
33
|
+
|
34
|
+
aget "/tree/*:*" do
|
35
|
+
tree(repo, params[:splat][1], params[:splat][0])
|
36
|
+
end
|
37
|
+
|
38
|
+
aget "/tree/*" do
|
39
|
+
force_ref(params[:splat], "tree", "master")
|
32
40
|
end
|
33
41
|
|
34
42
|
aget "/blob/*:*" do
|
35
43
|
ref, path = params[:splat]
|
36
|
-
blob(repo,
|
44
|
+
blob(repo, path, ref)
|
37
45
|
end
|
38
46
|
|
39
47
|
aget "/blob/*" do
|
40
|
-
|
48
|
+
force_ref(params[:splat], "blob", "master")
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def force_ref(args, action, ref)
|
53
|
+
redirect("/#{action}/#{ref}:" + args.join)
|
41
54
|
end
|
42
55
|
end
|
43
56
|
end
|
@@ -25,6 +25,7 @@ module Dolt
|
|
25
25
|
@layout = opt[:layout]
|
26
26
|
@type = opt[:type] || "erb"
|
27
27
|
@context_class = Class.new
|
28
|
+
@attributes = opt[:attributes] || {}
|
28
29
|
end
|
29
30
|
|
30
31
|
def helper(helper_module)
|
@@ -32,6 +33,7 @@ module Dolt
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def render(template, locals = {})
|
36
|
+
locals = locals.merge(attributes)
|
35
37
|
context = context_class.new
|
36
38
|
content = load(template).render(context, locals)
|
37
39
|
|
@@ -56,5 +58,6 @@ module Dolt
|
|
56
58
|
def layout; @layout; end
|
57
59
|
def type; @type; end
|
58
60
|
def context_class; @context_class; end
|
61
|
+
def attributes; @attributes; end
|
59
62
|
end
|
60
63
|
end
|
data/lib/dolt/version.rb
CHANGED
data/lib/dolt/view.rb
CHANGED
@@ -20,8 +20,9 @@ require "dolt/view/highlighter"
|
|
20
20
|
|
21
21
|
module Dolt
|
22
22
|
module View
|
23
|
-
def breadcrumb(repository, ref,
|
24
|
-
Dolt::View::Breadcrumb.new
|
23
|
+
def breadcrumb(repository, path, ref, options = {})
|
24
|
+
bc = Dolt::View::Breadcrumb.new(:multi_repo_mode => options[:multi_repo_mode])
|
25
|
+
bc.render(repository, ref, path)
|
25
26
|
end
|
26
27
|
|
27
28
|
def multiline(blob, options = {})
|
@@ -54,5 +55,27 @@ module Dolt
|
|
54
55
|
suffix = path.split(".").pop
|
55
56
|
Dolt::View::Highlighter.lexer(suffix)
|
56
57
|
end
|
58
|
+
|
59
|
+
def tree_url(repository, entry, ref, multi_repo_mode)
|
60
|
+
action = entry.file? ? "blob" : "tree"
|
61
|
+
repo_url(repository, "/#{action}/#{ref}:#{entry.full_path}", multi_repo_mode)
|
62
|
+
end
|
63
|
+
|
64
|
+
def blame_url(repository, blob, ref, multi_repo_mode)
|
65
|
+
repo_url(repository, "/blame/#{ref}:#{blob.path}", multi_repo_mode)
|
66
|
+
end
|
67
|
+
|
68
|
+
def history_url(repository, blob, ref, multi_repo_mode)
|
69
|
+
repo_url(repository, "/history/#{ref}:#{blob.path}", multi_repo_mode)
|
70
|
+
end
|
71
|
+
|
72
|
+
def raw_url(repository, blob, ref, multi_repo_mode)
|
73
|
+
repo_url(repository, "/raw/#{ref}:#{blob.path}", multi_repo_mode)
|
74
|
+
end
|
75
|
+
|
76
|
+
def repo_url(repository, url, multi_repo_mode)
|
77
|
+
prefix = multi_repo_mode ? "/#{repository.name}" : ""
|
78
|
+
"#{prefix}#{url}"
|
79
|
+
end
|
57
80
|
end
|
58
81
|
end
|
data/lib/dolt/view/breadcrumb.rb
CHANGED
@@ -18,13 +18,19 @@
|
|
18
18
|
module Dolt
|
19
19
|
module View
|
20
20
|
class Breadcrumb
|
21
|
+
attr_reader :multi_repo_mode
|
22
|
+
|
23
|
+
def initialize(options = {})
|
24
|
+
@multi_repo_mode = options[:multi_repo_mode]
|
25
|
+
end
|
26
|
+
|
21
27
|
def render(repository, ref, path)
|
22
28
|
dirs = path.split("/")
|
23
29
|
filename = dirs.pop
|
24
30
|
dir_html = accumulate_dirs(dirs, repository.name, ref)
|
25
31
|
<<-HTML
|
26
32
|
<ul class="breadcrumb">
|
27
|
-
<li><a href="/
|
33
|
+
<li><a href="#{prefix(repository)}/tree/#{ref}:"><i class="icon icon-file"></i></a></li>
|
28
34
|
#{dir_html}<li class="active">#{filename}</li>
|
29
35
|
</ul>
|
30
36
|
HTML
|
@@ -35,10 +41,13 @@ module Dolt
|
|
35
41
|
accumulated = []
|
36
42
|
dir_html = dirs.inject("") do |html, dir|
|
37
43
|
accumulated << dir
|
38
|
-
"#{html}<li><a href=\"
|
44
|
+
"#{html}<li><a href=\"#{prefix(repo)}/tree/#{ref}:#{accumulated.join('/')}\">" +
|
39
45
|
"#{dir}<span class=\"divider\">/</span></a></li>"
|
40
46
|
end
|
47
|
+
end
|
41
48
|
|
49
|
+
def prefix(repo)
|
50
|
+
multi_repo_mode ? "/#{repo}" : ""
|
42
51
|
end
|
43
52
|
end
|
44
53
|
end
|
data/test/dolt/git/blob_test.rb
CHANGED
@@ -18,10 +18,10 @@
|
|
18
18
|
require "test_helper"
|
19
19
|
require "dolt/git/blob"
|
20
20
|
|
21
|
-
describe Dolt::Blob do
|
21
|
+
describe Dolt::Git::Blob do
|
22
22
|
describe "#raw" do
|
23
23
|
it "returns full raw blob" do
|
24
|
-
blob = Dolt::Blob.new("file.txt", "Something something")
|
24
|
+
blob = Dolt::Git::Blob.new("file.txt", "Something something")
|
25
25
|
|
26
26
|
assert_equal "Something something", blob.raw
|
27
27
|
end
|
@@ -29,19 +29,19 @@ describe Dolt::Blob do
|
|
29
29
|
|
30
30
|
describe "#lines" do
|
31
31
|
it "returns empty array for empty blob" do
|
32
|
-
blob = Dolt::Blob.new("file.txt", "")
|
32
|
+
blob = Dolt::Git::Blob.new("file.txt", "")
|
33
33
|
|
34
34
|
assert_equal [], blob.lines
|
35
35
|
end
|
36
36
|
|
37
37
|
it "returns array of one line" do
|
38
|
-
blob = Dolt::Blob.new("file.txt", "Something something")
|
38
|
+
blob = Dolt::Git::Blob.new("file.txt", "Something something")
|
39
39
|
|
40
40
|
assert_equal ["Something something"], blob.lines
|
41
41
|
end
|
42
42
|
|
43
43
|
it "returns array of lines" do
|
44
|
-
blob = Dolt::Blob.new("file.txt", "Something\nsomething\nYup")
|
44
|
+
blob = Dolt::Git::Blob.new("file.txt", "Something\nsomething\nYup")
|
45
45
|
|
46
46
|
assert_equal ["Something", "something", "Yup"], blob.lines
|
47
47
|
end
|
@@ -28,7 +28,15 @@ class FakeGit
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def show(path, ref)
|
31
|
-
|
31
|
+
git("show", path, ref)
|
32
|
+
end
|
33
|
+
|
34
|
+
def ls_tree(path, ref)
|
35
|
+
git("ls-tree", path, ref)
|
36
|
+
end
|
37
|
+
|
38
|
+
def git(*args)
|
39
|
+
cmds << args
|
32
40
|
deferred = When::Deferred.new
|
33
41
|
deferreds << deferred.resolver
|
34
42
|
deferred.promise
|
@@ -67,4 +75,35 @@ describe Dolt::Git::Repository do
|
|
67
75
|
@git.last_resolver.resolve("class Repository;end")
|
68
76
|
end
|
69
77
|
end
|
78
|
+
|
79
|
+
describe "#tree" do
|
80
|
+
it "uses git ls-tree to list tree" do
|
81
|
+
repo = Dolt::Git::Repository.new("gitorious", @git)
|
82
|
+
repo.tree("app/models", "master")
|
83
|
+
|
84
|
+
assert_equal ["ls-tree", "app/models", "master"], @git.last_command
|
85
|
+
end
|
86
|
+
|
87
|
+
it "defaults to listing tree at HEAD" do
|
88
|
+
repo = Dolt::Git::Repository.new("gitorious", @git)
|
89
|
+
repo.tree("app/models")
|
90
|
+
|
91
|
+
assert_equal ["ls-tree", "app/models", "HEAD"], @git.last_command
|
92
|
+
end
|
93
|
+
|
94
|
+
it "invokes callback with tree object" do
|
95
|
+
repo = Dolt::Git::Repository.new("gitorious", @git)
|
96
|
+
d = repo.tree("app/models")
|
97
|
+
|
98
|
+
d.callback do |tree|
|
99
|
+
assert_equal 3, tree.entries.length
|
100
|
+
end
|
101
|
+
|
102
|
+
@git.last_resolver.resolve(<<-GIT)
|
103
|
+
100644 blob e90021f89616ddf86855d05337c188408d3b417e .gitmodules
|
104
|
+
100644 blob c80ee3697054566d1a4247d80be78ec3ddfde295 Gemfile
|
105
|
+
100644 blob 0053b3c95b0d9faa4916f7cd5e559c2b0f138027 Gemfile.lock
|
106
|
+
GIT
|
107
|
+
end
|
108
|
+
end
|
70
109
|
end
|
data/test/dolt/git/shell_test.rb
CHANGED
@@ -24,55 +24,89 @@ describe Dolt::Git::Shell do
|
|
24
24
|
include EM::MiniTest::Spec
|
25
25
|
include Dolt::StdioStub
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
describe "#git" do
|
28
|
+
it "assumes git dir in work tree" do
|
29
|
+
expected_cmd = ["git --git-dir /somewhere/.git ",
|
30
|
+
"--work-tree /somewhere log"].join
|
31
|
+
Dolt::DeferrableChildProcess.expects(:open).with(expected_cmd)
|
32
|
+
git = Dolt::Git::Shell.new("/somewhere")
|
33
|
+
git.git("log")
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
it "uses provided git dir" do
|
37
|
+
expected_cmd = ["git --git-dir /somewhere/.git ",
|
38
|
+
"--work-tree /elsewhere log"].join
|
39
|
+
Dolt::DeferrableChildProcess.expects(:open).with(expected_cmd)
|
40
|
+
git = Dolt::Git::Shell.new("/elsewhere", "/somewhere/.git")
|
41
|
+
git.git("log")
|
42
|
+
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
it "returns deferrable" do
|
45
|
+
silence_stderr do
|
46
|
+
git = Dolt::Git::Shell.new("/somwhere")
|
47
|
+
result = git.git("log")
|
47
48
|
|
48
|
-
|
49
|
-
|
49
|
+
assert result.respond_to?(:callback)
|
50
|
+
assert result.respond_to?(:errback)
|
51
|
+
end
|
50
52
|
end
|
51
|
-
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
it "joins arguments with spaces" do
|
55
|
+
expected_cmd = ["git --git-dir /somewhere/.git ",
|
56
|
+
"--work-tree /somewhere push origin master"].join
|
57
|
+
Dolt::DeferrableChildProcess.expects(:open).with(expected_cmd)
|
58
|
+
git = Dolt::Git::Shell.new("/somewhere")
|
59
|
+
git.git("push", "origin", "master")
|
60
|
+
end
|
61
|
+
|
62
|
+
it "calls errback when git operation fails" do
|
63
|
+
silence_stderr do
|
64
|
+
git = Dolt::Git::Shell.new("/somewhere")
|
65
|
+
result = git.git("push", "origin", "master")
|
66
|
+
result.errback do |status|
|
67
|
+
refute status.nil?
|
68
|
+
done!
|
69
|
+
end
|
70
|
+
wait!
|
71
|
+
end
|
72
|
+
end
|
59
73
|
end
|
60
74
|
|
61
|
-
|
62
|
-
|
75
|
+
describe "#show" do
|
76
|
+
it "shows a file" do
|
63
77
|
git = Dolt::Git::Shell.new("/somewhere")
|
64
|
-
|
65
|
-
result.
|
66
|
-
refute status.nil?
|
67
|
-
done!
|
68
|
-
end
|
69
|
-
wait!
|
78
|
+
git.expects(:git).with("show", "master:app/models/repository.rb")
|
79
|
+
result = git.show("app/models/repository.rb", "master")
|
70
80
|
end
|
71
81
|
end
|
72
82
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
83
|
+
describe "#ls_tree" do
|
84
|
+
it "lists tree root" do
|
85
|
+
git = Dolt::Git::Shell.new("/somewhere")
|
86
|
+
git.expects(:git).with("ls-tree", "master", "./")
|
87
|
+
|
88
|
+
result = git.ls_tree("", "master")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "lists tree root when starting with slash" do
|
92
|
+
git = Dolt::Git::Shell.new("/somewhere")
|
93
|
+
git.expects(:git).with("ls-tree", "master", "./")
|
94
|
+
|
95
|
+
result = git.ls_tree("/", "master")
|
96
|
+
end
|
97
|
+
|
98
|
+
it "lists path with trailing slash" do
|
99
|
+
git = Dolt::Git::Shell.new("/somewhere")
|
100
|
+
git.expects(:git).with("ls-tree", "master", "./app/models/")
|
101
|
+
|
102
|
+
result = git.ls_tree("app/models", "master")
|
103
|
+
end
|
104
|
+
|
105
|
+
it "lists path at given ref" do
|
106
|
+
git = Dolt::Git::Shell.new("/somewhere")
|
107
|
+
git.expects(:git).with("ls-tree", "v2.0.0", "./app/models/")
|
108
|
+
|
109
|
+
result = git.ls_tree("app/models/", "v2.0.0")
|
110
|
+
end
|
77
111
|
end
|
78
112
|
end
|
@@ -0,0 +1,120 @@
|
|
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 "test_helper"
|
19
|
+
require "dolt/git/tree"
|
20
|
+
|
21
|
+
describe Dolt::Git::Tree do
|
22
|
+
describe "parsing root tree" do
|
23
|
+
before do
|
24
|
+
lines = <<-GIT
|
25
|
+
100644 blob e90021f89616ddf86855d05337c188408d3b417e .gitmodules
|
26
|
+
100644 blob c80ee3697054566d1a4247d80be78ec3ddfde295 Gemfile
|
27
|
+
100644 blob 0053b3c95b0d9faa4916f7cd5e559c2b0f138027 Gemfile.lock
|
28
|
+
100644 blob 2ad22ff4b188c256d8ac97ded87c1c6ef6e96e43 Rakefile
|
29
|
+
100644 blob c8d1d197abfcd0f96c47583ec5f4328565cba433 Readme.md
|
30
|
+
040000 tree 18052467e73a1b7fb2613dc7b36baa554fab024b bin
|
31
|
+
100644 blob e83bb675977e7277698320cdd9c595c5698e5aa5 dolt.gemspec
|
32
|
+
040000 tree 4b051dd46c3ba70fbfd6a2484ec00121a70bee3a lib
|
33
|
+
040000 tree 86b096dc99b2cba28daa7676ed0dd38f709527b2 test
|
34
|
+
040000 tree d74d6bcb50cc5de9eb8fe019d7798b04d3a427e9 vendor
|
35
|
+
040000 tree be8fb09b735ac23265db2bec7c23e022a99ee730 views
|
36
|
+
GIT
|
37
|
+
|
38
|
+
@tree = Dolt::Git::Tree.parse("", lines)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "has path" do
|
42
|
+
assert_equal "./", @tree.path
|
43
|
+
end
|
44
|
+
|
45
|
+
it "extracts each line as an entry" do
|
46
|
+
assert_equal 11, @tree.entries.length
|
47
|
+
end
|
48
|
+
|
49
|
+
it "extracts file entry objects" do
|
50
|
+
gemfile = @tree.entries[6]
|
51
|
+
|
52
|
+
assert gemfile.file?
|
53
|
+
assert !gemfile.dir?
|
54
|
+
assert_equal "Gemfile", gemfile.path
|
55
|
+
assert_equal "Gemfile", gemfile.full_path
|
56
|
+
assert_equal "100644", gemfile.mode
|
57
|
+
assert_equal "c80ee3697054566d1a4247d80be78ec3ddfde295", gemfile.sha
|
58
|
+
end
|
59
|
+
|
60
|
+
it "extracts directory entry objects" do
|
61
|
+
bin = @tree.entries[0]
|
62
|
+
|
63
|
+
assert !bin.file?
|
64
|
+
assert bin.dir?
|
65
|
+
assert_equal "bin", bin.path
|
66
|
+
assert_equal "040000", bin.mode
|
67
|
+
assert_equal "18052467e73a1b7fb2613dc7b36baa554fab024b", bin.sha
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "parsing nested tree" do
|
72
|
+
before do
|
73
|
+
lines = <<-GIT
|
74
|
+
040000 tree c1d92125977841b672a10c96c6800e1b360a4e62 lib/dolt/async
|
75
|
+
100644 blob 6da3991090ba2df53eabe05bf4330aadf370a43a lib/dolt/disk_repo_resolver.rb
|
76
|
+
040000 tree 0142bdb42936094cdd92aa188d3193be85f7a6c1 lib/dolt/git
|
77
|
+
100644 blob 2b8674702e62aaa5607317ed83085e74a62b9781 lib/dolt/repo_actions.rb
|
78
|
+
040000 tree d93b4afc62ad460387cf5d91d98d1ad306219419 lib/dolt/sinatra
|
79
|
+
100644 blob 2a7e89f4b940e23a3d921199d9000e93da299872 lib/dolt/template_renderer.rb
|
80
|
+
100644 blob dfe78a965009e27d9cce7c9733787acb564b6630 lib/dolt/version.rb
|
81
|
+
100644 blob 685369dd2a66f0313b232ee898f8bbdafec6862d lib/dolt/view.rb
|
82
|
+
040000 tree 78347f337aaa613eb0a1c27ae7f89e39a22dcd6f lib/dolt/view
|
83
|
+
GIT
|
84
|
+
|
85
|
+
@tree = Dolt::Git::Tree.parse("lib/dolt", lines)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "does not include ./ in path" do
|
89
|
+
assert_equal "lib/dolt", @tree.path
|
90
|
+
end
|
91
|
+
|
92
|
+
it "strips root path from entries" do
|
93
|
+
assert_equal "disk_repo_resolver.rb", @tree.entries[4].path
|
94
|
+
end
|
95
|
+
|
96
|
+
it "groups tree by type, dirs first" do
|
97
|
+
assert @tree.entries[0].dir?
|
98
|
+
assert @tree.entries[1].dir?
|
99
|
+
assert @tree.entries[2].dir?
|
100
|
+
assert @tree.entries[3].dir?
|
101
|
+
assert @tree.entries[4].file?
|
102
|
+
assert @tree.entries[5].file?
|
103
|
+
assert @tree.entries[6].file?
|
104
|
+
assert @tree.entries[7].file?
|
105
|
+
assert @tree.entries[8].file?
|
106
|
+
end
|
107
|
+
|
108
|
+
it "sorts tree entries alphabetically" do
|
109
|
+
assert_equal "async", @tree.entries[0].path
|
110
|
+
assert_equal "git", @tree.entries[1].path
|
111
|
+
assert_equal "sinatra", @tree.entries[2].path
|
112
|
+
assert_equal "view", @tree.entries[3].path
|
113
|
+
assert_equal "disk_repo_resolver.rb", @tree.entries[4].path
|
114
|
+
assert_equal "repo_actions.rb", @tree.entries[5].path
|
115
|
+
assert_equal "template_renderer.rb", @tree.entries[6].path
|
116
|
+
assert_equal "version.rb", @tree.entries[7].path
|
117
|
+
assert_equal "view.rb", @tree.entries[8].path
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -28,7 +28,12 @@ class Repository
|
|
28
28
|
@deferred.promise
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def tree(path, ref)
|
32
|
+
@deferred = When::Deferred.new
|
33
|
+
@deferred.promise
|
34
|
+
end
|
35
|
+
|
36
|
+
def resolve_promise(blob)
|
32
37
|
@deferred.resolve(blob)
|
33
38
|
end
|
34
39
|
end
|
@@ -52,22 +57,46 @@ describe Dolt::RepoActions do
|
|
52
57
|
|
53
58
|
describe "#blob" do
|
54
59
|
it "resolves repository" do
|
55
|
-
@actions.blob("gitorious", "
|
60
|
+
@actions.blob("gitorious", "app", "master")
|
56
61
|
|
57
62
|
assert_equal ["gitorious"], @resolver.resolved.map(&:name)
|
58
63
|
end
|
59
64
|
|
60
|
-
it "yields blob, repo and
|
65
|
+
it "yields blob, repo, ref and base_tree_url to block" do
|
61
66
|
data = nil
|
62
|
-
@actions.blob("gitorious", "
|
67
|
+
@actions.blob("gitorious", "app", "babd120") do |status, d|
|
63
68
|
data = d
|
64
69
|
end
|
65
70
|
|
66
71
|
repo = @resolver.resolved.last
|
67
|
-
repo.
|
72
|
+
repo.resolve_promise "Blob"
|
68
73
|
|
69
|
-
|
70
|
-
|
74
|
+
assert_equal({
|
75
|
+
:blob => "Blob",
|
76
|
+
:repository => repo,
|
77
|
+
:ref => "babd120"
|
78
|
+
}, data)
|
71
79
|
end
|
72
80
|
end
|
81
|
+
|
82
|
+
describe "#tree" do
|
83
|
+
it "resolves repository" do
|
84
|
+
@actions.tree("gitorious", "app", "master")
|
85
|
+
|
86
|
+
assert_equal ["gitorious"], @resolver.resolved.map(&:name)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "yields tree, repo and ref to block" do
|
90
|
+
data = nil
|
91
|
+
@actions.tree("gitorious", "app", "babd120") do |status, d|
|
92
|
+
data = d
|
93
|
+
end
|
94
|
+
|
95
|
+
repo = @resolver.resolved.last
|
96
|
+
repo.resolve_promise "Tree"
|
97
|
+
|
98
|
+
expected = { :tree => "Tree", :repository => repo, :ref => "babd120" }
|
99
|
+
assert_equal expected, data
|
100
|
+
end
|
101
|
+
end
|
73
102
|
end
|
@@ -77,4 +77,12 @@ describe Dolt::TemplateRenderer do
|
|
77
77
|
|
78
78
|
assert_equal "Say it: YES", renderer.render(:file)
|
79
79
|
end
|
80
|
+
|
81
|
+
it "configures the renderer" do
|
82
|
+
renderer = Dolt::TemplateRenderer.new("/", { :attributes => { :stuff => "THING" } })
|
83
|
+
renderer.helper(ViewHelper)
|
84
|
+
File.stubs(:read).with("/file.erb").returns("<%= stuff %>")
|
85
|
+
|
86
|
+
assert_equal "THING", renderer.render(:file)
|
87
|
+
end
|
80
88
|
end
|
@@ -28,6 +28,9 @@ describe "blob template" do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def render(blob, options = {})
|
31
|
+
options[:attributes] = options[:attributes] || {}
|
32
|
+
attrs = options[:attributes]
|
33
|
+
if !attrs.key?(:multi_repo_mode); attrs[:multi_repo_mode] = true; end
|
31
34
|
renderer = Dolt::TemplateRenderer.new(@template_root, options)
|
32
35
|
renderer.helper(Dolt::View)
|
33
36
|
renderer.render(:blob, {
|
@@ -38,14 +41,14 @@ describe "blob template" do
|
|
38
41
|
end
|
39
42
|
|
40
43
|
it "renders blob without errors" do
|
41
|
-
blob = Dolt::Blob.new("file.txt", "Something something")
|
44
|
+
blob = Dolt::Git::Blob.new("file.txt", "Something something")
|
42
45
|
markup = render(blob)
|
43
46
|
|
44
47
|
assert_match /Something something/, markup
|
45
48
|
end
|
46
49
|
|
47
50
|
it "renders blob with line numbers" do
|
48
|
-
blob = Dolt::Blob.new("file.txt", "One\nTwo\nThree")
|
51
|
+
blob = Dolt::Git::Blob.new("file.txt", "One\nTwo\nThree")
|
49
52
|
markup = render(blob)
|
50
53
|
|
51
54
|
assert_match /<li.*One.*<\/li>/, markup
|
@@ -54,21 +57,21 @@ describe "blob template" do
|
|
54
57
|
end
|
55
58
|
|
56
59
|
it "renders blob with layout" do
|
57
|
-
blob = Dolt::Blob.new("file.txt", "Something something")
|
60
|
+
blob = Dolt::Git::Blob.new("file.txt", "Something something")
|
58
61
|
markup = render(blob, :layout => "layout")
|
59
62
|
|
60
63
|
assert_match /Something something/, markup
|
61
64
|
end
|
62
65
|
|
63
66
|
it "renders repo title in page" do
|
64
|
-
blob = Dolt::Blob.new("file.txt", "Something something")
|
67
|
+
blob = Dolt::Git::Blob.new("file.txt", "Something something")
|
65
68
|
markup = render(blob, :layout => "layout")
|
66
69
|
|
67
70
|
assert_match @repo.name, markup
|
68
71
|
end
|
69
72
|
|
70
73
|
it "renders links to other views" do
|
71
|
-
blob = Dolt::Blob.new("file.txt", "Something something")
|
74
|
+
blob = Dolt::Git::Blob.new("file.txt", "Something something")
|
72
75
|
markup = render(blob)
|
73
76
|
|
74
77
|
assert_match "/the-dolt/blame/master:file.txt", markup
|
@@ -76,8 +79,17 @@ describe "blob template" do
|
|
76
79
|
assert_match "/the-dolt/raw/master:file.txt", markup
|
77
80
|
end
|
78
81
|
|
82
|
+
it "renders links to other views in single repo mode" do
|
83
|
+
blob = Dolt::Git::Blob.new("file.txt", "Something something")
|
84
|
+
markup = render(blob, { :attributes => { :multi_repo_mode => false } })
|
85
|
+
|
86
|
+
assert_match "\"/blame/master:file.txt", markup
|
87
|
+
assert_match "\"/history/master:file.txt", markup
|
88
|
+
assert_match "\"/raw/master:file.txt", markup
|
89
|
+
end
|
90
|
+
|
79
91
|
it "renders links to other views for correct ref" do
|
80
|
-
blob = Dolt::Blob.new("file.txt", "Something something")
|
92
|
+
blob = Dolt::Git::Blob.new("file.txt", "Something something")
|
81
93
|
markup = render(blob, :ref => "123bc21")
|
82
94
|
|
83
95
|
assert_match "/the-dolt/blame/123bc21:file.txt", markup
|
@@ -86,7 +98,7 @@ describe "blob template" do
|
|
86
98
|
end
|
87
99
|
|
88
100
|
it "renders the path clickable" do
|
89
|
-
blob = Dolt::Blob.new("some/deeply/nested/file.txt", "Something something")
|
101
|
+
blob = Dolt::Git::Blob.new("some/deeply/nested/file.txt", "Something something")
|
90
102
|
markup = render(blob)
|
91
103
|
|
92
104
|
assert_match 'href="/the-dolt/tree/master:some"', markup
|
data/views/blob.erb
CHANGED
@@ -19,6 +19,7 @@
|
|
19
19
|
%>
|
20
20
|
<%
|
21
21
|
@title = "#{blob.path} in #{repository.name}:master"
|
22
|
+
if !defined?(multi_repo_mode); multi_repo_mode = false; end
|
22
23
|
%>
|
23
24
|
<div class="gts-file">
|
24
25
|
<%#
|
@@ -34,10 +35,10 @@
|
|
34
35
|
%>
|
35
36
|
<ul class="pull-right gts-blob-view">
|
36
37
|
<li class="active">Blob content</li>
|
37
|
-
<li><a href="
|
38
|
-
<li><a href="
|
39
|
-
<li><a href="
|
38
|
+
<li><a href="<%= blame_url(repository, blob, ref, multi_repo_mode) %>">Blame</a></li>
|
39
|
+
<li><a href="<%= history_url(repository, blob, ref, multi_repo_mode) %>">History</a></li>
|
40
|
+
<li><a href="<%= raw_url(repository, blob, ref, multi_repo_mode) %>">Raw blob</a></li>
|
40
41
|
</ul>
|
41
|
-
<%= breadcrumb(repository, ref,
|
42
|
+
<%= breadcrumb(repository, blob.path, ref, :multi_repo_mode => multi_repo_mode) %>
|
42
43
|
<%= highlight_lines(blob.path, blob.raw) %>
|
43
44
|
</div>
|
data/views/tree.erb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
<%#
|
2
|
+
# encoding: utf-8
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2012 Gitorious AS
|
5
|
+
#
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
17
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
%>
|
20
|
+
<% @title = "#{tree.path} in #{repository.name}:#{ref}" %>
|
21
|
+
<table class="table table-striped gts-tree-explorer">
|
22
|
+
<thead>
|
23
|
+
<tr>
|
24
|
+
<th>File</th>
|
25
|
+
<th>Changed</th>
|
26
|
+
<th colspan="2">Last commit</th>
|
27
|
+
</tr>
|
28
|
+
</thead>
|
29
|
+
<tbody>
|
30
|
+
<% tree.entries.each do |entry| %>
|
31
|
+
<tr>
|
32
|
+
<td class="gts-name">
|
33
|
+
<a href="<%= tree_url(repository, entry, ref, defined?(multi_repo_mode) && multi_repo_mode) %>">
|
34
|
+
<i class="icon <%= entry.file? ? "icon-file" : "icon-folder-close" %>"></i>
|
35
|
+
<%= entry.path %>
|
36
|
+
</a>
|
37
|
+
</td>
|
38
|
+
<td></td>
|
39
|
+
<td class="gts-sha"></td>
|
40
|
+
<td></td>
|
41
|
+
</tr>
|
42
|
+
<% end %>
|
43
|
+
</tbody>
|
44
|
+
</table>
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dolt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Christian Johansen
|
@@ -190,6 +190,7 @@ files:
|
|
190
190
|
- ./lib/dolt/git/blob.rb
|
191
191
|
- ./lib/dolt/git/repository.rb
|
192
192
|
- ./lib/dolt/git/shell.rb
|
193
|
+
- ./lib/dolt/git/tree.rb
|
193
194
|
- ./lib/dolt/repo_actions.rb
|
194
195
|
- ./lib/dolt/sinatra/actions.rb
|
195
196
|
- ./lib/dolt/sinatra/base.rb
|
@@ -203,6 +204,7 @@ files:
|
|
203
204
|
- ./test/dolt/git/blob_test.rb
|
204
205
|
- ./test/dolt/git/repository_test.rb
|
205
206
|
- ./test/dolt/git/shell_test.rb
|
207
|
+
- ./test/dolt/git/tree_test.rb
|
206
208
|
- ./test/dolt/repo_actions_test.rb
|
207
209
|
- ./test/dolt/sinatra/actions_test.rb
|
208
210
|
- ./test/dolt/template_renderer_test.rb
|
@@ -211,6 +213,7 @@ files:
|
|
211
213
|
- ./test/test_helper.rb
|
212
214
|
- ./views/blob.erb
|
213
215
|
- ./views/layout.erb
|
216
|
+
- ./views/tree.erb
|
214
217
|
- vendor/ui/bootstrap/css/bootstrap-responsive.min.css
|
215
218
|
- vendor/ui/bootstrap/css/bootstrap.min.css
|
216
219
|
- vendor/ui/bootstrap/img/glyphicons-halflings-white.png
|