{"thread":{"id":"31114","subject":"[PATCH v3] contrib: add win32 credential-helper","startedAt":"2012-07-27T17:10:06Z","lastAt":"2012-08-17T17:19:16Z","messageCount":5,"participants":["Erik Faye-Lund","Junio C Hamano"],"isPatch":true,"patchVersion":3,"patchTotal":null},"messages":[{"id":"195948","messageId":"1343409006-5056-1-git-send-email-kusmabite@gmail.com","threadId":"31114","inReplyTo":null,"subject":"[PATCH v3] contrib: add win32 credential-helper","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2012-07-27T17:10:06Z","receivedAt":"2012-07-27T17:10:06Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Since the Windows port of Git expects binary pipes, we need to make\nsure the helper-end also sets up binary pipes.\n\nSide-step CRLF-issue in test to make it pass.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n\nSorry for the delay, but here's the third iteration of my credential\nhelper for Windows' credential API.\n\nThe only change since v2 is that it now supports protocols without\na host component, as suggested by Jeff King.\n\n contrib/credential/wincred/Makefile                |   8 +\n .../credential/wincred/git-credential-wincred.c    | 357 +++++++++++++++++++++\n t/lib-credential.sh                                |   4 +\n 3 files changed, 369 insertions(+)\n create mode 100644 contrib/credential/wincred/Makefile\n create mode 100644 contrib/credential/wincred/git-credential-wincred.c\n\ndiff --git a/contrib/credential/wincred/Makefile b/contrib/credential/wincred/Makefile\nnew file mode 100644\nindex 0000000..b4f098f\n--- /dev/null\n+++ b/contrib/credential/wincred/Makefile\n@@ -0,0 +1,8 @@\n+all: git-credential-wincred.exe\n+\n+CC = gcc\n+RM = rm -f\n+CFLAGS = -O2 -Wall\n+\n+git-credential-wincred.exe : git-credential-wincred.c\n+\t$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@\ndiff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c\nnew file mode 100644\nindex 0000000..cbaec5f\n--- /dev/null\n+++ b/contrib/credential/wincred/git-credential-wincred.c\n@@ -0,0 +1,357 @@\n+/*\n+ * A git credential helper that interface with Windows' Credential Manager\n+ *\n+ */\n+#include <windows.h>\n+#include <stdio.h>\n+#include <io.h>\n+#include <fcntl.h>\n+\n+/* common helpers */\n+\n+static void die(const char *err, ...)\n+{\n+\tchar msg[4096];\n+\tva_list params;\n+\tva_start(params, err);\n+\tvsnprintf(msg, sizeof(msg), err, params);\n+\tfprintf(stderr, \"%s\\n\", msg);\n+\tva_end(params);\n+\texit(1);\n+}\n+\n+static void *xmalloc(size_t size)\n+{\n+\tvoid *ret = malloc(size);\n+\tif (!ret && !size)\n+\t\tret = malloc(1);\n+\tif (!ret)\n+\t\t die(\"Out of memory\");\n+\treturn ret;\n+}\n+\n+static char *xstrdup(const char *str)\n+{\n+\tchar *ret = strdup(str);\n+\tif (!ret)\n+\t\tdie(\"Out of memory\");\n+\treturn ret;\n+}\n+\n+/* MinGW doesn't have wincred.h, so we need to define stuff */\n+\n+typedef struct _CREDENTIAL_ATTRIBUTEW {\n+\tLPWSTR Keyword;\n+\tDWORD  Flags;\n+\tDWORD  ValueSize;\n+\tLPBYTE Value;\n+} CREDENTIAL_ATTRIBUTEW, *PCREDENTIAL_ATTRIBUTEW;\n+\n+typedef struct _CREDENTIALW {\n+\tDWORD                  Flags;\n+\tDWORD                  Type;\n+\tLPWSTR                 TargetName;\n+\tLPWSTR                 Comment;\n+\tFILETIME               LastWritten;\n+\tDWORD                  CredentialBlobSize;\n+\tLPBYTE                 CredentialBlob;\n+\tDWORD                  Persist;\n+\tDWORD                  AttributeCount;\n+\tPCREDENTIAL_ATTRIBUTEW Attributes;\n+\tLPWSTR                 TargetAlias;\n+\tLPWSTR                 UserName;\n+} CREDENTIALW, *PCREDENTIALW;\n+\n+#define CRED_TYPE_GENERIC 1\n+#define CRED_PERSIST_LOCAL_MACHINE 2\n+#define CRED_MAX_ATTRIBUTES 64\n+\n+typedef BOOL (WINAPI *CredWriteWT)(PCREDENTIALW, DWORD);\n+typedef BOOL (WINAPI *CredUnPackAuthenticationBufferWT)(DWORD, PVOID, DWORD,\n+    LPWSTR, DWORD *, LPWSTR, DWORD *, LPWSTR, DWORD *);\n+typedef BOOL (WINAPI *CredEnumerateWT)(LPCWSTR, DWORD, DWORD *,\n+    PCREDENTIALW **);\n+typedef BOOL (WINAPI *CredPackAuthenticationBufferWT)(DWORD, LPWSTR, LPWSTR,\n+    PBYTE, DWORD *);\n+typedef VOID (WINAPI *CredFreeT)(PVOID);\n+typedef BOOL (WINAPI *CredDeleteWT)(LPCWSTR, DWORD, DWORD);\n+\n+static HMODULE advapi, credui;\n+static CredWriteWT CredWriteW;\n+static CredUnPackAuthenticationBufferWT CredUnPackAuthenticationBufferW;\n+static CredEnumerateWT CredEnumerateW;\n+static CredPackAuthenticationBufferWT CredPackAuthenticationBufferW;\n+static CredFreeT CredFree;\n+static CredDeleteWT CredDeleteW;\n+\n+static void load_cred_funcs(void)\n+{\n+\t/* load DLLs */\n+\tadvapi = LoadLibrary(\"advapi32.dll\");\n+\tcredui = LoadLibrary(\"credui.dll\");\n+\tif (!advapi || !credui)\n+\t\tdie(\"failed to load DLLs\");\n+\n+\t/* get function pointers */\n+\tCredWriteW = (CredWriteWT)GetProcAddress(advapi, \"CredWriteW\");\n+\tCredUnPackAuthenticationBufferW = (CredUnPackAuthenticationBufferWT)\n+\t    GetProcAddress(credui, \"CredUnPackAuthenticationBufferW\");\n+\tCredEnumerateW = (CredEnumerateWT)GetProcAddress(advapi,\n+\t    \"CredEnumerateW\");\n+\tCredPackAuthenticationBufferW = (CredPackAuthenticationBufferWT)\n+\t    GetProcAddress(credui, \"CredPackAuthenticationBufferW\");\n+\tCredFree = (CredFreeT)GetProcAddress(advapi, \"CredFree\");\n+\tCredDeleteW = (CredDeleteWT)GetProcAddress(advapi, \"CredDeleteW\");\n+\tif (!CredWriteW || !CredUnPackAuthenticationBufferW ||\n+\t    !CredEnumerateW || !CredPackAuthenticationBufferW || !CredFree ||\n+\t    !CredDeleteW)\n+\t\tdie(\"failed to load functions\");\n+}\n+\n+static char target_buf[1024];\n+static char *protocol, *host, *path, *username;\n+static WCHAR *wusername, *password, *target;\n+\n+static void write_item(const char *what, WCHAR *wbuf)\n+{\n+\tchar *buf;\n+\tint len = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL,\n+\t    FALSE);\n+\tbuf = xmalloc(len);\n+\n+\tif (!WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, len, NULL, FALSE))\n+\t\tdie(\"WideCharToMultiByte failed!\");\n+\n+\tprintf(\"%s=\", what);\n+\tfwrite(buf, 1, len - 1, stdout);\n+\tputchar('\\n');\n+\tfree(buf);\n+}\n+\n+static int match_attr(const CREDENTIALW *cred, const WCHAR *keyword,\n+    const char *want)\n+{\n+\tint i;\n+\tif (!want)\n+\t\treturn 1;\n+\n+\tfor (i = 0; i < cred->AttributeCount; ++i)\n+\t\tif (!wcscmp(cred->Attributes[i].Keyword, keyword))\n+\t\t\treturn !strcmp((const char *)cred->Attributes[i].Value,\n+\t\t\t    want);\n+\n+\treturn 0; /* not found */\n+}\n+\n+static int match_cred(const CREDENTIALW *cred)\n+{\n+\treturn (!wusername || !wcscmp(wusername, cred->UserName)) &&\n+\t    match_attr(cred, L\"git_protocol\", protocol) &&\n+\t    match_attr(cred, L\"git_host\", host) &&\n+\t    match_attr(cred, L\"git_path\", path);\n+}\n+\n+static void get_credential(void)\n+{\n+\tWCHAR *user_buf, *pass_buf;\n+\tDWORD user_buf_size = 0, pass_buf_size = 0;\n+\tCREDENTIALW **creds, *cred = NULL;\n+\tDWORD num_creds;\n+\tint i;\n+\n+\tif (!CredEnumerateW(L\"git:*\", 0, &num_creds, &creds))\n+\t\treturn;\n+\n+\t/* search for the first credential that matches username */\n+\tfor (i = 0; i < num_creds; ++i)\n+\t\tif (match_cred(creds[i])) {\n+\t\t\tcred = creds[i];\n+\t\t\tbreak;\n+\t\t}\n+\tif (!cred)\n+\t\treturn;\n+\n+\tCredUnPackAuthenticationBufferW(0, cred->CredentialBlob,\n+\t    cred->CredentialBlobSize, NULL, &user_buf_size, NULL, NULL,\n+\t    NULL, &pass_buf_size);\n+\n+\tuser_buf = xmalloc(user_buf_size * sizeof(WCHAR));\n+\tpass_buf = xmalloc(pass_buf_size * sizeof(WCHAR));\n+\n+\tif (!CredUnPackAuthenticationBufferW(0, cred->CredentialBlob,\n+\t    cred->CredentialBlobSize, user_buf, &user_buf_size, NULL, NULL,\n+\t    pass_buf, &pass_buf_size))\n+\t\tdie(\"CredUnPackAuthenticationBuffer failed\");\n+\n+\tCredFree(creds);\n+\n+\t/* zero-terminate (sizes include zero-termination) */\n+\tuser_buf[user_buf_size - 1] = L'\\0';\n+\tpass_buf[pass_buf_size - 1] = L'\\0';\n+\n+\twrite_item(\"username\", user_buf);\n+\twrite_item(\"password\", pass_buf);\n+\n+\tfree(user_buf);\n+\tfree(pass_buf);\n+}\n+\n+static void write_attr(CREDENTIAL_ATTRIBUTEW *attr, const WCHAR *keyword,\n+    const char *value)\n+{\n+\tattr->Keyword = (LPWSTR)keyword;\n+\tattr->Flags = 0;\n+\tattr->ValueSize = strlen(value) + 1; /* store zero-termination */\n+\tattr->Value = (LPBYTE)value;\n+}\n+\n+static void store_credential(void)\n+{\n+\tCREDENTIALW cred;\n+\tBYTE *auth_buf;\n+\tDWORD auth_buf_size = 0;\n+\tCREDENTIAL_ATTRIBUTEW attrs[CRED_MAX_ATTRIBUTES];\n+\n+\tif (!wusername || !password)\n+\t\treturn;\n+\n+\t/* query buffer size */\n+\tCredPackAuthenticationBufferW(0, wusername, password,\n+\t    NULL, &auth_buf_size);\n+\n+\tauth_buf = xmalloc(auth_buf_size);\n+\n+\tif (!CredPackAuthenticationBufferW(0, wusername, password,\n+\t    auth_buf, &auth_buf_size))\n+\t\tdie(\"CredPackAuthenticationBuffer failed\");\n+\n+\tcred.Flags = 0;\n+\tcred.Type = CRED_TYPE_GENERIC;\n+\tcred.TargetName = target;\n+\tcred.Comment = L\"saved by git-credential-wincred\";\n+\tcred.CredentialBlobSize = auth_buf_size;\n+\tcred.CredentialBlob = auth_buf;\n+\tcred.Persist = CRED_PERSIST_LOCAL_MACHINE;\n+\tcred.AttributeCount = 1;\n+\tcred.Attributes = attrs;\n+\tcred.TargetAlias = NULL;\n+\tcred.UserName = wusername;\n+\n+\twrite_attr(attrs, L\"git_protocol\", protocol);\n+\n+\tif (host) {\n+\t\twrite_attr(attrs + cred.AttributeCount, L\"git_host\", host);\n+\t\tcred.AttributeCount++;\n+\t}\n+\n+\tif (path) {\n+\t\twrite_attr(attrs + cred.AttributeCount, L\"git_path\", path);\n+\t\tcred.AttributeCount++;\n+\t}\n+\n+\tif (!CredWriteW(&cred, 0))\n+\t\tdie(\"CredWrite failed\");\n+}\n+\n+static void erase_credential(void)\n+{\n+\tCREDENTIALW **creds;\n+\tDWORD num_creds;\n+\tint i;\n+\n+\tif (!CredEnumerateW(L\"git:*\", 0, &num_creds, &creds))\n+\t\treturn;\n+\n+\tfor (i = 0; i < num_creds; ++i) {\n+\t\tif (match_cred(creds[i]))\n+\t\t\tCredDeleteW(creds[i]->TargetName, creds[i]->Type, 0);\n+\t}\n+\n+\tCredFree(creds);\n+}\n+\n+static WCHAR *utf8_to_utf16_dup(const char *str)\n+{\n+\tint wlen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);\n+\tWCHAR *wstr = xmalloc(sizeof(WCHAR) * wlen);\n+\tMultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, wlen);\n+\treturn wstr;\n+}\n+\n+static void read_credential(void)\n+{\n+\tchar buf[1024];\n+\n+\twhile (fgets(buf, sizeof(buf), stdin)) {\n+\t\tchar *v;\n+\n+\t\tif (!strcmp(buf, \"\\n\"))\n+\t\t\tbreak;\n+\t\tbuf[strlen(buf)-1] = '\\0';\n+\n+\t\tv = strchr(buf, '=');\n+\t\tif (!v)\n+\t\t\tdie(\"bad input: %s\", buf);\n+\t\t*v++ = '\\0';\n+\n+\t\tif (!strcmp(buf, \"protocol\"))\n+\t\t\tprotocol = xstrdup(v);\n+\t\telse if (!strcmp(buf, \"host\"))\n+\t\t\thost = xstrdup(v);\n+\t\telse if (!strcmp(buf, \"path\"))\n+\t\t\tpath = xstrdup(v);\n+\t\telse if (!strcmp(buf, \"username\")) {\n+\t\t\tusername = xstrdup(v);\n+\t\t\twusername = utf8_to_utf16_dup(v);\n+\t\t} else if (!strcmp(buf, \"password\"))\n+\t\t\tpassword = utf8_to_utf16_dup(v);\n+\t\telse\n+\t\t\tdie(\"unrecognized input\");\n+\t}\n+}\n+\n+int main(int argc, char *argv[])\n+{\n+\tconst char *usage =\n+\t    \"Usage: git credential-wincred <get|store|erase>\\n\";\n+\n+\tif (!argv[1])\n+\t\tdie(usage);\n+\n+\t/* git use binary pipes to avoid CRLF-issues */\n+\t_setmode(_fileno(stdin), _O_BINARY);\n+\t_setmode(_fileno(stdout), _O_BINARY);\n+\n+\tread_credential();\n+\n+\tload_cred_funcs();\n+\n+\tif (!protocol || !(host || path))\n+\t\treturn 0;\n+\n+\t/* prepare 'target', the unique key for the credential */\n+\tstrncat(target_buf, \"git:\", sizeof(target_buf));\n+\tstrncat(target_buf, protocol, sizeof(target_buf));\n+\tstrncat(target_buf, \"://\", sizeof(target_buf));\n+\tif (username) {\n+\t\tstrncat(target_buf, username, sizeof(target_buf));\n+\t\tstrncat(target_buf, \"@\", sizeof(target_buf));\n+\t}\n+\tif (host)\n+\t\tstrncat(target_buf, host, sizeof(target_buf));\n+\tif (path) {\n+\t\tstrncat(target_buf, \"/\", sizeof(target_buf));\n+\t\tstrncat(target_buf, path, sizeof(target_buf));\n+\t}\n+\n+\ttarget = utf8_to_utf16_dup(target_buf);\n+\n+\tif (!strcmp(argv[1], \"get\"))\n+\t\tget_credential();\n+\telse if (!strcmp(argv[1], \"store\"))\n+\t\tstore_credential();\n+\telse if (!strcmp(argv[1], \"erase\"))\n+\t\terase_credential();\n+\t/* otherwise, ignore unknown action */\n+\treturn 0;\n+}\ndiff --git a/t/lib-credential.sh b/t/lib-credential.sh\nindex 957ae93..3c43ff1 100755\n--- a/t/lib-credential.sh\n+++ b/t/lib-credential.sh\n@@ -18,6 +18,10 @@ check() {\n \t\tcat stderr &&\n \t\tfalse\n \tfi &&\n+\tif test_have_prereq MINGW\n+\tthen\n+\t\tdos2unix -q stderr\n+\tfi &&\n \ttest_cmp expect-stdout stdout &&\n \ttest_cmp expect-stderr stderr\n }\n-- \n1.7.11.msysgit.0.5.g0225efe.dirty\n\n-- \n*** Please reply-to-all at all times ***\n*** (do not pretend to know who is subscribed and who is not) ***\n*** Please avoid top-posting. ***\nThe msysGit Wiki is here: https://github.com/msysgit/msysgit/wiki - Github accounts are free.\n\nYou received this message because you are subscribed to the Google\nGroups \"msysGit\" group.\nTo post to this group, send email to msysgit@googlegroups.com\nTo unsubscribe from this group, send email to\nmsysgit+unsubscribe@googlegroups.com\nFor more options, and view previous threads, visit this group at\nhttp://groups.google.com/group/msysgit?hl=en_US?hl=en\n"},{"id":"195954","messageId":"CABPQNSZt0a+447qbr6j9ELHfsmfr03VUw6-efAiu0vLicaKyEg@mail.gmail.com","threadId":"31114","inReplyTo":"1343409006-5056-1-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v3] contrib: add win32 credential-helper","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2012-07-27T17:32:08Z","receivedAt":"2012-07-27T17:32:08Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Jul 27, 2012 at 7:10 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> Since the Windows port of Git expects binary pipes, we need to make\n> sure the helper-end also sets up binary pipes.\n>\n> Side-step CRLF-issue in test to make it pass.\n>\n> Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n> ---\n>\n> Sorry for the delay, but here's the third iteration of my credential\n> helper for Windows' credential API.\n>\n> The only change since v2 is that it now supports protocols without\n> a host component, as suggested by Jeff King.\n>\n\n...aaand just as I sent it out, I realized that my Makefile was a bit\non the light side. Imagine this patch on top for now, please :)\n\ndiff --git a/contrib/credential/wincred/Makefile\nb/contrib/credential/wincred/Makefile\nindex b4f098f..bad45ca 100644\n--- a/contrib/credential/wincred/Makefile\n+++ b/contrib/credential/wincred/Makefile\n@@ -4,5 +4,11 @@ CC = gcc\n RM = rm -f\n CFLAGS = -O2 -Wall\n\n+-include ../../../config.mak.autogen\n+-include ../../../config.mak\n+\n git-credential-wincred.exe : git-credential-wincred.c\n \t$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@\n+\n+clean:\n+\t$(RM) git-credential-wincred.exe\n\n-- \n*** Please reply-to-all at all times ***\n*** (do not pretend to know who is subscribed and who is not) ***\n*** Please avoid top-posting. ***\nThe msysGit Wiki is here: https://github.com/msysgit/msysgit/wiki - Github accounts are free.\n\nYou received this message because you are subscribed to the Google\nGroups \"msysGit\" group.\nTo post to this group, send email to msysgit@googlegroups.com\nTo unsubscribe from this group, send email to\nmsysgit+unsubscribe@googlegroups.com\nFor more options, and view previous threads, visit this group at\nhttp://groups.google.com/group/msysgit?hl=en_US?hl=en\n"},{"id":"197160","messageId":"7vtxw2w5s4.fsf@alter.siamese.dyndns.org","threadId":"31114","inReplyTo":"CABPQNSZt0a+447qbr6j9ELHfsmfr03VUw6-efAiu0vLicaKyEg@mail.gmail.com","subject":"Re: [PATCH v3] contrib: add win32 credential-helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-08-17T03:34:19Z","receivedAt":"2012-08-17T03:34:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n> On Fri, Jul 27, 2012 at 7:10 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>> Since the Windows port of Git expects binary pipes, we need to make\n>> sure the helper-end also sets up binary pipes.\n>>\n>> Side-step CRLF-issue in test to make it pass.\n>>\n>> Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n>> ---\n>>\n>> Sorry for the delay, but here's the third iteration of my credential\n>> helper for Windows' credential API.\n>>\n>> The only change since v2 is that it now supports protocols without\n>> a host component, as suggested by Jeff King.\n>>\n>\n> ...aaand just as I sent it out, I realized that my Makefile was a bit\n> on the light side. Imagine this patch on top for now, please :)\n>\n> diff --git a/contrib/credential/wincred/Makefile\n> b/contrib/credential/wincred/Makefile\n> index b4f098f..bad45ca 100644\n> --- a/contrib/credential/wincred/Makefile\n> +++ b/contrib/credential/wincred/Makefile\n> @@ -4,5 +4,11 @@ CC = gcc\n>  RM = rm -f\n>  CFLAGS = -O2 -Wall\n>\n> +-include ../../../config.mak.autogen\n> +-include ../../../config.mak\n> +\n>  git-credential-wincred.exe : git-credential-wincred.c\n>  \t$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@\n> +\n> +clean:\n> +\t$(RM) git-credential-wincred.exe\n\nI notice that I didn't queue either of these; are you still\npolishing them, or are they in good enough shape that it wouldn't\nmake things harder for you if I queue it, with a plan to merge it\nsoon after 1.7.12?\n"},{"id":"197178","messageId":"CABPQNSaBK=nyyW2bibTkQKFaihiyd8k_MHeUJRiBhA6tZ-XnFw@mail.gmail.com","threadId":"31114","inReplyTo":"7vtxw2w5s4.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3] contrib: add win32 credential-helper","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2012-08-17T11:50:43Z","receivedAt":"2012-08-17T11:50:43Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Aug 17, 2012 at 5:34 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>\n>> On Fri, Jul 27, 2012 at 7:10 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>>> Since the Windows port of Git expects binary pipes, we need to make\n>>> sure the helper-end also sets up binary pipes.\n>>>\n>>> Side-step CRLF-issue in test to make it pass.\n>>>\n>>> Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n>>> ---\n>>>\n>>> Sorry for the delay, but here's the third iteration of my credential\n>>> helper for Windows' credential API.\n>>>\n>>> The only change since v2 is that it now supports protocols without\n>>> a host component, as suggested by Jeff King.\n>>>\n>>\n>> ...aaand just as I sent it out, I realized that my Makefile was a bit\n>> on the light side. Imagine this patch on top for now, please :)\n>>\n>\n> I notice that I didn't queue either of these; are you still\n> polishing them, or are they in good enough shape that it wouldn't\n> make things harder for you if I queue it, with a plan to merge it\n> soon after 1.7.12?\n>\n\nAs far as I'm concerned, I consider this complete from my point of\nview. Should I send out a new version with the fixup squashed in?\n"},{"id":"197193","messageId":"7vwr0xv3l7.fsf@alter.siamese.dyndns.org","threadId":"31114","inReplyTo":"CABPQNSaBK=nyyW2bibTkQKFaihiyd8k_MHeUJRiBhA6tZ-XnFw@mail.gmail.com","subject":"Re: [PATCH v3] contrib: add win32 credential-helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-08-17T17:19:16Z","receivedAt":"2012-08-17T17:19:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n> As far as I'm concerned, I consider this complete from my point of\n> view. Should I send out a new version with the fixup squashed in?\n\nI've already queued them as one commit.  Thanks.\n"}]}