rugged 0.18.0.gh.de28323 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (283) hide show
  1. data/README.md +9 -4
  2. data/Rakefile +1 -1
  3. data/ext/rugged/extconf.rb +10 -0
  4. data/ext/rugged/rugged.c +153 -86
  5. data/ext/rugged/rugged.h +44 -33
  6. data/ext/rugged/rugged_blob.c +288 -60
  7. data/ext/rugged/rugged_branch.c +82 -57
  8. data/ext/rugged/rugged_commit.c +83 -86
  9. data/ext/rugged/rugged_config.c +68 -68
  10. data/ext/rugged/rugged_diff.c +509 -0
  11. data/ext/rugged/rugged_diff_delta.c +94 -0
  12. data/ext/rugged/rugged_diff_hunk.c +100 -0
  13. data/ext/rugged/rugged_diff_line.c +79 -0
  14. data/ext/rugged/rugged_diff_patch.c +169 -0
  15. data/ext/rugged/rugged_index.c +539 -8
  16. data/ext/rugged/rugged_note.c +74 -80
  17. data/ext/rugged/rugged_object.c +63 -8
  18. data/ext/rugged/rugged_reference.c +231 -145
  19. data/ext/rugged/rugged_remote.c +509 -53
  20. data/ext/rugged/rugged_repo.c +572 -236
  21. data/ext/rugged/rugged_revwalk.c +59 -36
  22. data/ext/rugged/rugged_settings.c +7 -9
  23. data/ext/rugged/rugged_signature.c +7 -11
  24. data/ext/rugged/rugged_tag.c +93 -39
  25. data/ext/rugged/rugged_tree.c +321 -58
  26. data/lib/rugged.rb +1 -0
  27. data/lib/rugged/commit.rb +16 -1
  28. data/lib/rugged/console.rb +9 -0
  29. data/lib/rugged/diff.rb +19 -0
  30. data/lib/rugged/diff/delta.rb +54 -0
  31. data/lib/rugged/diff/hunk.rb +23 -0
  32. data/lib/rugged/diff/line.rb +29 -0
  33. data/lib/rugged/diff/patch.rb +28 -0
  34. data/lib/rugged/repository.rb +36 -39
  35. data/lib/rugged/version.rb +1 -1
  36. data/test/blob_test.rb +308 -1
  37. data/test/branch_test.rb +7 -0
  38. data/test/commit_test.rb +7 -10
  39. data/test/coverage/cover.rb +9 -1
  40. data/test/diff_test.rb +777 -0
  41. data/test/fixtures/archive.tar.gz +0 -0
  42. data/test/fixtures/attr/attr0 +1 -0
  43. data/test/fixtures/attr/attr1 +29 -0
  44. data/test/fixtures/attr/attr2 +21 -0
  45. data/test/fixtures/attr/attr3 +4 -0
  46. data/test/fixtures/attr/binfile +1 -0
  47. data/test/fixtures/attr/dir/file +0 -0
  48. data/test/fixtures/attr/file +1 -0
  49. data/test/fixtures/attr/gitattributes +29 -0
  50. data/test/fixtures/attr/gitignore +2 -0
  51. data/test/fixtures/attr/ign +1 -0
  52. data/test/fixtures/attr/macro_bad +1 -0
  53. data/test/fixtures/attr/macro_test +1 -0
  54. data/test/fixtures/attr/root_test1 +1 -0
  55. data/test/fixtures/attr/root_test2 +6 -0
  56. data/test/fixtures/attr/root_test3 +19 -0
  57. data/test/fixtures/attr/root_test4.txt +14 -0
  58. data/test/fixtures/attr/sub/abc +37 -0
  59. data/test/fixtures/attr/sub/dir/file +0 -0
  60. data/test/fixtures/attr/sub/file +1 -0
  61. data/test/fixtures/attr/sub/ign/file +1 -0
  62. data/test/fixtures/attr/sub/ign/sub/file +1 -0
  63. data/test/fixtures/attr/sub/sub/dir +0 -0
  64. data/test/fixtures/attr/sub/sub/file +1 -0
  65. data/test/fixtures/attr/sub/sub/subsub.txt +1 -0
  66. data/test/fixtures/attr/sub/subdir_test1 +2 -0
  67. data/test/fixtures/attr/sub/subdir_test2.txt +1 -0
  68. data/test/fixtures/diff/another.txt +38 -0
  69. data/test/fixtures/diff/readme.txt +36 -0
  70. data/test/fixtures/mergedrepo/conflicts-one.txt +5 -0
  71. data/test/fixtures/mergedrepo/conflicts-two.txt +5 -0
  72. data/test/fixtures/mergedrepo/one.txt +10 -0
  73. data/test/fixtures/mergedrepo/two.txt +12 -0
  74. data/test/fixtures/status/current_file +1 -0
  75. data/test/fixtures/status/ignored_file +1 -0
  76. data/test/fixtures/status/modified_file +2 -0
  77. data/test/fixtures/status/new_file +1 -0
  78. data/test/fixtures/status/staged_changes +2 -0
  79. data/test/fixtures/status/staged_changes_modified_file +3 -0
  80. data/test/fixtures/status/staged_delete_modified_file +1 -0
  81. data/test/fixtures/status/staged_new_file +1 -0
  82. data/test/fixtures/status/staged_new_file_modified_file +2 -0
  83. data/test/fixtures/status/subdir.txt +2 -0
  84. data/test/fixtures/status/subdir/current_file +1 -0
  85. data/test/fixtures/status/subdir/modified_file +2 -0
  86. data/test/fixtures/status/subdir/new_file +1 -0
  87. data/test/fixtures/status//350/277/231 +1 -0
  88. data/test/fixtures/testrepo.git/config +5 -0
  89. data/test/fixtures/testrepo.git/objects/77/71329dfa3002caf8c61a0ceb62a31d09023f37 +0 -0
  90. data/test/fixtures/text_file.md +464 -0
  91. data/test/fixtures/unsymlinked.git/HEAD +1 -0
  92. data/test/fixtures/unsymlinked.git/config +6 -0
  93. data/test/fixtures/unsymlinked.git/description +1 -0
  94. data/test/fixtures/unsymlinked.git/info/exclude +2 -0
  95. data/test/fixtures/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf +0 -0
  96. data/test/fixtures/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b +0 -0
  97. data/test/fixtures/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c +0 -0
  98. data/test/fixtures/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 +0 -0
  99. data/test/fixtures/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c +0 -0
  100. data/test/fixtures/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 +0 -0
  101. data/test/fixtures/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d +0 -0
  102. data/test/fixtures/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 +0 -0
  103. data/test/fixtures/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 +0 -0
  104. data/test/fixtures/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 +2 -0
  105. data/test/fixtures/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 +0 -0
  106. data/test/fixtures/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a +0 -0
  107. data/test/fixtures/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 +0 -0
  108. data/test/fixtures/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 +0 -0
  109. data/test/fixtures/unsymlinked.git/refs/heads/exe-file +1 -0
  110. data/test/fixtures/unsymlinked.git/refs/heads/master +1 -0
  111. data/test/fixtures/unsymlinked.git/refs/heads/reg-file +1 -0
  112. data/test/index_test.rb +120 -0
  113. data/test/reference_test.rb +38 -3
  114. data/test/remote_test.rb +224 -3
  115. data/test/repo_reset_test.rb +2 -0
  116. data/test/repo_test.rb +147 -10
  117. data/test/test_helper.rb +5 -2
  118. data/vendor/libgit2/include/git2/attr.h +3 -3
  119. data/vendor/libgit2/include/git2/blob.h +11 -17
  120. data/vendor/libgit2/include/git2/branch.h +3 -2
  121. data/vendor/libgit2/include/git2/checkout.h +7 -0
  122. data/vendor/libgit2/include/git2/clone.h +3 -0
  123. data/vendor/libgit2/include/git2/commit.h +61 -66
  124. data/vendor/libgit2/include/git2/common.h +73 -42
  125. data/vendor/libgit2/include/git2/config.h +57 -71
  126. data/vendor/libgit2/include/git2/cred_helpers.h +2 -2
  127. data/vendor/libgit2/include/git2/diff.h +179 -30
  128. data/vendor/libgit2/include/git2/errors.h +3 -3
  129. data/vendor/libgit2/include/git2/index.h +225 -146
  130. data/vendor/libgit2/include/git2/indexer.h +2 -22
  131. data/vendor/libgit2/include/git2/inttypes.h +9 -9
  132. data/vendor/libgit2/include/git2/merge.h +123 -5
  133. data/vendor/libgit2/include/git2/odb.h +59 -38
  134. data/vendor/libgit2/include/git2/odb_backend.h +45 -104
  135. data/vendor/libgit2/include/git2/oid.h +30 -19
  136. data/vendor/libgit2/include/git2/pack.h +21 -3
  137. data/vendor/libgit2/include/git2/refdb.h +0 -35
  138. data/vendor/libgit2/include/git2/refs.h +93 -31
  139. data/vendor/libgit2/include/git2/refspec.h +17 -0
  140. data/vendor/libgit2/include/git2/remote.h +60 -20
  141. data/vendor/libgit2/include/git2/repository.h +48 -70
  142. data/vendor/libgit2/include/git2/reset.h +3 -3
  143. data/vendor/libgit2/include/git2/revparse.h +22 -0
  144. data/vendor/libgit2/include/git2/stash.h +1 -1
  145. data/vendor/libgit2/include/git2/status.h +131 -56
  146. data/vendor/libgit2/include/git2/strarray.h +2 -2
  147. data/vendor/libgit2/include/git2/submodule.h +16 -16
  148. data/vendor/libgit2/include/git2/sys/commit.h +46 -0
  149. data/vendor/libgit2/include/git2/sys/config.h +71 -0
  150. data/vendor/libgit2/include/git2/sys/index.h +179 -0
  151. data/vendor/libgit2/include/git2/sys/odb_backend.h +86 -0
  152. data/vendor/libgit2/include/git2/sys/refdb_backend.h +158 -0
  153. data/vendor/libgit2/include/git2/sys/refs.h +38 -0
  154. data/vendor/libgit2/include/git2/sys/repository.h +106 -0
  155. data/vendor/libgit2/include/git2/tag.h +44 -18
  156. data/vendor/libgit2/include/git2/trace.h +1 -2
  157. data/vendor/libgit2/include/git2/transport.h +74 -0
  158. data/vendor/libgit2/include/git2/tree.h +12 -22
  159. data/vendor/libgit2/include/git2/types.h +33 -0
  160. data/vendor/libgit2/include/git2/version.h +2 -2
  161. data/vendor/libgit2/src/array.h +66 -0
  162. data/vendor/libgit2/src/attr.c +26 -13
  163. data/vendor/libgit2/src/attr_file.c +3 -2
  164. data/vendor/libgit2/src/attr_file.h +3 -3
  165. data/vendor/libgit2/src/attrcache.h +4 -4
  166. data/vendor/libgit2/src/blob.c +13 -9
  167. data/vendor/libgit2/src/blob.h +2 -2
  168. data/vendor/libgit2/src/branch.c +67 -49
  169. data/vendor/libgit2/src/cache.c +224 -54
  170. data/vendor/libgit2/src/cache.h +33 -20
  171. data/vendor/libgit2/src/checkout.c +145 -85
  172. data/vendor/libgit2/src/clone.c +62 -50
  173. data/vendor/libgit2/src/commit.c +74 -40
  174. data/vendor/libgit2/src/commit.h +2 -3
  175. data/vendor/libgit2/src/commit_list.c +14 -8
  176. data/vendor/libgit2/src/config.c +119 -36
  177. data/vendor/libgit2/src/config.h +3 -0
  178. data/vendor/libgit2/src/config_cache.c +24 -7
  179. data/vendor/libgit2/src/config_file.c +9 -6
  180. data/vendor/libgit2/src/crlf.c +4 -2
  181. data/vendor/libgit2/src/date.c +3 -3
  182. data/vendor/libgit2/src/delta.c +1 -1
  183. data/vendor/libgit2/src/diff.c +681 -303
  184. data/vendor/libgit2/src/diff.h +34 -2
  185. data/vendor/libgit2/src/diff_driver.c +405 -0
  186. data/vendor/libgit2/src/diff_driver.h +49 -0
  187. data/vendor/libgit2/src/diff_file.c +447 -0
  188. data/vendor/libgit2/src/diff_file.h +58 -0
  189. data/vendor/libgit2/src/diff_patch.c +995 -0
  190. data/vendor/libgit2/src/diff_patch.h +46 -0
  191. data/vendor/libgit2/src/diff_print.c +430 -0
  192. data/vendor/libgit2/src/diff_tform.c +464 -203
  193. data/vendor/libgit2/src/diff_xdiff.c +166 -0
  194. data/vendor/libgit2/src/diff_xdiff.h +28 -0
  195. data/vendor/libgit2/src/fetch.c +11 -4
  196. data/vendor/libgit2/src/fileops.c +85 -61
  197. data/vendor/libgit2/src/fileops.h +4 -0
  198. data/vendor/libgit2/src/global.c +10 -2
  199. data/vendor/libgit2/src/global.h +0 -8
  200. data/vendor/libgit2/src/hash/hash_generic.h +3 -3
  201. data/vendor/libgit2/src/hash/hash_win32.h +4 -4
  202. data/vendor/libgit2/src/hashsig.c +0 -1
  203. data/vendor/libgit2/src/ignore.c +68 -28
  204. data/vendor/libgit2/src/ignore.h +10 -1
  205. data/vendor/libgit2/src/index.c +666 -84
  206. data/vendor/libgit2/src/index.h +6 -0
  207. data/vendor/libgit2/src/indexer.c +10 -28
  208. data/vendor/libgit2/src/iterator.c +427 -283
  209. data/vendor/libgit2/src/iterator.h +58 -4
  210. data/vendor/libgit2/src/merge.c +1892 -32
  211. data/vendor/libgit2/src/merge.h +132 -5
  212. data/vendor/libgit2/src/merge_file.c +174 -0
  213. data/vendor/libgit2/src/merge_file.h +71 -0
  214. data/vendor/libgit2/src/mwindow.c +1 -1
  215. data/vendor/libgit2/src/notes.c +45 -48
  216. data/vendor/libgit2/src/object.c +89 -127
  217. data/vendor/libgit2/src/object.h +0 -1
  218. data/vendor/libgit2/src/object_api.c +129 -0
  219. data/vendor/libgit2/src/odb.c +156 -59
  220. data/vendor/libgit2/src/odb.h +5 -2
  221. data/vendor/libgit2/src/odb_loose.c +31 -17
  222. data/vendor/libgit2/src/odb_pack.c +39 -43
  223. data/vendor/libgit2/src/oid.c +62 -27
  224. data/vendor/libgit2/src/oid.h +33 -0
  225. data/vendor/libgit2/src/oidmap.h +4 -6
  226. data/vendor/libgit2/src/pack-objects.c +54 -22
  227. data/vendor/libgit2/src/pack.c +98 -56
  228. data/vendor/libgit2/src/pack.h +3 -1
  229. data/vendor/libgit2/src/pathspec.c +26 -1
  230. data/vendor/libgit2/src/pathspec.h +14 -0
  231. data/vendor/libgit2/src/pool.c +5 -0
  232. data/vendor/libgit2/src/posix.c +2 -2
  233. data/vendor/libgit2/src/posix.h +3 -0
  234. data/vendor/libgit2/src/push.c +13 -10
  235. data/vendor/libgit2/src/refdb.c +82 -62
  236. data/vendor/libgit2/src/refdb.h +16 -16
  237. data/vendor/libgit2/src/refdb_fs.c +386 -133
  238. data/vendor/libgit2/src/reflog.c +3 -1
  239. data/vendor/libgit2/src/refs.c +247 -221
  240. data/vendor/libgit2/src/refs.h +2 -1
  241. data/vendor/libgit2/src/refspec.c +18 -1
  242. data/vendor/libgit2/src/refspec.h +3 -1
  243. data/vendor/libgit2/src/remote.c +434 -253
  244. data/vendor/libgit2/src/remote.h +5 -3
  245. data/vendor/libgit2/src/repository.c +197 -111
  246. data/vendor/libgit2/src/repository.h +26 -5
  247. data/vendor/libgit2/src/reset.c +1 -1
  248. data/vendor/libgit2/src/revparse.c +84 -79
  249. data/vendor/libgit2/src/revwalk.c +1 -1
  250. data/vendor/libgit2/src/signature.c +22 -10
  251. data/vendor/libgit2/src/stash.c +5 -2
  252. data/vendor/libgit2/src/status.c +311 -107
  253. data/vendor/libgit2/src/status.h +23 -0
  254. data/vendor/libgit2/src/submodule.c +21 -13
  255. data/vendor/libgit2/src/tag.c +42 -31
  256. data/vendor/libgit2/src/tag.h +2 -3
  257. data/vendor/libgit2/src/thread-utils.h +105 -3
  258. data/vendor/libgit2/src/trace.c +1 -2
  259. data/vendor/libgit2/src/trace.h +3 -3
  260. data/vendor/libgit2/src/transport.c +18 -6
  261. data/vendor/libgit2/src/transports/cred.c +103 -1
  262. data/vendor/libgit2/src/transports/local.c +19 -9
  263. data/vendor/libgit2/src/transports/smart_protocol.c +32 -12
  264. data/vendor/libgit2/src/transports/ssh.c +519 -0
  265. data/vendor/libgit2/src/transports/winhttp.c +3 -1
  266. data/vendor/libgit2/src/tree.c +26 -28
  267. data/vendor/libgit2/src/tree.h +3 -3
  268. data/vendor/libgit2/src/unix/posix.h +2 -0
  269. data/vendor/libgit2/src/util.c +43 -6
  270. data/vendor/libgit2/src/util.h +40 -12
  271. data/vendor/libgit2/src/vector.c +3 -5
  272. data/vendor/libgit2/src/vector.h +9 -0
  273. data/vendor/libgit2/src/win32/dir.c +1 -1
  274. data/vendor/libgit2/src/win32/error.c +2 -0
  275. data/vendor/libgit2/src/win32/findfile.c +3 -6
  276. data/vendor/libgit2/src/win32/posix_w32.c +85 -59
  277. data/vendor/libgit2/src/win32/pthread.c +16 -8
  278. data/vendor/libgit2/src/win32/pthread.h +7 -4
  279. metadata +407 -306
  280. data/test/coverage/HEAD.json +0 -1
  281. data/vendor/libgit2/include/git2/refdb_backend.h +0 -109
  282. data/vendor/libgit2/src/diff_output.c +0 -1819
  283. data/vendor/libgit2/src/diff_output.h +0 -93
@@ -8,11 +8,13 @@
8
8
  #include "common.h"
9
9
  #include <zlib.h>
10
10
  #include "git2/object.h"
11
+ #include "git2/sys/odb_backend.h"
11
12
  #include "fileops.h"
12
13
  #include "hash.h"
13
14
  #include "odb.h"
14
15
  #include "delta-apply.h"
15
16
  #include "filter.h"
17
+ #include "repository.h"
16
18
 
17
19
  #include "git2/odb_backend.h"
18
20
  #include "git2/oid.h"
@@ -29,10 +31,19 @@ typedef struct
29
31
  {
30
32
  git_odb_backend *backend;
31
33
  int priority;
32
- int is_alternate;
34
+ bool is_alternate;
35
+ ino_t disk_inode;
33
36
  } backend_internal;
34
37
 
35
- size_t git_odb__cache_size = GIT_DEFAULT_CACHE_SIZE;
38
+ static git_cache *odb_cache(git_odb *odb)
39
+ {
40
+ if (odb->rc.owner != NULL) {
41
+ git_repository *owner = odb->rc.owner;
42
+ return &owner->objects;
43
+ }
44
+
45
+ return &odb->own_cache;
46
+ }
36
47
 
37
48
  static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth);
38
49
 
@@ -54,6 +65,7 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj)
54
65
 
55
66
  if (!git_object_typeisloose(obj->type))
56
67
  return -1;
68
+
57
69
  if (!obj->data && obj->len != 0)
58
70
  return -1;
59
71
 
@@ -70,23 +82,24 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj)
70
82
  }
71
83
 
72
84
 
73
- static git_odb_object *new_odb_object(const git_oid *oid, git_rawobj *source)
85
+ static git_odb_object *odb_object__alloc(const git_oid *oid, git_rawobj *source)
74
86
  {
75
- git_odb_object *object = git__malloc(sizeof(git_odb_object));
76
- memset(object, 0x0, sizeof(git_odb_object));
87
+ git_odb_object *object = git__calloc(1, sizeof(git_odb_object));
77
88
 
78
- git_oid_cpy(&object->cached.oid, oid);
79
- memcpy(&object->raw, source, sizeof(git_rawobj));
89
+ if (object != NULL) {
90
+ git_oid_cpy(&object->cached.oid, oid);
91
+ object->cached.type = source->type;
92
+ object->cached.size = source->len;
93
+ object->buffer = source->data;
94
+ }
80
95
 
81
96
  return object;
82
97
  }
83
98
 
84
- static void free_odb_object(void *o)
99
+ void git_odb_object__free(void *object)
85
100
  {
86
- git_odb_object *object = (git_odb_object *)o;
87
-
88
101
  if (object != NULL) {
89
- git__free(object->raw.data);
102
+ git__free(((git_odb_object *)object)->buffer);
90
103
  git__free(object);
91
104
  }
92
105
  }
@@ -98,17 +111,17 @@ const git_oid *git_odb_object_id(git_odb_object *object)
98
111
 
99
112
  const void *git_odb_object_data(git_odb_object *object)
100
113
  {
101
- return object->raw.data;
114
+ return object->buffer;
102
115
  }
103
116
 
104
117
  size_t git_odb_object_size(git_odb_object *object)
105
118
  {
106
- return object->raw.len;
119
+ return object->cached.size;
107
120
  }
108
121
 
109
122
  git_otype git_odb_object_type(git_odb_object *object)
110
123
  {
111
- return object->raw.type;
124
+ return object->cached.type;
112
125
  }
113
126
 
114
127
  void git_odb_object_free(git_odb_object *object)
@@ -116,7 +129,7 @@ void git_odb_object_free(git_odb_object *object)
116
129
  if (object == NULL)
117
130
  return;
118
131
 
119
- git_cached_obj_decref((git_cached_obj *)object, &free_odb_object);
132
+ git_cached_obj_decref(object);
120
133
  }
121
134
 
122
135
  int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type)
@@ -353,9 +366,8 @@ int git_odb_new(git_odb **out)
353
366
  git_odb *db = git__calloc(1, sizeof(*db));
354
367
  GITERR_CHECK_ALLOC(db);
355
368
 
356
- if (git_cache_init(&db->cache, git_odb__cache_size, &free_odb_object) < 0 ||
357
- git_vector_init(&db->backends, 4, backend_sort_cmp) < 0)
358
- {
369
+ if (git_cache_init(&db->own_cache) < 0 ||
370
+ git_vector_init(&db->backends, 4, backend_sort_cmp) < 0) {
359
371
  git__free(db);
360
372
  return -1;
361
373
  }
@@ -365,7 +377,9 @@ int git_odb_new(git_odb **out)
365
377
  return 0;
366
378
  }
367
379
 
368
- static int add_backend_internal(git_odb *odb, git_odb_backend *backend, int priority, int is_alternate)
380
+ static int add_backend_internal(
381
+ git_odb *odb, git_odb_backend *backend,
382
+ int priority, bool is_alternate, ino_t disk_inode)
369
383
  {
370
384
  backend_internal *internal;
371
385
 
@@ -382,6 +396,7 @@ static int add_backend_internal(git_odb *odb, git_odb_backend *backend, int prio
382
396
  internal->backend = backend;
383
397
  internal->priority = priority;
384
398
  internal->is_alternate = is_alternate;
399
+ internal->disk_inode = disk_inode;
385
400
 
386
401
  if (git_vector_insert(&odb->backends, internal) < 0) {
387
402
  git__free(internal);
@@ -395,26 +410,86 @@ static int add_backend_internal(git_odb *odb, git_odb_backend *backend, int prio
395
410
 
396
411
  int git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority)
397
412
  {
398
- return add_backend_internal(odb, backend, priority, 0);
413
+ return add_backend_internal(odb, backend, priority, false, 0);
399
414
  }
400
415
 
401
416
  int git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority)
402
417
  {
403
- return add_backend_internal(odb, backend, priority, 1);
418
+ return add_backend_internal(odb, backend, priority, true, 0);
419
+ }
420
+
421
+ size_t git_odb_num_backends(git_odb *odb)
422
+ {
423
+ assert(odb);
424
+ return odb->backends.length;
425
+ }
426
+
427
+ static int git_odb__error_unsupported_in_backend(const char *action)
428
+ {
429
+ giterr_set(GITERR_ODB,
430
+ "Cannot %s - unsupported in the loaded odb backends", action);
431
+ return -1;
432
+ }
433
+
434
+
435
+ int git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos)
436
+ {
437
+ backend_internal *internal;
438
+
439
+ assert(odb && odb);
440
+ internal = git_vector_get(&odb->backends, pos);
441
+
442
+ if (internal && internal->backend) {
443
+ *out = internal->backend;
444
+ return 0;
445
+ }
446
+
447
+ giterr_set(GITERR_ODB, "No ODB backend loaded at index " PRIuZ, pos);
448
+ return GIT_ENOTFOUND;
404
449
  }
405
450
 
406
- static int add_default_backends(git_odb *db, const char *objects_dir, int as_alternates, int alternate_depth)
451
+ static int add_default_backends(
452
+ git_odb *db, const char *objects_dir,
453
+ bool as_alternates, int alternate_depth)
407
454
  {
455
+ size_t i;
456
+ struct stat st;
457
+ ino_t inode;
408
458
  git_odb_backend *loose, *packed;
409
459
 
460
+ /* TODO: inodes are not really relevant on Win32, so we need to find
461
+ * a cross-platform workaround for this */
462
+ #ifdef GIT_WIN32
463
+ GIT_UNUSED(i);
464
+ GIT_UNUSED(st);
465
+
466
+ inode = 0;
467
+ #else
468
+ if (p_stat(objects_dir, &st) < 0) {
469
+ if (as_alternates)
470
+ return 0;
471
+
472
+ giterr_set(GITERR_ODB, "Failed to load object database in '%s'", objects_dir);
473
+ return -1;
474
+ }
475
+
476
+ inode = st.st_ino;
477
+
478
+ for (i = 0; i < db->backends.length; ++i) {
479
+ backend_internal *backend = git_vector_get(&db->backends, i);
480
+ if (backend->disk_inode == inode)
481
+ return 0;
482
+ }
483
+ #endif
484
+
410
485
  /* add the loose object backend */
411
486
  if (git_odb_backend_loose(&loose, objects_dir, -1, 0) < 0 ||
412
- add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates) < 0)
487
+ add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates, inode) < 0)
413
488
  return -1;
414
489
 
415
490
  /* add the packed file backend */
416
491
  if (git_odb_backend_pack(&packed, objects_dir) < 0 ||
417
- add_backend_internal(db, packed, GIT_PACKED_PRIORITY, as_alternates) < 0)
492
+ add_backend_internal(db, packed, GIT_PACKED_PRIORITY, as_alternates, inode) < 0)
418
493
  return -1;
419
494
 
420
495
  return load_alternates(db, objects_dir, alternate_depth);
@@ -429,9 +504,8 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
429
504
  int result = 0;
430
505
 
431
506
  /* Git reports an error, we just ignore anything deeper */
432
- if (alternate_depth > GIT_ALTERNATES_MAX_DEPTH) {
507
+ if (alternate_depth > GIT_ALTERNATES_MAX_DEPTH)
433
508
  return 0;
434
- }
435
509
 
436
510
  if (git_buf_joinpath(&alternates_path, objects_dir, GIT_ALTERNATES_FILE) < 0)
437
511
  return -1;
@@ -464,7 +538,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
464
538
  alternate = git_buf_cstr(&alternates_path);
465
539
  }
466
540
 
467
- if ((result = add_default_backends(odb, alternate, 1, alternate_depth + 1)) < 0)
541
+ if ((result = add_default_backends(odb, alternate, true, alternate_depth + 1)) < 0)
468
542
  break;
469
543
  }
470
544
 
@@ -476,7 +550,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
476
550
 
477
551
  int git_odb_add_disk_alternate(git_odb *odb, const char *path)
478
552
  {
479
- return add_default_backends(odb, path, 1, 0);
553
+ return add_default_backends(odb, path, true, 0);
480
554
  }
481
555
 
482
556
  int git_odb_open(git_odb **out, const char *objects_dir)
@@ -514,7 +588,9 @@ static void odb_free(git_odb *db)
514
588
  }
515
589
 
516
590
  git_vector_free(&db->backends);
517
- git_cache_free(&db->cache);
591
+ git_cache_free(&db->own_cache);
592
+
593
+ git__memzero(db, sizeof(*db));
518
594
  git__free(db);
519
595
  }
520
596
 
@@ -535,7 +611,7 @@ int git_odb_exists(git_odb *db, const git_oid *id)
535
611
 
536
612
  assert(db && id);
537
613
 
538
- if ((object = git_cache_get(&db->cache, id)) != NULL) {
614
+ if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
539
615
  git_odb_object_free(object);
540
616
  return (int)true;
541
617
  }
@@ -585,9 +661,9 @@ int git_odb__read_header_or_object(
585
661
 
586
662
  assert(db && id && out && len_p && type_p);
587
663
 
588
- if ((object = git_cache_get(&db->cache, id)) != NULL) {
589
- *len_p = object->raw.len;
590
- *type_p = object->raw.type;
664
+ if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
665
+ *len_p = object->cached.size;
666
+ *type_p = object->cached.type;
591
667
  *out = object;
592
668
  return 0;
593
669
  }
@@ -612,8 +688,8 @@ int git_odb__read_header_or_object(
612
688
  if ((error = git_odb_read(&object, db, id)) < 0)
613
689
  return error; /* error already set - pass along */
614
690
 
615
- *len_p = object->raw.len;
616
- *type_p = object->raw.type;
691
+ *len_p = object->cached.size;
692
+ *type_p = object->cached.type;
617
693
  *out = object;
618
694
 
619
695
  return 0;
@@ -621,19 +697,15 @@ int git_odb__read_header_or_object(
621
697
 
622
698
  int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
623
699
  {
624
- size_t i;
700
+ size_t i, reads = 0;
625
701
  int error;
626
702
  bool refreshed = false;
627
703
  git_rawobj raw;
704
+ git_odb_object *object;
628
705
 
629
706
  assert(out && db && id);
630
707
 
631
- if (db->backends.length == 0) {
632
- giterr_set(GITERR_ODB, "Failed to lookup object: no backends loaded");
633
- return GIT_ENOTFOUND;
634
- }
635
-
636
- *out = git_cache_get(&db->cache, id);
708
+ *out = git_cache_get_raw(odb_cache(db), id);
637
709
  if (*out != NULL)
638
710
  return 0;
639
711
 
@@ -644,8 +716,10 @@ attempt_lookup:
644
716
  backend_internal *internal = git_vector_get(&db->backends, i);
645
717
  git_odb_backend *b = internal->backend;
646
718
 
647
- if (b->read != NULL)
719
+ if (b->read != NULL) {
720
+ ++reads;
648
721
  error = b->read(&raw.data, &raw.len, &raw.type, b, id);
722
+ }
649
723
  }
650
724
 
651
725
  if (error == GIT_ENOTFOUND && !refreshed) {
@@ -656,10 +730,16 @@ attempt_lookup:
656
730
  goto attempt_lookup;
657
731
  }
658
732
 
659
- if (error && error != GIT_PASSTHROUGH)
733
+ if (error && error != GIT_PASSTHROUGH) {
734
+ if (!reads)
735
+ return git_odb__error_notfound("no match for id", id);
660
736
  return error;
737
+ }
738
+
739
+ if ((object = odb_object__alloc(id, &raw)) == NULL)
740
+ return -1;
661
741
 
662
- *out = git_cache_try_store(&db->cache, new_odb_object(id, &raw));
742
+ *out = git_cache_store_raw(odb_cache(db), object);
663
743
  return 0;
664
744
  }
665
745
 
@@ -672,6 +752,7 @@ int git_odb_read_prefix(
672
752
  git_rawobj raw;
673
753
  void *data = NULL;
674
754
  bool found = false, refreshed = false;
755
+ git_odb_object *object;
675
756
 
676
757
  assert(out && db);
677
758
 
@@ -682,7 +763,7 @@ int git_odb_read_prefix(
682
763
  len = GIT_OID_HEXSZ;
683
764
 
684
765
  if (len == GIT_OID_HEXSZ) {
685
- *out = git_cache_get(&db->cache, short_id);
766
+ *out = git_cache_get_raw(odb_cache(db), short_id);
686
767
  if (*out != NULL)
687
768
  return 0;
688
769
  }
@@ -704,7 +785,7 @@ attempt_lookup:
704
785
  git__free(data);
705
786
  data = raw.data;
706
787
 
707
- if (found && git_oid_cmp(&full_oid, &found_full_oid))
788
+ if (found && git_oid__cmp(&full_oid, &found_full_oid))
708
789
  return git_odb__error_ambiguous("multiple matches for prefix");
709
790
 
710
791
  found_full_oid = full_oid;
@@ -723,7 +804,10 @@ attempt_lookup:
723
804
  if (!found)
724
805
  return git_odb__error_notfound("no match for prefix", short_id);
725
806
 
726
- *out = git_cache_try_store(&db->cache, new_odb_object(&found_full_oid, &raw));
807
+ if ((object = odb_object__alloc(&found_full_oid, &raw)) == NULL)
808
+ return -1;
809
+
810
+ *out = git_cache_store_raw(odb_cache(db), object);
727
811
  return 0;
728
812
  }
729
813
 
@@ -770,10 +854,10 @@ int git_odb_write(
770
854
  if (!error || error == GIT_PASSTHROUGH)
771
855
  return 0;
772
856
 
773
- /* if no backends were able to write the object directly, we try a streaming
774
- * write to the backends; just write the whole object into the stream in one
775
- * push */
776
-
857
+ /* if no backends were able to write the object directly, we try a
858
+ * streaming write to the backends; just write the whole object into the
859
+ * stream in one push
860
+ */
777
861
  if ((error = git_odb_open_wstream(&stream, db, len, type)) != 0)
778
862
  return error;
779
863
 
@@ -787,7 +871,7 @@ int git_odb_write(
787
871
  int git_odb_open_wstream(
788
872
  git_odb_stream **stream, git_odb *db, size_t size, git_otype type)
789
873
  {
790
- size_t i;
874
+ size_t i, writes = 0;
791
875
  int error = GIT_ERROR;
792
876
 
793
877
  assert(stream && db);
@@ -800,21 +884,26 @@ int git_odb_open_wstream(
800
884
  if (internal->is_alternate)
801
885
  continue;
802
886
 
803
- if (b->writestream != NULL)
887
+ if (b->writestream != NULL) {
888
+ ++writes;
804
889
  error = b->writestream(stream, b, size, type);
805
- else if (b->write != NULL)
890
+ } else if (b->write != NULL) {
891
+ ++writes;
806
892
  error = init_fake_wstream(stream, b, size, type);
893
+ }
807
894
  }
808
895
 
809
896
  if (error == GIT_PASSTHROUGH)
810
897
  error = 0;
898
+ if (error < 0 && !writes)
899
+ error = git_odb__error_unsupported_in_backend("write object");
811
900
 
812
901
  return error;
813
902
  }
814
903
 
815
904
  int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oid)
816
905
  {
817
- size_t i;
906
+ size_t i, reads = 0;
818
907
  int error = GIT_ERROR;
819
908
 
820
909
  assert(stream && db);
@@ -823,19 +912,23 @@ int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oi
823
912
  backend_internal *internal = git_vector_get(&db->backends, i);
824
913
  git_odb_backend *b = internal->backend;
825
914
 
826
- if (b->readstream != NULL)
915
+ if (b->readstream != NULL) {
916
+ ++reads;
827
917
  error = b->readstream(stream, b, oid);
918
+ }
828
919
  }
829
920
 
830
921
  if (error == GIT_PASSTHROUGH)
831
922
  error = 0;
923
+ if (error < 0 && !reads)
924
+ error = git_odb__error_unsupported_in_backend("read object streamed");
832
925
 
833
926
  return error;
834
927
  }
835
928
 
836
929
  int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_transfer_progress_callback progress_cb, void *progress_payload)
837
930
  {
838
- size_t i;
931
+ size_t i, writes = 0;
839
932
  int error = GIT_ERROR;
840
933
 
841
934
  assert(out && db);
@@ -848,12 +941,16 @@ int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_transfer
848
941
  if (internal->is_alternate)
849
942
  continue;
850
943
 
851
- if (b->writepack != NULL)
944
+ if (b->writepack != NULL) {
945
+ ++writes;
852
946
  error = b->writepack(out, b, progress_cb, progress_payload);
947
+ }
853
948
  }
854
949
 
855
950
  if (error == GIT_PASSTHROUGH)
856
951
  error = 0;
952
+ if (error < 0 && !writes)
953
+ error = git_odb__error_unsupported_in_backend("write pack");
857
954
 
858
955
  return error;
859
956
  }