ddollar-git-db 0.0.2 → 0.1.2
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/README.rdoc +30 -9
- data/Rakefile +9 -23
- data/VERSION +1 -1
- data/bin/git-db +3 -2
- data/git-db.gemspec +35 -24
- data/lib/git-db.rb +56 -4
- data/lib/git-db/commands.rb +21 -0
- data/lib/git-db/commands/receive-pack.rb +73 -0
- data/lib/git-db/commands/upload-pack.rb +140 -0
- data/lib/git-db/database.rb +134 -0
- data/lib/git-db/objects.rb +20 -0
- data/lib/{git → git-db}/objects/base.rb +14 -9
- data/lib/git-db/objects/blob.rb +11 -0
- data/lib/{git → git-db}/objects/commit.rb +5 -5
- data/lib/{git → git-db}/objects/entry.rb +12 -4
- data/lib/git-db/objects/tag.rb +7 -0
- data/lib/{git → git-db}/objects/tree.rb +16 -16
- data/lib/{git → git-db}/pack.rb +6 -6
- data/lib/{git → git-db}/protocol.rb +3 -3
- data/lib/git-db/utility.rb +3 -0
- data/lib/{utility → git-db/utility}/counting_io.rb +0 -0
- data/spec/git-db/commands_spec.rb +23 -0
- data/spec/git-db/objects/base_spec.rb +27 -0
- data/spec/git-db/objects/entry_spec.rb +25 -0
- data/spec/git-db/objects/tag_spec.rb +14 -0
- data/spec/git-db/objects/tree_spec.rb +42 -0
- data/spec/git-db/utility/counting_io_spec.rb +30 -0
- data/spec/git-db_spec.rb +41 -3
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +2 -0
- metadata +33 -29
- data/lib/git.rb +0 -39
- data/lib/git/commands.rb +0 -17
- data/lib/git/commands/receive-pack.rb +0 -101
- data/lib/git/commands/upload-pack.rb +0 -204
- data/lib/git/objects.rb +0 -20
- data/lib/git/objects/blob.rb +0 -11
- data/lib/git/objects/tag.rb +0 -7
- data/lib/utility.rb +0 -3
@@ -0,0 +1,134 @@
|
|
1
|
+
class GitDB::Database
|
2
|
+
|
3
|
+
def self.couch
|
4
|
+
@couch ||= CouchRest.new('http://localhost:5984')
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.database(repository)
|
8
|
+
@databases ||= {}
|
9
|
+
@databases[repository] ||= new(repository)
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :repository, :name, :database
|
13
|
+
|
14
|
+
def initialize(repository)
|
15
|
+
@repository = repository
|
16
|
+
@name = "gitdb-#{repository.gsub('/', '-')}"
|
17
|
+
@database = self.class.couch.database!(name)
|
18
|
+
update_views
|
19
|
+
end
|
20
|
+
|
21
|
+
## refs ######################################################################
|
22
|
+
|
23
|
+
def get_ref(ref)
|
24
|
+
doc = database.view('refs/all', :key => ref)['rows'].first
|
25
|
+
doc ? doc['value'] : nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_refs
|
29
|
+
database.view('refs/all')['rows'].inject({}) do |hash, row|
|
30
|
+
hash.update(row['key'] => row['value']['sha'])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def write_ref(ref, sha)
|
35
|
+
if doc = get_ref(ref)
|
36
|
+
doc['sha'] = sha
|
37
|
+
database.save_doc(doc)
|
38
|
+
else
|
39
|
+
database.save_doc(:doctype => 'ref', :ref => ref, :sha => sha)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete_ref(ref)
|
44
|
+
if doc = get_ref(ref)
|
45
|
+
database.delete_doc(doc)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
## objects ###################################################################
|
50
|
+
|
51
|
+
def get_raw_object(sha)
|
52
|
+
doc = database.view('objects/all', :key => sha)['rows'].first
|
53
|
+
doc = doc ? decode_object(doc['value']) : nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_object(sha)
|
57
|
+
raw = get_raw_object(sha)
|
58
|
+
raw ? GitDB::Objects.new_from_type(raw['type'], raw['data']) : nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def write_object(object)
|
62
|
+
doc = object_to_doc(object)
|
63
|
+
doc = (get_raw_object(object.sha) || {}).merge(doc)
|
64
|
+
database.save_doc(doc)
|
65
|
+
end
|
66
|
+
|
67
|
+
def write_objects(objects)
|
68
|
+
docs = objects.map do |object|
|
69
|
+
doc = object_to_doc(object)
|
70
|
+
doc = (get_raw_object(object.sha) || {}).merge(doc)
|
71
|
+
end
|
72
|
+
database.bulk_save(docs)
|
73
|
+
end
|
74
|
+
|
75
|
+
## utility ###################################################################
|
76
|
+
|
77
|
+
def document_ids
|
78
|
+
database.documents['rows'].map { |row| row['id']}
|
79
|
+
end
|
80
|
+
|
81
|
+
def encode_object(doc)
|
82
|
+
doc['data'] = Base64.encode64(doc['data'])
|
83
|
+
doc
|
84
|
+
end
|
85
|
+
|
86
|
+
def decode_object(doc)
|
87
|
+
doc['data'] = Base64.decode64(doc['data'])
|
88
|
+
doc
|
89
|
+
end
|
90
|
+
|
91
|
+
def object_to_doc(object)
|
92
|
+
properties = object.properties
|
93
|
+
properties += [:type, :data, :sha]
|
94
|
+
doc = properties.inject({ :doctype => 'object' }) do |hash, property|
|
95
|
+
hash.update(property.to_s => object.send(property))
|
96
|
+
end
|
97
|
+
encode_object(doc)
|
98
|
+
end
|
99
|
+
|
100
|
+
def update_views
|
101
|
+
if document_ids.include?('_design/refs')
|
102
|
+
database.delete_doc(database.get('_design/refs'))
|
103
|
+
end
|
104
|
+
database.save_doc({
|
105
|
+
'_id' => '_design/refs',
|
106
|
+
:views => {
|
107
|
+
:all => {
|
108
|
+
:map => %{
|
109
|
+
function(doc) {
|
110
|
+
if (doc.doctype == 'ref') { emit(doc.ref, doc); }
|
111
|
+
}
|
112
|
+
}
|
113
|
+
},
|
114
|
+
}
|
115
|
+
})
|
116
|
+
if document_ids.include?('_design/objects')
|
117
|
+
database.delete_doc(database.get('_design/objects'))
|
118
|
+
end
|
119
|
+
database.save_doc({
|
120
|
+
'_id' => '_design/objects',
|
121
|
+
:views => {
|
122
|
+
:all => {
|
123
|
+
:map => %{
|
124
|
+
function(doc) {
|
125
|
+
if (doc.doctype == 'object') { emit(doc.sha, doc); }
|
126
|
+
}
|
127
|
+
}
|
128
|
+
},
|
129
|
+
}
|
130
|
+
})
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GitDB::Objects;
|
2
|
+
|
3
|
+
def self.new_from_type(type, data)
|
4
|
+
case type
|
5
|
+
when GitDB::OBJ_COMMIT then GitDB::Objects::Commit.new(data)
|
6
|
+
when GitDB::OBJ_TREE then GitDB::Objects::Tree.new(data)
|
7
|
+
when GitDB::OBJ_BLOB then GitDB::Objects::Blob.new(data)
|
8
|
+
when GitDB::OBJ_TAG then GitDB::Objects::Tag.new(data)
|
9
|
+
else raise "Unknown object type: #{type}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'git-db/objects/base'
|
16
|
+
require 'git-db/objects/blob'
|
17
|
+
require 'git-db/objects/commit'
|
18
|
+
require 'git-db/objects/entry'
|
19
|
+
require 'git-db/objects/tag'
|
20
|
+
require 'git-db/objects/tree'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class GitDB::
|
1
|
+
class GitDB::Objects::Base
|
2
2
|
|
3
3
|
attr_reader :data
|
4
4
|
|
@@ -7,7 +7,15 @@ class GitDB::Git::Objects::Base
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def inspect
|
10
|
-
%{#<#{self.class} #{
|
10
|
+
%{#<#{self.class} #{inspect_properties}>}
|
11
|
+
end
|
12
|
+
|
13
|
+
def properties
|
14
|
+
[:data]
|
15
|
+
end
|
16
|
+
|
17
|
+
def raw
|
18
|
+
data
|
11
19
|
end
|
12
20
|
|
13
21
|
def sha
|
@@ -16,14 +24,11 @@ class GitDB::Git::Objects::Base
|
|
16
24
|
|
17
25
|
private ######################################################################
|
18
26
|
|
19
|
-
def
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
def inspect_arguments_as_string
|
24
|
-
inspect_arguments.unshift(:sha).map do |argument|
|
27
|
+
def inspect_properties
|
28
|
+
inspectors = properties.unshift(:sha).map do |argument|
|
25
29
|
"#{argument}=#{self.send(argument).inspect}"
|
26
|
-
end
|
30
|
+
end
|
31
|
+
inspectors.join(' ')
|
27
32
|
end
|
28
33
|
|
29
34
|
end
|
@@ -1,11 +1,11 @@
|
|
1
|
-
class GitDB::
|
1
|
+
class GitDB::Objects::Commit < GitDB::Objects::Base
|
2
2
|
|
3
3
|
def raw
|
4
4
|
"commit #{data.length}\000#{data}"
|
5
5
|
end
|
6
6
|
|
7
7
|
def type
|
8
|
-
|
8
|
+
GitDB::OBJ_COMMIT
|
9
9
|
end
|
10
10
|
|
11
11
|
def message
|
@@ -28,12 +28,12 @@ class GitDB::Git::Objects::Commit < GitDB::Git::Objects::Base
|
|
28
28
|
attributes['parent']
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
def inspect_arguments
|
31
|
+
def properties
|
34
32
|
[:tree, :parents, :author, :committer, :message]
|
35
33
|
end
|
36
34
|
|
35
|
+
private ######################################################################
|
36
|
+
|
37
37
|
def attributes
|
38
38
|
@attributes ||= begin
|
39
39
|
attributes = data.split("\n\n", 2).first
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'stringio'
|
2
2
|
|
3
|
-
class GitDB::
|
3
|
+
class GitDB::Objects::Entry < GitDB::Objects::Base
|
4
4
|
|
5
5
|
attr_reader :sha, :permissions, :name
|
6
6
|
|
@@ -10,10 +10,18 @@ class GitDB::Git::Objects::Entry < GitDB::Git::Objects::Base
|
|
10
10
|
@name = name
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
def inspect_arguments
|
13
|
+
def properties
|
16
14
|
[:permissions, :name]
|
17
15
|
end
|
18
16
|
|
17
|
+
def to_hash
|
18
|
+
{ :sha => sha, :permissions => permissions, :name => name }
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_json
|
22
|
+
to_hash.to_json
|
23
|
+
end
|
24
|
+
|
25
|
+
private ######################################################################
|
26
|
+
|
19
27
|
end
|
@@ -1,19 +1,23 @@
|
|
1
1
|
require 'stringio'
|
2
2
|
|
3
|
-
class GitDB::
|
3
|
+
class GitDB::Objects::Tree < GitDB::Objects::Base
|
4
|
+
|
5
|
+
# TODO: memoize entries
|
4
6
|
|
5
7
|
def entries
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
entries << GitDB::Git::Objects::Entry.new(sha, perms, name)
|
14
|
-
end
|
15
|
-
entries
|
8
|
+
entries = []
|
9
|
+
stream = StringIO.new(data)
|
10
|
+
until stream.eof?
|
11
|
+
perms = read_until(stream, ' ').to_i
|
12
|
+
name = read_until(stream, 0.chr)
|
13
|
+
sha = GitDB.sha1_to_hex(stream.read(20))
|
14
|
+
entries << GitDB::Objects::Entry.new(sha, perms, name)
|
16
15
|
end
|
16
|
+
entries
|
17
|
+
end
|
18
|
+
|
19
|
+
def properties
|
20
|
+
[:entries]
|
17
21
|
end
|
18
22
|
|
19
23
|
def raw
|
@@ -21,15 +25,11 @@ class GitDB::Git::Objects::Tree < GitDB::Git::Objects::Base
|
|
21
25
|
end
|
22
26
|
|
23
27
|
def type
|
24
|
-
|
28
|
+
GitDB::OBJ_TREE
|
25
29
|
end
|
26
30
|
|
27
31
|
private ######################################################################
|
28
32
|
|
29
|
-
def inspect_arguments
|
30
|
-
[:entries]
|
31
|
-
end
|
32
|
-
|
33
33
|
def read_until(stream, separator)
|
34
34
|
data = ""
|
35
35
|
char = ""
|
data/lib/{git → git-db}/pack.rb
RENAMED
@@ -2,7 +2,7 @@ require 'digest/sha1'
|
|
2
2
|
require 'stringio'
|
3
3
|
require 'zlib'
|
4
4
|
|
5
|
-
class GitDB::
|
5
|
+
class GitDB::Pack
|
6
6
|
|
7
7
|
PackObject = Struct.new(:type, :offset, :data)
|
8
8
|
|
@@ -29,13 +29,13 @@ class GitDB::Git::Pack
|
|
29
29
|
|
30
30
|
object = case type
|
31
31
|
when 1 then
|
32
|
-
GitDB::
|
32
|
+
GitDB::Objects::Commit.new(read_compressed(io))
|
33
33
|
when 2 then
|
34
|
-
GitDB::
|
34
|
+
GitDB::Objects::Tree.new(read_compressed(io))
|
35
35
|
when 3 then
|
36
|
-
GitDB::
|
36
|
+
GitDB::Objects::Blob.new(read_compressed(io))
|
37
37
|
when 4 then
|
38
|
-
GitDB::
|
38
|
+
GitDB::Objects::Tag.new(read_compressed(io))
|
39
39
|
when 5 then
|
40
40
|
raise 'Invalid Type: 5'
|
41
41
|
when 6 then
|
@@ -80,7 +80,7 @@ class GitDB::Git::Pack
|
|
80
80
|
end
|
81
81
|
|
82
82
|
#GitDB.log("BUFFER: #{buffer.inspect}")
|
83
|
-
signature =
|
83
|
+
signature = GitDB::hex_to_sha1(Digest::SHA1.hexdigest(buffer))
|
84
84
|
#GitDB.log("SIGNATURE: #{signature.inspect}")
|
85
85
|
io.write(signature)
|
86
86
|
io.flush
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class GitDB::
|
1
|
+
class GitDB::Protocol
|
2
2
|
|
3
3
|
attr_reader :reader
|
4
4
|
attr_reader :writer
|
@@ -53,11 +53,11 @@ class GitDB::Git::Protocol
|
|
53
53
|
## packs #####################################################################
|
54
54
|
|
55
55
|
def read_pack
|
56
|
-
GitDB::
|
56
|
+
GitDB::Pack.new(reader).read
|
57
57
|
end
|
58
58
|
|
59
59
|
def write_pack(entries)
|
60
|
-
GitDB::
|
60
|
+
GitDB::Pack.new(writer).write(entries)
|
61
61
|
end
|
62
62
|
|
63
63
|
private ######################################################################
|
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "GitDB::Commands" do
|
4
|
+
|
5
|
+
it "has a receive-pack command" do
|
6
|
+
GitDB::Commands.commands['receive-pack'].should_not be_nil
|
7
|
+
end
|
8
|
+
|
9
|
+
it "has an upload-pack command" do
|
10
|
+
end
|
11
|
+
|
12
|
+
it "executes a command" do
|
13
|
+
@command = mock
|
14
|
+
@name = 'command'
|
15
|
+
@args = ['Test Repository']
|
16
|
+
|
17
|
+
GitDB::Commands.should_receive(:commands).at_least(:once).and_return({ @name => @command })
|
18
|
+
@command.should_receive(:execute).with(@args)
|
19
|
+
|
20
|
+
GitDB::Commands.execute(@name, @args)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe "GitDB::Objects::Base" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@data = "Test Data"
|
7
|
+
@base = GitDB::Objects::Base.new(@data)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "initializes with data" do
|
11
|
+
@base.data.should == @data
|
12
|
+
end
|
13
|
+
|
14
|
+
it "inspects its own properties" do
|
15
|
+
@base.should_receive(:properties).and_return([:data])
|
16
|
+
@base.inspect
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has default properties" do
|
20
|
+
@base.properties.should == [:data]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has default raw" do
|
24
|
+
@base.raw.should == @data
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|