Skip to content

Commit 311ca45

Browse files
committed
Wrap all the various way of doing checkouts in GTCheckoutOptions
Fixes #457
1 parent 8dc3d41 commit 311ca45

File tree

9 files changed

+233
-117
lines changed

9 files changed

+233
-117
lines changed

ObjectiveGit/GTCheckoutOptions.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// GTCheckoutOptions.h
3+
// ObjectiveGitFramework
4+
//
5+
// Created by Etienne on 10/04/2015.
6+
// Copyright (c) 2015 GitHub, Inc. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
#import "git2/checkout.h"
11+
12+
@class GTDiffFile;
13+
14+
NS_ASSUME_NONNULL_BEGIN
15+
16+
/// Checkout strategies used by the various -checkout... methods
17+
/// See git_checkout_strategy_t
18+
typedef NS_OPTIONS(NSInteger, GTCheckoutStrategyType) {
19+
GTCheckoutStrategyNone = GIT_CHECKOUT_NONE,
20+
GTCheckoutStrategySafe = GIT_CHECKOUT_SAFE,
21+
GTCheckoutStrategyForce = GIT_CHECKOUT_FORCE,
22+
GTCheckoutStrategyAllowConflicts = GIT_CHECKOUT_ALLOW_CONFLICTS,
23+
GTCheckoutStrategyRemoveUntracked = GIT_CHECKOUT_REMOVE_UNTRACKED,
24+
GTCheckoutStrategyRemoveIgnored = GIT_CHECKOUT_REMOVE_IGNORED,
25+
GTCheckoutStrategyUpdateOnly = GIT_CHECKOUT_UPDATE_ONLY,
26+
GTCheckoutStrategyDontUpdateIndex = GIT_CHECKOUT_DONT_UPDATE_INDEX,
27+
GTCheckoutStrategyNoRefresh = GIT_CHECKOUT_NO_REFRESH,
28+
GTCheckoutStrategyDisablePathspecMatch = GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH,
29+
GTCheckoutStrategySkipLockedDirectories = GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES,
30+
};
31+
32+
/// Checkout notification flags used by the various -checkout... methods
33+
/// See git_checkout_notify_t
34+
typedef NS_OPTIONS(NSInteger, GTCheckoutNotifyFlags) {
35+
GTCheckoutNotifyNone = GIT_CHECKOUT_NOTIFY_NONE,
36+
GTCheckoutNotifyConflict = GIT_CHECKOUT_NOTIFY_CONFLICT,
37+
GTCheckoutNotifyDirty = GIT_CHECKOUT_NOTIFY_DIRTY,
38+
GTCheckoutNotifyUpdated = GIT_CHECKOUT_NOTIFY_UPDATED,
39+
GTCheckoutNotifyUntracked = GIT_CHECKOUT_NOTIFY_UNTRACKED,
40+
GTCheckoutNotifyIgnored = GIT_CHECKOUT_NOTIFY_IGNORED,
41+
42+
GTCheckoutNotifyAll = GIT_CHECKOUT_NOTIFY_ALL,
43+
};
44+
45+
@interface GTCheckoutOptions : NSObject
46+
+ (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;
47+
48+
+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy notifyFlags:(GTCheckoutNotifyFlags)notifyFlags notifyBlock:(int (^)(GTCheckoutNotifyFlags why, NSString *path, GTDiffFile *baseline, GTDiffFile *target, GTDiffFile *workdir))notifyBlock;
49+
50+
+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy progressBlock:(void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock;
51+
52+
+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy;
53+
54+
- (git_checkout_options *)git_checkoutOptions NS_RETURNS_INNER_POINTER;
55+
56+
@property (assign) GTCheckoutStrategyType strategy;
57+
@property (copy) void (^progressBlock)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps);
58+
59+
@property (assign) GTCheckoutNotifyFlags notifyFlags;
60+
@property (copy) int (^notifyBlock)(GTCheckoutNotifyFlags why, NSString *path, GTDiffFile *baseline, GTDiffFile *target, GTDiffFile *workdir);
61+
@end
62+
63+
NS_ASSUME_NONNULL_END

ObjectiveGit/GTCheckoutOptions.m

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//
2+
// GTCheckoutOptions.m
3+
// ObjectiveGitFramework
4+
//
5+
// Created by Etienne on 10/04/2015.
6+
// Copyright (c) 2015 GitHub, Inc. All rights reserved.
7+
//
8+
9+
#import "GTCheckoutOptions.h"
10+
#import "GTDiffFile.h"
11+
#import "NSError+Git.h"
12+
#import "git2.h"
13+
14+
// The type of block set in progressBlock for progress reporting
15+
typedef void (^GTCheckoutProgressBlock)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps);
16+
17+
// The type of block set in notifyBlock for notification reporting
18+
typedef int (^GTCheckoutNotifyBlock)(GTCheckoutNotifyFlags why, NSString *path, GTDiffFile * __nullable baseline, GTDiffFile * __nullable target, GTDiffFile * __nullable workdir);
19+
20+
21+
@interface GTCheckoutOptions () {
22+
git_checkout_options _git_checkoutOptions;
23+
}
24+
@end
25+
26+
@implementation GTCheckoutOptions
27+
28+
+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy notifyFlags:(GTCheckoutNotifyFlags)notifyFlags progressBlock:(nullable GTCheckoutProgressBlock)progressBlock notifyBlock:(nullable GTCheckoutNotifyBlock)notifyBlock {
29+
GTCheckoutOptions *options = [self checkoutOptionsWithStrategy:strategy];
30+
options.notifyFlags = notifyFlags;
31+
options.notifyBlock = notifyBlock;
32+
options.progressBlock = progressBlock;
33+
return options;
34+
}
35+
36+
+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy progressBlock:(GTCheckoutProgressBlock)progressBlock {
37+
NSParameterAssert(progressBlock != nil);
38+
GTCheckoutOptions *options = [self checkoutOptionsWithStrategy:strategy];
39+
options.progressBlock = progressBlock;
40+
return options;
41+
}
42+
43+
+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy notifyFlags:(GTCheckoutNotifyFlags)notifyFlags notifyBlock:(GTCheckoutNotifyBlock)notifyBlock {
44+
NSParameterAssert(notifyBlock != nil);
45+
return [self checkoutOptionsWithStrategy:strategy notifyFlags:notifyFlags progressBlock:nil notifyBlock:notifyBlock];
46+
}
47+
48+
+ (instancetype)checkoutOptionsWithStrategy:(GTCheckoutStrategyType)strategy {
49+
GTCheckoutOptions *options = [[self alloc] init];
50+
options.strategy = strategy;
51+
return options;
52+
}
53+
54+
- (instancetype)init {
55+
self = [super init];
56+
if (self == nil) return nil;
57+
58+
_git_checkoutOptions.version = GIT_CHECKOUT_OPTIONS_VERSION;
59+
60+
return self;
61+
}
62+
63+
static void GTCheckoutProgressCallback(const char *path, size_t completedSteps, size_t totalSteps, void *payload) {
64+
if (payload == NULL) return;
65+
void (^block)(NSString *, NSUInteger, NSUInteger) = (__bridge id)payload;
66+
NSString *nsPath = (path != NULL ? [NSString stringWithUTF8String:path] : nil);
67+
block(nsPath, completedSteps, totalSteps);
68+
}
69+
70+
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) {
71+
if (payload == NULL) return 0;
72+
GTCheckoutNotifyBlock block = (__bridge id)payload;
73+
NSString *nsPath = (path != NULL ? @(path) : nil);
74+
GTDiffFile *gtBaseline = (baseline != NULL ? [[GTDiffFile alloc] initWithGitDiffFile:*baseline] : nil);
75+
GTDiffFile *gtTarget = (target != NULL ? [[GTDiffFile alloc] initWithGitDiffFile:*target] : nil);
76+
GTDiffFile *gtWorkdir = (workdir != NULL ? [[GTDiffFile alloc] initWithGitDiffFile:*workdir] : nil);
77+
return block((GTCheckoutNotifyFlags)why, nsPath, gtBaseline, gtTarget, gtWorkdir);
78+
}
79+
80+
- (git_checkout_options *)git_checkoutOptions {
81+
_git_checkoutOptions.checkout_strategy = self.strategy;
82+
83+
if (self.progressBlock) {
84+
_git_checkoutOptions.progress_cb = GTCheckoutProgressCallback;
85+
_git_checkoutOptions.progress_payload = (__bridge void *)self.progressBlock;
86+
}
87+
88+
if (self.notifyBlock) {
89+
_git_checkoutOptions.notify_cb = GTCheckoutNotifyCallback;
90+
_git_checkoutOptions.notify_flags = self.notifyFlags;
91+
_git_checkoutOptions.notify_payload = (__bridge void *)self.notifyBlock;
92+
}
93+
94+
return &_git_checkoutOptions;
95+
}
96+
97+
@end

ObjectiveGit/GTRepository.h

Lines changed: 14 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#import "GTObject.h"
3535
#import "GTReference.h"
3636
#import "GTFilterList.h"
37+
#import "GTCheckoutOptions.h"
3738
#import "git2/checkout.h"
3839
#import "git2/repository.h"
3940
#import "git2/transport.h"
@@ -55,35 +56,6 @@
5556

5657
NS_ASSUME_NONNULL_BEGIN
5758

58-
/// Checkout strategies used by the various -checkout... methods
59-
/// See git_checkout_strategy_t
60-
typedef NS_OPTIONS(NSInteger, GTCheckoutStrategyType) {
61-
GTCheckoutStrategyNone = GIT_CHECKOUT_NONE,
62-
GTCheckoutStrategySafe = GIT_CHECKOUT_SAFE,
63-
GTCheckoutStrategyForce = GIT_CHECKOUT_FORCE,
64-
GTCheckoutStrategyAllowConflicts = GIT_CHECKOUT_ALLOW_CONFLICTS,
65-
GTCheckoutStrategyRemoveUntracked = GIT_CHECKOUT_REMOVE_UNTRACKED,
66-
GTCheckoutStrategyRemoveIgnored = GIT_CHECKOUT_REMOVE_IGNORED,
67-
GTCheckoutStrategyUpdateOnly = GIT_CHECKOUT_UPDATE_ONLY,
68-
GTCheckoutStrategyDontUpdateIndex = GIT_CHECKOUT_DONT_UPDATE_INDEX,
69-
GTCheckoutStrategyNoRefresh = GIT_CHECKOUT_NO_REFRESH,
70-
GTCheckoutStrategyDisablePathspecMatch = GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH,
71-
GTCheckoutStrategySkipLockedDirectories = GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES,
72-
};
73-
74-
/// Checkout notification flags used by the various -checkout... methods
75-
/// See git_checkout_notify_t
76-
typedef NS_OPTIONS(NSInteger, GTCheckoutNotifyFlags) {
77-
GTCheckoutNotifyNone = GIT_CHECKOUT_NOTIFY_NONE,
78-
GTCheckoutNotifyConflict = GIT_CHECKOUT_NOTIFY_CONFLICT,
79-
GTCheckoutNotifyDirty = GIT_CHECKOUT_NOTIFY_DIRTY,
80-
GTCheckoutNotifyUpdated = GIT_CHECKOUT_NOTIFY_UPDATED,
81-
GTCheckoutNotifyUntracked = GIT_CHECKOUT_NOTIFY_UNTRACKED,
82-
GTCheckoutNotifyIgnored = GIT_CHECKOUT_NOTIFY_IGNORED,
83-
84-
GTCheckoutNotifyAll = GIT_CHECKOUT_NOTIFY_ALL,
85-
};
86-
8759
/// Transport flags sent as options to +cloneFromURL... method
8860
typedef NS_OPTIONS(NSInteger, GTTransportFlags) {
8961
GTTransportFlagsNone = GIT_TRANSPORTFLAGS_NONE
@@ -101,6 +73,9 @@ extern NSString * const GTRepositoryCloneOptionsBare;
10173
/// Default value is `YES`.
10274
extern NSString * const GTRepositoryCloneOptionsCheckout;
10375

76+
/// A `GTCheckoutOptions` object describing how to perform the checkout.
77+
extern NSString * const GTRepositoryCloneCheckoutOptions;
78+
10479
/// A `GTCredentialProvider`, that will be used to authenticate against the
10580
/// remote.
10681
extern NSString * const GTRepositoryCloneOptionsCredentialProvider;
@@ -253,7 +228,7 @@ typedef NS_ENUM(NSInteger, GTRepositoryStateType) {
253228
/// options - A dictionary consisting of the options:
254229
/// `GTRepositoryCloneOptionsTransportFlags`,
255230
/// `GTRepositoryCloneOptionsBare`,
256-
/// `GTRepositoryCloneOptionsCheckout`,
231+
/// `GTRepositoryCloneCheckoutOptions`,
257232
/// `GTRepositoryCloneOptionsCredentialProvider`,
258233
/// `GTRepositoryCloneOptionsCloneLocal`,
259234
/// `GTRepositoryCloneOptionsServerCertificateURL`
@@ -265,6 +240,9 @@ typedef NS_ENUM(NSInteger, GTRepositoryStateType) {
265240
/// May be NULL.
266241
///
267242
/// returns nil (and fills the error parameter) if an error occurred, or a GTRepository object if successful.
243+
+ (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;
244+
245+
/// Backward-compatible method that uses `GTRepositoryCloneOptionsCheckout`
268246
+ (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;
269247

270248
/// Lookup objects in the repo by oid or sha1
@@ -536,34 +514,20 @@ typedef NS_ENUM(NSInteger, GTRepositoryStateType) {
536514
/// Checkout a commit
537515
///
538516
/// targetCommit - The commit to checkout. Must not be nil.
539-
/// strategy - The checkout strategy to use.
540-
/// notifyFlags - Flags that indicate which notifications should cause `notifyBlock`
541-
/// to be called.
517+
/// options - The checkout options to use. Can be nil.
542518
/// error - The error if one occurred. Can be NULL.
543-
/// notifyBlock - The block to call back for notification handling. Can be nil.
544-
/// progressBlock - The block to call back for progress updates. Can be nil.
545519
///
546520
/// Returns YES if operation was successful, NO otherwise
547-
- (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;
521+
- (BOOL)checkoutCommit:(GTCommit *)targetCommit options:(nullable GTCheckoutOptions *)options error:(NSError **)error;
548522

549523
/// Checkout a reference
550524
///
551-
/// targetCommit - The reference to checkout.
552-
/// strategy - The checkout strategy to use.
553-
/// notifyFlags - Flags that indicate which notifications should cause `notifyBlock`
554-
/// to be called.
555-
/// error - The error if one occurred. Can be NULL.
556-
/// notifyBlock - The block to call back for notification handling. Can be nil.
557-
/// progressBlock - The block to call back for progress updates. Can be nil.
525+
/// targetReference - The reference to checkout. Must not be nil.
526+
/// options - The checkout options to use. Can be nil.
527+
/// error - The error if one occurred. Can be NULL.
558528
///
559529
/// Returns YES if operation was successful, NO otherwise
560-
- (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;
561-
562-
/// Convenience wrapper for checkoutCommit:strategy:notifyFlags:error:notifyBlock:progressBlock without notifications
563-
- (BOOL)checkoutCommit:(GTCommit *)target strategy:(GTCheckoutStrategyType)strategy error:(NSError **)error progressBlock:(nullable void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock;
564-
565-
/// Convenience wrapper for checkoutReference:strategy:notifyFlags:error:notifyBlock:progressBlock without notifications
566-
- (BOOL)checkoutReference:(GTReference *)target strategy:(GTCheckoutStrategyType)strategy error:(NSError **)error progressBlock:(nullable void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock;
530+
- (BOOL)checkoutReference:(GTReference *)targetReference options:(nullable GTCheckoutOptions *)options error:(NSError **)error;
567531

568532
/// Flush the gitattributes cache.
569533
- (void)flushAttributesCache;

0 commit comments

Comments
 (0)