From c9d19c4580c1d88f8f0f14484194abaceeef8869 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 10 Sep 2013 22:10:38 +0200 Subject: [PATCH 01/23] Add a GTCred wrapper. --- Classes/GTCred+Private.h | 29 +++++ Classes/GTCred.h | 50 +++++++++ Classes/GTCred.m | 103 ++++++++++++++++++ .../project.pbxproj | 12 ++ 4 files changed, 194 insertions(+) create mode 100644 Classes/GTCred+Private.h create mode 100644 Classes/GTCred.h create mode 100644 Classes/GTCred.m diff --git a/Classes/GTCred+Private.h b/Classes/GTCred+Private.h new file mode 100644 index 000000000..113dde0a9 --- /dev/null +++ b/Classes/GTCred+Private.h @@ -0,0 +1,29 @@ +// +// GTCred+Private.h +// ObjectiveGitFramework +// +// Created by Etienne on 10/09/13. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "GTCred.h" + +// If you need to authenticate an operation in libgit2, you'll have to +// have a `GTCredBlock` handy, like a parameter in the method you're writing, +// setup a GTCredAcquireCallbackInfo struct on the stack, and pass both as the +// arguments to the operation you're attempting. +// +// Example: ``` +// struct GTCredAcquireCallbackInfo info = { .credBlock = ... } +// git_remote_set_cred_acquire_cb(&git_remote, GTCredAcquireCallback, &payload); +// ``` +// +// `GTCredAcquireCallback` will act as a trampoline, and will ask the user code +// for a `GTCred` object. It is the user's responsibility to check the auth type +// and initialize its `GTCred` object correctly. + +typedef struct { + __unsafe_unretained GTCredBlock credBlock; +} GTCredAcquireCallbackInfo; + +int GTCredAcquireCallback(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload); diff --git a/Classes/GTCred.h b/Classes/GTCred.h new file mode 100644 index 000000000..3c77e4c3a --- /dev/null +++ b/Classes/GTCred.h @@ -0,0 +1,50 @@ +// +// GTCred.h +// ObjectiveGitFramework +// +// Created by Etienne on 10/09/13. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "git2.h" + +// An enum describing the data needed for authentication. +// See `git_credtype_t`. +typedef enum { + GTCredentialTypeUserPassPlaintext = GIT_CREDTYPE_USERPASS_PLAINTEXT, + GTCredentialTypeSSHKeyFilePassPhrase = GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE, + GTCredentialTypeSSHPublicKey = GIT_CREDTYPE_SSH_PUBLICKEY, +} GTCredentialType; + +@class GTCred; +// A typedef block for the various methods that require authentication +typedef GTCred *(^GTCredBlock)(GTCredentialType allowedTypes, NSString *URL, NSString *username); + +@interface GTCred : NSObject + +// Create a credential object from a username/password pair. +// +// userName - The username to authenticate as. +// password - The password belonging to that user. +// +// Return a new GTCred instance, or nil if an error occurred ++ (instancetype)credentialWithUserName:(NSString *)userName password:(NSString *)password error:(NSError **)error; + +// Create a credential object from a SSH keyfile +// +// userName - The username to authenticate as. +// publicKey - The public key for that user. +// privateKey - The private key for that user. +// passPhrase - The passPhrase for the private key. Optional if the private key has no password. +// +// Return a new GTCred instance, or nil if an error occurred ++ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSString *)publicKey privateKey:(NSString *)privateKey passPhrase:(NSString *)passPhrase error:(NSError **)error; + +// PARTIALIMPL ++ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSString *)publicKey signBlock:(void (^)(void))signBlock error:(NSError **)error; + +- (git_cred *)git_cred __attribute__((objc_returns_inner_pointer)); + +@property (readonly) BOOL hasUserName; + +@end diff --git a/Classes/GTCred.m b/Classes/GTCred.m new file mode 100644 index 000000000..dfe255513 --- /dev/null +++ b/Classes/GTCred.m @@ -0,0 +1,103 @@ +// +// GTCred.m +// ObjectiveGitFramework +// +// Created by Etienne on 10/09/13. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import +#import "GTCred.h" +#import "GTCred+Private.h" + +@interface GTCred () +@property (nonatomic, assign, readonly) git_cred *git_cred; +@end + +@implementation GTCred + ++ (instancetype)credentialWithUserName:(NSString *)userName password:(NSString *)password error:(NSError **)error { + git_cred *cred; + int gitError = git_cred_userpass_plaintext_new(&cred, userName.UTF8String, password.UTF8String); + if (gitError != GIT_OK) { + if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@.", userName]; + return nil; + } + + return [[self alloc] initWithGitCred:cred]; +} + ++ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSString *)publicKey privateKey:(NSString *)privateKey passPhrase:(NSString *)passPhrase error:(NSError **)error { + NSParameterAssert(privateKey != nil); + + git_cred *cred; + int gitError = git_cred_ssh_keyfile_passphrase_new(&cred, userName.UTF8String, publicKey.UTF8String, privateKey.UTF8String, passPhrase.UTF8String); + if (gitError != GIT_OK) { + if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@ with the provided public/private key pair.", userName]; + return nil; + } + + return [[self alloc] initWithGitCred:cred]; +} + ++ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSString *)publicKey signBlock:(void (^)(void))signBlock error:(NSError **)error { + /* prototype for second-to-last argument in `git_cred_ssh_publickey_new` : + * + * int git_cred_sign_callback(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, \ + const unsigned char *data, size_t data_len, void **abstract); + * + * LIBSSH2_SESSION ? Eek... + */ + + git_cred *cred; + int gitError = git_cred_ssh_publickey_new(&cred, userName.UTF8String, publicKey.UTF8String, [publicKey lengthOfBytesUsingEncoding:NSUTF8StringEncoding], NULL, NULL); + if (gitError != GIT_OK) { + if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@ with the provided public/private key pair.", userName]; + return nil; + } + + return [[self alloc] initWithGitCred:cred]; +} + +- (instancetype)initWithGitCred:(git_cred *)cred { + NSParameterAssert(cred != nil); + self = [self init]; + + if (!self) return nil; + + _git_cred = cred; + + return self; +} + +- (BOOL)hasUserName { + return git_cred_has_username(self.git_cred) == 1; +} + +@end + +int GTCredAcquireCallback(git_cred **git_cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload) { + NSCParameterAssert(git_cred != NULL); + NSCParameterAssert(payload != NULL); + + GTCredAcquireCallbackInfo *info = payload; + + if (info->credBlock == nil) { + NSString *errorMsg = [NSString stringWithFormat:@"No credentials provided, but authentication was requested."]; + giterr_set_str(GIT_EUSER, errorMsg.UTF8String); + return GIT_ERROR; + } + + NSString *URL = (url != NULL ? @(url) : nil); + NSString *userName = (username_from_url != NULL ? @(username_from_url) : nil); + + GTCred *cred = info->credBlock((GTCredentialType)allowed_types, URL, userName); + if (!cred) { + NSString *errorMsg = [NSString stringWithFormat:@"No credentials provided, but authentication was requested."]; + giterr_set_str(GIT_EUSER, errorMsg.UTF8String); + return GIT_ERROR; + } + + *git_cred = cred.git_cred; + return GIT_OK; +} diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index 38f3a23ec..ec06613b7 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -102,6 +102,9 @@ 30FDC08216835A8100654BF0 /* GTDiffLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 30FDC07E16835A8100654BF0 /* GTDiffLine.m */; }; 3E0A23E5159E0FDB00A6068F /* GTObjectDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 55C8054C13861F34004DCB0F /* GTObjectDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4D26799F178DAF31002A2795 /* GTTreeEntry+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D26799D178DAF31002A2795 /* GTTreeEntry+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4D79C0EE17DF9F4D00997DE4 /* GTCred.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D79C0EC17DF9F4D00997DE4 /* GTCred.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4D79C0EF17DF9F4D00997DE4 /* GTCred.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79C0ED17DF9F4D00997DE4 /* GTCred.m */; }; + 4D79C0F717DFAA7100997DE4 /* GTCred+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D79C0F617DFAA7100997DE4 /* GTCred+Private.h */; }; 4DE864351794A37E00371A65 /* GTRepository+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE864341794A37E00371A65 /* GTRepository+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4DE864361794A37E00371A65 /* GTRepository+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE864341794A37E00371A65 /* GTRepository+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 55C8054F13861FE7004DCB0F /* GTObjectDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C8054D13861F34004DCB0F /* GTObjectDatabase.m */; }; @@ -358,6 +361,9 @@ 30FDC07E16835A8100654BF0 /* GTDiffLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTDiffLine.m; sourceTree = ""; }; 32DBCF5E0370ADEE00C91783 /* ObjectiveGitFramework_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectiveGitFramework_Prefix.pch; sourceTree = ""; }; 4D26799D178DAF31002A2795 /* GTTreeEntry+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTTreeEntry+Private.h"; sourceTree = ""; }; + 4D79C0EC17DF9F4D00997DE4 /* GTCred.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTCred.h; sourceTree = ""; }; + 4D79C0ED17DF9F4D00997DE4 /* GTCred.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCred.m; sourceTree = ""; }; + 4D79C0F617DFAA7100997DE4 /* GTCred+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTCred+Private.h"; sourceTree = ""; }; 4DE864341794A37E00371A65 /* GTRepository+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTRepository+Private.h"; sourceTree = ""; }; 55C8054C13861F34004DCB0F /* GTObjectDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTObjectDatabase.h; sourceTree = ""; }; 55C8054D13861F34004DCB0F /* GTObjectDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTObjectDatabase.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; @@ -745,6 +751,9 @@ 8821547C17147B3600D76B76 /* GTOID.m */, D09C2E341755F16200065E36 /* GTSubmodule.h */, D09C2E351755F16200065E36 /* GTSubmodule.m */, + 4D79C0EC17DF9F4D00997DE4 /* GTCred.h */, + 4D79C0ED17DF9F4D00997DE4 /* GTCred.m */, + 4D79C0F617DFAA7100997DE4 /* GTCred+Private.h */, ); path = Classes; sourceTree = ""; @@ -919,6 +928,8 @@ D09C2E361755F16200065E36 /* GTSubmodule.h in Headers */, 4D26799F178DAF31002A2795 /* GTTreeEntry+Private.h in Headers */, 4DE864351794A37E00371A65 /* GTRepository+Private.h in Headers */, + 4D79C0EE17DF9F4D00997DE4 /* GTCred.h in Headers */, + 4D79C0F717DFAA7100997DE4 /* GTCred+Private.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1273,6 +1284,7 @@ 8821547F17147B3600D76B76 /* GTOID.m in Sources */, 5BE6128A1745EE3400266D8C /* GTTreeBuilder.m in Sources */, D09C2E381755F16200065E36 /* GTSubmodule.m in Sources */, + 4D79C0EF17DF9F4D00997DE4 /* GTCred.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 7d585228cbe49a0d6493b2cc337bcfecf3bcc283 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 15 Sep 2013 12:14:30 +0200 Subject: [PATCH 02/23] Rename `GTCred` => `GTCredential`. --- Classes/GTCred+Private.h | 29 ------------------- Classes/GTCredential+Private.h | 29 +++++++++++++++++++ Classes/{GTCred.h => GTCredential.h} | 8 ++--- Classes/{GTCred.m => GTCredential.m} | 16 +++++----- .../project.pbxproj | 24 +++++++-------- 5 files changed, 53 insertions(+), 53 deletions(-) delete mode 100644 Classes/GTCred+Private.h create mode 100644 Classes/GTCredential+Private.h rename Classes/{GTCred.h => GTCredential.h} (90%) rename Classes/{GTCred.m => GTCredential.m} (89%) diff --git a/Classes/GTCred+Private.h b/Classes/GTCred+Private.h deleted file mode 100644 index 113dde0a9..000000000 --- a/Classes/GTCred+Private.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// GTCred+Private.h -// ObjectiveGitFramework -// -// Created by Etienne on 10/09/13. -// Copyright (c) 2013 GitHub, Inc. All rights reserved. -// - -#import "GTCred.h" - -// If you need to authenticate an operation in libgit2, you'll have to -// have a `GTCredBlock` handy, like a parameter in the method you're writing, -// setup a GTCredAcquireCallbackInfo struct on the stack, and pass both as the -// arguments to the operation you're attempting. -// -// Example: ``` -// struct GTCredAcquireCallbackInfo info = { .credBlock = ... } -// git_remote_set_cred_acquire_cb(&git_remote, GTCredAcquireCallback, &payload); -// ``` -// -// `GTCredAcquireCallback` will act as a trampoline, and will ask the user code -// for a `GTCred` object. It is the user's responsibility to check the auth type -// and initialize its `GTCred` object correctly. - -typedef struct { - __unsafe_unretained GTCredBlock credBlock; -} GTCredAcquireCallbackInfo; - -int GTCredAcquireCallback(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload); diff --git a/Classes/GTCredential+Private.h b/Classes/GTCredential+Private.h new file mode 100644 index 000000000..0b51d042a --- /dev/null +++ b/Classes/GTCredential+Private.h @@ -0,0 +1,29 @@ +// +// GTCredential+Private.h +// ObjectiveGitFramework +// +// Created by Etienne on 10/09/13. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "GTCredential.h" + +// If you need to authenticate an operation in libgit2, you'll have to +// have a `GTCredentialBlock` handy, like a parameter in the method you're writing, +// setup a GTCredentialAcquireCallbackInfo struct on the stack, and pass both as the +// arguments to the operation you're attempting. +// +// Example: ``` +// struct GTCredentialAcquireCallbackInfo info = { .credBlock = ... } +// git_remote_set_cred_acquire_cb(&git_remote, GTCredentialAcquireCallback, &payload); +// ``` +// +// `GTCredentialAcquireCallback` will act as a trampoline, and will ask the user code +// for a `GTCredential` object. It is the user's responsibility to check the auth type +// and initialize its `GTCredential` object correctly. + +typedef struct { + __unsafe_unretained GTCredentialBlock credBlock; +} GTCredentialAcquireCallbackInfo; + +int GTCredentialAcquireCallback(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload); diff --git a/Classes/GTCred.h b/Classes/GTCredential.h similarity index 90% rename from Classes/GTCred.h rename to Classes/GTCredential.h index 3c77e4c3a..4cc639b9f 100644 --- a/Classes/GTCred.h +++ b/Classes/GTCredential.h @@ -1,5 +1,5 @@ // -// GTCred.h +// GTCredential.h // ObjectiveGitFramework // // Created by Etienne on 10/09/13. @@ -16,11 +16,11 @@ typedef enum { GTCredentialTypeSSHPublicKey = GIT_CREDTYPE_SSH_PUBLICKEY, } GTCredentialType; -@class GTCred; +@class GTCredential; // A typedef block for the various methods that require authentication -typedef GTCred *(^GTCredBlock)(GTCredentialType allowedTypes, NSString *URL, NSString *username); +typedef GTCredential *(^GTCredentialBlock)(GTCredentialType allowedTypes, NSString *URL, NSString *username); -@interface GTCred : NSObject +@interface GTCredential : NSObject // Create a credential object from a username/password pair. // diff --git a/Classes/GTCred.m b/Classes/GTCredential.m similarity index 89% rename from Classes/GTCred.m rename to Classes/GTCredential.m index dfe255513..85b6e38f5 100644 --- a/Classes/GTCred.m +++ b/Classes/GTCredential.m @@ -1,5 +1,5 @@ // -// GTCred.m +// GTCredential.m // ObjectiveGitFramework // // Created by Etienne on 10/09/13. @@ -7,14 +7,14 @@ // #import -#import "GTCred.h" -#import "GTCred+Private.h" +#import "GTCredential.h" +#import "GTCredential+Private.h" -@interface GTCred () +@interface GTCredential () @property (nonatomic, assign, readonly) git_cred *git_cred; @end -@implementation GTCred +@implementation GTCredential + (instancetype)credentialWithUserName:(NSString *)userName password:(NSString *)password error:(NSError **)error { git_cred *cred; @@ -76,11 +76,11 @@ - (BOOL)hasUserName { @end -int GTCredAcquireCallback(git_cred **git_cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload) { +int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload) { NSCParameterAssert(git_cred != NULL); NSCParameterAssert(payload != NULL); - GTCredAcquireCallbackInfo *info = payload; + GTCredentialAcquireCallbackInfo *info = payload; if (info->credBlock == nil) { NSString *errorMsg = [NSString stringWithFormat:@"No credentials provided, but authentication was requested."]; @@ -91,7 +91,7 @@ int GTCredAcquireCallback(git_cred **git_cred, const char *url, const char *user NSString *URL = (url != NULL ? @(url) : nil); NSString *userName = (username_from_url != NULL ? @(username_from_url) : nil); - GTCred *cred = info->credBlock((GTCredentialType)allowed_types, URL, userName); + GTCredential *cred = info->credBlock((GTCredentialType)allowed_types, URL, userName); if (!cred) { NSString *errorMsg = [NSString stringWithFormat:@"No credentials provided, but authentication was requested."]; giterr_set_str(GIT_EUSER, errorMsg.UTF8String); diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index a8cce2953..8de028f27 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -116,9 +116,9 @@ 30FDC08216835A8100654BF0 /* GTDiffLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 30FDC07E16835A8100654BF0 /* GTDiffLine.m */; }; 3E0A23E5159E0FDB00A6068F /* GTObjectDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 55C8054C13861F34004DCB0F /* GTObjectDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4D26799F178DAF31002A2795 /* GTTreeEntry+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D26799D178DAF31002A2795 /* GTTreeEntry+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4D79C0EE17DF9F4D00997DE4 /* GTCred.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D79C0EC17DF9F4D00997DE4 /* GTCred.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4D79C0EF17DF9F4D00997DE4 /* GTCred.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79C0ED17DF9F4D00997DE4 /* GTCred.m */; }; - 4D79C0F717DFAA7100997DE4 /* GTCred+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D79C0F617DFAA7100997DE4 /* GTCred+Private.h */; }; + 4D79C0EE17DF9F4D00997DE4 /* GTCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D79C0EC17DF9F4D00997DE4 /* GTCredential.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4D79C0EF17DF9F4D00997DE4 /* GTCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79C0ED17DF9F4D00997DE4 /* GTCredential.m */; }; + 4D79C0F717DFAA7100997DE4 /* GTCredential+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D79C0F617DFAA7100997DE4 /* GTCredential+Private.h */; }; 4DE864351794A37E00371A65 /* GTRepository+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE864341794A37E00371A65 /* GTRepository+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4DE864361794A37E00371A65 /* GTRepository+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE864341794A37E00371A65 /* GTRepository+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 55C8054F13861FE7004DCB0F /* GTObjectDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C8054D13861F34004DCB0F /* GTObjectDatabase.m */; }; @@ -390,9 +390,9 @@ 30FDC07E16835A8100654BF0 /* GTDiffLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTDiffLine.m; sourceTree = ""; }; 32DBCF5E0370ADEE00C91783 /* ObjectiveGitFramework_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectiveGitFramework_Prefix.pch; sourceTree = ""; }; 4D26799D178DAF31002A2795 /* GTTreeEntry+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTTreeEntry+Private.h"; sourceTree = ""; }; - 4D79C0EC17DF9F4D00997DE4 /* GTCred.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTCred.h; sourceTree = ""; }; - 4D79C0ED17DF9F4D00997DE4 /* GTCred.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCred.m; sourceTree = ""; }; - 4D79C0F617DFAA7100997DE4 /* GTCred+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTCred+Private.h"; sourceTree = ""; }; + 4D79C0EC17DF9F4D00997DE4 /* GTCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTCredential.h; sourceTree = ""; }; + 4D79C0ED17DF9F4D00997DE4 /* GTCredential.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCredential.m; sourceTree = ""; }; + 4D79C0F617DFAA7100997DE4 /* GTCredential+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTCredential+Private.h"; sourceTree = ""; }; 4DE864341794A37E00371A65 /* GTRepository+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTRepository+Private.h"; sourceTree = ""; }; 55C8054C13861F34004DCB0F /* GTObjectDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTObjectDatabase.h; sourceTree = ""; }; 55C8054D13861F34004DCB0F /* GTObjectDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTObjectDatabase.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; @@ -783,9 +783,9 @@ 8821547C17147B3600D76B76 /* GTOID.m */, D09C2E341755F16200065E36 /* GTSubmodule.h */, D09C2E351755F16200065E36 /* GTSubmodule.m */, - 4D79C0EC17DF9F4D00997DE4 /* GTCred.h */, - 4D79C0ED17DF9F4D00997DE4 /* GTCred.m */, - 4D79C0F617DFAA7100997DE4 /* GTCred+Private.h */, + 4D79C0EC17DF9F4D00997DE4 /* GTCredential.h */, + 4D79C0ED17DF9F4D00997DE4 /* GTCredential.m */, + 4D79C0F617DFAA7100997DE4 /* GTCredential+Private.h */, ); path = Classes; sourceTree = ""; @@ -962,8 +962,8 @@ D09C2E361755F16200065E36 /* GTSubmodule.h in Headers */, 4D26799F178DAF31002A2795 /* GTTreeEntry+Private.h in Headers */, 4DE864351794A37E00371A65 /* GTRepository+Private.h in Headers */, - 4D79C0EE17DF9F4D00997DE4 /* GTCred.h in Headers */, - 4D79C0F717DFAA7100997DE4 /* GTCred+Private.h in Headers */, + 4D79C0EE17DF9F4D00997DE4 /* GTCredential.h in Headers */, + 4D79C0F717DFAA7100997DE4 /* GTCredential+Private.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1332,7 +1332,7 @@ 8821547F17147B3600D76B76 /* GTOID.m in Sources */, 5BE6128A1745EE3400266D8C /* GTTreeBuilder.m in Sources */, D09C2E381755F16200065E36 /* GTSubmodule.m in Sources */, - 4D79C0EF17DF9F4D00997DE4 /* GTCred.m in Sources */, + 4D79C0EF17DF9F4D00997DE4 /* GTCredential.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From e8c3dde668dca927b38c3e8a94f75faf5764beb1 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 16 Sep 2013 11:56:38 +0200 Subject: [PATCH 03/23] Add GTCredentialProvider class + documentation. --- Classes/GTCredential+Private.h | 19 ++++++++++--------- Classes/GTCredential.h | 32 ++++++++++++++++++++++++++++++-- Classes/GTCredential.m | 33 +++++++++++++++++++++++++++++---- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/Classes/GTCredential+Private.h b/Classes/GTCredential+Private.h index 0b51d042a..866b389a7 100644 --- a/Classes/GTCredential+Private.h +++ b/Classes/GTCredential+Private.h @@ -8,22 +8,23 @@ #import "GTCredential.h" -// If you need to authenticate an operation in libgit2, you'll have to -// have a `GTCredentialBlock` handy, like a parameter in the method you're writing, -// setup a GTCredentialAcquireCallbackInfo struct on the stack, and pass both as the -// arguments to the operation you're attempting. +// If you need to authenticate an operation in libgit2, you'll have to have +// a `GTCredentialProvider` handy, like a parameter in the method you're writing, +// setup a GTCredentialAcquireCallbackInfo struct on the stack, and pass both as +// the arguments to the operation you're attempting. // // Example: ``` -// struct GTCredentialAcquireCallbackInfo info = { .credBlock = ... } +// struct GTCredentialAcquireCallbackInfo info = { .credProvider = myProvider } // git_remote_set_cred_acquire_cb(&git_remote, GTCredentialAcquireCallback, &payload); // ``` // -// `GTCredentialAcquireCallback` will act as a trampoline, and will ask the user code -// for a `GTCredential` object. It is the user's responsibility to check the auth type -// and initialize its `GTCredential` object correctly. +// `GTCredentialAcquireCallback` will act as a trampoline, and will ask the +// `GTCredentialProvider` for a `GTCredential` object corresponding to the +// information requested by `libgit2`. It is the providers's responsibility +// to check the auth type and initialize its `GTCredential` object accordingly. typedef struct { - __unsafe_unretained GTCredentialBlock credBlock; + __unsafe_unretained GTCredentialProvider *credProvider; } GTCredentialAcquireCallbackInfo; int GTCredentialAcquireCallback(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload); diff --git a/Classes/GTCredential.h b/Classes/GTCredential.h index 4cc639b9f..d0e56e01d 100644 --- a/Classes/GTCredential.h +++ b/Classes/GTCredential.h @@ -17,9 +17,36 @@ typedef enum { } GTCredentialType; @class GTCredential; -// A typedef block for the various methods that require authentication -typedef GTCredential *(^GTCredentialBlock)(GTCredentialType allowedTypes, NSString *URL, NSString *username); +// The GTCredentialProvider acts as a proxy for GTCredential requests. +// +// The default implementation is used through `+providerWithBlock:`, +// passing your own block that will build a GTCredential object. +// But you're allowed to subclass it and handle more complex workflows. +@interface GTCredentialProvider : NSObject + +// Creates a provider from a block. +// +// credentialBlock - a block that will be called when credentials are requested. ++ (instancetype)providerWithBlock:(GTCredential *(^)(GTCredentialType type, NSString *URL, NSString *userName))credentialBlock; + +// Default credential provider method. +// +// This method will get called when an operation requests credentials from the +// provider. +// +// The default implementation calls through the `providedBlock` passed +// in `providerWithBlock:` above, but your subclass is expected to override it +// to do its specific work. +// +// type - the credential types allowed by the operation. +// URL - the URL the operation is authenticating against. +// userName - the user name provided by the operation. Can be nil, and might be ignored. +- (GTCredential *)credentialForType:(GTCredentialType)type URL:(NSString *)URL userName:(NSString *)userName; +@end + +// The GTCredential class is used to provide authentication data. +// It acts as a wrapper around `git_cred` objects. @interface GTCredential : NSObject // Create a credential object from a username/password pair. @@ -43,6 +70,7 @@ typedef GTCredential *(^GTCredentialBlock)(GTCredentialType allowedTypes, NSStri // PARTIALIMPL + (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSString *)publicKey signBlock:(void (^)(void))signBlock error:(NSError **)error; +// The underlying `git_cred` object. - (git_cred *)git_cred __attribute__((objc_returns_inner_pointer)); @property (readonly) BOOL hasUserName; diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 85b6e38f5..2886d75f6 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -10,6 +10,30 @@ #import "GTCredential.h" #import "GTCredential+Private.h" +typedef GTCredential *(^GTCredentialProviderBlock)(GTCredentialType allowedTypes, NSString *URL, NSString *userName); + +@interface GTCredentialProvider () +@property (assign) GTCredentialProviderBlock credBlock; +@end + +@implementation GTCredentialProvider ++ (instancetype)providerWithBlock:(GTCredential *(^)(GTCredentialType type, NSString *URL, NSString *userName))credentialBlock { + NSParameterAssert(credentialBlock != nil); + GTCredentialProvider *provider = [[self alloc] init]; + + provider.credBlock = credentialBlock; + + return provider; +} + +- (GTCredential *)credentialForType:(GTCredentialType)type URL:(NSString *)URL userName:(NSString *)userName { + NSAssert(self.credBlock != nil, @"Provider asked for credentials without block being set."); + + return self.credBlock(type, URL, userName); +} + +@end + @interface GTCredential () @property (nonatomic, assign, readonly) git_cred *git_cred; @end @@ -81,9 +105,10 @@ int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char NSCParameterAssert(payload != NULL); GTCredentialAcquireCallbackInfo *info = payload; + GTCredentialProvider *provider = info->credProvider; - if (info->credBlock == nil) { - NSString *errorMsg = [NSString stringWithFormat:@"No credentials provided, but authentication was requested."]; + if (provider == nil) { + NSString *errorMsg = [NSString stringWithFormat:@"No GTCredentialProvider set, but authentication was requested."]; giterr_set_str(GIT_EUSER, errorMsg.UTF8String); return GIT_ERROR; } @@ -91,9 +116,9 @@ int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char NSString *URL = (url != NULL ? @(url) : nil); NSString *userName = (username_from_url != NULL ? @(username_from_url) : nil); - GTCredential *cred = info->credBlock((GTCredentialType)allowed_types, URL, userName); + GTCredential *cred = [provider credentialForType:(GTCredentialType)allowed_types URL:URL userName:userName]; if (!cred) { - NSString *errorMsg = [NSString stringWithFormat:@"No credentials provided, but authentication was requested."]; + NSString *errorMsg = [NSString stringWithFormat:@"GTCredentialProvider failed to provide credentials."]; giterr_set_str(GIT_EUSER, errorMsg.UTF8String); return GIT_ERROR; } From cff67535517b6266b127f7cbda619fdb34d0dc63 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 10 Sep 2013 19:15:22 +0200 Subject: [PATCH 04/23] One line `userInfo` creation. --- Classes/Categories/NSError+Git.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Classes/Categories/NSError+Git.m b/Classes/Categories/NSError+Git.m index 89b7ff4ec..625eab0b8 100644 --- a/Classes/Categories/NSError+Git.m +++ b/Classes/Categories/NSError+Git.m @@ -69,7 +69,11 @@ + (NSError *)git_errorFor:(int)code description:(NSString *)desc failureReason:( } + (NSError *)git_errorFor:(int)code { - return [NSError errorWithDomain:GTGitErrorDomain code:code userInfo:[NSDictionary dictionaryWithObject:[self gitLastErrorDescriptionWithCode:code] forKey:NSLocalizedDescriptionKey]]; + NSString *gitError = [self gitLastErrorDescriptionWithCode:code]; + + NSDictionary *userInfo = (gitError != nil ? @{NSLocalizedDescriptionKey: gitError} : nil); + + return [NSError errorWithDomain:GTGitErrorDomain code:code userInfo:userInfo]; } + (NSError *)git_errorForMkStr:(int)code { From 23b4253852e4a1fc34d3d9941366ec718a9b84fd Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 16 Sep 2013 23:27:43 +0200 Subject: [PATCH 05/23] Update as per `libgit2` documentation. This takes paths to key files, not actual key data. --- Classes/GTCredential.h | 11 ++++++----- Classes/GTCredential.m | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Classes/GTCredential.h b/Classes/GTCredential.h index d0e56e01d..4432bcc28 100644 --- a/Classes/GTCredential.h +++ b/Classes/GTCredential.h @@ -59,13 +59,14 @@ typedef enum { // Create a credential object from a SSH keyfile // -// userName - The username to authenticate as. -// publicKey - The public key for that user. -// privateKey - The private key for that user. -// passPhrase - The passPhrase for the private key. Optional if the private key has no password. +// userName - The username to authenticate as. +// publicKeyPath - The path to the public key for that user. +// Can be omitted to reconstruct the public key from the private key. +// privateKeyPath - The path to the private key for that user. +// passPhrase - The passPhrase for the private key. Optional if the private key has no password. // // Return a new GTCred instance, or nil if an error occurred -+ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSString *)publicKey privateKey:(NSString *)privateKey passPhrase:(NSString *)passPhrase error:(NSError **)error; ++ (instancetype)credentialWithUserName:(NSString *)userName publicKeyPath:(NSString *)publicKeyPath privateKeyPath:(NSString *)privateKeyPath passPhrase:(NSString *)passPhrase error:(NSError **)error; // PARTIALIMPL + (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSString *)publicKey signBlock:(void (^)(void))signBlock error:(NSError **)error; diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 2886d75f6..b0eb95542 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -51,11 +51,11 @@ + (instancetype)credentialWithUserName:(NSString *)userName password:(NSString * return [[self alloc] initWithGitCred:cred]; } -+ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSString *)publicKey privateKey:(NSString *)privateKey passPhrase:(NSString *)passPhrase error:(NSError **)error { - NSParameterAssert(privateKey != nil); ++ (instancetype)credentialWithUserName:(NSString *)userName publicKeyPath:(NSString *)publicKeyPath privateKeyPath:(NSString *)privateKeyPath passPhrase:(NSString *)passPhrase error:(NSError **)error { + NSParameterAssert(privateKeyPath != nil); git_cred *cred; - int gitError = git_cred_ssh_keyfile_passphrase_new(&cred, userName.UTF8String, publicKey.UTF8String, privateKey.UTF8String, passPhrase.UTF8String); + int gitError = git_cred_ssh_keyfile_passphrase_new(&cred, userName.UTF8String, publicKeyPath.fileSystemRepresentation, privateKeyPath.fileSystemRepresentation, passPhrase.UTF8String); if (gitError != GIT_OK) { if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@ with the provided public/private key pair.", userName]; return nil; From 282334574cfb04f0b190337c4f4cc92d9a2b33e9 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 17 Sep 2013 01:02:19 +0200 Subject: [PATCH 06/23] Small documentation fixes. --- Classes/GTCredential.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Classes/GTCredential.h b/Classes/GTCredential.h index 4432bcc28..52c3eec30 100644 --- a/Classes/GTCredential.h +++ b/Classes/GTCredential.h @@ -53,8 +53,9 @@ typedef enum { // // userName - The username to authenticate as. // password - The password belonging to that user. +// error - If not NULL, set to any errors that occur. // -// Return a new GTCred instance, or nil if an error occurred +// Return a new GTCredential instance, or nil if an error occurred + (instancetype)credentialWithUserName:(NSString *)userName password:(NSString *)password error:(NSError **)error; // Create a credential object from a SSH keyfile @@ -64,8 +65,9 @@ typedef enum { // Can be omitted to reconstruct the public key from the private key. // privateKeyPath - The path to the private key for that user. // passPhrase - The passPhrase for the private key. Optional if the private key has no password. +// error - If not NULL, set to any errors that occur. // -// Return a new GTCred instance, or nil if an error occurred +// Return a new GTCredential instance, or nil if an error occurred + (instancetype)credentialWithUserName:(NSString *)userName publicKeyPath:(NSString *)publicKeyPath privateKeyPath:(NSString *)privateKeyPath passPhrase:(NSString *)passPhrase error:(NSError **)error; // PARTIALIMPL From 6cc9a6624ef06d34f8b11cd240276e54a3e57a07 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 17 Sep 2013 01:03:00 +0200 Subject: [PATCH 07/23] Implement the 3rd method. That `GIT_SSH` define is needed in the project to make both `LIBSSH_SESSION` and the correct typedef for `git_cred_sign_callback` visible. I do think it's a quirk of libgit2 though... --- Classes/GTCredential.h | 14 ++++++-- Classes/GTCredential.m | 33 +++++++++++++------ .../project.pbxproj | 24 ++++++++++++++ 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/Classes/GTCredential.h b/Classes/GTCredential.h index 52c3eec30..04d85ef6a 100644 --- a/Classes/GTCredential.h +++ b/Classes/GTCredential.h @@ -70,8 +70,18 @@ typedef enum { // Return a new GTCredential instance, or nil if an error occurred + (instancetype)credentialWithUserName:(NSString *)userName publicKeyPath:(NSString *)publicKeyPath privateKeyPath:(NSString *)privateKeyPath passPhrase:(NSString *)passPhrase error:(NSError **)error; -// PARTIALIMPL -+ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSString *)publicKey signBlock:(void (^)(void))signBlock error:(NSError **)error; +// Create a credential object from a public key +// +// userName - The username to authenticate as. +// publicKey - The data of public key of the user. +// error - If not NULL, set to any errors that occur. +// signBlock - A block that will be called to authentify that the user owns the private key. +// You should return the contents of data, signed with the private key. +// session - A pointer to the underlying LIBSSH2_SESSION. +// data - The data to sign. +// +// Returns a new GTCredential instance, or nil if an error occurred. ++ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSData *)publicKey error:(NSError **)error signBlock:(NSData *(^)(void *session, NSData *data))signBlock ; // The underlying `git_cred` object. - (git_cred *)git_cred __attribute__((objc_returns_inner_pointer)); diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index b0eb95542..397f41794 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -9,6 +9,7 @@ #import #import "GTCredential.h" #import "GTCredential+Private.h" +#import typedef GTCredential *(^GTCredentialProviderBlock)(GTCredentialType allowedTypes, NSString *URL, NSString *userName); @@ -64,19 +65,31 @@ + (instancetype)credentialWithUserName:(NSString *)userName publicKeyPath:(NSStr return [[self alloc] initWithGitCred:cred]; } -+ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSString *)publicKey signBlock:(void (^)(void))signBlock error:(NSError **)error { - /* prototype for second-to-last argument in `git_cred_ssh_publickey_new` : - * - * int git_cred_sign_callback(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, \ - const unsigned char *data, size_t data_len, void **abstract); - * - * LIBSSH2_SESSION ? Eek... - */ +typedef NSData *(^GTCredentialSignBlock)(void *session, NSData *data); + +struct GTCredentialSignPayload { + __unsafe_unretained GTCredentialSignBlock signBlock; +}; + +int GTCredentialSignCallback(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, const unsigned char *data, size_t data_len, void **abstract) { + struct GTCredentialSignPayload *payload = *abstract; + NSData *dataObject = [NSData dataWithBytesNoCopy:(void *)data length:data_len]; + + NSData *signData = payload->signBlock(session, dataObject); + + memcpy(sig, signData.bytes, signData.length); + *sig_len = signData.length; + + return signData != nil ? 0 : -1; +} + ++ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSData *)publicKey error:(NSError **)error signBlock:(GTCredentialSignBlock)signBlock { + struct GTCredentialSignPayload payload = { .signBlock = signBlock }; git_cred *cred; - int gitError = git_cred_ssh_publickey_new(&cred, userName.UTF8String, publicKey.UTF8String, [publicKey lengthOfBytesUsingEncoding:NSUTF8StringEncoding], NULL, NULL); + int gitError = git_cred_ssh_publickey_new(&cred, userName.UTF8String, publicKey.bytes, publicKey.length, GTCredentialSignCallback, &payload); if (gitError != GIT_OK) { - if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@ with the provided public/private key pair.", userName]; + if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@ with the provided public key and sign block.", userName]; return nil; } diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index 8de028f27..b39f3ada2 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -1416,6 +1416,10 @@ "External/ios-openssl/lib", "External/libssh2-ios/lib", ); + OTHER_CFLAGS = ( + "$(inherited)", + "-DGIT_SSH", + ); OTHER_LDFLAGS = ( "-lgit2-iOS", "-all_load", @@ -1441,6 +1445,10 @@ "External/ios-openssl/lib", "External/libssh2-ios/lib", ); + OTHER_CFLAGS = ( + "$(inherited)", + "-DGIT_SSH", + ); OTHER_LDFLAGS = ( "-lgit2-iOS", "-all_load", @@ -1464,6 +1472,10 @@ /usr/local/include, ); INFOPLIST_FILE = Info.plist; + OTHER_CFLAGS = ( + "$(inherited)", + "-DGIT_SSH", + ); OTHER_LDFLAGS = ( "-lgit2", "-force_load", @@ -1489,6 +1501,10 @@ /usr/local/include, ); INFOPLIST_FILE = Info.plist; + OTHER_CFLAGS = ( + "$(inherited)", + "-DGIT_SSH", + ); OTHER_LDFLAGS = ( "-lgit2", "-force_load", @@ -1652,6 +1668,10 @@ /usr/local/include, ); INFOPLIST_FILE = Info.plist; + OTHER_CFLAGS = ( + "$(inherited)", + "-DGIT_SSH", + ); OTHER_LDFLAGS = ( "-lgit2", "-force_load", @@ -1679,6 +1699,10 @@ "External/ios-openssl/lib", "External/libssh2-ios/lib", ); + OTHER_CFLAGS = ( + "$(inherited)", + "-DGIT_SSH", + ); OTHER_LDFLAGS = ( "-lgit2-iOS", "-all_load", From 64c0c6dc2b21c435a79531fbaafa67f71376999f Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 17 Sep 2013 01:32:44 +0200 Subject: [PATCH 08/23] Allow passing a GTCredentialProvider when cloning. --- Classes/GTRepository.h | 3 +++ Classes/GTRepository.m | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/Classes/GTRepository.h b/Classes/GTRepository.h index 79dcb592a..583326dd9 100644 --- a/Classes/GTRepository.h +++ b/Classes/GTRepository.h @@ -114,6 +114,9 @@ extern NSString *const GTRepositoryCloneOptionsBare; // Default value is `YES`. extern NSString *const GTRepositoryCloneOptionsCheckout; +// A `GTCredentialProvider`, that will be used to authenticate against the remote. +extern NSString *const GTRepositoryCloneOptionsCredentialProvider; + typedef void (^GTRepositoryStatusBlock)(NSURL *fileURL, GTRepositoryFileStatus status, BOOL *stop); @interface GTRepository : NSObject diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index b2b61b0ff..44fb2c052 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -43,10 +43,13 @@ #import "NSError+Git.h" #import "NSString+Git.h" #import "GTDiffFile.h" +#import "GTCredential.h" +#import "GTCredential+Private.h" NSString *const GTRepositoryCloneOptionsBare = @"GTRepositoryCloneOptionsBare"; NSString *const GTRepositoryCloneOptionsCheckout = @"GTRepositoryCloneOptionsCheckout"; NSString *const GTRepositoryCloneOptionsTransportFlags = @"GTRepositoryCloneOptionsTransportFlags"; +NSString *const GTRepositoryCloneOptionsCredentialProvider = @"GTRepositoryCloneOptionsCredentialProvider"; // The type of block passed to -enumerateSubmodulesRecursively:usingBlock:. typedef void (^GTRepositorySubmoduleEnumerationBlock)(GTSubmodule *submodule, BOOL *stop); @@ -192,6 +195,13 @@ + (id)cloneFromURL:(NSURL *)originURL toWorkingDirectory:(NSURL *)workdirURL opt cloneOptions.checkout_opts = checkoutOptions; } + GTCredentialProvider *provider = options[GTRepositoryCloneOptionsCredentialProvider]; + if (provider) { + GTCredentialAcquireCallbackInfo info = { .credProvider = provider }; + cloneOptions.cred_acquire_cb = GTCredentialAcquireCallback; + cloneOptions.cred_acquire_payload = &info; + } + cloneOptions.fetch_progress_cb = transferProgressCallback; cloneOptions.fetch_progress_payload = (__bridge void *)transferProgressBlock; From 4b5b35a52001d1b105b530040eeef819d163c759 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 17 Sep 2013 11:30:10 +0200 Subject: [PATCH 09/23] Use `NSURL` for files. --- Classes/GTCredential.h | 14 +++++++------- Classes/GTCredential.m | 9 ++++++--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Classes/GTCredential.h b/Classes/GTCredential.h index 04d85ef6a..dab77ee86 100644 --- a/Classes/GTCredential.h +++ b/Classes/GTCredential.h @@ -13,7 +13,7 @@ typedef enum { GTCredentialTypeUserPassPlaintext = GIT_CREDTYPE_USERPASS_PLAINTEXT, GTCredentialTypeSSHKeyFilePassPhrase = GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE, - GTCredentialTypeSSHPublicKey = GIT_CREDTYPE_SSH_PUBLICKEY, + GTCredentialTypeSSHPublicKey = GIT_CREDTYPE_SSH_PUBLICKEY_SIGN, } GTCredentialType; @class GTCredential; @@ -60,15 +60,15 @@ typedef enum { // Create a credential object from a SSH keyfile // -// userName - The username to authenticate as. -// publicKeyPath - The path to the public key for that user. +// userName - The username to authenticate as. +// publicKeyURL - The URL to the public key for that user. // Can be omitted to reconstruct the public key from the private key. -// privateKeyPath - The path to the private key for that user. -// passPhrase - The passPhrase for the private key. Optional if the private key has no password. -// error - If not NULL, set to any errors that occur. +// privateKeyURL - The URL to the private key for that user. +// passphrase - The passPhrase for the private key. Optional if the private key has no password. +// error - If not NULL, set to any errors that occur. // // Return a new GTCredential instance, or nil if an error occurred -+ (instancetype)credentialWithUserName:(NSString *)userName publicKeyPath:(NSString *)publicKeyPath privateKeyPath:(NSString *)privateKeyPath passPhrase:(NSString *)passPhrase error:(NSError **)error; ++ (instancetype)credentialWithUserName:(NSString *)userName publicKeyURL:(NSURL *)publicKeyURL privateKeyURL:(NSURL *)privateKeyURL passphrase:(NSString *)passphrase error:(NSError **)error; // Create a credential object from a public key // diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 397f41794..918339a4f 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -52,11 +52,14 @@ + (instancetype)credentialWithUserName:(NSString *)userName password:(NSString * return [[self alloc] initWithGitCred:cred]; } -+ (instancetype)credentialWithUserName:(NSString *)userName publicKeyPath:(NSString *)publicKeyPath privateKeyPath:(NSString *)privateKeyPath passPhrase:(NSString *)passPhrase error:(NSError **)error { - NSParameterAssert(privateKeyPath != nil); ++ (instancetype)credentialWithUserName:(NSString *)userName publicKeyURL:(NSURL *)publicKeyURL privateKeyURL:(NSURL *)privateKeyURL passphrase:(NSString *)passphrase error:(NSError **)error { + NSParameterAssert(privateKeyURL != nil); + NSString *publicKeyPath = publicKeyURL.filePathURL.path; + NSString *privateKeyPath = privateKeyURL.filePathURL.path; + NSAssert(privateKeyPath != nil, @"Invalid file URL passed: %@", privateKeyURL); git_cred *cred; - int gitError = git_cred_ssh_keyfile_passphrase_new(&cred, userName.UTF8String, publicKeyPath.fileSystemRepresentation, privateKeyPath.fileSystemRepresentation, passPhrase.UTF8String); + int gitError = git_cred_ssh_keyfile_passphrase_new(&cred, userName.UTF8String, publicKeyPath.fileSystemRepresentation, privateKeyPath.fileSystemRepresentation, passphrase.UTF8String); if (gitError != GIT_OK) { if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@ with the provided public/private key pair.", userName]; return nil; From 194543b323443997798b30f2b2f1724dad305d7f Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 17 Sep 2013 11:32:58 +0200 Subject: [PATCH 10/23] Remove unused property. --- Classes/GTCredential.h | 2 -- Classes/GTCredential.m | 4 ---- 2 files changed, 6 deletions(-) diff --git a/Classes/GTCredential.h b/Classes/GTCredential.h index dab77ee86..27222047d 100644 --- a/Classes/GTCredential.h +++ b/Classes/GTCredential.h @@ -86,6 +86,4 @@ typedef enum { // The underlying `git_cred` object. - (git_cred *)git_cred __attribute__((objc_returns_inner_pointer)); -@property (readonly) BOOL hasUserName; - @end diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 918339a4f..62d4c3d7b 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -110,10 +110,6 @@ - (instancetype)initWithGitCred:(git_cred *)cred { return self; } -- (BOOL)hasUserName { - return git_cred_has_username(self.git_cred) == 1; -} - @end int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload) { From f3db7d0e5d5fabb413e4f0671984586796c050b9 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 17 Sep 2013 11:35:04 +0200 Subject: [PATCH 11/23] `assign` => `copy`. --- Classes/GTCredential.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 62d4c3d7b..ba1b6f07a 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -14,7 +14,7 @@ typedef GTCredential *(^GTCredentialProviderBlock)(GTCredentialType allowedTypes, NSString *URL, NSString *userName); @interface GTCredentialProvider () -@property (assign) GTCredentialProviderBlock credBlock; +@property (copy) GTCredentialProviderBlock credBlock; @end @implementation GTCredentialProvider From 3ad8518e961914d2372615b228273d0e15cf7b93 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 17 Sep 2013 11:35:17 +0200 Subject: [PATCH 12/23] Tab-indent. --- Classes/GTCredential.m | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index ba1b6f07a..8196f3ef3 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -49,7 +49,7 @@ + (instancetype)credentialWithUserName:(NSString *)userName password:(NSString * return nil; } - return [[self alloc] initWithGitCred:cred]; + return [[self alloc] initWithGitCred:cred]; } + (instancetype)credentialWithUserName:(NSString *)userName publicKeyURL:(NSURL *)publicKeyURL privateKeyURL:(NSURL *)privateKeyURL passphrase:(NSString *)passphrase error:(NSError **)error { @@ -65,7 +65,7 @@ + (instancetype)credentialWithUserName:(NSString *)userName publicKeyURL:(NSURL return nil; } - return [[self alloc] initWithGitCred:cred]; + return [[self alloc] initWithGitCred:cred]; } typedef NSData *(^GTCredentialSignBlock)(void *session, NSData *data); @@ -116,23 +116,23 @@ int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char NSCParameterAssert(git_cred != NULL); NSCParameterAssert(payload != NULL); - GTCredentialAcquireCallbackInfo *info = payload; + GTCredentialAcquireCallbackInfo *info = payload; GTCredentialProvider *provider = info->credProvider; - if (provider == nil) { - NSString *errorMsg = [NSString stringWithFormat:@"No GTCredentialProvider set, but authentication was requested."]; - giterr_set_str(GIT_EUSER, errorMsg.UTF8String); - return GIT_ERROR; - } + if (provider == nil) { + NSString *errorMsg = [NSString stringWithFormat:@"No GTCredentialProvider set, but authentication was requested."]; + giterr_set_str(GIT_EUSER, errorMsg.UTF8String); + return GIT_ERROR; + } - NSString *URL = (url != NULL ? @(url) : nil); - NSString *userName = (username_from_url != NULL ? @(username_from_url) : nil); + NSString *URL = (url != NULL ? @(url) : nil); + NSString *userName = (username_from_url != NULL ? @(username_from_url) : nil); GTCredential *cred = [provider credentialForType:(GTCredentialType)allowed_types URL:URL userName:userName]; if (!cred) { - NSString *errorMsg = [NSString stringWithFormat:@"GTCredentialProvider failed to provide credentials."]; - giterr_set_str(GIT_EUSER, errorMsg.UTF8String); - return GIT_ERROR; + NSString *errorMsg = [NSString stringWithFormat:@"GTCredentialProvider failed to provide credentials."]; + giterr_set_str(GIT_EUSER, errorMsg.UTF8String); + return GIT_ERROR; } *git_cred = cred.git_cred; From 47e042661250b81261eb6ad0dee89db668ac517b Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 17 Sep 2013 12:45:38 +0200 Subject: [PATCH 13/23] Oops. --- Classes/GTCredential.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/GTCredential.h b/Classes/GTCredential.h index 27222047d..ec1cad022 100644 --- a/Classes/GTCredential.h +++ b/Classes/GTCredential.h @@ -13,7 +13,7 @@ typedef enum { GTCredentialTypeUserPassPlaintext = GIT_CREDTYPE_USERPASS_PLAINTEXT, GTCredentialTypeSSHKeyFilePassPhrase = GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE, - GTCredentialTypeSSHPublicKey = GIT_CREDTYPE_SSH_PUBLICKEY_SIGN, + GTCredentialTypeSSHPublicKey = GIT_CREDTYPE_SSH_PUBLICKEY, } GTCredentialType; @class GTCredential; From 7617ee727545ace776afe80d8ff36ffb6a0fd5f7 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Wed, 25 Sep 2013 11:13:32 +0200 Subject: [PATCH 14/23] Remove 3rd authentication method. --- Classes/GTCredential.h | 13 ------------- Classes/GTCredential.m | 31 ------------------------------- 2 files changed, 44 deletions(-) diff --git a/Classes/GTCredential.h b/Classes/GTCredential.h index ec1cad022..c68ca0179 100644 --- a/Classes/GTCredential.h +++ b/Classes/GTCredential.h @@ -70,19 +70,6 @@ typedef enum { // Return a new GTCredential instance, or nil if an error occurred + (instancetype)credentialWithUserName:(NSString *)userName publicKeyURL:(NSURL *)publicKeyURL privateKeyURL:(NSURL *)privateKeyURL passphrase:(NSString *)passphrase error:(NSError **)error; -// Create a credential object from a public key -// -// userName - The username to authenticate as. -// publicKey - The data of public key of the user. -// error - If not NULL, set to any errors that occur. -// signBlock - A block that will be called to authentify that the user owns the private key. -// You should return the contents of data, signed with the private key. -// session - A pointer to the underlying LIBSSH2_SESSION. -// data - The data to sign. -// -// Returns a new GTCredential instance, or nil if an error occurred. -+ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSData *)publicKey error:(NSError **)error signBlock:(NSData *(^)(void *session, NSData *data))signBlock ; - // The underlying `git_cred` object. - (git_cred *)git_cred __attribute__((objc_returns_inner_pointer)); diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 8196f3ef3..6b5f6b3e0 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -68,37 +68,6 @@ + (instancetype)credentialWithUserName:(NSString *)userName publicKeyURL:(NSURL return [[self alloc] initWithGitCred:cred]; } -typedef NSData *(^GTCredentialSignBlock)(void *session, NSData *data); - -struct GTCredentialSignPayload { - __unsafe_unretained GTCredentialSignBlock signBlock; -}; - -int GTCredentialSignCallback(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, const unsigned char *data, size_t data_len, void **abstract) { - struct GTCredentialSignPayload *payload = *abstract; - NSData *dataObject = [NSData dataWithBytesNoCopy:(void *)data length:data_len]; - - NSData *signData = payload->signBlock(session, dataObject); - - memcpy(sig, signData.bytes, signData.length); - *sig_len = signData.length; - - return signData != nil ? 0 : -1; -} - -+ (instancetype)credentialWithUserName:(NSString *)userName publicKey:(NSData *)publicKey error:(NSError **)error signBlock:(GTCredentialSignBlock)signBlock { - struct GTCredentialSignPayload payload = { .signBlock = signBlock }; - - git_cred *cred; - int gitError = git_cred_ssh_publickey_new(&cred, userName.UTF8String, publicKey.bytes, publicKey.length, GTCredentialSignCallback, &payload); - if (gitError != GIT_OK) { - if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@ with the provided public key and sign block.", userName]; - return nil; - } - - return [[self alloc] initWithGitCred:cred]; -} - - (instancetype)initWithGitCred:(git_cred *)cred { NSParameterAssert(cred != nil); self = [self init]; From f21c87a62e5db01c1017ac543c30ebb6c6b67e95 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Wed, 25 Sep 2013 23:47:49 +0200 Subject: [PATCH 15/23] Move `-DGIT_SSH` at the project level. --- .../project.pbxproj | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index b39f3ada2..f2264ef88 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -1472,10 +1472,6 @@ /usr/local/include, ); INFOPLIST_FILE = Info.plist; - OTHER_CFLAGS = ( - "$(inherited)", - "-DGIT_SSH", - ); OTHER_LDFLAGS = ( "-lgit2", "-force_load", @@ -1501,10 +1497,6 @@ /usr/local/include, ); INFOPLIST_FILE = Info.plist; - OTHER_CFLAGS = ( - "$(inherited)", - "-DGIT_SSH", - ); OTHER_LDFLAGS = ( "-lgit2", "-force_load", @@ -1531,6 +1523,10 @@ External, ); MACOSX_DEPLOYMENT_TARGET = 10.7; + OTHER_CFLAGS = ( + "$(inherited)", + "-DGIT_SSH", + ); TEST_AFTER_BUILD = NO; }; name = Debug; @@ -1549,6 +1545,10 @@ External, ); MACOSX_DEPLOYMENT_TARGET = 10.7; + OTHER_CFLAGS = ( + "$(inherited)", + "-DGIT_SSH", + ); TEST_AFTER_BUILD = NO; }; name = Release; @@ -1651,6 +1651,10 @@ External, ); MACOSX_DEPLOYMENT_TARGET = 10.7; + OTHER_CFLAGS = ( + "$(inherited)", + "-DGIT_SSH", + ); TEST_AFTER_BUILD = NO; }; name = Profile; @@ -1668,10 +1672,6 @@ /usr/local/include, ); INFOPLIST_FILE = Info.plist; - OTHER_CFLAGS = ( - "$(inherited)", - "-DGIT_SSH", - ); OTHER_LDFLAGS = ( "-lgit2", "-force_load", From 4832625eb00f59faa5664923a604ca04aad0e49f Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 26 Sep 2013 00:02:33 +0200 Subject: [PATCH 16/23] Provide the paths to the public and private keys in the error message. --- Classes/GTCredential.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 6b5f6b3e0..56766135e 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -61,7 +61,7 @@ + (instancetype)credentialWithUserName:(NSString *)userName publicKeyURL:(NSURL git_cred *cred; int gitError = git_cred_ssh_keyfile_passphrase_new(&cred, userName.UTF8String, publicKeyPath.fileSystemRepresentation, privateKeyPath.fileSystemRepresentation, passphrase.UTF8String); if (gitError != GIT_OK) { - if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@ with the provided public/private key pair.", userName]; + if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@ with the provided public/private key pair.\nPublic key: %@\nPrivate key: %@", userName, publicKeyURL, privateKeyURL]; return nil; } From cc2670f5c98d8c14d984797643dd9dfeb1767fef Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 26 Sep 2013 00:08:48 +0200 Subject: [PATCH 17/23] No need for formatting. --- Classes/GTCredential.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 56766135e..a16f10616 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -89,7 +89,7 @@ int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char GTCredentialProvider *provider = info->credProvider; if (provider == nil) { - NSString *errorMsg = [NSString stringWithFormat:@"No GTCredentialProvider set, but authentication was requested."]; + NSString *errorMsg = @"No GTCredentialProvider set, but authentication was requested."; giterr_set_str(GIT_EUSER, errorMsg.UTF8String); return GIT_ERROR; } @@ -99,7 +99,7 @@ int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char GTCredential *cred = [provider credentialForType:(GTCredentialType)allowed_types URL:URL userName:userName]; if (!cred) { - NSString *errorMsg = [NSString stringWithFormat:@"GTCredentialProvider failed to provide credentials."]; + NSString *errorMsg = @"GTCredentialProvider failed to provide credentials."; giterr_set_str(GIT_EUSER, errorMsg.UTF8String); return GIT_ERROR; } From 29f132bced902766acf0af03cc5f444ab60fbe35 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 26 Sep 2013 00:08:58 +0200 Subject: [PATCH 18/23] Style: explicit nil comparison. --- Classes/GTCredential.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index a16f10616..806bcde49 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -72,7 +72,7 @@ - (instancetype)initWithGitCred:(git_cred *)cred { NSParameterAssert(cred != nil); self = [self init]; - if (!self) return nil; + if (self == nil) return nil; _git_cred = cred; @@ -98,7 +98,7 @@ int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char NSString *userName = (username_from_url != NULL ? @(username_from_url) : nil); GTCredential *cred = [provider credentialForType:(GTCredentialType)allowed_types URL:URL userName:userName]; - if (!cred) { + if (cred == nil) { NSString *errorMsg = @"GTCredentialProvider failed to provide credentials."; giterr_set_str(GIT_EUSER, errorMsg.UTF8String); return GIT_ERROR; From 3fb9a46e6e83ca26530520646db32f177432c83f Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 26 Sep 2013 00:12:26 +0200 Subject: [PATCH 19/23] Also move that one to the project level Else test building fails on the include. --- .../project.pbxproj | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index f2264ef88..804369c21 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -1467,10 +1467,6 @@ DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_PREFIX_HEADER = ObjectiveGitFramework_Prefix.pch; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /usr/local/include, - ); INFOPLIST_FILE = Info.plist; OTHER_LDFLAGS = ( "-lgit2", @@ -1492,10 +1488,6 @@ DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_PREFIX_HEADER = ObjectiveGitFramework_Prefix.pch; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /usr/local/include, - ); INFOPLIST_FILE = Info.plist; OTHER_LDFLAGS = ( "-lgit2", @@ -1516,7 +1508,10 @@ ARCHS = "$(ARCHS_STANDARD_64_BIT)"; GCC_STRICT_ALIASING = NO; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO; - HEADER_SEARCH_PATHS = External/libgit2/include; + HEADER_SEARCH_PATHS = ( + External/libgit2/include, + /usr/local/include, + ); IPHONEOS_DEPLOYMENT_TARGET = 5.0; LIBRARY_SEARCH_PATHS = ( ., @@ -1538,7 +1533,10 @@ ARCHS = "$(ARCHS_STANDARD_64_BIT)"; GCC_STRICT_ALIASING = NO; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO; - HEADER_SEARCH_PATHS = External/libgit2/include; + HEADER_SEARCH_PATHS = ( + External/libgit2/include, + /usr/local/include, + ); IPHONEOS_DEPLOYMENT_TARGET = 5.0; LIBRARY_SEARCH_PATHS = ( ., @@ -1644,7 +1642,10 @@ ARCHS = "$(ARCHS_STANDARD_64_BIT)"; GCC_STRICT_ALIASING = NO; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO; - HEADER_SEARCH_PATHS = External/libgit2/include; + HEADER_SEARCH_PATHS = ( + External/libgit2/include, + /usr/local/include, + ); IPHONEOS_DEPLOYMENT_TARGET = 5.0; LIBRARY_SEARCH_PATHS = ( ., @@ -1667,10 +1668,6 @@ DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_PREFIX_HEADER = ObjectiveGitFramework_Prefix.pch; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /usr/local/include, - ); INFOPLIST_FILE = Info.plist; OTHER_LDFLAGS = ( "-lgit2", From 0f9b7c92ba2403c142fbac3540b0e3a3450db611 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 30 Sep 2013 19:04:21 +0200 Subject: [PATCH 20/23] Use the typedef-ed block in that signature. --- Classes/GTCredential.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 806bcde49..2119738fe 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -18,7 +18,7 @@ @interface GTCredentialProvider () @end @implementation GTCredentialProvider -+ (instancetype)providerWithBlock:(GTCredential *(^)(GTCredentialType type, NSString *URL, NSString *userName))credentialBlock { ++ (instancetype)providerWithBlock:(GTCredentialProviderBlock)credentialBlock { NSParameterAssert(credentialBlock != nil); GTCredentialProvider *provider = [[self alloc] init]; From 9d691269003dcfd1df99108ade749cc4d27f345b Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 30 Sep 2013 19:05:29 +0200 Subject: [PATCH 21/23] Make the provider's block ivar `nonatomic, readonly`. --- Classes/GTCredential.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 2119738fe..05117f07e 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -14,15 +14,16 @@ typedef GTCredential *(^GTCredentialProviderBlock)(GTCredentialType allowedTypes, NSString *URL, NSString *userName); @interface GTCredentialProvider () -@property (copy) GTCredentialProviderBlock credBlock; +@property (nonatomic, readonly) GTCredentialProviderBlock credBlock; @end @implementation GTCredentialProvider + (instancetype)providerWithBlock:(GTCredentialProviderBlock)credentialBlock { NSParameterAssert(credentialBlock != nil); + GTCredentialProvider *provider = [[self alloc] init]; - provider.credBlock = credentialBlock; + provider->_credBlock = credentialBlock; return provider; } From e29d347060b1209010caaedfd113abcd3f4b780d Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 1 Oct 2013 09:37:53 +0200 Subject: [PATCH 22/23] Copy that. --- Classes/GTCredential.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 05117f07e..71682f406 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -14,7 +14,7 @@ typedef GTCredential *(^GTCredentialProviderBlock)(GTCredentialType allowedTypes, NSString *URL, NSString *userName); @interface GTCredentialProvider () -@property (nonatomic, readonly) GTCredentialProviderBlock credBlock; +@property (nonatomic, readonly, copy) GTCredentialProviderBlock credBlock; @end @implementation GTCredentialProvider @@ -23,7 +23,7 @@ + (instancetype)providerWithBlock:(GTCredentialProviderBlock)credentialBlock { GTCredentialProvider *provider = [[self alloc] init]; - provider->_credBlock = credentialBlock; + provider->_credBlock = [credentialBlock copy]; return provider; } From 32c00c22331d3f97d4bcd887a41dec8fbaa54968 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 1 Oct 2013 09:38:48 +0200 Subject: [PATCH 23/23] Use a C string instead of NSString. --- Classes/GTCredential.m | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Classes/GTCredential.m b/Classes/GTCredential.m index 71682f406..60bf1097f 100644 --- a/Classes/GTCredential.m +++ b/Classes/GTCredential.m @@ -90,8 +90,7 @@ int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char GTCredentialProvider *provider = info->credProvider; if (provider == nil) { - NSString *errorMsg = @"No GTCredentialProvider set, but authentication was requested."; - giterr_set_str(GIT_EUSER, errorMsg.UTF8String); + giterr_set_str(GIT_EUSER, "No GTCredentialProvider set, but authentication was requested."); return GIT_ERROR; } @@ -100,8 +99,7 @@ int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char GTCredential *cred = [provider credentialForType:(GTCredentialType)allowed_types URL:URL userName:userName]; if (cred == nil) { - NSString *errorMsg = @"GTCredentialProvider failed to provide credentials."; - giterr_set_str(GIT_EUSER, errorMsg.UTF8String); + giterr_set_str(GIT_EUSER, "GTCredentialProvider failed to provide credentials."); return GIT_ERROR; }