diff options
Diffstat (limited to 'refs.c')
-rw-r--r-- | refs.c | 101 |
1 files changed, 61 insertions, 40 deletions
@@ -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,9 +710,8 @@ 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) { - /* Append impiled '/' '*' if not present. */ + if (!has_glob_specials(pattern)) { + /* Append implied '/' '*' if not present. */ if (real_pattern.buf[real_pattern.len - 1] != '/') strbuf_addch(&real_pattern, '/'); /* No need to check for '*', there is none. */ @@ -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; @@ -1574,7 +1593,7 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs, { const char *logfile; FILE *logfp; - char buf[1024]; + struct strbuf sb = STRBUF_INIT; int ret = 0; logfile = git_path("logs/%s", ref); @@ -1587,24 +1606,24 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs, if (fstat(fileno(logfp), &statbuf) || statbuf.st_size < ofs || fseek(logfp, -ofs, SEEK_END) || - fgets(buf, sizeof(buf), logfp)) { + strbuf_getwholeline(&sb, logfp, '\n')) { fclose(logfp); + strbuf_release(&sb); return -1; } } - while (fgets(buf, sizeof(buf), logfp)) { + while (!strbuf_getwholeline(&sb, logfp, '\n')) { unsigned char osha1[20], nsha1[20]; char *email_end, *message; unsigned long timestamp; - int len, tz; + int tz; /* old SP new SP name <email> SP time TAB msg LF */ - len = strlen(buf); - if (len < 83 || buf[len-1] != '\n' || - get_sha1_hex(buf, osha1) || buf[40] != ' ' || - get_sha1_hex(buf + 41, nsha1) || buf[81] != ' ' || - !(email_end = strchr(buf + 82, '>')) || + if (sb.len < 83 || sb.buf[sb.len - 1] != '\n' || + get_sha1_hex(sb.buf, osha1) || sb.buf[40] != ' ' || + get_sha1_hex(sb.buf + 41, nsha1) || sb.buf[81] != ' ' || + !(email_end = strchr(sb.buf + 82, '>')) || email_end[1] != ' ' || !(timestamp = strtoul(email_end + 2, &message, 10)) || !message || message[0] != ' ' || @@ -1618,11 +1637,13 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs, message += 6; else message += 7; - ret = fn(osha1, nsha1, buf+82, timestamp, tz, message, cb_data); + ret = fn(osha1, nsha1, sb.buf + 82, timestamp, tz, message, + cb_data); if (ret) break; } fclose(logfp); + strbuf_release(&sb); return ret; } |