dolt 0.3.1 → 0.4.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.
Files changed (39) hide show
  1. data/Gemfile.lock +1 -1
  2. data/lib/dolt/async/when.rb +47 -6
  3. data/lib/dolt/git/commit.rb +1 -1
  4. data/lib/dolt/git/repository.rb +39 -4
  5. data/lib/dolt/repo_actions.rb +5 -0
  6. data/lib/dolt/sinatra/actions.rb +11 -0
  7. data/lib/dolt/sinatra/multi_repo_browser.rb +14 -0
  8. data/lib/dolt/sinatra/single_repo_browser.rb +5 -0
  9. data/lib/dolt/version.rb +1 -1
  10. data/lib/dolt/view/blob.rb +4 -0
  11. data/test/dolt/async/when_test.rb +112 -0
  12. data/test/dolt/git/repository_test.rb +90 -0
  13. data/test/dolt/repo_actions_test.rb +49 -0
  14. data/test/dolt/sinatra/actions_test.rb +14 -0
  15. data/test/dolt/templates/tree_history_test.rb +93 -0
  16. data/test/dolt/templates/tree_test.rb +2 -1
  17. data/vendor/ui/.gitignore +2 -0
  18. data/vendor/ui/.gitmodules +15 -0
  19. data/vendor/ui/build +28 -0
  20. data/vendor/ui/buster.js +5 -2
  21. data/vendor/ui/css/gitorious.css +11 -0
  22. data/vendor/ui/dist/gts-ui-deps.js +27 -0
  23. data/vendor/ui/js/components/ref-selector.js +32 -55
  24. data/vendor/ui/js/components/tree-history.js +62 -0
  25. data/vendor/ui/js/gitorious.js +6 -0
  26. data/vendor/ui/js/libs/cullquery.js +6 -0
  27. data/vendor/ui/js/libs/ext-libs.js +28 -0
  28. data/vendor/ui/{bootstrap → lib/bootstrap}/css/bootstrap-responsive.min.css +0 -0
  29. data/vendor/ui/{bootstrap → lib/bootstrap}/css/bootstrap.min.css +0 -0
  30. data/vendor/ui/{bootstrap → lib/bootstrap}/img/glyphicons-halflings-white.png +0 -0
  31. data/vendor/ui/{bootstrap → lib/bootstrap}/img/glyphicons-halflings.png +0 -0
  32. data/vendor/ui/{bootstrap → lib/bootstrap}/js/bootstrap.min.js +0 -0
  33. data/vendor/ui/package.json +20 -0
  34. data/vendor/ui/test/tree-history-test.js +260 -0
  35. data/views/500.erb +1 -1
  36. data/views/layout.erb +4 -4
  37. data/views/tree.erb +3 -3
  38. data/views/tree_history.erb +19 -0
  39. metadata +22 -10
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dolt (0.3.1)
4
+ dolt (0.4.0)
5
5
  async_sinatra (~> 1.0)
6
6
  builder (~> 3.1)
7
7
  em_pessimistic (~> 0.1)
@@ -33,6 +33,10 @@ module When
33
33
  @deferred.fail(*args)
34
34
  end
35
35
 
36
+ def resolved?
37
+ @resolved
38
+ end
39
+
36
40
  private
37
41
  def mark_resolved
38
42
  raise StandardError.new("Already resolved") if @resolved
@@ -65,23 +69,60 @@ module When
65
69
  @promise.errback(&block)
66
70
  end
67
71
 
72
+ def resolved?
73
+ @resolver.resolved?
74
+ end
75
+
68
76
  def self.resolved(value)
69
77
  d = self.new
70
- d.resolve(vaule)
78
+ d.resolve(value)
71
79
  d
72
80
  end
73
81
 
74
82
  def self.rejected(value)
75
83
  d = self.new
76
- d.reject(vaule)
84
+ d.reject(value)
77
85
  d
78
86
  end
79
87
  end
80
88
 
81
- module Functions
82
- def deferred(val)
83
- return val if val.respond_to?(:callback) && val.respond_to?(:errback)
84
- Deferred.resolved(val).promise
89
+ def self.deferred(val)
90
+ return val if val.respond_to?(:callback) && val.respond_to?(:errback)
91
+ Deferred.resolved(val).promise
92
+ end
93
+
94
+ def self.all(promises)
95
+ raise(ArgumentError, "expected enumerable promises") if !promises.is_a?(Enumerable)
96
+ resolved = 0
97
+ results = []
98
+ d = Deferred.new
99
+
100
+ attempt_resolution = lambda do |err, res|
101
+ break if d.resolved?
102
+ if err.nil?
103
+ d.resolve(res) if promises.length == resolved
104
+ else
105
+ d.reject(err)
106
+ end
107
+ end
108
+
109
+ wait_for_all(promises) do |err, result, index|
110
+ resolved += 1
111
+ results[index] = result
112
+ attempt_resolution.call(err, results)
113
+ end
114
+
115
+ attempt_resolution.call(nil, results) if promises.length == 0
116
+ d.promise
117
+ end
118
+
119
+ private
120
+ def self.wait_for_all(promises, &block)
121
+ promises.each_with_index do |p, i|
122
+ p.callback do |result|
123
+ block.call(nil, result, i)
124
+ end
125
+ p.errback { |e| block.call(e, nil, i) }
85
126
  end
86
127
  end
87
128
  end
@@ -56,7 +56,7 @@ module Dolt
56
56
  def self.extract_commit_summary(lines)
57
57
  summary = lines.shift
58
58
  lines.shift if lines.first == ""
59
- summary
59
+ summary.sub(/^ /, "")
60
60
  end
61
61
 
62
62
  def self.extract_commit_message(lines)
@@ -20,6 +20,7 @@ require "em_pessimistic/deferrable_child_process"
20
20
  require "em/deferrable"
21
21
  require "dolt/git/blame"
22
22
  require "dolt/git/commit"
23
+ require "dolt/async/when"
23
24
 
24
25
  module Dolt
25
26
  module Git
@@ -31,12 +32,46 @@ module Dolt
31
32
  end
32
33
 
33
34
  def log(ref, path, limit)
34
- deferred_method("log -n #{limit} #{ref} #{path}") do |out, s|
35
- Dolt::Git::Commit.parse_log(out)
35
+ entry_history(ref, path, limit)
36
+ end
37
+
38
+ def tree_history(ref, path, limit = 1)
39
+ d = EventMachine::DefaultDeferrable.new
40
+ rp = rev_parse("#{ref}:#{path}")
41
+ rp.errback { |err| d.fail(err) }
42
+ rp.callback do |tree|
43
+ if tree.class != Rugged::Tree
44
+ message = "#{ref}:#{path} is not a tree (#{tree.class.to_s})"
45
+ break d.fail(Exception.new(message))
46
+ end
47
+
48
+ building = build_history(path || "./", ref, tree, limit)
49
+ building.callback { |history| d.succeed(history) }
50
+ building.errback { |err| d.fail(err) }
36
51
  end
52
+ d
37
53
  end
38
54
 
39
55
  private
56
+ def entry_history(ref, entry, limit)
57
+ deferred_method("log -n #{limit} #{ref} #{entry}") do |out, s|
58
+ Dolt::Git::Commit.parse_log(out)
59
+ end
60
+ end
61
+
62
+ def build_history(path, ref, entries, limit)
63
+ d = EventMachine::DefaultDeferrable.new
64
+ resolve = lambda { |p| path == "" ? p : File.join(path, p) }
65
+ progress = When.all(entries.map do |e|
66
+ entry_history(ref, resolve.call(e[:name]), limit)
67
+ end)
68
+ progress.errback { |e| d.fail(e) }
69
+ progress.callback do |history|
70
+ d.succeed(entries.map { |e| e.merge({ :history => history.shift }) })
71
+ end
72
+ d
73
+ end
74
+
40
75
  def deferred_method(cmd, &block)
41
76
  d = EventMachine::DefaultDeferrable.new
42
77
  cmd = git(cmd)
@@ -46,8 +81,8 @@ module Dolt
46
81
  d.succeed(block.call(output, status))
47
82
  end
48
83
 
49
- p.errback do |err|
50
- d.fail(err)
84
+ p.errback do |stderr, status|
85
+ d.fail(stderr)
51
86
  end
52
87
 
53
88
  d
@@ -1,3 +1,4 @@
1
+
1
2
  # encoding: utf-8
2
3
  #--
3
4
  # Copyright (C) 2012 Gitorious AS
@@ -53,6 +54,10 @@ module Dolt
53
54
  d.errback { |err| block.call(err, nil) }
54
55
  end
55
56
 
57
+ def tree_history(repo, ref, path, count, &block)
58
+ repo_action(repo, ref, path, :tree, :tree_history, ref, path, count, &block)
59
+ end
60
+
56
61
  def repositories
57
62
  repo_resolver.all
58
63
  end
@@ -89,6 +89,17 @@ module Dolt
89
89
  body(renderer.render(:refs, data, :layout => nil))
90
90
  end
91
91
  end
92
+
93
+ def tree_history(repo, ref, path, count = 1)
94
+ actions.tree_history(repo, ref, path, count) do |err, data|
95
+ if !err.nil?
96
+ error(err, repo, ref)
97
+ else
98
+ response["Content-Type"] = "application/json"
99
+ body(renderer.render(:tree_history, data, :layout => nil))
100
+ end
101
+ end
102
+ end
92
103
  end
93
104
  end
94
105
  end
@@ -68,10 +68,24 @@ module Dolt
68
68
  force_ref(params[:splat], "blame", "master")
69
69
  end
70
70
 
71
+ aget "/*/history/*:*" do
72
+ repo, ref, path = params[:splat]
73
+ history(repo, ref, path, (params[:commit_count] || 20).to_i)
74
+ end
75
+
76
+ aget "/*/history/*" do
77
+ force_ref(params[:splat], "history", "master")
78
+ end
79
+
71
80
  aget "/*/refs" do
72
81
  refs(params[:splat].first)
73
82
  end
74
83
 
84
+ aget "/*/tree_history/*:*" do
85
+ repo, ref, path = params[:splat]
86
+ tree_history(repo, ref, path)
87
+ end
88
+
75
89
  private
76
90
  def force_ref(args, action, ref)
77
91
  redirect(args.shift + "/#{action}/#{ref}:" + args.join)
@@ -86,6 +86,11 @@ module Dolt
86
86
  refs(repo)
87
87
  end
88
88
 
89
+ aget "/tree_history/*:*" do
90
+ ref, path = params[:splat]
91
+ tree_history(repo, ref, path)
92
+ end
93
+
89
94
  private
90
95
  def force_ref(args, action, ref)
91
96
  redirect("/#{action}/#{ref}:" + args.join)
@@ -17,5 +17,5 @@
17
17
  #++
18
18
 
19
19
  module Dolt
20
- VERSION = "0.3.1"
20
+ VERSION = "0.4.0"
21
21
  end
@@ -67,6 +67,10 @@ The content you're attempting to browse appears to be binary.
67
67
  repo_url(repository, "/raw/#{ref}:#{path}")
68
68
  end
69
69
 
70
+ def tree_history_url(repository, ref, path)
71
+ repo_url(repository, "/tree_history/#{ref}:#{path}")
72
+ end
73
+
70
74
  def format_whitespace(text)
71
75
  text
72
76
  end
@@ -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 "test_helper"
19
+ require "dolt/async/when"
20
+
21
+ describe When do
22
+ include EM::MiniTest::Spec
23
+
24
+ describe ".all" do
25
+ it "returns deferrable" do
26
+ d = When.all([When.deferred(42)])
27
+ assert d.respond_to?(:callback)
28
+ assert d.respond_to?(:errback)
29
+ end
30
+
31
+ it "resolves immediately if no promises" do
32
+ d = When.all([])
33
+ d.callback do |results|
34
+ assert_equal [], results
35
+ done!
36
+ end
37
+ wait!
38
+ end
39
+
40
+ it "resolves when single deferrable resolves" do
41
+ deferred = When::Deferred.new
42
+ d = When.all([deferred.promise])
43
+ resolved = false
44
+ d.callback { |results| resolved = true }
45
+
46
+ assert !resolved
47
+ deferred.resolve(42)
48
+ assert resolved
49
+ end
50
+
51
+ it "resolves when all deferrables are resolved" do
52
+ deferreds = [When::Deferred.new, When::Deferred.new, When::Deferred.new]
53
+ d = When.all(deferreds.map(&:promise))
54
+ resolved = false
55
+ d.callback { |results| resolved = true }
56
+
57
+ assert !resolved
58
+ deferreds[0].resolve(42)
59
+ assert !resolved
60
+ deferreds[1].resolve(13)
61
+ assert !resolved
62
+ deferreds[2].resolve(3)
63
+ assert resolved
64
+ end
65
+
66
+ it "rejects when single deferrable rejects" do
67
+ deferred = When::Deferred.new
68
+ d = When.all([deferred.promise])
69
+ rejected = false
70
+ d.errback { |results| rejected = true }
71
+
72
+ assert !rejected
73
+ deferred.reject(StandardError.new)
74
+ assert rejected
75
+ end
76
+
77
+ it "rejects on first rejection" do
78
+ deferreds = [When::Deferred.new, When::Deferred.new, When::Deferred.new]
79
+ d = When.all(deferreds.map(&:promise))
80
+ rejected = false
81
+ d.errback { |results| rejected = true }
82
+
83
+ deferreds[0].resolve(42)
84
+ deferreds[2].reject(StandardError.new)
85
+ deferreds[1].resolve(13)
86
+
87
+ assert rejected
88
+ end
89
+
90
+ it "proxies resolution vaule in array" do
91
+ deferred = When::Deferred.new
92
+ d = When.all([deferred.promise])
93
+ results = nil
94
+ d.callback { |res| results = res }
95
+
96
+ deferred.resolve(42)
97
+ assert_equal [42], results
98
+ end
99
+
100
+ it "orders results like input" do
101
+ deferred1 = When::Deferred.new
102
+ deferred2 = When::Deferred.new
103
+ d = When.all([deferred1.promise, deferred2.promise])
104
+ results = nil
105
+ d.callback { |res| results = res }
106
+
107
+ deferred2.resolve(42)
108
+ deferred1.resolve(13)
109
+ assert_equal [13, 42], results
110
+ end
111
+ end
112
+ end
@@ -17,6 +17,7 @@
17
17
  #++
18
18
  require "test_helper"
19
19
  require "dolt/git/repository"
20
+ require "time"
20
21
 
21
22
  describe Dolt::Git::Repository do
22
23
  include EM::MiniTest::Spec
@@ -57,4 +58,93 @@ describe Dolt::Git::Repository do
57
58
  wait!
58
59
  end
59
60
  end
61
+
62
+ describe "#tree_history" do
63
+ before { @repository = Dolt::Git::Repository.new(".") }
64
+
65
+ it "returns deferrable" do
66
+ deferrable = @repository.tree_history("master", "")
67
+ assert deferrable.respond_to?(:callback)
68
+ assert deferrable.respond_to?(:errback)
69
+ end
70
+
71
+ it "fails if path is not a tree" do
72
+ deferrable = @repository.tree_history("master", "Gemfile")
73
+ deferrable.errback do |err|
74
+ assert_match /not a tree/, err.message
75
+ done!
76
+ end
77
+ wait!
78
+ end
79
+
80
+ it "fails if path does not exist in ref" do
81
+ deferrable = @repository.tree_history("26139a3", "test")
82
+ deferrable.errback do |err|
83
+ assert_match /does not exist/, err.message
84
+ done!
85
+ end
86
+ wait!
87
+ end
88
+
89
+ it "yields tree with history" do
90
+ promise = @repository.tree_history("48ffbf7", "")
91
+
92
+ promise.callback do |log|
93
+ assert_equal 11, log.length
94
+ expected = {
95
+ :type => :blob,
96
+ :oid => "e90021f89616ddf86855d05337c188408d3b417e",
97
+ :filemode => 33188,
98
+ :name => ".gitmodules",
99
+ :history => [{
100
+ :oid => "906d67b4f3e5de7364ba9b57d174d8998d53ced6",
101
+ :author => { :name => "Christian Johansen",
102
+ :email => "christian@cjohansen.no" },
103
+ :summary => "Working Moron server for viewing blobs",
104
+ :date => Time.parse("Mon Sep 10 15:07:39 +0200 2012"),
105
+ :message => ""
106
+ }]
107
+ }
108
+
109
+ assert_equal expected, log[0]
110
+ done!
111
+ end
112
+
113
+ promise.errback do |err|
114
+ puts "FAILED! #{err.inspect}"
115
+ end
116
+
117
+ wait!
118
+ end
119
+
120
+ it "yields nested tree with history" do
121
+ promise = @repository.tree_history("48ffbf7", "lib")
122
+
123
+ promise.callback do |log|
124
+ expected = [{
125
+ :type => :tree,
126
+ :oid => "58f84405b588699b24c619aa4cd83669c5623f88",
127
+ :filemode => 16384,
128
+ :name => "dolt",
129
+ :history => [{
130
+ :oid => "8ab4f8c42511f727244a02aeee04824891610bbd",
131
+ :author => { :name => "Christian Johansen",
132
+ :email => "christian@gitorious.com" },
133
+ :summary => "New version",
134
+ :date => Time.parse("Mon Oct 1 16:34:00 +0200 2012"),
135
+ :message => ""
136
+ }]
137
+ }]
138
+
139
+ assert_equal expected, log
140
+ done!
141
+ end
142
+
143
+ promise.errback do |err|
144
+ puts "FAILED! #{err.inspect}"
145
+ end
146
+
147
+ wait!
148
+ end
149
+ end
60
150
  end