rugged 0.17.0.b6 → 0.17.0.b7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. data/README.md +3 -3
  2. data/Rakefile +3 -1
  3. data/ext/rugged/rugged.c +30 -0
  4. data/ext/rugged/rugged.h +9 -0
  5. data/ext/rugged/rugged_branch.c +306 -0
  6. data/ext/rugged/rugged_config.c +16 -13
  7. data/ext/rugged/rugged_index.c +25 -0
  8. data/ext/rugged/rugged_object.c +6 -2
  9. data/ext/rugged/rugged_reference.c +11 -18
  10. data/ext/rugged/rugged_revwalk.c +1 -1
  11. data/lib/rugged.rb +1 -0
  12. data/lib/rugged/branch.rb +28 -0
  13. data/lib/rugged/commit.rb +5 -5
  14. data/lib/rugged/repository.rb +32 -7
  15. data/lib/rugged/tag.rb +5 -1
  16. data/lib/rugged/version.rb +1 -1
  17. data/test/branch_test.rb +227 -0
  18. data/test/config_test.rb +1 -1
  19. data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
  20. data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
  21. data/test/index_test.rb +31 -0
  22. data/test/index_test.rb~ +218 -0
  23. data/test/lib_test.rb +22 -0
  24. data/test/reference_test.rb +5 -3
  25. data/vendor/libgit2/Makefile.embed +1 -1
  26. data/vendor/libgit2/include/git2.h +1 -0
  27. data/vendor/libgit2/include/git2/branch.h +17 -13
  28. data/vendor/libgit2/include/git2/checkout.h +83 -22
  29. data/vendor/libgit2/include/git2/clone.h +6 -3
  30. data/vendor/libgit2/include/git2/common.h +1 -8
  31. data/vendor/libgit2/include/git2/config.h +185 -26
  32. data/vendor/libgit2/include/git2/diff.h +229 -17
  33. data/vendor/libgit2/include/git2/errors.h +39 -1
  34. data/vendor/libgit2/include/git2/ignore.h +6 -3
  35. data/vendor/libgit2/include/git2/indexer.h +1 -0
  36. data/vendor/libgit2/include/git2/merge.h +1 -1
  37. data/vendor/libgit2/include/git2/object.h +7 -4
  38. data/vendor/libgit2/include/git2/odb.h +4 -2
  39. data/vendor/libgit2/include/git2/odb_backend.h +6 -0
  40. data/vendor/libgit2/include/git2/oid.h +2 -0
  41. data/vendor/libgit2/include/git2/pack.h +89 -0
  42. data/vendor/libgit2/include/git2/refs.h +88 -0
  43. data/vendor/libgit2/include/git2/refspec.h +0 -8
  44. data/vendor/libgit2/include/git2/remote.h +34 -1
  45. data/vendor/libgit2/include/git2/repository.h +238 -6
  46. data/vendor/libgit2/include/git2/reset.h +4 -1
  47. data/vendor/libgit2/include/git2/revwalk.h +1 -1
  48. data/vendor/libgit2/include/git2/status.h +19 -14
  49. data/vendor/libgit2/include/git2/strarray.h +54 -0
  50. data/vendor/libgit2/include/git2/submodule.h +451 -45
  51. data/vendor/libgit2/include/git2/tag.h +16 -0
  52. data/vendor/libgit2/include/git2/tree.h +2 -2
  53. data/vendor/libgit2/include/git2/types.h +4 -0
  54. data/vendor/libgit2/src/amiga/map.c +4 -7
  55. data/vendor/libgit2/src/attr.c +21 -13
  56. data/vendor/libgit2/src/attr.h +3 -1
  57. data/vendor/libgit2/src/attr_file.c +14 -14
  58. data/vendor/libgit2/src/attr_file.h +6 -5
  59. data/vendor/libgit2/src/blob.c +22 -12
  60. data/vendor/libgit2/src/branch.c +62 -66
  61. data/vendor/libgit2/src/buffer.c +63 -14
  62. data/vendor/libgit2/src/buffer.h +4 -0
  63. data/vendor/libgit2/src/cache.c +5 -4
  64. data/vendor/libgit2/src/checkout.c +381 -159
  65. data/vendor/libgit2/src/clone.c +221 -94
  66. data/vendor/libgit2/src/common.h +13 -3
  67. data/vendor/libgit2/src/compress.c +53 -0
  68. data/vendor/libgit2/src/compress.h +16 -0
  69. data/vendor/libgit2/src/config.c +380 -175
  70. data/vendor/libgit2/src/config.h +2 -5
  71. data/vendor/libgit2/src/config_file.c +63 -46
  72. data/vendor/libgit2/src/config_file.h +16 -4
  73. data/vendor/libgit2/src/crlf.c +4 -3
  74. data/vendor/libgit2/src/delta.c +491 -0
  75. data/vendor/libgit2/src/delta.h +112 -0
  76. data/vendor/libgit2/src/diff.c +310 -67
  77. data/vendor/libgit2/src/diff.h +10 -1
  78. data/vendor/libgit2/src/diff_output.c +1030 -337
  79. data/vendor/libgit2/src/diff_output.h +86 -0
  80. data/vendor/libgit2/src/errors.c +10 -1
  81. data/vendor/libgit2/src/fetch.c +108 -24
  82. data/vendor/libgit2/src/filebuf.c +8 -2
  83. data/vendor/libgit2/src/fileops.c +342 -177
  84. data/vendor/libgit2/src/fileops.h +84 -7
  85. data/vendor/libgit2/src/filter.c +0 -35
  86. data/vendor/libgit2/src/filter.h +0 -12
  87. data/vendor/libgit2/src/{compat/fnmatch.c → fnmatch.c} +16 -4
  88. data/vendor/libgit2/src/{compat/fnmatch.h → fnmatch.h} +4 -3
  89. data/vendor/libgit2/src/global.c +4 -0
  90. data/vendor/libgit2/src/ignore.c +122 -23
  91. data/vendor/libgit2/src/ignore.h +1 -0
  92. data/vendor/libgit2/src/index.c +56 -10
  93. data/vendor/libgit2/src/index.h +2 -0
  94. data/vendor/libgit2/src/indexer.c +8 -9
  95. data/vendor/libgit2/src/iterator.c +244 -31
  96. data/vendor/libgit2/src/iterator.h +30 -1
  97. data/vendor/libgit2/src/message.c +1 -1
  98. data/vendor/libgit2/src/netops.c +44 -4
  99. data/vendor/libgit2/src/object.c +80 -69
  100. data/vendor/libgit2/src/object.h +39 -0
  101. data/vendor/libgit2/src/odb.c +79 -15
  102. data/vendor/libgit2/src/odb.h +20 -5
  103. data/vendor/libgit2/src/odb_pack.c +65 -33
  104. data/vendor/libgit2/src/oid.c +0 -3
  105. data/vendor/libgit2/src/pack-objects.c +1315 -0
  106. data/vendor/libgit2/src/pack-objects.h +87 -0
  107. data/vendor/libgit2/src/pack.c +36 -12
  108. data/vendor/libgit2/src/pack.h +1 -0
  109. data/vendor/libgit2/src/path.c +42 -9
  110. data/vendor/libgit2/src/path.h +14 -0
  111. data/vendor/libgit2/src/pkt.c +52 -2
  112. data/vendor/libgit2/src/pkt.h +10 -0
  113. data/vendor/libgit2/src/pool.h +11 -0
  114. data/vendor/libgit2/src/posix.h +8 -0
  115. data/vendor/libgit2/src/protocol.c +24 -2
  116. data/vendor/libgit2/src/protocol.h +4 -0
  117. data/vendor/libgit2/src/reflog.c +1 -1
  118. data/vendor/libgit2/src/refs.c +292 -124
  119. data/vendor/libgit2/src/refs.h +4 -2
  120. data/vendor/libgit2/src/refspec.c +117 -19
  121. data/vendor/libgit2/src/refspec.h +19 -0
  122. data/vendor/libgit2/src/remote.c +152 -48
  123. data/vendor/libgit2/src/remote.h +4 -1
  124. data/vendor/libgit2/src/repo_template.h +58 -0
  125. data/vendor/libgit2/src/repository.c +594 -179
  126. data/vendor/libgit2/src/repository.h +23 -22
  127. data/vendor/libgit2/src/reset.c +71 -29
  128. data/vendor/libgit2/src/revparse.c +26 -17
  129. data/vendor/libgit2/src/revwalk.c +36 -19
  130. data/vendor/libgit2/src/sha1.h +7 -0
  131. data/vendor/libgit2/src/{sha1.c → sha1/sha1.c} +0 -0
  132. data/vendor/libgit2/src/signature.c +12 -10
  133. data/vendor/libgit2/src/status.c +52 -6
  134. data/vendor/libgit2/src/submodule.c +1363 -255
  135. data/vendor/libgit2/src/submodule.h +102 -0
  136. data/vendor/libgit2/src/tag.c +42 -26
  137. data/vendor/libgit2/src/thread-utils.h +7 -7
  138. data/vendor/libgit2/src/transport.h +15 -1
  139. data/vendor/libgit2/src/transports/git.c +1 -1
  140. data/vendor/libgit2/src/transports/http.c +197 -36
  141. data/vendor/libgit2/src/tree.c +3 -3
  142. data/vendor/libgit2/src/unix/map.c +2 -0
  143. data/vendor/libgit2/src/unix/posix.h +1 -8
  144. data/vendor/libgit2/src/util.c +6 -1
  145. data/vendor/libgit2/src/util.h +7 -0
  146. data/vendor/libgit2/src/vector.c +16 -0
  147. data/vendor/libgit2/src/vector.h +1 -0
  148. data/vendor/libgit2/src/win32/dir.c +8 -21
  149. data/vendor/libgit2/src/win32/findfile.c +149 -0
  150. data/vendor/libgit2/src/win32/findfile.h +23 -0
  151. data/vendor/libgit2/src/win32/posix.h +3 -7
  152. data/vendor/libgit2/src/win32/posix_w32.c +44 -102
  153. data/vendor/libgit2/src/win32/pthread.c +68 -0
  154. data/vendor/libgit2/src/win32/pthread.h +7 -0
  155. data/vendor/libgit2/src/win32/utf-conv.c +60 -71
  156. data/vendor/libgit2/src/win32/utf-conv.h +4 -3
  157. metadata +70 -71
  158. data/vendor/libgit2/include/git2/windows.h +0 -59
@@ -9,6 +9,12 @@
9
9
 
10
10
  #include "common.h"
11
11
  #include "git2/index.h"
12
+ #include "vector.h"
13
+ #include "buffer.h"
14
+
15
+ #define ITERATOR_PREFIXCMP(ITER, STR, PREFIX) (((ITER).ignore_case) ? \
16
+ git__prefixcmp_icase((STR), (PREFIX)) : \
17
+ git__prefixcmp((STR), (PREFIX)))
12
18
 
13
19
  typedef struct git_iterator git_iterator;
14
20
 
@@ -16,7 +22,8 @@ typedef enum {
16
22
  GIT_ITERATOR_EMPTY = 0,
17
23
  GIT_ITERATOR_TREE = 1,
18
24
  GIT_ITERATOR_INDEX = 2,
19
- GIT_ITERATOR_WORKDIR = 3
25
+ GIT_ITERATOR_WORKDIR = 3,
26
+ GIT_ITERATOR_SPOOLANDSORT = 4
20
27
  } git_iterator_type_t;
21
28
 
22
29
  struct git_iterator {
@@ -29,6 +36,7 @@ struct git_iterator {
29
36
  int (*seek)(git_iterator *, const char *prefix);
30
37
  int (*reset)(git_iterator *);
31
38
  void (*free)(git_iterator *);
39
+ unsigned int ignore_case:1;
32
40
  };
33
41
 
34
42
  extern int git_iterator_for_nothing(git_iterator **iter);
@@ -63,6 +71,17 @@ GIT_INLINE(int) git_iterator_for_workdir(
63
71
  return git_iterator_for_workdir_range(iter, repo, NULL, NULL);
64
72
  }
65
73
 
74
+ extern int git_iterator_spoolandsort_range(
75
+ git_iterator **iter, git_iterator *towrap,
76
+ git_vector_cmp comparer, bool ignore_case,
77
+ const char *start, const char *end);
78
+
79
+ GIT_INLINE(int) git_iterator_spoolandsort(
80
+ git_iterator **iter, git_iterator *towrap,
81
+ git_vector_cmp comparer, bool ignore_case)
82
+ {
83
+ return git_iterator_spoolandsort_range(iter, towrap, comparer, ignore_case, NULL, NULL);
84
+ }
66
85
 
67
86
  /* Entry is not guaranteed to be fully populated. For a tree iterator,
68
87
  * we will only populate the mode, oid and path, for example. For a workdir
@@ -123,6 +142,9 @@ GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter)
123
142
  extern int git_iterator_current_tree_entry(
124
143
  git_iterator *iter, const git_tree_entry **tree_entry);
125
144
 
145
+ extern int git_iterator_current_parent_tree(
146
+ git_iterator *iter, const char *parent_path, const git_tree **tree_ptr);
147
+
126
148
  extern int git_iterator_current_is_ignored(git_iterator *iter);
127
149
 
128
150
  /**
@@ -148,4 +170,11 @@ extern int git_iterator_advance_into_directory(
148
170
  extern int git_iterator_cmp(
149
171
  git_iterator *iter, const char *path_prefix);
150
172
 
173
+ /**
174
+ * Get the full path of the current item from a workdir iterator.
175
+ * This will return NULL for a non-workdir iterator.
176
+ */
177
+ extern int git_iterator_current_workdir_path(
178
+ git_iterator *iter, git_buf **path);
179
+
151
180
  #endif
@@ -82,5 +82,5 @@ int git_message_prettify(char *message_out, size_t buffer_size, const char *mess
82
82
 
83
83
  done:
84
84
  git_buf_free(&buf);
85
- return out_size;
85
+ return (int)out_size;
86
86
  }
@@ -55,8 +55,44 @@ static void net_set_error(const char *str)
55
55
  static int ssl_set_error(gitno_ssl *ssl, int error)
56
56
  {
57
57
  int err;
58
+ unsigned long e;
59
+
58
60
  err = SSL_get_error(ssl->ssl, error);
59
- giterr_set(GITERR_NET, "SSL error: %s", ERR_error_string(err, NULL));
61
+
62
+ assert(err != SSL_ERROR_WANT_READ);
63
+ assert(err != SSL_ERROR_WANT_WRITE);
64
+
65
+ switch (err) {
66
+ case SSL_ERROR_WANT_CONNECT:
67
+ case SSL_ERROR_WANT_ACCEPT:
68
+ giterr_set(GITERR_NET, "SSL error: connection failure\n");
69
+ break;
70
+ case SSL_ERROR_WANT_X509_LOOKUP:
71
+ giterr_set(GITERR_NET, "SSL error: x509 error\n");
72
+ break;
73
+ case SSL_ERROR_SYSCALL:
74
+ e = ERR_get_error();
75
+ if (e > 0) {
76
+ giterr_set(GITERR_NET, "SSL error: %s",
77
+ ERR_error_string(e, NULL));
78
+ break;
79
+ } else if (error < 0) {
80
+ giterr_set(GITERR_OS, "SSL error: syscall failure");
81
+ break;
82
+ }
83
+ giterr_set(GITERR_NET, "SSL error: received early EOF");
84
+ break;
85
+ case SSL_ERROR_SSL:
86
+ e = ERR_get_error();
87
+ giterr_set(GITERR_NET, "SSL error: %s",
88
+ ERR_error_string(e, NULL));
89
+ break;
90
+ case SSL_ERROR_NONE:
91
+ case SSL_ERROR_ZERO_RETURN:
92
+ default:
93
+ giterr_set(GITERR_NET, "SSL error: unknown error");
94
+ break;
95
+ }
60
96
  return -1;
61
97
  }
62
98
  #endif
@@ -238,6 +274,10 @@ static int verify_server_cert(git_transport *t, const char *host)
238
274
  void *addr;
239
275
  int i = -1,j;
240
276
 
277
+ if (SSL_get_verify_result(t->ssl.ssl) != X509_V_OK) {
278
+ giterr_set(GITERR_SSL, "The SSL certificate is invalid");
279
+ return -1;
280
+ }
241
281
 
242
282
  /* Try to parse the host as an IP address to see if it is */
243
283
  if (inet_pton(AF_INET, host, &addr4)) {
@@ -286,7 +326,7 @@ static int verify_server_cert(git_transport *t, const char *host)
286
326
  GENERAL_NAMES_free(alts);
287
327
 
288
328
  if (matched == 0)
289
- goto on_error;
329
+ goto cert_fail;
290
330
 
291
331
  if (matched == 1)
292
332
  return 0;
@@ -354,7 +394,7 @@ static int ssl_setup(git_transport *t, const char *host)
354
394
  return ssl_set_error(&t->ssl, 0);
355
395
 
356
396
  SSL_CTX_set_mode(t->ssl.ctx, SSL_MODE_AUTO_RETRY);
357
- SSL_CTX_set_verify(t->ssl.ctx, SSL_VERIFY_PEER, NULL);
397
+ SSL_CTX_set_verify(t->ssl.ctx, SSL_VERIFY_NONE, NULL);
358
398
  if (!SSL_CTX_set_default_verify_paths(t->ssl.ctx))
359
399
  return ssl_set_error(&t->ssl, 0);
360
400
 
@@ -438,7 +478,7 @@ static int send_ssl(gitno_ssl *ssl, const char *msg, size_t len)
438
478
 
439
479
  while (off < len) {
440
480
  ret = SSL_write(ssl->ssl, msg + off, len - off);
441
- if (ret <= 0)
481
+ if (ret <= 0 && ret != SSL_ERROR_WANT_WRITE)
442
482
  return ssl_set_error(ssl, ret);
443
483
 
444
484
  off += ret;
@@ -77,6 +77,58 @@ static int create_object(git_object **object_out, git_otype type)
77
77
  return 0;
78
78
  }
79
79
 
80
+ int git_object__from_odb_object(
81
+ git_object **object_out,
82
+ git_repository *repo,
83
+ git_odb_object *odb_obj,
84
+ git_otype type)
85
+ {
86
+ int error;
87
+ git_object *object = NULL;
88
+
89
+ if (type != GIT_OBJ_ANY && type != odb_obj->raw.type) {
90
+ giterr_set(GITERR_ODB, "The requested type does not match the type in the ODB");
91
+ return GIT_ENOTFOUND;
92
+ }
93
+
94
+ type = odb_obj->raw.type;
95
+
96
+ if ((error = create_object(&object, type)) < 0)
97
+ return error;
98
+
99
+ /* Initialize parent object */
100
+ git_oid_cpy(&object->cached.oid, &odb_obj->cached.oid);
101
+ object->repo = repo;
102
+
103
+ switch (type) {
104
+ case GIT_OBJ_COMMIT:
105
+ error = git_commit__parse((git_commit *)object, odb_obj);
106
+ break;
107
+
108
+ case GIT_OBJ_TREE:
109
+ error = git_tree__parse((git_tree *)object, odb_obj);
110
+ break;
111
+
112
+ case GIT_OBJ_TAG:
113
+ error = git_tag__parse((git_tag *)object, odb_obj);
114
+ break;
115
+
116
+ case GIT_OBJ_BLOB:
117
+ error = git_blob__parse((git_blob *)object, odb_obj);
118
+ break;
119
+
120
+ default:
121
+ break;
122
+ }
123
+
124
+ if (error < 0)
125
+ git_object__free(object);
126
+ else
127
+ *object_out = git_cache_try_store(&repo->objects, object);
128
+
129
+ return error;
130
+ }
131
+
80
132
  int git_object_lookup_prefix(
81
133
  git_object **object_out,
82
134
  git_repository *repo,
@@ -148,53 +200,11 @@ int git_object_lookup_prefix(
148
200
  if (error < 0)
149
201
  return error;
150
202
 
151
- if (type != GIT_OBJ_ANY && type != odb_obj->raw.type) {
152
- git_odb_object_free(odb_obj);
153
- giterr_set(GITERR_ODB, "The given type does not match the type on the ODB");
154
- return GIT_ENOTFOUND;
155
- }
156
-
157
- type = odb_obj->raw.type;
158
-
159
- if (create_object(&object, type) < 0) {
160
- git_odb_object_free(odb_obj);
161
- return -1;
162
- }
163
-
164
- /* Initialize parent object */
165
- git_oid_cpy(&object->cached.oid, &odb_obj->cached.oid);
166
- object->repo = repo;
167
-
168
- switch (type) {
169
- case GIT_OBJ_COMMIT:
170
- error = git_commit__parse((git_commit *)object, odb_obj);
171
- break;
172
-
173
- case GIT_OBJ_TREE:
174
- error = git_tree__parse((git_tree *)object, odb_obj);
175
- break;
176
-
177
- case GIT_OBJ_TAG:
178
- error = git_tag__parse((git_tag *)object, odb_obj);
179
- break;
180
-
181
- case GIT_OBJ_BLOB:
182
- error = git_blob__parse((git_blob *)object, odb_obj);
183
- break;
184
-
185
- default:
186
- break;
187
- }
203
+ error = git_object__from_odb_object(object_out, repo, odb_obj, type);
188
204
 
189
205
  git_odb_object_free(odb_obj);
190
206
 
191
- if (error < 0) {
192
- git_object__free(object);
193
- return -1;
194
- }
195
-
196
- *object_out = git_cache_try_store(&repo->objects, object);
197
- return 0;
207
+ return error;
198
208
  }
199
209
 
200
210
  int git_object_lookup(git_object **object_out, git_repository *repo, const git_oid *id, git_otype type) {
@@ -334,6 +344,12 @@ int git_object__resolve_to_type(git_object **obj, git_otype type)
334
344
  return error;
335
345
  }
336
346
 
347
+ static int peel_error(int error, const char* msg)
348
+ {
349
+ giterr_set(GITERR_INVALID, "The given object cannot be peeled - %s", msg);
350
+ return error;
351
+ }
352
+
337
353
  static int dereference_object(git_object **dereferenced, git_object *obj)
338
354
  {
339
355
  git_otype type = git_object_type(obj);
@@ -341,48 +357,36 @@ static int dereference_object(git_object **dereferenced, git_object *obj)
341
357
  switch (type) {
342
358
  case GIT_OBJ_COMMIT:
343
359
  return git_commit_tree((git_tree **)dereferenced, (git_commit*)obj);
344
- break;
345
360
 
346
361
  case GIT_OBJ_TAG:
347
362
  return git_tag_target(dereferenced, (git_tag*)obj);
348
- break;
363
+
364
+ case GIT_OBJ_BLOB:
365
+ return peel_error(GIT_ERROR, "cannot dereference blob");
366
+
367
+ case GIT_OBJ_TREE:
368
+ return peel_error(GIT_ERROR, "cannot dereference tree");
349
369
 
350
370
  default:
351
- return GIT_ENOTFOUND;
352
- break;
371
+ return peel_error(GIT_ENOTFOUND, "unexpected object type encountered");
353
372
  }
354
373
  }
355
374
 
356
- static int peel_error(int error, const char* msg)
357
- {
358
- giterr_set(GITERR_INVALID, "The given object cannot be peeled - %s", msg);
359
- return error;
360
- }
361
-
362
375
  int git_object_peel(
363
- git_object **peeled,
364
- git_object *object,
365
- git_otype target_type)
376
+ git_object **peeled,
377
+ git_object *object,
378
+ git_otype target_type)
366
379
  {
367
380
  git_object *source, *deref = NULL;
368
381
 
369
- assert(object);
382
+ assert(object && peeled);
370
383
 
371
384
  if (git_object_type(object) == target_type)
372
385
  return git_object__dup(peeled, object);
373
386
 
374
- if (target_type == GIT_OBJ_BLOB
375
- || target_type == GIT_OBJ_ANY)
376
- return peel_error(GIT_EAMBIGUOUS, "Ambiguous target type");
377
-
378
- if (git_object_type(object) == GIT_OBJ_BLOB)
379
- return peel_error(GIT_ERROR, "A blob cannot be dereferenced");
380
-
381
387
  source = object;
382
388
 
383
- while (true) {
384
- if (dereference_object(&deref, source) < 0)
385
- goto cleanup;
389
+ while (!dereference_object(&deref, source)) {
386
390
 
387
391
  if (source != object)
388
392
  git_object_free(source);
@@ -392,13 +396,20 @@ int git_object_peel(
392
396
  return 0;
393
397
  }
394
398
 
399
+ if (target_type == GIT_OBJ_ANY &&
400
+ git_object_type(deref) != git_object_type(object))
401
+ {
402
+ *peeled = deref;
403
+ return 0;
404
+ }
405
+
395
406
  source = deref;
396
407
  deref = NULL;
397
408
  }
398
409
 
399
- cleanup:
400
410
  if (source != object)
401
411
  git_object_free(source);
412
+
402
413
  git_object_free(deref);
403
414
  return -1;
404
415
  }
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Copyright (C) 2009-2012 the libgit2 contributors
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+ #ifndef INCLUDE_object_h__
8
+ #define INCLUDE_object_h__
9
+
10
+ /** Base git object for inheritance */
11
+ struct git_object {
12
+ git_cached_obj cached;
13
+ git_repository *repo;
14
+ git_otype type;
15
+ };
16
+
17
+ /* fully free the object; internal method, DO NOT EXPORT */
18
+ void git_object__free(void *object);
19
+
20
+ GIT_INLINE(int) git_object__dup(git_object **dest, git_object *source)
21
+ {
22
+ git_cached_obj_incref(source);
23
+ *dest = source;
24
+ return 0;
25
+ }
26
+
27
+ int git_object__from_odb_object(
28
+ git_object **object_out,
29
+ git_repository *repo,
30
+ git_odb_object *odb_obj,
31
+ git_otype type);
32
+
33
+ int git_object__resolve_to_type(git_object **obj, git_otype type);
34
+
35
+ int git_oid__parse(git_oid *oid, const char **buffer_out, const char *buffer_end, const char *header);
36
+
37
+ void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid);
38
+
39
+ #endif
@@ -12,6 +12,7 @@
12
12
  #include "hash.h"
13
13
  #include "odb.h"
14
14
  #include "delta-apply.h"
15
+ #include "filter.h"
15
16
 
16
17
  #include "git2/odb_backend.h"
17
18
  #include "git2/oid.h"
@@ -106,6 +107,9 @@ git_otype git_odb_object_type(git_odb_object *object)
106
107
 
107
108
  void git_odb_object_free(git_odb_object *object)
108
109
  {
110
+ if (object == NULL)
111
+ return;
112
+
109
113
  git_cached_obj_decref((git_cached_obj *)object, &free_odb_object);
110
114
  }
111
115
 
@@ -114,32 +118,67 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type)
114
118
  int hdr_len;
115
119
  char hdr[64], buffer[2048];
116
120
  git_hash_ctx *ctx;
121
+ ssize_t read_len = 0;
122
+
123
+ if (!git_object_typeisloose(type)) {
124
+ giterr_set(GITERR_INVALID, "Invalid object type for hash");
125
+ return -1;
126
+ }
117
127
 
118
128
  hdr_len = format_object_header(hdr, sizeof(hdr), size, type);
119
129
 
120
130
  ctx = git_hash_new_ctx();
131
+ GITERR_CHECK_ALLOC(ctx);
121
132
 
122
133
  git_hash_update(ctx, hdr, hdr_len);
123
134
 
124
- while (size > 0) {
125
- ssize_t read_len = read(fd, buffer, sizeof(buffer));
126
-
127
- if (read_len < 0) {
128
- git_hash_free_ctx(ctx);
129
- giterr_set(GITERR_OS, "Error reading file");
130
- return -1;
131
- }
132
-
135
+ while (size > 0 && (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) {
133
136
  git_hash_update(ctx, buffer, read_len);
134
137
  size -= read_len;
135
138
  }
136
139
 
140
+ /* If p_read returned an error code, the read obviously failed.
141
+ * If size is not zero, the file was truncated after we originally
142
+ * stat'd it, so we consider this a read failure too */
143
+ if (read_len < 0 || size > 0) {
144
+ git_hash_free_ctx(ctx);
145
+ giterr_set(GITERR_OS, "Error reading file for hashing");
146
+ return -1;
147
+ }
148
+
137
149
  git_hash_final(out, ctx);
138
150
  git_hash_free_ctx(ctx);
139
151
 
140
152
  return 0;
141
153
  }
142
154
 
155
+ int git_odb__hashfd_filtered(
156
+ git_oid *out, git_file fd, size_t size, git_otype type, git_vector *filters)
157
+ {
158
+ int error;
159
+ git_buf raw = GIT_BUF_INIT;
160
+ git_buf filtered = GIT_BUF_INIT;
161
+
162
+ if (!filters || !filters->length)
163
+ return git_odb__hashfd(out, fd, size, type);
164
+
165
+ /* size of data is used in header, so we have to read the whole file
166
+ * into memory to apply filters before beginning to calculate the hash
167
+ */
168
+
169
+ if (!(error = git_futils_readbuffer_fd(&raw, fd, size)))
170
+ error = git_filters_apply(&filtered, &raw, filters);
171
+
172
+ git_buf_free(&raw);
173
+
174
+ if (!error)
175
+ error = git_odb_hash(out, filtered.ptr, filtered.size, type);
176
+
177
+ git_buf_free(&filtered);
178
+
179
+ return error;
180
+ }
181
+
143
182
  int git_odb__hashlink(git_oid *out, const char *path)
144
183
  {
145
184
  struct stat st;
@@ -160,10 +199,11 @@ int git_odb__hashlink(git_oid *out, const char *path)
160
199
  char *link_data;
161
200
  ssize_t read_len;
162
201
 
163
- link_data = git__malloc((size_t)size);
202
+ link_data = git__malloc((size_t)(size + 1));
164
203
  GITERR_CHECK_ALLOC(link_data);
165
204
 
166
- read_len = p_readlink(path, link_data, (size_t)(size + 1));
205
+ read_len = p_readlink(path, link_data, (size_t)size);
206
+ link_data[size] = '\0';
167
207
  if (read_len != (ssize_t)size) {
168
208
  giterr_set(GITERR_OS, "Failed to read symlink data for '%s'", path);
169
209
  return -1;
@@ -171,7 +211,7 @@ int git_odb__hashlink(git_oid *out, const char *path)
171
211
 
172
212
  result = git_odb_hash(out, link_data, (size_t)size, GIT_OBJ_BLOB);
173
213
  git__free(link_data);
174
- } else {
214
+ } else {
175
215
  int fd = git_futils_open_ro(path);
176
216
  if (fd < 0)
177
217
  return -1;
@@ -484,20 +524,37 @@ int git_odb_exists(git_odb *db, const git_oid *id)
484
524
  }
485
525
 
486
526
  int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git_oid *id)
527
+ {
528
+ int error;
529
+ git_odb_object *object;
530
+
531
+ error = git_odb__read_header_or_object(&object, len_p, type_p, db, id);
532
+
533
+ if (object)
534
+ git_odb_object_free(object);
535
+
536
+ return error;
537
+ }
538
+
539
+ int git_odb__read_header_or_object(
540
+ git_odb_object **out, size_t *len_p, git_otype *type_p,
541
+ git_odb *db, const git_oid *id)
487
542
  {
488
543
  unsigned int i;
489
544
  int error = GIT_ENOTFOUND;
490
545
  git_odb_object *object;
491
546
 
492
- assert(db && id);
547
+ assert(db && id && out && len_p && type_p);
493
548
 
494
549
  if ((object = git_cache_get(&db->cache, id)) != NULL) {
495
550
  *len_p = object->raw.len;
496
551
  *type_p = object->raw.type;
497
- git_odb_object_free(object);
552
+ *out = object;
498
553
  return 0;
499
554
  }
500
555
 
556
+ *out = NULL;
557
+
501
558
  for (i = 0; i < db->backends.length && error < 0; ++i) {
502
559
  backend_internal *internal = git_vector_get(&db->backends, i);
503
560
  git_odb_backend *b = internal->backend;
@@ -518,7 +575,8 @@ int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git
518
575
 
519
576
  *len_p = object->raw.len;
520
577
  *type_p = object->raw.type;
521
- git_odb_object_free(object);
578
+ *out = object;
579
+
522
580
  return 0;
523
581
  }
524
582
 
@@ -708,6 +766,12 @@ int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oi
708
766
  return error;
709
767
  }
710
768
 
769
+ void * git_odb_backend_malloc(git_odb_backend *backend, size_t len)
770
+ {
771
+ GIT_UNUSED(backend);
772
+ return git__malloc(len);
773
+ }
774
+
711
775
  int git_odb__error_notfound(const char *message, const git_oid *oid)
712
776
  {
713
777
  if (oid != NULL) {