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 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/git/file_system_repository_resolver"
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
- options = { :cache => false, :layout => "layout" }
41
- view = Dolt::TemplateRenderer.new(template_root, options)
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"))
@@ -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
- class Blob
20
- attr_reader :path, :raw, :repo
19
+ module Git
20
+ class Blob
21
+ attr_reader :path, :raw, :repo
21
22
 
22
- def initialize(path, raw)
23
- @path = path
24
- @raw = raw
25
- end
23
+ def initialize(path, raw)
24
+ @path = path
25
+ @raw = raw
26
+ end
26
27
 
27
- def lines
28
- raw.split("\n")
28
+ def lines
29
+ raw.split("\n")
30
+ end
29
31
  end
30
32
  end
31
33
  end
@@ -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
- gitop = git.show(path, ref)
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(Dolt::Blob.new(path, data))
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
@@ -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
@@ -23,7 +23,7 @@ module Dolt
23
23
  @repo_resolver = repo_resolver
24
24
  end
25
25
 
26
- def blob(repo, ref, path, &block)
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
@@ -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, ref, path)
27
- actions.blob(repo, ref, path) do |status, data|
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(*params[:splat])
37
+ blob(params[:splat][0], params[:splat][2], params[:splat][1])
30
38
  end
31
39
 
32
40
  aget "/*/blob/*" do
33
- redirect(params[:splat].shift + "/blob/master:" + params[:splat].join)
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("/blob/master:Readme.md")
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, ref, path)
44
+ blob(repo, path, ref)
37
45
  end
38
46
 
39
47
  aget "/blob/*" do
40
- redirect("/blob/master:" + params[:splat].join)
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
@@ -17,5 +17,5 @@
17
17
  #++
18
18
 
19
19
  module Dolt
20
- VERSION = "0.1.0"
20
+ VERSION = "0.1.1"
21
21
  end
@@ -20,8 +20,9 @@ require "dolt/view/highlighter"
20
20
 
21
21
  module Dolt
22
22
  module View
23
- def breadcrumb(repository, ref, path)
24
- Dolt::View::Breadcrumb.new.render(repository, ref, path)
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
@@ -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="/files"><i class="icon icon-file"></i></a></li>
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=\"/#{repo}/tree/#{ref}:#{accumulated.join('/')}\">" +
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
@@ -47,3 +47,6 @@ module Dolt
47
47
  end
48
48
 
49
49
  Dolt::View::Highlighter.add_lexer_alias("yml", "yaml")
50
+ Dolt::View::Highlighter.add_lexer_alias("Rakefile", "rb")
51
+ Dolt::View::Highlighter.add_lexer_alias("Gemfile", "rb")
52
+ Dolt::View::Highlighter.add_lexer_alias("gemspec", "rb")
@@ -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
- cmds << ["show", path, ref]
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
@@ -24,55 +24,89 @@ describe Dolt::Git::Shell do
24
24
  include EM::MiniTest::Spec
25
25
  include Dolt::StdioStub
26
26
 
27
- it "assumes git dir in work tree" do
28
- expected_cmd = ["git --git-dir /somewhere/.git ",
29
- "--work-tree /somewhere log"].join
30
- Dolt::DeferrableChildProcess.expects(:open).with(expected_cmd)
31
- git = Dolt::Git::Shell.new("/somewhere")
32
- git.git("log")
33
- end
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
- it "uses provided git dir" do
36
- expected_cmd = ["git --git-dir /somewhere/.git ",
37
- "--work-tree /elsewhere log"].join
38
- Dolt::DeferrableChildProcess.expects(:open).with(expected_cmd)
39
- git = Dolt::Git::Shell.new("/elsewhere", "/somewhere/.git")
40
- git.git("log")
41
- end
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
- it "returns deferrable" do
44
- silence_stderr do
45
- git = Dolt::Git::Shell.new("/somwhere")
46
- result = git.git("log")
44
+ it "returns deferrable" do
45
+ silence_stderr do
46
+ git = Dolt::Git::Shell.new("/somwhere")
47
+ result = git.git("log")
47
48
 
48
- assert result.respond_to?(:callback)
49
- assert result.respond_to?(:errback)
49
+ assert result.respond_to?(:callback)
50
+ assert result.respond_to?(:errback)
51
+ end
50
52
  end
51
- end
52
53
 
53
- it "joins arguments with spaces" do
54
- expected_cmd = ["git --git-dir /somewhere/.git ",
55
- "--work-tree /somewhere push origin master"].join
56
- Dolt::DeferrableChildProcess.expects(:open).with(expected_cmd)
57
- git = Dolt::Git::Shell.new("/somewhere")
58
- git.git("push", "origin", "master")
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
- it "calls errback when git operation fails" do
62
- silence_stderr do
75
+ describe "#show" do
76
+ it "shows a file" do
63
77
  git = Dolt::Git::Shell.new("/somewhere")
64
- result = git.git("push", "origin", "master")
65
- result.errback do |status|
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
- it "shows a file" do
74
- git = Dolt::Git::Shell.new("/somewhere")
75
- git.expects(:git).with("show", "master:app/models/repository.rb")
76
- result = git.show("app/models/repository.rb", "master")
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 yield_blob(blob)
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", "master", "app")
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 ref to block" do
65
+ it "yields blob, repo, ref and base_tree_url to block" do
61
66
  data = nil
62
- @actions.blob("gitorious", "babd120", "app") do |status, d|
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.yield_blob "Blob"
72
+ repo.resolve_promise "Blob"
68
73
 
69
- expected = { :blob => "Blob", :repository => repo, :ref => "babd120" }
70
- assert_equal expected, data
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
@@ -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="/<%= repository.name %>/blame/<%= ref %>:<%= blob.path %>">Blame</a></li>
38
- <li><a href="/<%= repository.name %>/history/<%= ref %>:<%= blob.path %>">History</a></li>
39
- <li><a href="/<%= repository.name %>/raw/<%= ref %>:<%= blob.path %>">Raw blob</a></li>
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, blob.path) %>
42
+ <%= breadcrumb(repository, blob.path, ref, :multi_repo_mode => multi_repo_mode) %>
42
43
  <%= highlight_lines(blob.path, blob.raw) %>
43
44
  </div>
@@ -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: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
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