gitki 0.1.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/ChangeLog +0 -0
- data/README.rdoc +74 -0
- data/Rakefile +59 -0
- data/app.rb +90 -0
- data/bin/gitki +3 -0
- data/bin/gitki.ru +13 -0
- data/config.ru +3 -0
- data/console +13 -0
- data/lib/gitki.png +0 -0
- data/lib/gitki.rb +116 -0
- data/lib/home_template.haml +17 -0
- data/lib/navigation_template.haml +4 -0
- data/public/background.png +0 -0
- data/public/favicon.ico +0 -0
- data/setting.yml +3 -0
- data/spec/gitki_spec.rb +104 -0
- data/vendor/git_store/LICENSE +18 -0
- data/vendor/git_store/README.md +147 -0
- data/vendor/git_store/Rakefile +35 -0
- data/vendor/git_store/TODO +3 -0
- data/vendor/git_store/git_store.gemspec +40 -0
- data/vendor/git_store/lib/git_store.rb +373 -0
- data/vendor/git_store/lib/git_store/blob.rb +32 -0
- data/vendor/git_store/lib/git_store/commit.rb +65 -0
- data/vendor/git_store/lib/git_store/diff.rb +76 -0
- data/vendor/git_store/lib/git_store/handlers.rb +36 -0
- data/vendor/git_store/lib/git_store/pack.rb +425 -0
- data/vendor/git_store/lib/git_store/tag.rb +40 -0
- data/vendor/git_store/lib/git_store/tree.rb +183 -0
- data/vendor/git_store/lib/git_store/user.rb +29 -0
- data/vendor/git_store/test/bare_store_spec.rb +33 -0
- data/vendor/git_store/test/benchmark.rb +30 -0
- data/vendor/git_store/test/commit_spec.rb +81 -0
- data/vendor/git_store/test/git_store_spec.rb +257 -0
- data/vendor/git_store/test/helper.rb +18 -0
- data/vendor/git_store/test/tree_spec.rb +92 -0
- data/views/layout.haml +23 -0
- data/views/page.haml +7 -0
- data/views/pages.haml +9 -0
- data/views/styles.sass +87 -0
- metadata +103 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
class GitStore
|
2
|
+
|
3
|
+
class Tag
|
4
|
+
attr_accessor :store, :id, :object, :type, :tagger, :message
|
5
|
+
|
6
|
+
def initialize(store, id = nil, data = nil)
|
7
|
+
@store = store
|
8
|
+
@id = id
|
9
|
+
|
10
|
+
parse(data) if data
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(other)
|
14
|
+
Tag === other and id == other.id
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse(data)
|
18
|
+
headers, @message = data.split(/\n\n/, 2)
|
19
|
+
|
20
|
+
headers.split(/\n/).each do |header|
|
21
|
+
key, value = header.split(/ /, 2)
|
22
|
+
case key
|
23
|
+
when 'type'
|
24
|
+
@type = value
|
25
|
+
|
26
|
+
when 'object'
|
27
|
+
@object = store.get(value)
|
28
|
+
|
29
|
+
when 'tagger'
|
30
|
+
@tagger = User.parse(value)
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
class GitStore
|
2
|
+
|
3
|
+
class Tree
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
attr_reader :store, :table
|
7
|
+
attr_accessor :id, :data, :mode
|
8
|
+
|
9
|
+
# Initialize a tree
|
10
|
+
def initialize(store, id = nil, data = nil)
|
11
|
+
@store = store
|
12
|
+
@id = id
|
13
|
+
@table = {}
|
14
|
+
@mode = "040000"
|
15
|
+
parse(data) if data
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(other)
|
19
|
+
Tree === other and id == other.id
|
20
|
+
end
|
21
|
+
|
22
|
+
# Has this tree been modified?
|
23
|
+
def modified?
|
24
|
+
@modified or @table.values.any? { |entry| Tree === entry and entry.modified? }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Find or create a subtree with specified name.
|
28
|
+
def tree(name)
|
29
|
+
get(name) or put(name, Tree.new(store))
|
30
|
+
end
|
31
|
+
|
32
|
+
# Read the contents of a raw git object.
|
33
|
+
def parse(data)
|
34
|
+
@table.clear
|
35
|
+
|
36
|
+
while data.size > 0
|
37
|
+
mode, data = data.split(" ", 2)
|
38
|
+
name, data = data.split("\0", 2)
|
39
|
+
id = data.slice!(0, 20).unpack("H*").first
|
40
|
+
|
41
|
+
@table[name] = store.get(id)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def dump
|
46
|
+
@table.map { |k, v| "#{ v.mode } #{ k }\0#{ [v.write].pack("H*") }" }.join
|
47
|
+
end
|
48
|
+
|
49
|
+
# Write this tree back to the git repository.
|
50
|
+
#
|
51
|
+
# Returns the object id of the tree.
|
52
|
+
def write
|
53
|
+
return id if not modified?
|
54
|
+
@modified = false
|
55
|
+
@id = store.put(self)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Read entry with specified name.
|
59
|
+
def get(name)
|
60
|
+
entry = @table[name]
|
61
|
+
|
62
|
+
case entry
|
63
|
+
when Blob
|
64
|
+
entry.object ||= handler_for(name).read(entry.data)
|
65
|
+
|
66
|
+
when Tree
|
67
|
+
entry
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def handler_for(name)
|
72
|
+
store.handler_for(name)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Write entry with specified name.
|
76
|
+
def put(name, value)
|
77
|
+
@modified = true
|
78
|
+
|
79
|
+
if value.is_a?(Tree)
|
80
|
+
@table[name] = value
|
81
|
+
else
|
82
|
+
@table[name] = Blob.new(store, nil, handler_for(name).write(value))
|
83
|
+
end
|
84
|
+
|
85
|
+
value
|
86
|
+
end
|
87
|
+
|
88
|
+
# Remove entry with specified name.
|
89
|
+
def remove(name)
|
90
|
+
@modified = true
|
91
|
+
@table.delete(name.to_s)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Does this key exist in the table?
|
95
|
+
def has_key?(name)
|
96
|
+
@table.has_key?(name.to_s)
|
97
|
+
end
|
98
|
+
|
99
|
+
def normalize_path(path)
|
100
|
+
(path[0, 1] == '/' ? path[1..-1] : path).split('/')
|
101
|
+
end
|
102
|
+
|
103
|
+
# Read a value on specified path.
|
104
|
+
def [](path)
|
105
|
+
normalize_path(path).inject(self) do |tree, key|
|
106
|
+
tree.get(key) or return nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Write a value on specified path.
|
111
|
+
def []=(path, value)
|
112
|
+
list = normalize_path(path)
|
113
|
+
tree = list[0..-2].to_a.inject(self) { |tree, name| tree.tree(name) }
|
114
|
+
tree.put(list.last, value)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Delete a value on specified path.
|
118
|
+
def delete(path)
|
119
|
+
list = normalize_path(path)
|
120
|
+
|
121
|
+
tree = list[0..-2].to_a.inject(self) do |tree, key|
|
122
|
+
tree.get(key) or return
|
123
|
+
end
|
124
|
+
|
125
|
+
tree.remove(list.last)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Iterate over all objects found in this subtree.
|
129
|
+
def each(path = [], &block)
|
130
|
+
@table.sort.each do |name, entry|
|
131
|
+
child_path = path + [name]
|
132
|
+
case entry
|
133
|
+
when Blob
|
134
|
+
entry.object ||= handler_for(name).read(entry.data)
|
135
|
+
yield child_path.join("/"), entry.object
|
136
|
+
|
137
|
+
when Tree
|
138
|
+
entry.each(child_path, &block)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def each_blob(path = [], &block)
|
144
|
+
@table.sort.each do |name, entry|
|
145
|
+
child_path = path + [name]
|
146
|
+
|
147
|
+
case entry
|
148
|
+
when Blob
|
149
|
+
yield child_path.join("/"), entry
|
150
|
+
|
151
|
+
when Tree
|
152
|
+
entry.each_blob(child_path, &block)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def paths
|
158
|
+
map { |path, data| path }
|
159
|
+
end
|
160
|
+
|
161
|
+
def values
|
162
|
+
map { |path, data| data }
|
163
|
+
end
|
164
|
+
|
165
|
+
# Convert this tree into a hash object.
|
166
|
+
def to_hash
|
167
|
+
@table.inject({}) do |hash, (name, entry)|
|
168
|
+
if entry.is_a?(Tree)
|
169
|
+
hash[name] = entry.to_hash
|
170
|
+
else
|
171
|
+
hash[name] = entry.object ||= handler_for(name).read(entry.data)
|
172
|
+
end
|
173
|
+
hash
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def inspect
|
178
|
+
"#<GitStore::Tree #{id} #{mode} #{to_hash.inspect}>"
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class GitStore
|
2
|
+
|
3
|
+
class User
|
4
|
+
attr_accessor :name, :email, :time
|
5
|
+
|
6
|
+
def initialize(name, email, time)
|
7
|
+
@name, @email, @time = name, email, time
|
8
|
+
end
|
9
|
+
|
10
|
+
def dump
|
11
|
+
"#{ name } <#{email}> #{ time.to_i } #{ time.strftime('%z') }"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.from_config
|
15
|
+
name = IO.popen("git config user.name") { |io| io.gets.chomp }
|
16
|
+
email = IO.popen("git config user.email") { |io| io.gets.chomp }
|
17
|
+
|
18
|
+
new name, email, Time.now
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.parse(user)
|
22
|
+
if match = user.match(/(.*)<(.*)> (\d+) ([+-]\d+)/)
|
23
|
+
new match[1].strip, match[2].strip, Time.at(match[3].to_i + match[4].to_i * 3600)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../lib/git_store"
|
2
|
+
require "#{File.dirname(__FILE__)}/helper"
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
describe GitStore do
|
6
|
+
|
7
|
+
REPO = '/tmp/git_store_test.git'
|
8
|
+
|
9
|
+
attr_reader :store
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
FileUtils.rm_rf REPO
|
13
|
+
Dir.mkdir REPO
|
14
|
+
Dir.chdir REPO
|
15
|
+
|
16
|
+
`git init --bare`
|
17
|
+
@store = GitStore.new(REPO, 'master', true)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should fail to initialize without a valid git repository' do
|
21
|
+
lambda {
|
22
|
+
GitStore.new('/foo', 'master', true)
|
23
|
+
}.should raise_error(ArgumentError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should save and load entries' do
|
27
|
+
store['a'] = 'Hello'
|
28
|
+
store.commit
|
29
|
+
store.load
|
30
|
+
|
31
|
+
store['a'].should == 'Hello'
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'git_store'
|
2
|
+
require 'grit'
|
3
|
+
require 'benchmark'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
REPO = '/tmp/git-store'
|
7
|
+
|
8
|
+
FileUtils.rm_rf REPO
|
9
|
+
FileUtils.mkpath REPO
|
10
|
+
Dir.chdir REPO
|
11
|
+
|
12
|
+
`git init`
|
13
|
+
|
14
|
+
store = GitStore.new(REPO)
|
15
|
+
|
16
|
+
Benchmark.bm 20 do |x|
|
17
|
+
x.report 'store 1000 objects' do
|
18
|
+
store.transaction { 'aaa'.upto('jjj') { |key| store[key] = rand.to_s } }
|
19
|
+
end
|
20
|
+
x.report 'commit one object' do
|
21
|
+
store.transaction { store['aa'] = rand.to_s }
|
22
|
+
end
|
23
|
+
x.report 'load 1000 objects' do
|
24
|
+
GitStore.new('.').values { |v| v }
|
25
|
+
end
|
26
|
+
x.report 'load 1000 with grit' do
|
27
|
+
Grit::Repo.new('.').tree.contents.each { |e| e.data }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../lib/git_store"
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
describe GitStore::Commit do
|
5
|
+
|
6
|
+
REPO = '/tmp/git_store_test'
|
7
|
+
|
8
|
+
attr_reader :store
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
FileUtils.rm_rf REPO
|
12
|
+
Dir.mkdir REPO
|
13
|
+
Dir.chdir REPO
|
14
|
+
`git init`
|
15
|
+
@store = GitStore.new(REPO)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should dump in right format" do
|
19
|
+
user = GitStore::User.new("hanni", "hanni@email.de", Time.now)
|
20
|
+
|
21
|
+
commit = GitStore::Commit.new(nil)
|
22
|
+
commit.tree = @store.root.id
|
23
|
+
commit.author = user
|
24
|
+
commit.committer = user
|
25
|
+
commit.message = "This is a message"
|
26
|
+
|
27
|
+
commit.dump.should == "tree #{@store.root.id}
|
28
|
+
author #{user.dump}
|
29
|
+
committer #{user.dump}
|
30
|
+
|
31
|
+
This is a message"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should be readable by git binary" do
|
35
|
+
time = Time.local(2009, 4, 20)
|
36
|
+
author = GitStore::User.new("hans", "hans@email.de", time)
|
37
|
+
|
38
|
+
store['a'] = "Yay"
|
39
|
+
commit = store.commit("Commit Message", author, author)
|
40
|
+
|
41
|
+
IO.popen("git log") do |io|
|
42
|
+
io.gets.should == "commit #{commit.id}\n"
|
43
|
+
io.gets.should == "Author: hans <hans@email.de>\n"
|
44
|
+
io.gets.should == "Date: Mon Apr 20 00:00:00 2009 #{Time.now.strftime('%z')}\n"
|
45
|
+
io.gets.should == "\n"
|
46
|
+
io.gets.should == " Commit Message\n"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should diff 2 commits" do
|
51
|
+
store['x'] = 'a'
|
52
|
+
store['y'] = "
|
53
|
+
First Line.
|
54
|
+
Second Line.
|
55
|
+
Last Line.
|
56
|
+
"
|
57
|
+
a = store.commit
|
58
|
+
|
59
|
+
store.delete('x')
|
60
|
+
store['y'] = "
|
61
|
+
First Line.
|
62
|
+
Last Line.
|
63
|
+
Another Line.
|
64
|
+
"
|
65
|
+
store['z'] = 'c'
|
66
|
+
|
67
|
+
b = store.commit
|
68
|
+
|
69
|
+
diff = b.diff(a)
|
70
|
+
|
71
|
+
diff[0].a_path.should == 'x'
|
72
|
+
diff[0].deleted_file.should be_true
|
73
|
+
|
74
|
+
diff[1].a_path.should == 'y'
|
75
|
+
diff[1].diff.should == "--- a/y\n+++ b/y\n@@ -1,4 +1,4 @@\n \n First Line.\n-Second Line.\n Last Line.\n+Another Line."
|
76
|
+
|
77
|
+
diff[2].a_path.should == 'z'
|
78
|
+
diff[2].new_file.should be_true
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../lib/git_store"
|
2
|
+
require "#{File.dirname(__FILE__)}/helper"
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
describe GitStore do
|
6
|
+
|
7
|
+
REPO = '/tmp/git_store_test'
|
8
|
+
|
9
|
+
attr_reader :store
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
FileUtils.rm_rf REPO
|
13
|
+
Dir.mkdir REPO
|
14
|
+
Dir.chdir REPO
|
15
|
+
|
16
|
+
`git init`
|
17
|
+
@store = GitStore.new(REPO)
|
18
|
+
end
|
19
|
+
|
20
|
+
def file(file, data)
|
21
|
+
FileUtils.mkpath(File.dirname(file))
|
22
|
+
open(file, 'w') { |io| io << data }
|
23
|
+
|
24
|
+
`git add #{file}`
|
25
|
+
`git commit -m 'added #{file}'`
|
26
|
+
File.unlink(file)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should fail to initialize without a valid git repository' do
|
30
|
+
lambda {
|
31
|
+
GitStore.new('/')
|
32
|
+
}.should raise_error(ArgumentError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should find modified entries' do
|
36
|
+
store['a'] = 'Hello'
|
37
|
+
|
38
|
+
store.root.should be_modified
|
39
|
+
|
40
|
+
store.commit
|
41
|
+
|
42
|
+
store.root.should_not be_modified
|
43
|
+
|
44
|
+
store['a'] = 'Bello'
|
45
|
+
|
46
|
+
store.root.should be_modified
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should load a repo' do
|
50
|
+
file 'a', 'Hello'
|
51
|
+
file 'b', 'World'
|
52
|
+
|
53
|
+
store.load
|
54
|
+
|
55
|
+
store['a'].should == 'Hello'
|
56
|
+
store['b'].should == 'World'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should load folders' do
|
60
|
+
file 'x/a', 'Hello'
|
61
|
+
file 'y/b', 'World'
|
62
|
+
|
63
|
+
store.load
|
64
|
+
store['x'].should be_kind_of(GitStore::Tree)
|
65
|
+
store['y'].should be_kind_of(GitStore::Tree)
|
66
|
+
|
67
|
+
store['x']['a'].should == 'Hello'
|
68
|
+
store['y']['b'].should == 'World'
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should load yaml' do
|
72
|
+
file 'x/a.yml', '[1, 2, 3, 4]'
|
73
|
+
|
74
|
+
store.load
|
75
|
+
|
76
|
+
store['x']['a.yml'].should == [1,2,3,4]
|
77
|
+
store['x']['a.yml'] = [1,2,3,4,5]
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should save yaml' do
|
81
|
+
store['x/a.yml'] = [1,2,3,4,5]
|
82
|
+
store['x/a.yml'].should == [1,2,3,4,5]
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should detect modification' do
|
86
|
+
store.transaction do
|
87
|
+
store['x/a'] = 'a'
|
88
|
+
end
|
89
|
+
|
90
|
+
store.load
|
91
|
+
|
92
|
+
store['x/a'].should == 'a'
|
93
|
+
|
94
|
+
store.transaction do
|
95
|
+
store['x/a'] = 'b'
|
96
|
+
store['x'].should be_modified
|
97
|
+
store.root.should be_modified
|
98
|
+
end
|
99
|
+
|
100
|
+
store.load
|
101
|
+
|
102
|
+
store['x/a'].should == 'b'
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should resolve paths' do
|
106
|
+
file 'x/a', 'Hello'
|
107
|
+
file 'y/b', 'World'
|
108
|
+
|
109
|
+
store.load
|
110
|
+
|
111
|
+
store['x/a'].should == 'Hello'
|
112
|
+
store['y/b'].should == 'World'
|
113
|
+
|
114
|
+
store['y/b'] = 'Now this'
|
115
|
+
|
116
|
+
store['y']['b'].should == 'Now this'
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should create new trees' do
|
120
|
+
store['new/tree'] = 'This tree'
|
121
|
+
store['new/tree'].should == 'This tree'
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should delete entries' do
|
125
|
+
store['a'] = 'Hello'
|
126
|
+
store.delete('a')
|
127
|
+
|
128
|
+
store['a'].should be_nil
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should have a head commit' do
|
132
|
+
file 'a', 'Hello'
|
133
|
+
|
134
|
+
store.load
|
135
|
+
store.head.should_not be_nil
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should detect changes' do
|
139
|
+
file 'a', 'Hello'
|
140
|
+
|
141
|
+
store.should be_changed
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should rollback a transaction' do
|
145
|
+
file 'a/b', 'Hello'
|
146
|
+
file 'c/d', 'World'
|
147
|
+
|
148
|
+
begin
|
149
|
+
store.transaction do
|
150
|
+
store['a/b'] = 'Changed'
|
151
|
+
store['x/a'] = 'Added'
|
152
|
+
raise
|
153
|
+
end
|
154
|
+
rescue
|
155
|
+
end
|
156
|
+
|
157
|
+
store['a/b'].should == 'Hello'
|
158
|
+
store['c/d'].should == 'World'
|
159
|
+
store['x/a'].should be_nil
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should commit a transaction' do
|
163
|
+
file 'a/b', 'Hello'
|
164
|
+
file 'c/d', 'World'
|
165
|
+
|
166
|
+
store.transaction do
|
167
|
+
store['a/b'] = 'Changed'
|
168
|
+
store['x/a'] = 'Added'
|
169
|
+
end
|
170
|
+
|
171
|
+
a = git_ls_tree(store['a'].id)
|
172
|
+
x = git_ls_tree(store['x'].id)
|
173
|
+
|
174
|
+
a.should == [["100644", "blob", "b653cf27cef08de46da49a11fa5016421e9e3b32", "b"]]
|
175
|
+
x.should == [["100644", "blob", "87d2b203800386b1cc8735a7d540a33e246357fa", "a"]]
|
176
|
+
|
177
|
+
git_show(a[0][2]).should == 'Changed'
|
178
|
+
git_show(x[0][2]).should == 'Added'
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should save blobs" do
|
182
|
+
store['a'] = 'a'
|
183
|
+
store['b'] = 'b'
|
184
|
+
store['c'] = 'c'
|
185
|
+
|
186
|
+
store.commit
|
187
|
+
|
188
|
+
a = store.id_for('blob', 'a')
|
189
|
+
b = store.id_for('blob', 'b')
|
190
|
+
c = store.id_for('blob', 'c')
|
191
|
+
|
192
|
+
git_show(a).should == 'a'
|
193
|
+
git_show(b).should == 'b'
|
194
|
+
git_show(c).should == 'c'
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should allow only one transaction' do
|
198
|
+
file 'a/b', 'Hello'
|
199
|
+
|
200
|
+
ready = false
|
201
|
+
|
202
|
+
store.transaction do
|
203
|
+
Thread.start do
|
204
|
+
store.transaction do
|
205
|
+
store['a/b'] = 'Changed by second thread'
|
206
|
+
end
|
207
|
+
ready = true
|
208
|
+
end
|
209
|
+
store['a/b'] = 'Changed'
|
210
|
+
end
|
211
|
+
|
212
|
+
sleep 0.01 until ready
|
213
|
+
|
214
|
+
store.load
|
215
|
+
|
216
|
+
store['a/b'].should == 'Changed by second thread'
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'should find all objects' do
|
220
|
+
store.load
|
221
|
+
store['c'] = 'Hello'
|
222
|
+
store['d'] = 'World'
|
223
|
+
store.commit
|
224
|
+
|
225
|
+
store.to_a.should == [['c', 'Hello'], ['d', 'World']]
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should load commits" do
|
229
|
+
store['a'] = 'a'
|
230
|
+
store.commit 'added a'
|
231
|
+
|
232
|
+
store['b'] = 'b'
|
233
|
+
store.commit 'added b'
|
234
|
+
|
235
|
+
store.commits[0].message.should == 'added b'
|
236
|
+
store.commits[1].message.should == 'added a'
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should load tags" do
|
240
|
+
file 'a', 'init'
|
241
|
+
|
242
|
+
`git tag -m 'message' 0.1`
|
243
|
+
|
244
|
+
store.load
|
245
|
+
|
246
|
+
user = GitStore::User.from_config
|
247
|
+
id = File.read('.git/refs/tags/0.1')
|
248
|
+
tag = store.get(id)
|
249
|
+
|
250
|
+
tag.type.should == 'commit'
|
251
|
+
tag.object.should == store.head
|
252
|
+
tag.tagger.name.should == user.name
|
253
|
+
tag.tagger.email.should == user.email
|
254
|
+
tag.message.should =~ /message/
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|