dolt 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/Gemfile.lock +25 -5
  2. data/Readme.md +90 -16
  3. data/bin/dolt +22 -4
  4. data/dolt.gemspec +10 -2
  5. data/lib/dolt/disk_repo_resolver.rb +3 -5
  6. data/lib/dolt/git/blame.rb +112 -0
  7. data/lib/dolt/git/commit.rb +73 -0
  8. data/lib/dolt/git/repository.rb +26 -24
  9. data/lib/dolt/repo_actions.rb +32 -19
  10. data/lib/dolt/sinatra/actions.rb +51 -18
  11. data/lib/dolt/sinatra/multi_repo_browser.rb +30 -3
  12. data/lib/dolt/sinatra/single_repo_browser.rb +36 -2
  13. data/lib/dolt/template_renderer.rb +7 -8
  14. data/lib/dolt/version.rb +1 -1
  15. data/lib/dolt/view.rb +3 -61
  16. data/lib/dolt/view/blame.rb +57 -0
  17. data/lib/dolt/view/blob.rb +60 -0
  18. data/lib/dolt/view/breadcrumb.rb +10 -17
  19. data/lib/dolt/{git/blob.rb → view/commit.rb} +5 -11
  20. data/lib/dolt/view/gravatar.rb +29 -0
  21. data/lib/dolt/{git/shell.rb → view/markup.rb} +10 -16
  22. data/lib/dolt/view/multi_repository.rb +27 -0
  23. data/lib/dolt/{async/deferrable_child_process.rb → view/object.rb} +11 -24
  24. data/lib/dolt/view/single_repository.rb +27 -0
  25. data/lib/dolt/view/smart_blob_renderer.rb +33 -0
  26. data/lib/dolt/view/syntax_highlight.rb +86 -0
  27. data/lib/dolt/view/tree.rb +69 -0
  28. data/test/dolt/git/blame_test.rb +128 -0
  29. data/test/dolt/git/commit_test.rb +89 -0
  30. data/test/dolt/git/repository_test.rb +24 -73
  31. data/test/dolt/repo_actions_test.rb +77 -15
  32. data/test/dolt/sinatra/actions_test.rb +168 -8
  33. data/test/dolt/template_renderer_test.rb +44 -10
  34. data/test/dolt/templates/blame_test.rb +56 -0
  35. data/test/dolt/{views → templates}/blob_test.rb +44 -34
  36. data/test/dolt/templates/commits_test.rb +61 -0
  37. data/test/dolt/templates/raw_test.rb +41 -0
  38. data/test/dolt/templates/tree_test.rb +51 -0
  39. data/test/dolt/view/blame_test.rb +122 -0
  40. data/test/dolt/view/blob_test.rb +90 -0
  41. data/test/dolt/view/breadcrumb_test.rb +46 -0
  42. data/test/dolt/view/commit_test.rb +31 -0
  43. data/test/dolt/view/gravatar_test.rb +30 -0
  44. data/test/dolt/view/markup_test.rb +30 -0
  45. data/test/dolt/{git/blob_test.rb → view/multi_repository_test.rb} +10 -24
  46. data/test/dolt/view/object_test.rb +71 -0
  47. data/test/dolt/view/single_repository_test.rb +30 -0
  48. data/test/dolt/{view_test.rb → view/syntax_highlight_test.rb} +40 -27
  49. data/test/dolt/view/tree_test.rb +115 -0
  50. data/test/test_helper.rb +18 -13
  51. data/vendor/ui/css/gitorious.css +20 -8
  52. data/views/blame.erb +41 -0
  53. data/views/blob.erb +6 -9
  54. data/views/commits.erb +23 -0
  55. data/views/index.erb +25 -0
  56. data/views/raw.erb +19 -0
  57. data/views/tree.erb +28 -26
  58. metadata +156 -26
  59. data/lib/dolt/git/tree.rb +0 -65
  60. data/lib/dolt/view/highlighter.rb +0 -52
  61. data/test/dolt/git/shell_test.rb +0 -112
  62. data/test/dolt/git/tree_test.rb +0 -120
data/Gemfile.lock CHANGED
@@ -3,11 +3,17 @@ PATH
3
3
  specs:
4
4
  dolt (0.1.1)
5
5
  async_sinatra (~> 1.0)
6
- eventmachine (~> 0.12)
6
+ builder (~> 3.1)
7
+ em_pessimistic (~> 0.1)
8
+ em_rugged (~> 0.1.0)
9
+ eventmachine (~> 1.0)
10
+ github-markup (~> 0.7)
11
+ htmlentities (~> 4.3)
7
12
  pygments.rb (~> 0.2)
8
13
  sinatra (~> 1.3)
9
14
  thin (~> 1.4)
10
15
  tilt (~> 1.3)
16
+ tzinfo (~> 0.3)
11
17
 
12
18
  GEM
13
19
  remote: http://rubygems.org/
@@ -15,23 +21,35 @@ GEM
15
21
  async_sinatra (1.0.0)
16
22
  rack (>= 1.4.1)
17
23
  sinatra (>= 1.3.2)
18
- blankslate (2.1.2.4)
24
+ blankslate (3.1.2)
25
+ builder (3.1.3)
19
26
  daemons (1.1.9)
20
27
  em-minitest-spec (1.1.1)
21
28
  eventmachine
22
- eventmachine (0.12.10)
29
+ em_pessimistic (0.1.2)
30
+ eventmachine (~> 1.0)
31
+ em_rugged (0.1.1)
32
+ eventmachine (~> 1.0)
33
+ rugged (~> 0.17)
34
+ eventmachine (1.0.0)
23
35
  ffi (1.0.11)
24
- minitest (2.1.0)
25
- mocha (0.9.12)
36
+ github-markup (0.7.4)
37
+ htmlentities (4.3.1)
38
+ metaclass (0.0.1)
39
+ minitest (2.12.1)
40
+ mocha (0.12.4)
41
+ metaclass (~> 0.0.1)
26
42
  pygments.rb (0.2.13)
27
43
  rubypython (~> 0.5.3)
28
44
  rack (1.4.1)
29
45
  rack-protection (1.2.0)
30
46
  rack
31
47
  rake (0.9.2.2)
48
+ redcarpet (2.1.1)
32
49
  rubypython (0.5.3)
33
50
  blankslate (>= 2.1.2.3)
34
51
  ffi (~> 1.0.7)
52
+ rugged (0.17.0)
35
53
  sinatra (1.3.3)
36
54
  rack (~> 1.3, >= 1.3.6)
37
55
  rack-protection (~> 1.2)
@@ -41,6 +59,7 @@ GEM
41
59
  eventmachine (>= 0.12.6)
42
60
  rack (>= 1.0.0)
43
61
  tilt (1.3.3)
62
+ tzinfo (0.3.33)
44
63
 
45
64
  PLATFORMS
46
65
  ruby
@@ -51,3 +70,4 @@ DEPENDENCIES
51
70
  minitest (~> 2.0)
52
71
  mocha
53
72
  rake (~> 0.9)
73
+ redcarpet
data/Readme.md CHANGED
@@ -1,25 +1,99 @@
1
1
  # Dolt - The Git project browser
2
2
 
3
- Dolt is a stand-alone server that allows you to browse git repositories in your
4
- browser. It uses Pygments to syntax highlight code, and displays blame as well
5
- as git history for individual files.
3
+ Dolt is a stand-alone Git repository browser. It can be used to explore repos in
4
+ your browser of choice and features syntax highlighting with
5
+ [Pygments](http://pygments.org/),
6
+ [Markdown](http://daringfireball.net/projects/markdown/)/[org-mode](http://orgmode.org/)/[+++](https://github.com/github/markup/)
7
+ rendering, commit log and blame.
6
8
 
7
- Dolt can also be used as a library to serve git trees from e.g. a Rails app. It
8
- is the blob viewer implementation that will be used in the Gitorious application
9
- (gitorious.org) when it is ready.
9
+ Dolt is also a library, designed to render Git trees, blobs, commit log and
10
+ blame. It can render said views with or without a layout, or you can provide
11
+ your own templates (through [Tilt](https://github.com/rtomayko/tilt/)). You can
12
+ also provide your own rendering implementation to render other formats than
13
+ templates outputting HTML.
10
14
 
11
- ## Blobs
15
+ Dolt is the implementation of the next generation repo browser to be used in the
16
+ [Gitorious](http://gitorious.org) software.
12
17
 
13
- Dolt currenly only serves blobs. The sample Rack application that comes with
14
- Dolt allows you to surf repos locally on your disk:
18
+ ## Installing Dolt
15
19
 
16
- env REPO_ROOT=/where/git/repos/reside rackup -Ilib
20
+ To install `dolt` you need Ruby, RubyGems and Python development files. The
21
+ Python development files are required to support Pygments syntax highlighting.
17
22
 
18
- That command will start the server, and allow you to view blobs in repos
19
- available in the `/where/git/repos/reside` directory. For example, on my machine,
20
- when I issue:
23
+ Note: Dolt uses [libgit2](http://libgit2.github.com) and its Ruby bindings,
24
+ [Rugged](http://github.com/libgit2/rugged) through
25
+ [em-rugged](http://gitorious.org/gitorious/em-rugged) for Git access where
26
+ feasible. Currently, ``EMRugged`` relies on a version of `Rugged` that is not
27
+ yet released, so you have to build it yourself.
28
+ [See em-rugged instructions](http://github.com/cjohansen/em-rugged).
21
29
 
22
- env REPO_ROOT=/home/christian/projects rackup -Ilib
30
+ ### Systems using apt (Debian/Ubuntu, others)
23
31
 
24
- I can go to [http://localhost:9292/gitorious/blob/master:app/models/repository.rb](http://localhost:9292/gitorious/blob/master:app/models/repository.rb)
25
- to view Gitorious blobs.
32
+ # 1) Install Ruby (skip if you already have Ruby installed)
33
+ sudo apt-get install ruby
34
+
35
+ # 2) Install Python development files
36
+ sudo apt-get install python-dev
37
+
38
+ # 3) Install dolt. This may or may not require the use of sudo, depending on
39
+ # how you installed Ruby. This step assumes that you already built and
40
+ # installed em-rugged as explained above.
41
+ sudo gem install dolt
42
+
43
+ ### Systems using yum (Fedora/CentOS/RedHat, others)
44
+
45
+ # 1) Install Ruby (skip if you already have Ruby installed)
46
+ sudo yum install ruby
47
+
48
+ # 2) Install Python development files
49
+ sudo yum install python-devel
50
+
51
+ # 3) Install dolt. This may or may not require the use of sudo, depending on
52
+ # how you installed Ruby. This step assumes that you already built and
53
+ # installed em-rugged as explained above.
54
+ sudo gem install dolt
55
+
56
+ # The Dolt CLI
57
+
58
+ The `dolt` library installs a CLI that can be used to quickly browse either a
59
+ single (typically the current) repository, or multiple repositories.
60
+
61
+ ## Browsing a single repository
62
+
63
+ In a git repository, issue the following command:
64
+
65
+ $ dolt .
66
+
67
+ Then open a browser at [http://localhost:3000](http://localhost:3000). You will
68
+ be redirected to the root tree, and can browse the repository. To view trees and
69
+ blobs at specific refs, use the URL. A branch/tag selector will be added later.
70
+
71
+ ## Browsing multiple repositories
72
+
73
+ The idea is that eventually, `dolt` should be able to serve up all Git
74
+ repositories managed by your Gitorious server. It does not yet do that, because
75
+ there currently is no "repository resolver" that understands the hashed paths
76
+ Gitorious uses.
77
+
78
+ Meanwhile, if you have a directory that contains multiple git repositories, you
79
+ can browse all of them through the same process by doing:
80
+
81
+ $ dolt /path/to/repos
82
+
83
+ Now [http://localhost:3000/repo](http://localhost:3000/repo) will allow you to
84
+ browse the `/path/repos/repo` repository. As `dolt` matures, there will be a
85
+ listing of all repositories and more.
86
+
87
+ ## Markup rendering
88
+
89
+ Dolt uses the [``GitHub::Markup``](https://github.com/github/markup/) library to
90
+ render certain markup formats as HTML. Dolt does not have a hard dependency on
91
+ any of the required gems to actually render markups, so see the
92
+ [``GitHub::Markup`` docs](https://github.com/github/markup/) for information on
93
+ what and how to install support for various languages.
94
+
95
+ # License
96
+
97
+ Dolt is free software licensed under the
98
+ [GNU Affero General Public License (AGPL)](http://www.gnu.org/licenses/agpl-3.0.html).
99
+ Dolt is developed as part of the Gitorious project.
data/bin/dolt CHANGED
@@ -21,14 +21,16 @@ end
21
21
 
22
22
  def create_app(dir, view)
23
23
  if is_git_repo?(dir)
24
- require "dolt/sinatra/single_repo_browser"
25
24
  dir = File.expand_path(dir)
26
25
  resolver = Dolt::DiskRepoResolver.new(File.dirname(dir))
27
26
  actions = Dolt::RepoActions.new(resolver)
27
+ view.helper(Dolt::View::SingleRepository)
28
+ require "dolt/sinatra/single_repo_browser"
28
29
  Dolt::Sinatra::SingleRepoBrowser.new(File.basename(dir), actions, view)
29
30
  else
30
31
  resolver = Dolt::DiskRepoResolver.new(dir)
31
32
  actions = Dolt::RepoActions.new(resolver)
33
+ view.helper(Dolt::View::MultiRepository)
32
34
  require "dolt/sinatra/multi_repo_browser"
33
35
  Dolt::Sinatra::MultiRepoBrowser.new(actions, view)
34
36
  end
@@ -39,11 +41,27 @@ base = File.join(File.dirname(__FILE__), "..")
39
41
  template_root = File.join(base, "views")
40
42
  view = Dolt::TemplateRenderer.new(template_root, {
41
43
  :cache => false,
42
- :layout => "layout",
43
- :attributes => { :multi_repo_mode => !is_git_repo?(ARGV[0]) }
44
+ :layout => "layout"
44
45
  })
45
46
 
46
- view.helper(Dolt::View)
47
+ view.helper(Dolt::View::Object)
48
+ view.helper(Dolt::View::Blob)
49
+ view.helper(Dolt::View::Blame)
50
+ view.helper(Dolt::View::Breadcrumb)
51
+ view.helper(Dolt::View::Tree)
52
+ view.helper(Dolt::View::Commit)
53
+ view.helper(Dolt::View::Gravatar)
54
+
55
+ # Configure blob rendering module
56
+
57
+ # Attempt to syntax highlight every blob
58
+ # view.helper(Dolt::View::SyntaxHighlight)
59
+
60
+ # Attempt to render every blob as markup
61
+ # view.helper(Dolt::View::Markup)
62
+
63
+ # Render supported formats as markup, syntax highlight the rest
64
+ view.helper(Dolt::View::SmartBlobRenderer)
47
65
 
48
66
  Sinatra::Base.set(:public_folder, File.join(base, "vendor/ui"))
49
67
  server = create_app(ARGV[0], view)
data/dolt.gemspec CHANGED
@@ -1,5 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.join("lib/dolt/version")
2
+ dir = File.expand_path(File.dirname(__FILE__))
3
+ require File.join(dir, "lib/dolt/version")
3
4
 
4
5
  module GemSpecHelper
5
6
  def self.files(path)
@@ -20,17 +21,24 @@ Gem::Specification.new do |s|
20
21
 
21
22
  s.rubyforge_project = "dolt"
22
23
 
23
- s.add_dependency "eventmachine", "~>0.12"
24
+ s.add_dependency "eventmachine", "~>1.0"
24
25
  s.add_dependency "thin", "~>1.4"
25
26
  s.add_dependency "sinatra", "~>1.3"
26
27
  s.add_dependency "async_sinatra", "~>1.0"
27
28
  s.add_dependency "tilt", "~>1.3"
28
29
  s.add_dependency "pygments.rb", "~>0.2"
30
+ s.add_dependency "em_pessimistic", "~>0.1"
31
+ s.add_dependency "builder", "~> 3.1"
32
+ s.add_dependency "em_rugged", "~> 0.1.2"
33
+ s.add_dependency "tzinfo", "~> 0.3"
34
+ s.add_dependency "github-markup", "~> 0.7"
35
+ s.add_dependency "htmlentities", "~> 4.3"
29
36
 
30
37
  s.add_development_dependency "minitest", "~> 2.0"
31
38
  s.add_development_dependency "em-minitest-spec", "~> 1.1"
32
39
  s.add_development_dependency "rake", "~> 0.9"
33
40
  s.add_development_dependency "mocha"
41
+ s.add_development_dependency "redcarpet"
34
42
 
35
43
  s.files = GemSpecHelper.files(".") + GemSpecHelper.files("vendor/ui")
36
44
  s.test_files = `git ls-files -- {test}/*`.split("\n")
@@ -15,7 +15,6 @@
15
15
  # You should have received a copy of the GNU Affero General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  #++
18
- require "dolt/git/shell"
19
18
  require "dolt/git/repository"
20
19
 
21
20
  module Dolt
@@ -25,13 +24,12 @@ module Dolt
25
24
  end
26
25
 
27
26
  def resolve(repo)
28
- git = Dolt::Git::Shell.new(File.join(root, repo))
29
- Dolt::Git::Repository.new(repo, git)
27
+ Dolt::Git::Repository.new(File.join(root, repo))
30
28
  end
31
29
 
32
30
  def all
33
- Dir.entries(root).reject do |e|
34
- e =~ /^\.+$/ || File.file?(File.join(root, e))
31
+ Dir.entries(root).select do |e|
32
+ File.exists?(File.join(root, e, ".git"))
35
33
  end
36
34
  end
37
35
 
@@ -0,0 +1,112 @@
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 "tzinfo"
19
+
20
+ module Dolt
21
+ module Git
22
+ class Blame
23
+ attr_reader :chunks
24
+
25
+ def initialize(chunks)
26
+ @chunks = chunks
27
+ end
28
+
29
+ def self.parse_porcelain(output)
30
+ self.new(Dolt::Git::Blame::PorcelainParser.new(output).parse)
31
+ end
32
+
33
+ class PorcelainParser
34
+ def initialize(output)
35
+ @output = output
36
+ @commits = {}
37
+ end
38
+
39
+ def parse
40
+ lines = @output.split("\n")
41
+ chunks = []
42
+
43
+ while lines.length > 0
44
+ chunk = extract_header(lines)
45
+ affected_lines = extract_lines(lines, chunk[:num_lines])
46
+
47
+ if chunks.last && chunk[:oid] == chunks.last[:oid]
48
+ chunks.last[:lines].concat(affected_lines)
49
+ else
50
+ chunk[:lines] = affected_lines
51
+ chunks << chunk
52
+ end
53
+ end
54
+
55
+ chunks
56
+ end
57
+
58
+ def is_header?(line)
59
+ line =~ /^[0-9a-f]{40} \d+ \d+ \d+$/
60
+ end
61
+
62
+ def extract_header(lines)
63
+ header = lines.shift
64
+ pieces = header.scan(/^([0-9a-f]{40}) (\d+) (\d+) (\d+)$/).first
65
+ header = { :oid => pieces.first, :num_lines => pieces[3].to_i }
66
+
67
+ if lines.first =~ /^author/
68
+ header[:author] = extract_hash(lines, :author)
69
+ header[:committer] = extract_hash(lines, :committer)
70
+ header[:summary] = extract(lines, "summary")
71
+ throwaway = lines.shift until throwaway =~ /^filename/
72
+ @commits[header[:oid]] = header
73
+ else
74
+ header[:author] = @commits[header[:oid]][:author]
75
+ header[:committer] = @commits[header[:oid]][:committer]
76
+ header[:summary] = @commits[header[:oid]][:summary]
77
+ end
78
+
79
+ header
80
+ end
81
+
82
+ def extract_lines(lines, num)
83
+ extracted = []
84
+
85
+ num.times do
86
+ if extracted.length > 0
87
+ line = lines.shift # Header for next line
88
+ end
89
+
90
+ content = lines.shift # Actual content
91
+ extracted.push(content[1..content.length]) # 8 spaces padding
92
+ end
93
+
94
+ extracted
95
+ end
96
+
97
+ def extract_hash(lines, type)
98
+ {
99
+ :name => extract(lines, "#{type}"),
100
+ :mail => extract(lines, "#{type}-mail").gsub(/[<>]/, ""),
101
+ :time => (Time.at(extract(lines, "#{type}-time").to_i) +
102
+ Time.zone_offset(extract(lines, "#{type}-tz")))
103
+ }
104
+ end
105
+
106
+ def extract(lines, thing)
107
+ lines.shift.split("#{thing} ")[1]
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,73 @@
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 "parsedate"
19
+
20
+ module Dolt
21
+ module Git
22
+ class Commit
23
+ def self.parse_log(log)
24
+ commits = []
25
+ lines = log.split("\n")
26
+ commits << extract_commit(lines) while lines.length > 0
27
+ commits
28
+ end
29
+
30
+ def self.extract_commit(lines)
31
+ commit = { :oid => lines.shift.split(" ")[1] }
32
+ while (line = lines.shift) != ""
33
+ pieces = line.split(": ")
34
+ extract_property(commit, pieces[0], pieces[1])
35
+ end
36
+
37
+ commit[:summary] = extract_commit_summary(lines)
38
+ commit[:message] = extract_commit_message(lines)
39
+ commit
40
+ end
41
+
42
+ def self.extract_property(hash, name, value)
43
+ key = name.downcase.to_sym
44
+
45
+ case key
46
+ when :author
47
+ pieces = value.match(/(.*)\s<(.*)>/)
48
+ value = { :name => pieces[1], :email => pieces[2] }
49
+ when :date
50
+ value = Time.mktime(*ParseDate.parsedate(value))
51
+ end
52
+
53
+ hash[key] = value
54
+ end
55
+
56
+ def self.extract_commit_summary(lines)
57
+ summary = lines.shift
58
+ lines.shift if lines.first == ""
59
+ summary
60
+ end
61
+
62
+ def self.extract_commit_message(lines)
63
+ message = ""
64
+
65
+ while !lines.first.nil? && lines.first !~ /^commit [a-z0-9]{40}$/
66
+ message << lines.shift
67
+ end
68
+
69
+ message
70
+ end
71
+ end
72
+ end
73
+ end