archive - leakfix for format_subst()
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index 4dc7e8b47659b75cc0dcf334f1bf33798b2e5157..09a2c87fc23e4298bb3bcddc5c2cc649c3206a04 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -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,7 +1116,7 @@ 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);
        if (close(logfd) != 0 || written != len)
@@ -1300,7 +1313,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) {
@@ -1313,7 +1326,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);