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
data/vendor/libgit2/src/status.c
CHANGED
|
@@ -44,6 +44,9 @@ static unsigned int index_delta2status(const git_diff_delta *head2idx)
|
|
|
44
44
|
case GIT_DELTA_TYPECHANGE:
|
|
45
45
|
st = GIT_STATUS_INDEX_TYPECHANGE;
|
|
46
46
|
break;
|
|
47
|
+
case GIT_DELTA_CONFLICTED:
|
|
48
|
+
st = GIT_STATUS_CONFLICTED;
|
|
49
|
+
break;
|
|
47
50
|
default:
|
|
48
51
|
break;
|
|
49
52
|
}
|
|
@@ -102,6 +105,9 @@ static unsigned int workdir_delta2status(
|
|
|
102
105
|
case GIT_DELTA_TYPECHANGE:
|
|
103
106
|
st = GIT_STATUS_WT_TYPECHANGE;
|
|
104
107
|
break;
|
|
108
|
+
case GIT_DELTA_CONFLICTED:
|
|
109
|
+
st = GIT_STATUS_CONFLICTED;
|
|
110
|
+
break;
|
|
105
111
|
default:
|
|
106
112
|
break;
|
|
107
113
|
}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
#include "git2/transport.h"
|
|
15
15
|
|
|
16
16
|
#include "socket_stream.h"
|
|
17
|
+
#include "curl_stream.h"
|
|
17
18
|
|
|
18
19
|
int stransport_error(OSStatus ret)
|
|
19
20
|
{
|
|
@@ -24,11 +25,16 @@ int stransport_error(OSStatus ret)
|
|
|
24
25
|
return 0;
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
#if !TARGET_OS_IPHONE
|
|
27
29
|
message = SecCopyErrorMessageString(ret, NULL);
|
|
28
30
|
GITERR_CHECK_ALLOC(message);
|
|
29
31
|
|
|
30
32
|
giterr_set(GITERR_NET, "SecureTransport error: %s", CFStringGetCStringPtr(message, kCFStringEncodingUTF8));
|
|
31
33
|
CFRelease(message);
|
|
34
|
+
#else
|
|
35
|
+
giterr_set(GITERR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret);
|
|
36
|
+
#endif
|
|
37
|
+
|
|
32
38
|
return -1;
|
|
33
39
|
}
|
|
34
40
|
|
|
@@ -110,19 +116,33 @@ int stransport_certificate(git_cert **out, git_stream *stream)
|
|
|
110
116
|
return 0;
|
|
111
117
|
}
|
|
112
118
|
|
|
119
|
+
int stransport_set_proxy(git_stream *stream, const char *proxy)
|
|
120
|
+
{
|
|
121
|
+
stransport_stream *st = (stransport_stream *) stream;
|
|
122
|
+
|
|
123
|
+
return git_stream_set_proxy(st->io, proxy);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/*
|
|
127
|
+
* Contrary to typical network IO callbacks, Secure Transport write callback is
|
|
128
|
+
* expected to write *all* passed data, not just as much as it can, and any
|
|
129
|
+
* other case would be considered a failure.
|
|
130
|
+
*
|
|
131
|
+
* This behavior is actually not specified in the Apple documentation, but is
|
|
132
|
+
* required for things to work correctly (and incidentally, that's also how
|
|
133
|
+
* Apple implements it in its projects at opensource.apple.com).
|
|
134
|
+
*
|
|
135
|
+
* Libgit2 streams happen to already have this very behavior so this is just
|
|
136
|
+
* passthrough.
|
|
137
|
+
*/
|
|
113
138
|
static OSStatus write_cb(SSLConnectionRef conn, const void *data, size_t *len)
|
|
114
139
|
{
|
|
115
140
|
git_stream *io = (git_stream *) conn;
|
|
116
|
-
ssize_t ret;
|
|
117
141
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
*len = 0;
|
|
121
|
-
return -1;
|
|
142
|
+
if (git_stream_write(io, data, *len, 0) < 0) {
|
|
143
|
+
return -36; /* "ioErr" from MacErrors.h which is not available on iOS */
|
|
122
144
|
}
|
|
123
145
|
|
|
124
|
-
*len = ret;
|
|
125
|
-
|
|
126
146
|
return noErr;
|
|
127
147
|
}
|
|
128
148
|
|
|
@@ -141,29 +161,38 @@ ssize_t stransport_write(git_stream *stream, const char *data, size_t len, int f
|
|
|
141
161
|
return processed;
|
|
142
162
|
}
|
|
143
163
|
|
|
164
|
+
/*
|
|
165
|
+
* Contrary to typical network IO callbacks, Secure Transport read callback is
|
|
166
|
+
* expected to read *exactly* the requested number of bytes, not just as much
|
|
167
|
+
* as it can, and any other case would be considered a failure.
|
|
168
|
+
*
|
|
169
|
+
* This behavior is actually not specified in the Apple documentation, but is
|
|
170
|
+
* required for things to work correctly (and incidentally, that's also how
|
|
171
|
+
* Apple implements it in its projects at opensource.apple.com).
|
|
172
|
+
*/
|
|
144
173
|
static OSStatus read_cb(SSLConnectionRef conn, void *data, size_t *len)
|
|
145
174
|
{
|
|
146
175
|
git_stream *io = (git_stream *) conn;
|
|
176
|
+
OSStatus error = noErr;
|
|
177
|
+
size_t off = 0;
|
|
147
178
|
ssize_t ret;
|
|
148
|
-
size_t left, requested;
|
|
149
179
|
|
|
150
|
-
requested = left = *len;
|
|
151
180
|
do {
|
|
152
|
-
ret = git_stream_read(io, data +
|
|
181
|
+
ret = git_stream_read(io, data + off, *len - off);
|
|
153
182
|
if (ret < 0) {
|
|
154
|
-
|
|
155
|
-
|
|
183
|
+
error = -36; /* "ioErr" from MacErrors.h which is not available on iOS */
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
if (ret == 0) {
|
|
187
|
+
error = errSSLClosedGraceful;
|
|
188
|
+
break;
|
|
156
189
|
}
|
|
157
190
|
|
|
158
|
-
|
|
159
|
-
} while (
|
|
160
|
-
|
|
161
|
-
*len = requested;
|
|
162
|
-
|
|
163
|
-
if (ret == 0)
|
|
164
|
-
return errSSLClosedGraceful;
|
|
191
|
+
off += ret;
|
|
192
|
+
} while (off < *len);
|
|
165
193
|
|
|
166
|
-
|
|
194
|
+
*len = off;
|
|
195
|
+
return error;
|
|
167
196
|
}
|
|
168
197
|
|
|
169
198
|
ssize_t stransport_read(git_stream *stream, void *data, size_t len)
|
|
@@ -212,7 +241,13 @@ int git_stransport_stream_new(git_stream **out, const char *host, const char *po
|
|
|
212
241
|
st = git__calloc(1, sizeof(stransport_stream));
|
|
213
242
|
GITERR_CHECK_ALLOC(st);
|
|
214
243
|
|
|
215
|
-
|
|
244
|
+
#ifdef GIT_CURL
|
|
245
|
+
error = git_curl_stream_new(&st->io, host, port);
|
|
246
|
+
#else
|
|
247
|
+
error = git_socket_stream_new(&st->io, host, port);
|
|
248
|
+
#endif
|
|
249
|
+
|
|
250
|
+
if (error < 0){
|
|
216
251
|
git__free(st);
|
|
217
252
|
return error;
|
|
218
253
|
}
|
|
@@ -235,8 +270,10 @@ int git_stransport_stream_new(git_stream **out, const char *host, const char *po
|
|
|
235
270
|
|
|
236
271
|
st->parent.version = GIT_STREAM_VERSION;
|
|
237
272
|
st->parent.encrypted = 1;
|
|
273
|
+
st->parent.proxy_support = git_stream_supports_proxy(st->io);
|
|
238
274
|
st->parent.connect = stransport_connect;
|
|
239
275
|
st->parent.certificate = stransport_certificate;
|
|
276
|
+
st->parent.set_proxy = stransport_set_proxy;
|
|
240
277
|
st->parent.read = stransport_read;
|
|
241
278
|
st->parent.write = stransport_write;
|
|
242
279
|
st->parent.close = stransport_close;
|
data/vendor/libgit2/src/stream.h
CHANGED
|
@@ -30,6 +30,21 @@ GIT_INLINE(int) git_stream_certificate(git_cert **out, git_stream *st)
|
|
|
30
30
|
return st->certificate(out, st);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
GIT_INLINE(int) git_stream_supports_proxy(git_stream *st)
|
|
34
|
+
{
|
|
35
|
+
return st->proxy_support;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
GIT_INLINE(int) git_stream_set_proxy(git_stream *st, const char *proxy_url)
|
|
39
|
+
{
|
|
40
|
+
if (!st->proxy_support) {
|
|
41
|
+
giterr_set(GITERR_INVALID, "proxy not supported on this stream");
|
|
42
|
+
return -1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return st->set_proxy(st, proxy_url);
|
|
46
|
+
}
|
|
47
|
+
|
|
33
48
|
GIT_INLINE(ssize_t) git_stream_read(git_stream *st, void *data, size_t len)
|
|
34
49
|
{
|
|
35
50
|
return st->read(st, data, len);
|
|
@@ -87,17 +87,16 @@ __KHASH_IMPL(
|
|
|
87
87
|
str, static kh_inline, const char *, void *, 1,
|
|
88
88
|
str_hash_no_trailing_slash, str_equal_no_trailing_slash)
|
|
89
89
|
|
|
90
|
-
static int
|
|
91
|
-
static
|
|
92
|
-
|
|
93
|
-
static git_config_backend *open_gitmodules(git_submodule_cache *, int gitmod);
|
|
90
|
+
static int submodule_alloc(git_submodule **out, git_repository *repo, const char *name);
|
|
91
|
+
static git_config_backend *open_gitmodules(git_repository *repo, int gitmod);
|
|
94
92
|
static int get_url_base(git_buf *url, git_repository *repo);
|
|
95
93
|
static int lookup_head_remote_key(git_buf *remote_key, git_repository *repo);
|
|
96
|
-
static int submodule_get(git_submodule **, git_submodule_cache *, const char *, const char *);
|
|
97
94
|
static int submodule_load_from_config(const git_config_entry *, void *);
|
|
98
95
|
static int submodule_load_from_wd_lite(git_submodule *);
|
|
99
96
|
static void submodule_get_index_status(unsigned int *, git_submodule *);
|
|
100
97
|
static void submodule_get_wd_status(unsigned int *, git_submodule *, git_repository *, git_submodule_ignore_t);
|
|
98
|
+
static void submodule_update_from_index_entry(git_submodule *sm, const git_index_entry *ie);
|
|
99
|
+
static void submodule_update_from_head_data(git_submodule *sm, mode_t mode, const git_oid *id);
|
|
101
100
|
|
|
102
101
|
static int submodule_cmp(const void *a, const void *b)
|
|
103
102
|
{
|
|
@@ -111,69 +110,10 @@ static int submodule_config_key_trunc_puts(git_buf *key, const char *suffix)
|
|
|
111
110
|
return git_buf_puts(key, suffix);
|
|
112
111
|
}
|
|
113
112
|
|
|
114
|
-
/* lookup submodule or return ENOTFOUND if it doesn't exist */
|
|
115
|
-
static int submodule_lookup(
|
|
116
|
-
git_submodule **out,
|
|
117
|
-
git_submodule_cache *cache,
|
|
118
|
-
const char *name,
|
|
119
|
-
const char *alternate)
|
|
120
|
-
{
|
|
121
|
-
khiter_t pos;
|
|
122
|
-
|
|
123
|
-
/* lock cache */
|
|
124
|
-
|
|
125
|
-
pos = git_strmap_lookup_index(cache->submodules, name);
|
|
126
|
-
|
|
127
|
-
if (!git_strmap_valid_index(cache->submodules, pos) && alternate)
|
|
128
|
-
pos = git_strmap_lookup_index(cache->submodules, alternate);
|
|
129
|
-
|
|
130
|
-
if (!git_strmap_valid_index(cache->submodules, pos)) {
|
|
131
|
-
/* unlock cache */
|
|
132
|
-
return GIT_ENOTFOUND; /* don't set error - caller will cope */
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (out != NULL) {
|
|
136
|
-
git_submodule *sm = git_strmap_value_at(cache->submodules, pos);
|
|
137
|
-
GIT_REFCOUNT_INC(sm);
|
|
138
|
-
*out = sm;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/* unlock cache */
|
|
142
|
-
|
|
143
|
-
return 0;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/* clear a set of flags on all submodules */
|
|
147
|
-
static void submodule_cache_clear_flags(
|
|
148
|
-
git_submodule_cache *cache, uint32_t mask)
|
|
149
|
-
{
|
|
150
|
-
git_submodule *sm;
|
|
151
|
-
uint32_t inverted_mask = ~mask;
|
|
152
|
-
|
|
153
|
-
git_strmap_foreach_value(cache->submodules, sm, {
|
|
154
|
-
sm->flags &= inverted_mask;
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
113
|
/*
|
|
159
114
|
* PUBLIC APIS
|
|
160
115
|
*/
|
|
161
116
|
|
|
162
|
-
bool git_submodule__is_submodule(git_repository *repo, const char *name)
|
|
163
|
-
{
|
|
164
|
-
git_strmap *map;
|
|
165
|
-
|
|
166
|
-
if (submodule_cache_init(repo, CACHE_OK) < 0) {
|
|
167
|
-
giterr_clear();
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (!repo->_submodules || !(map = repo->_submodules->submodules))
|
|
172
|
-
return false;
|
|
173
|
-
|
|
174
|
-
return git_strmap_valid_index(map, git_strmap_lookup_index(map, name));
|
|
175
|
-
}
|
|
176
|
-
|
|
177
117
|
static void submodule_set_lookup_error(int error, const char *name)
|
|
178
118
|
{
|
|
179
119
|
if (!error)
|
|
@@ -184,22 +124,24 @@ static void submodule_set_lookup_error(int error, const char *name)
|
|
|
184
124
|
"Submodule '%s' has not been added yet", name);
|
|
185
125
|
}
|
|
186
126
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
{
|
|
192
|
-
int error;
|
|
193
|
-
|
|
194
|
-
assert(repo && name);
|
|
127
|
+
typedef struct {
|
|
128
|
+
const char *path;
|
|
129
|
+
char *name;
|
|
130
|
+
} fbp_data;
|
|
195
131
|
|
|
196
|
-
|
|
197
|
-
|
|
132
|
+
static int find_by_path(const git_config_entry *entry, void *payload)
|
|
133
|
+
{
|
|
134
|
+
fbp_data *data = payload;
|
|
198
135
|
|
|
199
|
-
if ((
|
|
200
|
-
|
|
136
|
+
if (!strcmp(entry->value, data->path)) {
|
|
137
|
+
const char *fdot, *ldot;
|
|
138
|
+
fdot = strchr(entry->name, '.');
|
|
139
|
+
ldot = strrchr(entry->name, '.');
|
|
140
|
+
data->name = git__strndup(fdot + 1, ldot - fdot - 1);
|
|
141
|
+
GITERR_CHECK_ALLOC(data->name);
|
|
142
|
+
}
|
|
201
143
|
|
|
202
|
-
return
|
|
144
|
+
return 0;
|
|
203
145
|
}
|
|
204
146
|
|
|
205
147
|
int git_submodule_lookup(
|
|
@@ -208,20 +150,71 @@ int git_submodule_lookup(
|
|
|
208
150
|
const char *name) /* trailing slash is allowed */
|
|
209
151
|
{
|
|
210
152
|
int error;
|
|
153
|
+
unsigned int location;
|
|
154
|
+
git_submodule *sm;
|
|
211
155
|
|
|
212
156
|
assert(repo && name);
|
|
213
157
|
|
|
214
|
-
if ((error =
|
|
158
|
+
if ((error = submodule_alloc(&sm, repo, name)) < 0)
|
|
215
159
|
return error;
|
|
216
160
|
|
|
217
|
-
if ((error =
|
|
161
|
+
if ((error = git_submodule_reload(sm, false)) < 0) {
|
|
162
|
+
git_submodule_free(sm);
|
|
163
|
+
return error;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if ((error = git_submodule_location(&location, sm)) < 0) {
|
|
167
|
+
git_submodule_free(sm);
|
|
168
|
+
return error;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* If it's not configured, we need to check for the path */
|
|
172
|
+
if (location == 0 || location == GIT_SUBMODULE_STATUS_IN_WD) {
|
|
173
|
+
git_config_backend *mods;
|
|
174
|
+
const char *pattern = "submodule\\..*\\.path";
|
|
175
|
+
fbp_data data = { name, NULL };
|
|
176
|
+
|
|
177
|
+
mods = open_gitmodules(repo, GITMODULES_EXISTING);
|
|
178
|
+
|
|
179
|
+
if (mods)
|
|
180
|
+
error = git_config_file_foreach_match(mods, pattern, find_by_path, &data);
|
|
218
181
|
|
|
219
|
-
|
|
182
|
+
git_config_file_free(mods);
|
|
183
|
+
|
|
184
|
+
if (error < 0) {
|
|
185
|
+
git_submodule_free(sm);
|
|
186
|
+
return error;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (data.name) {
|
|
190
|
+
git__free(sm->name);
|
|
191
|
+
sm->name = data.name;
|
|
192
|
+
sm->path = git__strdup(name);
|
|
193
|
+
GITERR_CHECK_ALLOC(sm->path);
|
|
194
|
+
|
|
195
|
+
/* Try to load again with the right name */
|
|
196
|
+
if ((error = git_submodule_reload(sm, false)) < 0) {
|
|
197
|
+
git_submodule_free(sm);
|
|
198
|
+
return error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if ((error = git_submodule_location(&location, sm)) < 0) {
|
|
204
|
+
git_submodule_free(sm);
|
|
205
|
+
return error;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* If we still haven't found it, do the WD check */
|
|
209
|
+
if (location == 0 || location == GIT_SUBMODULE_STATUS_IN_WD) {
|
|
210
|
+
git_submodule_free(sm);
|
|
211
|
+
error = GIT_ENOTFOUND;
|
|
212
|
+
|
|
213
|
+
/* If it's not configured, we still check if there's a repo at the path */
|
|
220
214
|
if (git_repository_workdir(repo)) {
|
|
221
215
|
git_buf path = GIT_BUF_INIT;
|
|
222
|
-
|
|
223
216
|
if (git_buf_join3(&path,
|
|
224
|
-
|
|
217
|
+
'/', git_repository_workdir(repo), name, DOT_GIT) < 0)
|
|
225
218
|
return -1;
|
|
226
219
|
|
|
227
220
|
if (git_path_exists(path.ptr))
|
|
@@ -231,9 +224,15 @@ int git_submodule_lookup(
|
|
|
231
224
|
}
|
|
232
225
|
|
|
233
226
|
submodule_set_lookup_error(error, name);
|
|
227
|
+
return error;
|
|
234
228
|
}
|
|
235
229
|
|
|
236
|
-
|
|
230
|
+
if (out)
|
|
231
|
+
*out = sm;
|
|
232
|
+
else
|
|
233
|
+
git_submodule_free(sm);
|
|
234
|
+
|
|
235
|
+
return 0;
|
|
237
236
|
}
|
|
238
237
|
|
|
239
238
|
static void submodule_free_dup(void *sm)
|
|
@@ -241,41 +240,221 @@ static void submodule_free_dup(void *sm)
|
|
|
241
240
|
git_submodule_free(sm);
|
|
242
241
|
}
|
|
243
242
|
|
|
243
|
+
static int submodule_get_or_create(git_submodule **out, git_repository *repo, git_strmap *map, const char *name)
|
|
244
|
+
{
|
|
245
|
+
int error = 0;
|
|
246
|
+
khiter_t pos;
|
|
247
|
+
git_submodule *sm = NULL;
|
|
248
|
+
|
|
249
|
+
pos = git_strmap_lookup_index(map, name);
|
|
250
|
+
if (git_strmap_valid_index(map, pos)) {
|
|
251
|
+
sm = git_strmap_value_at(map, pos);
|
|
252
|
+
goto done;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* if the submodule doesn't exist yet in the map, create it */
|
|
256
|
+
if ((error = submodule_alloc(&sm, repo, name)) < 0)
|
|
257
|
+
return error;
|
|
258
|
+
|
|
259
|
+
pos = kh_put(str, map, sm->name, &error);
|
|
260
|
+
/* nobody can beat us to adding it */
|
|
261
|
+
assert(error != 0);
|
|
262
|
+
if (error < 0) {
|
|
263
|
+
git_submodule_free(sm);
|
|
264
|
+
return error;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
git_strmap_set_value_at(map, pos, sm);
|
|
268
|
+
|
|
269
|
+
done:
|
|
270
|
+
GIT_REFCOUNT_INC(sm);
|
|
271
|
+
*out = sm;
|
|
272
|
+
return 0;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
static int submodules_from_index(git_strmap *map, git_index *idx)
|
|
276
|
+
{
|
|
277
|
+
int error;
|
|
278
|
+
git_iterator *i;
|
|
279
|
+
const git_index_entry *entry;
|
|
280
|
+
|
|
281
|
+
if ((error = git_iterator_for_index(&i, idx, 0, NULL, NULL)) < 0)
|
|
282
|
+
return error;
|
|
283
|
+
|
|
284
|
+
while (!(error = git_iterator_advance(&entry, i))) {
|
|
285
|
+
khiter_t pos = git_strmap_lookup_index(map, entry->path);
|
|
286
|
+
git_submodule *sm;
|
|
287
|
+
|
|
288
|
+
if (git_strmap_valid_index(map, pos)) {
|
|
289
|
+
sm = git_strmap_value_at(map, pos);
|
|
290
|
+
|
|
291
|
+
if (S_ISGITLINK(entry->mode))
|
|
292
|
+
submodule_update_from_index_entry(sm, entry);
|
|
293
|
+
else
|
|
294
|
+
sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE;
|
|
295
|
+
} else if (S_ISGITLINK(entry->mode)) {
|
|
296
|
+
if (!submodule_get_or_create(&sm, git_index_owner(idx), map, entry->path)) {
|
|
297
|
+
submodule_update_from_index_entry(sm, entry);
|
|
298
|
+
git_submodule_free(sm);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (error == GIT_ITEROVER)
|
|
304
|
+
error = 0;
|
|
305
|
+
|
|
306
|
+
git_iterator_free(i);
|
|
307
|
+
|
|
308
|
+
return error;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
static int submodules_from_head(git_strmap *map, git_tree *head)
|
|
312
|
+
{
|
|
313
|
+
int error;
|
|
314
|
+
git_iterator *i;
|
|
315
|
+
const git_index_entry *entry;
|
|
316
|
+
|
|
317
|
+
if ((error = git_iterator_for_tree(&i, head, 0, NULL, NULL)) < 0)
|
|
318
|
+
return error;
|
|
319
|
+
|
|
320
|
+
while (!(error = git_iterator_advance(&entry, i))) {
|
|
321
|
+
khiter_t pos = git_strmap_lookup_index(map, entry->path);
|
|
322
|
+
git_submodule *sm;
|
|
323
|
+
|
|
324
|
+
if (git_strmap_valid_index(map, pos)) {
|
|
325
|
+
sm = git_strmap_value_at(map, pos);
|
|
326
|
+
|
|
327
|
+
if (S_ISGITLINK(entry->mode))
|
|
328
|
+
submodule_update_from_head_data(sm, entry->mode, &entry->id);
|
|
329
|
+
else
|
|
330
|
+
sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE;
|
|
331
|
+
} else if (S_ISGITLINK(entry->mode)) {
|
|
332
|
+
if (!submodule_get_or_create(&sm, git_tree_owner(head), map, entry->path)) {
|
|
333
|
+
submodule_update_from_head_data(
|
|
334
|
+
sm, entry->mode, &entry->id);
|
|
335
|
+
git_submodule_free(sm);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (error == GIT_ITEROVER)
|
|
341
|
+
error = 0;
|
|
342
|
+
|
|
343
|
+
git_iterator_free(i);
|
|
344
|
+
|
|
345
|
+
return error;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* If have_sm is true, sm is populated, otherwise map an repo are. */
|
|
349
|
+
typedef struct {
|
|
350
|
+
int have_sm;
|
|
351
|
+
git_submodule *sm;
|
|
352
|
+
git_strmap *map;
|
|
353
|
+
git_repository *repo;
|
|
354
|
+
} lfc_data;
|
|
355
|
+
|
|
356
|
+
static int all_submodules(git_repository *repo, git_strmap *map)
|
|
357
|
+
{
|
|
358
|
+
int error = 0;
|
|
359
|
+
git_index *idx = NULL;
|
|
360
|
+
git_tree *head = NULL;
|
|
361
|
+
const char *wd = NULL;
|
|
362
|
+
git_buf path = GIT_BUF_INIT;
|
|
363
|
+
git_submodule *sm;
|
|
364
|
+
git_config_backend *mods = NULL;
|
|
365
|
+
uint32_t mask;
|
|
366
|
+
|
|
367
|
+
assert(repo && map);
|
|
368
|
+
|
|
369
|
+
/* get sources that we will need to check */
|
|
370
|
+
if (git_repository_index(&idx, repo) < 0)
|
|
371
|
+
giterr_clear();
|
|
372
|
+
if (git_repository_head_tree(&head, repo) < 0)
|
|
373
|
+
giterr_clear();
|
|
374
|
+
|
|
375
|
+
wd = git_repository_workdir(repo);
|
|
376
|
+
if (wd && (error = git_buf_joinpath(&path, wd, GIT_MODULES_FILE)) < 0)
|
|
377
|
+
goto cleanup;
|
|
378
|
+
|
|
379
|
+
/* clear submodule flags that are to be refreshed */
|
|
380
|
+
mask = 0;
|
|
381
|
+
mask |= GIT_SUBMODULE_STATUS_IN_INDEX |
|
|
382
|
+
GIT_SUBMODULE_STATUS__INDEX_FLAGS |
|
|
383
|
+
GIT_SUBMODULE_STATUS__INDEX_OID_VALID |
|
|
384
|
+
GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES;
|
|
385
|
+
|
|
386
|
+
mask |= GIT_SUBMODULE_STATUS_IN_HEAD |
|
|
387
|
+
GIT_SUBMODULE_STATUS__HEAD_OID_VALID;
|
|
388
|
+
mask |= GIT_SUBMODULE_STATUS_IN_CONFIG;
|
|
389
|
+
if (mask != 0)
|
|
390
|
+
mask |= GIT_SUBMODULE_STATUS_IN_WD |
|
|
391
|
+
GIT_SUBMODULE_STATUS__WD_SCANNED |
|
|
392
|
+
GIT_SUBMODULE_STATUS__WD_FLAGS |
|
|
393
|
+
GIT_SUBMODULE_STATUS__WD_OID_VALID;
|
|
394
|
+
|
|
395
|
+
/* add back submodule information from index */
|
|
396
|
+
if (idx) {
|
|
397
|
+
if ((error = submodules_from_index(map, idx)) < 0)
|
|
398
|
+
goto cleanup;
|
|
399
|
+
}
|
|
400
|
+
/* add submodule information from HEAD */
|
|
401
|
+
if (head) {
|
|
402
|
+
if ((error = submodules_from_head(map, head)) < 0)
|
|
403
|
+
goto cleanup;
|
|
404
|
+
}
|
|
405
|
+
/* add submodule information from .gitmodules */
|
|
406
|
+
if (wd) {
|
|
407
|
+
lfc_data data = { 0 };
|
|
408
|
+
data.map = map;
|
|
409
|
+
data.repo = repo;
|
|
410
|
+
if ((mods = open_gitmodules(repo, false)) != NULL &&
|
|
411
|
+
(error = git_config_file_foreach(
|
|
412
|
+
mods, submodule_load_from_config, &data)) < 0)
|
|
413
|
+
goto cleanup;
|
|
414
|
+
}
|
|
415
|
+
/* shallow scan submodules in work tree as needed */
|
|
416
|
+
if (wd && mask != 0) {
|
|
417
|
+
git_strmap_foreach_value(map, sm, {
|
|
418
|
+
submodule_load_from_wd_lite(sm);
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
cleanup:
|
|
423
|
+
git_config_file_free(mods);
|
|
424
|
+
/* TODO: if we got an error, mark submodule config as invalid? */
|
|
425
|
+
git_index_free(idx);
|
|
426
|
+
git_tree_free(head);
|
|
427
|
+
git_buf_free(&path);
|
|
428
|
+
return error;
|
|
429
|
+
}
|
|
430
|
+
|
|
244
431
|
int git_submodule_foreach(
|
|
245
432
|
git_repository *repo,
|
|
246
433
|
int (*callback)(git_submodule *sm, const char *name, void *payload),
|
|
247
434
|
void *payload)
|
|
248
435
|
{
|
|
436
|
+
git_vector snapshot = GIT_VECTOR_INIT;
|
|
437
|
+
git_strmap *submodules;
|
|
438
|
+
git_submodule *sm;
|
|
249
439
|
int error;
|
|
250
440
|
size_t i;
|
|
251
|
-
git_submodule *sm;
|
|
252
|
-
git_submodule_cache *cache;
|
|
253
|
-
git_vector snapshot = GIT_VECTOR_INIT;
|
|
254
|
-
|
|
255
|
-
assert(repo && callback);
|
|
256
441
|
|
|
257
|
-
if ((error =
|
|
442
|
+
if ((error = git_strmap_alloc(&submodules)) < 0)
|
|
258
443
|
return error;
|
|
259
444
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (git_mutex_lock(&cache->lock) < 0) {
|
|
263
|
-
giterr_set(GITERR_OS, "Unable to acquire lock on submodule cache");
|
|
264
|
-
return -1;
|
|
265
|
-
}
|
|
445
|
+
if ((error = all_submodules(repo, submodules)) < 0)
|
|
446
|
+
goto done;
|
|
266
447
|
|
|
267
448
|
if (!(error = git_vector_init(
|
|
268
|
-
&snapshot, kh_size(
|
|
449
|
+
&snapshot, kh_size(submodules), submodule_cmp))) {
|
|
269
450
|
|
|
270
|
-
git_strmap_foreach_value(
|
|
451
|
+
git_strmap_foreach_value(submodules, sm, {
|
|
271
452
|
if ((error = git_vector_insert(&snapshot, sm)) < 0)
|
|
272
453
|
break;
|
|
273
454
|
GIT_REFCOUNT_INC(sm);
|
|
274
455
|
});
|
|
275
456
|
}
|
|
276
457
|
|
|
277
|
-
git_mutex_unlock(&cache->lock);
|
|
278
|
-
|
|
279
458
|
if (error < 0)
|
|
280
459
|
goto done;
|
|
281
460
|
|
|
@@ -293,17 +472,12 @@ done:
|
|
|
293
472
|
git_submodule_free(sm);
|
|
294
473
|
git_vector_free(&snapshot);
|
|
295
474
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
{
|
|
301
|
-
git_submodule_cache *cache;
|
|
302
|
-
|
|
303
|
-
assert(repo);
|
|
475
|
+
git_strmap_foreach_value(submodules, sm, {
|
|
476
|
+
git_submodule_free(sm);
|
|
477
|
+
});
|
|
478
|
+
git_strmap_free(submodules);
|
|
304
479
|
|
|
305
|
-
|
|
306
|
-
submodule_cache_free(cache);
|
|
480
|
+
return error;
|
|
307
481
|
}
|
|
308
482
|
|
|
309
483
|
static int submodule_repo_init(
|
|
@@ -394,7 +568,7 @@ int git_submodule_add_setup(
|
|
|
394
568
|
|
|
395
569
|
/* update .gitmodules */
|
|
396
570
|
|
|
397
|
-
if (!(mods = open_gitmodules(repo
|
|
571
|
+
if (!(mods = open_gitmodules(repo, GITMODULES_CREATE))) {
|
|
398
572
|
giterr_set(GITERR_SUBMODULE,
|
|
399
573
|
"Adding submodules to a bare repository is not supported");
|
|
400
574
|
return -1;
|
|
@@ -430,19 +604,10 @@ int git_submodule_add_setup(
|
|
|
430
604
|
goto cleanup;
|
|
431
605
|
}
|
|
432
606
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
if (git_mutex_lock(&repo->_submodules->lock) < 0) {
|
|
436
|
-
giterr_set(GITERR_OS, "Unable to acquire lock on submodule cache");
|
|
437
|
-
error = -1;
|
|
607
|
+
if ((error = git_submodule_lookup(&sm, repo, path)) < 0)
|
|
438
608
|
goto cleanup;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
if (!(error = submodule_get(&sm, repo->_submodules, path, NULL)) &&
|
|
442
|
-
!(error = git_submodule_reload(sm, false)))
|
|
443
|
-
error = git_submodule_init(sm, false);
|
|
444
609
|
|
|
445
|
-
|
|
610
|
+
error = git_submodule_init(sm, false);
|
|
446
611
|
|
|
447
612
|
cleanup:
|
|
448
613
|
if (error && sm) {
|
|
@@ -572,15 +737,6 @@ cleanup:
|
|
|
572
737
|
return error;
|
|
573
738
|
}
|
|
574
739
|
|
|
575
|
-
const char *git_submodule_ignore_to_str(git_submodule_ignore_t ignore)
|
|
576
|
-
{
|
|
577
|
-
int i;
|
|
578
|
-
for (i = 0; i < (int)ARRAY_SIZE(_sm_ignore_map); ++i)
|
|
579
|
-
if (_sm_ignore_map[i].map_value == ignore)
|
|
580
|
-
return _sm_ignore_map[i].str_match;
|
|
581
|
-
return NULL;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
740
|
const char *git_submodule_update_to_str(git_submodule_update_t update)
|
|
585
741
|
{
|
|
586
742
|
int i;
|
|
@@ -590,132 +746,90 @@ const char *git_submodule_update_to_str(git_submodule_update_t update)
|
|
|
590
746
|
return NULL;
|
|
591
747
|
}
|
|
592
748
|
|
|
593
|
-
|
|
749
|
+
git_repository *git_submodule_owner(git_submodule *submodule)
|
|
594
750
|
{
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
if (_sm_recurse_map[i].map_value == recurse)
|
|
598
|
-
return _sm_recurse_map[i].str_match;
|
|
599
|
-
return NULL;
|
|
751
|
+
assert(submodule);
|
|
752
|
+
return submodule->repo;
|
|
600
753
|
}
|
|
601
754
|
|
|
602
|
-
|
|
755
|
+
const char *git_submodule_name(git_submodule *submodule)
|
|
603
756
|
{
|
|
604
|
-
int error = 0;
|
|
605
|
-
git_config_backend *mods;
|
|
606
|
-
git_buf key = GIT_BUF_INIT;
|
|
607
|
-
const char *val;
|
|
608
|
-
|
|
609
757
|
assert(submodule);
|
|
758
|
+
return submodule->name;
|
|
759
|
+
}
|
|
610
760
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
761
|
+
const char *git_submodule_path(git_submodule *submodule)
|
|
762
|
+
{
|
|
763
|
+
assert(submodule);
|
|
764
|
+
return submodule->path;
|
|
765
|
+
}
|
|
617
766
|
|
|
618
|
-
|
|
619
|
-
|
|
767
|
+
const char *git_submodule_url(git_submodule *submodule)
|
|
768
|
+
{
|
|
769
|
+
assert(submodule);
|
|
770
|
+
return submodule->url;
|
|
771
|
+
}
|
|
620
772
|
|
|
621
|
-
|
|
773
|
+
int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *url)
|
|
774
|
+
{
|
|
775
|
+
int error = 0;
|
|
622
776
|
|
|
623
|
-
|
|
624
|
-
(error = git_config_file_set_string(mods, key.ptr, submodule->path)) < 0)
|
|
625
|
-
goto cleanup;
|
|
777
|
+
assert(out && repo && url);
|
|
626
778
|
|
|
627
|
-
|
|
628
|
-
(error = git_config_file_set_string(mods, key.ptr, submodule->url)) < 0)
|
|
629
|
-
goto cleanup;
|
|
779
|
+
git_buf_sanitize(out);
|
|
630
780
|
|
|
631
|
-
if ((
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
error =
|
|
639
|
-
giterr_clear();
|
|
781
|
+
if (git_path_is_relative(url)) {
|
|
782
|
+
if (!(error = get_url_base(out, repo)))
|
|
783
|
+
error = git_path_apply_relative(out, url);
|
|
784
|
+
} else if (strchr(url, ':') != NULL || url[0] == '/') {
|
|
785
|
+
error = git_buf_sets(out, url);
|
|
786
|
+
} else {
|
|
787
|
+
giterr_set(GITERR_SUBMODULE, "Invalid format for submodule URL");
|
|
788
|
+
error = -1;
|
|
640
789
|
}
|
|
641
|
-
if (error < 0)
|
|
642
|
-
goto cleanup;
|
|
643
|
-
|
|
644
|
-
if (!(error = submodule_config_key_trunc_puts(&key, "update")) &&
|
|
645
|
-
(val = git_submodule_update_to_str(submodule->update)) != NULL)
|
|
646
|
-
error = git_config_file_set_string(mods, key.ptr, val);
|
|
647
|
-
if (error < 0)
|
|
648
|
-
goto cleanup;
|
|
649
|
-
|
|
650
|
-
if (!(error = submodule_config_key_trunc_puts(&key, "ignore")) &&
|
|
651
|
-
(val = git_submodule_ignore_to_str(submodule->ignore)) != NULL)
|
|
652
|
-
error = git_config_file_set_string(mods, key.ptr, val);
|
|
653
|
-
if (error < 0)
|
|
654
|
-
goto cleanup;
|
|
655
|
-
|
|
656
|
-
if (!(error = submodule_config_key_trunc_puts(&key, "fetchRecurseSubmodules")) &&
|
|
657
|
-
(val = git_submodule_recurse_to_str(submodule->fetch_recurse)) != NULL)
|
|
658
|
-
error = git_config_file_set_string(mods, key.ptr, val);
|
|
659
|
-
if (error < 0)
|
|
660
|
-
goto cleanup;
|
|
661
|
-
|
|
662
|
-
/* update internal defaults */
|
|
663
|
-
|
|
664
|
-
submodule->ignore_default = submodule->ignore;
|
|
665
|
-
submodule->update_default = submodule->update;
|
|
666
|
-
submodule->fetch_recurse_default = submodule->fetch_recurse;
|
|
667
|
-
submodule->flags |= GIT_SUBMODULE_STATUS_IN_CONFIG;
|
|
668
|
-
|
|
669
|
-
cleanup:
|
|
670
|
-
git_config_file_free(mods);
|
|
671
|
-
git_buf_free(&key);
|
|
672
790
|
|
|
673
791
|
return error;
|
|
674
792
|
}
|
|
675
793
|
|
|
676
|
-
git_repository *
|
|
794
|
+
static int write_var(git_repository *repo, const char *name, const char *var, const char *val)
|
|
677
795
|
{
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
796
|
+
git_buf key = GIT_BUF_INIT;
|
|
797
|
+
git_config_backend *mods;
|
|
798
|
+
int error;
|
|
681
799
|
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
return submodule->name;
|
|
686
|
-
}
|
|
800
|
+
mods = open_gitmodules(repo, GITMODULES_CREATE);
|
|
801
|
+
if (!mods)
|
|
802
|
+
return -1;
|
|
687
803
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
804
|
+
if ((error = git_buf_printf(&key, "submodule.%s.%s", name, var)) < 0)
|
|
805
|
+
goto cleanup;
|
|
806
|
+
|
|
807
|
+
if (val)
|
|
808
|
+
error = git_config_file_set_string(mods, key.ptr, val);
|
|
809
|
+
else
|
|
810
|
+
error = git_config_file_delete(mods, key.ptr);
|
|
811
|
+
|
|
812
|
+
git_buf_free(&key);
|
|
693
813
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
return submodule->url;
|
|
814
|
+
cleanup:
|
|
815
|
+
git_config_file_free(mods);
|
|
816
|
+
return error;
|
|
698
817
|
}
|
|
699
818
|
|
|
700
|
-
int
|
|
819
|
+
static int write_mapped_var(git_repository *repo, const char *name, git_cvar_map *maps, size_t nmaps, const char *var, int ival)
|
|
701
820
|
{
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
assert(out && repo && url);
|
|
705
|
-
|
|
706
|
-
git_buf_sanitize(out);
|
|
821
|
+
git_cvar_t type;
|
|
822
|
+
const char *val;
|
|
707
823
|
|
|
708
|
-
if (
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
} else if (strchr(url, ':') != NULL || url[0] == '/') {
|
|
712
|
-
error = git_buf_sets(out, url);
|
|
713
|
-
} else {
|
|
714
|
-
giterr_set(GITERR_SUBMODULE, "Invalid format for submodule URL");
|
|
715
|
-
error = -1;
|
|
824
|
+
if (git_config_lookup_map_enum(&type, &val, maps, nmaps, ival) < 0) {
|
|
825
|
+
giterr_set(GITERR_SUBMODULE, "invalid value for %s", var);
|
|
826
|
+
return -1;
|
|
716
827
|
}
|
|
717
828
|
|
|
718
|
-
|
|
829
|
+
if (type == GIT_CVAR_TRUE)
|
|
830
|
+
val = "true";
|
|
831
|
+
|
|
832
|
+
return write_var(repo, name, var, val);
|
|
719
833
|
}
|
|
720
834
|
|
|
721
835
|
const char *git_submodule_branch(git_submodule *submodule)
|
|
@@ -724,31 +838,19 @@ const char *git_submodule_branch(git_submodule *submodule)
|
|
|
724
838
|
return submodule->branch;
|
|
725
839
|
}
|
|
726
840
|
|
|
727
|
-
int git_submodule_set_branch(
|
|
841
|
+
int git_submodule_set_branch(git_repository *repo, const char *name, const char *branch)
|
|
728
842
|
{
|
|
729
|
-
assert(submodule);
|
|
730
843
|
|
|
731
|
-
|
|
732
|
-
submodule->branch = NULL;
|
|
733
|
-
|
|
734
|
-
if (branch != NULL) {
|
|
735
|
-
submodule->branch = git__strdup(branch);
|
|
736
|
-
GITERR_CHECK_ALLOC(submodule->branch);
|
|
737
|
-
}
|
|
844
|
+
assert(repo && name);
|
|
738
845
|
|
|
739
|
-
return
|
|
846
|
+
return write_var(repo, name, "branch", branch);
|
|
740
847
|
}
|
|
741
848
|
|
|
742
|
-
int git_submodule_set_url(
|
|
849
|
+
int git_submodule_set_url(git_repository *repo, const char *name, const char *url)
|
|
743
850
|
{
|
|
744
|
-
assert(
|
|
745
|
-
|
|
746
|
-
git__free(submodule->url);
|
|
747
|
-
|
|
748
|
-
submodule->url = git__strdup(url);
|
|
749
|
-
GITERR_CHECK_ALLOC(submodule->url);
|
|
851
|
+
assert(repo && name && url);
|
|
750
852
|
|
|
751
|
-
return
|
|
853
|
+
return write_var(repo, name, "url", url);
|
|
752
854
|
}
|
|
753
855
|
|
|
754
856
|
const git_oid *git_submodule_index_id(git_submodule *submodule)
|
|
@@ -799,19 +901,11 @@ git_submodule_ignore_t git_submodule_ignore(git_submodule *submodule)
|
|
|
799
901
|
GIT_SUBMODULE_IGNORE_NONE : submodule->ignore;
|
|
800
902
|
}
|
|
801
903
|
|
|
802
|
-
|
|
803
|
-
git_submodule *submodule, git_submodule_ignore_t ignore)
|
|
904
|
+
int git_submodule_set_ignore(git_repository *repo, const char *name, git_submodule_ignore_t ignore)
|
|
804
905
|
{
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
assert(submodule);
|
|
808
|
-
|
|
809
|
-
if (ignore == GIT_SUBMODULE_IGNORE_RESET)
|
|
810
|
-
ignore = submodule->ignore_default;
|
|
906
|
+
assert(repo && name);
|
|
811
907
|
|
|
812
|
-
|
|
813
|
-
submodule->ignore = ignore;
|
|
814
|
-
return old;
|
|
908
|
+
return write_mapped_var(repo, name, _sm_ignore_map, ARRAY_SIZE(_sm_ignore_map), "ignore", ignore);
|
|
815
909
|
}
|
|
816
910
|
|
|
817
911
|
git_submodule_update_t git_submodule_update_strategy(git_submodule *submodule)
|
|
@@ -821,19 +915,11 @@ git_submodule_update_t git_submodule_update_strategy(git_submodule *submodule)
|
|
|
821
915
|
GIT_SUBMODULE_UPDATE_CHECKOUT : submodule->update;
|
|
822
916
|
}
|
|
823
917
|
|
|
824
|
-
|
|
825
|
-
git_submodule *submodule, git_submodule_update_t update)
|
|
918
|
+
int git_submodule_set_update(git_repository *repo, const char *name, git_submodule_update_t update)
|
|
826
919
|
{
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
assert(submodule);
|
|
830
|
-
|
|
831
|
-
if (update == GIT_SUBMODULE_UPDATE_RESET)
|
|
832
|
-
update = submodule->update_default;
|
|
920
|
+
assert(repo && name);
|
|
833
921
|
|
|
834
|
-
|
|
835
|
-
submodule->update = update;
|
|
836
|
-
return old;
|
|
922
|
+
return write_mapped_var(repo, name, _sm_update_map, ARRAY_SIZE(_sm_update_map), "update", update);
|
|
837
923
|
}
|
|
838
924
|
|
|
839
925
|
git_submodule_recurse_t git_submodule_fetch_recurse_submodules(
|
|
@@ -843,20 +929,11 @@ git_submodule_recurse_t git_submodule_fetch_recurse_submodules(
|
|
|
843
929
|
return submodule->fetch_recurse;
|
|
844
930
|
}
|
|
845
931
|
|
|
846
|
-
|
|
847
|
-
git_submodule *submodule,
|
|
848
|
-
git_submodule_recurse_t fetch_recurse_submodules)
|
|
932
|
+
int git_submodule_set_fetch_recurse_submodules(git_repository *repo, const char *name, git_submodule_recurse_t recurse)
|
|
849
933
|
{
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
assert(submodule);
|
|
853
|
-
|
|
854
|
-
if (fetch_recurse_submodules == GIT_SUBMODULE_RECURSE_RESET)
|
|
855
|
-
fetch_recurse_submodules = submodule->fetch_recurse_default;
|
|
934
|
+
assert(repo && name);
|
|
856
935
|
|
|
857
|
-
|
|
858
|
-
submodule->fetch_recurse = fetch_recurse_submodules;
|
|
859
|
-
return old;
|
|
936
|
+
return write_mapped_var(repo, name, _sm_recurse_map, ARRAY_SIZE(_sm_recurse_map), "fetchRecurseSubmodules", recurse);
|
|
860
937
|
}
|
|
861
938
|
|
|
862
939
|
static int submodule_repo_create(
|
|
@@ -950,10 +1027,10 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
|
|
|
950
1027
|
GITERR_CHECK_VERSION(&update_options, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, "git_submodule_update_options");
|
|
951
1028
|
|
|
952
1029
|
/* Copy over the remote callbacks */
|
|
953
|
-
clone_options.
|
|
1030
|
+
memcpy(&clone_options.fetch_opts, &update_options.fetch_opts, sizeof(git_fetch_options));
|
|
954
1031
|
|
|
955
1032
|
/* Get the status of the submodule to determine if it is already initialized */
|
|
956
|
-
if ((error = git_submodule_status(&submodule_status, sm)) < 0)
|
|
1033
|
+
if ((error = git_submodule_status(&submodule_status, sm->repo, sm->name, GIT_SUBMODULE_IGNORE_UNSPECIFIED)) < 0)
|
|
957
1034
|
goto done;
|
|
958
1035
|
|
|
959
1036
|
/*
|
|
@@ -1197,11 +1274,6 @@ int git_submodule_open(git_repository **subrepo, git_submodule *sm)
|
|
|
1197
1274
|
return git_submodule__open(subrepo, sm, false);
|
|
1198
1275
|
}
|
|
1199
1276
|
|
|
1200
|
-
int git_submodule_reload_all(git_repository *repo, int force)
|
|
1201
|
-
{
|
|
1202
|
-
return submodule_cache_init(repo, force ? CACHE_FLUSH : CACHE_REFRESH);
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
1277
|
static void submodule_update_from_index_entry(
|
|
1206
1278
|
git_submodule *sm, const git_index_entry *ie)
|
|
1207
1279
|
{
|
|
@@ -1280,14 +1352,12 @@ int git_submodule_reload(git_submodule *sm, int force)
|
|
|
1280
1352
|
{
|
|
1281
1353
|
int error = 0;
|
|
1282
1354
|
git_config_backend *mods;
|
|
1283
|
-
|
|
1355
|
+
lfc_data data = { 0 };
|
|
1284
1356
|
|
|
1285
1357
|
GIT_UNUSED(force);
|
|
1286
1358
|
|
|
1287
1359
|
assert(sm);
|
|
1288
1360
|
|
|
1289
|
-
cache = sm->repo->_submodules;
|
|
1290
|
-
|
|
1291
1361
|
/* refresh index data */
|
|
1292
1362
|
if ((error = submodule_update_index(sm)) < 0)
|
|
1293
1363
|
return error;
|
|
@@ -1301,7 +1371,7 @@ int git_submodule_reload(git_submodule *sm, int force)
|
|
|
1301
1371
|
return error;
|
|
1302
1372
|
|
|
1303
1373
|
/* refresh config data */
|
|
1304
|
-
mods = open_gitmodules(
|
|
1374
|
+
mods = open_gitmodules(sm->repo, GITMODULES_EXISTING);
|
|
1305
1375
|
if (mods != NULL) {
|
|
1306
1376
|
git_buf path = GIT_BUF_INIT;
|
|
1307
1377
|
|
|
@@ -1309,11 +1379,14 @@ int git_submodule_reload(git_submodule *sm, int force)
|
|
|
1309
1379
|
git_buf_text_puts_escape_regex(&path, sm->name);
|
|
1310
1380
|
git_buf_puts(&path, ".*");
|
|
1311
1381
|
|
|
1312
|
-
if (git_buf_oom(&path))
|
|
1382
|
+
if (git_buf_oom(&path)) {
|
|
1313
1383
|
error = -1;
|
|
1314
|
-
else
|
|
1384
|
+
} else {
|
|
1385
|
+
data.have_sm = 1;
|
|
1386
|
+
data.sm = sm;
|
|
1315
1387
|
error = git_config_file_foreach_match(
|
|
1316
|
-
mods, path.ptr, submodule_load_from_config,
|
|
1388
|
+
mods, path.ptr, submodule_load_from_config, &data);
|
|
1389
|
+
}
|
|
1317
1390
|
|
|
1318
1391
|
git_buf_free(&path);
|
|
1319
1392
|
git_config_file_free(mods);
|
|
@@ -1352,7 +1425,7 @@ int git_submodule__status(
|
|
|
1352
1425
|
unsigned int status;
|
|
1353
1426
|
git_repository *smrepo = NULL;
|
|
1354
1427
|
|
|
1355
|
-
if (ign
|
|
1428
|
+
if (ign == GIT_SUBMODULE_IGNORE_UNSPECIFIED)
|
|
1356
1429
|
ign = sm->ignore;
|
|
1357
1430
|
|
|
1358
1431
|
/* only return location info if ignore == all */
|
|
@@ -1401,11 +1474,20 @@ int git_submodule__status(
|
|
|
1401
1474
|
return 0;
|
|
1402
1475
|
}
|
|
1403
1476
|
|
|
1404
|
-
int git_submodule_status(unsigned int *status,
|
|
1477
|
+
int git_submodule_status(unsigned int *status, git_repository *repo, const char *name, git_submodule_ignore_t ignore)
|
|
1405
1478
|
{
|
|
1406
|
-
|
|
1479
|
+
git_submodule *sm;
|
|
1480
|
+
int error;
|
|
1481
|
+
|
|
1482
|
+
assert(status && repo && name);
|
|
1483
|
+
|
|
1484
|
+
if ((error = git_submodule_lookup(&sm, repo, name)) < 0)
|
|
1485
|
+
return error;
|
|
1486
|
+
|
|
1487
|
+
error = git_submodule__status(status, NULL, NULL, NULL, sm, ignore);
|
|
1488
|
+
git_submodule_free(sm);
|
|
1407
1489
|
|
|
1408
|
-
return
|
|
1490
|
+
return error;
|
|
1409
1491
|
}
|
|
1410
1492
|
|
|
1411
1493
|
int git_submodule_location(unsigned int *location, git_submodule *sm)
|
|
@@ -1422,7 +1504,7 @@ int git_submodule_location(unsigned int *location, git_submodule *sm)
|
|
|
1422
1504
|
*/
|
|
1423
1505
|
|
|
1424
1506
|
static int submodule_alloc(
|
|
1425
|
-
git_submodule **out,
|
|
1507
|
+
git_submodule **out, git_repository *repo, const char *name)
|
|
1426
1508
|
{
|
|
1427
1509
|
size_t namelen;
|
|
1428
1510
|
git_submodule *sm;
|
|
@@ -1445,56 +1527,20 @@ static int submodule_alloc(
|
|
|
1445
1527
|
sm->ignore = sm->ignore_default = GIT_SUBMODULE_IGNORE_NONE;
|
|
1446
1528
|
sm->update = sm->update_default = GIT_SUBMODULE_UPDATE_CHECKOUT;
|
|
1447
1529
|
sm->fetch_recurse = sm->fetch_recurse_default = GIT_SUBMODULE_RECURSE_NO;
|
|
1448
|
-
sm->repo =
|
|
1530
|
+
sm->repo = repo;
|
|
1449
1531
|
sm->branch = NULL;
|
|
1450
1532
|
|
|
1451
1533
|
*out = sm;
|
|
1452
1534
|
return 0;
|
|
1453
1535
|
}
|
|
1454
1536
|
|
|
1455
|
-
static void submodule_cache_remove_item(
|
|
1456
|
-
git_submodule_cache *cache,
|
|
1457
|
-
git_submodule *item,
|
|
1458
|
-
bool free_after_remove)
|
|
1459
|
-
{
|
|
1460
|
-
git_strmap *map;
|
|
1461
|
-
const char *name, *alt;
|
|
1462
|
-
|
|
1463
|
-
if (!cache || !(map = cache->submodules) || !item)
|
|
1464
|
-
return;
|
|
1465
|
-
|
|
1466
|
-
name = item->name;
|
|
1467
|
-
alt = (item->path != item->name) ? item->path : NULL;
|
|
1468
|
-
|
|
1469
|
-
for (; name; name = alt, alt = NULL) {
|
|
1470
|
-
khiter_t pos = git_strmap_lookup_index(map, name);
|
|
1471
|
-
git_submodule *found;
|
|
1472
|
-
|
|
1473
|
-
if (!git_strmap_valid_index(map, pos))
|
|
1474
|
-
continue;
|
|
1475
|
-
|
|
1476
|
-
found = git_strmap_value_at(map, pos);
|
|
1477
|
-
|
|
1478
|
-
if (found != item)
|
|
1479
|
-
continue;
|
|
1480
|
-
|
|
1481
|
-
git_strmap_set_value_at(map, pos, NULL);
|
|
1482
|
-
git_strmap_delete_at(map, pos);
|
|
1483
|
-
|
|
1484
|
-
if (free_after_remove)
|
|
1485
|
-
git_submodule_free(found);
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1489
1537
|
static void submodule_release(git_submodule *sm)
|
|
1490
1538
|
{
|
|
1491
1539
|
if (!sm)
|
|
1492
1540
|
return;
|
|
1493
1541
|
|
|
1494
1542
|
if (sm->repo) {
|
|
1495
|
-
git_submodule_cache *cache = sm->repo->_submodules;
|
|
1496
1543
|
sm->repo = NULL;
|
|
1497
|
-
submodule_cache_remove_item(cache, sm, false);
|
|
1498
1544
|
}
|
|
1499
1545
|
|
|
1500
1546
|
if (sm->path != sm->name)
|
|
@@ -1513,54 +1559,6 @@ void git_submodule_free(git_submodule *sm)
|
|
|
1513
1559
|
GIT_REFCOUNT_DEC(sm, submodule_release);
|
|
1514
1560
|
}
|
|
1515
1561
|
|
|
1516
|
-
static int submodule_get(
|
|
1517
|
-
git_submodule **out,
|
|
1518
|
-
git_submodule_cache *cache,
|
|
1519
|
-
const char *name,
|
|
1520
|
-
const char *alternate)
|
|
1521
|
-
{
|
|
1522
|
-
int error = 0;
|
|
1523
|
-
khiter_t pos;
|
|
1524
|
-
git_submodule *sm;
|
|
1525
|
-
|
|
1526
|
-
pos = git_strmap_lookup_index(cache->submodules, name);
|
|
1527
|
-
|
|
1528
|
-
if (!git_strmap_valid_index(cache->submodules, pos) && alternate)
|
|
1529
|
-
pos = git_strmap_lookup_index(cache->submodules, alternate);
|
|
1530
|
-
|
|
1531
|
-
if (!git_strmap_valid_index(cache->submodules, pos)) {
|
|
1532
|
-
if ((error = submodule_alloc(&sm, cache, name)) < 0)
|
|
1533
|
-
return error;
|
|
1534
|
-
|
|
1535
|
-
/* insert value at name - if another thread beats us to it, then use
|
|
1536
|
-
* their record and release our own.
|
|
1537
|
-
*/
|
|
1538
|
-
pos = kh_put(str, cache->submodules, sm->name, &error);
|
|
1539
|
-
|
|
1540
|
-
if (error < 0)
|
|
1541
|
-
goto done;
|
|
1542
|
-
else if (error == 0) {
|
|
1543
|
-
git_submodule_free(sm);
|
|
1544
|
-
sm = git_strmap_value_at(cache->submodules, pos);
|
|
1545
|
-
} else {
|
|
1546
|
-
error = 0;
|
|
1547
|
-
git_strmap_set_value_at(cache->submodules, pos, sm);
|
|
1548
|
-
}
|
|
1549
|
-
} else {
|
|
1550
|
-
sm = git_strmap_value_at(cache->submodules, pos);
|
|
1551
|
-
}
|
|
1552
|
-
|
|
1553
|
-
done:
|
|
1554
|
-
if (error < 0)
|
|
1555
|
-
git_submodule_free(sm);
|
|
1556
|
-
else if (out) {
|
|
1557
|
-
GIT_REFCOUNT_INC(sm);
|
|
1558
|
-
*out = sm;
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
return error;
|
|
1562
|
-
}
|
|
1563
|
-
|
|
1564
1562
|
static int submodule_config_error(const char *property, const char *value)
|
|
1565
1563
|
{
|
|
1566
1564
|
giterr_set(GITERR_INVALID,
|
|
@@ -1613,12 +1611,12 @@ int git_submodule_parse_recurse(git_submodule_recurse_t *out, const char *value)
|
|
|
1613
1611
|
static int submodule_load_from_config(
|
|
1614
1612
|
const git_config_entry *entry, void *payload)
|
|
1615
1613
|
{
|
|
1616
|
-
git_submodule_cache *cache = payload;
|
|
1617
1614
|
const char *namestart, *property;
|
|
1618
1615
|
const char *key = entry->name, *value = entry->value, *path;
|
|
1619
1616
|
char *alternate = NULL, *replaced = NULL;
|
|
1620
1617
|
git_buf name = GIT_BUF_INIT;
|
|
1621
|
-
|
|
1618
|
+
lfc_data *data = payload;
|
|
1619
|
+
git_submodule *sm;
|
|
1622
1620
|
int error = 0;
|
|
1623
1621
|
|
|
1624
1622
|
if (git__prefixcmp(key, "submodule.") != 0)
|
|
@@ -1633,10 +1631,29 @@ static int submodule_load_from_config(
|
|
|
1633
1631
|
property++;
|
|
1634
1632
|
path = !strcasecmp(property, "path") ? value : NULL;
|
|
1635
1633
|
|
|
1636
|
-
if ((error = git_buf_set(&name, namestart, property - namestart -
|
|
1637
|
-
(error = submodule_get(&sm, cache, name.ptr, path)) < 0)
|
|
1634
|
+
if ((error = git_buf_set(&name, namestart, property - namestart -1)) < 0)
|
|
1638
1635
|
goto done;
|
|
1639
1636
|
|
|
1637
|
+
if (data->have_sm) {
|
|
1638
|
+
sm = data->sm;
|
|
1639
|
+
} else {
|
|
1640
|
+
khiter_t pos;
|
|
1641
|
+
git_strmap *map = data->map;
|
|
1642
|
+
pos = git_strmap_lookup_index(map, name.ptr);
|
|
1643
|
+
if (git_strmap_valid_index(map, pos)) {
|
|
1644
|
+
sm = git_strmap_value_at(map, pos);
|
|
1645
|
+
} else {
|
|
1646
|
+
if ((error = submodule_alloc(&sm, data->repo, name.ptr)) < 0)
|
|
1647
|
+
goto done;
|
|
1648
|
+
|
|
1649
|
+
git_strmap_insert(map, sm->name, sm, error);
|
|
1650
|
+
assert(error != 0);
|
|
1651
|
+
if (error < 0)
|
|
1652
|
+
goto done;
|
|
1653
|
+
error = 0;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1640
1657
|
sm->flags |= GIT_SUBMODULE_STATUS_IN_CONFIG;
|
|
1641
1658
|
|
|
1642
1659
|
/* Only from config might we get differing names & paths. If so, then
|
|
@@ -1648,7 +1665,7 @@ static int submodule_load_from_config(
|
|
|
1648
1665
|
*/
|
|
1649
1666
|
|
|
1650
1667
|
if (strcmp(sm->name, name.ptr) != 0) { /* name changed */
|
|
1651
|
-
if (!strcmp(sm->path, name.ptr)) { /* already set as path */
|
|
1668
|
+
if (sm->path && !strcmp(sm->path, name.ptr)) { /* already set as path */
|
|
1652
1669
|
replaced = sm->name;
|
|
1653
1670
|
sm->name = sm->path;
|
|
1654
1671
|
} else {
|
|
@@ -1674,7 +1691,6 @@ static int submodule_load_from_config(
|
|
|
1674
1691
|
|
|
1675
1692
|
/* Deregister under name being replaced */
|
|
1676
1693
|
if (replaced) {
|
|
1677
|
-
git_strmap_delete(cache->submodules, replaced);
|
|
1678
1694
|
git_submodule_free(sm);
|
|
1679
1695
|
git__free(replaced);
|
|
1680
1696
|
}
|
|
@@ -1682,7 +1698,6 @@ static int submodule_load_from_config(
|
|
|
1682
1698
|
/* Insert under alternate key */
|
|
1683
1699
|
if (alternate) {
|
|
1684
1700
|
void *old_sm = NULL;
|
|
1685
|
-
git_strmap_insert2(cache->submodules, alternate, sm, old_sm, error);
|
|
1686
1701
|
|
|
1687
1702
|
if (error < 0)
|
|
1688
1703
|
goto done;
|
|
@@ -1742,7 +1757,6 @@ static int submodule_load_from_config(
|
|
|
1742
1757
|
/* ignore other unknown submodule properties */
|
|
1743
1758
|
|
|
1744
1759
|
done:
|
|
1745
|
-
git_submodule_free(sm); /* offset refcount inc from submodule_get() */
|
|
1746
1760
|
git_buf_free(&name);
|
|
1747
1761
|
return error;
|
|
1748
1762
|
}
|
|
@@ -1764,86 +1778,11 @@ static int submodule_load_from_wd_lite(git_submodule *sm)
|
|
|
1764
1778
|
return 0;
|
|
1765
1779
|
}
|
|
1766
1780
|
|
|
1767
|
-
static int submodule_cache_refresh_from_index(
|
|
1768
|
-
git_submodule_cache *cache, git_index *idx)
|
|
1769
|
-
{
|
|
1770
|
-
int error;
|
|
1771
|
-
git_iterator *i;
|
|
1772
|
-
const git_index_entry *entry;
|
|
1773
|
-
|
|
1774
|
-
if ((error = git_iterator_for_index(&i, idx, 0, NULL, NULL)) < 0)
|
|
1775
|
-
return error;
|
|
1776
|
-
|
|
1777
|
-
while (!(error = git_iterator_advance(&entry, i))) {
|
|
1778
|
-
khiter_t pos = git_strmap_lookup_index(cache->submodules, entry->path);
|
|
1779
|
-
git_submodule *sm;
|
|
1780
|
-
|
|
1781
|
-
if (git_strmap_valid_index(cache->submodules, pos)) {
|
|
1782
|
-
sm = git_strmap_value_at(cache->submodules, pos);
|
|
1783
|
-
|
|
1784
|
-
if (S_ISGITLINK(entry->mode))
|
|
1785
|
-
submodule_update_from_index_entry(sm, entry);
|
|
1786
|
-
else
|
|
1787
|
-
sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE;
|
|
1788
|
-
} else if (S_ISGITLINK(entry->mode)) {
|
|
1789
|
-
if (!submodule_get(&sm, cache, entry->path, NULL)) {
|
|
1790
|
-
submodule_update_from_index_entry(sm, entry);
|
|
1791
|
-
git_submodule_free(sm);
|
|
1792
|
-
}
|
|
1793
|
-
}
|
|
1794
|
-
}
|
|
1795
|
-
|
|
1796
|
-
if (error == GIT_ITEROVER)
|
|
1797
|
-
error = 0;
|
|
1798
|
-
|
|
1799
|
-
git_iterator_free(i);
|
|
1800
|
-
|
|
1801
|
-
return error;
|
|
1802
|
-
}
|
|
1803
|
-
|
|
1804
|
-
static int submodule_cache_refresh_from_head(
|
|
1805
|
-
git_submodule_cache *cache, git_tree *head)
|
|
1806
|
-
{
|
|
1807
|
-
int error;
|
|
1808
|
-
git_iterator *i;
|
|
1809
|
-
const git_index_entry *entry;
|
|
1810
|
-
|
|
1811
|
-
if ((error = git_iterator_for_tree(&i, head, 0, NULL, NULL)) < 0)
|
|
1812
|
-
return error;
|
|
1813
|
-
|
|
1814
|
-
while (!(error = git_iterator_advance(&entry, i))) {
|
|
1815
|
-
khiter_t pos = git_strmap_lookup_index(cache->submodules, entry->path);
|
|
1816
|
-
git_submodule *sm;
|
|
1817
|
-
|
|
1818
|
-
if (git_strmap_valid_index(cache->submodules, pos)) {
|
|
1819
|
-
sm = git_strmap_value_at(cache->submodules, pos);
|
|
1820
|
-
|
|
1821
|
-
if (S_ISGITLINK(entry->mode))
|
|
1822
|
-
submodule_update_from_head_data(sm, entry->mode, &entry->id);
|
|
1823
|
-
else
|
|
1824
|
-
sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE;
|
|
1825
|
-
} else if (S_ISGITLINK(entry->mode)) {
|
|
1826
|
-
if (!submodule_get(&sm, cache, entry->path, NULL)) {
|
|
1827
|
-
submodule_update_from_head_data(
|
|
1828
|
-
sm, entry->mode, &entry->id);
|
|
1829
|
-
git_submodule_free(sm);
|
|
1830
|
-
}
|
|
1831
|
-
}
|
|
1832
|
-
}
|
|
1833
|
-
|
|
1834
|
-
if (error == GIT_ITEROVER)
|
|
1835
|
-
error = 0;
|
|
1836
|
-
|
|
1837
|
-
git_iterator_free(i);
|
|
1838
|
-
|
|
1839
|
-
return error;
|
|
1840
|
-
}
|
|
1841
|
-
|
|
1842
1781
|
static git_config_backend *open_gitmodules(
|
|
1843
|
-
|
|
1782
|
+
git_repository *repo,
|
|
1844
1783
|
int okay_to_create)
|
|
1845
1784
|
{
|
|
1846
|
-
const char *workdir = git_repository_workdir(
|
|
1785
|
+
const char *workdir = git_repository_workdir(repo);
|
|
1847
1786
|
git_buf path = GIT_BUF_INIT;
|
|
1848
1787
|
git_config_backend *mods = NULL;
|
|
1849
1788
|
|
|
@@ -1868,199 +1807,6 @@ static git_config_backend *open_gitmodules(
|
|
|
1868
1807
|
return mods;
|
|
1869
1808
|
}
|
|
1870
1809
|
|
|
1871
|
-
static void submodule_cache_free(git_submodule_cache *cache)
|
|
1872
|
-
{
|
|
1873
|
-
git_submodule *sm;
|
|
1874
|
-
|
|
1875
|
-
if (!cache)
|
|
1876
|
-
return;
|
|
1877
|
-
|
|
1878
|
-
git_strmap_foreach_value(cache->submodules, sm, {
|
|
1879
|
-
sm->repo = NULL; /* disconnect from repo */
|
|
1880
|
-
git_submodule_free(sm);
|
|
1881
|
-
});
|
|
1882
|
-
git_strmap_free(cache->submodules);
|
|
1883
|
-
|
|
1884
|
-
git_buf_free(&cache->gitmodules_path);
|
|
1885
|
-
git_mutex_free(&cache->lock);
|
|
1886
|
-
git__free(cache);
|
|
1887
|
-
}
|
|
1888
|
-
|
|
1889
|
-
static int submodule_cache_alloc(
|
|
1890
|
-
git_submodule_cache **out, git_repository *repo)
|
|
1891
|
-
{
|
|
1892
|
-
git_submodule_cache *cache = git__calloc(1, sizeof(git_submodule_cache));
|
|
1893
|
-
GITERR_CHECK_ALLOC(cache);
|
|
1894
|
-
|
|
1895
|
-
if (git_mutex_init(&cache->lock) < 0) {
|
|
1896
|
-
giterr_set(GITERR_OS, "Unable to initialize submodule cache lock");
|
|
1897
|
-
git__free(cache);
|
|
1898
|
-
return -1;
|
|
1899
|
-
}
|
|
1900
|
-
|
|
1901
|
-
if (git_strmap_alloc(&cache->submodules) < 0) {
|
|
1902
|
-
submodule_cache_free(cache);
|
|
1903
|
-
return -1;
|
|
1904
|
-
}
|
|
1905
|
-
|
|
1906
|
-
cache->repo = repo;
|
|
1907
|
-
git_buf_init(&cache->gitmodules_path, 0);
|
|
1908
|
-
|
|
1909
|
-
*out = cache;
|
|
1910
|
-
return 0;
|
|
1911
|
-
}
|
|
1912
|
-
|
|
1913
|
-
static int submodule_cache_refresh(git_submodule_cache *cache, int refresh)
|
|
1914
|
-
{
|
|
1915
|
-
int error = 0, update_index, update_head, update_gitmod;
|
|
1916
|
-
git_index *idx = NULL;
|
|
1917
|
-
git_tree *head = NULL;
|
|
1918
|
-
const char *wd = NULL;
|
|
1919
|
-
git_buf path = GIT_BUF_INIT;
|
|
1920
|
-
git_submodule *sm;
|
|
1921
|
-
git_config_backend *mods = NULL;
|
|
1922
|
-
uint32_t mask;
|
|
1923
|
-
|
|
1924
|
-
if (!cache || !cache->repo || !refresh)
|
|
1925
|
-
return 0;
|
|
1926
|
-
|
|
1927
|
-
if (git_mutex_lock(&cache->lock) < 0) {
|
|
1928
|
-
giterr_set(GITERR_OS, "Unable to acquire lock on submodule cache");
|
|
1929
|
-
return -1;
|
|
1930
|
-
}
|
|
1931
|
-
|
|
1932
|
-
/* get sources that we will need to check */
|
|
1933
|
-
|
|
1934
|
-
if (git_repository_index(&idx, cache->repo) < 0)
|
|
1935
|
-
giterr_clear();
|
|
1936
|
-
if (git_repository_head_tree(&head, cache->repo) < 0)
|
|
1937
|
-
giterr_clear();
|
|
1938
|
-
|
|
1939
|
-
wd = git_repository_workdir(cache->repo);
|
|
1940
|
-
if (wd && (error = git_buf_joinpath(&path, wd, GIT_MODULES_FILE)) < 0)
|
|
1941
|
-
goto cleanup;
|
|
1942
|
-
|
|
1943
|
-
/* check for invalidation */
|
|
1944
|
-
|
|
1945
|
-
if (refresh == CACHE_FLUSH)
|
|
1946
|
-
update_index = update_head = update_gitmod = true;
|
|
1947
|
-
else {
|
|
1948
|
-
update_index =
|
|
1949
|
-
!idx || git_index__changed_relative_to(idx, &cache->index_stamp);
|
|
1950
|
-
update_head =
|
|
1951
|
-
!head || !git_oid_equal(&cache->head_id, git_tree_id(head));
|
|
1952
|
-
|
|
1953
|
-
update_gitmod = (wd != NULL) ?
|
|
1954
|
-
git_futils_filestamp_check(&cache->gitmodules_stamp, path.ptr) :
|
|
1955
|
-
(cache->gitmodules_stamp.mtime != 0);
|
|
1956
|
-
}
|
|
1957
|
-
|
|
1958
|
-
/* clear submodule flags that are to be refreshed */
|
|
1959
|
-
|
|
1960
|
-
mask = 0;
|
|
1961
|
-
if (!idx || update_index)
|
|
1962
|
-
mask |= GIT_SUBMODULE_STATUS_IN_INDEX |
|
|
1963
|
-
GIT_SUBMODULE_STATUS__INDEX_FLAGS |
|
|
1964
|
-
GIT_SUBMODULE_STATUS__INDEX_OID_VALID |
|
|
1965
|
-
GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES;
|
|
1966
|
-
if (!head || update_head)
|
|
1967
|
-
mask |= GIT_SUBMODULE_STATUS_IN_HEAD |
|
|
1968
|
-
GIT_SUBMODULE_STATUS__HEAD_OID_VALID;
|
|
1969
|
-
if (update_gitmod)
|
|
1970
|
-
mask |= GIT_SUBMODULE_STATUS_IN_CONFIG;
|
|
1971
|
-
if (mask != 0)
|
|
1972
|
-
mask |= GIT_SUBMODULE_STATUS_IN_WD |
|
|
1973
|
-
GIT_SUBMODULE_STATUS__WD_SCANNED |
|
|
1974
|
-
GIT_SUBMODULE_STATUS__WD_FLAGS |
|
|
1975
|
-
GIT_SUBMODULE_STATUS__WD_OID_VALID;
|
|
1976
|
-
else
|
|
1977
|
-
goto cleanup; /* nothing to do */
|
|
1978
|
-
|
|
1979
|
-
submodule_cache_clear_flags(cache, mask);
|
|
1980
|
-
|
|
1981
|
-
/* add back submodule information from index */
|
|
1982
|
-
|
|
1983
|
-
if (idx && update_index) {
|
|
1984
|
-
if ((error = submodule_cache_refresh_from_index(cache, idx)) < 0)
|
|
1985
|
-
goto cleanup;
|
|
1986
|
-
|
|
1987
|
-
git_futils_filestamp_set(
|
|
1988
|
-
&cache->index_stamp, git_index__filestamp(idx));
|
|
1989
|
-
}
|
|
1990
|
-
|
|
1991
|
-
/* add submodule information from HEAD */
|
|
1992
|
-
|
|
1993
|
-
if (head && update_head) {
|
|
1994
|
-
if ((error = submodule_cache_refresh_from_head(cache, head)) < 0)
|
|
1995
|
-
goto cleanup;
|
|
1996
|
-
|
|
1997
|
-
git_oid_cpy(&cache->head_id, git_tree_id(head));
|
|
1998
|
-
}
|
|
1999
|
-
|
|
2000
|
-
/* add submodule information from .gitmodules */
|
|
2001
|
-
|
|
2002
|
-
if (wd && update_gitmod > 0) {
|
|
2003
|
-
if ((mods = open_gitmodules(cache, false)) != NULL &&
|
|
2004
|
-
(error = git_config_file_foreach(
|
|
2005
|
-
mods, submodule_load_from_config, cache)) < 0)
|
|
2006
|
-
goto cleanup;
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
/* shallow scan submodules in work tree as needed */
|
|
2010
|
-
|
|
2011
|
-
if (wd && mask != 0) {
|
|
2012
|
-
git_strmap_foreach_value(cache->submodules, sm, {
|
|
2013
|
-
submodule_load_from_wd_lite(sm);
|
|
2014
|
-
});
|
|
2015
|
-
}
|
|
2016
|
-
|
|
2017
|
-
/* remove submodules that no longer exist */
|
|
2018
|
-
|
|
2019
|
-
git_strmap_foreach_value(cache->submodules, sm, {
|
|
2020
|
-
/* purge unless in HEAD, index, or .gitmodules; no sm for wd only */
|
|
2021
|
-
if (sm != NULL &&
|
|
2022
|
-
!(sm->flags &
|
|
2023
|
-
(GIT_SUBMODULE_STATUS_IN_HEAD |
|
|
2024
|
-
GIT_SUBMODULE_STATUS_IN_INDEX |
|
|
2025
|
-
GIT_SUBMODULE_STATUS_IN_CONFIG)))
|
|
2026
|
-
submodule_cache_remove_item(cache, sm, true);
|
|
2027
|
-
});
|
|
2028
|
-
|
|
2029
|
-
cleanup:
|
|
2030
|
-
git_config_file_free(mods);
|
|
2031
|
-
|
|
2032
|
-
/* TODO: if we got an error, mark submodule config as invalid? */
|
|
2033
|
-
|
|
2034
|
-
git_mutex_unlock(&cache->lock);
|
|
2035
|
-
|
|
2036
|
-
git_index_free(idx);
|
|
2037
|
-
git_tree_free(head);
|
|
2038
|
-
git_buf_free(&path);
|
|
2039
|
-
|
|
2040
|
-
return error;
|
|
2041
|
-
}
|
|
2042
|
-
|
|
2043
|
-
static int submodule_cache_init(git_repository *repo, int cache_refresh)
|
|
2044
|
-
{
|
|
2045
|
-
int error = 0;
|
|
2046
|
-
git_submodule_cache *cache = NULL;
|
|
2047
|
-
|
|
2048
|
-
/* if submodules already exist, just refresh as requested */
|
|
2049
|
-
if (repo->_submodules)
|
|
2050
|
-
return submodule_cache_refresh(repo->_submodules, cache_refresh);
|
|
2051
|
-
|
|
2052
|
-
/* otherwise create a new cache, load it, and atomically swap it in */
|
|
2053
|
-
if (!(error = submodule_cache_alloc(&cache, repo)) &&
|
|
2054
|
-
!(error = submodule_cache_refresh(cache, CACHE_FLUSH)))
|
|
2055
|
-
cache = git__compare_and_swap(&repo->_submodules, NULL, cache);
|
|
2056
|
-
|
|
2057
|
-
/* might have raced with another thread to set cache, so free if needed */
|
|
2058
|
-
if (cache)
|
|
2059
|
-
submodule_cache_free(cache);
|
|
2060
|
-
|
|
2061
|
-
return error;
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
1810
|
/* Lookup name of remote of the local tracking branch HEAD points to */
|
|
2065
1811
|
static int lookup_head_remote_key(git_buf *remote_name, git_repository *repo)
|
|
2066
1812
|
{
|