Merge branch 'jk/ident-gecos-strbuf'
Fixes quite a lot of brokenness when ident information needs to be taken from the system and cleans up the code. By Jeff King * jk/ident-gecos-strbuf: (22 commits) format-patch: do not use bogus email addresses in message ids ident: reject bogus email addresses with IDENT_STRICT ident: rename IDENT_ERROR_ON_NO_NAME to IDENT_STRICT format-patch: use GIT_COMMITTER_EMAIL in message ids ident: let callers omit name with fmt_indent ident: refactor NO_DATE flag in fmt_ident ident: reword empty ident error message format-patch: refactor get_patch_filename ident: trim whitespace from default name/email ident: use a dynamic strbuf in fmt_ident ident: use full dns names to generate email addresses ident: report passwd errors with a more friendly message drop length limitations on gecos-derived names and emails ident: don't write fallback username into git_default_name fmt_ident: drop IDENT_WARN_ON_NO_NAME code format-patch: use default email for generating message ids ident: trim trailing newline from /etc/mailname move git_default_* variables to ident.c move identity config parsing to ident.c fmt-merge-msg: don't use static buffer in record_person ...
This commit is contained in:
commit
261ec7d02a
@ -88,15 +88,6 @@ for one to be entered and terminated with ^D.
|
|||||||
|
|
||||||
include::date-formats.txt[]
|
include::date-formats.txt[]
|
||||||
|
|
||||||
Diagnostics
|
|
||||||
-----------
|
|
||||||
You don't exist. Go away!::
|
|
||||||
The passwd(5) gecos field couldn't be read
|
|
||||||
Your parents must have hated you!::
|
|
||||||
The passwd(5) gecos field is longer than a giant static buffer.
|
|
||||||
Your sysadmin must hate you!::
|
|
||||||
The passwd(5) name field is longer than a giant static buffer.
|
|
||||||
|
|
||||||
Discussion
|
Discussion
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -59,15 +59,6 @@ ifdef::git-default-pager[]
|
|||||||
The build you are using chose '{git-default-pager}' as the default.
|
The build you are using chose '{git-default-pager}' as the default.
|
||||||
endif::git-default-pager[]
|
endif::git-default-pager[]
|
||||||
|
|
||||||
Diagnostics
|
|
||||||
-----------
|
|
||||||
You don't exist. Go away!::
|
|
||||||
The passwd(5) gecos field couldn't be read
|
|
||||||
Your parents must have hated you!::
|
|
||||||
The passwd(5) gecos field is longer than a giant static buffer.
|
|
||||||
Your sysadmin must hate you!::
|
|
||||||
The passwd(5) name field is longer than a giant static buffer.
|
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
linkgit:git-commit-tree[1]
|
linkgit:git-commit-tree[1]
|
||||||
|
@ -526,8 +526,7 @@ static void determine_author_info(struct strbuf *author_ident)
|
|||||||
|
|
||||||
if (force_date)
|
if (force_date)
|
||||||
date = force_date;
|
date = force_date;
|
||||||
strbuf_addstr(author_ident, fmt_ident(name, email, date,
|
strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
|
||||||
IDENT_ERROR_ON_NO_NAME));
|
|
||||||
if (!split_ident_line(&author, author_ident->buf, author_ident->len)) {
|
if (!split_ident_line(&author, author_ident->buf, author_ident->len)) {
|
||||||
export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
|
export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
|
||||||
export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
|
export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
|
||||||
|
@ -230,7 +230,7 @@ static void add_branch_desc(struct strbuf *out, const char *name)
|
|||||||
static void record_person(int which, struct string_list *people,
|
static void record_person(int which, struct string_list *people,
|
||||||
struct commit *commit)
|
struct commit *commit)
|
||||||
{
|
{
|
||||||
char name_buf[MAX_GITNAME], *name, *name_end;
|
char *name_buf, *name, *name_end;
|
||||||
struct string_list_item *elem;
|
struct string_list_item *elem;
|
||||||
const char *field = (which == 'a') ? "\nauthor " : "\ncommitter ";
|
const char *field = (which == 'a') ? "\nauthor " : "\ncommitter ";
|
||||||
|
|
||||||
@ -243,10 +243,9 @@ static void record_person(int which, struct string_list *people,
|
|||||||
name_end--;
|
name_end--;
|
||||||
while (isspace(*name_end) && name <= name_end)
|
while (isspace(*name_end) && name <= name_end)
|
||||||
name_end--;
|
name_end--;
|
||||||
if (name_end < name || name + MAX_GITNAME <= name_end)
|
if (name_end < name)
|
||||||
return;
|
return;
|
||||||
memcpy(name_buf, name, name_end - name + 1);
|
name_buf = xmemdupz(name, name_end - name + 1);
|
||||||
name_buf[name_end - name + 1] = '\0';
|
|
||||||
|
|
||||||
elem = string_list_lookup(people, name_buf);
|
elem = string_list_lookup(people, name_buf);
|
||||||
if (!elem) {
|
if (!elem) {
|
||||||
@ -254,6 +253,7 @@ static void record_person(int which, struct string_list *people,
|
|||||||
elem->util = (void *)0;
|
elem->util = (void *)0;
|
||||||
}
|
}
|
||||||
elem->util = (void*)(util_as_integral(elem) + 1);
|
elem->util = (void*)(util_as_integral(elem) + 1);
|
||||||
|
free(name_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmp_string_list_util_as_integral(const void *a_, const void *b_)
|
static int cmp_string_list_util_as_integral(const void *a_, const void *b_)
|
||||||
|
@ -663,7 +663,8 @@ static FILE *realstdout = NULL;
|
|||||||
static const char *output_directory = NULL;
|
static const char *output_directory = NULL;
|
||||||
static int outdir_offset;
|
static int outdir_offset;
|
||||||
|
|
||||||
static int reopen_stdout(struct commit *commit, struct rev_info *rev, int quiet)
|
static int reopen_stdout(struct commit *commit, const char *subject,
|
||||||
|
struct rev_info *rev, int quiet)
|
||||||
{
|
{
|
||||||
struct strbuf filename = STRBUF_INIT;
|
struct strbuf filename = STRBUF_INIT;
|
||||||
int suffix_len = strlen(fmt_patch_suffix) + 1;
|
int suffix_len = strlen(fmt_patch_suffix) + 1;
|
||||||
@ -677,7 +678,7 @@ static int reopen_stdout(struct commit *commit, struct rev_info *rev, int quiet)
|
|||||||
strbuf_addch(&filename, '/');
|
strbuf_addch(&filename, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
get_patch_filename(commit, rev->nr, fmt_patch_suffix, &filename);
|
get_patch_filename(commit, subject, rev->nr, fmt_patch_suffix, &filename);
|
||||||
|
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
|
fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
|
||||||
@ -737,15 +738,10 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const cha
|
|||||||
|
|
||||||
static void gen_message_id(struct rev_info *info, char *base)
|
static void gen_message_id(struct rev_info *info, char *base)
|
||||||
{
|
{
|
||||||
const char *committer = git_committer_info(IDENT_WARN_ON_NO_NAME);
|
|
||||||
const char *email_start = strrchr(committer, '<');
|
|
||||||
const char *email_end = strrchr(committer, '>');
|
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
if (!email_start || !email_end || email_start > email_end - 1)
|
strbuf_addf(&buf, "%s.%lu.git.%s", base,
|
||||||
die(_("Could not extract email from committer identity."));
|
|
||||||
strbuf_addf(&buf, "%s.%lu.git.%.*s", base,
|
|
||||||
(unsigned long) time(NULL),
|
(unsigned long) time(NULL),
|
||||||
(int)(email_end - email_start - 1), email_start + 1);
|
git_committer_info(IDENT_NO_NAME|IDENT_NO_DATE|IDENT_STRICT));
|
||||||
info->message_id = strbuf_detach(&buf, NULL);
|
info->message_id = strbuf_detach(&buf, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,7 +780,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
|||||||
const char *encoding = "UTF-8";
|
const char *encoding = "UTF-8";
|
||||||
struct diff_options opts;
|
struct diff_options opts;
|
||||||
int need_8bit_cte = 0;
|
int need_8bit_cte = 0;
|
||||||
struct commit *commit = NULL;
|
|
||||||
struct pretty_print_context pp = {0};
|
struct pretty_print_context pp = {0};
|
||||||
|
|
||||||
if (rev->commit_format != CMIT_FMT_EMAIL)
|
if (rev->commit_format != CMIT_FMT_EMAIL)
|
||||||
@ -792,31 +787,10 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
|||||||
|
|
||||||
committer = git_committer_info(0);
|
committer = git_committer_info(0);
|
||||||
|
|
||||||
if (!numbered_files) {
|
if (!use_stdout &&
|
||||||
/*
|
reopen_stdout(NULL, numbered_files ? NULL : "cover-letter", rev, quiet))
|
||||||
* We fake a commit for the cover letter so we get the filename
|
|
||||||
* desired.
|
|
||||||
*/
|
|
||||||
commit = xcalloc(1, sizeof(*commit));
|
|
||||||
commit->buffer = xmalloc(400);
|
|
||||||
snprintf(commit->buffer, 400,
|
|
||||||
"tree 0000000000000000000000000000000000000000\n"
|
|
||||||
"parent %s\n"
|
|
||||||
"author %s\n"
|
|
||||||
"committer %s\n\n"
|
|
||||||
"cover letter\n",
|
|
||||||
sha1_to_hex(head->object.sha1), committer, committer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!use_stdout && reopen_stdout(commit, rev, quiet))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (commit) {
|
|
||||||
|
|
||||||
free(commit->buffer);
|
|
||||||
free(commit);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
|
log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
|
||||||
&need_8bit_cte);
|
&need_8bit_cte);
|
||||||
|
|
||||||
@ -1173,7 +1147,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
|||||||
if (do_signoff) {
|
if (do_signoff) {
|
||||||
const char *committer;
|
const char *committer;
|
||||||
const char *endpos;
|
const char *endpos;
|
||||||
committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
|
committer = git_committer_info(IDENT_STRICT);
|
||||||
endpos = strchr(committer, '>');
|
endpos = strchr(committer, '>');
|
||||||
if (!endpos)
|
if (!endpos)
|
||||||
die(_("bogus committer info %s"), committer);
|
die(_("bogus committer info %s"), committer);
|
||||||
@ -1411,8 +1385,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
|||||||
gen_message_id(&rev, sha1_to_hex(commit->object.sha1));
|
gen_message_id(&rev, sha1_to_hex(commit->object.sha1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!use_stdout && reopen_stdout(numbered_files ? NULL : commit,
|
if (!use_stdout &&
|
||||||
&rev, quiet))
|
reopen_stdout(numbered_files ? NULL : commit, NULL, &rev, quiet))
|
||||||
die(_("Failed to create output files"));
|
die(_("Failed to create output files"));
|
||||||
shown = log_tree_commit(&rev, commit);
|
shown = log_tree_commit(&rev, commit);
|
||||||
free(commit->buffer);
|
free(commit->buffer);
|
||||||
|
@ -1447,7 +1447,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||||||
refresh_cache(REFRESH_QUIET);
|
refresh_cache(REFRESH_QUIET);
|
||||||
if (allow_trivial && !fast_forward_only) {
|
if (allow_trivial && !fast_forward_only) {
|
||||||
/* See if it is really trivial. */
|
/* See if it is really trivial. */
|
||||||
git_committer_info(IDENT_ERROR_ON_NO_NAME);
|
git_committer_info(IDENT_STRICT);
|
||||||
printf(_("Trying really trivial in-index merge...\n"));
|
printf(_("Trying really trivial in-index merge...\n"));
|
||||||
if (!read_tree_trivial(common->item->object.sha1,
|
if (!read_tree_trivial(common->item->object.sha1,
|
||||||
head_commit->object.sha1,
|
head_commit->object.sha1,
|
||||||
@ -1490,7 +1490,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||||||
die(_("Not possible to fast-forward, aborting."));
|
die(_("Not possible to fast-forward, aborting."));
|
||||||
|
|
||||||
/* We are going to make a new commit. */
|
/* We are going to make a new commit. */
|
||||||
git_committer_info(IDENT_ERROR_ON_NO_NAME);
|
git_committer_info(IDENT_STRICT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point, we need a real merge. No matter what strategy
|
* At this point, we need a real merge. No matter what strategy
|
||||||
|
@ -332,7 +332,7 @@ static void create_tag(const unsigned char *object, const char *tag,
|
|||||||
sha1_to_hex(object),
|
sha1_to_hex(object),
|
||||||
typename(type),
|
typename(type),
|
||||||
tag,
|
tag,
|
||||||
git_committer_info(IDENT_ERROR_ON_NO_NAME));
|
git_committer_info(IDENT_STRICT));
|
||||||
|
|
||||||
if (header_len > sizeof(header_buf) - 1)
|
if (header_len > sizeof(header_buf) - 1)
|
||||||
die(_("tag header too big."));
|
die(_("tag header too big."));
|
||||||
|
@ -11,7 +11,7 @@ static const char *editor(int flag)
|
|||||||
{
|
{
|
||||||
const char *pgm = git_editor();
|
const char *pgm = git_editor();
|
||||||
|
|
||||||
if (!pgm && flag & IDENT_ERROR_ON_NO_NAME)
|
if (!pgm && flag & IDENT_STRICT)
|
||||||
die("Terminal is dumb, but EDITOR unset");
|
die("Terminal is dumb, but EDITOR unset");
|
||||||
|
|
||||||
return pgm;
|
return pgm;
|
||||||
@ -55,7 +55,7 @@ static const char *read_var(const char *var)
|
|||||||
val = NULL;
|
val = NULL;
|
||||||
for (ptr = git_vars; ptr->read; ptr++) {
|
for (ptr = git_vars; ptr->read; ptr++) {
|
||||||
if (strcmp(var, ptr->name) == 0) {
|
if (strcmp(var, ptr->name) == 0) {
|
||||||
val = ptr->read(IDENT_ERROR_ON_NO_NAME);
|
val = ptr->read(IDENT_STRICT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
cache.h
13
cache.h
@ -887,15 +887,19 @@ unsigned long approxidate_careful(const char *, int *);
|
|||||||
unsigned long approxidate_relative(const char *date, const struct timeval *now);
|
unsigned long approxidate_relative(const char *date, const struct timeval *now);
|
||||||
enum date_mode parse_date_format(const char *format);
|
enum date_mode parse_date_format(const char *format);
|
||||||
|
|
||||||
#define IDENT_WARN_ON_NO_NAME 1
|
#define IDENT_STRICT 1
|
||||||
#define IDENT_ERROR_ON_NO_NAME 2
|
#define IDENT_NO_DATE 2
|
||||||
#define IDENT_NO_DATE 4
|
#define IDENT_NO_NAME 4
|
||||||
extern const char *git_author_info(int);
|
extern const char *git_author_info(int);
|
||||||
extern const char *git_committer_info(int);
|
extern const char *git_committer_info(int);
|
||||||
extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
|
extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
|
||||||
extern const char *fmt_name(const char *name, const char *email);
|
extern const char *fmt_name(const char *name, const char *email);
|
||||||
|
extern const char *ident_default_name(void);
|
||||||
|
extern const char *ident_default_email(void);
|
||||||
|
extern const char *ident_default_date(void);
|
||||||
extern const char *git_editor(void);
|
extern const char *git_editor(void);
|
||||||
extern const char *git_pager(int stdout_is_tty);
|
extern const char *git_pager(int stdout_is_tty);
|
||||||
|
extern int git_ident_config(const char *, const char *, void *);
|
||||||
|
|
||||||
struct ident_split {
|
struct ident_split {
|
||||||
const char *name_begin;
|
const char *name_begin;
|
||||||
@ -1139,9 +1143,6 @@ struct config_include_data {
|
|||||||
#define CONFIG_INCLUDE_INIT { 0 }
|
#define CONFIG_INCLUDE_INIT { 0 }
|
||||||
extern int git_config_include(const char *name, const char *value, void *data);
|
extern int git_config_include(const char *name, const char *value, void *data);
|
||||||
|
|
||||||
#define MAX_GITNAME (1000)
|
|
||||||
extern char git_default_email[MAX_GITNAME];
|
|
||||||
extern char git_default_name[MAX_GITNAME];
|
|
||||||
#define IDENT_NAME_GIVEN 01
|
#define IDENT_NAME_GIVEN 01
|
||||||
#define IDENT_MAIL_GIVEN 02
|
#define IDENT_MAIL_GIVEN 02
|
||||||
#define IDENT_ALL_GIVEN (IDENT_NAME_GIVEN|IDENT_MAIL_GIVEN)
|
#define IDENT_ALL_GIVEN (IDENT_NAME_GIVEN|IDENT_MAIL_GIVEN)
|
||||||
|
4
commit.c
4
commit.c
@ -1154,9 +1154,9 @@ int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
|
|||||||
|
|
||||||
/* Person/date information */
|
/* Person/date information */
|
||||||
if (!author)
|
if (!author)
|
||||||
author = git_author_info(IDENT_ERROR_ON_NO_NAME);
|
author = git_author_info(IDENT_STRICT);
|
||||||
strbuf_addf(&buffer, "author %s\n", author);
|
strbuf_addf(&buffer, "author %s\n", author);
|
||||||
strbuf_addf(&buffer, "committer %s\n", git_committer_info(IDENT_ERROR_ON_NO_NAME));
|
strbuf_addf(&buffer, "committer %s\n", git_committer_info(IDENT_STRICT));
|
||||||
if (!encoding_is_utf8)
|
if (!encoding_is_utf8)
|
||||||
strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding);
|
strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding);
|
||||||
|
|
||||||
|
24
config.c
24
config.c
@ -762,28 +762,6 @@ static int git_default_core_config(const char *var, const char *value)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int git_default_user_config(const char *var, const char *value)
|
|
||||||
{
|
|
||||||
if (!strcmp(var, "user.name")) {
|
|
||||||
if (!value)
|
|
||||||
return config_error_nonbool(var);
|
|
||||||
strlcpy(git_default_name, value, sizeof(git_default_name));
|
|
||||||
user_ident_explicitly_given |= IDENT_NAME_GIVEN;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(var, "user.email")) {
|
|
||||||
if (!value)
|
|
||||||
return config_error_nonbool(var);
|
|
||||||
strlcpy(git_default_email, value, sizeof(git_default_email));
|
|
||||||
user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add other config variables here and to Documentation/config.txt. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int git_default_i18n_config(const char *var, const char *value)
|
static int git_default_i18n_config(const char *var, const char *value)
|
||||||
{
|
{
|
||||||
if (!strcmp(var, "i18n.commitencoding"))
|
if (!strcmp(var, "i18n.commitencoding"))
|
||||||
@ -870,7 +848,7 @@ int git_default_config(const char *var, const char *value, void *dummy)
|
|||||||
return git_default_core_config(var, value);
|
return git_default_core_config(var, value);
|
||||||
|
|
||||||
if (!prefixcmp(var, "user."))
|
if (!prefixcmp(var, "user."))
|
||||||
return git_default_user_config(var, value);
|
return git_ident_config(var, value, dummy);
|
||||||
|
|
||||||
if (!prefixcmp(var, "i18n."))
|
if (!prefixcmp(var, "i18n."))
|
||||||
return git_default_i18n_config(var, value);
|
return git_default_i18n_config(var, value);
|
||||||
|
@ -11,9 +11,6 @@
|
|||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
#include "fmt-merge-msg.h"
|
#include "fmt-merge-msg.h"
|
||||||
|
|
||||||
char git_default_email[MAX_GITNAME];
|
|
||||||
char git_default_name[MAX_GITNAME];
|
|
||||||
int user_ident_explicitly_given;
|
|
||||||
int trust_executable_bit = 1;
|
int trust_executable_bit = 1;
|
||||||
int trust_ctime = 1;
|
int trust_ctime = 1;
|
||||||
int has_symlinks = 1;
|
int has_symlinks = 1;
|
||||||
|
@ -595,4 +595,7 @@ int rmdir_or_warn(const char *path);
|
|||||||
*/
|
*/
|
||||||
int remove_or_warn(unsigned int mode, const char *path);
|
int remove_or_warn(unsigned int mode, const char *path);
|
||||||
|
|
||||||
|
/* Get the passwd entry for the UID of the current process. */
|
||||||
|
struct passwd *xgetpwuid_self(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,7 +30,7 @@ const char *get_signing_key(void)
|
|||||||
{
|
{
|
||||||
if (configured_signing_key)
|
if (configured_signing_key)
|
||||||
return configured_signing_key;
|
return configured_signing_key;
|
||||||
return git_committer_info(IDENT_ERROR_ON_NO_NAME|IDENT_NO_DATE);
|
return git_committer_info(IDENT_STRICT|IDENT_NO_DATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -904,7 +904,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
|
|||||||
ep = strchr(ep + 1, '/');
|
ep = strchr(ep + 1, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
escaped = xml_entities(git_default_email);
|
escaped = xml_entities(ident_default_email());
|
||||||
strbuf_addf(&out_buffer.buf, LOCK_REQUEST, escaped);
|
strbuf_addf(&out_buffer.buf, LOCK_REQUEST, escaped);
|
||||||
free(escaped);
|
free(escaped);
|
||||||
|
|
||||||
|
237
ident.c
237
ident.c
@ -7,7 +7,10 @@
|
|||||||
*/
|
*/
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
|
static struct strbuf git_default_name = STRBUF_INIT;
|
||||||
|
static struct strbuf git_default_email = STRBUF_INIT;
|
||||||
static char git_default_date[50];
|
static char git_default_date[50];
|
||||||
|
int user_ident_explicitly_given;
|
||||||
|
|
||||||
#ifdef NO_GECOS_IN_PWENT
|
#ifdef NO_GECOS_IN_PWENT
|
||||||
#define get_gecos(ignored) "&"
|
#define get_gecos(ignored) "&"
|
||||||
@ -15,42 +18,27 @@ static char git_default_date[50];
|
|||||||
#define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos)
|
#define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void copy_gecos(const struct passwd *w, char *name, size_t sz)
|
static void copy_gecos(const struct passwd *w, struct strbuf *name)
|
||||||
{
|
{
|
||||||
char *src, *dst;
|
char *src;
|
||||||
size_t len, nlen;
|
|
||||||
|
|
||||||
nlen = strlen(w->pw_name);
|
|
||||||
|
|
||||||
/* Traditionally GECOS field had office phone numbers etc, separated
|
/* Traditionally GECOS field had office phone numbers etc, separated
|
||||||
* with commas. Also & stands for capitalized form of the login name.
|
* with commas. Also & stands for capitalized form of the login name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (len = 0, dst = name, src = get_gecos(w); len < sz; src++) {
|
for (src = get_gecos(w); *src && *src != ','; src++) {
|
||||||
int ch = *src;
|
int ch = *src;
|
||||||
if (ch != '&') {
|
if (ch != '&')
|
||||||
*dst++ = ch;
|
strbuf_addch(name, ch);
|
||||||
if (ch == 0 || ch == ',')
|
else {
|
||||||
break;
|
|
||||||
len++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (len + nlen < sz) {
|
|
||||||
/* Sorry, Mr. McDonald... */
|
/* Sorry, Mr. McDonald... */
|
||||||
*dst++ = toupper(*w->pw_name);
|
strbuf_addch(name, toupper(*w->pw_name));
|
||||||
memcpy(dst, w->pw_name + 1, nlen - 1);
|
strbuf_addstr(name, w->pw_name + 1);
|
||||||
dst += nlen - 1;
|
|
||||||
len += nlen;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (len < sz)
|
|
||||||
name[len] = 0;
|
|
||||||
else
|
|
||||||
die("Your parents must have hated you!");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_mailname_host(char *buf, size_t len)
|
static int add_mailname_host(struct strbuf *buf)
|
||||||
{
|
{
|
||||||
FILE *mailname;
|
FILE *mailname;
|
||||||
|
|
||||||
@ -61,7 +49,7 @@ static int add_mailname_host(char *buf, size_t len)
|
|||||||
strerror(errno));
|
strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!fgets(buf, len, mailname)) {
|
if (strbuf_getline(buf, mailname, '\n') == EOF) {
|
||||||
if (ferror(mailname))
|
if (ferror(mailname))
|
||||||
warning("cannot read /etc/mailname: %s",
|
warning("cannot read /etc/mailname: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
@ -73,94 +61,67 @@ static int add_mailname_host(char *buf, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_domainname(char *buf, size_t len)
|
static void add_domainname(struct strbuf *out)
|
||||||
{
|
{
|
||||||
|
char buf[1024];
|
||||||
struct hostent *he;
|
struct hostent *he;
|
||||||
size_t namelen;
|
|
||||||
const char *domainname;
|
|
||||||
|
|
||||||
if (gethostname(buf, len)) {
|
if (gethostname(buf, sizeof(buf))) {
|
||||||
warning("cannot get host name: %s", strerror(errno));
|
warning("cannot get host name: %s", strerror(errno));
|
||||||
strlcpy(buf, "(none)", len);
|
strbuf_addstr(out, "(none)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
namelen = strlen(buf);
|
if (strchr(buf, '.'))
|
||||||
if (memchr(buf, '.', namelen))
|
strbuf_addstr(out, buf);
|
||||||
return;
|
else if ((he = gethostbyname(buf)) && strchr(he->h_name, '.'))
|
||||||
|
strbuf_addstr(out, he->h_name);
|
||||||
he = gethostbyname(buf);
|
|
||||||
buf[namelen++] = '.';
|
|
||||||
buf += namelen;
|
|
||||||
len -= namelen;
|
|
||||||
if (he && (domainname = strchr(he->h_name, '.')))
|
|
||||||
strlcpy(buf, domainname + 1, len);
|
|
||||||
else
|
else
|
||||||
strlcpy(buf, "(none)", len);
|
strbuf_addf(out, "%s.(none)", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copy_email(const struct passwd *pw)
|
static void copy_email(const struct passwd *pw, struct strbuf *email)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Make up a fake email address
|
* Make up a fake email address
|
||||||
* (name + '@' + hostname [+ '.' + domainname])
|
* (name + '@' + hostname [+ '.' + domainname])
|
||||||
*/
|
*/
|
||||||
size_t len = strlen(pw->pw_name);
|
strbuf_addstr(email, pw->pw_name);
|
||||||
if (len > sizeof(git_default_email)/2)
|
strbuf_addch(email, '@');
|
||||||
die("Your sysadmin must hate you!");
|
|
||||||
memcpy(git_default_email, pw->pw_name, len);
|
|
||||||
git_default_email[len++] = '@';
|
|
||||||
|
|
||||||
if (!add_mailname_host(git_default_email + len,
|
if (!add_mailname_host(email))
|
||||||
sizeof(git_default_email) - len))
|
|
||||||
return; /* read from "/etc/mailname" (Debian) */
|
return; /* read from "/etc/mailname" (Debian) */
|
||||||
add_domainname(git_default_email + len,
|
add_domainname(email);
|
||||||
sizeof(git_default_email) - len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_ident(const char **name, const char **emailp)
|
const char *ident_default_name(void)
|
||||||
{
|
{
|
||||||
struct passwd *pw = NULL;
|
if (!git_default_name.len) {
|
||||||
|
copy_gecos(xgetpwuid_self(), &git_default_name);
|
||||||
/* Get the name ("gecos") */
|
strbuf_trim(&git_default_name);
|
||||||
if (!*name && !git_default_name[0]) {
|
|
||||||
pw = getpwuid(getuid());
|
|
||||||
if (!pw)
|
|
||||||
die("You don't exist. Go away!");
|
|
||||||
copy_gecos(pw, git_default_name, sizeof(git_default_name));
|
|
||||||
}
|
}
|
||||||
if (!*name)
|
return git_default_name.buf;
|
||||||
*name = git_default_name;
|
}
|
||||||
|
|
||||||
if (!*emailp && !git_default_email[0]) {
|
const char *ident_default_email(void)
|
||||||
|
{
|
||||||
|
if (!git_default_email.len) {
|
||||||
const char *email = getenv("EMAIL");
|
const char *email = getenv("EMAIL");
|
||||||
|
|
||||||
if (email && email[0]) {
|
if (email && email[0]) {
|
||||||
strlcpy(git_default_email, email,
|
strbuf_addstr(&git_default_email, email);
|
||||||
sizeof(git_default_email));
|
|
||||||
user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
|
user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
|
||||||
} else {
|
} else
|
||||||
if (!pw)
|
copy_email(xgetpwuid_self(), &git_default_email);
|
||||||
pw = getpwuid(getuid());
|
strbuf_trim(&git_default_email);
|
||||||
if (!pw)
|
|
||||||
die("You don't exist. Go away!");
|
|
||||||
copy_email(pw);
|
|
||||||
}
|
}
|
||||||
}
|
return git_default_email.buf;
|
||||||
if (!*emailp)
|
|
||||||
*emailp = git_default_email;
|
|
||||||
|
|
||||||
/* And set the default date */
|
|
||||||
if (!git_default_date[0])
|
|
||||||
datestamp(git_default_date, sizeof(git_default_date));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_raw(char *buf, size_t size, int offset, const char *str)
|
const char *ident_default_date(void)
|
||||||
{
|
{
|
||||||
size_t len = strlen(str);
|
if (!git_default_date[0])
|
||||||
if (offset + len > size)
|
datestamp(git_default_date, sizeof(git_default_date));
|
||||||
return size;
|
return git_default_date;
|
||||||
memcpy(buf + offset, str, len);
|
|
||||||
return offset + len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int crud(unsigned char c)
|
static int crud(unsigned char c)
|
||||||
@ -181,7 +142,7 @@ static int crud(unsigned char c)
|
|||||||
* Copy over a string to the destination, but avoid special
|
* Copy over a string to the destination, but avoid special
|
||||||
* characters ('\n', '<' and '>') and remove crud at the end
|
* characters ('\n', '<' and '>') and remove crud at the end
|
||||||
*/
|
*/
|
||||||
static int copy(char *buf, size_t size, int offset, const char *src)
|
static void strbuf_addstr_without_crud(struct strbuf *sb, const char *src)
|
||||||
{
|
{
|
||||||
size_t i, len;
|
size_t i, len;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
@ -205,19 +166,19 @@ static int copy(char *buf, size_t size, int offset, const char *src)
|
|||||||
/*
|
/*
|
||||||
* Copy the rest to the buffer, but avoid the special
|
* Copy the rest to the buffer, but avoid the special
|
||||||
* characters '\n' '<' and '>' that act as delimiters on
|
* characters '\n' '<' and '>' that act as delimiters on
|
||||||
* an identification line
|
* an identification line. We can only remove crud, never add it,
|
||||||
|
* so 'len' is our maximum.
|
||||||
*/
|
*/
|
||||||
|
strbuf_grow(sb, len);
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
c = *src++;
|
c = *src++;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\n': case '<': case '>':
|
case '\n': case '<': case '>':
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (offset >= size)
|
sb->buf[sb->len++] = c;
|
||||||
return size;
|
|
||||||
buf[offset++] = c;
|
|
||||||
}
|
}
|
||||||
return offset;
|
sb->buf[sb->len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -304,57 +265,62 @@ static const char *env_hint =
|
|||||||
const char *fmt_ident(const char *name, const char *email,
|
const char *fmt_ident(const char *name, const char *email,
|
||||||
const char *date_str, int flag)
|
const char *date_str, int flag)
|
||||||
{
|
{
|
||||||
static char buffer[1000];
|
static struct strbuf ident = STRBUF_INIT;
|
||||||
char date[50];
|
char date[50];
|
||||||
int i;
|
int strict = (flag & IDENT_STRICT);
|
||||||
int error_on_no_name = (flag & IDENT_ERROR_ON_NO_NAME);
|
int want_date = !(flag & IDENT_NO_DATE);
|
||||||
int warn_on_no_name = (flag & IDENT_WARN_ON_NO_NAME);
|
int want_name = !(flag & IDENT_NO_NAME);
|
||||||
int name_addr_only = (flag & IDENT_NO_DATE);
|
|
||||||
|
|
||||||
setup_ident(&name, &email);
|
if (want_name && !name)
|
||||||
|
name = ident_default_name();
|
||||||
|
if (!email)
|
||||||
|
email = ident_default_email();
|
||||||
|
|
||||||
if (!*name) {
|
if (want_name && !*name) {
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
if ((warn_on_no_name || error_on_no_name) &&
|
if (strict) {
|
||||||
name == git_default_name && env_hint) {
|
if (name == git_default_name.buf)
|
||||||
fputs(env_hint, stderr);
|
fputs(env_hint, stderr);
|
||||||
env_hint = NULL; /* warn only once */
|
die("empty ident name (for <%s>) not allowed", email);
|
||||||
}
|
}
|
||||||
if (error_on_no_name)
|
pw = xgetpwuid_self();
|
||||||
die("empty ident %s <%s> not allowed", name, email);
|
name = pw->pw_name;
|
||||||
pw = getpwuid(getuid());
|
|
||||||
if (!pw)
|
|
||||||
die("You don't exist. Go away!");
|
|
||||||
strlcpy(git_default_name, pw->pw_name,
|
|
||||||
sizeof(git_default_name));
|
|
||||||
name = git_default_name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(date, git_default_date);
|
if (strict && email == git_default_email.buf &&
|
||||||
if (!name_addr_only && date_str && date_str[0]) {
|
strstr(email, "(none)")) {
|
||||||
|
fputs(env_hint, stderr);
|
||||||
|
die("unable to auto-detect email address (got '%s')", email);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (want_date) {
|
||||||
|
if (date_str && date_str[0]) {
|
||||||
if (parse_date(date_str, date, sizeof(date)) < 0)
|
if (parse_date(date_str, date, sizeof(date)) < 0)
|
||||||
die("invalid date format: %s", date_str);
|
die("invalid date format: %s", date_str);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
i = copy(buffer, sizeof(buffer), 0, name);
|
strcpy(date, ident_default_date());
|
||||||
i = add_raw(buffer, sizeof(buffer), i, " <");
|
|
||||||
i = copy(buffer, sizeof(buffer), i, email);
|
|
||||||
if (!name_addr_only) {
|
|
||||||
i = add_raw(buffer, sizeof(buffer), i, "> ");
|
|
||||||
i = copy(buffer, sizeof(buffer), i, date);
|
|
||||||
} else {
|
|
||||||
i = add_raw(buffer, sizeof(buffer), i, ">");
|
|
||||||
}
|
}
|
||||||
if (i >= sizeof(buffer))
|
|
||||||
die("Impossibly long personal identifier");
|
strbuf_reset(&ident);
|
||||||
buffer[i] = 0;
|
if (want_name) {
|
||||||
return buffer;
|
strbuf_addstr_without_crud(&ident, name);
|
||||||
|
strbuf_addstr(&ident, " <");
|
||||||
|
}
|
||||||
|
strbuf_addstr_without_crud(&ident, email);
|
||||||
|
if (want_name)
|
||||||
|
strbuf_addch(&ident, '>');
|
||||||
|
if (want_date) {
|
||||||
|
strbuf_addch(&ident, ' ');
|
||||||
|
strbuf_addstr_without_crud(&ident, date);
|
||||||
|
}
|
||||||
|
return ident.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *fmt_name(const char *name, const char *email)
|
const char *fmt_name(const char *name, const char *email)
|
||||||
{
|
{
|
||||||
return fmt_ident(name, email, NULL, IDENT_ERROR_ON_NO_NAME | IDENT_NO_DATE);
|
return fmt_ident(name, email, NULL, IDENT_STRICT | IDENT_NO_DATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *git_author_info(int flag)
|
const char *git_author_info(int flag)
|
||||||
@ -385,3 +351,26 @@ int user_ident_sufficiently_given(void)
|
|||||||
return (user_ident_explicitly_given == IDENT_ALL_GIVEN);
|
return (user_ident_explicitly_given == IDENT_ALL_GIVEN);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_ident_config(const char *var, const char *value, void *data)
|
||||||
|
{
|
||||||
|
if (!strcmp(var, "user.name")) {
|
||||||
|
if (!value)
|
||||||
|
return config_error_nonbool(var);
|
||||||
|
strbuf_reset(&git_default_name);
|
||||||
|
strbuf_addstr(&git_default_name, value);
|
||||||
|
user_ident_explicitly_given |= IDENT_NAME_GIVEN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(var, "user.email")) {
|
||||||
|
if (!value)
|
||||||
|
return config_error_nonbool(var);
|
||||||
|
strbuf_reset(&git_default_email);
|
||||||
|
strbuf_addstr(&git_default_email, value);
|
||||||
|
user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
17
log-tree.c
17
log-tree.c
@ -299,19 +299,22 @@ static unsigned int digits_in_number(unsigned int number)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_patch_filename(struct commit *commit, int nr, const char *suffix,
|
void get_patch_filename(struct commit *commit, const char *subject, int nr,
|
||||||
struct strbuf *buf)
|
const char *suffix, struct strbuf *buf)
|
||||||
{
|
{
|
||||||
int suffix_len = strlen(suffix) + 1;
|
int suffix_len = strlen(suffix) + 1;
|
||||||
int start_len = buf->len;
|
int start_len = buf->len;
|
||||||
|
|
||||||
strbuf_addf(buf, commit ? "%04d-" : "%d", nr);
|
strbuf_addf(buf, commit || subject ? "%04d-" : "%d", nr);
|
||||||
if (commit) {
|
if (commit || subject) {
|
||||||
int max_len = start_len + FORMAT_PATCH_NAME_MAX - suffix_len;
|
int max_len = start_len + FORMAT_PATCH_NAME_MAX - suffix_len;
|
||||||
struct pretty_print_context ctx = {0};
|
struct pretty_print_context ctx = {0};
|
||||||
ctx.date_mode = DATE_NORMAL;
|
|
||||||
|
|
||||||
|
if (subject)
|
||||||
|
strbuf_addstr(buf, subject);
|
||||||
|
else if (commit)
|
||||||
format_commit_message(commit, "%f", buf, &ctx);
|
format_commit_message(commit, "%f", buf, &ctx);
|
||||||
|
|
||||||
if (max_len < buf->len)
|
if (max_len < buf->len)
|
||||||
strbuf_setlen(buf, max_len);
|
strbuf_setlen(buf, max_len);
|
||||||
strbuf_addstr(buf, suffix);
|
strbuf_addstr(buf, suffix);
|
||||||
@ -384,8 +387,8 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
|
|||||||
mime_boundary_leader, opt->mime_boundary);
|
mime_boundary_leader, opt->mime_boundary);
|
||||||
extra_headers = subject_buffer;
|
extra_headers = subject_buffer;
|
||||||
|
|
||||||
get_patch_filename(opt->numbered_files ? NULL : commit, opt->nr,
|
get_patch_filename(opt->numbered_files ? NULL : commit, NULL,
|
||||||
opt->patch_suffix, &filename);
|
opt->nr, opt->patch_suffix, &filename);
|
||||||
snprintf(buffer, sizeof(buffer) - 1,
|
snprintf(buffer, sizeof(buffer) - 1,
|
||||||
"\n--%s%s\n"
|
"\n--%s%s\n"
|
||||||
"Content-Type: text/x-patch;"
|
"Content-Type: text/x-patch;"
|
||||||
|
@ -21,7 +21,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
|
|||||||
void load_ref_decorations(int flags);
|
void load_ref_decorations(int flags);
|
||||||
|
|
||||||
#define FORMAT_PATCH_NAME_MAX 64
|
#define FORMAT_PATCH_NAME_MAX 64
|
||||||
void get_patch_filename(struct commit *commit, int nr, const char *suffix,
|
void get_patch_filename(struct commit *commit, const char *subject, int nr,
|
||||||
struct strbuf *buf);
|
const char *suffix, struct strbuf *buf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
12
wrapper.c
12
wrapper.c
@ -402,3 +402,15 @@ int remove_or_warn(unsigned int mode, const char *file)
|
|||||||
{
|
{
|
||||||
return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file);
|
return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct passwd *xgetpwuid_self(void)
|
||||||
|
{
|
||||||
|
struct passwd *pw;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
pw = getpwuid(getuid());
|
||||||
|
if (!pw)
|
||||||
|
die(_("unable to look up current user in the passwd file: %s"),
|
||||||
|
errno ? strerror(errno) : _("no such user"));
|
||||||
|
return pw;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user