osxkeychain: state to skip unnecessary store operations

git passes a credential that has been used successfully to the helpers to record. If a credential is already stored, "git-credential-osxkeychain store" just records the credential returned by "git-credential-osxkeychain get", and unnecessary (sometimes problematic) SecItemAdd() and/or SecItemUpdate() are performed. We can skip such unnecessary operations by marking a credential returned by "git-credential-osxkeychain get". This marking can be done by utilizing the "state[]" feature: - The "get" command sets the field "state[]=osxkeychain:seen=1". - The "store" command skips its actual operation if the field "state[]=osxkeychain:seen=1" exists. Introduce a new state "state[]=osxkeychain:seen=1". Suggested-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Koji Nakamaru <koji.nakamaru@gree.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Koji Nakamaru committed May 15, 2024 at 19:21 UTC e1ab45b2dab51f94db9548666dfd7af626d2aa7e
1 file changed +11
contrib/credential/osxkeychain/git-credential-osxkeychain.c
+11
@@ -12,6 +12,7 @@ static CFStringRef username;
12 static CFDataRef password;
13 static CFDataRef password_expiry_utc;
14 static CFDataRef oauth_refresh_token;
15 +static int state_seen;
16
17 static void clear_credential(void)
18 {
@@ -171,6 +172,9 @@ static OSStatus find_internet_password(void)
172
173 CFRelease(item);
174
175 + write_item("capability[]", "state", strlen("state"));
176 + write_item("state[]", "osxkeychain:seen=1", strlen("osxkeychain:seen=1"));
177 +
178 out:
179 CFRelease(attrs);
180
@@ -284,6 +288,9 @@ static OSStatus add_internet_password(void)
288 CFDictionaryRef attrs;
289 OSStatus result;
290
291 + if (state_seen)
292 + return errSecSuccess;
293 +
294 /* Only store complete credentials */
295 if (!protocol || !host || !username || !password)
296 return -1;
@@ -395,6 +402,10 @@ static void read_credential(void)
402 oauth_refresh_token = CFDataCreate(kCFAllocatorDefault,
403 (UInt8 *)v,
404 strlen(v));
405 + else if (!strcmp(buf, "state[]")) {
406 + if (!strcmp(v, "osxkeychain:seen=1"))
407 + state_seen = 1;
408 + }
409 /*
410 * Ignore other lines; we don't know what they mean, but
411 * this future-proofs us when later versions of git do