X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=refs.c;h=6f486ae62d8b4605520e75286ca36217d0715363;hb=5bfd53629e93113a17fe7d6a7a24554dc3c17cdb;hp=63e30d74a7eacee53682b20068e8e24a37840ccc;hpb=8ca788035644f2aaf7a951272ae16a7bd319554c;p=git.git diff --git a/refs.c b/refs.c index 63e30d74a..6f486ae62 100644 --- a/refs.c +++ b/refs.c @@ -6,6 +6,7 @@ /* ISSYMREF=01 and ISPACKED=02 are public interfaces */ #define REF_KNOWS_PEELED 04 +#define REF_BROKEN 010 struct ref_list { struct ref_list *next; @@ -275,8 +276,10 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list) list = get_ref_dir(ref, list); continue; } - if (!resolve_ref(ref, sha1, 1, &flag)) + if (!resolve_ref(ref, sha1, 1, &flag)) { hashclr(sha1); + flag |= REF_BROKEN; + } list = add_ref(ref, sha1, flag, list, NULL); } free(ref); @@ -311,7 +314,11 @@ static int warn_if_dangling_symref(const char *refname, const unsigned char *sha void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname) { - struct warn_if_dangling_data data = { fp, refname, msg_fmt }; + struct warn_if_dangling_data data; + + data.fp = fp; + data.refname = refname; + data.msg_fmt = msg_fmt; for_each_rawref(warn_if_dangling_symref, &data); } @@ -539,10 +546,10 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim, { if (strncmp(base, entry->name, trim)) return 0; - /* Is this a "negative ref" that represents a deleted ref? */ - if (is_null_sha1(entry->sha1)) - return 0; + if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) { + if (entry->flag & REF_BROKEN) + return 0; /* ignore dangling symref */ if (!has_sha1_file(entry->sha1)) { error("%s does not point to a valid object!", entry->name); return 0; @@ -695,7 +702,6 @@ int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, { struct strbuf real_pattern = STRBUF_INIT; struct ref_filter filter; - const char *has_glob_specials; int ret; if (!prefix && prefixcmp(pattern, "refs/")) @@ -704,8 +710,7 @@ int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, strbuf_addstr(&real_pattern, prefix); strbuf_addstr(&real_pattern, pattern); - has_glob_specials = strpbrk(pattern, "?*["); - if (!has_glob_specials) { + if (!has_glob_specials(pattern)) { /* Append implied '/' '*' if not present. */ if (real_pattern.buf[real_pattern.len - 1] != '/') strbuf_addch(&real_pattern, '/'); @@ -1257,51 +1262,65 @@ static int copy_msg(char *buf, const char *msg) return cp - buf; } -static int log_ref_write(const char *ref_name, const unsigned char *old_sha1, - const unsigned char *new_sha1, const char *msg) +int log_ref_setup(const char *ref_name, char *logfile, int bufsize) { - int logfd, written, oflags = O_APPEND | O_WRONLY; - unsigned maxlen, len; - int msglen; - char log_file[PATH_MAX]; - char *logrec; - const char *committer; - - if (log_all_ref_updates < 0) - log_all_ref_updates = !is_bare_repository(); - - git_snpath(log_file, sizeof(log_file), "logs/%s", ref_name); + int logfd, oflags = O_APPEND | O_WRONLY; + git_snpath(logfile, bufsize, "logs/%s", ref_name); if (log_all_ref_updates && (!prefixcmp(ref_name, "refs/heads/") || !prefixcmp(ref_name, "refs/remotes/") || + !prefixcmp(ref_name, "refs/notes/") || !strcmp(ref_name, "HEAD"))) { - if (safe_create_leading_directories(log_file) < 0) + if (safe_create_leading_directories(logfile) < 0) return error("unable to create directory for %s", - log_file); + logfile); oflags |= O_CREAT; } - logfd = open(log_file, oflags, 0666); + logfd = open(logfile, oflags, 0666); if (logfd < 0) { if (!(oflags & O_CREAT) && errno == ENOENT) return 0; if ((oflags & O_CREAT) && errno == EISDIR) { - if (remove_empty_directories(log_file)) { + if (remove_empty_directories(logfile)) { return error("There are still logs under '%s'", - log_file); + logfile); } - logfd = open(log_file, oflags, 0666); + logfd = open(logfile, oflags, 0666); } if (logfd < 0) return error("Unable to append to %s: %s", - log_file, strerror(errno)); + logfile, strerror(errno)); } - adjust_shared_perm(log_file); + adjust_shared_perm(logfile); + close(logfd); + return 0; +} + +static int log_ref_write(const char *ref_name, const unsigned char *old_sha1, + const unsigned char *new_sha1, const char *msg) +{ + int logfd, result, written, oflags = O_APPEND | O_WRONLY; + unsigned maxlen, len; + int msglen; + char log_file[PATH_MAX]; + char *logrec; + const char *committer; + + if (log_all_ref_updates < 0) + log_all_ref_updates = !is_bare_repository(); + + result = log_ref_setup(ref_name, log_file, sizeof(log_file)); + if (result) + return result; + logfd = open(log_file, oflags); + if (logfd < 0) + return 0; msglen = msg ? strlen(msg) : 0; committer = git_committer_info(0); maxlen = strlen(committer) + msglen + 100;