rugged 0.23.0b2 → 0.23.0b4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/rugged/rugged_blob.c +39 -0
- data/ext/rugged/rugged_diff.c +7 -3
- data/ext/rugged/rugged_index.c +2 -2
- data/ext/rugged/rugged_remote.c +27 -148
- data/ext/rugged/rugged_remote_collection.c +134 -12
- data/ext/rugged/rugged_repo.c +74 -5
- data/ext/rugged/rugged_submodule.c +18 -208
- data/ext/rugged/rugged_submodule_collection.c +148 -0
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/AUTHORS +1 -0
- data/vendor/libgit2/CMakeLists.txt +33 -25
- data/vendor/libgit2/deps/winhttp/winhttp.def +29 -29
- data/vendor/libgit2/include/git2.h +1 -1
- data/vendor/libgit2/include/git2/blob.h +4 -6
- data/vendor/libgit2/include/git2/checkout.h +10 -1
- data/vendor/libgit2/include/git2/clone.h +6 -7
- data/vendor/libgit2/include/git2/commit.h +11 -0
- data/vendor/libgit2/include/git2/cred_helpers.h +2 -2
- data/vendor/libgit2/include/git2/describe.h +1 -1
- data/vendor/libgit2/include/git2/diff.h +68 -11
- data/vendor/libgit2/include/git2/errors.h +4 -1
- data/vendor/libgit2/include/git2/filter.h +16 -0
- data/vendor/libgit2/include/git2/index.h +38 -11
- data/vendor/libgit2/include/git2/odb.h +1 -1
- data/vendor/libgit2/include/git2/odb_backend.h +2 -2
- data/vendor/libgit2/include/git2/remote.h +300 -207
- data/vendor/libgit2/include/git2/reset.h +1 -0
- data/vendor/libgit2/include/git2/stash.h +135 -4
- data/vendor/libgit2/include/git2/status.h +1 -0
- data/vendor/libgit2/include/git2/submodule.h +46 -75
- data/vendor/libgit2/include/git2/sys/odb_backend.h +1 -1
- data/vendor/libgit2/include/git2/sys/stream.h +2 -0
- data/vendor/libgit2/include/git2/sys/transport.h +1 -21
- data/vendor/libgit2/include/git2/transport.h +27 -0
- data/vendor/libgit2/include/git2/types.h +20 -10
- data/vendor/libgit2/include/git2/version.h +3 -3
- data/vendor/libgit2/libgit2.pc.in +4 -2
- data/vendor/libgit2/src/attr.c +2 -1
- data/vendor/libgit2/src/attr_file.c +18 -37
- data/vendor/libgit2/src/blame.c +2 -2
- data/vendor/libgit2/src/blob.c +4 -3
- data/vendor/libgit2/src/branch.c +6 -3
- data/vendor/libgit2/src/buf_text.c +4 -6
- data/vendor/libgit2/src/buf_text.h +1 -2
- data/vendor/libgit2/src/buffer.c +8 -6
- data/vendor/libgit2/src/buffer.h +1 -1
- data/vendor/libgit2/src/cache.c +1 -0
- data/vendor/libgit2/src/checkout.c +34 -20
- data/vendor/libgit2/src/clone.c +29 -29
- data/vendor/libgit2/src/commit.c +65 -0
- data/vendor/libgit2/src/common.h +5 -0
- data/vendor/libgit2/src/config.c +20 -0
- data/vendor/libgit2/src/config.h +6 -0
- data/vendor/libgit2/src/config_file.c +2 -2
- data/vendor/libgit2/src/crlf.c +39 -17
- data/vendor/libgit2/src/curl_stream.c +257 -0
- data/vendor/libgit2/src/curl_stream.h +14 -0
- data/vendor/libgit2/src/diff.c +223 -88
- data/vendor/libgit2/src/diff.h +21 -1
- data/vendor/libgit2/src/diff_file.c +23 -13
- data/vendor/libgit2/src/diff_file.h +4 -2
- data/vendor/libgit2/src/diff_patch.c +266 -71
- data/vendor/libgit2/src/diff_patch.h +36 -0
- data/vendor/libgit2/src/diff_print.c +156 -126
- data/vendor/libgit2/src/diff_tform.c +32 -54
- data/vendor/libgit2/src/fetch.c +27 -10
- data/vendor/libgit2/src/fetch.h +2 -2
- data/vendor/libgit2/src/filebuf.c +1 -1
- data/vendor/libgit2/src/fileops.c +6 -2
- data/vendor/libgit2/src/filter.c +28 -7
- data/vendor/libgit2/src/fnmatch.c +5 -5
- data/vendor/libgit2/src/global.c +16 -0
- data/vendor/libgit2/src/ident.c +2 -2
- data/vendor/libgit2/src/ignore.c +1 -0
- data/vendor/libgit2/src/index.c +338 -80
- data/vendor/libgit2/src/index.h +4 -1
- data/vendor/libgit2/src/indexer.c +19 -5
- data/vendor/libgit2/src/iterator.c +118 -11
- data/vendor/libgit2/src/iterator.h +25 -0
- data/vendor/libgit2/src/merge.c +96 -106
- data/vendor/libgit2/src/merge.h +14 -4
- data/vendor/libgit2/src/netops.c +3 -3
- data/vendor/libgit2/src/odb.c +17 -9
- data/vendor/libgit2/src/odb.h +1 -1
- data/vendor/libgit2/src/odb_loose.c +2 -2
- data/vendor/libgit2/src/odb_pack.c +1 -1
- data/vendor/libgit2/src/openssl_stream.c +118 -27
- data/vendor/libgit2/src/pack-objects.c +28 -0
- data/vendor/libgit2/src/pack-objects.h +1 -0
- data/vendor/libgit2/src/pack.c +18 -10
- data/vendor/libgit2/src/path.c +16 -11
- data/vendor/libgit2/src/path.h +1 -1
- data/vendor/libgit2/src/push.c +26 -42
- data/vendor/libgit2/src/push.h +2 -34
- data/vendor/libgit2/src/rebase.c +1 -1
- data/vendor/libgit2/src/refs.c +1 -1
- data/vendor/libgit2/src/refspec.c +6 -0
- data/vendor/libgit2/src/remote.c +381 -274
- data/vendor/libgit2/src/remote.h +0 -4
- data/vendor/libgit2/src/repository.c +33 -12
- data/vendor/libgit2/src/repository.h +0 -1
- data/vendor/libgit2/src/reset.c +1 -0
- data/vendor/libgit2/src/stash.c +439 -17
- data/vendor/libgit2/src/status.c +6 -0
- data/vendor/libgit2/src/stransport_stream.c +58 -21
- data/vendor/libgit2/src/stream.h +15 -0
- data/vendor/libgit2/src/submodule.c +410 -664
- data/vendor/libgit2/src/submodule.h +0 -24
- data/vendor/libgit2/src/transaction.c +1 -0
- data/vendor/libgit2/src/transports/cred.c +55 -1
- data/vendor/libgit2/src/transports/http.c +18 -2
- data/vendor/libgit2/src/transports/local.c +60 -59
- data/vendor/libgit2/src/transports/smart.h +1 -1
- data/vendor/libgit2/src/transports/smart_protocol.c +11 -11
- data/vendor/libgit2/src/transports/ssh.c +46 -7
- data/vendor/libgit2/src/unix/posix.h +4 -0
- data/vendor/libgit2/src/util.c +9 -9
- data/vendor/libgit2/src/util.h +9 -0
- data/vendor/libgit2/src/win32/posix.h +3 -0
- data/vendor/libgit2/src/win32/posix_w32.c +38 -0
- data/vendor/libgit2/src/win32/w32_util.h +10 -0
- metadata +4 -3
- data/vendor/libgit2/include/git2/push.h +0 -94
|
@@ -0,0 +1,257 @@
|
|
|
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
|
+
#ifdef GIT_CURL
|
|
9
|
+
|
|
10
|
+
#include <curl/curl.h>
|
|
11
|
+
|
|
12
|
+
#include "stream.h"
|
|
13
|
+
#include "git2/transport.h"
|
|
14
|
+
#include "buffer.h"
|
|
15
|
+
#include "vector.h"
|
|
16
|
+
|
|
17
|
+
typedef struct {
|
|
18
|
+
git_stream parent;
|
|
19
|
+
CURL *handle;
|
|
20
|
+
curl_socket_t socket;
|
|
21
|
+
char curl_error[CURL_ERROR_SIZE + 1];
|
|
22
|
+
git_cert_x509 cert_info;
|
|
23
|
+
git_strarray cert_info_strings;
|
|
24
|
+
} curl_stream;
|
|
25
|
+
|
|
26
|
+
static int seterr_curl(curl_stream *s)
|
|
27
|
+
{
|
|
28
|
+
giterr_set(GITERR_NET, "curl error: %s\n", s->curl_error);
|
|
29
|
+
return -1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static int curls_connect(git_stream *stream)
|
|
33
|
+
{
|
|
34
|
+
curl_stream *s = (curl_stream *) stream;
|
|
35
|
+
long sockextr;
|
|
36
|
+
int failed_cert = 0;
|
|
37
|
+
CURLcode res;
|
|
38
|
+
res = curl_easy_perform(s->handle);
|
|
39
|
+
|
|
40
|
+
if (res != CURLE_OK && res != CURLE_PEER_FAILED_VERIFICATION)
|
|
41
|
+
return seterr_curl(s);
|
|
42
|
+
if (res == CURLE_PEER_FAILED_VERIFICATION)
|
|
43
|
+
failed_cert = 1;
|
|
44
|
+
|
|
45
|
+
if ((res = curl_easy_getinfo(s->handle, CURLINFO_LASTSOCKET, &sockextr)) != CURLE_OK)
|
|
46
|
+
return seterr_curl(s);
|
|
47
|
+
|
|
48
|
+
s->socket = sockextr;
|
|
49
|
+
|
|
50
|
+
if (s->parent.encrypted && failed_cert)
|
|
51
|
+
return GIT_ECERTIFICATE;
|
|
52
|
+
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static int curls_certificate(git_cert **out, git_stream *stream)
|
|
57
|
+
{
|
|
58
|
+
int error;
|
|
59
|
+
CURLcode res;
|
|
60
|
+
struct curl_slist *slist;
|
|
61
|
+
struct curl_certinfo *certinfo;
|
|
62
|
+
git_vector strings = GIT_VECTOR_INIT;
|
|
63
|
+
curl_stream *s = (curl_stream *) stream;
|
|
64
|
+
|
|
65
|
+
if ((res = curl_easy_getinfo(s->handle, CURLINFO_CERTINFO, &certinfo)) != CURLE_OK)
|
|
66
|
+
return seterr_curl(s);
|
|
67
|
+
|
|
68
|
+
/* No information is available, can happen with SecureTransport */
|
|
69
|
+
if (certinfo->num_of_certs == 0) {
|
|
70
|
+
s->cert_info.cert_type = GIT_CERT_NONE;
|
|
71
|
+
s->cert_info.data = NULL;
|
|
72
|
+
s->cert_info.len = 0;
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if ((error = git_vector_init(&strings, 8, NULL)) < 0)
|
|
77
|
+
return error;
|
|
78
|
+
|
|
79
|
+
for (slist = certinfo->certinfo[0]; slist; slist = slist->next) {
|
|
80
|
+
char *str = git__strdup(slist->data);
|
|
81
|
+
GITERR_CHECK_ALLOC(str);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Copy the contents of the vector into a strarray so we can expose them */
|
|
85
|
+
s->cert_info_strings.strings = (char **) strings.contents;
|
|
86
|
+
s->cert_info_strings.count = strings.length;
|
|
87
|
+
|
|
88
|
+
s->cert_info.cert_type = GIT_CERT_STRARRAY;
|
|
89
|
+
s->cert_info.data = &s->cert_info_strings;
|
|
90
|
+
s->cert_info.len = strings.length;
|
|
91
|
+
|
|
92
|
+
*out = (git_cert *) &s->cert_info;
|
|
93
|
+
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
static int curls_set_proxy(git_stream *stream, const char *proxy_url)
|
|
98
|
+
{
|
|
99
|
+
CURLcode res;
|
|
100
|
+
curl_stream *s = (curl_stream *) stream;
|
|
101
|
+
|
|
102
|
+
if ((res = curl_easy_setopt(s->handle, CURLOPT_PROXY, proxy_url)) != CURLE_OK)
|
|
103
|
+
return seterr_curl(s);
|
|
104
|
+
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static int wait_for(curl_socket_t fd, bool reading)
|
|
109
|
+
{
|
|
110
|
+
int ret;
|
|
111
|
+
fd_set infd, outfd, errfd;
|
|
112
|
+
|
|
113
|
+
FD_ZERO(&infd);
|
|
114
|
+
FD_ZERO(&outfd);
|
|
115
|
+
FD_ZERO(&errfd);
|
|
116
|
+
|
|
117
|
+
FD_SET(fd, &errfd);
|
|
118
|
+
if (reading)
|
|
119
|
+
FD_SET(fd, &infd);
|
|
120
|
+
else
|
|
121
|
+
FD_SET(fd, &outfd);
|
|
122
|
+
|
|
123
|
+
if ((ret = select(fd + 1, &infd, &outfd, &errfd, NULL)) < 0) {
|
|
124
|
+
giterr_set(GITERR_OS, "error in select");
|
|
125
|
+
return -1;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static ssize_t curls_write(git_stream *stream, const char *data, size_t len, int flags)
|
|
132
|
+
{
|
|
133
|
+
int error;
|
|
134
|
+
size_t off = 0, sent;
|
|
135
|
+
CURLcode res;
|
|
136
|
+
curl_stream *s = (curl_stream *) stream;
|
|
137
|
+
|
|
138
|
+
GIT_UNUSED(flags);
|
|
139
|
+
|
|
140
|
+
do {
|
|
141
|
+
if ((error = wait_for(s->socket, false)) < 0)
|
|
142
|
+
return error;
|
|
143
|
+
|
|
144
|
+
res = curl_easy_send(s->handle, data + off, len - off, &sent);
|
|
145
|
+
if (res == CURLE_OK)
|
|
146
|
+
off += sent;
|
|
147
|
+
} while ((res == CURLE_OK || res == CURLE_AGAIN) && off < len);
|
|
148
|
+
|
|
149
|
+
if (res != CURLE_OK)
|
|
150
|
+
return seterr_curl(s);
|
|
151
|
+
|
|
152
|
+
return len;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
static ssize_t curls_read(git_stream *stream, void *data, size_t len)
|
|
156
|
+
{
|
|
157
|
+
int error;
|
|
158
|
+
size_t read;
|
|
159
|
+
CURLcode res;
|
|
160
|
+
curl_stream *s = (curl_stream *) stream;
|
|
161
|
+
|
|
162
|
+
do {
|
|
163
|
+
if ((error = wait_for(s->socket, true)) < 0)
|
|
164
|
+
return error;
|
|
165
|
+
|
|
166
|
+
res = curl_easy_recv(s->handle, data, len, &read);
|
|
167
|
+
} while (res == CURLE_AGAIN);
|
|
168
|
+
|
|
169
|
+
if (res != CURLE_OK)
|
|
170
|
+
return seterr_curl(s);
|
|
171
|
+
|
|
172
|
+
return read;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
static int curls_close(git_stream *stream)
|
|
176
|
+
{
|
|
177
|
+
curl_stream *s = (curl_stream *) stream;
|
|
178
|
+
|
|
179
|
+
if (!s->handle)
|
|
180
|
+
return 0;
|
|
181
|
+
|
|
182
|
+
curl_easy_cleanup(s->handle);
|
|
183
|
+
s->handle = NULL;
|
|
184
|
+
s->socket = 0;
|
|
185
|
+
|
|
186
|
+
return 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
static void curls_free(git_stream *stream)
|
|
190
|
+
{
|
|
191
|
+
curl_stream *s = (curl_stream *) stream;
|
|
192
|
+
|
|
193
|
+
curls_close(stream);
|
|
194
|
+
git_strarray_free(&s->cert_info_strings);
|
|
195
|
+
git__free(s);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
int git_curl_stream_new(git_stream **out, const char *host, const char *port)
|
|
199
|
+
{
|
|
200
|
+
curl_stream *st;
|
|
201
|
+
CURL *handle;
|
|
202
|
+
int iport = 0, error;
|
|
203
|
+
|
|
204
|
+
st = git__calloc(1, sizeof(curl_stream));
|
|
205
|
+
GITERR_CHECK_ALLOC(st);
|
|
206
|
+
|
|
207
|
+
handle = curl_easy_init();
|
|
208
|
+
if (handle == NULL) {
|
|
209
|
+
giterr_set(GITERR_NET, "failed to create curl handle");
|
|
210
|
+
return -1;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if ((error = git__strtol32(&iport, port, NULL, 10)) < 0)
|
|
214
|
+
return error;
|
|
215
|
+
|
|
216
|
+
curl_easy_setopt(handle, CURLOPT_URL, host);
|
|
217
|
+
curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, st->curl_error);
|
|
218
|
+
curl_easy_setopt(handle, CURLOPT_PORT, iport);
|
|
219
|
+
curl_easy_setopt(handle, CURLOPT_CONNECT_ONLY, 1);
|
|
220
|
+
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 1);
|
|
221
|
+
curl_easy_setopt(handle, CURLOPT_CERTINFO, 1);
|
|
222
|
+
curl_easy_setopt(handle, CURLOPT_HTTPPROXYTUNNEL, 1);
|
|
223
|
+
|
|
224
|
+
/* curl_easy_setopt(handle, CURLOPT_VERBOSE, 1); */
|
|
225
|
+
|
|
226
|
+
st->parent.version = GIT_STREAM_VERSION;
|
|
227
|
+
st->parent.encrypted = 0; /* we don't encrypt ourselves */
|
|
228
|
+
st->parent.proxy_support = 1;
|
|
229
|
+
st->parent.connect = curls_connect;
|
|
230
|
+
st->parent.certificate = curls_certificate;
|
|
231
|
+
st->parent.set_proxy = curls_set_proxy;
|
|
232
|
+
st->parent.read = curls_read;
|
|
233
|
+
st->parent.write = curls_write;
|
|
234
|
+
st->parent.close = curls_close;
|
|
235
|
+
st->parent.free = curls_free;
|
|
236
|
+
st->handle = handle;
|
|
237
|
+
|
|
238
|
+
*out = (git_stream *) st;
|
|
239
|
+
return 0;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
#else
|
|
243
|
+
|
|
244
|
+
#include "stream.h"
|
|
245
|
+
|
|
246
|
+
int git_curl_stream_new(git_stream **out, const char *host, const char *port)
|
|
247
|
+
{
|
|
248
|
+
GIT_UNUSED(out);
|
|
249
|
+
GIT_UNUSED(host);
|
|
250
|
+
GIT_UNUSED(port);
|
|
251
|
+
|
|
252
|
+
giterr_set(GITERR_NET, "curl is not supported in this version");
|
|
253
|
+
return -1;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
#endif
|
|
@@ -0,0 +1,14 @@
|
|
|
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_curl_stream_h__
|
|
8
|
+
#define INCLUDE_curl_stream_h__
|
|
9
|
+
|
|
10
|
+
#include "git2/sys/stream.h"
|
|
11
|
+
|
|
12
|
+
extern int git_curl_stream_new(git_stream **out, const char *host, const char *port);
|
|
13
|
+
|
|
14
|
+
#endif
|
data/vendor/libgit2/src/diff.c
CHANGED
|
@@ -77,11 +77,24 @@ static int diff_insert_delta(
|
|
|
77
77
|
static int diff_delta__from_one(
|
|
78
78
|
git_diff *diff,
|
|
79
79
|
git_delta_t status,
|
|
80
|
-
const git_index_entry *
|
|
80
|
+
const git_index_entry *oitem,
|
|
81
|
+
const git_index_entry *nitem)
|
|
81
82
|
{
|
|
83
|
+
const git_index_entry *entry = nitem;
|
|
84
|
+
bool has_old = false;
|
|
82
85
|
git_diff_delta *delta;
|
|
83
86
|
const char *matched_pathspec;
|
|
84
87
|
|
|
88
|
+
assert((oitem != NULL) ^ (nitem != NULL));
|
|
89
|
+
|
|
90
|
+
if (oitem) {
|
|
91
|
+
entry = oitem;
|
|
92
|
+
has_old = true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE))
|
|
96
|
+
has_old = !has_old;
|
|
97
|
+
|
|
85
98
|
if ((entry->flags & GIT_IDXENTRY_VALID) != 0)
|
|
86
99
|
return 0;
|
|
87
100
|
|
|
@@ -111,20 +124,21 @@ static int diff_delta__from_one(
|
|
|
111
124
|
assert(status != GIT_DELTA_MODIFIED);
|
|
112
125
|
delta->nfiles = 1;
|
|
113
126
|
|
|
114
|
-
if (
|
|
127
|
+
if (has_old) {
|
|
115
128
|
delta->old_file.mode = entry->mode;
|
|
116
129
|
delta->old_file.size = entry->file_size;
|
|
130
|
+
delta->old_file.flags |= GIT_DIFF_FLAG_EXISTS;
|
|
117
131
|
git_oid_cpy(&delta->old_file.id, &entry->id);
|
|
118
132
|
} else /* ADDED, IGNORED, UNTRACKED */ {
|
|
119
133
|
delta->new_file.mode = entry->mode;
|
|
120
134
|
delta->new_file.size = entry->file_size;
|
|
135
|
+
delta->new_file.flags |= GIT_DIFF_FLAG_EXISTS;
|
|
121
136
|
git_oid_cpy(&delta->new_file.id, &entry->id);
|
|
122
137
|
}
|
|
123
138
|
|
|
124
139
|
delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
|
125
140
|
|
|
126
|
-
if (delta->
|
|
127
|
-
!git_oid_iszero(&delta->new_file.id))
|
|
141
|
+
if (has_old || !git_oid_iszero(&delta->new_file.id))
|
|
128
142
|
delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
|
129
143
|
|
|
130
144
|
return diff_insert_delta(diff, delta, matched_pathspec);
|
|
@@ -137,9 +151,10 @@ static int diff_delta__from_two(
|
|
|
137
151
|
uint32_t old_mode,
|
|
138
152
|
const git_index_entry *new_entry,
|
|
139
153
|
uint32_t new_mode,
|
|
140
|
-
git_oid *
|
|
154
|
+
const git_oid *new_id,
|
|
141
155
|
const char *matched_pathspec)
|
|
142
156
|
{
|
|
157
|
+
const git_oid *old_id = &old_entry->id;
|
|
143
158
|
git_diff_delta *delta;
|
|
144
159
|
const char *canonical_path = old_entry->path;
|
|
145
160
|
|
|
@@ -147,38 +162,45 @@ static int diff_delta__from_two(
|
|
|
147
162
|
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNMODIFIED))
|
|
148
163
|
return 0;
|
|
149
164
|
|
|
165
|
+
if (!new_id)
|
|
166
|
+
new_id = &new_entry->id;
|
|
167
|
+
|
|
150
168
|
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) {
|
|
151
169
|
uint32_t temp_mode = old_mode;
|
|
152
170
|
const git_index_entry *temp_entry = old_entry;
|
|
171
|
+
const git_oid *temp_id = old_id;
|
|
172
|
+
|
|
153
173
|
old_entry = new_entry;
|
|
154
174
|
new_entry = temp_entry;
|
|
155
175
|
old_mode = new_mode;
|
|
156
176
|
new_mode = temp_mode;
|
|
177
|
+
old_id = new_id;
|
|
178
|
+
new_id = temp_id;
|
|
157
179
|
}
|
|
158
180
|
|
|
159
181
|
delta = diff_delta__alloc(diff, status, canonical_path);
|
|
160
182
|
GITERR_CHECK_ALLOC(delta);
|
|
161
183
|
delta->nfiles = 2;
|
|
162
184
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
185
|
+
if (!git_index_entry_is_conflict(old_entry)) {
|
|
186
|
+
delta->old_file.size = old_entry->file_size;
|
|
187
|
+
delta->old_file.mode = old_mode;
|
|
188
|
+
git_oid_cpy(&delta->old_file.id, old_id);
|
|
189
|
+
delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID |
|
|
190
|
+
GIT_DIFF_FLAG_EXISTS;
|
|
191
|
+
}
|
|
167
192
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
193
|
+
if (!git_index_entry_is_conflict(new_entry)) {
|
|
194
|
+
git_oid_cpy(&delta->new_file.id, new_id);
|
|
195
|
+
delta->new_file.size = new_entry->file_size;
|
|
196
|
+
delta->new_file.mode = new_mode;
|
|
197
|
+
delta->old_file.flags |= GIT_DIFF_FLAG_EXISTS;
|
|
198
|
+
delta->new_file.flags |= GIT_DIFF_FLAG_EXISTS;
|
|
171
199
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
git_oid_cpy(&delta->old_file.id, new_oid);
|
|
175
|
-
else
|
|
176
|
-
git_oid_cpy(&delta->new_file.id, new_oid);
|
|
200
|
+
if (!git_oid_iszero(&new_entry->id))
|
|
201
|
+
delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
|
177
202
|
}
|
|
178
203
|
|
|
179
|
-
if (new_oid || !git_oid_iszero(&new_entry->id))
|
|
180
|
-
delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
|
181
|
-
|
|
182
204
|
return diff_insert_delta(diff, delta, matched_pathspec);
|
|
183
205
|
}
|
|
184
206
|
|
|
@@ -327,6 +349,22 @@ static const char *diff_mnemonic_prefix(
|
|
|
327
349
|
return pfx;
|
|
328
350
|
}
|
|
329
351
|
|
|
352
|
+
static int diff_entry_cmp(const void *a, const void *b)
|
|
353
|
+
{
|
|
354
|
+
const git_index_entry *entry_a = a;
|
|
355
|
+
const git_index_entry *entry_b = b;
|
|
356
|
+
|
|
357
|
+
return strcmp(entry_a->path, entry_b->path);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
static int diff_entry_icmp(const void *a, const void *b)
|
|
361
|
+
{
|
|
362
|
+
const git_index_entry *entry_a = a;
|
|
363
|
+
const git_index_entry *entry_b = b;
|
|
364
|
+
|
|
365
|
+
return strcasecmp(entry_a->path, entry_b->path);
|
|
366
|
+
}
|
|
367
|
+
|
|
330
368
|
static void diff_set_ignore_case(git_diff *diff, bool ignore_case)
|
|
331
369
|
{
|
|
332
370
|
if (!ignore_case) {
|
|
@@ -335,7 +373,7 @@ static void diff_set_ignore_case(git_diff *diff, bool ignore_case)
|
|
|
335
373
|
diff->strcomp = git__strcmp;
|
|
336
374
|
diff->strncomp = git__strncmp;
|
|
337
375
|
diff->pfxcomp = git__prefixcmp;
|
|
338
|
-
diff->entrycomp =
|
|
376
|
+
diff->entrycomp = diff_entry_cmp;
|
|
339
377
|
|
|
340
378
|
git_vector_set_cmp(&diff->deltas, git_diff_delta__cmp);
|
|
341
379
|
} else {
|
|
@@ -344,7 +382,7 @@ static void diff_set_ignore_case(git_diff *diff, bool ignore_case)
|
|
|
344
382
|
diff->strcomp = git__strcasecmp;
|
|
345
383
|
diff->strncomp = git__strncasecmp;
|
|
346
384
|
diff->pfxcomp = git__prefixcmp_icase;
|
|
347
|
-
diff->entrycomp =
|
|
385
|
+
diff->entrycomp = diff_entry_icmp;
|
|
348
386
|
|
|
349
387
|
git_vector_set_cmp(&diff->deltas, git_diff_delta__casecmp);
|
|
350
388
|
}
|
|
@@ -532,7 +570,7 @@ int git_diff__oid_for_file(
|
|
|
532
570
|
git_oid *out,
|
|
533
571
|
git_diff *diff,
|
|
534
572
|
const char *path,
|
|
535
|
-
uint16_t
|
|
573
|
+
uint16_t mode,
|
|
536
574
|
git_off_t size)
|
|
537
575
|
{
|
|
538
576
|
git_index_entry entry;
|
|
@@ -542,13 +580,14 @@ int git_diff__oid_for_file(
|
|
|
542
580
|
entry.file_size = size;
|
|
543
581
|
entry.path = (char *)path;
|
|
544
582
|
|
|
545
|
-
return git_diff__oid_for_entry(out, diff, &entry, NULL);
|
|
583
|
+
return git_diff__oid_for_entry(out, diff, &entry, mode, NULL);
|
|
546
584
|
}
|
|
547
585
|
|
|
548
586
|
int git_diff__oid_for_entry(
|
|
549
587
|
git_oid *out,
|
|
550
588
|
git_diff *diff,
|
|
551
589
|
const git_index_entry *src,
|
|
590
|
+
uint16_t mode,
|
|
552
591
|
const git_oid *update_match)
|
|
553
592
|
{
|
|
554
593
|
int error = 0;
|
|
@@ -562,7 +601,7 @@ int git_diff__oid_for_entry(
|
|
|
562
601
|
&full_path, git_repository_workdir(diff->repo), entry.path) < 0)
|
|
563
602
|
return -1;
|
|
564
603
|
|
|
565
|
-
if (!
|
|
604
|
+
if (!mode) {
|
|
566
605
|
struct stat st;
|
|
567
606
|
|
|
568
607
|
diff->perf.stat_calls++;
|
|
@@ -578,7 +617,7 @@ int git_diff__oid_for_entry(
|
|
|
578
617
|
}
|
|
579
618
|
|
|
580
619
|
/* calculate OID for file if possible */
|
|
581
|
-
if (S_ISGITLINK(
|
|
620
|
+
if (S_ISGITLINK(mode)) {
|
|
582
621
|
git_submodule *sm;
|
|
583
622
|
|
|
584
623
|
if (!git_submodule_lookup(&sm, diff->repo, entry.path)) {
|
|
@@ -592,7 +631,7 @@ int git_diff__oid_for_entry(
|
|
|
592
631
|
*/
|
|
593
632
|
giterr_clear();
|
|
594
633
|
}
|
|
595
|
-
} else if (S_ISLNK(
|
|
634
|
+
} else if (S_ISLNK(mode)) {
|
|
596
635
|
error = git_odb__hashlink(out, full_path.ptr);
|
|
597
636
|
diff->perf.oid_calculations++;
|
|
598
637
|
} else if (!git__is_sizet(entry.file_size)) {
|
|
@@ -619,10 +658,15 @@ int git_diff__oid_for_entry(
|
|
|
619
658
|
/* update index for entry if requested */
|
|
620
659
|
if (!error && update_match && git_oid_equal(out, update_match)) {
|
|
621
660
|
git_index *idx;
|
|
661
|
+
git_index_entry updated_entry;
|
|
662
|
+
|
|
663
|
+
memcpy(&updated_entry, &entry, sizeof(git_index_entry));
|
|
664
|
+
updated_entry.mode = mode;
|
|
665
|
+
git_oid_cpy(&updated_entry.id, out);
|
|
622
666
|
|
|
623
667
|
if (!(error = git_repository_index__weakptr(&idx, diff->repo))) {
|
|
624
|
-
|
|
625
|
-
|
|
668
|
+
error = git_index_add(idx, &updated_entry);
|
|
669
|
+
diff->index_updated = true;
|
|
626
670
|
}
|
|
627
671
|
}
|
|
628
672
|
|
|
@@ -731,47 +775,54 @@ static int maybe_modified(
|
|
|
731
775
|
new_is_workdir)
|
|
732
776
|
nmode = (nmode & ~MODE_BITS_MASK) | (omode & MODE_BITS_MASK);
|
|
733
777
|
|
|
778
|
+
/* if one side is a conflict, mark the whole delta as conflicted */
|
|
779
|
+
if (git_index_entry_is_conflict(oitem) ||
|
|
780
|
+
git_index_entry_is_conflict(nitem)) {
|
|
781
|
+
status = GIT_DELTA_CONFLICTED;
|
|
782
|
+
|
|
734
783
|
/* support "assume unchanged" (poorly, b/c we still stat everything) */
|
|
735
|
-
if ((oitem->flags & GIT_IDXENTRY_VALID) != 0)
|
|
784
|
+
} else if ((oitem->flags & GIT_IDXENTRY_VALID) != 0) {
|
|
736
785
|
status = GIT_DELTA_UNMODIFIED;
|
|
737
786
|
|
|
738
787
|
/* support "skip worktree" index bit */
|
|
739
|
-
else if ((oitem->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE) != 0)
|
|
788
|
+
} else if ((oitem->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE) != 0) {
|
|
740
789
|
status = GIT_DELTA_UNMODIFIED;
|
|
741
790
|
|
|
742
791
|
/* if basic type of file changed, then split into delete and add */
|
|
743
|
-
else if (GIT_MODE_TYPE(omode) != GIT_MODE_TYPE(nmode)) {
|
|
744
|
-
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE))
|
|
792
|
+
} else if (GIT_MODE_TYPE(omode) != GIT_MODE_TYPE(nmode)) {
|
|
793
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE)) {
|
|
745
794
|
status = GIT_DELTA_TYPECHANGE;
|
|
795
|
+
}
|
|
796
|
+
|
|
746
797
|
else if (nmode == GIT_FILEMODE_UNREADABLE) {
|
|
747
|
-
if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem)))
|
|
748
|
-
error = diff_delta__from_one(diff, GIT_DELTA_UNREADABLE, nitem);
|
|
798
|
+
if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem, NULL)))
|
|
799
|
+
error = diff_delta__from_one(diff, GIT_DELTA_UNREADABLE, NULL, nitem);
|
|
749
800
|
return error;
|
|
750
801
|
}
|
|
802
|
+
|
|
751
803
|
else {
|
|
752
|
-
if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem)))
|
|
753
|
-
error = diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem);
|
|
804
|
+
if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem, NULL)))
|
|
805
|
+
error = diff_delta__from_one(diff, GIT_DELTA_ADDED, NULL, nitem);
|
|
754
806
|
return error;
|
|
755
807
|
}
|
|
756
|
-
}
|
|
757
808
|
|
|
758
809
|
/* if oids and modes match (and are valid), then file is unmodified */
|
|
759
|
-
else if (git_oid_equal(&oitem->id, &nitem->id) &&
|
|
810
|
+
} else if (git_oid_equal(&oitem->id, &nitem->id) &&
|
|
760
811
|
omode == nmode &&
|
|
761
|
-
!git_oid_iszero(&oitem->id))
|
|
812
|
+
!git_oid_iszero(&oitem->id)) {
|
|
762
813
|
status = GIT_DELTA_UNMODIFIED;
|
|
763
814
|
|
|
764
815
|
/* if we have an unknown OID and a workdir iterator, then check some
|
|
765
816
|
* circumstances that can accelerate things or need special handling
|
|
766
817
|
*/
|
|
767
|
-
else if (git_oid_iszero(&nitem->id) && new_is_workdir) {
|
|
818
|
+
} else if (git_oid_iszero(&nitem->id) && new_is_workdir) {
|
|
768
819
|
bool use_ctime = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_CTIME) != 0);
|
|
769
820
|
bool use_nanos = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_NANOSECS) != 0);
|
|
821
|
+
git_index *index;
|
|
822
|
+
git_iterator_index(&index, info->new_iter);
|
|
770
823
|
|
|
771
824
|
status = GIT_DELTA_UNMODIFIED;
|
|
772
825
|
|
|
773
|
-
/* TODO: add check against index file st_mtime to avoid racy-git */
|
|
774
|
-
|
|
775
826
|
if (S_ISGITLINK(nmode)) {
|
|
776
827
|
if ((error = maybe_modified_submodule(&status, &noid, diff, info)) < 0)
|
|
777
828
|
return error;
|
|
@@ -790,17 +841,18 @@ static int maybe_modified(
|
|
|
790
841
|
!diff_time_eq(&oitem->ctime, &nitem->ctime, use_nanos)) ||
|
|
791
842
|
oitem->ino != nitem->ino ||
|
|
792
843
|
oitem->uid != nitem->uid ||
|
|
793
|
-
oitem->gid != nitem->gid
|
|
844
|
+
oitem->gid != nitem->gid ||
|
|
845
|
+
(index && nitem->mtime.seconds >= index->stamp.mtime))
|
|
794
846
|
{
|
|
795
847
|
status = GIT_DELTA_MODIFIED;
|
|
796
848
|
modified_uncertain = true;
|
|
797
849
|
}
|
|
798
|
-
}
|
|
799
850
|
|
|
800
851
|
/* if mode is GITLINK and submodules are ignored, then skip */
|
|
801
|
-
else if (S_ISGITLINK(nmode) &&
|
|
802
|
-
DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES))
|
|
852
|
+
} else if (S_ISGITLINK(nmode) &&
|
|
853
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES)) {
|
|
803
854
|
status = GIT_DELTA_UNMODIFIED;
|
|
855
|
+
}
|
|
804
856
|
|
|
805
857
|
/* if we got here and decided that the files are modified, but we
|
|
806
858
|
* haven't calculated the OID of the new item, then calculate it now
|
|
@@ -809,8 +861,9 @@ static int maybe_modified(
|
|
|
809
861
|
const git_oid *update_check =
|
|
810
862
|
DIFF_FLAG_IS_SET(diff, GIT_DIFF_UPDATE_INDEX) && omode == nmode ?
|
|
811
863
|
&oitem->id : NULL;
|
|
864
|
+
|
|
812
865
|
if ((error = git_diff__oid_for_entry(
|
|
813
|
-
&noid, diff, nitem, update_check)) < 0)
|
|
866
|
+
&noid, diff, nitem, nmode, update_check)) < 0)
|
|
814
867
|
return error;
|
|
815
868
|
|
|
816
869
|
/* if oid matches, then mark unmodified (except submodules, where
|
|
@@ -830,8 +883,9 @@ static int maybe_modified(
|
|
|
830
883
|
DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_CASECHANGE) &&
|
|
831
884
|
strcmp(oitem->path, nitem->path) != 0) {
|
|
832
885
|
|
|
833
|
-
if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem)))
|
|
834
|
-
error = diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem);
|
|
886
|
+
if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem, NULL)))
|
|
887
|
+
error = diff_delta__from_one(diff, GIT_DELTA_ADDED, NULL, nitem);
|
|
888
|
+
|
|
835
889
|
return error;
|
|
836
890
|
}
|
|
837
891
|
|
|
@@ -857,6 +911,84 @@ static bool entry_is_prefixed(
|
|
|
857
911
|
item->path[pathlen] == '/');
|
|
858
912
|
}
|
|
859
913
|
|
|
914
|
+
static int iterator_current(
|
|
915
|
+
const git_index_entry **entry,
|
|
916
|
+
git_iterator *iterator)
|
|
917
|
+
{
|
|
918
|
+
int error;
|
|
919
|
+
|
|
920
|
+
if ((error = git_iterator_current(entry, iterator)) == GIT_ITEROVER) {
|
|
921
|
+
*entry = NULL;
|
|
922
|
+
error = 0;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
return error;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
static int iterator_advance(
|
|
929
|
+
const git_index_entry **entry,
|
|
930
|
+
git_iterator *iterator)
|
|
931
|
+
{
|
|
932
|
+
const git_index_entry *prev_entry = *entry;
|
|
933
|
+
int cmp, error;
|
|
934
|
+
|
|
935
|
+
/* if we're looking for conflicts, we only want to report
|
|
936
|
+
* one conflict for each file, instead of all three sides.
|
|
937
|
+
* so if this entry is a conflict for this file, and the
|
|
938
|
+
* previous one was a conflict for the same file, skip it.
|
|
939
|
+
*/
|
|
940
|
+
while ((error = git_iterator_advance(entry, iterator)) == 0) {
|
|
941
|
+
if (!(iterator->flags & GIT_ITERATOR_INCLUDE_CONFLICTS) ||
|
|
942
|
+
!git_index_entry_is_conflict(prev_entry) ||
|
|
943
|
+
!git_index_entry_is_conflict(*entry))
|
|
944
|
+
break;
|
|
945
|
+
|
|
946
|
+
cmp = (iterator->flags & GIT_ITERATOR_IGNORE_CASE) ?
|
|
947
|
+
strcasecmp(prev_entry->path, (*entry)->path) :
|
|
948
|
+
strcmp(prev_entry->path, (*entry)->path);
|
|
949
|
+
|
|
950
|
+
if (cmp)
|
|
951
|
+
break;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
if (error == GIT_ITEROVER) {
|
|
955
|
+
*entry = NULL;
|
|
956
|
+
error = 0;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
return error;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
static int iterator_advance_into(
|
|
963
|
+
const git_index_entry **entry,
|
|
964
|
+
git_iterator *iterator)
|
|
965
|
+
{
|
|
966
|
+
int error;
|
|
967
|
+
|
|
968
|
+
if ((error = git_iterator_advance_into(entry, iterator)) == GIT_ITEROVER) {
|
|
969
|
+
*entry = NULL;
|
|
970
|
+
error = 0;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
return error;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
static int iterator_advance_over_with_status(
|
|
977
|
+
const git_index_entry **entry,
|
|
978
|
+
git_iterator_status_t *status,
|
|
979
|
+
git_iterator *iterator)
|
|
980
|
+
{
|
|
981
|
+
int error;
|
|
982
|
+
|
|
983
|
+
if ((error = git_iterator_advance_over_with_status(
|
|
984
|
+
entry, status, iterator)) == GIT_ITEROVER) {
|
|
985
|
+
*entry = NULL;
|
|
986
|
+
error = 0;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
return error;
|
|
990
|
+
}
|
|
991
|
+
|
|
860
992
|
static int handle_unmatched_new_item(
|
|
861
993
|
git_diff *diff, diff_in_progress *info)
|
|
862
994
|
{
|
|
@@ -868,8 +1000,12 @@ static int handle_unmatched_new_item(
|
|
|
868
1000
|
/* check if this is a prefix of the other side */
|
|
869
1001
|
contains_oitem = entry_is_prefixed(diff, info->oitem, nitem);
|
|
870
1002
|
|
|
1003
|
+
/* update delta_type if this item is conflicted */
|
|
1004
|
+
if (git_index_entry_is_conflict(nitem))
|
|
1005
|
+
delta_type = GIT_DELTA_CONFLICTED;
|
|
1006
|
+
|
|
871
1007
|
/* update delta_type if this item is ignored */
|
|
872
|
-
if (git_iterator_current_is_ignored(info->new_iter))
|
|
1008
|
+
else if (git_iterator_current_is_ignored(info->new_iter))
|
|
873
1009
|
delta_type = GIT_DELTA_IGNORED;
|
|
874
1010
|
|
|
875
1011
|
if (nitem->mode == GIT_FILEMODE_TREE) {
|
|
@@ -904,18 +1040,17 @@ static int handle_unmatched_new_item(
|
|
|
904
1040
|
git_iterator_status_t untracked_state;
|
|
905
1041
|
|
|
906
1042
|
/* attempt to insert record for this directory */
|
|
907
|
-
if ((error = diff_delta__from_one(diff, delta_type, nitem)) != 0)
|
|
1043
|
+
if ((error = diff_delta__from_one(diff, delta_type, NULL, nitem)) != 0)
|
|
908
1044
|
return error;
|
|
909
1045
|
|
|
910
1046
|
/* if delta wasn't created (because of rules), just skip ahead */
|
|
911
1047
|
last = diff_delta__last_for_item(diff, nitem);
|
|
912
1048
|
if (!last)
|
|
913
|
-
return
|
|
1049
|
+
return iterator_advance(&info->nitem, info->new_iter);
|
|
914
1050
|
|
|
915
1051
|
/* iterate into dir looking for an actual untracked file */
|
|
916
|
-
if ((error =
|
|
917
|
-
&info->nitem, &untracked_state, info->new_iter)) < 0
|
|
918
|
-
error != GIT_ITEROVER)
|
|
1052
|
+
if ((error = iterator_advance_over_with_status(
|
|
1053
|
+
&info->nitem, &untracked_state, info->new_iter)) < 0)
|
|
919
1054
|
return error;
|
|
920
1055
|
|
|
921
1056
|
/* if we found nothing or just ignored items, update the record */
|
|
@@ -935,7 +1070,7 @@ static int handle_unmatched_new_item(
|
|
|
935
1070
|
|
|
936
1071
|
/* try to advance into directory if necessary */
|
|
937
1072
|
if (recurse_into_dir) {
|
|
938
|
-
error =
|
|
1073
|
+
error = iterator_advance_into(&info->nitem, info->new_iter);
|
|
939
1074
|
|
|
940
1075
|
/* if real error or no error, proceed with iteration */
|
|
941
1076
|
if (error != GIT_ENOTFOUND)
|
|
@@ -946,7 +1081,7 @@ static int handle_unmatched_new_item(
|
|
|
946
1081
|
* it or ignore it
|
|
947
1082
|
*/
|
|
948
1083
|
if (contains_oitem)
|
|
949
|
-
return
|
|
1084
|
+
return iterator_advance(&info->nitem, info->new_iter);
|
|
950
1085
|
delta_type = GIT_DELTA_IGNORED;
|
|
951
1086
|
}
|
|
952
1087
|
}
|
|
@@ -955,10 +1090,12 @@ static int handle_unmatched_new_item(
|
|
|
955
1090
|
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_RECURSE_IGNORED_DIRS) &&
|
|
956
1091
|
git_iterator_current_tree_is_ignored(info->new_iter))
|
|
957
1092
|
/* item contained in ignored directory, so skip over it */
|
|
958
|
-
return
|
|
1093
|
+
return iterator_advance(&info->nitem, info->new_iter);
|
|
959
1094
|
|
|
960
|
-
else if (info->new_iter->type != GIT_ITERATOR_TYPE_WORKDIR)
|
|
961
|
-
delta_type
|
|
1095
|
+
else if (info->new_iter->type != GIT_ITERATOR_TYPE_WORKDIR) {
|
|
1096
|
+
if (delta_type != GIT_DELTA_CONFLICTED)
|
|
1097
|
+
delta_type = GIT_DELTA_ADDED;
|
|
1098
|
+
}
|
|
962
1099
|
|
|
963
1100
|
else if (nitem->mode == GIT_FILEMODE_COMMIT) {
|
|
964
1101
|
/* ignore things that are not actual submodules */
|
|
@@ -968,12 +1105,12 @@ static int handle_unmatched_new_item(
|
|
|
968
1105
|
|
|
969
1106
|
/* if this contains a tracked item, treat as normal TREE */
|
|
970
1107
|
if (contains_oitem) {
|
|
971
|
-
error =
|
|
1108
|
+
error = iterator_advance_into(&info->nitem, info->new_iter);
|
|
972
1109
|
if (error != GIT_ENOTFOUND)
|
|
973
1110
|
return error;
|
|
974
1111
|
|
|
975
1112
|
giterr_clear();
|
|
976
|
-
return
|
|
1113
|
+
return iterator_advance(&info->nitem, info->new_iter);
|
|
977
1114
|
}
|
|
978
1115
|
}
|
|
979
1116
|
}
|
|
@@ -986,7 +1123,7 @@ static int handle_unmatched_new_item(
|
|
|
986
1123
|
}
|
|
987
1124
|
|
|
988
1125
|
/* Actually create the record for this item if necessary */
|
|
989
|
-
if ((error = diff_delta__from_one(diff, delta_type, nitem)) != 0)
|
|
1126
|
+
if ((error = diff_delta__from_one(diff, delta_type, NULL, nitem)) != 0)
|
|
990
1127
|
return error;
|
|
991
1128
|
|
|
992
1129
|
/* If user requested TYPECHANGE records, then check for that instead of
|
|
@@ -1004,14 +1141,20 @@ static int handle_unmatched_new_item(
|
|
|
1004
1141
|
}
|
|
1005
1142
|
}
|
|
1006
1143
|
|
|
1007
|
-
return
|
|
1144
|
+
return iterator_advance(&info->nitem, info->new_iter);
|
|
1008
1145
|
}
|
|
1009
1146
|
|
|
1010
1147
|
static int handle_unmatched_old_item(
|
|
1011
1148
|
git_diff *diff, diff_in_progress *info)
|
|
1012
1149
|
{
|
|
1013
|
-
|
|
1014
|
-
|
|
1150
|
+
git_delta_t delta_type = GIT_DELTA_DELETED;
|
|
1151
|
+
int error;
|
|
1152
|
+
|
|
1153
|
+
/* update delta_type if this item is conflicted */
|
|
1154
|
+
if (git_index_entry_is_conflict(info->oitem))
|
|
1155
|
+
delta_type = GIT_DELTA_CONFLICTED;
|
|
1156
|
+
|
|
1157
|
+
if ((error = diff_delta__from_one(diff, delta_type, info->oitem, NULL)) < 0)
|
|
1015
1158
|
return error;
|
|
1016
1159
|
|
|
1017
1160
|
/* if we are generating TYPECHANGE records then check for that
|
|
@@ -1033,10 +1176,10 @@ static int handle_unmatched_old_item(
|
|
|
1033
1176
|
*/
|
|
1034
1177
|
if (S_ISDIR(info->nitem->mode) &&
|
|
1035
1178
|
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_RECURSE_UNTRACKED_DIRS))
|
|
1036
|
-
return
|
|
1179
|
+
return iterator_advance(&info->nitem, info->new_iter);
|
|
1037
1180
|
}
|
|
1038
1181
|
|
|
1039
|
-
return
|
|
1182
|
+
return iterator_advance(&info->oitem, info->old_iter);
|
|
1040
1183
|
}
|
|
1041
1184
|
|
|
1042
1185
|
static int handle_matched_item(
|
|
@@ -1047,9 +1190,8 @@ static int handle_matched_item(
|
|
|
1047
1190
|
if ((error = maybe_modified(diff, info)) < 0)
|
|
1048
1191
|
return error;
|
|
1049
1192
|
|
|
1050
|
-
if (!(error =
|
|
1051
|
-
error
|
|
1052
|
-
error = git_iterator_advance(&info->nitem, info->new_iter);
|
|
1193
|
+
if (!(error = iterator_advance(&info->oitem, info->old_iter)))
|
|
1194
|
+
error = iterator_advance(&info->nitem, info->new_iter);
|
|
1053
1195
|
|
|
1054
1196
|
return error;
|
|
1055
1197
|
}
|
|
@@ -1085,13 +1227,9 @@ int git_diff__from_iterators(
|
|
|
1085
1227
|
if ((error = diff_list_apply_options(diff, opts)) < 0)
|
|
1086
1228
|
goto cleanup;
|
|
1087
1229
|
|
|
1088
|
-
if ((error =
|
|
1089
|
-
error
|
|
1230
|
+
if ((error = iterator_current(&info.oitem, old_iter)) < 0 ||
|
|
1231
|
+
(error = iterator_current(&info.nitem, new_iter)) < 0)
|
|
1090
1232
|
goto cleanup;
|
|
1091
|
-
if ((error = git_iterator_current(&info.nitem, new_iter)) < 0 &&
|
|
1092
|
-
error != GIT_ITEROVER)
|
|
1093
|
-
goto cleanup;
|
|
1094
|
-
error = 0;
|
|
1095
1233
|
|
|
1096
1234
|
/* run iterators building diffs */
|
|
1097
1235
|
while (!error && (info.oitem || info.nitem)) {
|
|
@@ -1113,10 +1251,6 @@ int git_diff__from_iterators(
|
|
|
1113
1251
|
*/
|
|
1114
1252
|
else
|
|
1115
1253
|
error = handle_matched_item(diff, &info);
|
|
1116
|
-
|
|
1117
|
-
/* because we are iterating over two lists, ignore ITEROVER */
|
|
1118
|
-
if (error == GIT_ITEROVER)
|
|
1119
|
-
error = 0;
|
|
1120
1254
|
}
|
|
1121
1255
|
|
|
1122
1256
|
diff->perf.stat_calls += old_iter->stat_calls + new_iter->stat_calls;
|
|
@@ -1186,6 +1320,8 @@ int git_diff_tree_to_index(
|
|
|
1186
1320
|
{
|
|
1187
1321
|
int error = 0;
|
|
1188
1322
|
bool index_ignore_case = false;
|
|
1323
|
+
git_iterator_flag_t iflag = GIT_ITERATOR_DONT_IGNORE_CASE |
|
|
1324
|
+
GIT_ITERATOR_INCLUDE_CONFLICTS;
|
|
1189
1325
|
|
|
1190
1326
|
assert(diff && repo);
|
|
1191
1327
|
|
|
@@ -1195,10 +1331,8 @@ int git_diff_tree_to_index(
|
|
|
1195
1331
|
index_ignore_case = index->ignore_case;
|
|
1196
1332
|
|
|
1197
1333
|
DIFF_FROM_ITERATORS(
|
|
1198
|
-
git_iterator_for_tree(
|
|
1199
|
-
|
|
1200
|
-
git_iterator_for_index(
|
|
1201
|
-
&b, index, GIT_ITERATOR_DONT_IGNORE_CASE, pfx, pfx)
|
|
1334
|
+
git_iterator_for_tree(&a, old_tree, iflag, pfx, pfx),
|
|
1335
|
+
git_iterator_for_index(&b, index, iflag, pfx, pfx)
|
|
1202
1336
|
);
|
|
1203
1337
|
|
|
1204
1338
|
/* if index is in case-insensitive order, re-sort deltas to match */
|
|
@@ -1222,12 +1356,13 @@ int git_diff_index_to_workdir(
|
|
|
1222
1356
|
return error;
|
|
1223
1357
|
|
|
1224
1358
|
DIFF_FROM_ITERATORS(
|
|
1225
|
-
git_iterator_for_index(
|
|
1359
|
+
git_iterator_for_index(
|
|
1360
|
+
&a, index, GIT_ITERATOR_INCLUDE_CONFLICTS, pfx, pfx),
|
|
1226
1361
|
git_iterator_for_workdir(
|
|
1227
1362
|
&b, repo, index, NULL, GIT_ITERATOR_DONT_AUTOEXPAND, pfx, pfx)
|
|
1228
1363
|
);
|
|
1229
1364
|
|
|
1230
|
-
if (!error && DIFF_FLAG_IS_SET(*diff, GIT_DIFF_UPDATE_INDEX))
|
|
1365
|
+
if (!error && DIFF_FLAG_IS_SET(*diff, GIT_DIFF_UPDATE_INDEX) && (*diff)->index_updated)
|
|
1231
1366
|
error = git_index_write(index);
|
|
1232
1367
|
|
|
1233
1368
|
return error;
|