{"thread":{"id":"30768","subject":"[PATCH v3] add 'git credential' plumbing command","startedAt":"2012-06-11T18:44:54Z","lastAt":"2012-06-11T19:14:00Z","messageCount":5,"participants":["javier.roucher-iglesias@ensimag.imag.fr","Matthieu Moy","konglu@minatec.inpg.fr","roucherj"],"isPatch":true,"patchVersion":3,"patchTotal":null},"messages":[{"id":"193346","messageId":"1339440294-8010-1-git-send-email-Javier.Roucher-Iglesias@ensimag.imag.fr","threadId":"30768","inReplyTo":null,"subject":"[PATCH v3] add 'git credential' plumbing command","fromName":"","fromEmail":"javier.roucher-iglesias@ensimag.imag.fr","sentAt":"2012-06-11T18:44:54Z","receivedAt":"2012-06-11T18:44:54Z","isPatch":true,"sender":{"key":"javier.roucher-iglesias@ensimag.imag.fr","avatar":null},"body":"From: Javier Roucher <jroucher@gmail.com>\n\nThe credential API is in C, and not available to scripting languages.\nExpose the functionalities of the API by wrapping them into a new\nplumbing command \"git credentials\".\n\nChanges in the version2 vs version1:\n· Doc have been changed.\n· Correction of git.c:\n\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n· Delete a few lines of code in builtin/credential.c\n\tfor (i = 2; i < argc; i++)\n\t\tstring_list_append(&c.helpers, argv[i]);\n· Correction of the name of the PATCH v2 vs PATCH_v1\n· Code style correction\n\nIf i miss some correction, please remember me. Thanks.\n\nAdding to the next patch, version3:\n· Tests files\n\nSigned-off-by: Pavel Volek <Pavel.Volek@ensimag.imag.fr>\nSigned-off-by: NGUYEN Kim Thuat <Kim-Thuat.Nguyen@ensimag.imag.fr>\nSigned-off-by: ROUCHER IGLESIAS Javier <roucherj@ensimag.imag.fr>\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n\n---\n .gitignore                       |  1 +\n Documentation/git-credential.txt | 74 ++++++++++++++++++++++++++++++++++++++++\n Makefile                         |  1 +\n builtin.h                        |  1 +\n builtin/credential.c             | 37 ++++++++++++++++++++\n git.c                            |  1 +\n 6 files changed, 115 insertions(+)\n create mode 100644 Documentation/git-credential.txt\n create mode 100644 builtin/credential.c\n\ndiff --git a/.gitignore b/.gitignore\nindex bf66648..7d1d86e 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -31,6 +31,7 @@\n /git-commit-tree\n /git-config\n /git-count-objects\n+/git-credential\n /git-credential-cache\n /git-credential-cache--daemon\n /git-credential-store\ndiff --git a/Documentation/git-credential.txt b/Documentation/git-credential.txt\nnew file mode 100644\nindex 0000000..ad4e6c7\n--- /dev/null\n+++ b/Documentation/git-credential.txt\n@@ -0,0 +1,74 @@\n+git-credential(7)\n+=================\n+\n+NAME\n+----\n+git-credential - Provides and store user credentials to git\n+\n+SYNOPSIS\n+--------\n+------------------\n+git credential <fill|approve|reject>\n+\n+------------------\n+\n+DESCRIPTION\n+-----------\n+\n+Git-credential permits to the user of the script to save:\n+username, password, host, path and protocol. When the user of script\n+invoke git-credential, the script can ask for a password, using the command\n+'git credential fill'.\n+Taking data from the standard input, the program treats each line as a\n+separate data item, and the end of series of data item is signalled by a \n+blank line.\n+\n+\t\tusername=admin\\n \n+\t\tprotocol=[http|https]\\n\n+\t\thost=localhost\\n\n+\t\tpath=/dir\\n\\n\n+\n+-If git-credential system has the password already stored\n+git-credential will answer with by STDOUT:\n+\t\n+\t\tusername=admin\n+\t\tpassword=*****\n+\n+-If it is not stored, the user will be prompt for a password:\n+\t\t\n+\t\t> Password for '[http|https]admin@localhost':\n+\n+\n+Then if the password is correct, (note: it's not git credential that\n+decides if the password is correct or not. That part is done by the \n+external system) it can be stored using command 'git crendential approve' \n+by providing the structure, by STDIN.\n+\n+\t\tusername=admin\n+\t\tpassword=*****\n+\t\tprotocol=[http|https]\n+\t\thost=localhost\n+\t\tpath=/dir\n+\n+If the password is refused, it can be deleted using command\n+'git credential reject' by providing the same structure.\n+\n+\n+REQUESTING CREDENTIALS\n+----------------------\n+\n+1. The 'git credential fill' makes the structure,\n+with this structure it will be able to save your\n+credentials, and if the credential is already stored,\n+it will fill the password.\n+\n+\t\tusername=foo\n+\t\tpassword=****\n+\t\tprotocol=[http|https]\n+\t\tlocalhost=url\n+\t\tpath=/direction\n+\n+2. Then 'git credential approve' to store them.\n+\n+3. Otherwise, if the credential is not correct you can do\n+  'git credential reject' to delete the credential.\ndiff --git a/Makefile b/Makefile\nindex 4592f1f..3f53da8 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -827,6 +827,7 @@ BUILTIN_OBJS += builtin/commit-tree.o\n BUILTIN_OBJS += builtin/commit.o\n BUILTIN_OBJS += builtin/config.o\n BUILTIN_OBJS += builtin/count-objects.o\n+BUILTIN_OBJS += builtin/credential.o\n BUILTIN_OBJS += builtin/describe.o\n BUILTIN_OBJS += builtin/diff-files.o\n BUILTIN_OBJS += builtin/diff-index.o\ndiff --git a/builtin.h b/builtin.h\nindex 338f540..48feddc 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -66,6 +66,7 @@ extern int cmd_commit(int argc, const char **argv, const char *prefix);\n extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);\n extern int cmd_config(int argc, const char **argv, const char *prefix);\n extern int cmd_count_objects(int argc, const char **argv, const char *prefix);\n+extern int cmd_credential(int argc, const char **argv, const char *prefix);\n extern int cmd_describe(int argc, const char **argv, const char *prefix);\n extern int cmd_diff_files(int argc, const char **argv, const char *prefix);\n extern int cmd_diff_index(int argc, const char **argv, const char *prefix);\ndiff --git a/builtin/credential.c b/builtin/credential.c\nnew file mode 100644\nindex 0000000..a6b6962\n--- /dev/null\n+++ b/builtin/credential.c\n@@ -0,0 +1,37 @@\n+#include <stdio.h>\n+#include \"cache.h\"\n+#include \"credential.h\"\n+#include \"string-list.h\"\n+\n+static const char usage_msg[] =\n+\"credential <fill|approve|reject>\";\n+\n+void cmd_credential (int argc, char **argv, const char *prefix) {\n+\tconst char *op;\n+\tstruct credential c = CREDENTIAL_INIT;\n+\tint i;\n+\n+\top = argv[1];\n+\tif (!op)\n+\t\tusage(usage_msg);\n+\n+\tif (credential_read(&c, stdin) < 0)\n+\t\tdie(\"unable to read credential from stdin\");\n+\n+\tif (!strcmp(op, \"fill\")) {\n+\t\tcredential_fill(&c);\n+\t\tif (c.username)\n+\t\t\tprintf(\"username=%s\\n\", c.username);\n+\t\tif (c.password)\n+\t\t\tprintf(\"password=%s\\n\", c.password);\n+\t}\n+\telse if (!strcmp(op, \"approve\")) {\n+\t\tcredential_approve(&c);\n+\t}\n+\telse if (!strcmp(op, \"reject\")) {\n+\t\tcredential_reject(&c);\n+\t}\n+\telse {\n+\t\tusage(usage_msg);\n+\t}\n+}\ndiff --git a/git.c b/git.c\nindex d232de9..660c926 100644\n--- a/git.c\n+++ b/git.c\n@@ -353,6 +353,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n \t\t{ \"config\", cmd_config, RUN_SETUP_GENTLY },\n \t\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n+\t\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n \t\t{ \"describe\", cmd_describe, RUN_SETUP },\n \t\t{ \"diff\", cmd_diff },\n \t\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },\n-- \n1.7.11.rc2.4.gfbe8a84.dirty\n"},{"id":"193356","messageId":"vpqehpl4qm0.fsf@bauges.imag.fr","threadId":"30768","inReplyTo":"1339440294-8010-1-git-send-email-Javier.Roucher-Iglesias@ensimag.imag.fr","subject":"Re: [PATCH v3] add 'git credential' plumbing command","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2012-06-11T19:04:39Z","receivedAt":"2012-06-11T19:04:39Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"> Subject: Re: [PATCH v3] add 'git credential' plumbing command\n\nI guess you mean v2.\n\nJavier.Roucher-Iglesias@ensimag.imag.fr writes:\n\n> Changes in the version2 vs version1:\n\nThese should not go to the commit message, but below the --- below (and\nbefore the diffstat).\n\n> Adding to the next patch, version3:\n> · Tests files\n\nIf the todo-list isn't empty, then mark your patch as \"RFC\".\n\n> --- /dev/null\n> +++ b/Documentation/git-credential.txt\n> @@ -0,0 +1,74 @@\n> +git-credential(7)\n> +=================\n> +\n> +NAME\n> +----\n> +git-credential - Provides and store user credentials to git\n\nProvides -> Provide\n\nI'd remove the \"to git\" part.\n\nOther than that, I prefer Jeff's version sent yesterday. Any reason not\nto use it?\n\nThe command still isn't listed in \"man git\", aka Documentation/git.txt\n(I already mentionned it)\n\n> +\tif (!strcmp(op, \"fill\")) {\n> +\t\tcredential_fill(&c);\n> +\t\tif (c.username)\n> +\t\t\tprintf(\"username=%s\\n\", c.username);\n> +\t\tif (c.password)\n> +\t\t\tprintf(\"password=%s\\n\", c.password);\n> +\t}\n\nSee Jeff's remarks. It makes sense to output all fields here\n(protocol, path, ...).\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"193357","messageId":"20120611210745.Horde.72y3YnwdC4BP1kIBup3BWrA@webmail.minatec.grenoble-inp.fr","threadId":"30768","inReplyTo":"1339440294-8010-1-git-send-email-Javier.Roucher-Iglesias@ensimag.imag.fr","subject":"Re: [PATCH v3] add 'git credential' plumbing command","fromName":"","fromEmail":"konglu@minatec.inpg.fr","sentAt":"2012-06-11T19:07:45Z","receivedAt":"2012-06-11T19:07:45Z","isPatch":true,"sender":{"key":"konglu@minatec.inpg.fr","avatar":null},"body":"\nJavier.Roucher-Iglesias@ensimag.imag.fr a écrit :\n\n> +Git-credential permits to the user of the script to save:\n> +username, password, host, path and protocol. When the user of script\n> +invoke git-credential, the script can ask for a password, using the command\n> +'git credential fill'.\n> +Taking data from the standard input, the program treats each line as a\n> +separate data item, and the end of series of data item is signalled by a\n> +blank line.\n> +\n> +\t\tusername=admin\\n\n> +\t\tprotocol=[http|https]\\n\n> +\t\thost=localhost\\n\n> +\t\tpath=/dir\\n\\n\n> +\n> +-If git-credential system has the password already stored\n> +git-credential will answer with by STDOUT:\n> +\n> +\t\tusername=admin\n> +\t\tpassword=*****\n> +\n> +-If it is not stored, the user will be prompt for a password:\n> +\n> +\t\t> Password for '[http|https]admin@localhost':\n\nWhitespaces detected (and also some more after in the doc)\n\n> diff --git a/builtin/credential.c b/builtin/credential.c\n> new file mode 100644\n> index 0000000..a6b6962\n> --- /dev/null\n> +++ b/builtin/credential.c\n> @@ -0,0 +1,37 @@\n> +#include <stdio.h>\n> +#include \"cache.h\"\n> +#include \"credential.h\"\n> +#include \"string-list.h\"\n> +\n> +static const char usage_msg[] =\n> +\"credential <fill|approve|reject>\";\n> +\n> +void cmd_credential (int argc, char **argv, const char *prefix) {\n> +\tconst char *op;\n> +\tstruct credential c = CREDENTIAL_INIT;\n> +\tint i;\n> +\n> +\top = argv[1];\n> +\tif (!op)\n> +\t\tusage(usage_msg);\n> +\n> +\tif (credential_read(&c, stdin) < 0)\n> +\t\tdie(\"unable to read credential from stdin\");\n> +\n> +\tif (!strcmp(op, \"fill\")) {\n> +\t\tcredential_fill(&c);\n> +\t\tif (c.username)\n> +\t\t\tprintf(\"username=%s\\n\", c.username);\n> +\t\tif (c.password)\n> +\t\t\tprintf(\"password=%s\\n\", c.password);\n> +\t}\n> +\telse if (!strcmp(op, \"approve\")) {\n> +\t\tcredential_approve(&c);\n> +\t}\n> +\telse if (!strcmp(op, \"reject\")) {\n> +\t\tcredential_reject(&c);\n> +\t}\n> +\telse {\n> +\t\tusage(usage_msg);\n> +\t}\n> +}\n\nStructure:\n\n\tif (!strcmp(op, \"fill\")) {\n\t\tcredential_fill(&c);\n\t\tif (c.username)\n\t\t\tprintf(\"username=%s\\n\", c.username);\n\t\tif (c.password)\n\t\t\tprintf(\"password=%s\\n\", c.password);\n\t} else if (!strcmp(op, \"approve\")) {\n\t\tcredential_approve(&c);\n\t} else if (!strcmp(op, \"reject\")) {\n\t\tcredential_reject(&c);\n\t} else {\n\t\tusage(usage_msg);\n\t}\n"},{"id":"193359","messageId":"edf83e30636b67d2b95bf1df8519cdcd@telesun.imag.fr","threadId":"30768","inReplyTo":"vpqehpl4qm0.fsf@bauges.imag.fr","subject":"Re: [PATCH v3] add 'git credential' plumbing command","fromName":"roucherj","fromEmail":"roucherj@telesun.imag.fr","sentAt":"2012-06-11T19:12:17Z","receivedAt":"2012-06-11T19:12:17Z","isPatch":true,"sender":{"key":"roucherj@telesun.imag.fr","avatar":null},"body":"On Mon, 11 Jun 2012 21:04:39 +0200, Matthieu Moy wrote:\n>> Subject: Re: [PATCH v3] add 'git credential' plumbing command\n>\n> I guess you mean v2.\n>\n\nSorry is a miss typing.\n\n> Javier.Roucher-Iglesias@ensimag.imag.fr writes:\n>\n>> Changes in the version2 vs version1:\n>\n> These should not go to the commit message, but below the --- below \n> (and\n> before the diffstat).\n>\n>> Adding to the next patch, version3:\n>> · Tests files\n>\n> If the todo-list isn't empty, then mark your patch as \"RFC\".\n>\n>> --- /dev/null\n>> +++ b/Documentation/git-credential.txt\n>> @@ -0,0 +1,74 @@\n>> +git-credential(7)\n>> +=================\n>> +\n>> +NAME\n>> +----\n>> +git-credential - Provides and store user credentials to git\n>\n> Provides -> Provide\n>\n> I'd remove the \"to git\" part.\n>\n\nChanged it\n\n\n> Other than that, I prefer Jeff's version sent yesterday. Any reason \n> not\n> to use it?\n>\n> The command still isn't listed in \"man git\", aka \n> Documentation/git.txt\n> (I already mentionned it)\n>\n>> +\tif (!strcmp(op, \"fill\")) {\n>> +\t\tcredential_fill(&c);\n>> +\t\tif (c.username)\n>> +\t\t\tprintf(\"username=%s\\n\", c.username);\n>> +\t\tif (c.password)\n>> +\t\t\tprintf(\"password=%s\\n\", c.password);\n>> +\t}\n>\n> See Jeff's remarks. It makes sense to output all fields here\n> (protocol, path, ...).\n\nokay for the next patch i will add (protocol, path, ..)\n"},{"id":"193361","messageId":"0425823888ed7e40d9332e148ac9e77a@telesun.imag.fr","threadId":"30768","inReplyTo":"20120611210745.Horde.72y3YnwdC4BP1kIBup3BWrA@webmail.minatec.grenoble-inp.fr","subject":"Re: [PATCH v3] add 'git credential' plumbing command","fromName":"roucherj","fromEmail":"roucherj@telesun.imag.fr","sentAt":"2012-06-11T19:14:00Z","receivedAt":"2012-06-11T19:14:00Z","isPatch":true,"sender":{"key":"roucherj@telesun.imag.fr","avatar":null},"body":"On Mon, 11 Jun 2012 21:07:45 +0200, konglu@minatec.inpg.fr wrote:\n> Javier.Roucher-Iglesias@ensimag.imag.fr a écrit :\n>\n>> +Git-credential permits to the user of the script to save:\n>> +username, password, host, path and protocol. When the user of \n>> script\n>> +invoke git-credential, the script can ask for a password, using the \n>> command\n>> +'git credential fill'.\n>> +Taking data from the standard input, the program treats each line \n>> as a\n>> +separate data item, and the end of series of data item is signalled \n>> by a\n>> +blank line.\n>> +\n>> +\t\tusername=admin\\n\n>> +\t\tprotocol=[http|https]\\n\n>> +\t\thost=localhost\\n\n>> +\t\tpath=/dir\\n\\n\n>> +\n>> +-If git-credential system has the password already stored\n>> +git-credential will answer with by STDOUT:\n>> +\n>> +\t\tusername=admin\n>> +\t\tpassword=*****\n>> +\n>> +-If it is not stored, the user will be prompt for a password:\n>> +\n>> +\t\t> Password for '[http|https]admin@localhost':\n>\n> Whitespaces detected (and also some more after in the doc)\n>\n>> diff --git a/builtin/credential.c b/builtin/credential.c\n>> new file mode 100644\n>> index 0000000..a6b6962\n>> --- /dev/null\n>> +++ b/builtin/credential.c\n>> @@ -0,0 +1,37 @@\n>> +#include <stdio.h>\n>> +#include \"cache.h\"\n>> +#include \"credential.h\"\n>> +#include \"string-list.h\"\n>> +\n>> +static const char usage_msg[] =\n>> +\"credential <fill|approve|reject>\";\n>> +\n>> +void cmd_credential (int argc, char **argv, const char *prefix) {\n>> +\tconst char *op;\n>> +\tstruct credential c = CREDENTIAL_INIT;\n>> +\tint i;\n>> +\n>> +\top = argv[1];\n>> +\tif (!op)\n>> +\t\tusage(usage_msg);\n>> +\n>> +\tif (credential_read(&c, stdin) < 0)\n>> +\t\tdie(\"unable to read credential from stdin\");\n>> +\n>> +\tif (!strcmp(op, \"fill\")) {\n>> +\t\tcredential_fill(&c);\n>> +\t\tif (c.username)\n>> +\t\t\tprintf(\"username=%s\\n\", c.username);\n>> +\t\tif (c.password)\n>> +\t\t\tprintf(\"password=%s\\n\", c.password);\n>> +\t}\n>> +\telse if (!strcmp(op, \"approve\")) {\n>> +\t\tcredential_approve(&c);\n>> +\t}\n>> +\telse if (!strcmp(op, \"reject\")) {\n>> +\t\tcredential_reject(&c);\n>> +\t}\n>> +\telse {\n>> +\t\tusage(usage_msg);\n>> +\t}\n>> +}\n>\n> Structure:\n>\n> if (!strcmp(op, \"fill\")) {\n> \tcredential_fill(&c);\n> \tif (c.username)\n> \t\tprintf(\"username=%s\\n\", c.username);\n> \tif (c.password)\n> \t\tprintf(\"password=%s\\n\", c.password);\n> } else if (!strcmp(op, \"approve\")) {\n> \tcredential_approve(&c);\n> } else if (!strcmp(op, \"reject\")) {\n> \tcredential_reject(&c);\n> } else {\n> \tusage(usage_msg);\n> }\n\n\nI will change the structure, thanks.\n"}]}