mirror of
https://github.com/libgit2/libgit2.git
synced 2026-06-22 06:26:26 +00:00
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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user