Teach ref iteration module about submodules
We will use this in a later patch to extend setup_revisions() to load revisions directly from a submodule. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Heiko Voigt committed
Jul 7, 2010 at 15:39 UTC
0bad611b1ebacf170976a10690bd0169f8d372bf
3 files changed
+127
-32
cache.h
+3
@@ -641,6 +641,9 @@ extern char *git_pathdup(const char *fmt, ...)
641
/* Return a statically allocated filename matching the sha1 signature */
642
extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
643
extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
644
+extern char *git_path_submodule(const char *path, const char *fmt, ...)
645
+ __attribute__((format (printf, 2, 3)));
646
+
647
extern char *sha1_file_name(const unsigned char *sha1);
648
extern char *sha1_pack_name(const unsigned char *sha1);
649
extern char *sha1_pack_index_name(const unsigned char *sha1);
path.c
+38
@@ -122,6 +122,44 @@ char *git_path(const char *fmt, ...)
122
return cleanup_path(pathname);
123
}
124
125
+char *git_path_submodule(const char *path, const char *fmt, ...)
126
+{
127
+ char *pathname = get_pathname();
128
+ struct strbuf buf = STRBUF_INIT;
129
+ const char *git_dir;
130
+ va_list args;
131
+ unsigned len;
132
+
133
+ len = strlen(path);
134
+ if (len > PATH_MAX-100)
135
+ return bad_path;
136
+
137
+ strbuf_addstr(&buf, path);
138
+ if (len && path[len-1] != '/')
139
+ strbuf_addch(&buf, '/');
140
+ strbuf_addstr(&buf, ".git");
141
+
142
+ git_dir = read_gitfile_gently(buf.buf);
143
+ if (git_dir) {
144
+ strbuf_reset(&buf);
145
+ strbuf_addstr(&buf, git_dir);
146
+ }
147
+ strbuf_addch(&buf, '/');
148
+
149
+ if (buf.len >= PATH_MAX)
150
+ return bad_path;
151
+ memcpy(pathname, buf.buf, buf.len + 1);
152
+
153
+ strbuf_release(&buf);
154
+ len = strlen(pathname);
155
+
156
+ va_start(args, fmt);
157
+ len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args);
158
+ va_end(args);
159
+ if (len >= PATH_MAX)
160
+ return bad_path;
161
+ return cleanup_path(pathname);
162
+}
163
164
/* git_mkstemp() - create tmp file honoring TMPDIR variable */
165
int git_mkstemp(char *path, size_t len, const char *template)
refs.c
+86
-32
@@ -157,7 +157,7 @@ static struct cached_refs {
157
char did_packed;
158
struct ref_list *loose;
159
struct ref_list *packed;
160
-} cached_refs;
160
+} cached_refs, submodule_refs;
161
static struct ref_list *current_ref;
162
163
static struct ref_list *extra_refs;
@@ -229,23 +229,45 @@ void clear_extra_refs(void)
229
extra_refs = NULL;
230
}
231
232
-static struct ref_list *get_packed_refs(void)
232
+static struct ref_list *get_packed_refs(const char *submodule)
233
{
234
- if (!cached_refs.did_packed) {
235
- FILE *f = fopen(git_path("packed-refs"), "r");
236
- cached_refs.packed = NULL;
234
+ const char *packed_refs_file;
235
+ struct cached_refs *refs;
236
+
237
+ if (submodule) {
238
+ packed_refs_file = git_path_submodule(submodule, "packed-refs");
239
+ refs = &submodule_refs;
240
+ free_ref_list(refs->packed);
241
+ } else {
242
+ packed_refs_file = git_path("packed-refs");
243
+ refs = &cached_refs;
244
+ }
245
+
246
+ if (!refs->did_packed || submodule) {
247
+ FILE *f = fopen(packed_refs_file, "r");
248
+ refs->packed = NULL;
249
if (f) {
238
- read_packed_refs(f, &cached_refs);
250
+ read_packed_refs(f, refs);
251
fclose(f);
252
}
241
- cached_refs.did_packed = 1;
253
+ refs->did_packed = 1;
254
}
243
- return cached_refs.packed;
255
+ return refs->packed;
256
}
257
246
-static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
258
+static struct ref_list *get_ref_dir(const char *submodule, const char *base,
259
+ struct ref_list *list)
260
{
248
- DIR *dir = opendir(git_path("%s", base));
261
+ DIR *dir;
262
+ const char *path;
263
+
264
+ if (submodule)
265
+ path = git_path_submodule(submodule, "%s", base);
266
+ else
267
+ path = git_path("%s", base);
268
+
269
+
270
+ dir = opendir(path);
271
272
if (dir) {
273
struct dirent *de;
@@ -261,6 +283,7 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
283
struct stat st;
284
int flag;
285
int namelen;
286
+ const char *refdir;
287
288
if (de->d_name[0] == '.')
289
continue;
@@ -270,16 +293,27 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
293
if (has_extension(de->d_name, ".lock"))
294
continue;
295
memcpy(ref + baselen, de->d_name, namelen+1);
273
- if (stat(git_path("%s", ref), &st) < 0)
296
+ refdir = submodule
297
+ ? git_path_submodule(submodule, "%s", ref)
298
+ : git_path("%s", ref);
299
+ if (stat(refdir, &st) < 0)
300
continue;
301
if (S_ISDIR(st.st_mode)) {
276
- list = get_ref_dir(ref, list);
302
+ list = get_ref_dir(submodule, ref, list);
303
continue;
304
}
279
- if (!resolve_ref(ref, sha1, 1, &flag)) {
305
+ if (submodule) {
306
hashclr(sha1);
281
- flag |= REF_BROKEN;
282
- }
307
+ flag = 0;
308
+ if (resolve_gitlink_ref(submodule, ref, sha1) < 0) {
309
+ hashclr(sha1);
310
+ flag |= REF_BROKEN;
311
+ }
312
+ } else
313
+ if (!resolve_ref(ref, sha1, 1, &flag)) {
314
+ hashclr(sha1);
315
+ flag |= REF_BROKEN;
316
+ }
317
list = add_ref(ref, sha1, flag, list, NULL);
318
}
319
free(ref);
@@ -322,10 +356,16 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
356
for_each_rawref(warn_if_dangling_symref, &data);
357
}
358
325
-static struct ref_list *get_loose_refs(void)
359
+static struct ref_list *get_loose_refs(const char *submodule)
360
{
361
+ if (submodule) {
362
+ free_ref_list(submodule_refs.loose);
363
+ submodule_refs.loose = get_ref_dir(submodule, "refs", NULL);
364
+ return submodule_refs.loose;
365
+ }
366
+
367
if (!cached_refs.did_loose) {
328
- cached_refs.loose = get_ref_dir("refs", NULL);
368
+ cached_refs.loose = get_ref_dir(NULL, "refs", NULL);
369
cached_refs.did_loose = 1;
370
}
371
return cached_refs.loose;
@@ -459,7 +499,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
499
git_snpath(path, sizeof(path), "%s", ref);
500
/* Special case: non-existing file. */
501
if (lstat(path, &st) < 0) {
462
- struct ref_list *list = get_packed_refs();
502
+ struct ref_list *list = get_packed_refs(NULL);
503
while (list) {
504
if (!strcmp(ref, list->name)) {
505
hashcpy(sha1, list->sha1);
@@ -588,7 +628,7 @@ int peel_ref(const char *ref, unsigned char *sha1)
628
return -1;
629
630
if ((flag & REF_ISPACKED)) {
591
- struct ref_list *list = get_packed_refs();
631
+ struct ref_list *list = get_packed_refs(NULL);
632
633
while (list) {
634
if (!strcmp(list->name, ref)) {
@@ -615,12 +655,12 @@ fallback:
655
return -1;
656
}
657
618
-static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
619
- int flags, void *cb_data)
658
+static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,
659
+ int trim, int flags, void *cb_data)
660
{
661
int retval = 0;
622
- struct ref_list *packed = get_packed_refs();
623
- struct ref_list *loose = get_loose_refs();
662
+ struct ref_list *packed = get_packed_refs(submodule);
663
+ struct ref_list *loose = get_loose_refs(submodule);
664
665
struct ref_list *extra;
666
@@ -657,24 +697,38 @@ end_each:
697
return retval;
698
}
699
660
-int head_ref(each_ref_fn fn, void *cb_data)
700
+
701
+static int do_head_ref(const char *submodule, each_ref_fn fn, void *cb_data)
702
{
703
unsigned char sha1[20];
704
int flag;
705
706
+ if (submodule) {
707
+ if (resolve_gitlink_ref(submodule, "HEAD", sha1) == 0)
708
+ return fn("HEAD", sha1, 0, cb_data);
709
+
710
+ return 0;
711
+ }
712
+
713
if (resolve_ref("HEAD", sha1, 1, &flag))
714
return fn("HEAD", sha1, flag, cb_data);
715
+
716
return 0;
717
}
718
719
+int head_ref(each_ref_fn fn, void *cb_data)
720
+{
721
+ return do_head_ref(NULL, fn, cb_data);
722
+}
723
+
724
int for_each_ref(each_ref_fn fn, void *cb_data)
725
{
672
- return do_for_each_ref("refs/", fn, 0, 0, cb_data);
726
+ return do_for_each_ref(NULL, "refs/", fn, 0, 0, cb_data);
727
}
728
729
int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
730
{
677
- return do_for_each_ref(prefix, fn, strlen(prefix), 0, cb_data);
731
+ return do_for_each_ref(NULL, prefix, fn, strlen(prefix), 0, cb_data);
732
}
733
734
int for_each_tag_ref(each_ref_fn fn, void *cb_data)
@@ -694,7 +748,7 @@ int for_each_remote_ref(each_ref_fn fn, void *cb_data)
748
749
int for_each_replace_ref(each_ref_fn fn, void *cb_data)
750
{
697
- return do_for_each_ref("refs/replace/", fn, 13, 0, cb_data);
751
+ return do_for_each_ref(NULL, "refs/replace/", fn, 13, 0, cb_data);
752
}
753
754
int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
@@ -734,7 +788,7 @@ int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
788
789
int for_each_rawref(each_ref_fn fn, void *cb_data)
790
{
737
- return do_for_each_ref("refs/", fn, 0,
791
+ return do_for_each_ref(NULL, "refs/", fn, 0,
792
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
793
}
794
@@ -958,7 +1012,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
1012
* name is a proper prefix of our refname.
1013
*/
1014
if (missing &&
961
- !is_refname_available(ref, NULL, get_packed_refs(), 0)) {
1015
+ !is_refname_available(ref, NULL, get_packed_refs(NULL), 0)) {
1016
last_errno = ENOTDIR;
1017
goto error_return;
1018
}
@@ -1021,7 +1075,7 @@ static int repack_without_ref(const char *refname)
1075
int fd;
1076
int found = 0;
1077
1024
- packed_ref_list = get_packed_refs();
1078
+ packed_ref_list = get_packed_refs(NULL);
1079
for (list = packed_ref_list; list; list = list->next) {
1080
if (!strcmp(refname, list->name)) {
1081
found = 1;
@@ -1110,10 +1164,10 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
1164
if (!symref)
1165
return error("refname %s not found", oldref);
1166
1113
- if (!is_refname_available(newref, oldref, get_packed_refs(), 0))
1167
+ if (!is_refname_available(newref, oldref, get_packed_refs(NULL), 0))
1168
return 1;
1169
1116
- if (!is_refname_available(newref, oldref, get_loose_refs(), 0))
1170
+ if (!is_refname_available(newref, oldref, get_loose_refs(NULL), 0))
1171
return 1;
1172
1173
lock = lock_ref_sha1_basic(renamed_ref, NULL, 0, NULL);