rugged 0.23.0b2 → 0.23.0b4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/rugged/rugged_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
|
{
|