dolt 0.1.0 → 0.1.1
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/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
|