Skip to content

Commit

Permalink
Wrap all the various way of doing checkouts in GTCheckoutOptions
Browse files Browse the repository at this point in the history
Fixes #457
  • Loading branch information
tiennou committed Dec 18, 2016
1 parent 15cd2a7 commit b65755c
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 117 deletions.
63 changes: 63 additions & 0 deletions ObjectiveGit/GTCheckoutOptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// GTCheckoutOptions.h
// ObjectiveGitFramework
//
// Created by Etienne on 10/04/2015.
// Copyright (c) 2015 GitHub, Inc. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "git2/checkout.h"

@class GTDiffFile;

NS_ASSUME_NONNULL_BEGIN

/// Checkout strategies used by the various -checkout... methods
/// See git_checkout_strategy_t
typedef NS_OPTIONS(NSInteger, GTCheckoutStrategyType) {
GTCheckoutStrategyNone = GIT_CHECKOUT_NONE,
GTCheckoutStrategySafe = GIT_CHECKOUT_SAFE,
GTCheckoutStrategyForce = GIT_CHECKOUT_FORCE,
GTCheckoutStrategyAllowConflicts = GIT_CHECKOUT_ALLOW_CONFLICTS,
GTCheckoutStrategyRemoveUntracked = GIT_CHECKOUT_REMOVE_UNTRACKED,
GTCheckoutStrategyRemoveIgnored = GIT_CHECKOUT_REMOVE_IGNORED,
GTCheckoutStrategyUpdateOnly = GIT_CHECKOUT_UPDATE_ONLY,
GTCheckoutStrategyDontUpdateIndex = GIT_CHECKOUT_DONT_UPDATE_INDEX,
GTCheckoutStrategyNoRefresh = GIT_CHECKOUT_NO_REFRESH,
GTCheckoutStrategyDisablePathspecMatch = GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH,
GTCheckoutStrategySkipLockedDirectories = GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES,
};

/// Checkout notification flags used by the various -checkout... methods
/// See git_checkout_notify_t
typedef NS_OPTIONS(NSInteger, GTCheckoutNotifyFlags) {
GTCheckoutNotifyNone = GIT_CHECKOUT_NOTIFY_NONE,
GTCheckoutNotifyConflict = GIT_CHECKOUT_NOTIFY_CONFLICT,
GTCheckoutNotifyDirty = GIT_CHECKOUT_NOTIFY_DIRTY,
GTCheckoutNotifyUpdated = GIT_CHECKOUT_NOTIFY_UPDATED,
GTCheckoutNotifyUntracked = GIT_CHECKOUT_NOTIFY_UNTRACKED,
GTCheckoutNotifyIgnored = GIT_CHECKOUT_NOTIFY_IGNORED,

GTCheckoutNotifyAll = GIT_CHECKOUT_NOTIFY_ALL,
};

@interface GTCheckoutOptions : NSObject
+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy notifyFlags:(GTCheckoutNotifyFlags)notifyFlags progressBlock:(nullable void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock notifyBlock:(nullable int (^)(GTCheckoutNotifyFlags why, NSString *path, GTDiffFile *baseline, GTDiffFile *target, GTDiffFile *workdir))notifyBlock;

+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy notifyFlags:(GTCheckoutNotifyFlags)notifyFlags notifyBlock:(int (^)(GTCheckoutNotifyFlags why, NSString *path, GTDiffFile *baseline, GTDiffFile *target, GTDiffFile *workdir))notifyBlock;

+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy progressBlock:(void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock;

+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy;

- (git_checkout_options *)git_checkoutOptions NS_RETURNS_INNER_POINTER;

@property (assign) GTCheckoutStrategyType strategy;
@property (copy) void (^progressBlock)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps);

@property (assign) GTCheckoutNotifyFlags notifyFlags;
@property (copy) int (^notifyBlock)(GTCheckoutNotifyFlags why, NSString *path, GTDiffFile *baseline, GTDiffFile *target, GTDiffFile *workdir);
@end

NS_ASSUME_NONNULL_END
97 changes: 97 additions & 0 deletions ObjectiveGit/GTCheckoutOptions.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// GTCheckoutOptions.m
// ObjectiveGitFramework
//
// Created by Etienne on 10/04/2015.
// Copyright (c) 2015 GitHub, Inc. All rights reserved.
//

#import "GTCheckoutOptions.h"
#import "GTDiffFile.h"
#import "NSError+Git.h"
#import "git2.h"

// The type of block set in progressBlock for progress reporting
typedef void (^GTCheckoutProgressBlock)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps);

// The type of block set in notifyBlock for notification reporting
typedef int (^GTCheckoutNotifyBlock)(GTCheckoutNotifyFlags why, NSString *path, GTDiffFile * __nullable baseline, GTDiffFile * __nullable target, GTDiffFile * __nullable workdir);


@interface GTCheckoutOptions () {
git_checkout_options _git_checkoutOptions;
}
@end

@implementation GTCheckoutOptions

+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy notifyFlags:(GTCheckoutNotifyFlags)notifyFlags progressBlock:(nullable GTCheckoutProgressBlock)progressBlock notifyBlock:(nullable GTCheckoutNotifyBlock)notifyBlock {
GTCheckoutOptions *options = [self checkoutOptionsWithStrategy:strategy];
options.notifyFlags = notifyFlags;
options.notifyBlock = notifyBlock;
options.progressBlock = progressBlock;
return options;
}

+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy progressBlock:(GTCheckoutProgressBlock)progressBlock {
NSParameterAssert(progressBlock != nil);
GTCheckoutOptions *options = [self checkoutOptionsWithStrategy:strategy];
options.progressBlock = progressBlock;
return options;
}

+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy notifyFlags:(GTCheckoutNotifyFlags)notifyFlags notifyBlock:(GTCheckoutNotifyBlock)notifyBlock {
NSParameterAssert(notifyBlock != nil);
return [self checkoutOptionsWithStrategy:strategy notifyFlags:notifyFlags progressBlock:nil notifyBlock:notifyBlock];
}

+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy {
GTCheckoutOptions *options = [[self alloc] init];
options.strategy = strategy;
return options;
}

- (instancetype)init {
self = [super init];
if (self == nil) return nil;

_git_checkoutOptions.version = GIT_CHECKOUT_OPTIONS_VERSION;

return self;
}

static void GTCheckoutProgressCallback(const char *path, size_t completedSteps, size_t totalSteps, void *payload) {
if (payload == NULL) return;
void (^block)(NSString *, NSUInteger, NSUInteger) = (__bridge id)payload;
NSString *nsPath = (path != NULL ? [NSString stringWithUTF8String:path] : nil);
block(nsPath, completedSteps, totalSteps);
}

static int GTCheckoutNotifyCallback(git_checkout_notify_t why, const char *path, const git_diff_file *baseline, const git_diff_file *target, const git_diff_file *workdir, void *payload) {
if (payload == NULL) return 0;
GTCheckoutNotifyBlock block = (__bridge id)payload;
NSString *nsPath = (path != NULL ? @(path) : nil);
GTDiffFile *gtBaseline = (baseline != NULL ? [[GTDiffFile alloc] initWithGitDiffFile:*baseline] : nil);
GTDiffFile *gtTarget = (target != NULL ? [[GTDiffFile alloc] initWithGitDiffFile:*target] : nil);
GTDiffFile *gtWorkdir = (workdir != NULL ? [[GTDiffFile alloc] initWithGitDiffFile:*workdir] : nil);
return block((GTCheckoutNotifyFlags)why, nsPath, gtBaseline, gtTarget, gtWorkdir);
}

- (git_checkout_options *)git_checkoutOptions {
_git_checkoutOptions.checkout_strategy = self.strategy;

if (self.progressBlock) {
_git_checkoutOptions.progress_cb = GTCheckoutProgressCallback;
_git_checkoutOptions.progress_payload = (__bridge void *)self.progressBlock;
}

if (self.notifyBlock) {
_git_checkoutOptions.notify_cb = GTCheckoutNotifyCallback;
_git_checkoutOptions.notify_flags = self.notifyFlags;
_git_checkoutOptions.notify_payload = (__bridge void *)self.notifyBlock;
}

return &_git_checkoutOptions;
}

@end
64 changes: 14 additions & 50 deletions ObjectiveGit/GTRepository.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#import "GTObject.h"
#import "GTReference.h"
#import "GTFilterList.h"
#import "GTCheckoutOptions.h"
#import "git2/checkout.h"
#import "git2/repository.h"
#import "git2/transport.h"
Expand All @@ -55,35 +56,6 @@

NS_ASSUME_NONNULL_BEGIN

/// Checkout strategies used by the various -checkout... methods
/// See git_checkout_strategy_t
typedef NS_OPTIONS(NSInteger, GTCheckoutStrategyType) {
GTCheckoutStrategyNone = GIT_CHECKOUT_NONE,
GTCheckoutStrategySafe = GIT_CHECKOUT_SAFE,
GTCheckoutStrategyForce = GIT_CHECKOUT_FORCE,
GTCheckoutStrategyAllowConflicts = GIT_CHECKOUT_ALLOW_CONFLICTS,
GTCheckoutStrategyRemoveUntracked = GIT_CHECKOUT_REMOVE_UNTRACKED,
GTCheckoutStrategyRemoveIgnored = GIT_CHECKOUT_REMOVE_IGNORED,
GTCheckoutStrategyUpdateOnly = GIT_CHECKOUT_UPDATE_ONLY,
GTCheckoutStrategyDontUpdateIndex = GIT_CHECKOUT_DONT_UPDATE_INDEX,
GTCheckoutStrategyNoRefresh = GIT_CHECKOUT_NO_REFRESH,
GTCheckoutStrategyDisablePathspecMatch = GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH,
GTCheckoutStrategySkipLockedDirectories = GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES,
};

/// Checkout notification flags used by the various -checkout... methods
/// See git_checkout_notify_t
typedef NS_OPTIONS(NSInteger, GTCheckoutNotifyFlags) {
GTCheckoutNotifyNone = GIT_CHECKOUT_NOTIFY_NONE,
GTCheckoutNotifyConflict = GIT_CHECKOUT_NOTIFY_CONFLICT,
GTCheckoutNotifyDirty = GIT_CHECKOUT_NOTIFY_DIRTY,
GTCheckoutNotifyUpdated = GIT_CHECKOUT_NOTIFY_UPDATED,
GTCheckoutNotifyUntracked = GIT_CHECKOUT_NOTIFY_UNTRACKED,
GTCheckoutNotifyIgnored = GIT_CHECKOUT_NOTIFY_IGNORED,

GTCheckoutNotifyAll = GIT_CHECKOUT_NOTIFY_ALL,
};

/// Transport flags sent as options to +cloneFromURL... method
typedef NS_OPTIONS(NSInteger, GTTransportFlags) {
GTTransportFlagsNone = GIT_TRANSPORTFLAGS_NONE
Expand All @@ -101,6 +73,9 @@ extern NSString * const GTRepositoryCloneOptionsBare;
/// Default value is `YES`.
extern NSString * const GTRepositoryCloneOptionsCheckout;

/// A `GTCheckoutOptions` object describing how to perform the checkout.
extern NSString * const GTRepositoryCloneCheckoutOptions;

/// A `GTCredentialProvider`, that will be used to authenticate against the
/// remote.
extern NSString * const GTRepositoryCloneOptionsCredentialProvider;
Expand Down Expand Up @@ -253,7 +228,7 @@ typedef NS_ENUM(NSInteger, GTRepositoryStateType) {
/// options - A dictionary consisting of the options:
/// `GTRepositoryCloneOptionsTransportFlags`,
/// `GTRepositoryCloneOptionsBare`,
/// `GTRepositoryCloneOptionsCheckout`,
/// `GTRepositoryCloneCheckoutOptions`,
/// `GTRepositoryCloneOptionsCredentialProvider`,
/// `GTRepositoryCloneOptionsCloneLocal`,
/// `GTRepositoryCloneOptionsServerCertificateURL`
Expand All @@ -265,6 +240,9 @@ typedef NS_ENUM(NSInteger, GTRepositoryStateType) {
/// May be NULL.
///
/// returns nil (and fills the error parameter) if an error occurred, or a GTRepository object if successful.
+ (nullable instancetype)cloneFromURL:(NSURL *)originURL toWorkingDirectory:(NSURL *)workdirURL options:(nullable NSDictionary *)options error:(NSError **)error transferProgressBlock:(nullable void (^)(const git_transfer_progress *, BOOL *stop))transferProgressBlock;

/// Backward-compatible method that uses `GTRepositoryCloneOptionsCheckout`
+ (nullable instancetype)cloneFromURL:(NSURL *)originURL toWorkingDirectory:(NSURL *)workdirURL options:(nullable NSDictionary *)options error:(NSError **)error transferProgressBlock:(nullable void (^)(const git_transfer_progress *, BOOL *stop))transferProgressBlock checkoutProgressBlock:(nullable void (^) (NSString *__nullable path, NSUInteger completedSteps, NSUInteger totalSteps))checkoutProgressBlock;

/// Lookup objects in the repo by oid or sha1
Expand Down Expand Up @@ -536,34 +514,20 @@ typedef NS_ENUM(NSInteger, GTRepositoryStateType) {
/// Checkout a commit
///
/// targetCommit - The commit to checkout. Must not be nil.
/// strategy - The checkout strategy to use.
/// notifyFlags - Flags that indicate which notifications should cause `notifyBlock`
/// to be called.
/// options - The checkout options to use. Can be nil.
/// error - The error if one occurred. Can be NULL.
/// notifyBlock - The block to call back for notification handling. Can be nil.
/// progressBlock - The block to call back for progress updates. Can be nil.
///
/// Returns YES if operation was successful, NO otherwise
- (BOOL)checkoutCommit:(GTCommit *)targetCommit strategy:(GTCheckoutStrategyType)strategy notifyFlags:(GTCheckoutNotifyFlags)notifyFlags error:(NSError **)error progressBlock:(nullable void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock notifyBlock:(nullable int (^)(GTCheckoutNotifyFlags why, NSString *path, GTDiffFile *baseline, GTDiffFile *target, GTDiffFile *workdir))notifyBlock;
- (BOOL)checkoutCommit:(GTCommit *)targetCommit options:(nullable GTCheckoutOptions *)options error:(NSError **)error;

/// Checkout a reference
///
/// targetCommit - The reference to checkout.
/// strategy - The checkout strategy to use.
/// notifyFlags - Flags that indicate which notifications should cause `notifyBlock`
/// to be called.
/// error - The error if one occurred. Can be NULL.
/// notifyBlock - The block to call back for notification handling. Can be nil.
/// progressBlock - The block to call back for progress updates. Can be nil.
/// targetReference - The reference to checkout. Must not be nil.
/// options - The checkout options to use. Can be nil.
/// error - The error if one occurred. Can be NULL.
///
/// Returns YES if operation was successful, NO otherwise
- (BOOL)checkoutReference:(GTReference *)targetReference strategy:(GTCheckoutStrategyType)strategy notifyFlags:(GTCheckoutNotifyFlags)notifyFlags error:(NSError **)error progressBlock:(nullable void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock notifyBlock:(nullable int (^)(GTCheckoutNotifyFlags why, NSString *path, GTDiffFile *baseline, GTDiffFile *target, GTDiffFile *workdir))notifyBlock;

/// Convenience wrapper for checkoutCommit:strategy:notifyFlags:error:notifyBlock:progressBlock without notifications
- (BOOL)checkoutCommit:(GTCommit *)target strategy:(GTCheckoutStrategyType)strategy error:(NSError **)error progressBlock:(nullable void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock;

/// Convenience wrapper for checkoutReference:strategy:notifyFlags:error:notifyBlock:progressBlock without notifications
- (BOOL)checkoutReference:(GTReference *)target strategy:(GTCheckoutStrategyType)strategy error:(NSError **)error progressBlock:(nullable void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock;
- (BOOL)checkoutReference:(GTReference *)targetReference options:(nullable GTCheckoutOptions *)options error:(NSError **)error;

/// Flush the gitattributes cache.
- (void)flushAttributesCache;
Expand Down
Loading

0 comments on commit b65755c

Please sign in to comment.