X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=refs.c;h=07e260c8a15c9118ee829964aed65b209900dc36;hb=182af8343c307436bb5364309aa6d4d46fa5911d;hp=ef4484d2937727b131eade1c6b62180cd9722976;hpb=1924d64f6e070edf1ad1949bf2eb95d4d2451f30;p=git.git diff --git a/refs.c b/refs.c index ef4484d29..07e260c8a 100644 --- a/refs.c +++ b/refs.c @@ -150,7 +150,7 @@ static struct ref_list *sort_ref_list(struct ref_list *list) * Future: need to be in "struct repository" * when doing a full libification. */ -struct cached_refs { +static struct cached_refs { char did_loose; char did_packed; struct ref_list *loose; @@ -869,6 +869,7 @@ static int repack_without_ref(const char *refname) die("too long a refname '%s'", list->name); write_or_die(fd, line, len); } + close(fd); return commit_lock_file(&packlock); } @@ -1036,6 +1037,32 @@ void unlock_ref(struct ref_lock *lock) free(lock); } +/* + * copy the reflog message msg to buf, which has been allocated sufficiently + * large, while cleaning up the whitespaces. Especially, convert LF to space, + * because reflog file is one line per entry. + */ +static int copy_msg(char *buf, const char *msg) +{ + char *cp = buf; + char c; + int wasspace = 1; + + *cp++ = '\t'; + while ((c = *msg++)) { + if (wasspace && isspace(c)) + continue; + wasspace = isspace(c); + if (wasspace) + c = ' '; + *cp++ = c; + } + while (buf < cp && isspace(cp[-1])) + cp--; + *cp++ = '\n'; + 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) { @@ -1080,21 +1107,7 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1, adjust_shared_perm(log_file); - msglen = 0; - if (msg) { - /* clean up the message and make sure it is a single line */ - for ( ; *msg; msg++) - if (!isspace(*msg)) - break; - if (*msg) { - const char *ep = strchr(msg, '\n'); - if (ep) - msglen = ep - msg; - else - msglen = strlen(msg); - } - } - + msglen = msg ? strlen(msg) : 0; committer = git_committer_info(-1); maxlen = strlen(committer) + msglen + 100; logrec = xmalloc(maxlen); @@ -1103,11 +1116,10 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1, sha1_to_hex(new_sha1), committer); if (msglen) - len += sprintf(logrec + len - 1, "\t%.*s\n", msglen, msg) - 1; + len += copy_msg(logrec + len - 1, msg) - 1; written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1; free(logrec); - close(logfd); - if (written != len) + if (close(logfd) != 0 || written != len) return error("Unable to append to %s", log_file); return 0; } @@ -1204,8 +1216,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master, goto error_free_return; } written = write_in_full(fd, ref, len); - close(fd); - if (written != len) { + if (close(fd) != 0 || written != len) { error("Unable to write to %s", lockpath); goto error_unlink_return; } @@ -1235,15 +1246,11 @@ int create_symref(const char *ref_target, const char *refs_heads_master, static char *ref_msg(const char *line, const char *endp) { const char *ep; - char *msg; - line += 82; - for (ep = line; ep < endp && *ep != '\n'; ep++) - ; - msg = xmalloc(ep - line + 1); - memcpy(msg, line, ep - line); - msg[ep - line] = 0; - return msg; + ep = memchr(line, '\n', endp - line); + if (!ep) + ep = endp; + return xmemdupz(line, ep - line); } int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt) @@ -1302,7 +1309,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char * if (hashcmp(logged_sha1, sha1)) { fprintf(stderr, "warning: Log %s has gap after %s.\n", - logfile, show_rfc2822_date(date, tz)); + logfile, show_date(date, tz, DATE_RFC2822)); } } else if (date == at_time) { @@ -1315,7 +1322,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char * if (hashcmp(logged_sha1, sha1)) { fprintf(stderr, "warning: Log %s unexpectedly ended on %s.\n", - logfile, show_rfc2822_date(date, tz)); + logfile, show_date(date, tz, DATE_RFC2822)); } } munmap(log_mapped, mapsz); @@ -1444,3 +1451,30 @@ int for_each_reflog(each_ref_fn fn, void *cb_data) { return do_for_each_reflog("", fn, cb_data); } + +int update_ref(const char *action, const char *refname, + const unsigned char *sha1, const unsigned char *oldval, + int flags, enum action_on_err onerr) +{ + static struct ref_lock *lock; + lock = lock_any_ref_for_update(refname, oldval, flags); + if (!lock) { + const char *str = "Cannot lock the ref '%s'."; + switch (onerr) { + case MSG_ON_ERR: error(str, refname); break; + case DIE_ON_ERR: die(str, refname); break; + case QUIET_ON_ERR: break; + } + return 1; + } + if (write_ref_sha1(lock, sha1, action) < 0) { + const char *str = "Cannot update the ref '%s'."; + switch (onerr) { + case MSG_ON_ERR: error(str, refname); break; + case DIE_ON_ERR: die(str, refname); break; + case QUIET_ON_ERR: break; + } + return 1; + } + return 0; +}