<pre style='margin:0'>
Herby Gillot (herbygillot) pushed a commit to branch master
in repository macports-ports.

</pre>
<p><a href="https://github.com/macports/macports-ports/commit/4182aebb5c3389a8588ae4e9ca920c65d7258385">https://github.com/macports/macports-ports/commit/4182aebb5c3389a8588ae4e9ca920c65d7258385</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new 4182aebb5c3 git-devel: update patch for < 10.7
</span>4182aebb5c3 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit 4182aebb5c3389a8588ae4e9ca920c65d7258385
</span>Author: Sergey Fedorov <barracuda@macos-powerpc.org>
AuthorDate: Sun Sep 15 16:55:29 2024 +0800

<span style='display:block; white-space:pre;color:#404040;'>    git-devel: update patch for < 10.7
</span>---
 devel/git/Portfile                                 |  24 +-
 ...atch-git-devel-Revert-breaking-osxkeychain.diff | 535 +++++++++++++++++++++
 2 files changed, 551 insertions(+), 8 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/git/Portfile b/devel/git/Portfile
</span><span style='display:block; white-space:pre;color:#808080;'>index 997b5310a55..3e0b260645c 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/devel/git/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/git/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -43,6 +43,8 @@ categories          devel
</span> license             GPL-2 LGPL-2.1+
 installs_libs       no
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+patch.pre_args-replace  -p0 -p1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> if {${name} eq ${subport}} {
     # RELEASE VERSION
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -71,6 +73,13 @@ if {${name} eq ${subport}} {
</span> 
     conflicts       git-devel
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    # Reverts breakage introduced by 51c15ac1b6ab15d8e29651d0bd364d8f62dc6509
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # and later commits.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # TODO: consider convising upstream to restore fallback code.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {${os.platform} eq "darwin" && ${os.major} < 11} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        patchfiles-append patch-Revert-breaking-osxkeychain.diff
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>     livecheck.type  regexm
     livecheck.regex {<span class="version">.*?(\d+\.\d+\.\d+).*?</span>}
 } else {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -88,6 +97,13 @@ if {${name} eq ${subport}} {
</span>     build.target    all man html
 
     conflicts       git
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # Reverts breakage introduced by 51c15ac1b6ab15d8e29651d0bd364d8f62dc6509
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # and later commits.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # TODO: consider convising upstream to restore fallback code.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {${os.platform} eq "darwin" && ${os.major} < 11} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        patchfiles-append patch-git-devel-Revert-breaking-osxkeychain.diff
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span> }
 
 perl5.require_variant   false
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -112,14 +128,6 @@ patchfiles-append   patch-Makefile.diff \
</span>                     patch-sha1dc-older-apple-gcc-versions.diff \
                     patch-gitk-git-gitk.diff
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-patch.pre_args-replace  -p0 -p1
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-# Reverts breakage introduced by:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-# https://github.com/git/git/commit/51c15ac1b6ab15d8e29651d0bd364d8f62dc6509
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-if {${os.platform} eq "darwin" && ${os.major} < 11} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    patchfiles-append patch-Revert-breaking-osxkeychain.diff
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span> # Git 2.36.0 implements a new FSEvent listener that uses
 # the API available in Yosemite and newer.
 if {${os.platform} eq "darwin" && ${os.major} < 14} {
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/git/files/patch-git-devel-Revert-breaking-osxkeychain.diff b/devel/git/files/patch-git-devel-Revert-breaking-osxkeychain.diff
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..1133d309b88
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/git/files/patch-git-devel-Revert-breaking-osxkeychain.diff
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,535 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From ac042352b4910134c4c4d74b68f30061bde145b1 Mon Sep 17 00:00:00 2001
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From: Sergey Fedorov <barracuda@macos-powerpc.org>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Date: Sun, 15 Sep 2024 15:44:12 +0800
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Subject: [PATCH] Revert breaking osxkeychain
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit e1ab45b2dab51f94db9548666dfd7af626d2aa7e.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit fcf5b74e59c1c0d18a8e8e939475007b3b5f83ad.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit d5b35bba86e6fdf0484ea71bf5b8ef1167f14015.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit e3cef40db89f5a7c91f4e9d6c4959ca1e41f4647.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit 9032bcad82f45a403e4a8de86e1fcb4bfd1ab282.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit 9abe31f5f161be4d69118bdfae00103cd6efa510.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit b201316835bbf2c49c2780f23cfd6146f6b8d1a2.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+---
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ contrib/credential/osxkeychain/Makefile       |   3 +-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ .../osxkeychain/git-credential-osxkeychain.c  | 390 +++---------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 2 files changed, 69 insertions(+), 324 deletions(-)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git a/contrib/credential/osxkeychain/Makefile b/contrib/credential/osxkeychain/Makefile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 238f5f8c36..4b3a08a2ba 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- a/contrib/credential/osxkeychain/Makefile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ b/contrib/credential/osxkeychain/Makefile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -8,8 +8,7 @@ CFLAGS = -g -O2 -Wall
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ -include ../../../config.mak
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ git-credential-osxkeychain: git-credential-osxkeychain.o
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          -framework Security -framework CoreFoundation
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -Wl,-framework -Wl,Security
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ git-credential-osxkeychain.o: git-credential-osxkeychain.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   $(CC) -c $(CFLAGS) $<
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 1c8310d7fe..5f2e5f16c8 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3,52 +3,14 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <stdlib.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <Security/Security.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#define ENCODING kCFStringEncodingUTF8
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFStringRef protocol; /* Stores constant strings - not memory managed */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFStringRef host;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFNumberRef port;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFStringRef path;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFStringRef username;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFDataRef password;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFDataRef password_expiry_utc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFDataRef oauth_refresh_token;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static int state_seen;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static void clear_credential(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (host) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFRelease(host);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          host = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (port) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFRelease(port);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          port = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFRelease(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          path = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (username) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFRelease(username);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          username = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (password) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFRelease(password);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          password = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (password_expiry_utc) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFRelease(password_expiry_utc);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          password_expiry_utc = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (oauth_refresh_token) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFRelease(oauth_refresh_token);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          oauth_refresh_token = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#define STRING_WITH_LENGTH(s) s, sizeof(s) - 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-__attribute__((format (printf, 1, 2), __noreturn__))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static SecProtocolType protocol;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static char *host;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static char *path;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static char *username;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static char *password;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static UInt16 port;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++__attribute__((format (printf, 1, 2)))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static void die(const char *err, ...)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   char msg[4096];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -57,202 +19,70 @@ static void die(const char *err, ...)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   vsnprintf(msg, sizeof(msg), err, params);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   fprintf(stderr, "%s\n", msg);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   va_end(params);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  clear_credential();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   exit(1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static void *xmalloc(size_t len)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void *xstrdup(const char *s1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  void *ret = malloc(len);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  void *ret = strdup(s1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if (!ret)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           die("Out of memory");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFDictionaryRef create_dictionary(CFAllocatorRef allocator, ...)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  va_list args;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  const void *key;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFMutableDictionaryRef result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  result = CFDictionaryCreateMutable(allocator,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                     0,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                     &kCFTypeDictionaryKeyCallBacks,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                     &kCFTypeDictionaryValueCallBacks);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  va_start(args, allocator);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  while ((key = va_arg(args, const void *)) != NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          const void *value;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          value = va_arg(args, const void *);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          if (value)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  CFDictionarySetValue(result, key, value);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  va_end(args);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#define CREATE_SEC_ATTRIBUTES(...) \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  create_dictionary(kCFAllocatorDefault, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                    kSecClass, kSecClassInternetPassword, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                    kSecAttrServer, host, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                    kSecAttrAccount, username, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                    kSecAttrPath, path, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                    kSecAttrPort, port, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                    kSecAttrProtocol, protocol, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                    kSecAttrAuthenticationType, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                    kSecAttrAuthenticationTypeDefault, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                    __VA_ARGS__);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static void write_item(const char *what, const char *buf, size_t len)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#define KEYCHAIN_ITEM(x) (x ? strlen(x) : 0), x
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#define KEYCHAIN_ARGS \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  NULL, /* default keychain */ \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  KEYCHAIN_ITEM(host), \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  0, NULL, /* account domain */ \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  KEYCHAIN_ITEM(username), \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  KEYCHAIN_ITEM(path), \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  port, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  protocol, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  kSecAuthenticationTypeDefault
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void write_item(const char *what, const char *buf, int len)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   printf("%s=", what);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   fwrite(buf, 1, len, stdout);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   putchar('\n');
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static void find_username_in_item(CFDictionaryRef item)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void find_username_in_item(SecKeychainItemRef item)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFStringRef account_ref;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  char *username_buf;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFIndex buffer_len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  SecKeychainAttributeList list;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  SecKeychainAttribute attr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  account_ref = CFDictionaryGetValue(item, kSecAttrAccount);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (!account_ref)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          write_item("username", "", 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  list.count = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  list.attr = &attr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  attr.tag = kSecAccountItemAttr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  username_buf = (char *)CFStringGetCStringPtr(account_ref, ENCODING);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (username_buf)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          write_item("username", username_buf, strlen(username_buf));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  if (SecKeychainItemCopyContent(item, NULL, &list, NULL, NULL))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  /* If we can't get a CString pointer then
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-   * we need to allocate our own buffer */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  buffer_len = CFStringGetMaximumSizeForEncoding(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  CFStringGetLength(account_ref), ENCODING) + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  username_buf = xmalloc(buffer_len);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (CFStringGetCString(account_ref,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          username_buf,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          buffer_len,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          ENCODING)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          write_item("username", username_buf, strlen(username_buf));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  free(username_buf);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  write_item("username", attr.data, attr.length);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  SecKeychainItemFreeContent(&list, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static OSStatus find_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void find_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFDictionaryRef attrs;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFDictionaryRef item;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFDataRef data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  OSStatus result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  void *buf;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  UInt32 len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  SecKeychainItemRef item;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  attrs = CREATE_SEC_ATTRIBUTES(kSecMatchLimit, kSecMatchLimitOne,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                kSecReturnAttributes, kCFBooleanTrue,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                kSecReturnData, kCFBooleanTrue,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  result = SecItemCopyMatching(attrs, (CFTypeRef *)&item);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (result) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          goto out;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  data = CFDictionaryGetValue(item, kSecValueData);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  if (SecKeychainFindInternetPassword(KEYCHAIN_ARGS, &len, &buf, &item))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  write_item("password",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-             (const char *)CFDataGetBytePtr(data),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-             CFDataGetLength(data));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  write_item("password", buf, len);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if (!username)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           find_username_in_item(item);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFRelease(item);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  write_item("capability[]", "state", strlen("state"));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  write_item("state[]", "osxkeychain:seen=1", strlen("osxkeychain:seen=1"));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-out:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFRelease(attrs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  /* We consider not found to not be an error */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (result == errSecItemNotFound)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          result = errSecSuccess;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static OSStatus delete_ref(const void *itemRef)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFArrayRef item_ref_list;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFDictionaryRef delete_query;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  OSStatus result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  item_ref_list = CFArrayCreate(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                &itemRef,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                1,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                &kCFTypeArrayCallBacks);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  delete_query = create_dictionary(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                   kSecClass, kSecClassInternetPassword,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                   kSecMatchItemList, item_ref_list,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                   NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (password) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          /* We only want to delete items with a matching password */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFIndex capacity;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFMutableDictionaryRef query;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFDataRef data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          capacity = CFDictionaryGetCount(delete_query) + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          query = CFDictionaryCreateMutableCopy(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                capacity,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                delete_query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          result = SecItemCopyMatching(query, (CFTypeRef *)&data);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          if (!result) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  CFDataRef kc_password;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  const UInt8 *raw_data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  const UInt8 *line;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  /* Don't match appended metadata */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  raw_data = CFDataGetBytePtr(data);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  line = memchr(raw_data, '\n', CFDataGetLength(data));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  if (line)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          kc_password = CFDataCreateWithBytesNoCopy(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                          kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                          raw_data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                          line - raw_data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                          kCFAllocatorNull);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          kc_password = data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  if (CFEqual(kc_password, password))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          result = SecItemDelete(delete_query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  if (line)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          CFRelease(kc_password);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  CFRelease(data);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFRelease(query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          result = SecItemDelete(delete_query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFRelease(delete_query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFRelease(item_ref_list);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  SecKeychainItemFreeContent(NULL, buf);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static OSStatus delete_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void delete_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFDictionaryRef attrs;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFArrayRef refs;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  OSStatus result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  SecKeychainItemRef item;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    * Require at least a protocol and host for removal, which is what git
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -260,72 +90,25 @@ static OSStatus delete_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    * Keychain manager.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if (!protocol || !host)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  attrs = CREATE_SEC_ATTRIBUTES(kSecMatchLimit, kSecMatchLimitAll,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                kSecReturnRef, kCFBooleanTrue,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  result = SecItemCopyMatching(attrs, (CFTypeRef *)&refs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFRelease(attrs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (!result) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          for (CFIndex i = 0; !result && i < CFArrayGetCount(refs); i++)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  result = delete_ref(CFArrayGetValueAtIndex(refs, i));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFRelease(refs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  /* We consider not found to not be an error */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (result == errSecItemNotFound)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          result = errSecSuccess;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  if (SecKeychainFindInternetPassword(KEYCHAIN_ARGS, 0, NULL, &item))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  SecKeychainItemDelete(item);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static OSStatus add_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void add_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFMutableDataRef data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFDictionaryRef attrs;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  OSStatus result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (state_seen)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          return errSecSuccess;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   /* Only store complete credentials */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if (!protocol || !host || !username || !password)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  data = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, password);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (password_expiry_utc) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFDataAppendBytes(data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-              (const UInt8 *)STRING_WITH_LENGTH("\npassword_expiry_utc="));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFDataAppendBytes(data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                            CFDataGetBytePtr(password_expiry_utc),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                            CFDataGetLength(password_expiry_utc));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (oauth_refresh_token) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFDataAppendBytes(data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-              (const UInt8 *)STRING_WITH_LENGTH("\noauth_refresh_token="));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFDataAppendBytes(data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                            CFDataGetBytePtr(oauth_refresh_token),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                            CFDataGetLength(oauth_refresh_token));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  attrs = CREATE_SEC_ATTRIBUTES(kSecValueData, data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  result = SecItemAdd(attrs, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (result == errSecDuplicateItem) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFDictionaryRef query;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          query = CREATE_SEC_ATTRIBUTES(NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          result = SecItemUpdate(query, attrs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          CFRelease(query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFRelease(data);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  CFRelease(attrs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  if (SecKeychainAddInternetPassword(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        KEYCHAIN_ARGS,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        KEYCHAIN_ITEM(password),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        NULL))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static void read_credential(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -348,64 +131,36 @@ static void read_credential(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           if (!strcmp(buf, "protocol")) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   if (!strcmp(v, "imap"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          protocol = kSecAttrProtocolIMAP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                          protocol = kSecProtocolTypeIMAP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   else if (!strcmp(v, "imaps"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          protocol = kSecAttrProtocolIMAPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                          protocol = kSecProtocolTypeIMAPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   else if (!strcmp(v, "ftp"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          protocol = kSecAttrProtocolFTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                          protocol = kSecProtocolTypeFTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   else if (!strcmp(v, "ftps"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          protocol = kSecAttrProtocolFTPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                          protocol = kSecProtocolTypeFTPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   else if (!strcmp(v, "https"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          protocol = kSecAttrProtocolHTTPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                          protocol = kSecProtocolTypeHTTPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   else if (!strcmp(v, "http"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          protocol = kSecAttrProtocolHTTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                          protocol = kSecProtocolTypeHTTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   else if (!strcmp(v, "smtp"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          protocol = kSecAttrProtocolSMTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          /* we don't yet handle other protocols */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          clear_credential();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                          protocol = kSecProtocolTypeSMTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                  else /* we don't yet handle other protocols */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           exit(0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           else if (!strcmp(buf, "host")) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   char *colon = strchr(v, ':');
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   if (colon) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          UInt16 port_i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           *colon++ = '\0';
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          port_i = atoi(colon);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          port = CFNumberCreate(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                kCFNumberShortType,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                &port_i);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                          port = atoi(colon);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  host = CFStringCreateWithCString(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                   v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                   ENCODING);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                  host = xstrdup(v);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           else if (!strcmp(buf, "path"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  path = CFStringCreateWithCString(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                   v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                   ENCODING);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                  path = xstrdup(v);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           else if (!strcmp(buf, "username"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  username = CFStringCreateWithCString(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                  kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                  v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                  ENCODING);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                  username = xstrdup(v);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           else if (!strcmp(buf, "password"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  password = CFDataCreate(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                          (UInt8 *)v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                          strlen(v));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          else if (!strcmp(buf, "password_expiry_utc"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  password_expiry_utc = CFDataCreate(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                     (UInt8 *)v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                     strlen(v));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          else if (!strcmp(buf, "oauth_refresh_token"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  oauth_refresh_token = CFDataCreate(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                     (UInt8 *)v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                                                     strlen(v));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          else if (!strcmp(buf, "state[]")) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                  if (!strcmp(v, "osxkeychain:seen=1"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-                          state_seen = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                  password = xstrdup(v);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            * Ignore other lines; we don't know what they mean, but
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            * this future-proofs us when later versions of git do
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -418,30 +173,21 @@ static void read_credential(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int main(int argc, const char **argv)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  OSStatus result = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   const char *usage =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           "usage: git credential-osxkeychain <get|store|erase>";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if (!argv[1])
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           die("%s", usage);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (open(argv[0], O_RDONLY | O_EXLOCK) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          die("failed to lock %s", argv[0]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   read_credential();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if (!strcmp(argv[1], "get"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          result = find_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          find_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   else if (!strcmp(argv[1], "store"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          result = add_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          add_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   else if (!strcmp(argv[1], "erase"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          result = delete_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          delete_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   /* otherwise, ignore unknown action */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (result)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          die("failed to %s: %d", argv[1], (int)result);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  clear_credential();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span></pre><pre style='margin:0'>

</pre>