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 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