dolt 0.1.1 → 0.2.0
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/Gemfile.lock +25 -5
- data/Readme.md +90 -16
- data/bin/dolt +22 -4
- data/dolt.gemspec +10 -2
- data/lib/dolt/disk_repo_resolver.rb +3 -5
- data/lib/dolt/git/blame.rb +112 -0
- data/lib/dolt/git/commit.rb +73 -0
- data/lib/dolt/git/repository.rb +26 -24
- data/lib/dolt/repo_actions.rb +32 -19
- data/lib/dolt/sinatra/actions.rb +51 -18
- data/lib/dolt/sinatra/multi_repo_browser.rb +30 -3
- data/lib/dolt/sinatra/single_repo_browser.rb +36 -2
- data/lib/dolt/template_renderer.rb +7 -8
- data/lib/dolt/version.rb +1 -1
- data/lib/dolt/view.rb +3 -61
- data/lib/dolt/view/blame.rb +57 -0
- data/lib/dolt/view/blob.rb +60 -0
- data/lib/dolt/view/breadcrumb.rb +10 -17
- data/lib/dolt/{git/blob.rb → view/commit.rb} +5 -11
- data/lib/dolt/view/gravatar.rb +29 -0
- data/lib/dolt/{git/shell.rb → view/markup.rb} +10 -16
- data/lib/dolt/view/multi_repository.rb +27 -0
- data/lib/dolt/{async/deferrable_child_process.rb → view/object.rb} +11 -24
- data/lib/dolt/view/single_repository.rb +27 -0
- data/lib/dolt/view/smart_blob_renderer.rb +33 -0
- data/lib/dolt/view/syntax_highlight.rb +86 -0
- data/lib/dolt/view/tree.rb +69 -0
- data/test/dolt/git/blame_test.rb +128 -0
- data/test/dolt/git/commit_test.rb +89 -0
- data/test/dolt/git/repository_test.rb +24 -73
- data/test/dolt/repo_actions_test.rb +77 -15
- data/test/dolt/sinatra/actions_test.rb +168 -8
- data/test/dolt/template_renderer_test.rb +44 -10
- data/test/dolt/templates/blame_test.rb +56 -0
- data/test/dolt/{views → templates}/blob_test.rb +44 -34
- data/test/dolt/templates/commits_test.rb +61 -0
- data/test/dolt/templates/raw_test.rb +41 -0
- data/test/dolt/templates/tree_test.rb +51 -0
- data/test/dolt/view/blame_test.rb +122 -0
- data/test/dolt/view/blob_test.rb +90 -0
- data/test/dolt/view/breadcrumb_test.rb +46 -0
- data/test/dolt/view/commit_test.rb +31 -0
- data/test/dolt/view/gravatar_test.rb +30 -0
- data/test/dolt/view/markup_test.rb +30 -0
- data/test/dolt/{git/blob_test.rb → view/multi_repository_test.rb} +10 -24
- data/test/dolt/view/object_test.rb +71 -0
- data/test/dolt/view/single_repository_test.rb +30 -0
- data/test/dolt/{view_test.rb → view/syntax_highlight_test.rb} +40 -27
- data/test/dolt/view/tree_test.rb +115 -0
- data/test/test_helper.rb +18 -13
- data/vendor/ui/css/gitorious.css +20 -8
- data/views/blame.erb +41 -0
- data/views/blob.erb +6 -9
- data/views/commits.erb +23 -0
- data/views/index.erb +25 -0
- data/views/raw.erb +19 -0
- data/views/tree.erb +28 -26
- metadata +156 -26
- data/lib/dolt/git/tree.rb +0 -65
- data/lib/dolt/view/highlighter.rb +0 -52
- data/test/dolt/git/shell_test.rb +0 -112
- 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
|
-
|
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 (
|
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
|
-
|
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
|
-
|
25
|
-
|
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
|
4
|
-
browser
|
5
|
-
|
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
|
8
|
-
|
9
|
-
(
|
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
|
-
|
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
|
-
|
14
|
-
Dolt allows you to surf repos locally on your disk:
|
18
|
+
## Installing Dolt
|
15
19
|
|
16
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
30
|
+
### Systems using apt (Debian/Ubuntu, others)
|
23
31
|
|
24
|
-
|
25
|
-
|
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
|
-
|
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
|
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
|
-
|
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).
|
34
|
-
|
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
|