dolt 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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