From f62abd00db3618afff5eb4fd1c23bd7259d8e6d8 Mon Sep 17 00:00:00 2001 From: u_quark Date: Mon, 18 Dec 2023 15:26:55 +0000 Subject: [PATCH 1/7] Use environment variables when creating signatures When creating an action signature (e.g. for a commit author and committer) read the following environment variables that can override the configuration options: * `GIT_AUTHOR_NAME` is the human-readable name in the "author" field. * `GIT_AUTHOR_EMAIL` is the email for the "author" field. * `GIT_AUTHOR_DATE` is the timestamp used for the "author" field. * `GIT_COMMITTER_NAME` sets the human name for the "committer" field. * `GIT_COMMITTER_EMAIL` is the email address for the "committer" field. * `GIT_COMMITTER_DATE` is used for the timestamp in the "committer" field. * `EMAIL` is the fallback email address in case the user.email configuration value isn't set. If this isn't set, Git falls back to the system user and host names. This is taken from the git documentation chapter "10.8 Environment Variables": https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables This PR adds support for reading these environment variables by adding two new functions `git_signature_default_author` and `git_signature_default_committer` and deprecates the `git_signature_default` function. Fixes: https://github.com/libgit2/libgit2/issues/3751 Prior work: * https://github.com/libgit2/libgit2/pull/4409 * https://github.com/libgit2/libgit2/pull/5479 * https://github.com/libgit2/libgit2/pull/6290 --- examples/commit.c | 14 ++++-- examples/init.c | 10 ++-- examples/stash.c | 2 +- examples/tag.c | 2 +- include/git2/signature.h | 48 +++++++++++++++++++ src/libgit2/rebase.c | 2 +- src/libgit2/refs.c | 2 +- src/libgit2/signature.c | 73 +++++++++++++++++++++++++++++ src/libgit2/signature.h | 2 +- src/util/date.c | 10 +++- src/util/date.h | 12 +++++ tests/libgit2/commit/signature.c | 80 ++++++++++++++++++++++++++++++++ tests/libgit2/date/date.c | 8 ++++ tests/libgit2/remote/fetch.c | 2 +- tests/libgit2/repo/init.c | 12 +++-- 15 files changed, 258 insertions(+), 21 deletions(-) diff --git a/examples/commit.c b/examples/commit.c index aedc1af7e..1ba4739f0 100644 --- a/examples/commit.c +++ b/examples/commit.c @@ -39,7 +39,7 @@ int lg2_commit(git_repository *repo, int argc, char **argv) git_index *index; git_object *parent = NULL; git_reference *ref = NULL; - git_signature *signature; + git_signature *author_signature, *committer_signature; /* Validate args */ if (argc < 3 || strcmp(opt, "-m") != 0) { @@ -63,21 +63,25 @@ int lg2_commit(git_repository *repo, int argc, char **argv) check_lg2(git_tree_lookup(&tree, repo, &tree_oid), "Error looking up tree", NULL); - check_lg2(git_signature_default(&signature, repo), "Error creating signature", NULL); + check_lg2(git_signature_default_author(&author_signature, repo), + "Error creating author signature", NULL); + check_lg2(git_signature_default_committer(&committer_signature, repo), + "Error creating committer signature", NULL); check_lg2(git_commit_create_v( &commit_oid, repo, "HEAD", - signature, - signature, + author_signature, + committer_signature, NULL, comment, tree, parent ? 1 : 0, parent), "Error creating commit", NULL); git_index_free(index); - git_signature_free(signature); + git_signature_free(author_signature); + git_signature_free(committer_signature); git_tree_free(tree); git_object_free(parent); git_reference_free(ref); diff --git a/examples/init.c b/examples/init.c index 2f681c5ae..4cd55abad 100644 --- a/examples/init.c +++ b/examples/init.c @@ -123,14 +123,15 @@ int lg2_init(git_repository *repo, int argc, char *argv[]) */ static void create_initial_commit(git_repository *repo) { - git_signature *sig; + git_signature *author_sig, *committer_sig; git_index *index; git_oid tree_id, commit_id; git_tree *tree; /** First use the config to initialize a commit signature for the user. */ - if (git_signature_default(&sig, repo) < 0) + if ((git_signature_default_author(&author_sig, repo) < 0) || + (git_signature_default_committer(&committer_sig, repo) < 0)) fatal("Unable to create a commit signature.", "Perhaps 'user.name' and 'user.email' are not set"); @@ -162,14 +163,15 @@ static void create_initial_commit(git_repository *repo) */ if (git_commit_create_v( - &commit_id, repo, "HEAD", sig, sig, + &commit_id, repo, "HEAD", author_sig, committer_sig, NULL, "Initial commit", tree, 0) < 0) fatal("Could not create the initial commit", NULL); /** Clean up so we don't leak memory. */ git_tree_free(tree); - git_signature_free(sig); + git_signature_free(author_sig); + git_signature_free(committer_sig); } static void usage(const char *error, const char *arg) diff --git a/examples/stash.c b/examples/stash.c index 8142439c7..c330cbce1 100644 --- a/examples/stash.c +++ b/examples/stash.c @@ -108,7 +108,7 @@ static int cmd_push(git_repository *repo, struct opts *opts) if (opts->argc) usage("push does not accept any parameters"); - check_lg2(git_signature_default(&signature, repo), + check_lg2(git_signature_default_author(&signature, repo), "Unable to get signature", NULL); check_lg2(git_stash_save(&stashid, repo, signature, NULL, GIT_STASH_DEFAULT), "Unable to save stash", NULL); diff --git a/examples/tag.c b/examples/tag.c index e4f71ae62..9bebcd1e6 100644 --- a/examples/tag.c +++ b/examples/tag.c @@ -226,7 +226,7 @@ static void action_create_tag(tag_state *state) check_lg2(git_revparse_single(&target, repo, opts->target), "Unable to resolve spec", opts->target); - check_lg2(git_signature_default(&tagger, repo), + check_lg2(git_signature_default_author(&tagger, repo), "Unable to create signature", NULL); check_lg2(git_tag_create(&oid, repo, opts->tag_name, diff --git a/include/git2/signature.h b/include/git2/signature.h index 849998e66..31aa9676d 100644 --- a/include/git2/signature.h +++ b/include/git2/signature.h @@ -48,6 +48,52 @@ GIT_EXTERN(int) git_signature_new(git_signature **out, const char *name, const c */ GIT_EXTERN(int) git_signature_now(git_signature **out, const char *name, const char *email); +/** Create a new author action signature with default information based on the + * configuration and environment variables. + * + * If GIT_AUTHOR_NAME environment variable is set it uses that over the + * user.name value from the configuration. + * + * If GIT_AUTHOR_EMAIL environment variable is set it uses that over the + * user.email value from the configuration. The EMAIL environment variable is + * the fallback email address in case the user.email configuration value isn't + * set. + * + * If GIT_AUTHOR_DATE is set it uses that, otherwise it uses the current time + * as the timestamp. + * + * It will return GIT_ENOTFOUND if either the user.name or user.email are not + * set and there is no fallback from an environment variable. + * + * @param out new signature + * @param repo repository pointer + * @return 0 on success, GIT_ENOTFOUND if config is missing, or error code + */ +GIT_EXTERN(int) git_signature_default_author(git_signature **out, git_repository *repo); + +/** Create a new committer action signature with default information based on + * the configuration and environment variables. + * + * If GIT_COMMITTER_NAME environment variable is set it uses that over the + * user.name value from the configuration. + * + * If GIT_COMMITTER_EMAIL environment variable is set it uses that over the + * user.email value from the configuration. The EMAIL environment variable is + * the fallback email address in case the user.email configuration value isn't + * set. + * + * If GIT_COMMITTER_DATE is set it uses that, otherwise it uses the current + * time as the timestamp. + * + * It will return GIT_ENOTFOUND if either the user.name or user.email are not + * set and there is no fallback from an environment variable. + * + * @param out new signature @param repo repository pointer @return 0 on + * success, GIT_ENOTFOUND if config is missing, or error code + */ +GIT_EXTERN(int) git_signature_default_committer(git_signature **out, git_repository *repo); + +#ifndef GIT_DEPRECATE_HARD /** * Create a new action signature with default user and now timestamp. * @@ -56,11 +102,13 @@ GIT_EXTERN(int) git_signature_now(git_signature **out, const char *name, const c * based on that information. It will return GIT_ENOTFOUND if either the * user.name or user.email are not set. * + * @deprecated use git_signature_default_author or git_signature_default_committer instead * @param out new signature * @param repo repository pointer * @return 0 on success, GIT_ENOTFOUND if config is missing, or error code */ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo); +#endif /** * Create a new signature by parsing the given buffer, which is diff --git a/src/libgit2/rebase.c b/src/libgit2/rebase.c index 77e442e98..e9de62652 100644 --- a/src/libgit2/rebase.c +++ b/src/libgit2/rebase.c @@ -1268,7 +1268,7 @@ static int rebase_copy_note( } if (!committer) { - if((error = git_signature_default(&who, rebase->repo)) < 0) { + if((error = git_signature_default_committer(&who, rebase->repo)) < 0) { if (error != GIT_ENOTFOUND || (error = git_signature_now(&who, "unknown", "unknown")) < 0) goto done; diff --git a/src/libgit2/refs.c b/src/libgit2/refs.c index c1ed04d23..8b553d40a 100644 --- a/src/libgit2/refs.c +++ b/src/libgit2/refs.c @@ -451,7 +451,7 @@ int git_reference__log_signature(git_signature **out, git_repository *repo) git_signature *who; if(((error = refs_configured_ident(&who, repo)) < 0) && - ((error = git_signature_default(&who, repo)) < 0) && + ((error = git_signature_default_author(&who, repo)) < 0) && ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) return error; diff --git a/src/libgit2/signature.c b/src/libgit2/signature.c index 12d2b5f8d..1a694c4cf 100644 --- a/src/libgit2/signature.c +++ b/src/libgit2/signature.c @@ -10,6 +10,7 @@ #include "repository.h" #include "git2/common.h" #include "posix.h" +#include "date.h" void git_signature_free(git_signature *sig) { @@ -201,6 +202,78 @@ int git_signature_default(git_signature **out, git_repository *repo) return error; } +int git_signature__default_from_env(const char *name_env_var, const char *email_env_var, + const char *date_env_var, git_signature **out, git_repository *repo) +{ + int error; + git_config *cfg; + const char *name, *email, *date; + git_time_t timestamp; + int offset; + git_str name_env = GIT_STR_INIT; + git_str email_env = GIT_STR_INIT; + git_str date_env = GIT_STR_INIT; + int have_email_env = -1; + + if ((error = git_repository_config_snapshot(&cfg, repo)) < 0) + return error; + + /* Check if the environment variable for the name is set */ + if (!(git__getenv(&name_env, name_env_var))) + name = git_str_cstr(&name_env); + else + /* or else read the configuration value. */ + if ((error = git_config_get_string(&name, cfg, "user.name")) < 0) + goto done; + + /* Check if the environment variable for the email is set. */ + if (!(git__getenv(&email_env, email_env_var))) + email = git_str_cstr(&email_env); + else { + /* Check if the fallback EMAIL environment variable is set + * before we check the configuration so that we preserve the + * error message if the configuration value is missing. */ + git_str_dispose(&email_env); + have_email_env = !git__getenv(&email_env, "EMAIL"); + if ((error = git_config_get_string(&email, cfg, "user.email")) < 0) { + if (have_email_env) { + email = git_str_cstr(&email_env); + error = 0; + } else + goto done; + } + } + + /* Check if the environment variable for the timestamp is set */ + if (!(git__getenv(&date_env, date_env_var))) { + date = git_str_cstr(&date_env); + if ((error = git_date_offset_parse(×tamp, &offset, date)) < 0) + goto done; + error = git_signature_new(out, name, email, timestamp, offset); + } else + /* or else default to the current timestamp. */ + error = git_signature_now(out, name, email); + +done: + git_config_free(cfg); + git_str_dispose(&name_env); + git_str_dispose(&email_env); + git_str_dispose(&date_env); + return error; +} + +int git_signature_default_author(git_signature **out, git_repository *repo) +{ + return git_signature__default_from_env("GIT_AUTHOR_NAME", "GIT_AUTHOR_EMAIL", + "GIT_AUTHOR_DATE", out, repo); +} + +int git_signature_default_committer(git_signature **out, git_repository *repo) +{ + return git_signature__default_from_env("GIT_COMMITTER_NAME", "GIT_COMMITTER_EMAIL", + "GIT_COMMITTER_DATE", out, repo); +} + int git_signature__parse(git_signature *sig, const char **buffer_out, const char *buffer_end, const char *header, char ender) { diff --git a/src/libgit2/signature.h b/src/libgit2/signature.h index 5c8270954..23356161e 100644 --- a/src/libgit2/signature.h +++ b/src/libgit2/signature.h @@ -17,7 +17,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out, const char *buffer_end, const char *header, char ender); void git_signature__writebuf(git_str *buf, const char *header, const git_signature *sig); bool git_signature__equal(const git_signature *one, const git_signature *two); - int git_signature__pdup(git_signature **dest, const git_signature *source, git_pool *pool); +int git_signature__default_from_env(const char *name_env_var, const char *email_env_var, const char *date_env_var, git_signature **out, git_repository *repo); #endif diff --git a/src/util/date.c b/src/util/date.c index 4d757e21a..161712e16 100644 --- a/src/util/date.c +++ b/src/util/date.c @@ -858,7 +858,7 @@ static git_time_t approxidate_str(const char *date, return update_tm(&tm, &now, 0); } -int git_date_parse(git_time_t *out, const char *date) +int git_date_offset_parse(git_time_t *out, int * out_offset, const char *date) { time_t time_sec; git_time_t timestamp; @@ -866,6 +866,7 @@ int git_date_parse(git_time_t *out, const char *date) if (!parse_date_basic(date, ×tamp, &offset)) { *out = timestamp; + *out_offset = offset; return 0; } @@ -876,6 +877,13 @@ int git_date_parse(git_time_t *out, const char *date) return error_ret; } +int git_date_parse(git_time_t *out, const char *date) +{ + int offset; + + return git_date_offset_parse(out, &offset, date); +} + int git_date_rfc2822_fmt(git_str *out, git_time_t time, int offset) { time_t t; diff --git a/src/util/date.h b/src/util/date.h index 7ebd3c30e..785fc064b 100644 --- a/src/util/date.h +++ b/src/util/date.h @@ -10,9 +10,21 @@ #include "util.h" #include "str.h" +/* + * Parse a string into a value as a git_time_t with a timezone offset. + * + * Sample valid input: + * - "yesterday" + * - "July 17, 2003" + * - "2003-7-17 08:23i+03" + */ +extern int git_date_offset_parse(git_time_t *out, int *out_offset, const char *date); + /* * Parse a string into a value as a git_time_t. * + * Timezone offset is ignored. + * * Sample valid input: * - "yesterday" * - "July 17, 2003" diff --git a/tests/libgit2/commit/signature.c b/tests/libgit2/commit/signature.c index fddd5076e..b41182ce6 100644 --- a/tests/libgit2/commit/signature.c +++ b/tests/libgit2/commit/signature.c @@ -153,3 +153,83 @@ void test_commit_signature__pos_and_neg_zero_offsets_dont_match(void) git_signature_free((git_signature *)with_neg_zero); git_signature_free((git_signature *)with_pos_zero); } + +static git_repository *g_repo; + +void test_commit_signature__initialize(void) +{ + g_repo = cl_git_sandbox_init("empty_standard_repo"); +} + +void test_commit_signature__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +void test_commit_signature__signature_default(void) +{ + git_signature *author_sign, *committer_sign; + git_config *cfg, *local; + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_open_level(&local, cfg, GIT_CONFIG_LEVEL_LOCAL)); + /* No configuration value is set and no environment variable */ + cl_git_fail(git_signature_default_author(&author_sign, g_repo)); + cl_git_fail(git_signature_default_committer(&committer_sign, g_repo)); + /* Name is read from configuration and email is read from fallback EMAIL + * environment variable */ + cl_git_pass(git_config_set_string(local, "user.name", "Name (config)")); + cl_setenv("EMAIL", "email-envvar@example.com"); + cl_git_pass(git_signature_default_author(&author_sign, g_repo)); + cl_git_pass(git_signature_default_committer(&committer_sign, g_repo)); + cl_assert_equal_s("Name (config)", author_sign->name); + cl_assert_equal_s("email-envvar@example.com", author_sign->email); + cl_assert_equal_s("Name (config)", committer_sign->name); + cl_assert_equal_s("email-envvar@example.com", committer_sign->email); + cl_setenv("EMAIL", NULL); + git_signature_free(author_sign); + git_signature_free(committer_sign); + /* Environment variables have precedence over configuration */ + cl_git_pass(git_config_set_string(local, "user.email", "config@example.com")); + cl_setenv("GIT_AUTHOR_NAME", "Author (envvar)"); + cl_setenv("GIT_AUTHOR_EMAIL", "author-envvar@example.com"); + cl_setenv("GIT_COMMITTER_NAME", "Committer (envvar)"); + cl_setenv("GIT_COMMITTER_EMAIL", "committer-envvar@example.com"); + cl_git_pass(git_signature_default_author(&author_sign, g_repo)); + cl_git_pass(git_signature_default_committer(&committer_sign, g_repo)); + cl_assert_equal_s("Author (envvar)", author_sign->name); + cl_assert_equal_s("author-envvar@example.com", author_sign->email); + cl_assert_equal_s("Committer (envvar)", committer_sign->name); + cl_assert_equal_s("committer-envvar@example.com", committer_sign->email); + git_signature_free(author_sign); + git_signature_free(committer_sign); + /* When environment variables are not set we can still read from + * configuration */ + cl_setenv("GIT_AUTHOR_NAME", NULL); + cl_setenv("GIT_AUTHOR_EMAIL", NULL); + cl_setenv("GIT_COMMITTER_NAME", NULL); + cl_setenv("GIT_COMMITTER_EMAIL", NULL); + cl_git_pass(git_signature_default_author(&author_sign, g_repo)); + cl_git_pass(git_signature_default_committer(&committer_sign, g_repo)); + cl_assert_equal_s("Name (config)", author_sign->name); + cl_assert_equal_s("config@example.com", author_sign->email); + cl_assert_equal_s("Name (config)", committer_sign->name); + cl_assert_equal_s("config@example.com", committer_sign->email); + git_signature_free(author_sign); + git_signature_free(committer_sign); + /* We can also override the timestamp with an environment variable */ + cl_setenv("GIT_AUTHOR_DATE", "1971-02-03 04:05:06+01"); + cl_setenv("GIT_COMMITTER_DATE", "1988-09-10 11:12:13-01"); + cl_git_pass(git_signature_default_author(&author_sign, g_repo)); + cl_git_pass(git_signature_default_committer(&committer_sign, g_repo)); + cl_assert_equal_i(34398306, author_sign->when.time); /* 1971-02-03 03:05:06 UTC */ + cl_assert_equal_i(60, author_sign->when.offset); + cl_assert_equal_i(589896733, committer_sign->when.time); /* 1988-09-10 12:12:13 UTC */ + cl_assert_equal_i(-60, committer_sign->when.offset); + git_signature_free(author_sign); + git_signature_free(committer_sign); + cl_setenv("GIT_AUTHOR_DATE", NULL); + cl_setenv("GIT_COMMITTER_DATE", NULL); + git_config_free(local); + git_config_free(cfg); +} diff --git a/tests/libgit2/date/date.c b/tests/libgit2/date/date.c index 82b5c6728..b5796861c 100644 --- a/tests/libgit2/date/date.c +++ b/tests/libgit2/date/date.c @@ -20,3 +20,11 @@ void test_date_date__invalid_date(void) cl_git_fail(git_date_parse(&d, "")); cl_git_fail(git_date_parse(&d, "NEITHER_INTEGER_NOR_DATETIME")); } + +void test_date_date__offset(void) +{ + git_time_t d; + int offset; + cl_git_pass(git_date_offset_parse(&d, &offset, "1970-1-1 01:00:00+03")); + cl_assert_equal_i(offset, 3*60); +} diff --git a/tests/libgit2/remote/fetch.c b/tests/libgit2/remote/fetch.c index a5d3272c5..c24ec5a01 100644 --- a/tests/libgit2/remote/fetch.c +++ b/tests/libgit2/remote/fetch.c @@ -82,7 +82,7 @@ static void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id, cl_git_pass(git_treebuilder_new(&tb, repo1, NULL)); cl_git_pass(git_treebuilder_write(&empty_tree_id, tb)); cl_git_pass(git_tree_lookup(&empty_tree, repo1, &empty_tree_id)); - cl_git_pass(git_signature_default(&sig, repo1)); + cl_git_pass(git_signature_default_author(&sig, repo1)); cl_git_pass(git_commit_create(commit1id, repo1, REPO1_REFNAME, sig, sig, NULL, "one", empty_tree, 0, NULL)); cl_git_pass(git_commit_lookup(&commit1, repo1, commit1id)); diff --git a/tests/libgit2/repo/init.c b/tests/libgit2/repo/init.c index d78ec063c..bb26e5443 100644 --- a/tests/libgit2/repo/init.c +++ b/tests/libgit2/repo/init.c @@ -581,7 +581,7 @@ void test_repo_init__init_with_initial_commit(void) * made to a repository... */ - /* Make sure we're ready to use git_signature_default :-) */ + /* Make sure we're ready to use git_signature_default_author :-) */ { git_config *cfg, *local; cl_git_pass(git_repository_config(&cfg, g_repo)); @@ -594,20 +594,22 @@ void test_repo_init__init_with_initial_commit(void) /* Create a commit with the new contents of the index */ { - git_signature *sig; + git_signature *author_sig, *committer_sig; git_oid tree_id, commit_id; git_tree *tree; - cl_git_pass(git_signature_default(&sig, g_repo)); + cl_git_pass(git_signature_default_author(&author_sig, g_repo)); + cl_git_pass(git_signature_default_committer(&committer_sig, g_repo)); cl_git_pass(git_index_write_tree(&tree_id, index)); cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); cl_git_pass(git_commit_create_v( - &commit_id, g_repo, "HEAD", sig, sig, + &commit_id, g_repo, "HEAD", author_sig, committer_sig, NULL, "First", tree, 0)); git_tree_free(tree); - git_signature_free(sig); + git_signature_free(author_sig); + git_signature_free(committer_sig); } git_index_free(index); From 47ec74b7c1caa840661e88550e9a909779e8aab6 Mon Sep 17 00:00:00 2001 From: u_quark Date: Fri, 22 Dec 2023 12:14:12 +0000 Subject: [PATCH 2/7] Guard deprecated function definition - fix CI --- src/libgit2/signature.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libgit2/signature.c b/src/libgit2/signature.c index 1a694c4cf..fa067c7ad 100644 --- a/src/libgit2/signature.c +++ b/src/libgit2/signature.c @@ -185,6 +185,7 @@ int git_signature_now(git_signature **sig_out, const char *name, const char *ema return 0; } +#ifndef GIT_DEPRECATE_HARD int git_signature_default(git_signature **out, git_repository *repo) { int error; @@ -201,6 +202,7 @@ int git_signature_default(git_signature **out, git_repository *repo) git_config_free(cfg); return error; } +#endif int git_signature__default_from_env(const char *name_env_var, const char *email_env_var, const char *date_env_var, git_signature **out, git_repository *repo) From 94125fb5c7241efb59bf4717561d7f18fd07ae87 Mon Sep 17 00:00:00 2001 From: u_quark Date: Sun, 24 Dec 2023 09:26:37 +0000 Subject: [PATCH 3/7] Fix clang tests: uninitialized variable --- examples/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/init.c b/examples/init.c index 4cd55abad..f0f0105be 100644 --- a/examples/init.c +++ b/examples/init.c @@ -123,7 +123,7 @@ int lg2_init(git_repository *repo, int argc, char *argv[]) */ static void create_initial_commit(git_repository *repo) { - git_signature *author_sig, *committer_sig; + git_signature *author_sig = NULL, *committer_sig = NULL; git_index *index; git_oid tree_id, commit_id; git_tree *tree; From 080248352b4517bf07525036be29c87a0198b0c6 Mon Sep 17 00:00:00 2001 From: u_quark Date: Sun, 14 Jan 2024 12:13:25 +0000 Subject: [PATCH 4/7] Address review comments Also fix some comment formatting. --- include/git2/signature.h | 17 +++++++++++------ src/libgit2/signature.c | 2 +- src/libgit2/signature.h | 1 - src/util/date.c | 2 +- tests/libgit2/commit/signature.c | 5 +++++ 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/include/git2/signature.h b/include/git2/signature.h index 31aa9676d..845cca214 100644 --- a/include/git2/signature.h +++ b/include/git2/signature.h @@ -48,7 +48,8 @@ GIT_EXTERN(int) git_signature_new(git_signature **out, const char *name, const c */ GIT_EXTERN(int) git_signature_now(git_signature **out, const char *name, const char *email); -/** Create a new author action signature with default information based on the +/** + * Create a new author action signature with default information based on the * configuration and environment variables. * * If GIT_AUTHOR_NAME environment variable is set it uses that over the @@ -71,7 +72,8 @@ GIT_EXTERN(int) git_signature_now(git_signature **out, const char *name, const c */ GIT_EXTERN(int) git_signature_default_author(git_signature **out, git_repository *repo); -/** Create a new committer action signature with default information based on +/** + * Create a new committer action signature with default information based on * the configuration and environment variables. * * If GIT_COMMITTER_NAME environment variable is set it uses that over the @@ -88,15 +90,19 @@ GIT_EXTERN(int) git_signature_default_author(git_signature **out, git_repository * It will return GIT_ENOTFOUND if either the user.name or user.email are not * set and there is no fallback from an environment variable. * - * @param out new signature @param repo repository pointer @return 0 on - * success, GIT_ENOTFOUND if config is missing, or error code + * @param out new signature + * @param repo repository pointer + * @return 0 on success, GIT_ENOTFOUND if config is missing, or error code */ GIT_EXTERN(int) git_signature_default_committer(git_signature **out, git_repository *repo); -#ifndef GIT_DEPRECATE_HARD /** * Create a new action signature with default user and now timestamp. * + * Warning: This function may be deprecated in the future. Use one of + * git_signature_default_author or git_signature_default_committer instead. + * These are more compliant with how git constructs default signatures. + * * This looks up the user.name and user.email from the configuration and * uses the current time as the timestamp, and creates a new signature * based on that information. It will return GIT_ENOTFOUND if either the @@ -108,7 +114,6 @@ GIT_EXTERN(int) git_signature_default_committer(git_signature **out, git_reposit * @return 0 on success, GIT_ENOTFOUND if config is missing, or error code */ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo); -#endif /** * Create a new signature by parsing the given buffer, which is diff --git a/src/libgit2/signature.c b/src/libgit2/signature.c index fa067c7ad..e6b1ac662 100644 --- a/src/libgit2/signature.c +++ b/src/libgit2/signature.c @@ -204,7 +204,7 @@ int git_signature_default(git_signature **out, git_repository *repo) } #endif -int git_signature__default_from_env(const char *name_env_var, const char *email_env_var, +static int git_signature__default_from_env(const char *name_env_var, const char *email_env_var, const char *date_env_var, git_signature **out, git_repository *repo) { int error; diff --git a/src/libgit2/signature.h b/src/libgit2/signature.h index 23356161e..a5645e9bb 100644 --- a/src/libgit2/signature.h +++ b/src/libgit2/signature.h @@ -18,6 +18,5 @@ int git_signature__parse(git_signature *sig, const char **buffer_out, const char void git_signature__writebuf(git_str *buf, const char *header, const git_signature *sig); bool git_signature__equal(const git_signature *one, const git_signature *two); int git_signature__pdup(git_signature **dest, const git_signature *source, git_pool *pool); -int git_signature__default_from_env(const char *name_env_var, const char *email_env_var, const char *date_env_var, git_signature **out, git_repository *repo); #endif diff --git a/src/util/date.c b/src/util/date.c index 161712e16..2e9fc00e1 100644 --- a/src/util/date.c +++ b/src/util/date.c @@ -858,7 +858,7 @@ static git_time_t approxidate_str(const char *date, return update_tm(&tm, &now, 0); } -int git_date_offset_parse(git_time_t *out, int * out_offset, const char *date) +int git_date_offset_parse(git_time_t *out, int *out_offset, const char *date) { time_t time_sec; git_time_t timestamp; diff --git a/tests/libgit2/commit/signature.c b/tests/libgit2/commit/signature.c index b41182ce6..2ad91f3f3 100644 --- a/tests/libgit2/commit/signature.c +++ b/tests/libgit2/commit/signature.c @@ -174,6 +174,11 @@ void test_commit_signature__signature_default(void) cl_git_pass(git_repository_config(&cfg, g_repo)); cl_git_pass(git_config_open_level(&local, cfg, GIT_CONFIG_LEVEL_LOCAL)); /* No configuration value is set and no environment variable */ + cl_setenv("EMAIL", NULL); + cl_setenv("GIT_AUTHOR_NAME", NULL); + cl_setenv("GIT_AUTHOR_EMAIL", NULL); + cl_setenv("GIT_COMMITTER_NAME", NULL); + cl_setenv("GIT_COMMITTER_EMAIL", NULL); cl_git_fail(git_signature_default_author(&author_sign, g_repo)); cl_git_fail(git_signature_default_committer(&committer_sign, g_repo)); /* Name is read from configuration and email is read from fallback EMAIL From 48cb38a1b8f4479c940068be45d4b2b66686611e Mon Sep 17 00:00:00 2001 From: u_quark Date: Sun, 14 Jan 2024 12:22:26 +0000 Subject: [PATCH 5/7] Remove deprecated annotation --- include/git2/signature.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/git2/signature.h b/include/git2/signature.h index 845cca214..84c36a33d 100644 --- a/include/git2/signature.h +++ b/include/git2/signature.h @@ -108,7 +108,6 @@ GIT_EXTERN(int) git_signature_default_committer(git_signature **out, git_reposit * based on that information. It will return GIT_ENOTFOUND if either the * user.name or user.email are not set. * - * @deprecated use git_signature_default_author or git_signature_default_committer instead * @param out new signature * @param repo repository pointer * @return 0 on success, GIT_ENOTFOUND if config is missing, or error code From 24d9fe13390ba84a326ae3895ce9979f89cd147a Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 14 Jun 2024 12:49:09 +0200 Subject: [PATCH 6/7] signature: keep using signature_default internally Making the various pieces that create commits automatically (eg, rebase) start paying attention to the environment variables is a Big Change. For now, this is a big change in defaults; we should treat it as breaking. We don't move to this by default; we may add `from_env` or `honor_env` type of API surface in the future. --- src/libgit2/rebase.c | 2 +- src/libgit2/refs.c | 2 +- tests/libgit2/remote/fetch.c | 2 +- tests/libgit2/repo/init.c | 12 +++++------- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/libgit2/rebase.c b/src/libgit2/rebase.c index e9de62652..77e442e98 100644 --- a/src/libgit2/rebase.c +++ b/src/libgit2/rebase.c @@ -1268,7 +1268,7 @@ static int rebase_copy_note( } if (!committer) { - if((error = git_signature_default_committer(&who, rebase->repo)) < 0) { + if((error = git_signature_default(&who, rebase->repo)) < 0) { if (error != GIT_ENOTFOUND || (error = git_signature_now(&who, "unknown", "unknown")) < 0) goto done; diff --git a/src/libgit2/refs.c b/src/libgit2/refs.c index 8b553d40a..c1ed04d23 100644 --- a/src/libgit2/refs.c +++ b/src/libgit2/refs.c @@ -451,7 +451,7 @@ int git_reference__log_signature(git_signature **out, git_repository *repo) git_signature *who; if(((error = refs_configured_ident(&who, repo)) < 0) && - ((error = git_signature_default_author(&who, repo)) < 0) && + ((error = git_signature_default(&who, repo)) < 0) && ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) return error; diff --git a/tests/libgit2/remote/fetch.c b/tests/libgit2/remote/fetch.c index c24ec5a01..a5d3272c5 100644 --- a/tests/libgit2/remote/fetch.c +++ b/tests/libgit2/remote/fetch.c @@ -82,7 +82,7 @@ static void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id, cl_git_pass(git_treebuilder_new(&tb, repo1, NULL)); cl_git_pass(git_treebuilder_write(&empty_tree_id, tb)); cl_git_pass(git_tree_lookup(&empty_tree, repo1, &empty_tree_id)); - cl_git_pass(git_signature_default_author(&sig, repo1)); + cl_git_pass(git_signature_default(&sig, repo1)); cl_git_pass(git_commit_create(commit1id, repo1, REPO1_REFNAME, sig, sig, NULL, "one", empty_tree, 0, NULL)); cl_git_pass(git_commit_lookup(&commit1, repo1, commit1id)); diff --git a/tests/libgit2/repo/init.c b/tests/libgit2/repo/init.c index bb26e5443..d78ec063c 100644 --- a/tests/libgit2/repo/init.c +++ b/tests/libgit2/repo/init.c @@ -581,7 +581,7 @@ void test_repo_init__init_with_initial_commit(void) * made to a repository... */ - /* Make sure we're ready to use git_signature_default_author :-) */ + /* Make sure we're ready to use git_signature_default :-) */ { git_config *cfg, *local; cl_git_pass(git_repository_config(&cfg, g_repo)); @@ -594,22 +594,20 @@ void test_repo_init__init_with_initial_commit(void) /* Create a commit with the new contents of the index */ { - git_signature *author_sig, *committer_sig; + git_signature *sig; git_oid tree_id, commit_id; git_tree *tree; - cl_git_pass(git_signature_default_author(&author_sig, g_repo)); - cl_git_pass(git_signature_default_committer(&committer_sig, g_repo)); + cl_git_pass(git_signature_default(&sig, g_repo)); cl_git_pass(git_index_write_tree(&tree_id, index)); cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); cl_git_pass(git_commit_create_v( - &commit_id, g_repo, "HEAD", author_sig, committer_sig, + &commit_id, g_repo, "HEAD", sig, sig, NULL, "First", tree, 0)); git_tree_free(tree); - git_signature_free(author_sig); - git_signature_free(committer_sig); + git_signature_free(sig); } git_index_free(index); From 649ef1cca624f1e6e4cfa7e286f7a7aca06abab1 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 14 Jun 2024 12:50:40 +0200 Subject: [PATCH 7/7] signature: add `git_signature_default_from_env` People who are doing a commit expect a unified timestamp between author and committer information when we're using the current timestamp. Provide a single function that returns both author and committer information so that they can have an identical timestamp when none is specified in the environment. --- examples/commit.c | 6 +- examples/init.c | 3 +- examples/stash.c | 2 +- examples/tag.c | 2 +- include/git2/signature.h | 72 +++++++--------- src/libgit2/signature.c | 137 ++++++++++++++++++++----------- tests/libgit2/commit/signature.c | 17 ++-- 7 files changed, 131 insertions(+), 108 deletions(-) diff --git a/examples/commit.c b/examples/commit.c index 1ba4739f0..c6e0a8dc4 100644 --- a/examples/commit.c +++ b/examples/commit.c @@ -63,10 +63,8 @@ int lg2_commit(git_repository *repo, int argc, char **argv) check_lg2(git_tree_lookup(&tree, repo, &tree_oid), "Error looking up tree", NULL); - check_lg2(git_signature_default_author(&author_signature, repo), - "Error creating author signature", NULL); - check_lg2(git_signature_default_committer(&committer_signature, repo), - "Error creating committer signature", NULL); + check_lg2(git_signature_default_from_env(&author_signature, &committer_signature, repo), + "Error creating signature", NULL); check_lg2(git_commit_create_v( &commit_oid, diff --git a/examples/init.c b/examples/init.c index f0f0105be..036c156ab 100644 --- a/examples/init.c +++ b/examples/init.c @@ -130,8 +130,7 @@ static void create_initial_commit(git_repository *repo) /** First use the config to initialize a commit signature for the user. */ - if ((git_signature_default_author(&author_sig, repo) < 0) || - (git_signature_default_committer(&committer_sig, repo) < 0)) + if ((git_signature_default_from_env(&author_sig, &committer_sig, repo) < 0)) fatal("Unable to create a commit signature.", "Perhaps 'user.name' and 'user.email' are not set"); diff --git a/examples/stash.c b/examples/stash.c index c330cbce1..197724364 100644 --- a/examples/stash.c +++ b/examples/stash.c @@ -108,7 +108,7 @@ static int cmd_push(git_repository *repo, struct opts *opts) if (opts->argc) usage("push does not accept any parameters"); - check_lg2(git_signature_default_author(&signature, repo), + check_lg2(git_signature_default_from_env(&signature, NULL, repo), "Unable to get signature", NULL); check_lg2(git_stash_save(&stashid, repo, signature, NULL, GIT_STASH_DEFAULT), "Unable to save stash", NULL); diff --git a/examples/tag.c b/examples/tag.c index 9bebcd1e6..ebe1a9d7b 100644 --- a/examples/tag.c +++ b/examples/tag.c @@ -226,7 +226,7 @@ static void action_create_tag(tag_state *state) check_lg2(git_revparse_single(&target, repo, opts->target), "Unable to resolve spec", opts->target); - check_lg2(git_signature_default_author(&tagger, repo), + check_lg2(git_signature_default_from_env(&tagger, NULL, repo), "Unable to create signature", NULL); check_lg2(git_tag_create(&oid, repo, opts->tag_name, diff --git a/include/git2/signature.h b/include/git2/signature.h index 84c36a33d..a027d25dc 100644 --- a/include/git2/signature.h +++ b/include/git2/signature.h @@ -49,65 +49,53 @@ GIT_EXTERN(int) git_signature_new(git_signature **out, const char *name, const c GIT_EXTERN(int) git_signature_now(git_signature **out, const char *name, const char *email); /** - * Create a new author action signature with default information based on the - * configuration and environment variables. + * Create a new author and/or committer signatures with default + * information based on the configuration and environment variables. * - * If GIT_AUTHOR_NAME environment variable is set it uses that over the - * user.name value from the configuration. + * If `author_out` is set, it will be populated with the author + * information. The `GIT_AUTHOR_NAME` and `GIT_AUTHOR_EMAIL` + * environment variables will be honored, and `user.name` and + * `user.email` configuration options will be honored if the + * environment variables are unset. For timestamps, `GIT_AUTHOR_DATE` + * will be used, otherwise the current time will be used. * - * If GIT_AUTHOR_EMAIL environment variable is set it uses that over the - * user.email value from the configuration. The EMAIL environment variable is - * the fallback email address in case the user.email configuration value isn't - * set. + * If `committer_out` is set, it will be populated with the + * committer information. The `GIT_COMMITTER_NAME` and + * `GIT_COMMITTER_EMAIL` environment variables will be honored, + * and `user.name` and `user.email` configuration options will + * be honored if the environment variables are unset. For timestamps, + * `GIT_COMMITTER_DATE` will be used, otherwise the current time will + * be used. * - * If GIT_AUTHOR_DATE is set it uses that, otherwise it uses the current time - * as the timestamp. + * If neither `GIT_AUTHOR_DATE` nor `GIT_COMMITTER_DATE` are set, + * both timestamps will be set to the same time. * - * It will return GIT_ENOTFOUND if either the user.name or user.email are not - * set and there is no fallback from an environment variable. + * It will return `GIT_ENOTFOUND` if either the `user.name` or + * `user.email` are not set and there is no fallback from an environment + * variable. One of `author_out` or `committer_out` must be set. * - * @param out new signature + * @param author_out pointer to set the author signature, or NULL + * @param committer_out pointer to set the committer signature, or NULL * @param repo repository pointer * @return 0 on success, GIT_ENOTFOUND if config is missing, or error code */ -GIT_EXTERN(int) git_signature_default_author(git_signature **out, git_repository *repo); - -/** - * Create a new committer action signature with default information based on - * the configuration and environment variables. - * - * If GIT_COMMITTER_NAME environment variable is set it uses that over the - * user.name value from the configuration. - * - * If GIT_COMMITTER_EMAIL environment variable is set it uses that over the - * user.email value from the configuration. The EMAIL environment variable is - * the fallback email address in case the user.email configuration value isn't - * set. - * - * If GIT_COMMITTER_DATE is set it uses that, otherwise it uses the current - * time as the timestamp. - * - * It will return GIT_ENOTFOUND if either the user.name or user.email are not - * set and there is no fallback from an environment variable. - * - * @param out new signature - * @param repo repository pointer - * @return 0 on success, GIT_ENOTFOUND if config is missing, or error code - */ -GIT_EXTERN(int) git_signature_default_committer(git_signature **out, git_repository *repo); +GIT_EXTERN(int) git_signature_default_from_env( + git_signature **author_out, + git_signature **committer_out, + git_repository *repo); /** * Create a new action signature with default user and now timestamp. * - * Warning: This function may be deprecated in the future. Use one of - * git_signature_default_author or git_signature_default_committer instead. - * These are more compliant with how git constructs default signatures. - * * This looks up the user.name and user.email from the configuration and * uses the current time as the timestamp, and creates a new signature * based on that information. It will return GIT_ENOTFOUND if either the * user.name or user.email are not set. * + * Note that these do not examine environment variables, only the + * configuration files. Use `git_signature_default_from_env` to + * consider the environment variables. + * * @param out new signature * @param repo repository pointer * @return 0 on success, GIT_ENOTFOUND if config is missing, or error code diff --git a/src/libgit2/signature.c b/src/libgit2/signature.c index e6b1ac662..71da41623 100644 --- a/src/libgit2/signature.c +++ b/src/libgit2/signature.c @@ -153,15 +153,10 @@ int git_signature__pdup(git_signature **dest, const git_signature *source, git_p return 0; } -int git_signature_now(git_signature **sig_out, const char *name, const char *email) +static void current_time(time_t *now_out, int *offset_out) { - time_t now; time_t offset; - struct tm *utc_tm; - git_signature *sig; - struct tm _utc; - - *sig_out = NULL; + struct tm _utc, *utc_tm; /* * Get the current time as seconds since the epoch and @@ -171,21 +166,28 @@ int git_signature_now(git_signature **sig_out, const char *name, const char *ema * us that time as seconds since the epoch. The difference * between its return value and 'now' is our offset to UTC. */ - time(&now); - utc_tm = p_gmtime_r(&now, &_utc); + time(now_out); + utc_tm = p_gmtime_r(now_out, &_utc); utc_tm->tm_isdst = -1; - offset = (time_t)difftime(now, mktime(utc_tm)); + offset = (time_t)difftime(*now_out, mktime(utc_tm)); offset /= 60; - if (git_signature_new(&sig, name, email, now, (int)offset) < 0) - return -1; - - *sig_out = sig; - - return 0; + *offset_out = (int)offset; +} + +int git_signature_now( + git_signature **sig_out, + const char *name, + const char *email) +{ + time_t now; + int offset; + + current_time(&now, &offset); + + return git_signature_new(sig_out, name, email, now, offset); } -#ifndef GIT_DEPRECATE_HARD int git_signature_default(git_signature **out, git_repository *repo) { int error; @@ -202,10 +204,15 @@ int git_signature_default(git_signature **out, git_repository *repo) git_config_free(cfg); return error; } -#endif -static int git_signature__default_from_env(const char *name_env_var, const char *email_env_var, - const char *date_env_var, git_signature **out, git_repository *repo) +static int user_from_env( + git_signature **out, + git_repository *repo, + const char *name_env_var, + const char *email_env_var, + const char *date_env_var, + time_t default_time, + int default_offset) { int error; git_config *cfg; @@ -215,46 +222,53 @@ static int git_signature__default_from_env(const char *name_env_var, const char git_str name_env = GIT_STR_INIT; git_str email_env = GIT_STR_INIT; git_str date_env = GIT_STR_INIT; - int have_email_env = -1; if ((error = git_repository_config_snapshot(&cfg, repo)) < 0) return error; /* Check if the environment variable for the name is set */ - if (!(git__getenv(&name_env, name_env_var))) + if (!(git__getenv(&name_env, name_env_var))) { name = git_str_cstr(&name_env); - else + } else { /* or else read the configuration value. */ if ((error = git_config_get_string(&name, cfg, "user.name")) < 0) goto done; + } /* Check if the environment variable for the email is set. */ - if (!(git__getenv(&email_env, email_env_var))) + if (!(git__getenv(&email_env, email_env_var))) { email = git_str_cstr(&email_env); - else { - /* Check if the fallback EMAIL environment variable is set - * before we check the configuration so that we preserve the - * error message if the configuration value is missing. */ - git_str_dispose(&email_env); - have_email_env = !git__getenv(&email_env, "EMAIL"); - if ((error = git_config_get_string(&email, cfg, "user.email")) < 0) { - if (have_email_env) { - email = git_str_cstr(&email_env); - error = 0; - } else + } else { + if ((error = git_config_get_string(&email, cfg, "user.email")) == GIT_ENOTFOUND) { + git_error *last_error; + + git_error_save(&last_error); + + if ((error = git__getenv(&email_env, "EMAIL")) < 0) { + git_error_restore(last_error); + error = GIT_ENOTFOUND; goto done; + } + + email = git_str_cstr(&email_env); + git_error_free(last_error); + } else if (error < 0) { + goto done; } } /* Check if the environment variable for the timestamp is set */ if (!(git__getenv(&date_env, date_env_var))) { date = git_str_cstr(&date_env); + if ((error = git_date_offset_parse(×tamp, &offset, date)) < 0) goto done; - error = git_signature_new(out, name, email, timestamp, offset); - } else - /* or else default to the current timestamp. */ - error = git_signature_now(out, name, email); + } else { + timestamp = default_time; + offset = default_offset; + } + + error = git_signature_new(out, name, email, timestamp, offset); done: git_config_free(cfg); @@ -264,16 +278,45 @@ done: return error; } -int git_signature_default_author(git_signature **out, git_repository *repo) +int git_signature_default_from_env( + git_signature **author_out, + git_signature **committer_out, + git_repository *repo) { - return git_signature__default_from_env("GIT_AUTHOR_NAME", "GIT_AUTHOR_EMAIL", - "GIT_AUTHOR_DATE", out, repo); -} + git_signature *author = NULL, *committer = NULL; + time_t now; + int offset; + int error; -int git_signature_default_committer(git_signature **out, git_repository *repo) -{ - return git_signature__default_from_env("GIT_COMMITTER_NAME", "GIT_COMMITTER_EMAIL", - "GIT_COMMITTER_DATE", out, repo); + GIT_ASSERT_ARG(author_out || committer_out); + GIT_ASSERT_ARG(repo); + + current_time(&now, &offset); + + if (author_out && + (error = user_from_env(&author, repo, "GIT_AUTHOR_NAME", + "GIT_AUTHOR_EMAIL", "GIT_AUTHOR_DATE", + now, offset)) < 0) + goto on_error; + + if (committer_out && + (error = user_from_env(&committer, repo, "GIT_COMMITTER_NAME", + "GIT_COMMITTER_EMAIL", "GIT_COMMITTER_DATE", + now, offset)) < 0) + goto on_error; + + if (author_out) + *author_out = author; + + if (committer_out) + *committer_out = committer; + + return 0; + +on_error: + git__free(author); + git__free(committer); + return error; } int git_signature__parse(git_signature *sig, const char **buffer_out, diff --git a/tests/libgit2/commit/signature.c b/tests/libgit2/commit/signature.c index 2ad91f3f3..3fa6646cf 100644 --- a/tests/libgit2/commit/signature.c +++ b/tests/libgit2/commit/signature.c @@ -167,7 +167,7 @@ void test_commit_signature__cleanup(void) g_repo = NULL; } -void test_commit_signature__signature_default(void) +void test_commit_signature__from_env(void) { git_signature *author_sign, *committer_sign; git_config *cfg, *local; @@ -179,14 +179,12 @@ void test_commit_signature__signature_default(void) cl_setenv("GIT_AUTHOR_EMAIL", NULL); cl_setenv("GIT_COMMITTER_NAME", NULL); cl_setenv("GIT_COMMITTER_EMAIL", NULL); - cl_git_fail(git_signature_default_author(&author_sign, g_repo)); - cl_git_fail(git_signature_default_committer(&committer_sign, g_repo)); + cl_git_fail(git_signature_default_from_env(&author_sign, &committer_sign, g_repo)); /* Name is read from configuration and email is read from fallback EMAIL * environment variable */ cl_git_pass(git_config_set_string(local, "user.name", "Name (config)")); cl_setenv("EMAIL", "email-envvar@example.com"); - cl_git_pass(git_signature_default_author(&author_sign, g_repo)); - cl_git_pass(git_signature_default_committer(&committer_sign, g_repo)); + cl_git_pass(git_signature_default_from_env(&author_sign, &committer_sign, g_repo)); cl_assert_equal_s("Name (config)", author_sign->name); cl_assert_equal_s("email-envvar@example.com", author_sign->email); cl_assert_equal_s("Name (config)", committer_sign->name); @@ -200,8 +198,7 @@ void test_commit_signature__signature_default(void) cl_setenv("GIT_AUTHOR_EMAIL", "author-envvar@example.com"); cl_setenv("GIT_COMMITTER_NAME", "Committer (envvar)"); cl_setenv("GIT_COMMITTER_EMAIL", "committer-envvar@example.com"); - cl_git_pass(git_signature_default_author(&author_sign, g_repo)); - cl_git_pass(git_signature_default_committer(&committer_sign, g_repo)); + cl_git_pass(git_signature_default_from_env(&author_sign, &committer_sign, g_repo)); cl_assert_equal_s("Author (envvar)", author_sign->name); cl_assert_equal_s("author-envvar@example.com", author_sign->email); cl_assert_equal_s("Committer (envvar)", committer_sign->name); @@ -214,8 +211,7 @@ void test_commit_signature__signature_default(void) cl_setenv("GIT_AUTHOR_EMAIL", NULL); cl_setenv("GIT_COMMITTER_NAME", NULL); cl_setenv("GIT_COMMITTER_EMAIL", NULL); - cl_git_pass(git_signature_default_author(&author_sign, g_repo)); - cl_git_pass(git_signature_default_committer(&committer_sign, g_repo)); + cl_git_pass(git_signature_default_from_env(&author_sign, &committer_sign, g_repo)); cl_assert_equal_s("Name (config)", author_sign->name); cl_assert_equal_s("config@example.com", author_sign->email); cl_assert_equal_s("Name (config)", committer_sign->name); @@ -225,8 +221,7 @@ void test_commit_signature__signature_default(void) /* We can also override the timestamp with an environment variable */ cl_setenv("GIT_AUTHOR_DATE", "1971-02-03 04:05:06+01"); cl_setenv("GIT_COMMITTER_DATE", "1988-09-10 11:12:13-01"); - cl_git_pass(git_signature_default_author(&author_sign, g_repo)); - cl_git_pass(git_signature_default_committer(&committer_sign, g_repo)); + cl_git_pass(git_signature_default_from_env(&author_sign, &committer_sign, g_repo)); cl_assert_equal_i(34398306, author_sign->when.time); /* 1971-02-03 03:05:06 UTC */ cl_assert_equal_i(60, author_sign->when.offset); cl_assert_equal_i(589896733, committer_sign->when.time); /* 1988-09-10 12:12:13 UTC */