diff options
Diffstat (limited to 'refs.c')
-rw-r--r-- | refs.c | 87 |
1 files changed, 56 insertions, 31 deletions
@@ -314,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); } @@ -698,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/")) @@ -707,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, '/'); @@ -1088,6 +1090,15 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt) return ret; } +/* + * People using contrib's git-new-workdir have .git/logs/refs -> + * /some/other/path/.git/logs/refs, and that may live on another device. + * + * IOW, to avoid cross device rename errors, the temporary renamed log must + * live into logs/refs. + */ +#define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log" + int rename_ref(const char *oldref, const char *newref, const char *logmsg) { static const char renamed_ref[] = "RENAMED-REF"; @@ -1121,8 +1132,8 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg) if (write_ref_sha1(lock, orig_sha1, logmsg)) return error("unable to save current sha1 in %s", renamed_ref); - if (log && rename(git_path("logs/%s", oldref), git_path("tmp-renamed-log"))) - return error("unable to move logfile logs/%s to tmp-renamed-log: %s", + if (log && rename(git_path("logs/%s", oldref), git_path(TMP_RENAMED_LOG))) + return error("unable to move logfile logs/%s to "TMP_RENAMED_LOG": %s", oldref, strerror(errno)); if (delete_ref(oldref, orig_sha1, REF_NODEREF)) { @@ -1148,7 +1159,7 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg) } retry: - if (log && rename(git_path("tmp-renamed-log"), git_path("logs/%s", newref))) { + if (log && rename(git_path(TMP_RENAMED_LOG), git_path("logs/%s", newref))) { if (errno==EISDIR || errno==ENOTDIR) { /* * rename(a, b) when b is an existing @@ -1161,7 +1172,7 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg) } goto retry; } else { - error("unable to move logfile tmp-renamed-log to logs/%s: %s", + error("unable to move logfile "TMP_RENAMED_LOG" to logs/%s: %s", newref, strerror(errno)); goto rollback; } @@ -1201,8 +1212,8 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg) error("unable to restore logfile %s from %s: %s", oldref, newref, strerror(errno)); if (!logmoved && log && - rename(git_path("tmp-renamed-log"), git_path("logs/%s", oldref))) - error("unable to restore logfile %s from tmp-renamed-log: %s", + rename(git_path(TMP_RENAMED_LOG), git_path("logs/%s", oldref))) + error("unable to restore logfile %s from "TMP_RENAMED_LOG": %s", oldref, strerror(errno)); return 1; @@ -1260,51 +1271,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; |