rugged 0.25.0b5 → 0.25.0b6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged_patch.c +77 -17
  3. data/lib/rugged/version.rb +1 -1
  4. data/vendor/libgit2/CMakeLists.txt +8 -6
  5. data/vendor/libgit2/include/git2/checkout.h +7 -0
  6. data/vendor/libgit2/include/git2/common.h +1 -0
  7. data/vendor/libgit2/include/git2/diff.h +54 -7
  8. data/vendor/libgit2/include/git2/errors.h +2 -1
  9. data/vendor/libgit2/include/git2/index.h +25 -0
  10. data/vendor/libgit2/include/git2/pack.h +4 -4
  11. data/vendor/libgit2/include/git2/repository.h +20 -1
  12. data/vendor/libgit2/include/git2/submodule.h +11 -3
  13. data/vendor/libgit2/include/git2/sys/odb_backend.h +11 -0
  14. data/vendor/libgit2/src/apply.c +369 -0
  15. data/vendor/libgit2/src/apply.h +21 -0
  16. data/vendor/libgit2/src/array.h +0 -1
  17. data/vendor/libgit2/src/blame_git.c +18 -8
  18. data/vendor/libgit2/src/buffer.c +252 -20
  19. data/vendor/libgit2/src/buffer.h +8 -0
  20. data/vendor/libgit2/src/checkout.c +7 -1
  21. data/vendor/libgit2/src/clone.c +0 -8
  22. data/vendor/libgit2/src/common.h +1 -1
  23. data/vendor/libgit2/src/crlf.c +1 -0
  24. data/vendor/libgit2/src/delta.c +238 -62
  25. data/vendor/libgit2/src/delta.h +79 -58
  26. data/vendor/libgit2/src/diff.c +32 -1547
  27. data/vendor/libgit2/src/diff.h +12 -122
  28. data/vendor/libgit2/src/diff_driver.c +1 -2
  29. data/vendor/libgit2/src/diff_file.c +3 -0
  30. data/vendor/libgit2/src/diff_generate.c +1611 -0
  31. data/vendor/libgit2/src/diff_generate.h +123 -0
  32. data/vendor/libgit2/src/diff_parse.c +105 -0
  33. data/vendor/libgit2/src/diff_print.c +259 -142
  34. data/vendor/libgit2/src/diff_stats.c +3 -2
  35. data/vendor/libgit2/src/diff_tform.c +1 -0
  36. data/vendor/libgit2/src/diff_tform.h +22 -0
  37. data/vendor/libgit2/src/diff_xdiff.c +9 -9
  38. data/vendor/libgit2/src/diff_xdiff.h +5 -5
  39. data/vendor/libgit2/src/fileops.c +13 -0
  40. data/vendor/libgit2/src/fileops.h +6 -0
  41. data/vendor/libgit2/src/global.c +9 -8
  42. data/vendor/libgit2/src/ignore.c +45 -16
  43. data/vendor/libgit2/src/index.c +161 -47
  44. data/vendor/libgit2/src/index.h +2 -0
  45. data/vendor/libgit2/src/merge.c +2 -0
  46. data/vendor/libgit2/src/mwindow.c +8 -19
  47. data/vendor/libgit2/src/mwindow.h +1 -2
  48. data/vendor/libgit2/src/odb.c +46 -10
  49. data/vendor/libgit2/src/odb_loose.c +19 -1
  50. data/vendor/libgit2/src/odb_pack.c +27 -4
  51. data/vendor/libgit2/src/pack-objects.c +106 -77
  52. data/vendor/libgit2/src/pack-objects.h +13 -12
  53. data/vendor/libgit2/src/pack.c +4 -3
  54. data/vendor/libgit2/src/pack.h +2 -0
  55. data/vendor/libgit2/src/patch.c +207 -0
  56. data/vendor/libgit2/src/patch.h +66 -0
  57. data/vendor/libgit2/src/{diff_patch.c → patch_generate.c} +171 -359
  58. data/vendor/libgit2/src/patch_generate.h +66 -0
  59. data/vendor/libgit2/src/patch_parse.c +1121 -0
  60. data/vendor/libgit2/src/patch_parse.h +54 -0
  61. data/vendor/libgit2/src/path.c +19 -0
  62. data/vendor/libgit2/src/path.h +6 -0
  63. data/vendor/libgit2/src/pool.h +5 -0
  64. data/vendor/libgit2/src/remote.c +15 -80
  65. data/vendor/libgit2/src/repository.c +227 -39
  66. data/vendor/libgit2/src/settings.c +11 -5
  67. data/vendor/libgit2/src/stash.c +1 -0
  68. data/vendor/libgit2/src/status.c +1 -0
  69. data/vendor/libgit2/src/stransport_stream.c +14 -9
  70. data/vendor/libgit2/src/submodule.c +16 -4
  71. data/vendor/libgit2/src/sysdir.c +41 -47
  72. data/vendor/libgit2/src/sysdir.h +0 -5
  73. data/vendor/libgit2/src/thread-utils.h +5 -51
  74. data/vendor/libgit2/src/transport.c +3 -5
  75. data/vendor/libgit2/src/transports/http.c +2 -3
  76. data/vendor/libgit2/src/transports/smart_pkt.c +1 -0
  77. data/vendor/libgit2/src/transports/smart_protocol.c +11 -0
  78. data/vendor/libgit2/src/transports/winhttp.c +16 -2
  79. data/vendor/libgit2/src/unix/pthread.h +54 -0
  80. data/vendor/libgit2/src/util.c +23 -5
  81. data/vendor/libgit2/src/util.h +10 -0
  82. data/vendor/libgit2/src/varint.c +44 -0
  83. data/vendor/libgit2/src/varint.h +15 -0
  84. data/vendor/libgit2/src/vector.c +42 -0
  85. data/vendor/libgit2/src/vector.h +3 -0
  86. data/vendor/libgit2/src/win32/precompiled.h +1 -1
  87. data/vendor/libgit2/src/win32/{pthread.c → thread.c} +50 -80
  88. data/vendor/libgit2/src/win32/thread.h +62 -0
  89. data/vendor/libgit2/src/zstream.c +36 -7
  90. data/vendor/libgit2/src/zstream.h +8 -1
  91. metadata +20 -9
  92. data/vendor/libgit2/src/delta-apply.c +0 -166
  93. data/vendor/libgit2/src/delta-apply.h +0 -62
  94. data/vendor/libgit2/src/diff_patch.h +0 -83
  95. data/vendor/libgit2/src/win32/pthread.h +0 -92
@@ -83,6 +83,17 @@ struct git_odb_backend {
83
83
  git_odb_writepack **, git_odb_backend *, git_odb *odb,
84
84
  git_transfer_progress_cb progress_cb, void *progress_payload);
85
85
 
86
+ /**
87
+ * "Freshens" an already existing object, updating its last-used
88
+ * time. This occurs when `git_odb_write` was called, but the
89
+ * object already existed (and will not be re-written). The
90
+ * underlying implementation may want to update last-used timestamps.
91
+ *
92
+ * If callers implement this, they should return `0` if the object
93
+ * exists and was freshened, and non-zero otherwise.
94
+ */
95
+ int (* freshen)(git_odb_backend *, const git_oid *);
96
+
86
97
  /**
87
98
  * Frees any resources held by the odb (including the `git_odb_backend`
88
99
  * itself). An odb backend implementation must provide this function.
@@ -0,0 +1,369 @@
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 %d", 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;
295
+
296
+ /* first, apply the new_file delta to the given source */
297
+ if ((error = apply_binary_delta(out, source, source_len,
298
+ &patch->binary.new_file)) < 0)
299
+ goto done;
300
+
301
+ /* second, apply the old_file delta to sanity check the result */
302
+ if ((error = apply_binary_delta(&reverse, out->ptr, out->size,
303
+ &patch->binary.old_file)) < 0)
304
+ goto done;
305
+
306
+ if (source_len != reverse.size ||
307
+ memcmp(source, reverse.ptr, source_len) != 0) {
308
+ error = apply_err("binary patch did not apply cleanly");
309
+ goto done;
310
+ }
311
+
312
+ done:
313
+ if (error < 0)
314
+ git_buf_free(out);
315
+
316
+ git_buf_free(&reverse);
317
+ return error;
318
+ }
319
+
320
+ int git_apply__patch(
321
+ git_buf *contents_out,
322
+ char **filename_out,
323
+ unsigned int *mode_out,
324
+ const char *source,
325
+ size_t source_len,
326
+ git_patch *patch)
327
+ {
328
+ char *filename = NULL;
329
+ unsigned int mode = 0;
330
+ int error = 0;
331
+
332
+ assert(contents_out && filename_out && mode_out && (source || !source_len) && patch);
333
+
334
+ *filename_out = NULL;
335
+ *mode_out = 0;
336
+
337
+ if (patch->delta->status != GIT_DELTA_DELETED) {
338
+ const git_diff_file *newfile = &patch->delta->new_file;
339
+
340
+ filename = git__strdup(newfile->path);
341
+ mode = newfile->mode ?
342
+ newfile->mode : GIT_FILEMODE_BLOB;
343
+ }
344
+
345
+ if (patch->delta->flags & GIT_DIFF_FLAG_BINARY)
346
+ error = apply_binary(contents_out, source, source_len, patch);
347
+ else if (patch->hunks.size)
348
+ error = apply_hunks(contents_out, source, source_len, patch);
349
+ else
350
+ error = git_buf_put(contents_out, source, source_len);
351
+
352
+ if (error)
353
+ goto done;
354
+
355
+ if (patch->delta->status == GIT_DELTA_DELETED &&
356
+ git_buf_len(contents_out) > 0) {
357
+ error = apply_err("removal patch leaves file contents");
358
+ goto done;
359
+ }
360
+
361
+ *filename_out = filename;
362
+ *mode_out = mode;
363
+
364
+ done:
365
+ if (error < 0)
366
+ git__free(filename);
367
+
368
+ return error;
369
+ }
@@ -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,
@@ -37,25 +37,27 @@ static void origin_decref(git_blame__origin *o)
37
37
  static int make_origin(git_blame__origin **out, git_commit *commit, const char *path)
38
38
  {
39
39
  git_blame__origin *o;
40
+ git_object *blob;
40
41
  size_t path_len = strlen(path), alloc_len;
41
42
  int error = 0;
42
43
 
44
+ if ((error = git_object_lookup_bypath(&blob, (git_object*)commit,
45
+ path, GIT_OBJ_BLOB)) < 0)
46
+ return error;
47
+
43
48
  GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*o), path_len);
44
49
  GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1);
45
50
  o = git__calloc(1, alloc_len);
46
51
  GITERR_CHECK_ALLOC(o);
47
52
 
48
53
  o->commit = commit;
54
+ o->blob = (git_blob *) blob;
49
55
  o->refcnt = 1;
50
56
  strcpy(o->path, path);
51
57
 
52
- if (!(error = git_object_lookup_bypath((git_object**)&o->blob, (git_object*)commit,
53
- path, GIT_OBJ_BLOB))) {
54
- *out = o;
55
- } else {
56
- origin_decref(o);
57
- }
58
- return error;
58
+ *out = o;
59
+
60
+ return 0;
59
61
  }
60
62
 
61
63
  /* Locate an existing origin or create a new one. */
@@ -529,8 +531,16 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
529
531
  goto finish;
530
532
  porigin = find_origin(blame, p, origin);
531
533
 
532
- if (!porigin)
534
+ if (!porigin) {
535
+ /*
536
+ * We only have to decrement the parent's
537
+ * reference count when no porigin has
538
+ * been created, as otherwise the commit
539
+ * is assigned to the created object.
540
+ */
541
+ git_commit_free(p);
533
542
  continue;
543
+ }
534
544
  if (porigin->blob && origin->blob &&
535
545
  !git_oid_cmp(git_blob_id(porigin->blob), git_blob_id(origin->blob))) {
536
546
  pass_whole_blame(blame, origin, porigin);