rugged 0.24.6.1 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/ext/rugged/extconf.rb +9 -2
  4. data/ext/rugged/rugged.c +85 -21
  5. data/ext/rugged/rugged.h +7 -21
  6. data/ext/rugged/rugged_backend.c +3 -20
  7. data/ext/rugged/rugged_blame.c +7 -24
  8. data/ext/rugged/rugged_blob.c +136 -59
  9. data/ext/rugged/rugged_branch.c +3 -20
  10. data/ext/rugged/rugged_branch_collection.c +3 -20
  11. data/ext/rugged/rugged_commit.c +251 -101
  12. data/ext/rugged/rugged_config.c +3 -20
  13. data/ext/rugged/rugged_cred.c +3 -20
  14. data/ext/rugged/rugged_diff.c +3 -20
  15. data/ext/rugged/rugged_diff_delta.c +3 -20
  16. data/ext/rugged/rugged_diff_hunk.c +3 -20
  17. data/ext/rugged/rugged_diff_line.c +3 -20
  18. data/ext/rugged/rugged_index.c +46 -229
  19. data/ext/rugged/rugged_note.c +3 -20
  20. data/ext/rugged/rugged_object.c +3 -20
  21. data/ext/rugged/rugged_patch.c +192 -34
  22. data/ext/rugged/rugged_rebase.c +90 -48
  23. data/ext/rugged/rugged_reference.c +4 -21
  24. data/ext/rugged/rugged_reference_collection.c +3 -20
  25. data/ext/rugged/rugged_remote.c +70 -42
  26. data/ext/rugged/rugged_remote_collection.c +3 -20
  27. data/ext/rugged/rugged_repo.c +50 -59
  28. data/ext/rugged/rugged_revwalk.c +4 -21
  29. data/ext/rugged/rugged_settings.c +3 -20
  30. data/ext/rugged/rugged_signature.c +3 -20
  31. data/ext/rugged/rugged_submodule.c +4 -21
  32. data/ext/rugged/rugged_submodule_collection.c +3 -20
  33. data/ext/rugged/rugged_tag.c +3 -20
  34. data/ext/rugged/rugged_tag_collection.c +3 -20
  35. data/ext/rugged/rugged_tree.c +189 -184
  36. data/lib/rugged/attributes.rb +5 -0
  37. data/lib/rugged/blob.rb +5 -0
  38. data/lib/rugged/branch.rb +6 -1
  39. data/lib/rugged/commit.rb +5 -0
  40. data/lib/rugged/console.rb +5 -0
  41. data/lib/rugged/credentials.rb +5 -0
  42. data/lib/rugged/diff/delta.rb +5 -0
  43. data/lib/rugged/diff/hunk.rb +5 -0
  44. data/lib/rugged/diff/line.rb +5 -0
  45. data/lib/rugged/diff.rb +5 -0
  46. data/lib/rugged/index.rb +120 -0
  47. data/lib/rugged/object.rb +5 -0
  48. data/lib/rugged/patch.rb +5 -0
  49. data/lib/rugged/reference.rb +5 -0
  50. data/lib/rugged/remote.rb +5 -0
  51. data/lib/rugged/repository.rb +9 -4
  52. data/lib/rugged/submodule_collection.rb +5 -0
  53. data/lib/rugged/tag.rb +5 -0
  54. data/lib/rugged/tree.rb +156 -1
  55. data/lib/rugged/version.rb +6 -1
  56. data/lib/rugged/walker.rb +5 -0
  57. data/lib/rugged.rb +5 -0
  58. data/vendor/libgit2/CMakeLists.txt +12 -2
  59. data/vendor/libgit2/include/git2/blob.h +39 -28
  60. data/vendor/libgit2/include/git2/commit.h +76 -0
  61. data/vendor/libgit2/include/git2/common.h +21 -1
  62. data/vendor/libgit2/include/git2/describe.h +5 -2
  63. data/vendor/libgit2/include/git2/diff.h +62 -7
  64. data/vendor/libgit2/include/git2/errors.h +2 -1
  65. data/vendor/libgit2/include/git2/index.h +25 -0
  66. data/vendor/libgit2/include/git2/merge.h +10 -1
  67. data/vendor/libgit2/include/git2/odb.h +47 -1
  68. data/vendor/libgit2/include/git2/pack.h +4 -4
  69. data/vendor/libgit2/include/git2/patch.h +1 -1
  70. data/vendor/libgit2/include/git2/proxy.h +92 -0
  71. data/vendor/libgit2/include/git2/refs.h +11 -0
  72. data/vendor/libgit2/include/git2/remote.h +21 -8
  73. data/vendor/libgit2/include/git2/repository.h +20 -1
  74. data/vendor/libgit2/include/git2/revwalk.h +4 -6
  75. data/vendor/libgit2/include/git2/signature.h +13 -0
  76. data/vendor/libgit2/include/git2/submodule.h +11 -3
  77. data/vendor/libgit2/include/git2/sys/merge.h +177 -0
  78. data/vendor/libgit2/include/git2/sys/odb_backend.h +11 -0
  79. data/vendor/libgit2/include/git2/sys/remote.h +16 -0
  80. data/vendor/libgit2/include/git2/sys/stream.h +2 -1
  81. data/vendor/libgit2/include/git2/sys/time.h +31 -0
  82. data/vendor/libgit2/include/git2/sys/transport.h +3 -1
  83. data/vendor/libgit2/include/git2/tag.h +9 -0
  84. data/vendor/libgit2/include/git2/transaction.h +9 -0
  85. data/vendor/libgit2/include/git2/tree.h +55 -0
  86. data/vendor/libgit2/include/git2/version.h +4 -4
  87. data/vendor/libgit2/include/git2.h +1 -0
  88. data/vendor/libgit2/src/annotated_commit.c +99 -80
  89. data/vendor/libgit2/src/annotated_commit.h +5 -2
  90. data/vendor/libgit2/src/apply.c +377 -0
  91. data/vendor/libgit2/src/apply.h +21 -0
  92. data/vendor/libgit2/src/array.h +0 -1
  93. data/vendor/libgit2/src/blob.c +71 -39
  94. data/vendor/libgit2/src/branch.c +7 -5
  95. data/vendor/libgit2/src/buffer.c +252 -20
  96. data/vendor/libgit2/src/buffer.h +8 -0
  97. data/vendor/libgit2/src/checkout.c +69 -42
  98. data/vendor/libgit2/src/clone.c +0 -8
  99. data/vendor/libgit2/src/commit.c +193 -49
  100. data/vendor/libgit2/src/commit_list.c +8 -3
  101. data/vendor/libgit2/src/commit_list.h +1 -0
  102. data/vendor/libgit2/src/common.h +2 -1
  103. data/vendor/libgit2/src/config.c +3 -3
  104. data/vendor/libgit2/src/config_file.c +20 -10
  105. data/vendor/libgit2/src/crlf.c +1 -0
  106. data/vendor/libgit2/src/curl_stream.c +106 -6
  107. data/vendor/libgit2/src/delta.c +238 -62
  108. data/vendor/libgit2/src/delta.h +79 -58
  109. data/vendor/libgit2/src/describe.c +1 -1
  110. data/vendor/libgit2/src/diff.c +32 -1554
  111. data/vendor/libgit2/src/diff.h +14 -122
  112. data/vendor/libgit2/src/diff_driver.c +4 -6
  113. data/vendor/libgit2/src/diff_file.c +3 -0
  114. data/vendor/libgit2/src/diff_generate.c +1613 -0
  115. data/vendor/libgit2/src/diff_generate.h +123 -0
  116. data/vendor/libgit2/src/diff_parse.c +101 -0
  117. data/vendor/libgit2/src/diff_parse.h +18 -0
  118. data/vendor/libgit2/src/diff_print.c +263 -144
  119. data/vendor/libgit2/src/diff_stats.c +21 -12
  120. data/vendor/libgit2/src/diff_tform.c +1 -0
  121. data/vendor/libgit2/src/diff_tform.h +22 -0
  122. data/vendor/libgit2/src/diff_xdiff.c +9 -9
  123. data/vendor/libgit2/src/diff_xdiff.h +5 -5
  124. data/vendor/libgit2/src/fetchhead.c +8 -8
  125. data/vendor/libgit2/src/filebuf.c +6 -1
  126. data/vendor/libgit2/src/filebuf.h +1 -0
  127. data/vendor/libgit2/src/fileops.c +22 -1
  128. data/vendor/libgit2/src/fileops.h +8 -2
  129. data/vendor/libgit2/src/fnmatch.c +18 -5
  130. data/vendor/libgit2/src/global.c +21 -4
  131. data/vendor/libgit2/src/global.h +6 -0
  132. data/vendor/libgit2/src/graph.c +1 -1
  133. data/vendor/libgit2/src/index.c +159 -46
  134. data/vendor/libgit2/src/index.h +2 -0
  135. data/vendor/libgit2/src/iterator.c +1573 -1468
  136. data/vendor/libgit2/src/iterator.h +52 -69
  137. data/vendor/libgit2/src/merge.c +163 -64
  138. data/vendor/libgit2/src/merge.h +61 -2
  139. data/vendor/libgit2/src/merge_driver.c +397 -0
  140. data/vendor/libgit2/src/merge_driver.h +60 -0
  141. data/vendor/libgit2/src/merge_file.c +11 -49
  142. data/vendor/libgit2/src/netops.c +12 -10
  143. data/vendor/libgit2/src/object_api.c +19 -1
  144. data/vendor/libgit2/src/odb.c +228 -52
  145. data/vendor/libgit2/src/odb_loose.c +19 -1
  146. data/vendor/libgit2/src/odb_mempack.c +1 -1
  147. data/vendor/libgit2/src/odb_pack.c +27 -1
  148. data/vendor/libgit2/src/openssl_stream.c +4 -5
  149. data/vendor/libgit2/src/pack-objects.c +105 -76
  150. data/vendor/libgit2/src/pack-objects.h +13 -12
  151. data/vendor/libgit2/src/pack.c +16 -10
  152. data/vendor/libgit2/src/pack.h +2 -0
  153. data/vendor/libgit2/src/patch.c +216 -0
  154. data/vendor/libgit2/src/patch.h +66 -0
  155. data/vendor/libgit2/src/{diff_patch.c → patch_generate.c} +203 -376
  156. data/vendor/libgit2/src/patch_generate.h +68 -0
  157. data/vendor/libgit2/src/patch_parse.c +1159 -0
  158. data/vendor/libgit2/src/patch_parse.h +56 -0
  159. data/vendor/libgit2/src/path.c +38 -2
  160. data/vendor/libgit2/src/path.h +18 -0
  161. data/vendor/libgit2/src/pathspec.c +1 -1
  162. data/vendor/libgit2/src/pool.h +5 -0
  163. data/vendor/libgit2/src/pqueue.c +12 -5
  164. data/vendor/libgit2/src/pqueue.h +1 -0
  165. data/vendor/libgit2/src/proxy.c +32 -0
  166. data/vendor/libgit2/src/proxy.h +14 -0
  167. data/vendor/libgit2/src/push.c +1 -1
  168. data/vendor/libgit2/src/rebase.c +63 -36
  169. data/vendor/libgit2/src/refdb.c +4 -2
  170. data/vendor/libgit2/src/refdb_fs.c +82 -54
  171. data/vendor/libgit2/src/refs.c +13 -1
  172. data/vendor/libgit2/src/remote.c +20 -81
  173. data/vendor/libgit2/src/repository.c +212 -29
  174. data/vendor/libgit2/src/reset.c +1 -1
  175. data/vendor/libgit2/src/revparse.c +1 -1
  176. data/vendor/libgit2/src/revwalk.c +260 -184
  177. data/vendor/libgit2/src/settings.c +11 -3
  178. data/vendor/libgit2/src/signature.c +27 -2
  179. data/vendor/libgit2/src/sortedcache.c +14 -5
  180. data/vendor/libgit2/src/stash.c +1 -0
  181. data/vendor/libgit2/src/status.c +1 -0
  182. data/vendor/libgit2/src/stransport_stream.c +4 -2
  183. data/vendor/libgit2/src/stream.h +2 -2
  184. data/vendor/libgit2/src/submodule.c +16 -4
  185. data/vendor/libgit2/src/sysdir.c +1 -1
  186. data/vendor/libgit2/src/transport.c +3 -5
  187. data/vendor/libgit2/src/transports/http.c +38 -13
  188. data/vendor/libgit2/src/transports/local.c +4 -1
  189. data/vendor/libgit2/src/transports/smart.c +6 -0
  190. data/vendor/libgit2/src/transports/smart.h +1 -0
  191. data/vendor/libgit2/src/transports/smart_pkt.c +5 -13
  192. data/vendor/libgit2/src/transports/smart_protocol.c +22 -7
  193. data/vendor/libgit2/src/transports/winhttp.c +144 -11
  194. data/vendor/libgit2/src/tree.c +267 -2
  195. data/vendor/libgit2/src/unix/posix.h +10 -0
  196. data/vendor/libgit2/src/unix/pthread.h +2 -0
  197. data/vendor/libgit2/src/util.c +25 -2
  198. data/vendor/libgit2/src/util.h +10 -0
  199. data/vendor/libgit2/src/varint.c +44 -0
  200. data/vendor/libgit2/src/varint.h +15 -0
  201. data/vendor/libgit2/src/vector.c +58 -0
  202. data/vendor/libgit2/src/vector.h +8 -0
  203. data/vendor/libgit2/src/win32/posix.h +3 -0
  204. data/vendor/libgit2/src/win32/thread.c +18 -0
  205. data/vendor/libgit2/src/win32/thread.h +2 -0
  206. data/vendor/libgit2/src/win32/w32_util.h +1 -1
  207. data/vendor/libgit2/src/zstream.c +37 -8
  208. data/vendor/libgit2/src/zstream.h +8 -1
  209. metadata +100 -82
  210. data/vendor/libgit2/Makefile.embed +0 -60
  211. data/vendor/libgit2/src/delta-apply.c +0 -166
  212. data/vendor/libgit2/src/delta-apply.h +0 -62
  213. data/vendor/libgit2/src/diff_patch.h +0 -83
@@ -0,0 +1,377 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
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
+
8
+ #include <assert.h>
9
+
10
+ #include "git2/patch.h"
11
+ #include "git2/filter.h"
12
+ #include "array.h"
13
+ #include "patch.h"
14
+ #include "fileops.h"
15
+ #include "apply.h"
16
+ #include "delta.h"
17
+ #include "zstream.h"
18
+
19
+ #define apply_err(...) \
20
+ ( giterr_set(GITERR_PATCH, __VA_ARGS__), -1 )
21
+
22
+ typedef struct {
23
+ /* The lines that we allocate ourself are allocated out of the pool.
24
+ * (Lines may have been allocated out of the diff.)
25
+ */
26
+ git_pool pool;
27
+ git_vector lines;
28
+ } patch_image;
29
+
30
+ static void patch_line_init(
31
+ git_diff_line *out,
32
+ const char *in,
33
+ size_t in_len,
34
+ size_t in_offset)
35
+ {
36
+ out->content = in;
37
+ out->content_len = in_len;
38
+ out->content_offset = in_offset;
39
+ }
40
+
41
+ #define PATCH_IMAGE_INIT { GIT_POOL_INIT, GIT_VECTOR_INIT }
42
+
43
+ static int patch_image_init_fromstr(
44
+ patch_image *out, const char *in, size_t in_len)
45
+ {
46
+ git_diff_line *line;
47
+ const char *start, *end;
48
+
49
+ memset(out, 0x0, sizeof(patch_image));
50
+
51
+ git_pool_init(&out->pool, sizeof(git_diff_line));
52
+
53
+ for (start = in; start < in + in_len; start = end) {
54
+ end = memchr(start, '\n', in_len);
55
+
56
+ if (end == NULL)
57
+ end = in + in_len;
58
+
59
+ else if (end < in + in_len)
60
+ end++;
61
+
62
+ line = git_pool_mallocz(&out->pool, 1);
63
+ GITERR_CHECK_ALLOC(line);
64
+
65
+ if (git_vector_insert(&out->lines, line) < 0)
66
+ return -1;
67
+
68
+ patch_line_init(line, start, (end - start), (start - in));
69
+ }
70
+
71
+ return 0;
72
+ }
73
+
74
+ static void patch_image_free(patch_image *image)
75
+ {
76
+ if (image == NULL)
77
+ return;
78
+
79
+ git_pool_clear(&image->pool);
80
+ git_vector_free(&image->lines);
81
+ }
82
+
83
+ static bool match_hunk(
84
+ patch_image *image,
85
+ patch_image *preimage,
86
+ size_t linenum)
87
+ {
88
+ bool match = 0;
89
+ size_t i;
90
+
91
+ /* Ensure this hunk is within the image boundaries. */
92
+ if (git_vector_length(&preimage->lines) + linenum >
93
+ git_vector_length(&image->lines))
94
+ return 0;
95
+
96
+ match = 1;
97
+
98
+ /* Check exact match. */
99
+ for (i = 0; i < git_vector_length(&preimage->lines); i++) {
100
+ git_diff_line *preimage_line = git_vector_get(&preimage->lines, i);
101
+ git_diff_line *image_line = git_vector_get(&image->lines, linenum + i);
102
+
103
+ if (preimage_line->content_len != image_line->content_len ||
104
+ memcmp(preimage_line->content, image_line->content, image_line->content_len) != 0) {
105
+ match = 0;
106
+ break;
107
+ }
108
+ }
109
+
110
+ return match;
111
+ }
112
+
113
+ static bool find_hunk_linenum(
114
+ size_t *out,
115
+ patch_image *image,
116
+ patch_image *preimage,
117
+ size_t linenum)
118
+ {
119
+ size_t max = git_vector_length(&image->lines);
120
+ bool match;
121
+
122
+ if (linenum > max)
123
+ linenum = max;
124
+
125
+ match = match_hunk(image, preimage, linenum);
126
+
127
+ *out = linenum;
128
+ return match;
129
+ }
130
+
131
+ static int update_hunk(
132
+ patch_image *image,
133
+ unsigned int linenum,
134
+ patch_image *preimage,
135
+ patch_image *postimage)
136
+ {
137
+ size_t postlen = git_vector_length(&postimage->lines);
138
+ size_t prelen = git_vector_length(&preimage->lines);
139
+ size_t i;
140
+ int error = 0;
141
+
142
+ if (postlen > prelen)
143
+ error = git_vector_insert_null(
144
+ &image->lines, linenum, (postlen - prelen));
145
+ else if (prelen > postlen)
146
+ error = git_vector_remove_range(
147
+ &image->lines, linenum, (prelen - postlen));
148
+
149
+ if (error) {
150
+ giterr_set_oom();
151
+ return -1;
152
+ }
153
+
154
+ for (i = 0; i < git_vector_length(&postimage->lines); i++) {
155
+ image->lines.contents[linenum + i] =
156
+ git_vector_get(&postimage->lines, i);
157
+ }
158
+
159
+ return 0;
160
+ }
161
+
162
+ static int apply_hunk(
163
+ patch_image *image,
164
+ git_patch *patch,
165
+ git_patch_hunk *hunk)
166
+ {
167
+ patch_image preimage = PATCH_IMAGE_INIT, postimage = PATCH_IMAGE_INIT;
168
+ size_t line_num, i;
169
+ int error = 0;
170
+
171
+ for (i = 0; i < hunk->line_count; i++) {
172
+ size_t linenum = hunk->line_start + i;
173
+ git_diff_line *line = git_array_get(patch->lines, linenum);
174
+
175
+ if (!line) {
176
+ error = apply_err("Preimage does not contain line %"PRIuZ, linenum);
177
+ goto done;
178
+ }
179
+
180
+ if (line->origin == GIT_DIFF_LINE_CONTEXT ||
181
+ line->origin == GIT_DIFF_LINE_DELETION) {
182
+ if ((error = git_vector_insert(&preimage.lines, line)) < 0)
183
+ goto done;
184
+ }
185
+
186
+ if (line->origin == GIT_DIFF_LINE_CONTEXT ||
187
+ line->origin == GIT_DIFF_LINE_ADDITION) {
188
+ if ((error = git_vector_insert(&postimage.lines, line)) < 0)
189
+ goto done;
190
+ }
191
+ }
192
+
193
+ line_num = hunk->hunk.new_start ? hunk->hunk.new_start - 1 : 0;
194
+
195
+ if (!find_hunk_linenum(&line_num, image, &preimage, line_num)) {
196
+ error = apply_err("Hunk at line %d did not apply",
197
+ hunk->hunk.new_start);
198
+ goto done;
199
+ }
200
+
201
+ error = update_hunk(image, line_num, &preimage, &postimage);
202
+
203
+ done:
204
+ patch_image_free(&preimage);
205
+ patch_image_free(&postimage);
206
+
207
+ return error;
208
+ }
209
+
210
+ static int apply_hunks(
211
+ git_buf *out,
212
+ const char *source,
213
+ size_t source_len,
214
+ git_patch *patch)
215
+ {
216
+ git_patch_hunk *hunk;
217
+ git_diff_line *line;
218
+ patch_image image;
219
+ size_t i;
220
+ int error = 0;
221
+
222
+ if ((error = patch_image_init_fromstr(&image, source, source_len)) < 0)
223
+ goto done;
224
+
225
+ git_array_foreach(patch->hunks, i, hunk) {
226
+ if ((error = apply_hunk(&image, patch, hunk)) < 0)
227
+ goto done;
228
+ }
229
+
230
+ git_vector_foreach(&image.lines, i, line)
231
+ git_buf_put(out, line->content, line->content_len);
232
+
233
+ done:
234
+ patch_image_free(&image);
235
+
236
+ return error;
237
+ }
238
+
239
+ static int apply_binary_delta(
240
+ git_buf *out,
241
+ const char *source,
242
+ size_t source_len,
243
+ git_diff_binary_file *binary_file)
244
+ {
245
+ git_buf inflated = GIT_BUF_INIT;
246
+ int error = 0;
247
+
248
+ /* no diff means identical contents */
249
+ if (binary_file->datalen == 0)
250
+ return git_buf_put(out, source, source_len);
251
+
252
+ error = git_zstream_inflatebuf(&inflated,
253
+ binary_file->data, binary_file->datalen);
254
+
255
+ if (!error && inflated.size != binary_file->inflatedlen) {
256
+ error = apply_err("inflated delta does not match expected length");
257
+ git_buf_free(out);
258
+ }
259
+
260
+ if (error < 0)
261
+ goto done;
262
+
263
+ if (binary_file->type == GIT_DIFF_BINARY_DELTA) {
264
+ void *data;
265
+ size_t data_len;
266
+
267
+ error = git_delta_apply(&data, &data_len, (void *)source, source_len,
268
+ (void *)inflated.ptr, inflated.size);
269
+
270
+ out->ptr = data;
271
+ out->size = data_len;
272
+ out->asize = data_len;
273
+ }
274
+ else if (binary_file->type == GIT_DIFF_BINARY_LITERAL) {
275
+ git_buf_swap(out, &inflated);
276
+ }
277
+ else {
278
+ error = apply_err("unknown binary delta type");
279
+ goto done;
280
+ }
281
+
282
+ done:
283
+ git_buf_free(&inflated);
284
+ return error;
285
+ }
286
+
287
+ static int apply_binary(
288
+ git_buf *out,
289
+ const char *source,
290
+ size_t source_len,
291
+ git_patch *patch)
292
+ {
293
+ git_buf reverse = GIT_BUF_INIT;
294
+ int error = 0;
295
+
296
+ if (!patch->binary.contains_data) {
297
+ error = apply_err("patch does not contain binary data");
298
+ goto done;
299
+ }
300
+
301
+ if (!patch->binary.old_file.datalen && !patch->binary.new_file.datalen)
302
+ goto done;
303
+
304
+ /* first, apply the new_file delta to the given source */
305
+ if ((error = apply_binary_delta(out, source, source_len,
306
+ &patch->binary.new_file)) < 0)
307
+ goto done;
308
+
309
+ /* second, apply the old_file delta to sanity check the result */
310
+ if ((error = apply_binary_delta(&reverse, out->ptr, out->size,
311
+ &patch->binary.old_file)) < 0)
312
+ goto done;
313
+
314
+ if (source_len != reverse.size ||
315
+ memcmp(source, reverse.ptr, source_len) != 0) {
316
+ error = apply_err("binary patch did not apply cleanly");
317
+ goto done;
318
+ }
319
+
320
+ done:
321
+ if (error < 0)
322
+ git_buf_free(out);
323
+
324
+ git_buf_free(&reverse);
325
+ return error;
326
+ }
327
+
328
+ int git_apply__patch(
329
+ git_buf *contents_out,
330
+ char **filename_out,
331
+ unsigned int *mode_out,
332
+ const char *source,
333
+ size_t source_len,
334
+ git_patch *patch)
335
+ {
336
+ char *filename = NULL;
337
+ unsigned int mode = 0;
338
+ int error = 0;
339
+
340
+ assert(contents_out && filename_out && mode_out && (source || !source_len) && patch);
341
+
342
+ *filename_out = NULL;
343
+ *mode_out = 0;
344
+
345
+ if (patch->delta->status != GIT_DELTA_DELETED) {
346
+ const git_diff_file *newfile = &patch->delta->new_file;
347
+
348
+ filename = git__strdup(newfile->path);
349
+ mode = newfile->mode ?
350
+ newfile->mode : GIT_FILEMODE_BLOB;
351
+ }
352
+
353
+ if (patch->delta->flags & GIT_DIFF_FLAG_BINARY)
354
+ error = apply_binary(contents_out, source, source_len, patch);
355
+ else if (patch->hunks.size)
356
+ error = apply_hunks(contents_out, source, source_len, patch);
357
+ else
358
+ error = git_buf_put(contents_out, source, source_len);
359
+
360
+ if (error)
361
+ goto done;
362
+
363
+ if (patch->delta->status == GIT_DELTA_DELETED &&
364
+ git_buf_len(contents_out) > 0) {
365
+ error = apply_err("removal patch leaves file contents");
366
+ goto done;
367
+ }
368
+
369
+ *filename_out = filename;
370
+ *mode_out = mode;
371
+
372
+ done:
373
+ if (error < 0)
374
+ git__free(filename);
375
+
376
+ return error;
377
+ }
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
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_apply_h__
8
+ #define INCLUDE_apply_h__
9
+
10
+ #include "git2/patch.h"
11
+ #include "buffer.h"
12
+
13
+ extern int git_apply__patch(
14
+ git_buf *out,
15
+ char **filename,
16
+ unsigned int *mode,
17
+ const char *source,
18
+ size_t source_len,
19
+ git_patch *patch);
20
+
21
+ #endif
@@ -85,7 +85,6 @@ on_oom:
85
85
  #define git_array_foreach(a, i, element) \
86
86
  for ((i) = 0; (i) < (a).size && ((element) = &(a).ptr[(i)]); (i)++)
87
87
 
88
-
89
88
  GIT_INLINE(int) git_array__search(
90
89
  size_t *out,
91
90
  void *array_ptr,
@@ -274,64 +274,96 @@ int git_blob_create_fromdisk(
274
274
  return error;
275
275
  }
276
276
 
277
- #define BUFFER_SIZE 4096
277
+ typedef struct {
278
+ git_writestream parent;
279
+ git_filebuf fbuf;
280
+ git_repository *repo;
281
+ char *hintpath;
282
+ } blob_writestream;
283
+
284
+ static int blob_writestream_close(git_writestream *_stream)
285
+ {
286
+ blob_writestream *stream = (blob_writestream *) _stream;
278
287
 
279
- int git_blob_create_fromchunks(
280
- git_oid *id,
281
- git_repository *repo,
282
- const char *hintpath,
283
- int (*source_cb)(char *content, size_t max_length, void *payload),
284
- void *payload)
288
+ git_filebuf_cleanup(&stream->fbuf);
289
+ return 0;
290
+ }
291
+
292
+ static void blob_writestream_free(git_writestream *_stream)
293
+ {
294
+ blob_writestream *stream = (blob_writestream *) _stream;
295
+
296
+ git_filebuf_cleanup(&stream->fbuf);
297
+ git__free(stream->hintpath);
298
+ git__free(stream);
299
+ }
300
+
301
+ static int blob_writestream_write(git_writestream *_stream, const char *buffer, size_t len)
302
+ {
303
+ blob_writestream *stream = (blob_writestream *) _stream;
304
+
305
+ return git_filebuf_write(&stream->fbuf, buffer, len);
306
+ }
307
+
308
+ int git_blob_create_fromstream(git_writestream **out, git_repository *repo, const char *hintpath)
285
309
  {
286
310
  int error;
287
- char *content = NULL;
288
- git_filebuf file = GIT_FILEBUF_INIT;
289
311
  git_buf path = GIT_BUF_INIT;
312
+ blob_writestream *stream;
290
313
 
291
- assert(id && repo && source_cb);
314
+ assert(out && repo);
292
315
 
293
- if ((error = git_buf_joinpath(
294
- &path, git_repository_path(repo), GIT_OBJECTS_DIR "streamed")) < 0)
295
- goto cleanup;
316
+ stream = git__calloc(1, sizeof(blob_writestream));
317
+ GITERR_CHECK_ALLOC(stream);
296
318
 
297
- content = git__malloc(BUFFER_SIZE);
298
- GITERR_CHECK_ALLOC(content);
319
+ if (hintpath) {
320
+ stream->hintpath = git__strdup(hintpath);
321
+ GITERR_CHECK_ALLOC(stream->hintpath);
322
+ }
299
323
 
300
- if ((error = git_filebuf_open(
301
- &file, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY, 0666)) < 0)
324
+ stream->repo = repo;
325
+ stream->parent.write = blob_writestream_write;
326
+ stream->parent.close = blob_writestream_close;
327
+ stream->parent.free = blob_writestream_free;
328
+
329
+ if ((error = git_buf_joinpath(&path,
330
+ git_repository_path(repo), GIT_OBJECTS_DIR "streamed")) < 0)
302
331
  goto cleanup;
303
332
 
304
- while (1) {
305
- int read_bytes = source_cb(content, BUFFER_SIZE, payload);
333
+ if ((error = git_filebuf_open_withsize(&stream->fbuf, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY,
334
+ 0666, 2 * 1024 * 1024)) < 0)
335
+ goto cleanup;
306
336
 
307
- if (!read_bytes)
308
- break;
337
+ *out = (git_writestream *) stream;
309
338
 
310
- if (read_bytes > BUFFER_SIZE) {
311
- giterr_set(GITERR_OBJECT, "Invalid chunk size while creating blob");
312
- error = GIT_EBUFS;
313
- } else if (read_bytes < 0) {
314
- error = giterr_set_after_callback(read_bytes);
315
- } else {
316
- error = git_filebuf_write(&file, content, read_bytes);
317
- }
339
+ cleanup:
340
+ if (error < 0)
341
+ blob_writestream_free((git_writestream *) stream);
318
342
 
319
- if (error < 0)
320
- goto cleanup;
321
- }
343
+ git_buf_free(&path);
344
+ return error;
345
+ }
322
346
 
323
- if ((error = git_filebuf_flush(&file)) < 0)
347
+ int git_blob_create_fromstream_commit(git_oid *out, git_writestream *_stream)
348
+ {
349
+ int error;
350
+ blob_writestream *stream = (blob_writestream *) _stream;
351
+
352
+ /*
353
+ * We can make this more officient by avoiding writing to
354
+ * disk, but for now let's re-use the helper functions we
355
+ * have.
356
+ */
357
+ if ((error = git_filebuf_flush(&stream->fbuf)) < 0)
324
358
  goto cleanup;
325
359
 
326
- error = git_blob__create_from_paths(
327
- id, NULL, repo, file.path_lock, hintpath, 0, hintpath != NULL);
360
+ error = git_blob__create_from_paths(out, NULL, stream->repo, stream->fbuf.path_lock,
361
+ stream->hintpath, 0, !!stream->hintpath);
328
362
 
329
363
  cleanup:
330
- git_buf_free(&path);
331
- git_filebuf_cleanup(&file);
332
- git__free(content);
333
-
364
+ blob_writestream_free(_stream);
334
365
  return error;
366
+
335
367
  }
336
368
 
337
369
  int git_blob_is_binary(const git_blob *blob)
@@ -58,16 +58,17 @@ static int create_branch(
58
58
  const char *from,
59
59
  int force)
60
60
  {
61
- int is_head = 0;
61
+ int is_unmovable_head = 0;
62
62
  git_reference *branch = NULL;
63
63
  git_buf canonical_branch_name = GIT_BUF_INIT,
64
64
  log_message = GIT_BUF_INIT;
65
65
  int error = -1;
66
+ int bare = git_repository_is_bare(repository);
66
67
 
67
68
  assert(branch_name && commit && ref_out);
68
69
  assert(git_object_owner((const git_object *)commit) == repository);
69
70
 
70
- if (force && git_branch_lookup(&branch, repository, branch_name, GIT_BRANCH_LOCAL) == 0) {
71
+ if (force && !bare && git_branch_lookup(&branch, repository, branch_name, GIT_BRANCH_LOCAL) == 0) {
71
72
  error = git_branch_is_head(branch);
72
73
  git_reference_free(branch);
73
74
  branch = NULL;
@@ -75,10 +76,10 @@ static int create_branch(
75
76
  if (error < 0)
76
77
  goto cleanup;
77
78
 
78
- is_head = error;
79
+ is_unmovable_head = error;
79
80
  }
80
81
 
81
- if (is_head && force) {
82
+ if (is_unmovable_head && force) {
82
83
  giterr_set(GITERR_REFERENCE, "Cannot force update branch '%s' as it is "
83
84
  "the current HEAD of the repository.", branch_name);
84
85
  error = -1;
@@ -121,7 +122,8 @@ int git_branch_create_from_annotated(
121
122
  const git_annotated_commit *commit,
122
123
  int force)
123
124
  {
124
- return create_branch(ref_out, repository, branch_name, commit->commit, commit->ref_name, force);
125
+ return create_branch(ref_out,
126
+ repository, branch_name, commit->commit, commit->description, force);
125
127
  }
126
128
 
127
129
  int git_branch_delete(git_reference *branch)