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>
This commit is contained in:
parent
78db709ae5
commit
0bad611b1e
3
cache.h
3
cache.h
@ -641,6 +641,9 @@ extern char *git_pathdup(const char *fmt, ...)
|
||||
/* Return a statically allocated filename matching the sha1 signature */
|
||||
extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
|
||||
extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
|
||||
extern char *git_path_submodule(const char *path, const char *fmt, ...)
|
||||
__attribute__((format (printf, 2, 3)));
|
||||
|
||||
extern char *sha1_file_name(const unsigned char *sha1);
|
||||
extern char *sha1_pack_name(const unsigned char *sha1);
|
||||
extern char *sha1_pack_index_name(const unsigned char *sha1);
|
||||
|
38
path.c
38
path.c
@ -122,6 +122,44 @@ char *git_path(const char *fmt, ...)
|
||||
return cleanup_path(pathname);
|
||||
}
|
||||
|
||||
char *git_path_submodule(const char *path, const char *fmt, ...)
|
||||
{
|
||||
char *pathname = get_pathname();
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
const char *git_dir;
|
||||
va_list args;
|
||||
unsigned len;
|
||||
|
||||
len = strlen(path);
|
||||
if (len > PATH_MAX-100)
|
||||
return bad_path;
|
||||
|
||||
strbuf_addstr(&buf, path);
|
||||
if (len && path[len-1] != '/')
|
||||
strbuf_addch(&buf, '/');
|
||||
strbuf_addstr(&buf, ".git");
|
||||
|
||||
git_dir = read_gitfile_gently(buf.buf);
|
||||
if (git_dir) {
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addstr(&buf, git_dir);
|
||||
}
|
||||
strbuf_addch(&buf, '/');
|
||||
|
||||
if (buf.len >= PATH_MAX)
|
||||
return bad_path;
|
||||
memcpy(pathname, buf.buf, buf.len + 1);
|
||||
|
||||
strbuf_release(&buf);
|
||||
len = strlen(pathname);
|
||||
|
||||
va_start(args, fmt);
|
||||
len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args);
|
||||
va_end(args);
|
||||
if (len >= PATH_MAX)
|
||||
return bad_path;
|
||||
return cleanup_path(pathname);
|
||||
}
|
||||
|
||||
/* git_mkstemp() - create tmp file honoring TMPDIR variable */
|
||||
int git_mkstemp(char *path, size_t len, const char *template)
|
||||
|
120
refs.c
120
refs.c
@ -157,7 +157,7 @@ static struct cached_refs {
|
||||
char did_packed;
|
||||
struct ref_list *loose;
|
||||
struct ref_list *packed;
|
||||
} cached_refs;
|
||||
} cached_refs, submodule_refs;
|
||||
static struct ref_list *current_ref;
|
||||
|
||||
static struct ref_list *extra_refs;
|
||||
@ -229,23 +229,45 @@ void clear_extra_refs(void)
|
||||
extra_refs = NULL;
|
||||
}
|
||||
|
||||
static struct ref_list *get_packed_refs(void)
|
||||
static struct ref_list *get_packed_refs(const char *submodule)
|
||||
{
|
||||
if (!cached_refs.did_packed) {
|
||||
FILE *f = fopen(git_path("packed-refs"), "r");
|
||||
cached_refs.packed = NULL;
|
||||
if (f) {
|
||||
read_packed_refs(f, &cached_refs);
|
||||
fclose(f);
|
||||
}
|
||||
cached_refs.did_packed = 1;
|
||||
}
|
||||
return cached_refs.packed;
|
||||
const char *packed_refs_file;
|
||||
struct cached_refs *refs;
|
||||
|
||||
if (submodule) {
|
||||
packed_refs_file = git_path_submodule(submodule, "packed-refs");
|
||||
refs = &submodule_refs;
|
||||
free_ref_list(refs->packed);
|
||||
} else {
|
||||
packed_refs_file = git_path("packed-refs");
|
||||
refs = &cached_refs;
|
||||
}
|
||||
|
||||
static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
|
||||
if (!refs->did_packed || submodule) {
|
||||
FILE *f = fopen(packed_refs_file, "r");
|
||||
refs->packed = NULL;
|
||||
if (f) {
|
||||
read_packed_refs(f, refs);
|
||||
fclose(f);
|
||||
}
|
||||
refs->did_packed = 1;
|
||||
}
|
||||
return refs->packed;
|
||||
}
|
||||
|
||||
static struct ref_list *get_ref_dir(const char *submodule, const char *base,
|
||||
struct ref_list *list)
|
||||
{
|
||||
DIR *dir = opendir(git_path("%s", base));
|
||||
DIR *dir;
|
||||
const char *path;
|
||||
|
||||
if (submodule)
|
||||
path = git_path_submodule(submodule, "%s", base);
|
||||
else
|
||||
path = git_path("%s", base);
|
||||
|
||||
|
||||
dir = opendir(path);
|
||||
|
||||
if (dir) {
|
||||
struct dirent *de;
|
||||
@ -261,6 +283,7 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
|
||||
struct stat st;
|
||||
int flag;
|
||||
int namelen;
|
||||
const char *refdir;
|
||||
|
||||
if (de->d_name[0] == '.')
|
||||
continue;
|
||||
@ -270,12 +293,23 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
|
||||
if (has_extension(de->d_name, ".lock"))
|
||||
continue;
|
||||
memcpy(ref + baselen, de->d_name, namelen+1);
|
||||
if (stat(git_path("%s", ref), &st) < 0)
|
||||
refdir = submodule
|
||||
? git_path_submodule(submodule, "%s", ref)
|
||||
: git_path("%s", ref);
|
||||
if (stat(refdir, &st) < 0)
|
||||
continue;
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
list = get_ref_dir(ref, list);
|
||||
list = get_ref_dir(submodule, ref, list);
|
||||
continue;
|
||||
}
|
||||
if (submodule) {
|
||||
hashclr(sha1);
|
||||
flag = 0;
|
||||
if (resolve_gitlink_ref(submodule, ref, sha1) < 0) {
|
||||
hashclr(sha1);
|
||||
flag |= REF_BROKEN;
|
||||
}
|
||||
} else
|
||||
if (!resolve_ref(ref, sha1, 1, &flag)) {
|
||||
hashclr(sha1);
|
||||
flag |= REF_BROKEN;
|
||||
@ -322,10 +356,16 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
|
||||
for_each_rawref(warn_if_dangling_symref, &data);
|
||||
}
|
||||
|
||||
static struct ref_list *get_loose_refs(void)
|
||||
static struct ref_list *get_loose_refs(const char *submodule)
|
||||
{
|
||||
if (submodule) {
|
||||
free_ref_list(submodule_refs.loose);
|
||||
submodule_refs.loose = get_ref_dir(submodule, "refs", NULL);
|
||||
return submodule_refs.loose;
|
||||
}
|
||||
|
||||
if (!cached_refs.did_loose) {
|
||||
cached_refs.loose = get_ref_dir("refs", NULL);
|
||||
cached_refs.loose = get_ref_dir(NULL, "refs", NULL);
|
||||
cached_refs.did_loose = 1;
|
||||
}
|
||||
return cached_refs.loose;
|
||||
@ -459,7 +499,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
|
||||
git_snpath(path, sizeof(path), "%s", ref);
|
||||
/* Special case: non-existing file. */
|
||||
if (lstat(path, &st) < 0) {
|
||||
struct ref_list *list = get_packed_refs();
|
||||
struct ref_list *list = get_packed_refs(NULL);
|
||||
while (list) {
|
||||
if (!strcmp(ref, list->name)) {
|
||||
hashcpy(sha1, list->sha1);
|
||||
@ -588,7 +628,7 @@ int peel_ref(const char *ref, unsigned char *sha1)
|
||||
return -1;
|
||||
|
||||
if ((flag & REF_ISPACKED)) {
|
||||
struct ref_list *list = get_packed_refs();
|
||||
struct ref_list *list = get_packed_refs(NULL);
|
||||
|
||||
while (list) {
|
||||
if (!strcmp(list->name, ref)) {
|
||||
@ -615,12 +655,12 @@ fallback:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
|
||||
int flags, void *cb_data)
|
||||
static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,
|
||||
int trim, int flags, void *cb_data)
|
||||
{
|
||||
int retval = 0;
|
||||
struct ref_list *packed = get_packed_refs();
|
||||
struct ref_list *loose = get_loose_refs();
|
||||
struct ref_list *packed = get_packed_refs(submodule);
|
||||
struct ref_list *loose = get_loose_refs(submodule);
|
||||
|
||||
struct ref_list *extra;
|
||||
|
||||
@ -657,24 +697,38 @@ end_each:
|
||||
return retval;
|
||||
}
|
||||
|
||||
int head_ref(each_ref_fn fn, void *cb_data)
|
||||
|
||||
static int do_head_ref(const char *submodule, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
unsigned char sha1[20];
|
||||
int flag;
|
||||
|
||||
if (submodule) {
|
||||
if (resolve_gitlink_ref(submodule, "HEAD", sha1) == 0)
|
||||
return fn("HEAD", sha1, 0, cb_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (resolve_ref("HEAD", sha1, 1, &flag))
|
||||
return fn("HEAD", sha1, flag, cb_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int head_ref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_head_ref(NULL, fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_ref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref("refs/", fn, 0, 0, cb_data);
|
||||
return do_for_each_ref(NULL, "refs/", fn, 0, 0, cb_data);
|
||||
}
|
||||
|
||||
int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(prefix, fn, strlen(prefix), 0, cb_data);
|
||||
return do_for_each_ref(NULL, prefix, fn, strlen(prefix), 0, cb_data);
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
int for_each_replace_ref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref("refs/replace/", fn, 13, 0, cb_data);
|
||||
return do_for_each_ref(NULL, "refs/replace/", fn, 13, 0, cb_data);
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
int for_each_rawref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref("refs/", fn, 0,
|
||||
return do_for_each_ref(NULL, "refs/", fn, 0,
|
||||
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
|
||||
}
|
||||
|
||||
@ -958,7 +1012,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
|
||||
* name is a proper prefix of our refname.
|
||||
*/
|
||||
if (missing &&
|
||||
!is_refname_available(ref, NULL, get_packed_refs(), 0)) {
|
||||
!is_refname_available(ref, NULL, get_packed_refs(NULL), 0)) {
|
||||
last_errno = ENOTDIR;
|
||||
goto error_return;
|
||||
}
|
||||
@ -1021,7 +1075,7 @@ static int repack_without_ref(const char *refname)
|
||||
int fd;
|
||||
int found = 0;
|
||||
|
||||
packed_ref_list = get_packed_refs();
|
||||
packed_ref_list = get_packed_refs(NULL);
|
||||
for (list = packed_ref_list; list; list = list->next) {
|
||||
if (!strcmp(refname, list->name)) {
|
||||
found = 1;
|
||||
@ -1110,10 +1164,10 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
|
||||
if (!symref)
|
||||
return error("refname %s not found", oldref);
|
||||
|
||||
if (!is_refname_available(newref, oldref, get_packed_refs(), 0))
|
||||
if (!is_refname_available(newref, oldref, get_packed_refs(NULL), 0))
|
||||
return 1;
|
||||
|
||||
if (!is_refname_available(newref, oldref, get_loose_refs(), 0))
|
||||
if (!is_refname_available(newref, oldref, get_loose_refs(NULL), 0))
|
||||
return 1;
|
||||
|
||||
lock = lock_ref_sha1_basic(renamed_ref, NULL, 0, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user