Commit add30a838867820788c871c1d034fcf68c2ad12c

Edward Thomson 2021-11-18T12:36:25

date: rfc2822 formatting uses a `git_buf` instead of a static string

diff --git a/src/date.c b/src/date.c
index f7498e7..52cc308 100644
--- a/src/date.c
+++ b/src/date.c
@@ -13,6 +13,7 @@
 #include "util.h"
 #include "cache.h"
 #include "posix.h"
+#include "date.h"
 
 #include <ctype.h>
 #include <time.h>
@@ -875,31 +876,24 @@ int git_date_parse(git_time_t *out, const char *date)
    return error_ret;
 }
 
-int git_date_rfc2822_fmt(char *out, size_t len, const git_time *date)
+int git_date_rfc2822_fmt(git_str *out, git_time_t time, int offset)
 {
-	int written;
-	struct tm gmt;
 	time_t t;
+	struct tm gmt;
 
 	GIT_ASSERT_ARG(out);
-	GIT_ASSERT_ARG(date);
 
-	t = (time_t) (date->time + date->offset * 60);
+	t = (time_t) (time + offset * 60);
 
-	if (p_gmtime_r (&t, &gmt) == NULL)
+	if (p_gmtime_r(&t, &gmt) == NULL)
 		return -1;
 
-	written = p_snprintf(out, len, "%.3s, %u %.3s %.4u %02u:%02u:%02u %+03d%02d",
+	return git_str_printf(out, "%.3s, %u %.3s %.4u %02u:%02u:%02u %+03d%02d",
 		weekday_names[gmt.tm_wday],
 		gmt.tm_mday,
 		month_names[gmt.tm_mon],
 		gmt.tm_year + 1900,
 		gmt.tm_hour, gmt.tm_min, gmt.tm_sec,
-		date->offset / 60, date->offset % 60);
-
-	if (written < 0 || (written > (int) len - 1))
-		return -1;
-
-	return 0;
+		offset / 60, offset % 60);
 }
 
diff --git a/src/date.h b/src/date.h
index 133f20b..7ebd3c3 100644
--- a/src/date.h
+++ b/src/date.h
@@ -23,11 +23,11 @@ extern int git_date_parse(git_time_t *out, const char *date);
 /*
  * Format a git_time as a RFC2822 string
  *
- * @param out buffer to store formatted date; a '\\0' terminator will automatically be added.
- * @param len size of the buffer; should be atleast `GIT_DATE_RFC2822_SZ` in size;
- * @param date the date to be formatted
+ * @param out buffer to store formatted date
+ * @param time the time to be formatted
+ * @param offset the timezone offset
  * @return 0 if successful; -1 on error
  */
-extern int git_date_rfc2822_fmt(char *out, size_t len, const git_time *date);
+extern int git_date_rfc2822_fmt(git_str *out, git_time_t time, int offset);
 
 #endif
diff --git a/src/email.c b/src/email.c
index 66ed2dd..e19a292 100644
--- a/src/email.c
+++ b/src/email.c
@@ -73,6 +73,19 @@ static int append_prefix(
 	return git_str_oom(out) ? -1 : 0;
 }
 
+static int append_date(
+	git_str *out,
+	const git_time *date)
+{
+	int error;
+
+	if ((error = git_str_printf(out, "Date: ")) == 0 &&
+	    (error = git_date_rfc2822_fmt(out, date->time, date->offset)) == 0)
+	    error = git_str_putc(out, '\n');
+
+	return error;
+}
+
 static int append_subject(
 	git_str *out,
 	size_t patch_idx,
@@ -118,14 +131,12 @@ static int append_header(
 	git_email_create_options *opts)
 {
 	char id[GIT_OID_HEXSZ];
-	char date[GIT_DATE_RFC2822_SZ];
 	int error;
 
 	if ((error = git_oid_fmt(id, commit_id)) < 0 ||
 	    (error = git_str_printf(out, "From %.*s %s\n", GIT_OID_HEXSZ, id, EMAIL_TIMESTAMP)) < 0 ||
 	    (error = git_str_printf(out, "From: %s <%s>\n", author->name, author->email)) < 0 ||
-	    (error = git_date_rfc2822_fmt(date, sizeof(date), &author->when)) < 0 ||
-	    (error = git_str_printf(out, "Date: %s\n", date)) < 0 ||
+	    (error = append_date(out, &author->when)) < 0 ||
 	    (error = append_subject(out, patch_idx, patch_count, summary, opts)) < 0)
 		return error;
 
diff --git a/src/util.h b/src/util.h
index 3d6ee12..141779a 100644
--- a/src/util.h
+++ b/src/util.h
@@ -37,8 +37,6 @@
 # define GIT_CONTAINER_OF(ptr, type, member) (type *)(ptr)
 #endif
 
-#define GIT_DATE_RFC2822_SZ  32
-
 /**
  * Return the length of a constant string.
  * We are aware that `strlen` performs the same task and is usually
diff --git a/tests/date/rfc2822.c b/tests/date/rfc2822.c
index c94c840..b0bbcfc 100644
--- a/tests/date/rfc2822.c
+++ b/tests/date/rfc2822.c
@@ -5,36 +5,33 @@
 void test_date_rfc2822__format_rfc2822_no_offset(void)
 {
 	git_time t = {1397031663, 0};
-	char buf[GIT_DATE_RFC2822_SZ];
+	git_str buf = GIT_STR_INIT;
 
-	cl_git_pass(git_date_rfc2822_fmt(buf, sizeof(buf), &t));
-	cl_assert(strcmp(buf, "Wed, 9 Apr 2014 08:21:03 +0000") == 0);
+	cl_git_pass(git_date_rfc2822_fmt(&buf, t.time, t.offset));
+	cl_assert_equal_s("Wed, 9 Apr 2014 08:21:03 +0000", buf.ptr);
+
+	git_str_dispose(&buf);
 }
 
 void test_date_rfc2822__format_rfc2822_positive_offset(void)
 {
 	git_time t = {1397031663, 120};
-	char buf[GIT_DATE_RFC2822_SZ];
+	git_str buf = GIT_STR_INIT;
+
+	cl_git_pass(git_date_rfc2822_fmt(&buf, t.time, t.offset));
+	cl_assert_equal_s("Wed, 9 Apr 2014 10:21:03 +0200", buf.ptr);
 
-	cl_git_pass(git_date_rfc2822_fmt(buf, sizeof(buf), &t));
-	cl_assert(strcmp(buf, "Wed, 9 Apr 2014 10:21:03 +0200") == 0);
+	git_str_dispose(&buf);
 }
 
 void test_date_rfc2822__format_rfc2822_negative_offset(void)
 {
 	git_time t = {1397031663, -120};
-	char buf[GIT_DATE_RFC2822_SZ];
+	git_str buf = GIT_STR_INIT;
 
-	cl_git_pass(git_date_rfc2822_fmt(buf, sizeof(buf), &t));
-	cl_assert(strcmp(buf, "Wed, 9 Apr 2014 06:21:03 -0200") == 0);
-}
-
-void test_date_rfc2822__format_rfc2822_buffer_too_small(void)
-{
-	/* "Wed, 10 Apr 2014 08:21:03 +0000" */
-	git_time t = {1397031663 + 86400, 0};
-	char buf[GIT_DATE_RFC2822_SZ-1];
+	cl_git_pass(git_date_rfc2822_fmt(&buf, t.time, t.offset));
+	cl_assert_equal_s("Wed, 9 Apr 2014 06:21:03 -0200", buf.ptr);
 
-	cl_git_fail(git_date_rfc2822_fmt(buf, sizeof(buf), &t));
+	git_str_dispose(&buf);
 }