diff --git a/ObjectiveGit/GTRepository.h b/ObjectiveGit/GTRepository.h index 45f3caead..b98137207 100644 --- a/ObjectiveGit/GTRepository.h +++ b/ObjectiveGit/GTRepository.h @@ -110,6 +110,16 @@ extern NSString * const GTRepositoryCloneOptionsCloneLocal; /// A NSURL pointing to a local file that contains PEM-encoded certificate chain. extern NSString *const GTRepositoryCloneOptionsServerCertificateURL; +/// Repository extended open control flags for +/// +initWithURL:flags:ceilingDirs:error:. +/// +/// See respository.h for documentation of each individual flag. +typedef NS_OPTIONS(NSInteger, GTRepositoryOpenFlags) { + GTRepositoryOpenNoSearch = GIT_REPOSITORY_OPEN_NO_SEARCH, + GTRepositoryOpenCrossFS = GIT_REPOSITORY_OPEN_CROSS_FS, + GTRepositoryOpenBare = GIT_REPOSITORY_OPEN_BARE, +}; + /// Initialization flags associated with `GTRepositoryInitOptionsFlags` for /// +initializeEmptyRepositoryAtFileURL:options:error:. /// @@ -209,6 +219,17 @@ typedef NS_ENUM(NSInteger, GTRepositoryStateType) { /// Returns the initialized repository, or nil if an error occurred. - (nullable instancetype)initWithURL:(NSURL *)localFileURL error:(NSError **)error; +/// Convenience initializer to find and open a repository with extended controls. +/// +/// localFileURL - The file URL for the new repository. Cannot be nil. +/// flags - A combination of the `GTRepositoryOpenFlags` flags. +/// ceilingDirURLs - An array of URLs at which the search for a containing +/// repository should terminate. Can be NULL. +/// error - The error if one occurs. +/// +/// Returns the initialized repository, or nil if an error occurred. +- (nullable instancetype)initWithURL:(NSURL *)localFileURL flags:(NSInteger)flags ceilingDirs:(nullable NSArray *)ceilingDirURLs error:(NSError **)error; + - (instancetype)init NS_UNAVAILABLE; /// Initializes the receiver to wrap the given repository object. Designated initializer. diff --git a/ObjectiveGit/GTRepository.m b/ObjectiveGit/GTRepository.m index fc1e22d98..3a4976bc3 100644 --- a/ObjectiveGit/GTRepository.m +++ b/ObjectiveGit/GTRepository.m @@ -177,6 +177,35 @@ - (instancetype)initWithURL:(NSURL *)localFileURL error:(NSError **)error { return [self initWithGitRepository:r]; } +- (instancetype)initWithURL:(NSURL *)localFileURL flags:(NSInteger)flags ceilingDirs:(NSArray *)ceilingDirURLs error:(NSError **)error { + if (!localFileURL.isFileURL || localFileURL.path == nil) { + if (error != NULL) *error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileReadUnsupportedSchemeError userInfo:@{ NSLocalizedDescriptionKey: NSLocalizedString(@"Invalid file path URL to open.", @"") }]; + return nil; + } + + // Concatenate URL paths. + NSMutableString *ceilingDirsString; + if (ceilingDirURLs.count > 0) { + ceilingDirsString = [[NSMutableString alloc] init]; + [ceilingDirURLs enumerateObjectsUsingBlock:^(NSURL * _Nonnull url, NSUInteger idx, BOOL * _Nonnull stop) { + if (idx < ceilingDirURLs.count - 1) { + [ceilingDirsString appendString:[NSString stringWithFormat:@"%@%c", url.path, GIT_PATH_LIST_SEPARATOR]]; + } else { + [ceilingDirsString appendString:url.path]; + } + }]; + } + + git_repository *r; + int gitError = git_repository_open_ext(&r, localFileURL.path.fileSystemRepresentation, (unsigned int)flags, ceilingDirsString.fileSystemRepresentation); + if (gitError < GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to open repository at URL %@.", localFileURL]; + return nil; + } + + return [self initWithGitRepository:r]; +} + typedef void(^GTTransferProgressBlock)(const git_transfer_progress *progress, BOOL *stop);