git-ds 0.9.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.
Files changed (51) hide show
  1. data/README.rdoc +795 -0
  2. data/doc/Examples.rdoc +36 -0
  3. data/doc/examples/key_value/kv_get.rb +29 -0
  4. data/doc/examples/key_value/kv_init.rb +20 -0
  5. data/doc/examples/key_value/kv_list.rb +28 -0
  6. data/doc/examples/key_value/kv_remove.rb +29 -0
  7. data/doc/examples/key_value/kv_set.rb +39 -0
  8. data/doc/examples/key_value/model.rb +156 -0
  9. data/doc/examples/key_value/test.rb +50 -0
  10. data/doc/examples/test_suite/model.rb +503 -0
  11. data/doc/examples/test_suite/test.rb +173 -0
  12. data/doc/examples/test_suite/ts_add_bug.rb +65 -0
  13. data/doc/examples/test_suite/ts_add_module.rb +74 -0
  14. data/doc/examples/test_suite/ts_add_module_to_test.rb +78 -0
  15. data/doc/examples/test_suite/ts_add_test.rb +77 -0
  16. data/doc/examples/test_suite/ts_add_test_suite.rb +65 -0
  17. data/doc/examples/test_suite/ts_add_test_to_bug.rb +76 -0
  18. data/doc/examples/test_suite/ts_init.rb +20 -0
  19. data/doc/examples/test_suite/ts_list.rb +118 -0
  20. data/doc/examples/test_suite/ts_perform_test.rb +104 -0
  21. data/doc/examples/test_suite/ts_update_bugs.rb +58 -0
  22. data/doc/examples/user_group/model.rb +265 -0
  23. data/doc/examples/user_group/test.rb +64 -0
  24. data/doc/examples/user_group/ug_add_group.rb +39 -0
  25. data/doc/examples/user_group/ug_add_group_user.rb +36 -0
  26. data/doc/examples/user_group/ug_add_user.rb +39 -0
  27. data/doc/examples/user_group/ug_init.rb +20 -0
  28. data/doc/examples/user_group/ug_list.rb +32 -0
  29. data/lib/git-ds.rb +14 -0
  30. data/lib/git-ds/config.rb +53 -0
  31. data/lib/git-ds/database.rb +289 -0
  32. data/lib/git-ds/exec_cmd.rb +107 -0
  33. data/lib/git-ds/index.rb +205 -0
  34. data/lib/git-ds/model.rb +136 -0
  35. data/lib/git-ds/model/db_item.rb +42 -0
  36. data/lib/git-ds/model/fs_item.rb +51 -0
  37. data/lib/git-ds/model/item.rb +428 -0
  38. data/lib/git-ds/model/item_list.rb +97 -0
  39. data/lib/git-ds/model/item_proxy.rb +128 -0
  40. data/lib/git-ds/model/property.rb +144 -0
  41. data/lib/git-ds/model/root.rb +46 -0
  42. data/lib/git-ds/repo.rb +455 -0
  43. data/lib/git-ds/shared.rb +17 -0
  44. data/lib/git-ds/transaction.rb +77 -0
  45. data/tests/ut_database.rb +304 -0
  46. data/tests/ut_git_grit_equiv.rb +195 -0
  47. data/tests/ut_index.rb +203 -0
  48. data/tests/ut_model.rb +360 -0
  49. data/tests/ut_repo.rb +260 -0
  50. data/tests/ut_user_group_model.rb +316 -0
  51. metadata +142 -0
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # :title: Git-DS::Shared
3
+ =begin rdoc
4
+
5
+ Copyright 2010 Thoughtgang <http://www.thoughtgang.org>
6
+ =end
7
+
8
+ module GitDS
9
+
10
+ # =============================================================================
11
+ =begin rdoc
12
+ Exception raised when a repo-backed object does not exist
13
+ =end
14
+ class ObjectNotFound < NameError
15
+ end
16
+
17
+ end
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+ # :title: Git-DS::Transaction
3
+ =begin rdoc
4
+
5
+ Copyright 2010 Thoughtgang <http://www.thoughtgang.org>
6
+ =end
7
+
8
+ require 'git-ds/shared'
9
+ require 'git-ds/exec_cmd'
10
+
11
+ module GitDS
12
+
13
+ =begin rdoc
14
+ Exception raised to rollback a transaction.
15
+ =end
16
+ class TransactionRollback < RuntimeError
17
+ end
18
+
19
+ =begin rdoc
20
+ A Transaction takes a code block and guarantees that all of its commands, or
21
+ none, are executed. Transactions can be nested.
22
+
23
+ Usage:
24
+ db.transaction { |trans, idx| ... }
25
+ =end
26
+ class Transaction < ExecCmd
27
+
28
+ attr_reader :propagate_exceptions
29
+
30
+ =begin rdoc
31
+ A transaction is considered successful if the transaction block executes with
32
+ no exceptions. If a block must exit prematurely and abort the transaction,
33
+ it should use the rollback method.
34
+
35
+ Note that exceptions are propagated to the parent if transaction is nested;
36
+ this permits an inner transaction to abort an outer transaction when
37
+ rollback() is called.
38
+ =end
39
+ def perform
40
+ @propagate_exceptions = false # propagation off by default
41
+ rv = true
42
+ begin
43
+ instance_eval(&self.block)
44
+ rescue Exception => e
45
+ raise e if self.nested
46
+ raise e if (not e.kind_of? TransactionRollback) && @propagate_exceptions
47
+
48
+ rv = false
49
+ end
50
+
51
+ if rv
52
+ self.index.build # required during nesting to support merge_and_branch
53
+ commit if not @nested
54
+ end
55
+
56
+ rv
57
+ end
58
+
59
+ =begin rdoc
60
+ Throw all non-rollback exceptions after aborting the transaction. This is
61
+ useful for debugging transaction blocks.
62
+
63
+ By default, all exceptions are caught and discarded.
64
+ =end
65
+ def propagate
66
+ @propagate_exceptions = true
67
+ end
68
+
69
+ =begin rdoc
70
+ Abort the transaction.
71
+ =end
72
+ def rollback
73
+ raise TransactionRollback.new
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,304 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright 2010 Thoughtgang <http://www.thoughtgang.org>
3
+ # Unit test for Git-DS Database class
4
+
5
+ require 'test/unit'
6
+ require 'fileutils'
7
+
8
+ require 'git-ds/database'
9
+
10
+ # StageIndex that tracks the number of writes made
11
+ class TestStageIndex < GitDS::StageIndex
12
+ attr_reader :write_count
13
+
14
+ def commit(msg, author=nil)
15
+ @write_count ||= 0
16
+ @write_count += 1
17
+ super
18
+ end
19
+
20
+ def clear_write_count
21
+ @write_count = 0
22
+ end
23
+ end
24
+
25
+ class TC_GitDatabaseTest < Test::Unit::TestCase
26
+ TMP = File.dirname(__FILE__) + File::SEPARATOR + 'tmp'
27
+
28
+ attr_reader :db
29
+
30
+ def setup
31
+ FileUtils.remove_dir(TMP) if File.exist?(TMP)
32
+ Dir.mkdir(TMP)
33
+
34
+ path = TMP + File::SEPARATOR + 'db_test'
35
+ @db = GitDS::Database.new(path)
36
+ end
37
+
38
+ def teardown
39
+ FileUtils.remove_dir(TMP) if File.exist?(TMP)
40
+ end
41
+
42
+ def test_connect
43
+ path = TMP + File::SEPARATOR + 'test-db-conn'
44
+
45
+ # no-create should refuse to create the database
46
+ GitDS::Database.connect(path, false)
47
+ assert( (not File.exist?(path + File::SEPARATOR + '.git')),
48
+ "Repo #{path} incorrectly created by connect" )
49
+
50
+ # ...otherwise connect should create the db
51
+ db = GitDS::Database.connect(path)
52
+ assert( File.exist?(path + File::SEPARATOR + '.git'),
53
+ "Repo #{path} not created by connect" )
54
+
55
+ # verify that closing the DB works.
56
+ db.close
57
+
58
+ # verify that a closed database cannot be acted on
59
+ # NOTE: this should verify every method
60
+ assert_raise( GitDS::InvalidDbError ) { db.exec }
61
+ assert_raise( GitDS::InvalidDbError ) { db.head }
62
+ assert_raise( GitDS::InvalidDbError ) { db.tree }
63
+ assert_raise( GitDS::InvalidDbError ) { db.index }
64
+ assert_raise( GitDS::InvalidDbError ) { db.transaction }
65
+ assert_raise( GitDS::InvalidDbError ) { db.purge }
66
+ assert_raise( GitDS::InvalidDbError ) { db.close }
67
+ end
68
+
69
+ def test_create_delete
70
+ path = TMP + File::SEPARATOR + 'test-db'
71
+
72
+ # test that ctor creates a database by default
73
+ GitDS::Database.new(path)
74
+ assert( File.exist?(path + File::SEPARATOR + '.git'),
75
+ "Repo #{path} not created via new" )
76
+
77
+ # test that connecting to an existing database works
78
+ db = GitDS::Database.connect(path, false)
79
+ assert_not_nil( db, 'Connect to existing DB failed' )
80
+
81
+ # test that deleting a database works
82
+ db.purge
83
+ assert( (not File.exist?(path + File::SEPARATOR + '.git')),
84
+ "Repo #{path} did not get deleted" )
85
+ end
86
+
87
+ def test_config
88
+ cfg = GitDS::RepoConfig.new(@db)
89
+ assert_equal('misc.stuff', cfg.path('stuff'), 'Default path is wrong')
90
+
91
+ cfg = GitDS::RepoConfig.new(@db, 'a_b c?d')
92
+ assert_equal('a-b-c-d.stuff', cfg.path('stuff'), 'Cleaned path is wrong')
93
+
94
+ cfg = GitDS::RepoConfig.new(@db, 'test')
95
+ cfg['stuff'] = '123456'
96
+ assert_equal('123456', cfg['stuff'], 'Could not write to section')
97
+
98
+ assert_equal('', @db.config['a test entry'], 'Test cfg entry not empty')
99
+ assert_equal('git-ds.a-test-entry', @db.config.path('a test entry'),
100
+ 'Config object generated wrong path')
101
+ @db.config['a test entry'] = 'abcdef'
102
+ assert_equal('abcdef', @db.config['a test entry'], 'Cfg string incorrect')
103
+ end
104
+
105
+ def test_staging
106
+ assert((not @db.staging?), 'db.staging not nil by default')
107
+
108
+ index = GitDS::StageIndex.new(@db)
109
+ @db.staging = index
110
+ assert_equal(index, @db.staging, 'db.staging= method failed')
111
+
112
+ @db.staging = nil
113
+ assert((not @db.staging?), 'db.staging=nil method failed')
114
+ end
115
+
116
+ def test_exec
117
+ assert((not @db.staging?), 'db.staging not nil by default')
118
+
119
+ # test with no index
120
+ fname, data = 'a_test_file', '123456'
121
+ @db.exec { index.add(fname, data) }
122
+ assert( (not @db.staging?), 'exec created current index!')
123
+
124
+ # verify that exceptions do not break anything
125
+ assert_raises(RuntimeError, 'ExecCmd did not propagate error') {
126
+ @db.exec {
127
+ raise RuntimeError
128
+ }
129
+ }
130
+
131
+ # Verify that the exec worked
132
+ index = TestStageIndex.new(@db)
133
+ blob = index.current_tree./(fname)
134
+ assert_not_nil(blob, "db.exec did not create '#{fname}' in staging")
135
+ assert_equal(data, blob.data, "BLOB data for '#{fname}' does not match")
136
+
137
+ # test exec with staging set
138
+ @db.staging = index
139
+ @db.exec { index.delete(fname) }
140
+ index.build
141
+ blob = index.current_tree./(fname)
142
+ assert_equal(index, @db.staging, 'db.exec clobbered staging')
143
+ assert_nil(blob, "db.exec did not delete '#{fname}' in staging")
144
+
145
+ # test nested exec
146
+ name1, data1 = 'test1', '!!##$$@@^^**&&%%'
147
+ name2, data2 = 'test2', '_-_-_-'
148
+ @db.staging.clear_write_count
149
+ @db.exec {
150
+ index.add(name1, data1)
151
+ database.exec { index.add(name2, data2) }
152
+ }
153
+ @db.staging.commit('etc')
154
+ assert_equal(index, @db.staging,
155
+ 'nested db.exec clobbered staging')
156
+ assert_equal(1, @db.staging.write_count,
157
+ 'Nested exec caused > 1 write!')
158
+
159
+ # verify that both files in nested exec were created
160
+ blob = index.current_tree./(name1)
161
+ assert_not_nil(blob, "nested db.exec did not create '#{name1}' in staging")
162
+ assert_equal(data1, blob.data, "BLOB data for '#{name1}' does not match")
163
+
164
+ blob = index.current_tree./(name2)
165
+ assert_not_nil(blob, "nested db.exec did not create '#{name2}' in staging")
166
+ assert_equal(data2, blob.data, "BLOB data for '#{name2}' does not match")
167
+
168
+ # cleanup
169
+ index.delete(name1)
170
+ index.delete(name2)
171
+ @db.staging = nil
172
+
173
+ # test commits
174
+ num_commits = @db.commits.count
175
+ @db.exec {
176
+ index.add('exec-nested-commit-file-1', 'zaazza')
177
+ database.exec {
178
+ index.add('exec-nested-commit-file-2', 'plplpl')
179
+ commit
180
+ }
181
+ }
182
+ assert_equal(num_commits + 2, @db.commits.count, 'Nested commits failed')
183
+ end
184
+
185
+ def test_transaction
186
+ assert((not @db.staging?), 'db.staging not nil by default')
187
+
188
+ # test with no index
189
+ fname, data = 'test_file_1', 'abcdef'
190
+ @db.transaction { index.add(fname, data) }
191
+ assert( (not @db.staging?), 'transaction created current index!')
192
+
193
+ # Verify that the transaction worked
194
+ index = TestStageIndex.new(@db)
195
+ blob = index.current_tree./(fname)
196
+ assert_not_nil(blob, "db.exec did not create '#{fname}' in staging")
197
+ assert_equal(data, blob.data, "BLOB data for '#{fname}' does not match")
198
+
199
+ # test rollback method
200
+ name1, data1 = 'test_file_2', '54321'
201
+ @db.transaction {
202
+ index.add(name1, data1)
203
+ rollback
204
+ }
205
+ blob = index.current_tree./(name1)
206
+ assert_nil(blob, "rollback still created '#{name1}' in staging")
207
+
208
+ # test nested rollback
209
+ @db.transaction {
210
+ index.add(name1, data1)
211
+ database.transaction { rollback }
212
+ }
213
+ blob = index.current_tree./(name1)
214
+ assert_nil(blob, "rollback still created '#{name1}' in staging")
215
+
216
+ # test rollback on raise
217
+ @db.transaction {
218
+ index.add(name1, data1)
219
+ raise "ROLLBACK!"
220
+ }
221
+ blob = index.current_tree./(name1)
222
+ assert_nil(blob, "transaction raise still created '#{name1}' in staging")
223
+
224
+ assert_raises(RuntimeError, 'Transaction did not propagate error') {
225
+ @db.transaction {
226
+ propagate
227
+ raise RuntimeError
228
+ }
229
+ }
230
+
231
+ # test commit
232
+ msg = 'SUCCESS'
233
+ name, email = 'me', 'myself@i.com'
234
+ @db.transaction {
235
+ author name, email
236
+ message(msg)
237
+ index.add('test-commit-file', 'zyxwvu')
238
+ }
239
+ cmt = @db.commits.last
240
+ assert_not_nil(cmt, "transaction did not create commit")
241
+ assert_equal(msg, cmt.message, "transaction commit has wrong message")
242
+ assert_equal(name, cmt.author.name, "transaction commit has wrong author")
243
+ assert_equal(email, cmt.author.email, "transaction commit has wrong email")
244
+
245
+ # test commits in nested transaction
246
+ num_commits = @db.commits.count
247
+ @db.transaction {
248
+ index.add('trans-nested-commit-file-1', '223344')
249
+ database.transaction {
250
+ index.add('trans-nested-commit-file-2', 'ccddff')
251
+ commit
252
+ }
253
+ }
254
+ assert_equal(num_commits + 2, @db.commits.count, 'Nested commits failed')
255
+
256
+ # test transaction with staging set
257
+ @db.staging = index
258
+ @db.transaction { index.delete(fname) }
259
+ blob = index.current_tree./(fname)
260
+ assert_equal(index, @db.staging, 'db.exec clobbered staging')
261
+
262
+ # test nested transactions
263
+ name2, data2 = 'xtest2', '~~~~~~~'
264
+ @db.staging.clear_write_count
265
+ @db.transaction {
266
+ index.add(name1, data1)
267
+ database.transaction { index.add(name2, data2) }
268
+ }
269
+ index.commit('etc') # existing index means both transactions are nested
270
+ assert_equal(index, @db.staging, 'nested transaction clobbered staging')
271
+ assert_equal(1, @db.staging.write_count,
272
+ 'Nested transaction caused > 1 write!')
273
+
274
+ # verify that both files in nested exec were created
275
+ blob = index.current_tree./(name1)
276
+ assert_not_nil(blob, "nested db.exec did not create '#{name1}' in staging")
277
+ assert_equal(data1, blob.data, "BLOB data for '#{name1}' does not match")
278
+
279
+ blob = index.current_tree./(name2)
280
+ assert_not_nil(blob, "nested db.exec did not create '#{name2}' in staging")
281
+ assert_equal(data2, blob.data, "BLOB data for '#{name2}' does not match")
282
+ end
283
+
284
+ def test_branch
285
+
286
+ num = @db.heads.count
287
+ @db.branch_and_merge {
288
+ index.add('tmp/1', '1')
289
+ }
290
+ assert_equal(num+1, @db.heads.count, 'Anon Branch&Merge failed!')
291
+
292
+ name = 'named branch'
293
+ num = @db.heads.count
294
+ @db.branch_and_merge(name) {
295
+ database.index.add('tmp/2', '2')
296
+ }
297
+ assert_equal(num+1, @db.heads.count, 'Named Branch&Merge failed!')
298
+ assert_equal(1, @db.heads.select{ |h| h.name == @db.clean_tag(name)}.count,
299
+ 'Named Branch not present!')
300
+
301
+ end
302
+
303
+ end
304
+
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright 2011 Thoughtgang <http://www.thoughtgang.org>
3
+ # Unit tests to ensure that assumptions about Grit behaving like Git still hold.
4
+ # Note: This is used to verify that Grit can be made to act like the Git
5
+ # command line, and to determine what Grit methods correspond to
6
+ # Git commands.
7
+
8
+ require 'test/unit'
9
+ require 'fileutils'
10
+
11
+ require 'rubygems'
12
+ require 'grit'
13
+ require 'grit/git-ruby'
14
+
15
+ # NOTES:
16
+ # `git read-tree --prefix=path #{sha}` will read SHA object into git at the
17
+ # specified path. git-write-tree can then be used to create the tree object
18
+ # for the entire index. NOTE: `export GIT_INDEX_FILE=/tmp/index` can be used
19
+ # to specify an index that is NOT the staging index. IMPORTANT!
20
+ # git-update-index --force-remove
21
+ # git-update-index --add --cacheinfo 100644 `echo '#{data}' | git-hash-object --stdin` #{path}
22
+ # echo '#{msg}' | git commit-tree #{sha}
23
+ # git-ls-files --stage #{path}
24
+ # git rev-parse --show-toplevel
25
+ # git rev-parse --show-prefix : path of curr dir from top_level. cdup = inverse.
26
+
27
+ # Grit:Git methods:
28
+ # object_exists? sha
29
+ # git_dir, work_tree
30
+ # fs_exist? path [on fs, in git dir]. fs_read|write|delete|move|mkdir|chmod
31
+ # commit_from_sha sha
32
+ # raw_git(command, index_filename) : note this is exec_in_git!
33
+ # get_object_by_sha1 sha
34
+ # object_exists? sha
35
+ # cat_file_type sha
36
+ # cat_file_size sha
37
+ # cat_file sha
38
+ # list_tree sha => ['blob'|'tree']['NAME'] = { :mode, :sha }
39
+ # ls_tree sha, paths, recursive = false -> cat-file output
40
+ # ls_tree_path(sha, path, append=nil) -> array of tree entries
41
+ # get_subtree(commit_sha, path) -> tree sha (or parent of, or /)
42
+
43
+ class TC_GitGritEquivalenceTest < Test::Unit::TestCase
44
+ TMP = File.dirname(__FILE__) + File::SEPARATOR + 'tmp'
45
+ GIT_REPO = 'git_repo'
46
+ GRIT_REPO = 'grit_repo'
47
+
48
+ attr_reader :repo # grit repo object
49
+
50
+ def exec_in_dir(dir, &block)
51
+ curr = Dir.getwd
52
+ Dir.chdir dir
53
+ result = yield
54
+ Dir.chdir curr
55
+ result
56
+ end
57
+
58
+ def git_exec(&block)
59
+ exec_in_dir(TMP + File::SEPARATOR + GIT_REPO, &block)
60
+ end
61
+
62
+ # this allows mimics Grit's use of anonymous (non-stage) indexes
63
+ def git_index_exec(filename, &block)
64
+ old_index = ENV[GIT_INDEX_FILE]
65
+ ENV[GIT_INDEX_FILE] = TMP + File::SEPARATOR + filename
66
+ rv = git_exec(&block)
67
+ ENV[GIT_INDEX_FILE] = old_index
68
+ rv
69
+ end
70
+
71
+ # Create a Git repo and a Grit repo in a temporary directory
72
+ def setup
73
+ FileUtils.remove_dir(TMP) if File.exist?(TMP)
74
+ Dir.mkdir(TMP)
75
+
76
+ # init git repo
77
+ exec_in_dir(TMP) { `git init #{GIT_REPO}` }
78
+ @git_path = TMP + File::SEPARATOR + GIT_REPO
79
+
80
+ # init grit repo
81
+ @grit_path = TMP + File::SEPARATOR + GRIT_REPO
82
+ @repo = Grit::Repo.init(@grit_path)
83
+ end
84
+
85
+ # Delete all repos
86
+ def teardown
87
+ FileUtils.remove_dir(TMP) if File.exist?(TMP)
88
+ end
89
+
90
+ # Test that initializing a repository produces the same results
91
+ def test_init
92
+ sep = File::SEPARATOR
93
+ assert( File.exist?(TMP + sep + GIT_REPO + sep + '.git'),
94
+ 'git repo was not created!')
95
+ assert( File.exist?(TMP + sep + GRIT_REPO + sep + '.git'),
96
+ 'Grit repo was not created!')
97
+ end
98
+
99
+ # Test that generating an object SHA produces the same results
100
+ def test_object_sha
101
+ data = '01020304050607080900!@#$%^&*()_+='
102
+ git_sha = git_exec { `echo -n '#{data}' | git hash-object --stdin` }.chomp
103
+ grit_sha = Grit::GitRuby::Internal::LooseStorage.calculate_sha(data, 'blob')
104
+ assert_equal( git_sha, grit_sha, 'Git and Grit SHA differ')
105
+ end
106
+
107
+ # Test that adding a Blob object produces the same results
108
+ def test_add_blob_to_object_database
109
+ data = '7654321098!@$#%^&*()_-=+'
110
+ git_sha = git_exec {`echo -n '#{data}' | git hash-object -w --stdin`}.chomp
111
+ blob_data = git_exec { `git cat-file -p #{git_sha}` }
112
+ assert_equal(data, blob_data, 'Git cat-file does not match input')
113
+
114
+
115
+ grit_sha = @repo.git.put_raw_object(data, 'blob')
116
+ assert(@repo.git.object_exists?(grit_sha), 'Grit fails object_exists? call')
117
+ assert_equal(data, @repo.git.ruby_git.cat_file(grit_sha),
118
+ 'Grit cat_file does not match input')
119
+
120
+ assert_equal( git_sha, grit_sha, 'Git and Grit SHA differ')
121
+
122
+ sep = File::SEPARATOR
123
+ path = sep + '.git' + sep + 'objects' + sep + git_sha[0,2] + sep +
124
+ git_sha[2..-1]
125
+ assert(File.exist?(@git_path + path), 'Git did not add blob to object DB')
126
+ assert(File.exist?(@grit_path + path), 'Grit did not add blob to object DB')
127
+ end
128
+
129
+ # Test that adding a Tree object produces the same results
130
+ def test_add_path_to_object_database
131
+ bdata = "123454321"
132
+ bsha = git_exec {`echo -n '#{bdata}' | git hash-object -w --stdin`}.chomp
133
+ grit_bsha = @repo.git.put_raw_object(bdata, 'blob')
134
+
135
+ tdata1 = "100644 blob #{bsha}\ttest_blob"
136
+ git_sha = git_exec {`echo -n '#{tdata1}' | git mktree`}.chomp
137
+
138
+ # Note the different format needed for Grit!
139
+ tdata1 = "100644 test_blob\0#{[bsha].pack('H*')}"
140
+ grit_sha = @repo.git.put_raw_object(tdata1, 'tree')
141
+ assert(@repo.git.object_exists?(grit_sha), 'Grit fails object_exists? call')
142
+ assert_not_nil( @repo.tree(grit_sha), 'Grit did not create valid tree')
143
+
144
+ assert_equal( git_sha, grit_sha, 'Git and Grit SHA differ')
145
+ end
146
+
147
+ # Test that adding a Blob to the (staging) index produces the same results
148
+ def test_add_blob_to_index
149
+ data = '....****....'
150
+ fname = 'test_add_blob'
151
+
152
+ # Add BLOB to Git object database
153
+ git_sha = git_exec {`echo -n '#{data}' | git hash-object -w --stdin`}.chomp
154
+ # Add BLOB to Git index
155
+ git_exec {`git update-index --add --cacheinfo 100644 #{git_sha} #{fname}`}
156
+ # Get SHA for filename in index
157
+ mode, sha, junk = git_exec { `git ls-files -s #{fname}` }.split(/\s/)
158
+ assert_equal(git_sha, sha, 'SHA in staging does not match input SHA')
159
+
160
+ idx = @repo.index
161
+ # Add BLOB to Grit index
162
+ idx.add( fname, data)
163
+ # Add BLOB to Grit object database and re-read
164
+ idx.read_tree(idx.write_tree(idx.tree))
165
+ # Get SHA for filename in index
166
+ blob = idx.current_tree/fname
167
+ assert_equal(data, blob.data, 'Grit index data does not match input data')
168
+
169
+ assert_equal( git_sha, blob.id, 'Git and Grit SHA differ')
170
+ end
171
+
172
+ def test_add_path_to_index
173
+ end
174
+
175
+ def test_remove_file_from_object_database
176
+ end
177
+
178
+ def test_remove_path_from_object_database
179
+ end
180
+
181
+ def test_remove_file_from_index
182
+ end
183
+
184
+ def test_remove_path_from_index
185
+ end
186
+
187
+ def test_list_tree_in_object_database
188
+ end
189
+
190
+ def test_list_tree_in_index
191
+ end
192
+
193
+ # TODO: branch, commit, ref.
194
+ end
195
+