oid: Export `git_oid_tostr_s` instead of `_allocfmt` The old `allocfmt` is of no use to callers, as they are not able to free the returned buffer. Export a new API that returns a static string that doesn't need to be freed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
diff --git a/include/git2/oid.h b/include/git2/oid.h
index 1cfd4e5..db2f3af 100644
--- a/include/git2/oid.h
+++ b/include/git2/oid.h
@@ -116,13 +116,17 @@ GIT_EXTERN(void) git_oid_nfmt(char *out, size_t n, const git_oid *id);
GIT_EXTERN(void) git_oid_pathfmt(char *out, const git_oid *id);
/**
- * Format a git_oid into a newly allocated c-string.
+ * Format a git_oid into a statically allocated c-string.
+ *
+ * The c-string is owned by the library and should not be freed
+ * by the user. If libgit2 is built with thread support, the string
+ * will be stored in TLS (i.e. one buffer per thread) to allow for
+ * concurrent calls of the function.
*
* @param id the oid structure to format
- * @return the c-string; NULL if memory is exhausted. Caller must
- * deallocate the string with git__free().
+ * @return the c-string
*/
-GIT_EXTERN(char *) git_oid_allocfmt(const git_oid *id);
+GIT_EXTERN(char *) git_oid_tostr_s(const git_oid *oid);
/**
* Format a git_oid into a buffer as a hex format c-string.
diff --git a/src/global.h b/src/global.h
index 745df3e..1065046 100644
--- a/src/global.h
+++ b/src/global.h
@@ -13,6 +13,7 @@
typedef struct {
git_error *last_error;
git_error error_t;
+ char oid_fmt[41];
} git_global_st;
#ifdef GIT_SSL
diff --git a/src/oid.c b/src/oid.c
index b640cad..969931d 100644
--- a/src/oid.c
+++ b/src/oid.c
@@ -8,6 +8,7 @@
#include "common.h"
#include "git2/oid.h"
#include "repository.h"
+#include "global.h"
#include <string.h>
#include <limits.h>
@@ -99,6 +100,13 @@ void git_oid_pathfmt(char *str, const git_oid *oid)
str = fmt_one(str, oid->id[i]);
}
+char *git_oid_tostr_s(const git_oid *oid)
+{
+ char *str = GIT_GLOBAL->oid_fmt;
+ git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid);
+ return str;
+}
+
char *git_oid_allocfmt(const git_oid *oid)
{
char *str = git__malloc(GIT_OID_HEXSZ + 1);
diff --git a/src/oid.h b/src/oid.h
index cfe7ca1..aa1f0bf 100644
--- a/src/oid.h
+++ b/src/oid.h
@@ -9,6 +9,17 @@
#include "git2/oid.h"
+/**
+ * Format a git_oid into a newly allocated c-string.
+ *
+ * The c-string is owned by the caller and needs to be manually freed.
+ *
+ * @param id the oid structure to format
+ * @return the c-string; NULL if memory is exhausted. Caller must
+ * deallocate the string with git__free().
+ */
+char *git_oid_allocfmt(const git_oid *id);
+
GIT_INLINE(int) git_oid__hashcmp(const unsigned char *sha1, const unsigned char *sha2)
{
int i;
diff --git a/tests/object/raw/compare.c b/tests/object/raw/compare.c
index 1c9ce4b..56c016b 100644
--- a/tests/object/raw/compare.c
+++ b/tests/object/raw/compare.c
@@ -90,7 +90,7 @@ void test_object_raw_compare__compare_fmt_oids(void)
cl_assert_equal_s(exp, out);
}
-void test_object_raw_compare__compare_allocfmt_oids(void)
+void test_object_raw_compare__compare_static_oids(void)
{
const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0";
git_oid in;
@@ -98,10 +98,9 @@ void test_object_raw_compare__compare_allocfmt_oids(void)
cl_git_pass(git_oid_fromstr(&in, exp));
- out = git_oid_allocfmt(&in);
+ out = git_oid_tostr_s(&in);
cl_assert(out);
cl_assert_equal_s(exp, out);
- git__free(out);
}
void test_object_raw_compare__compare_pathfmt_oids(void)
diff --git a/tests/online/push_util.c b/tests/online/push_util.c
index 038c144..68e71ea 100644
--- a/tests/online/push_util.c
+++ b/tests/online/push_util.c
@@ -110,9 +110,8 @@ failed:
git_buf_puts(&msg, "Expected and actual refs differ:\nEXPECTED:\n");
for(i = 0; i < expected_refs_len; i++) {
- cl_assert(oid_str = git_oid_allocfmt(expected_refs[i].oid));
+ oid_str = git_oid_tostr_s(expected_refs[i].oid);
cl_git_pass(git_buf_printf(&msg, "%s = %s\n", expected_refs[i].name, oid_str));
- git__free(oid_str);
}
git_buf_puts(&msg, "\nACTUAL:\n");
@@ -121,9 +120,8 @@ failed:
if (master_present && !strcmp(actual->name, "refs/heads/master"))
continue;
- cl_assert(oid_str = git_oid_allocfmt(&actual->oid));
+ oid_str = git_oid_tostr_s(&actual->oid);
cl_git_pass(git_buf_printf(&msg, "%s = %s\n", actual->name, oid_str));
- git__free(oid_str);
}
cl_fail(git_buf_cstr(&msg));
diff --git a/tests/stash/save.c b/tests/stash/save.c
index 87c6d7e..3b301bf 100644
--- a/tests/stash/save.c
+++ b/tests/stash/save.c
@@ -227,18 +227,12 @@ void test_stash_save__can_stash_against_a_detached_head(void)
void test_stash_save__stashing_updates_the_reflog(void)
{
- char *sha;
-
assert_object_oid("refs/stash@{0}", NULL, GIT_OBJ_COMMIT);
cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT));
- sha = git_oid_allocfmt(&stash_tip_oid);
-
- assert_object_oid("refs/stash@{0}", sha, GIT_OBJ_COMMIT);
+ assert_object_oid("refs/stash@{0}", git_oid_tostr_s(&stash_tip_oid), GIT_OBJ_COMMIT);
assert_object_oid("refs/stash@{1}", NULL, GIT_OBJ_COMMIT);
-
- git__free(sha);
}
void test_stash_save__cannot_stash_when_there_are_no_local_change(void)