rugged 0.25.0b5 → 0.25.0b6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/rugged/rugged_patch.c +77 -17
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/CMakeLists.txt +8 -6
- data/vendor/libgit2/include/git2/checkout.h +7 -0
- data/vendor/libgit2/include/git2/common.h +1 -0
- data/vendor/libgit2/include/git2/diff.h +54 -7
- data/vendor/libgit2/include/git2/errors.h +2 -1
- data/vendor/libgit2/include/git2/index.h +25 -0
- data/vendor/libgit2/include/git2/pack.h +4 -4
- data/vendor/libgit2/include/git2/repository.h +20 -1
- data/vendor/libgit2/include/git2/submodule.h +11 -3
- data/vendor/libgit2/include/git2/sys/odb_backend.h +11 -0
- data/vendor/libgit2/src/apply.c +369 -0
- data/vendor/libgit2/src/apply.h +21 -0
- data/vendor/libgit2/src/array.h +0 -1
- data/vendor/libgit2/src/blame_git.c +18 -8
- data/vendor/libgit2/src/buffer.c +252 -20
- data/vendor/libgit2/src/buffer.h +8 -0
- data/vendor/libgit2/src/checkout.c +7 -1
- data/vendor/libgit2/src/clone.c +0 -8
- data/vendor/libgit2/src/common.h +1 -1
- data/vendor/libgit2/src/crlf.c +1 -0
- data/vendor/libgit2/src/delta.c +238 -62
- data/vendor/libgit2/src/delta.h +79 -58
- data/vendor/libgit2/src/diff.c +32 -1547
- data/vendor/libgit2/src/diff.h +12 -122
- data/vendor/libgit2/src/diff_driver.c +1 -2
- data/vendor/libgit2/src/diff_file.c +3 -0
- data/vendor/libgit2/src/diff_generate.c +1611 -0
- data/vendor/libgit2/src/diff_generate.h +123 -0
- data/vendor/libgit2/src/diff_parse.c +105 -0
- data/vendor/libgit2/src/diff_print.c +259 -142
- data/vendor/libgit2/src/diff_stats.c +3 -2
- data/vendor/libgit2/src/diff_tform.c +1 -0
- data/vendor/libgit2/src/diff_tform.h +22 -0
- data/vendor/libgit2/src/diff_xdiff.c +9 -9
- data/vendor/libgit2/src/diff_xdiff.h +5 -5
- data/vendor/libgit2/src/fileops.c +13 -0
- data/vendor/libgit2/src/fileops.h +6 -0
- data/vendor/libgit2/src/global.c +9 -8
- data/vendor/libgit2/src/ignore.c +45 -16
- data/vendor/libgit2/src/index.c +161 -47
- data/vendor/libgit2/src/index.h +2 -0
- data/vendor/libgit2/src/merge.c +2 -0
- data/vendor/libgit2/src/mwindow.c +8 -19
- data/vendor/libgit2/src/mwindow.h +1 -2
- data/vendor/libgit2/src/odb.c +46 -10
- data/vendor/libgit2/src/odb_loose.c +19 -1
- data/vendor/libgit2/src/odb_pack.c +27 -4
- data/vendor/libgit2/src/pack-objects.c +106 -77
- data/vendor/libgit2/src/pack-objects.h +13 -12
- data/vendor/libgit2/src/pack.c +4 -3
- data/vendor/libgit2/src/pack.h +2 -0
- data/vendor/libgit2/src/patch.c +207 -0
- data/vendor/libgit2/src/patch.h +66 -0
- data/vendor/libgit2/src/{diff_patch.c → patch_generate.c} +171 -359
- data/vendor/libgit2/src/patch_generate.h +66 -0
- data/vendor/libgit2/src/patch_parse.c +1121 -0
- data/vendor/libgit2/src/patch_parse.h +54 -0
- data/vendor/libgit2/src/path.c +19 -0
- data/vendor/libgit2/src/path.h +6 -0
- data/vendor/libgit2/src/pool.h +5 -0
- data/vendor/libgit2/src/remote.c +15 -80
- data/vendor/libgit2/src/repository.c +227 -39
- data/vendor/libgit2/src/settings.c +11 -5
- data/vendor/libgit2/src/stash.c +1 -0
- data/vendor/libgit2/src/status.c +1 -0
- data/vendor/libgit2/src/stransport_stream.c +14 -9
- data/vendor/libgit2/src/submodule.c +16 -4
- data/vendor/libgit2/src/sysdir.c +41 -47
- data/vendor/libgit2/src/sysdir.h +0 -5
- data/vendor/libgit2/src/thread-utils.h +5 -51
- data/vendor/libgit2/src/transport.c +3 -5
- data/vendor/libgit2/src/transports/http.c +2 -3
- data/vendor/libgit2/src/transports/smart_pkt.c +1 -0
- data/vendor/libgit2/src/transports/smart_protocol.c +11 -0
- data/vendor/libgit2/src/transports/winhttp.c +16 -2
- data/vendor/libgit2/src/unix/pthread.h +54 -0
- data/vendor/libgit2/src/util.c +23 -5
- data/vendor/libgit2/src/util.h +10 -0
- data/vendor/libgit2/src/varint.c +44 -0
- data/vendor/libgit2/src/varint.h +15 -0
- data/vendor/libgit2/src/vector.c +42 -0
- data/vendor/libgit2/src/vector.h +3 -0
- data/vendor/libgit2/src/win32/precompiled.h +1 -1
- data/vendor/libgit2/src/win32/{pthread.c → thread.c} +50 -80
- data/vendor/libgit2/src/win32/thread.h +62 -0
- data/vendor/libgit2/src/zstream.c +36 -7
- data/vendor/libgit2/src/zstream.h +8 -1
- metadata +20 -9
- data/vendor/libgit2/src/delta-apply.c +0 -166
- data/vendor/libgit2/src/delta-apply.h +0 -62
- data/vendor/libgit2/src/diff_patch.h +0 -83
- 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
|
data/vendor/libgit2/src/array.h
CHANGED
@@ -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
|
-
|
53
|
-
|
54
|
-
|
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);
|