{"thread":{"id":"33801","subject":"[PATCH] teach the user to be nice to git and let him say please sometimes","startedAt":"2013-05-12T07:26:18Z","lastAt":"2013-05-12T07:26:18Z","messageCount":1,"participants":["Heiko Voigt"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"217059","messageId":"20130512072616.GC23115@book.hvoigt.net","threadId":"33801","inReplyTo":null,"subject":"[PATCH] teach the user to be nice to git and let him say please sometimes","fromName":"Heiko Voigt","fromEmail":"hvoigt@hvoigt.net","sentAt":"2013-05-12T07:26:18Z","receivedAt":"2013-05-12T07:26:18Z","isPatch":true,"sender":{"key":"hvoigt@hvoigt.net","avatar":"https://avatars.githubusercontent.com/u/184958?v=4"},"body":"Since ages we do not care about our program enough. Lets not treat them\nas slaves anymore and say please.\n\nSigned-off-by: Heiko Voigt <hvoigt@hvoigt.net>\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\nSigned-off-by: Jens Lehmann <Jens.Lehmann@web.de>\nSigned-off-by: Thomas Rast <trast@inf.ethz.ch>\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n\nI do not know why this very urgent patch did not make it to the\nmailinglist yesterday evening. Well here is a resend.\n\n .gitignore                       |  1 +\n Makefile                         |  1 +\n builtin.h                        |  1 +\n builtin/config.c                 | 23 ++-----------------\n builtin/please.c                 |  9 ++++++++\n cache.h                          |  1 +\n config.c                         | 23 +++++++++++++++++++\n contrib/completion/git-prompt.sh |  5 +++-\n git.c                            | 49 +++++++++++++++++++++++++++++++++++++++-\n 9 files changed, 90 insertions(+), 23 deletions(-)\n create mode 100644 builtin/please.c\n\ndiff --git a/.gitignore b/.gitignore\nindex 6669bf0..28dd4cf 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -105,6 +105,7 @@\n /git-parse-remote\n /git-patch-id\n /git-peek-remote\n+/git-please\n /git-prune\n /git-prune-packed\n /git-pull\ndiff --git a/Makefile b/Makefile\nindex 0f931a2..7e22cc0 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -943,6 +943,7 @@ BUILTIN_OBJS += builtin/pack-objects.o\n BUILTIN_OBJS += builtin/pack-redundant.o\n BUILTIN_OBJS += builtin/pack-refs.o\n BUILTIN_OBJS += builtin/patch-id.o\n+BUILTIN_OBJS += builtin/please.o\n BUILTIN_OBJS += builtin/prune-packed.o\n BUILTIN_OBJS += builtin/prune.o\n BUILTIN_OBJS += builtin/push.o\ndiff --git a/builtin.h b/builtin.h\nindex faef559..6fe1d5f 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -105,6 +105,7 @@ extern int cmd_notes(int argc, const char **argv, const char *prefix);\n extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);\n extern int cmd_pack_redundant(int argc, const char **argv, const char *prefix);\n extern int cmd_patch_id(int argc, const char **argv, const char *prefix);\n+extern int cmd_please(int argc, const char **argv, const char *prefix);\n extern int cmd_prune(int argc, const char **argv, const char *prefix);\n extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);\n extern int cmd_push(int argc, const char **argv, const char *prefix);\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 33c9bf9..16b5152 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -364,27 +364,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(builtin_config_usage, builtin_config_options);\n \t}\n \n-\tif (use_global_config) {\n-\t\tchar *user_config = NULL;\n-\t\tchar *xdg_config = NULL;\n-\n-\t\thome_config_paths(&user_config, &xdg_config, \"config\");\n-\n-\t\tif (!user_config)\n-\t\t\t/*\n-\t\t\t * It is unknown if HOME/.gitconfig exists, so\n-\t\t\t * we do not know if we should write to XDG\n-\t\t\t * location; error out even if XDG_CONFIG_HOME\n-\t\t\t * is set and points at a sane location.\n-\t\t\t */\n-\t\t\tdie(\"$HOME not set\");\n-\n-\t\tif (access_or_warn(user_config, R_OK) &&\n-\t\t    xdg_config && !access_or_warn(xdg_config, R_OK))\n-\t\t\tgiven_config_file = xdg_config;\n-\t\telse\n-\t\t\tgiven_config_file = user_config;\n-\t}\n+\tif (use_global_config)\n+\t\tgiven_config_file = git_user_config();\n \telse if (use_system_config)\n \t\tgiven_config_file = git_etc_gitconfig();\n \telse if (use_local_config)\ndiff --git a/builtin/please.c b/builtin/please.c\nnew file mode 100644\nindex 0000000..aea8424\n--- /dev/null\n+++ b/builtin/please.c\n@@ -0,0 +1,9 @@\n+#include \"builtin.h\"\n+#include \"run-command.h\"\n+\n+int cmd_please(int argc, const char **argv, const char *prefix)\n+{\n+\tif (!strcmp(argv[1], \"-h\"))\n+\t\tusage(\"Sometimes\");\n+\treturn run_command_v_opt(argv+1, RUN_GIT_CMD);\n+}\ndiff --git a/cache.h b/cache.h\nindex 94ca1ac..73a9caf 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1164,6 +1164,7 @@ extern int git_config_set_multivar_in_file(const char *, const char *, const cha\n extern int git_config_rename_section(const char *, const char *);\n extern int git_config_rename_section_in_file(const char *, const char *, const char *);\n extern const char *git_etc_gitconfig(void);\n+extern const char *git_user_config(void);\n extern int check_repository_format_version(const char *var, const char *value, void *cb);\n extern int git_env_bool(const char *, int);\n extern int git_config_system(void);\ndiff --git a/config.c b/config.c\nindex aefd80b..8b3e473 100644\n--- a/config.c\n+++ b/config.c\n@@ -935,6 +935,29 @@ const char *git_etc_gitconfig(void)\n \treturn system_wide;\n }\n \n+const char *git_user_config(void)\n+{\n+\tchar *user_config = NULL;\n+\tchar *xdg_config = NULL;\n+\n+\thome_config_paths(&user_config, &xdg_config, \"config\");\n+\n+\tif (!user_config)\n+\t\t/*\n+\t\t * It is unknown if HOME/.gitconfig exists, so\n+\t\t * we do not know if we should write to XDG\n+\t\t * location; error out even if XDG_CONFIG_HOME\n+\t\t * is set and points at a sane location.\n+\t\t */\n+\t\tdie(\"$HOME not set\");\n+\n+\tif (access_or_warn(user_config, R_OK) &&\n+\t\t\txdg_config && !access_or_warn(xdg_config, R_OK))\n+\t\treturn xdg_config;\n+\telse\n+\t\treturn user_config;\n+}\n+\n int git_env_bool(const char *k, int def)\n {\n \tconst char *v = getenv(k);\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex eaf5c36..a455d72 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -241,6 +241,7 @@ __git_ps1 ()\n \tlocal ps1pc_start='\\u@\\h:\\w '\n \tlocal ps1pc_end='\\$ '\n \tlocal printf_format=' (%s)'\n+\texport GIT_POLITENESS_CHECK_PASSED=\"Yes\"\n \n \tcase \"$#\" in\n \t\t2|3)\tpcmode=yes\n@@ -250,7 +251,8 @@ __git_ps1 ()\n \t\t;;\n \t\t0|1)\tprintf_format=\"${1:-$printf_format}\"\n \t\t;;\n-\t\t*)\treturn\n+\t\t*)      unset GIT_POLITENESS_CHECK_PASSED\n+\t\t\treturn\n \t\t;;\n \tesac\n \n@@ -409,4 +411,5 @@ __git_ps1 ()\n \t\t\tprintf -- \"$printf_format\" \"$c${b##refs/heads/}${f:+ $f}$r$p\"\n \t\tfi\n \tfi\n+\tunset GIT_POLITENESS_CHECK_PASSED\n }\ndiff --git a/git.c b/git.c\nindex 1ada169..6c67cef 100644\n--- a/git.c\n+++ b/git.c\n@@ -19,6 +19,8 @@ const char git_more_info_string[] =\n \n static struct startup_info git_startup_info;\n static int use_pager = -1;\n+static int impolite_counter;\n+static int polite_counter;\n \n static void commit_pager_choice(void) {\n \tswitch (use_pager) {\n@@ -302,6 +304,48 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n \treturn 0;\n }\n \n+static int read_polite_counter(const char *key, const char *value, void *data)\n+{\n+\tif (!strcmp(key, \"user.impolite\"))\n+\t\timpolite_counter = git_config_int(key, value);\n+\telse if (!strcmp(key, \"user.polite\"))\n+\t\tpolite_counter = git_config_int(key, value);\n+\treturn 0;\n+}\n+\n+static void check_politeness(const char *cmd)\n+{\n+\tconst char *user_config;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\n+\tif (getenv(\"GIT_POLITENESS_CHECK_PASSED\"))\n+\t\treturn;\n+\n+\tsetenv(\"GIT_POLITENESS_CHECK_PASSED\", \"Yes\", 1);\n+\n+\tgit_config_early(read_polite_counter, NULL, NULL);\n+\tif (!strcmp(cmd, \"please\")) {\n+\t\timpolite_counter = 0;\n+\t\tpolite_counter++;\n+\t} else {\n+\t\timpolite_counter++;\n+\t\tpolite_counter = 0;\n+\t}\n+\n+\tif (impolite_counter > 10)\n+\t\tdie(\"Error: Learn some manners, say please some time!\");\n+\tif (polite_counter > 10)\n+\t\tdie(\"Error: Too many please! I don't believe you.\");\n+\n+\tuser_config = git_user_config();\n+\tstrbuf_addf(&buf, \"%d\", polite_counter);\n+\tgit_config_set_in_file(user_config, \"user.polite\", buf.buf);\n+\tstrbuf_reset(&buf);\n+\tstrbuf_addf(&buf, \"%d\", impolite_counter);\n+\tgit_config_set_in_file(user_config, \"user.impolite\", buf.buf);\n+\tstrbuf_release(&buf);\n+}\n+\n static void handle_internal_command(int argc, const char **argv)\n {\n \tconst char *cmd = argv[0];\n@@ -379,6 +423,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"patch-id\", cmd_patch_id },\n \t\t{ \"peek-remote\", cmd_ls_remote, RUN_SETUP_GENTLY },\n \t\t{ \"pickaxe\", cmd_blame, RUN_SETUP },\n+\t\t{ \"please\", cmd_please, RUN_SETUP_GENTLY },\n \t\t{ \"prune\", cmd_prune, RUN_SETUP },\n \t\t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n \t\t{ \"push\", cmd_push, RUN_SETUP },\n@@ -441,8 +486,11 @@ static void handle_internal_command(int argc, const char **argv)\n \n \tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n \t\tstruct cmd_struct *p = commands+i;\n+\n \t\tif (strcmp(p->cmd, cmd))\n \t\t\tcontinue;\n+\n+\t\tcheck_politeness(cmd);\n \t\texit(run_builtin(p, argc, argv));\n \t}\n }\n@@ -506,7 +554,6 @@ static int run_argv(int *argcp, const char ***argv)\n \treturn done_alias;\n }\n \n-\n int main(int argc, const char **argv)\n {\n \tconst char *cmd;\n-- \n1.8.3.rc1.44.gb387c77\n"}]}