@@ -29,6 +29,7 @@ <h2 id="content">Contents</h2>
29
29
< li > < a href ="api.html#trees "> tree traversal</ a > </ li >
30
30
< li > < a href ="api.html#revwalk "> revision walking</ a > </ li >
31
31
< li > < a href ="api.html#index "> index file (staging area) manipulation</ a > </ li >
32
+ < li > < a href ="api.html#backends "> custom ODB backends</ a > </ li >
32
33
</ ul >
33
34
</ div >
34
35
</ div > </ div >
@@ -48,17 +49,17 @@ <h2 id="started">Getting started</h2>
48
49
the libgit2 API.
49
50
</ p >
50
51
51
- < p > You will have to include both < code > git2.h</ code > for the main
52
- libgit2 functionality, plus a backend, which generally is going to
53
- be < code > odb_backend.h</ code > . This is the on-disk normal Git data
54
- store.</ p >
52
+ < p > You will have to include both < code > git2.h</ code > to access the main
53
+ libgit2 functionality.</ p >
55
54
56
55
< span class ="shtitle "> C</ span >
57
56
< pre class ="sh_c ">
58
57
#include <git2.h>
59
- #include <git2/odb_backend.h>
60
58
git_repository *repo;
61
59
git_repository_open(&repo, "/path/to/repo.git");
60
+
61
+ /* do stuff with the repository */
62
+
62
63
git_repository_free(repo);
63
64
</ pre >
64
65
@@ -136,9 +137,13 @@ <h2 id="rawread">Raw Data Reading and Writing</h2>
136
137
< p > This is the lowest layer of Git access, raw read and write
137
138
access to the object database. With libgit2 you can read the raw
138
139
data of any object out of the database by providing the SHA1 hash
139
- of that object. It will pull from loose or packed objects
140
- transparently.
141
- </ p >
140
+ of that object.</ p >
141
+
142
+ < p > The object database is split in several layers, called backends.
143
+ By default, it is instantiated with two backends, just like the original
144
+ git.git: object requests will first be looked up in the loose object storage,
145
+ and if not found, a lookup will be attempted on the packfile storage. On top
146
+ of that, libgit2 also supports < a href ="api.html#backends "> custom backends</ a > .</ p >
142
147
143
148
< h3 > Reading Data</ h3 >
144
149
@@ -158,7 +163,9 @@ <h3>Reading Data</h3>
158
163
159
164
data = obj.data; // raw object data
160
165
str_type = git_obj_type_to_string(obj.type); // human readable object type
161
- printf("object length and type: %d, %s\n", (int)obj.len, str_type)
166
+ printf("object length and type: %d, %s\n", (int)obj.len, str_type);
167
+
168
+ git_obj_close(&obj); // close the object when you are done with it
162
169
</ pre >
163
170
164
171
< br />
@@ -167,7 +174,11 @@ <h3>Reading Data</h3>
167
174
< pre class ="sh_ruby ">
168
175
sha = "599955586da1c3ad514f3e65f1081d2012ec862d"
169
176
if @repo.exists(sha)
170
- data, length, type = @repo.read(sha)
177
+ raw_objct = @repo.read(sha)
178
+
179
+ pp raw_object.data
180
+ pp raw_object.type
181
+ pp raw_object.len
171
182
end
172
183
</ pre >
173
184
@@ -189,15 +200,14 @@ <h3>Writing Data</h3>
189
200
190
201
odb = git_repository_database(repo);
191
202
192
- (& obj)- > data = "any ol content will do";
193
- (& obj)- > len = 22;
194
- (& obj)- > type = git_obj_string_to_type("blob");
203
+ obj. data = "any ol content will do";
204
+ obj. len = 22;
205
+ obj. type = git_obj_string_to_type("blob");
195
206
196
- git_obj_hash(&oid, &obj);
197
- git_oid_fmt(out, &oid);
198
- printf("SHA hex string: %s\n", out);
207
+ error = git_odb_write(&oid, odb, &obj); // actually write to the db, update oid
199
208
200
- error = git_odb_write(&oid, odb, &obj); // actually write to the db
209
+ git_oid_fmt(out, &oid);
210
+ printf("The new OID is: %s\n", out);
201
211
</ pre >
202
212
203
213
< br />
@@ -222,6 +232,18 @@ <h2 id="parsing">Object Parsing and Writing</h2>
222
232
format given the raw data to for easy write-back capability.
223
233
</ p >
224
234
235
+ < p > You can get objects from the database either via the
236
+ < code > git_[object]_lookup(&obj, repo, &id)</ code > method or the more
237
+ general < code > git_repository_lookup(&obj, repo, &oid, OBJ_TYPE)</ code >
238
+ call. I will use them interchangably through these examples.</ p >
239
+
240
+ < p > Note that any object references returned by these two methods are owned by
241
+ the Repository object, and shall not be < code > free</ code > 'd manually. The repository
242
+ has an internal object cache, and will take care of freeing all the loaded
243
+ objects after the repository itself is < code > free</ code > 'd. However, if you
244
+ are sure that an object won't be needed again, you can manually free it
245
+ using the < code > git_object_free(obj)</ code > method.</ p >
246
+
225
247
< a class ="apilink " href ="http://libgit2.github.com/libgit2/group__git__commit.html "> Commit API</ a >
226
248
< h3 id ="commits "> Commits</ h3 >
227
249
@@ -270,10 +292,6 @@ <h3 id="commits">Commits</h3>
270
292
git_object_write((git_object *)commit);
271
293
</ pre >
272
294
273
- < p > Notice that you can get objects from the database either via the
274
- < code > git_[object]_lookup(&obj, repo, &id)</ code > method or the more
275
- general < code > git_repository_lookup(&obj, repo, &oid, OBJ_TYPE)</ code >
276
- call. I will use them interchangably through these examples.</ p >
277
295
278
296
< br />
279
297
@@ -476,8 +494,10 @@ <h2 id="revwalk">Revision Walking</h2>
476
494
< span class ="shtitle "> Ruby</ span >
477
495
< pre class ="sh_ruby ">
478
496
walker = Rugged::Walker.new(@repo)
479
- walker.push("d6c2306fcbf0d346b9129b303c3babae58f619f7") # find commits reachable from this
480
- walker.hide("42b551c353a29d29f6f0dc4137a40706b128a8d3") # but not from this
497
+ # find commits reachable from this
498
+ walker.push("d6c2306fcbf0d346b9129b303c3babae58f619f7")
499
+ # but not from this
500
+ walker.hide("42b551c353a29d29f6f0dc4137a40706b128a8d3")
481
501
walker.each do |commit|
482
502
msg = commit.message
483
503
email = commit.author.email
@@ -547,6 +567,148 @@ <h3 id="indexread">Reading Index Files</h3>
547
567
</ div >
548
568
</ div > </ div >
549
569
570
+ < h2 id ="backends "> Custom backends</ h2 >
571
+
572
+ < div class ="contents "> < div class ="bullet ">
573
+ < div class ="description ">
574
+ < p > libgit2 decouples the Object Database logic from the actual storage of
575
+ the objects. This means that you can actually extend the library with
576
+ custom backends that steer away from the default "loose object and packfiles"
577
+ storage model that Git uses.</ p >
578
+
579
+ < p > Before extending the library with a custom backend in C, the special header
580
+ < code > git2/odb_backend.h</ code > must be included< p >
581
+
582
+ < h3 id ="indexread "> Implementing a custom backend</ h3 >
583
+
584
+
585
+ < span class ="shtitle "> C</ span >
586
+ < pre class ="sh_c ">
587
+ typedef struct {
588
+ git_odb_backend parent;
589
+
590
+ /* custom data for your backend */
591
+ const char *sqlite_db;
592
+ } sqlite_backend;
593
+
594
+ int sqlb_read(git_rawobj *out, git_odb_backend *back, const git_oid *oid)
595
+ {
596
+ sqlite_backend *b = (sqlite_backend *)back;
597
+
598
+ /* read the object identified by 'oid' and write its contents
599
+ to 'out'. Return 'GIT_SUCCESS' if the read was succesful,
600
+ or an error code otherwise. */
601
+
602
+ return GIT_SUCCESS;
603
+ }
604
+
605
+ int sqlb_read_header(git_rawobj *out, git_odb_backend *back, const git_oid *oid)
606
+ {
607
+ sqlite_backend *b = (sqlite_backend *)backend;
608
+
609
+ /* read the header of the object identified by 'oid' and fill
610
+ the 'out->type' and 'out->len' fields without actually
611
+ loading the whole object in memory. Return 'GIT_SUCCESS' if
612
+ the read was succesful, or an error code otherwise. */
613
+
614
+ return GIT_SUCCESS;
615
+ }
616
+
617
+ int sqlb_exists(git_odb_backend *back, const git_oid *oid)
618
+ {
619
+ sqlite_backend *b = (sqlite_backend *)back;
620
+
621
+ /* check whether the object identified by 'oid' exists in the backend.
622
+ Return 1 or 0. */
623
+
624
+ return 1;
625
+ }
626
+
627
+ int sqlb_write(git_oid *out, git_odb_backend *back, git_rawobj *obj)
628
+ {
629
+ sqlite_backend *b = (sqlite_backend *)back;
630
+
631
+ /* write the object in 'obj' to the storage, and fill the 'out' oid
632
+ with the SHA1 identifier of the written object. Return 'GIT_SUCCESS'
633
+ if the write was successful, error code otherwise */
634
+
635
+ return GIT_SUCCESS;
636
+ }
637
+
638
+ void sqlb_free(git_odb_backend *backend)
639
+ {
640
+ sqlite_backend *b = (sqlite_backend *)back;
641
+
642
+ /* completely free the backend instance */
643
+
644
+ free(b->sqlite_db);
645
+ free(b);
646
+ }
647
+
648
+ sqlite_backend *create_backend(const char *path_do_db)
649
+ {
650
+ sqlite_backend *backend;
651
+
652
+ /* create a new instance of the backend */
653
+ backend = calloc(1, sizeof(sqlite_backend));
654
+
655
+ /* fill the instance with pointers to the backend methods */
656
+ backend->parent.read = &sqlb_read;
657
+ backend->parent.read_header = &sqlb_read_header;
658
+ backend->parent.write = &sqlb_write;
659
+ backend->parent.exists = &sqlb_exists;
660
+ backend->parent.free = &sqlb_free;
661
+
662
+ /* set the priority of the backend */
663
+ backend->parent.priority = 3;
664
+
665
+ /* fill the custom data fields, if needed */
666
+ backend->sqlite_db = strdup(path_to_db);
667
+
668
+ return backend;
669
+ }
670
+ </ pre >
671
+
672
+ < p > Once you have created a new backend instance, you can add
673
+ it to an existing object database using the < code > git_odb_add_backend(backend)</ code > method.
674
+ A single backend instance can only be active in one ODB at the same time</ p >
675
+
676
+ < span class ="shtitle "> Ruby</ span >
677
+ < pre class ="sh_ruby ">
678
+ class TestBackend < Rugged::Backend
679
+ def read(oid)
680
+ # return a raw object with the read contents
681
+ Rugged::RawObject.new(type, contents)
682
+ end
683
+
684
+ def read_header(oid)
685
+ # return a raw object with the read header (type and length)
686
+ Rugged::RawObject.new(type, nil, len)
687
+ end
688
+
689
+ def exists(oid)
690
+ # return whether the object exists in the backend
691
+ true
692
+ end
693
+
694
+ def write(raw_object)
695
+ # write the object and return a SHA1 id
696
+ sha1
697
+ end
698
+ end
699
+
700
+ # add the backend to our repository
701
+ backend = TestBackend.new(5) # high priority
702
+ @repo.add_backend(backend)
703
+ </ pre >
704
+
705
+ </ div >
706
+ </ div > </ div >
707
+
708
+
709
+
710
+
711
+
550
712
< h2 id ="index "> Overview</ h2 >
551
713
552
714
< div class ="contents "> < div class ="bullet ">
0 commit comments