Skip to content

Commit 4edb350

Browse files
committed
Wrap all the various way of doing checkouts in GTCheckoutOptions
Fixes #457
1 parent 6e5a9d9 commit 4edb350

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"
@@ -54,35 +55,6 @@
5455

5556
NS_ASSUME_NONNULL_BEGIN
5657

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

75+
/// A `GTCheckoutOptions` object describing how to perform the checkout.
76+
extern NSString * const GTRepositoryCloneCheckoutOptions;
77+
10378
/// A `GTCredentialProvider`, that will be used to authenticate against the
10479
/// remote.
10580
extern NSString * const GTRepositoryCloneOptionsCredentialProvider;
@@ -216,7 +191,7 @@ extern NSString * const GTRepositoryInitOptionsOriginURLString;
216191
/// options - A dictionary consisting of the options:
217192
/// `GTRepositoryCloneOptionsTransportFlags`,
218193
/// `GTRepositoryCloneOptionsBare`,
219-
/// `GTRepositoryCloneOptionsCheckout`,
194+
/// `GTRepositoryCloneCheckoutOptions`,
220195
/// `GTRepositoryCloneOptionsCredentialProvider`,
221196
/// `GTRepositoryCloneOptionsCloneLocal`,
222197
/// `GTRepositoryCloneOptionsServerCertificateURL`
@@ -228,6 +203,9 @@ extern NSString * const GTRepositoryInitOptionsOriginURLString;
228203
/// May be NULL.
229204
///
230205
/// returns nil (and fills the error parameter) if an error occurred, or a GTRepository object if successful.
206+
+ (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;
207+
208+
/// Backward-compatible method that uses `GTRepositoryCloneOptionsCheckout`
231209
+ (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;
232210

233211
/// Lookup objects in the repo by oid or sha1
@@ -483,34 +461,20 @@ extern NSString * const GTRepositoryInitOptionsOriginURLString;
483461
/// Checkout a commit
484462
///
485463
/// targetCommit - The commit to checkout. Must not be nil.
486-
/// strategy - The checkout strategy to use.
487-
/// notifyFlags - Flags that indicate which notifications should cause `notifyBlock`
488-
/// to be called.
464+
/// options - The checkout options to use. Can be nil.
489465
/// error - The error if one occurred. Can be NULL.
490-
/// notifyBlock - The block to call back for notification handling. Can be nil.
491-
/// progressBlock - The block to call back for progress updates. Can be nil.
492466
///
493467
/// Returns YES if operation was successful, NO otherwise
494-
- (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;
468+
- (BOOL)checkoutCommit:(GTCommit *)targetCommit options:(nullable GTCheckoutOptions *)options error:(NSError **)error;
495469

496470
/// Checkout a reference
497471
///
498-
/// targetCommit - The reference to checkout.
499-
/// strategy - The checkout strategy to use.
500-
/// notifyFlags - Flags that indicate which notifications should cause `notifyBlock`
501-
/// to be called.
502-
/// error - The error if one occurred. Can be NULL.
503-
/// notifyBlock - The block to call back for notification handling. Can be nil.
504-
/// progressBlock - The block to call back for progress updates. Can be nil.
472+
/// targetReference - The reference to checkout. Must not be nil.
473+
/// options - The checkout options to use. Can be nil.
474+
/// error - The error if one occurred. Can be NULL.
505475
///
506476
/// Returns YES if operation was successful, NO otherwise
507-
- (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;
508-
509-
/// Convenience wrapper for checkoutCommit:strategy:notifyFlags:error:notifyBlock:progressBlock without notifications
510-
- (BOOL)checkoutCommit:(GTCommit *)target strategy:(GTCheckoutStrategyType)strategy error:(NSError **)error progressBlock:(nullable void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock;
511-
512-
/// Convenience wrapper for checkoutReference:strategy:notifyFlags:error:notifyBlock:progressBlock without notifications
513-
- (BOOL)checkoutReference:(GTReference *)target strategy:(GTCheckoutStrategyType)strategy error:(NSError **)error progressBlock:(nullable void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))progressBlock;
477+
- (BOOL)checkoutReference:(GTReference *)targetReference options:(nullable GTCheckoutOptions *)options error:(NSError **)error;
514478

515479
/// Flush the gitattributes cache.
516480
- (void)flushAttributesCache;

0 commit comments

Comments
 (0)