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
@@ -0,0 +1,123 @@
|
|
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_diff_generate_h__
|
8
|
+
#define INCLUDE_diff_generate_h__
|
9
|
+
|
10
|
+
enum {
|
11
|
+
GIT_DIFFCAPS_HAS_SYMLINKS = (1 << 0), /* symlinks on platform? */
|
12
|
+
GIT_DIFFCAPS_IGNORE_STAT = (1 << 1), /* use stat? */
|
13
|
+
GIT_DIFFCAPS_TRUST_MODE_BITS = (1 << 2), /* use st_mode? */
|
14
|
+
GIT_DIFFCAPS_TRUST_CTIME = (1 << 3), /* use st_ctime? */
|
15
|
+
GIT_DIFFCAPS_USE_DEV = (1 << 4), /* use st_dev? */
|
16
|
+
};
|
17
|
+
|
18
|
+
#define DIFF_FLAGS_KNOWN_BINARY (GIT_DIFF_FLAG_BINARY|GIT_DIFF_FLAG_NOT_BINARY)
|
19
|
+
#define DIFF_FLAGS_NOT_BINARY (GIT_DIFF_FLAG_NOT_BINARY|GIT_DIFF_FLAG__NO_DATA)
|
20
|
+
|
21
|
+
enum {
|
22
|
+
GIT_DIFF_FLAG__FREE_PATH = (1 << 7), /* `path` is allocated memory */
|
23
|
+
GIT_DIFF_FLAG__FREE_DATA = (1 << 8), /* internal file data is allocated */
|
24
|
+
GIT_DIFF_FLAG__UNMAP_DATA = (1 << 9), /* internal file data is mmap'ed */
|
25
|
+
GIT_DIFF_FLAG__NO_DATA = (1 << 10), /* file data should not be loaded */
|
26
|
+
GIT_DIFF_FLAG__FREE_BLOB = (1 << 11), /* release the blob when done */
|
27
|
+
GIT_DIFF_FLAG__LOADED = (1 << 12), /* file data has been loaded */
|
28
|
+
|
29
|
+
GIT_DIFF_FLAG__TO_DELETE = (1 << 16), /* delete entry during rename det. */
|
30
|
+
GIT_DIFF_FLAG__TO_SPLIT = (1 << 17), /* split entry during rename det. */
|
31
|
+
GIT_DIFF_FLAG__IS_RENAME_TARGET = (1 << 18),
|
32
|
+
GIT_DIFF_FLAG__IS_RENAME_SOURCE = (1 << 19),
|
33
|
+
GIT_DIFF_FLAG__HAS_SELF_SIMILARITY = (1 << 20),
|
34
|
+
};
|
35
|
+
|
36
|
+
#define GIT_DIFF_FLAG__CLEAR_INTERNAL(F) (F) = ((F) & 0x00FFFF)
|
37
|
+
|
38
|
+
#define GIT_DIFF__VERBOSE (1 << 30)
|
39
|
+
|
40
|
+
extern void git_diff_addref(git_diff *diff);
|
41
|
+
|
42
|
+
extern bool git_diff_delta__should_skip(
|
43
|
+
const git_diff_options *opts, const git_diff_delta *delta);
|
44
|
+
|
45
|
+
extern int git_diff__from_iterators(
|
46
|
+
git_diff **diff_ptr,
|
47
|
+
git_repository *repo,
|
48
|
+
git_iterator *old_iter,
|
49
|
+
git_iterator *new_iter,
|
50
|
+
const git_diff_options *opts);
|
51
|
+
|
52
|
+
extern int git_diff__commit(
|
53
|
+
git_diff **diff, git_repository *repo, const git_commit *commit, const git_diff_options *opts);
|
54
|
+
|
55
|
+
extern int git_diff__paired_foreach(
|
56
|
+
git_diff *idx2head,
|
57
|
+
git_diff *wd2idx,
|
58
|
+
int (*cb)(git_diff_delta *i2h, git_diff_delta *w2i, void *payload),
|
59
|
+
void *payload);
|
60
|
+
|
61
|
+
/* Merge two `git_diff`s according to the callback given by `cb`. */
|
62
|
+
|
63
|
+
typedef git_diff_delta *(*git_diff__merge_cb)(
|
64
|
+
const git_diff_delta *left,
|
65
|
+
const git_diff_delta *right,
|
66
|
+
git_pool *pool);
|
67
|
+
|
68
|
+
extern int git_diff__merge(
|
69
|
+
git_diff *onto, const git_diff *from, git_diff__merge_cb cb);
|
70
|
+
|
71
|
+
extern git_diff_delta *git_diff__merge_like_cgit(
|
72
|
+
const git_diff_delta *a,
|
73
|
+
const git_diff_delta *b,
|
74
|
+
git_pool *pool);
|
75
|
+
|
76
|
+
/* Duplicate a `git_diff_delta` out of the `git_pool` */
|
77
|
+
extern git_diff_delta *git_diff__delta_dup(
|
78
|
+
const git_diff_delta *d, git_pool *pool);
|
79
|
+
|
80
|
+
extern int git_diff__oid_for_file(
|
81
|
+
git_oid *out,
|
82
|
+
git_diff *diff,
|
83
|
+
const char *path,
|
84
|
+
uint16_t mode,
|
85
|
+
git_off_t size);
|
86
|
+
|
87
|
+
extern int git_diff__oid_for_entry(
|
88
|
+
git_oid *out,
|
89
|
+
git_diff *diff,
|
90
|
+
const git_index_entry *src,
|
91
|
+
uint16_t mode,
|
92
|
+
const git_oid *update_match);
|
93
|
+
|
94
|
+
/*
|
95
|
+
* Sometimes a git_diff_file will have a zero size; this attempts to
|
96
|
+
* fill in the size without loading the blob if possible. If that is
|
97
|
+
* not possible, then it will return the git_odb_object that had to be
|
98
|
+
* loaded and the caller can use it or dispose of it as needed.
|
99
|
+
*/
|
100
|
+
GIT_INLINE(int) git_diff_file__resolve_zero_size(
|
101
|
+
git_diff_file *file, git_odb_object **odb_obj, git_repository *repo)
|
102
|
+
{
|
103
|
+
int error;
|
104
|
+
git_odb *odb;
|
105
|
+
size_t len;
|
106
|
+
git_otype type;
|
107
|
+
|
108
|
+
if ((error = git_repository_odb(&odb, repo)) < 0)
|
109
|
+
return error;
|
110
|
+
|
111
|
+
error = git_odb__read_header_or_object(
|
112
|
+
odb_obj, &len, &type, odb, &file->id);
|
113
|
+
|
114
|
+
git_odb_free(odb);
|
115
|
+
|
116
|
+
if (!error)
|
117
|
+
file->size = (git_off_t)len;
|
118
|
+
|
119
|
+
return error;
|
120
|
+
}
|
121
|
+
|
122
|
+
#endif
|
123
|
+
|
@@ -0,0 +1,105 @@
|
|
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
|
+
#include "common.h"
|
8
|
+
#include "diff.h"
|
9
|
+
#include "patch.h"
|
10
|
+
#include "patch_parse.h"
|
11
|
+
|
12
|
+
typedef struct {
|
13
|
+
struct git_diff base;
|
14
|
+
|
15
|
+
git_vector patches;
|
16
|
+
} git_diff_parsed;
|
17
|
+
|
18
|
+
static void diff_parsed_free(git_diff *d)
|
19
|
+
{
|
20
|
+
git_diff_parsed *diff = (git_diff_parsed *)d;
|
21
|
+
git_patch *patch;
|
22
|
+
size_t i;
|
23
|
+
|
24
|
+
git_vector_foreach(&diff->patches, i, patch)
|
25
|
+
git_patch_free(patch);
|
26
|
+
|
27
|
+
git_vector_free(&diff->patches);
|
28
|
+
|
29
|
+
git_vector_free(&diff->base.deltas);
|
30
|
+
git_pool_clear(&diff->base.pool);
|
31
|
+
|
32
|
+
git__memzero(diff, sizeof(*diff));
|
33
|
+
git__free(diff);
|
34
|
+
}
|
35
|
+
|
36
|
+
static git_diff_parsed *diff_parsed_alloc(void)
|
37
|
+
{
|
38
|
+
git_diff_parsed *diff;
|
39
|
+
|
40
|
+
if ((diff = git__calloc(1, sizeof(git_diff_parsed))) == NULL)
|
41
|
+
return NULL;
|
42
|
+
|
43
|
+
GIT_REFCOUNT_INC(diff);
|
44
|
+
diff->base.type = GIT_DIFF_TYPE_PARSED;
|
45
|
+
diff->base.opts.flags &= ~GIT_DIFF_IGNORE_CASE;
|
46
|
+
diff->base.strcomp = git__strcmp;
|
47
|
+
diff->base.strncomp = git__strncmp;
|
48
|
+
diff->base.pfxcomp = git__prefixcmp;
|
49
|
+
diff->base.entrycomp = git_diff__entry_cmp;
|
50
|
+
diff->base.free_fn = diff_parsed_free;
|
51
|
+
|
52
|
+
git_pool_init(&diff->base.pool, 1);
|
53
|
+
|
54
|
+
if (git_vector_init(&diff->patches, 0, NULL) < 0 ||
|
55
|
+
git_vector_init(&diff->base.deltas, 0, git_diff_delta__cmp) < 0) {
|
56
|
+
git_diff_free(&diff->base);
|
57
|
+
return NULL;
|
58
|
+
}
|
59
|
+
|
60
|
+
git_vector_set_cmp(&diff->base.deltas, git_diff_delta__cmp);
|
61
|
+
|
62
|
+
return diff;
|
63
|
+
}
|
64
|
+
|
65
|
+
int git_diff_from_buffer(
|
66
|
+
git_diff **out,
|
67
|
+
const char *content,
|
68
|
+
size_t content_len)
|
69
|
+
{
|
70
|
+
git_diff_parsed *diff;
|
71
|
+
git_patch *patch;
|
72
|
+
git_patch_parse_ctx *ctx = NULL;
|
73
|
+
int error = 0;
|
74
|
+
|
75
|
+
*out = NULL;
|
76
|
+
|
77
|
+
diff = diff_parsed_alloc();
|
78
|
+
GITERR_CHECK_ALLOC(diff);
|
79
|
+
|
80
|
+
ctx = git_patch_parse_ctx_init(content, content_len, NULL);
|
81
|
+
GITERR_CHECK_ALLOC(ctx);
|
82
|
+
|
83
|
+
while (ctx->remain_len) {
|
84
|
+
if ((error = git_patch_parse(&patch, ctx)) < 0)
|
85
|
+
break;
|
86
|
+
|
87
|
+
git_vector_insert(&diff->patches, patch);
|
88
|
+
git_vector_insert(&diff->base.deltas, patch->delta);
|
89
|
+
}
|
90
|
+
|
91
|
+
if (error == GIT_ENOTFOUND && git_vector_length(&diff->patches) > 0) {
|
92
|
+
giterr_clear();
|
93
|
+
error = 0;
|
94
|
+
}
|
95
|
+
|
96
|
+
git_patch_parse_ctx_free(ctx);
|
97
|
+
|
98
|
+
if (error < 0)
|
99
|
+
git_diff_free(&diff->base);
|
100
|
+
else
|
101
|
+
*out = &diff->base;
|
102
|
+
|
103
|
+
return error;
|
104
|
+
}
|
105
|
+
|
@@ -6,7 +6,8 @@
|
|
6
6
|
*/
|
7
7
|
#include "common.h"
|
8
8
|
#include "diff.h"
|
9
|
-
#include "
|
9
|
+
#include "diff_file.h"
|
10
|
+
#include "patch_generate.h"
|
10
11
|
#include "fileops.h"
|
11
12
|
#include "zstream.h"
|
12
13
|
#include "blob.h"
|
@@ -14,19 +15,19 @@
|
|
14
15
|
#include "git2/sys/diff.h"
|
15
16
|
|
16
17
|
typedef struct {
|
17
|
-
git_diff *diff;
|
18
18
|
git_diff_format_t format;
|
19
19
|
git_diff_line_cb print_cb;
|
20
20
|
void *payload;
|
21
|
+
|
21
22
|
git_buf *buf;
|
22
|
-
uint32_t flags;
|
23
|
-
int oid_strlen;
|
24
23
|
git_diff_line line;
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
|
25
|
+
const char *old_prefix;
|
26
|
+
const char *new_prefix;
|
27
|
+
uint32_t flags;
|
28
|
+
int id_strlen;
|
29
|
+
|
30
|
+
int (*strcomp)(const char *, const char *);
|
30
31
|
} diff_print_info;
|
31
32
|
|
32
33
|
static int diff_print_info_init__common(
|
@@ -42,17 +43,15 @@ static int diff_print_info_init__common(
|
|
42
43
|
pi->payload = payload;
|
43
44
|
pi->buf = out;
|
44
45
|
|
45
|
-
if (!pi->
|
46
|
+
if (!pi->id_strlen) {
|
46
47
|
if (!repo)
|
47
|
-
pi->
|
48
|
-
else if (git_repository__cvar(&pi->
|
48
|
+
pi->id_strlen = GIT_ABBREV_DEFAULT;
|
49
|
+
else if (git_repository__cvar(&pi->id_strlen, repo, GIT_CVAR_ABBREV) < 0)
|
49
50
|
return -1;
|
50
51
|
}
|
51
52
|
|
52
|
-
pi->
|
53
|
-
|
54
|
-
if (pi->oid_strlen > GIT_OID_HEXSZ + 1)
|
55
|
-
pi->oid_strlen = GIT_OID_HEXSZ + 1;
|
53
|
+
if (pi->id_strlen > GIT_OID_HEXSZ)
|
54
|
+
pi->id_strlen = GIT_OID_HEXSZ;
|
56
55
|
|
57
56
|
memset(&pi->line, 0, sizeof(pi->line));
|
58
57
|
pi->line.old_lineno = -1;
|
@@ -74,11 +73,13 @@ static int diff_print_info_init_fromdiff(
|
|
74
73
|
|
75
74
|
memset(pi, 0, sizeof(diff_print_info));
|
76
75
|
|
77
|
-
pi->diff = diff;
|
78
|
-
|
79
76
|
if (diff) {
|
80
77
|
pi->flags = diff->opts.flags;
|
81
|
-
pi->
|
78
|
+
pi->id_strlen = diff->opts.id_abbrev;
|
79
|
+
pi->old_prefix = diff->opts.old_prefix;
|
80
|
+
pi->new_prefix = diff->opts.new_prefix;
|
81
|
+
|
82
|
+
pi->strcomp = diff->strcomp;
|
82
83
|
}
|
83
84
|
|
84
85
|
return diff_print_info_init__common(pi, out, repo, format, cb, payload);
|
@@ -92,24 +93,16 @@ static int diff_print_info_init_frompatch(
|
|
92
93
|
git_diff_line_cb cb,
|
93
94
|
void *payload)
|
94
95
|
{
|
95
|
-
git_repository *repo;
|
96
|
-
|
97
96
|
assert(patch);
|
98
97
|
|
99
|
-
repo = patch->diff ? patch->diff->repo : NULL;
|
100
|
-
|
101
98
|
memset(pi, 0, sizeof(diff_print_info));
|
102
99
|
|
103
|
-
pi->diff = patch->diff;
|
104
|
-
|
105
100
|
pi->flags = patch->diff_opts.flags;
|
106
|
-
pi->
|
107
|
-
|
108
|
-
pi->
|
109
|
-
pi->ofile = &patch->ofile;
|
110
|
-
pi->nfile = &patch->nfile;
|
101
|
+
pi->id_strlen = patch->diff_opts.id_abbrev;
|
102
|
+
pi->old_prefix = patch->diff_opts.old_prefix;
|
103
|
+
pi->new_prefix = patch->diff_opts.new_prefix;
|
111
104
|
|
112
|
-
return diff_print_info_init__common(pi, out, repo, format, cb, payload);
|
105
|
+
return diff_print_info_init__common(pi, out, patch->repo, format, cb, payload);
|
113
106
|
}
|
114
107
|
|
115
108
|
static char diff_pick_suffix(int mode)
|
@@ -173,8 +166,8 @@ static int diff_print_one_name_status(
|
|
173
166
|
diff_print_info *pi = data;
|
174
167
|
git_buf *out = pi->buf;
|
175
168
|
char old_suffix, new_suffix, code = git_diff_status_char(delta->status);
|
176
|
-
int
|
177
|
-
pi->
|
169
|
+
int(*strcomp)(const char *, const char *) = pi->strcomp ?
|
170
|
+
pi->strcomp : git__strcmp;
|
178
171
|
|
179
172
|
GIT_UNUSED(progress);
|
180
173
|
|
@@ -213,6 +206,7 @@ static int diff_print_one_raw(
|
|
213
206
|
{
|
214
207
|
diff_print_info *pi = data;
|
215
208
|
git_buf *out = pi->buf;
|
209
|
+
int id_abbrev;
|
216
210
|
char code = git_diff_status_char(delta->status);
|
217
211
|
char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
|
218
212
|
|
@@ -223,11 +217,21 @@ static int diff_print_one_raw(
|
|
223
217
|
|
224
218
|
git_buf_clear(out);
|
225
219
|
|
226
|
-
|
227
|
-
|
220
|
+
id_abbrev = delta->old_file.mode ? delta->old_file.id_abbrev :
|
221
|
+
delta->new_file.id_abbrev;
|
222
|
+
|
223
|
+
if (pi->id_strlen > id_abbrev) {
|
224
|
+
giterr_set(GITERR_PATCH,
|
225
|
+
"The patch input contains %d id characters (cannot print %d)",
|
226
|
+
id_abbrev, pi->id_strlen);
|
227
|
+
return -1;
|
228
|
+
}
|
229
|
+
|
230
|
+
git_oid_tostr(start_oid, pi->id_strlen + 1, &delta->old_file.id);
|
231
|
+
git_oid_tostr(end_oid, pi->id_strlen + 1, &delta->new_file.id);
|
228
232
|
|
229
233
|
git_buf_printf(
|
230
|
-
out, (pi->
|
234
|
+
out, (pi->id_strlen <= GIT_OID_HEXSZ) ?
|
231
235
|
":%06o %06o %s... %s... %c" : ":%06o %06o %s %s %c",
|
232
236
|
delta->old_file.mode, delta->new_file.mode, start_oid, end_oid, code);
|
233
237
|
|
@@ -252,53 +256,140 @@ static int diff_print_one_raw(
|
|
252
256
|
return pi->print_cb(delta, NULL, &pi->line, pi->payload);
|
253
257
|
}
|
254
258
|
|
259
|
+
static int diff_print_modes(
|
260
|
+
git_buf *out, const git_diff_delta *delta)
|
261
|
+
{
|
262
|
+
git_buf_printf(out, "old mode %o\n", delta->old_file.mode);
|
263
|
+
git_buf_printf(out, "new mode %o\n", delta->new_file.mode);
|
264
|
+
|
265
|
+
return git_buf_oom(out) ? -1 : 0;
|
266
|
+
}
|
267
|
+
|
255
268
|
static int diff_print_oid_range(
|
256
|
-
git_buf *out, const git_diff_delta *delta, int
|
269
|
+
git_buf *out, const git_diff_delta *delta, int id_strlen)
|
257
270
|
{
|
258
271
|
char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
|
259
272
|
|
260
|
-
|
261
|
-
|
273
|
+
if (delta->old_file.mode &&
|
274
|
+
id_strlen > delta->old_file.id_abbrev) {
|
275
|
+
giterr_set(GITERR_PATCH,
|
276
|
+
"The patch input contains %d id characters (cannot print %d)",
|
277
|
+
delta->old_file.id_abbrev, id_strlen);
|
278
|
+
return -1;
|
279
|
+
}
|
280
|
+
|
281
|
+
if ((delta->new_file.mode &&
|
282
|
+
id_strlen > delta->new_file.id_abbrev)) {
|
283
|
+
giterr_set(GITERR_PATCH,
|
284
|
+
"The patch input contains %d id characters (cannot print %d)",
|
285
|
+
delta->new_file.id_abbrev, id_strlen);
|
286
|
+
return -1;
|
287
|
+
}
|
288
|
+
|
289
|
+
git_oid_tostr(start_oid, id_strlen + 1, &delta->old_file.id);
|
290
|
+
git_oid_tostr(end_oid, id_strlen + 1, &delta->new_file.id);
|
262
291
|
|
263
|
-
/* TODO: Match git diff more closely */
|
264
292
|
if (delta->old_file.mode == delta->new_file.mode) {
|
265
293
|
git_buf_printf(out, "index %s..%s %o\n",
|
266
294
|
start_oid, end_oid, delta->old_file.mode);
|
267
295
|
} else {
|
268
|
-
if (delta->old_file.mode == 0)
|
296
|
+
if (delta->old_file.mode == 0)
|
269
297
|
git_buf_printf(out, "new file mode %o\n", delta->new_file.mode);
|
270
|
-
|
298
|
+
else if (delta->new_file.mode == 0)
|
271
299
|
git_buf_printf(out, "deleted file mode %o\n", delta->old_file.mode);
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
}
|
300
|
+
else
|
301
|
+
diff_print_modes(out, delta);
|
302
|
+
|
276
303
|
git_buf_printf(out, "index %s..%s\n", start_oid, end_oid);
|
277
304
|
}
|
278
305
|
|
279
306
|
return git_buf_oom(out) ? -1 : 0;
|
280
307
|
}
|
281
308
|
|
309
|
+
static int diff_delta_format_path(
|
310
|
+
git_buf *out, const char *prefix, const char *filename)
|
311
|
+
{
|
312
|
+
if (git_buf_joinpath(out, prefix, filename) < 0)
|
313
|
+
return -1;
|
314
|
+
|
315
|
+
return git_buf_quote(out);
|
316
|
+
}
|
317
|
+
|
282
318
|
static int diff_delta_format_with_paths(
|
283
319
|
git_buf *out,
|
284
320
|
const git_diff_delta *delta,
|
285
|
-
const char *
|
286
|
-
const char *
|
287
|
-
const char *
|
321
|
+
const char *template,
|
322
|
+
const char *oldpath,
|
323
|
+
const char *newpath)
|
288
324
|
{
|
289
|
-
|
290
|
-
const char *newpath = delta->new_file.path;
|
291
|
-
|
292
|
-
if (git_oid_iszero(&delta->old_file.id)) {
|
293
|
-
oldpfx = "";
|
325
|
+
if (git_oid_iszero(&delta->old_file.id))
|
294
326
|
oldpath = "/dev/null";
|
295
|
-
|
296
|
-
if (git_oid_iszero(&delta->new_file.id))
|
297
|
-
newpfx = "";
|
327
|
+
|
328
|
+
if (git_oid_iszero(&delta->new_file.id))
|
298
329
|
newpath = "/dev/null";
|
330
|
+
|
331
|
+
return git_buf_printf(out, template, oldpath, newpath);
|
332
|
+
}
|
333
|
+
|
334
|
+
int diff_delta_format_similarity_header(
|
335
|
+
git_buf *out,
|
336
|
+
const git_diff_delta *delta)
|
337
|
+
{
|
338
|
+
git_buf old_path = GIT_BUF_INIT, new_path = GIT_BUF_INIT;
|
339
|
+
const char *type;
|
340
|
+
int error = 0;
|
341
|
+
|
342
|
+
if (delta->similarity > 100) {
|
343
|
+
giterr_set(GITERR_PATCH, "invalid similarity %d", delta->similarity);
|
344
|
+
error = -1;
|
345
|
+
goto done;
|
299
346
|
}
|
300
347
|
|
301
|
-
|
348
|
+
if (delta->status == GIT_DELTA_RENAMED)
|
349
|
+
type = "rename";
|
350
|
+
else if (delta->status == GIT_DELTA_COPIED)
|
351
|
+
type = "copy";
|
352
|
+
else
|
353
|
+
abort();
|
354
|
+
|
355
|
+
if ((error = git_buf_puts(&old_path, delta->old_file.path)) < 0 ||
|
356
|
+
(error = git_buf_puts(&new_path, delta->new_file.path)) < 0 ||
|
357
|
+
(error = git_buf_quote(&old_path)) < 0 ||
|
358
|
+
(error = git_buf_quote(&new_path)) < 0)
|
359
|
+
goto done;
|
360
|
+
|
361
|
+
git_buf_printf(out,
|
362
|
+
"similarity index %d%%\n"
|
363
|
+
"%s from %s\n"
|
364
|
+
"%s to %s\n",
|
365
|
+
delta->similarity,
|
366
|
+
type, old_path.ptr,
|
367
|
+
type, new_path.ptr);
|
368
|
+
|
369
|
+
if (git_buf_oom(out))
|
370
|
+
error = -1;
|
371
|
+
|
372
|
+
done:
|
373
|
+
git_buf_free(&old_path);
|
374
|
+
git_buf_free(&new_path);
|
375
|
+
|
376
|
+
return error;
|
377
|
+
}
|
378
|
+
|
379
|
+
static bool delta_is_unchanged(const git_diff_delta *delta)
|
380
|
+
{
|
381
|
+
if (git_oid_iszero(&delta->old_file.id) &&
|
382
|
+
git_oid_iszero(&delta->new_file.id))
|
383
|
+
return true;
|
384
|
+
|
385
|
+
if (delta->old_file.mode == GIT_FILEMODE_COMMIT ||
|
386
|
+
delta->new_file.mode == GIT_FILEMODE_COMMIT)
|
387
|
+
return false;
|
388
|
+
|
389
|
+
if (git_oid_equal(&delta->old_file.id, &delta->new_file.id))
|
390
|
+
return true;
|
391
|
+
|
392
|
+
return false;
|
302
393
|
}
|
303
394
|
|
304
395
|
int git_diff_delta__format_file_header(
|
@@ -306,27 +397,56 @@ int git_diff_delta__format_file_header(
|
|
306
397
|
const git_diff_delta *delta,
|
307
398
|
const char *oldpfx,
|
308
399
|
const char *newpfx,
|
309
|
-
int
|
400
|
+
int id_strlen)
|
310
401
|
{
|
402
|
+
git_buf old_path = GIT_BUF_INIT, new_path = GIT_BUF_INIT;
|
403
|
+
bool unchanged = delta_is_unchanged(delta);
|
404
|
+
int error = 0;
|
405
|
+
|
311
406
|
if (!oldpfx)
|
312
407
|
oldpfx = DIFF_OLD_PREFIX_DEFAULT;
|
313
408
|
if (!newpfx)
|
314
409
|
newpfx = DIFF_NEW_PREFIX_DEFAULT;
|
315
|
-
if (!
|
316
|
-
|
410
|
+
if (!id_strlen)
|
411
|
+
id_strlen = GIT_ABBREV_DEFAULT;
|
412
|
+
|
413
|
+
if ((error = diff_delta_format_path(
|
414
|
+
&old_path, oldpfx, delta->old_file.path)) < 0 ||
|
415
|
+
(error = diff_delta_format_path(
|
416
|
+
&new_path, newpfx, delta->new_file.path)) < 0)
|
417
|
+
goto done;
|
317
418
|
|
318
419
|
git_buf_clear(out);
|
319
420
|
|
320
|
-
git_buf_printf(out, "diff --git %s
|
321
|
-
|
421
|
+
git_buf_printf(out, "diff --git %s %s\n",
|
422
|
+
old_path.ptr, new_path.ptr);
|
322
423
|
|
323
|
-
|
424
|
+
if (delta->status == GIT_DELTA_RENAMED ||
|
425
|
+
(delta->status == GIT_DELTA_COPIED && unchanged)) {
|
426
|
+
if ((error = diff_delta_format_similarity_header(out, delta)) < 0)
|
427
|
+
goto done;
|
428
|
+
}
|
324
429
|
|
325
|
-
if (
|
326
|
-
|
327
|
-
|
430
|
+
if (!unchanged) {
|
431
|
+
if ((error = diff_print_oid_range(out, delta, id_strlen)) < 0)
|
432
|
+
goto done;
|
328
433
|
|
329
|
-
|
434
|
+
if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0)
|
435
|
+
diff_delta_format_with_paths(out, delta,
|
436
|
+
"--- %s\n+++ %s\n", old_path.ptr, new_path.ptr);
|
437
|
+
}
|
438
|
+
|
439
|
+
if (unchanged && delta->old_file.mode != delta->new_file.mode)
|
440
|
+
diff_print_modes(out, delta);
|
441
|
+
|
442
|
+
if (git_buf_oom(out))
|
443
|
+
error = -1;
|
444
|
+
|
445
|
+
done:
|
446
|
+
git_buf_free(&old_path);
|
447
|
+
git_buf_free(&new_path);
|
448
|
+
|
449
|
+
return error;
|
330
450
|
}
|
331
451
|
|
332
452
|
static int format_binary(
|
@@ -367,37 +487,30 @@ static int format_binary(
|
|
367
487
|
return 0;
|
368
488
|
}
|
369
489
|
|
370
|
-
static int
|
371
|
-
diff_print_info *pi,
|
372
|
-
|
490
|
+
static int diff_print_patch_file_binary_noshow(
|
491
|
+
diff_print_info *pi, git_diff_delta *delta,
|
492
|
+
const char *old_pfx, const char *new_pfx)
|
373
493
|
{
|
374
|
-
|
494
|
+
git_buf old_path = GIT_BUF_INIT, new_path = GIT_BUF_INIT;
|
375
495
|
int error;
|
376
496
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
497
|
+
if ((error = diff_delta_format_path(
|
498
|
+
&old_path, old_pfx, delta->old_file.path)) < 0 ||
|
499
|
+
(error = diff_delta_format_path(
|
500
|
+
&new_path, new_pfx, delta->new_file.path)) < 0)
|
501
|
+
goto done;
|
381
502
|
|
382
|
-
GITERR_CHECK_ALLOC(ofile);
|
383
|
-
GITERR_CHECK_ALLOC(nfile);
|
384
503
|
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
git__free(ofile);
|
391
|
-
git__free(nfile);
|
392
|
-
return error;
|
393
|
-
}
|
504
|
+
pi->line.num_lines = 1;
|
505
|
+
error = diff_delta_format_with_paths(
|
506
|
+
pi->buf, delta, "Binary files %s and %s differ\n",
|
507
|
+
old_path.ptr, new_path.ptr);
|
394
508
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
pi->nfile = nfile;
|
509
|
+
done:
|
510
|
+
git_buf_free(&old_path);
|
511
|
+
git_buf_free(&new_path);
|
399
512
|
|
400
|
-
return
|
513
|
+
return error;
|
401
514
|
}
|
402
515
|
|
403
516
|
static int diff_print_patch_file_binary(
|
@@ -409,11 +522,11 @@ static int diff_print_patch_file_binary(
|
|
409
522
|
int error;
|
410
523
|
|
411
524
|
if ((pi->flags & GIT_DIFF_SHOW_BINARY) == 0)
|
412
|
-
|
525
|
+
return diff_print_patch_file_binary_noshow(
|
526
|
+
pi, delta, old_pfx, new_pfx);
|
413
527
|
|
414
|
-
if (
|
415
|
-
|
416
|
-
return error;
|
528
|
+
if (binary->new_file.datalen == 0 && binary->old_file.datalen == 0)
|
529
|
+
return 0;
|
417
530
|
|
418
531
|
pre_binary_size = pi->buf->size;
|
419
532
|
git_buf_printf(pi->buf, "GIT binary patch\n");
|
@@ -427,18 +540,14 @@ static int diff_print_patch_file_binary(
|
|
427
540
|
if (error == GIT_EBUFS) {
|
428
541
|
giterr_clear();
|
429
542
|
git_buf_truncate(pi->buf, pre_binary_size);
|
430
|
-
|
543
|
+
|
544
|
+
return diff_print_patch_file_binary_noshow(
|
545
|
+
pi, delta, old_pfx, new_pfx);
|
431
546
|
}
|
432
547
|
}
|
433
548
|
|
434
549
|
pi->line.num_lines++;
|
435
550
|
return error;
|
436
|
-
|
437
|
-
noshow:
|
438
|
-
pi->line.num_lines = 1;
|
439
|
-
return diff_delta_format_with_paths(
|
440
|
-
pi->buf, delta, old_pfx, new_pfx,
|
441
|
-
"Binary files %s%s and %s%s differ\n");
|
442
551
|
}
|
443
552
|
|
444
553
|
static int diff_print_patch_file(
|
@@ -447,15 +556,15 @@ static int diff_print_patch_file(
|
|
447
556
|
int error;
|
448
557
|
diff_print_info *pi = data;
|
449
558
|
const char *oldpfx =
|
450
|
-
pi->
|
559
|
+
pi->old_prefix ? pi->old_prefix : DIFF_OLD_PREFIX_DEFAULT;
|
451
560
|
const char *newpfx =
|
452
|
-
pi->
|
561
|
+
pi->new_prefix ? pi->new_prefix : DIFF_NEW_PREFIX_DEFAULT;
|
453
562
|
|
454
563
|
bool binary = (delta->flags & GIT_DIFF_FLAG_BINARY) ||
|
455
564
|
(pi->flags & GIT_DIFF_FORCE_BINARY);
|
456
565
|
bool show_binary = !!(pi->flags & GIT_DIFF_SHOW_BINARY);
|
457
|
-
int
|
458
|
-
GIT_OID_HEXSZ
|
566
|
+
int id_strlen = binary && show_binary ?
|
567
|
+
GIT_OID_HEXSZ : pi->id_strlen;
|
459
568
|
|
460
569
|
GIT_UNUSED(progress);
|
461
570
|
|
@@ -468,7 +577,7 @@ static int diff_print_patch_file(
|
|
468
577
|
return 0;
|
469
578
|
|
470
579
|
if ((error = git_diff_delta__format_file_header(
|
471
|
-
pi->buf, delta, oldpfx, newpfx,
|
580
|
+
pi->buf, delta, oldpfx, newpfx, id_strlen)) < 0)
|
472
581
|
return error;
|
473
582
|
|
474
583
|
pi->line.origin = GIT_DIFF_LINE_FILE_HDR;
|
@@ -485,9 +594,9 @@ static int diff_print_patch_binary(
|
|
485
594
|
{
|
486
595
|
diff_print_info *pi = data;
|
487
596
|
const char *old_pfx =
|
488
|
-
pi->
|
597
|
+
pi->old_prefix ? pi->old_prefix : DIFF_OLD_PREFIX_DEFAULT;
|
489
598
|
const char *new_pfx =
|
490
|
-
pi->
|
599
|
+
pi->new_prefix ? pi->new_prefix : DIFF_NEW_PREFIX_DEFAULT;
|
491
600
|
int error;
|
492
601
|
|
493
602
|
git_buf_clear(pi->buf);
|
@@ -582,43 +691,11 @@ int git_diff_print(
|
|
582
691
|
giterr_set_after_callback_function(error, "git_diff_print");
|
583
692
|
}
|
584
693
|
|
585
|
-
git__free(pi.nfile);
|
586
|
-
git__free(pi.ofile);
|
587
|
-
|
588
694
|
git_buf_free(&buf);
|
589
695
|
|
590
696
|
return error;
|
591
697
|
}
|
592
698
|
|
593
|
-
/* print a git_patch to an output callback */
|
594
|
-
int git_patch_print(
|
595
|
-
git_patch *patch,
|
596
|
-
git_diff_line_cb print_cb,
|
597
|
-
void *payload)
|
598
|
-
{
|
599
|
-
int error;
|
600
|
-
git_buf temp = GIT_BUF_INIT;
|
601
|
-
diff_print_info pi;
|
602
|
-
|
603
|
-
assert(patch && print_cb);
|
604
|
-
|
605
|
-
if (!(error = diff_print_info_init_frompatch(
|
606
|
-
&pi, &temp, patch,
|
607
|
-
GIT_DIFF_FORMAT_PATCH, print_cb, payload)))
|
608
|
-
{
|
609
|
-
error = git_patch__invoke_callbacks(
|
610
|
-
patch, diff_print_patch_file, diff_print_patch_binary,
|
611
|
-
diff_print_patch_hunk, diff_print_patch_line, &pi);
|
612
|
-
|
613
|
-
if (error) /* make sure error message is set */
|
614
|
-
giterr_set_after_callback_function(error, "git_patch_print");
|
615
|
-
}
|
616
|
-
|
617
|
-
git_buf_free(&temp);
|
618
|
-
|
619
|
-
return error;
|
620
|
-
}
|
621
|
-
|
622
699
|
int git_diff_print_callback__to_buf(
|
623
700
|
const git_diff_delta *delta,
|
624
701
|
const git_diff_hunk *hunk,
|
@@ -659,6 +736,46 @@ int git_diff_print_callback__to_file_handle(
|
|
659
736
|
return 0;
|
660
737
|
}
|
661
738
|
|
739
|
+
/* print a git_diff to a git_buf */
|
740
|
+
int git_diff_to_buf(git_buf *out, git_diff *diff, git_diff_format_t format)
|
741
|
+
{
|
742
|
+
assert(out && diff);
|
743
|
+
git_buf_sanitize(out);
|
744
|
+
return git_diff_print(
|
745
|
+
diff, format, git_diff_print_callback__to_buf, out);
|
746
|
+
}
|
747
|
+
|
748
|
+
/* print a git_patch to an output callback */
|
749
|
+
int git_patch_print(
|
750
|
+
git_patch *patch,
|
751
|
+
git_diff_line_cb print_cb,
|
752
|
+
void *payload)
|
753
|
+
{
|
754
|
+
int error;
|
755
|
+
git_buf temp = GIT_BUF_INIT;
|
756
|
+
diff_print_info pi;
|
757
|
+
|
758
|
+
assert(patch && print_cb);
|
759
|
+
|
760
|
+
if (!(error = diff_print_info_init_frompatch(
|
761
|
+
&pi, &temp, patch,
|
762
|
+
GIT_DIFF_FORMAT_PATCH, print_cb, payload)))
|
763
|
+
{
|
764
|
+
error = git_patch__invoke_callbacks(
|
765
|
+
patch,
|
766
|
+
diff_print_patch_file, diff_print_patch_binary,
|
767
|
+
diff_print_patch_hunk, diff_print_patch_line,
|
768
|
+
&pi);
|
769
|
+
|
770
|
+
if (error) /* make sure error message is set */
|
771
|
+
giterr_set_after_callback_function(error, "git_patch_print");
|
772
|
+
}
|
773
|
+
|
774
|
+
git_buf_free(&temp);
|
775
|
+
|
776
|
+
return error;
|
777
|
+
}
|
778
|
+
|
662
779
|
/* print a git_patch to a git_buf */
|
663
780
|
int git_patch_to_buf(git_buf *out, git_patch *patch)
|
664
781
|
{
|