Skip to content

Commit c6f9784

Browse files
committed
Revert d56bd92..5068116
This rolls back to commit d56bd92.
1 parent 5068116 commit c6f9784

40 files changed

+1103
-434
lines changed

ObjectiveGit.modulemap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ framework module ObjectiveGit {
4747
header "git2/status.h"
4848
header "git2/submodule.h"
4949
header "git2/tag.h"
50+
header "git2/threads.h"
5051
header "git2/transport.h"
5152
header "git2/tree.h"
5253
header "git2/types.h"
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//
2+
// GTRepository+RemoteOperations.h
3+
// ObjectiveGitFramework
4+
//
5+
// Created by Etienne on 18/11/13.
6+
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
7+
//
8+
9+
#import "GTRepository.h"
10+
11+
@class GTFetchHeadEntry;
12+
13+
/// A `GTCredentialProvider`, that will be used to authenticate against the remote.
14+
extern NSString *const GTRepositoryRemoteOptionsCredentialProvider;
15+
16+
@interface GTRepository (RemoteOperations)
17+
18+
#pragma mark - Fetch
19+
20+
/// Fetch a remote.
21+
///
22+
/// remote - The remote to fetch from.
23+
/// options - Options applied to the fetch operation.
24+
/// Recognized options are :
25+
/// `GTRepositoryRemoteOptionsCredentialProvider`
26+
/// error - The error if one occurred. Can be NULL.
27+
///
28+
/// Returns YES if the fetch was successful, NO otherwise (and `error`, if provided,
29+
/// will point to an error describing what happened).
30+
- (BOOL)fetchRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(void (^)(const git_transfer_progress *stats, BOOL *stop))progressBlock;
31+
32+
/// Enumerate all available fetch head entries.
33+
///
34+
/// error - The error if one ocurred. Can be NULL.
35+
/// block - A block to execute for each FETCH_HEAD entry. `fetchHeadEntry` will be the current
36+
/// fetch head entry. Setting `stop` to YES will cause enumeration to stop after the block returns.
37+
///
38+
/// Returns YES if the operation succedded, NO otherwise.
39+
- (BOOL)enumerateFetchHeadEntriesWithError:(NSError **)error usingBlock:(void (^)(GTFetchHeadEntry *fetchHeadEntry, BOOL *stop))block;
40+
41+
/// Convenience method for -enumerateFetchHeadEntriesWithError:usingBlock: that retuns an NSArray with all the fetch head entries.
42+
///
43+
/// error - The error if one ocurred. Can be NULL.
44+
///
45+
/// Retruns an array with GTFetchHeadEntry objects
46+
- (NSArray *)fetchHeadEntriesWithError:(NSError **)error;
47+
48+
#pragma mark - Push
49+
50+
/// Push a single branch to a remote.
51+
///
52+
/// branch - The branch to push.
53+
/// remote - The remote to push to.
54+
/// options - Options applied to the push operation.
55+
/// Recognized options are:
56+
/// `GTRepositoryRemoteOptionsCredentialProvider`
57+
/// error - The error if one occurred. Can be NULL.
58+
/// progressBlock - An optional callback for monitoring progress.
59+
///
60+
/// Returns YES if the push was successful, NO otherwise (and `error`, if provided,
61+
/// will point to an error describing what happened).
62+
- (BOOL)pushBranch:(GTBranch *)branch toRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(void (^)(unsigned int current, unsigned int total, size_t bytes, BOOL *stop))progressBlock;
63+
64+
/// Push an array of branches to a remote.
65+
///
66+
/// branches - An array of branches to push.
67+
/// remote - The remote to push to.
68+
/// options - Options applied to the push operation.
69+
/// Recognized options are:
70+
/// `GTRepositoryRemoteOptionsCredentialProvider`
71+
/// error - The error if one occurred. Can be NULL.
72+
/// progressBlock - An optional callback for monitoring progress.
73+
///
74+
/// Returns YES if the push was successful, NO otherwise (and `error`, if provided,
75+
/// will point to an error describing what happened).
76+
- (BOOL)pushBranches:(NSArray *)branches toRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(void (^)(unsigned int current, unsigned int total, size_t bytes, BOOL *stop))progressBlock;
77+
78+
@end
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
//
2+
// GTRepository+RemoteOperations.m
3+
// ObjectiveGitFramework
4+
//
5+
// Created by Etienne on 18/11/13.
6+
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
7+
//
8+
9+
#import "GTRepository+RemoteOperations.h"
10+
11+
#import "EXTScope.h"
12+
#import "GTCredential.h"
13+
#import "GTCredential+Private.h"
14+
#import "GTFetchHeadEntry.h"
15+
#import "GTOID.h"
16+
#import "GTRemote.h"
17+
#import "GTSignature.h"
18+
#import "NSError+Git.h"
19+
20+
#import "git2/errors.h"
21+
#import "git2/remote.h"
22+
#import "git2/push.h"
23+
24+
NSString *const GTRepositoryRemoteOptionsCredentialProvider = @"GTRepositoryRemoteOptionsCredentialProvider";
25+
26+
typedef void (^GTRemoteFetchTransferProgressBlock)(const git_transfer_progress *stats, BOOL *stop);
27+
typedef void (^GTRemotePushTransferProgressBlock)(unsigned int current, unsigned int total, size_t bytes, BOOL *stop);
28+
29+
@implementation GTRepository (RemoteOperations)
30+
31+
#pragma mark -
32+
#pragma mark Common Remote code
33+
34+
typedef struct {
35+
GTCredentialAcquireCallbackInfo credProvider;
36+
__unsafe_unretained GTRemoteFetchTransferProgressBlock fetchProgressBlock;
37+
__unsafe_unretained GTRemotePushTransferProgressBlock pushProgressBlock;
38+
git_direction direction;
39+
} GTRemoteConnectionInfo;
40+
41+
int GTRemoteFetchTransferProgressCallback(const git_transfer_progress *stats, void *payload) {
42+
GTRemoteConnectionInfo *info = payload;
43+
BOOL stop = NO;
44+
45+
if (info->fetchProgressBlock != nil) {
46+
info->fetchProgressBlock(stats, &stop);
47+
}
48+
49+
return (stop == YES ? GIT_EUSER : 0);
50+
}
51+
52+
int GTRemotePushTransferProgressCallback(unsigned int current, unsigned int total, size_t bytes, void *payload) {
53+
GTRemoteConnectionInfo *pushPayload = payload;
54+
55+
BOOL stop = NO;
56+
if (pushPayload->pushProgressBlock) {
57+
pushPayload->pushProgressBlock(current, total, bytes, &stop);
58+
}
59+
60+
return (stop == YES ? GIT_EUSER : 0);
61+
}
62+
63+
static int GTRemotePushRefspecStatusCallback(const char *ref, const char *msg, void *data) {
64+
if (msg != NULL) {
65+
return GIT_ERROR;
66+
}
67+
68+
return GIT_OK;
69+
}
70+
71+
#pragma mark -
72+
#pragma mark Fetch
73+
74+
- (BOOL)fetchRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock {
75+
GTCredentialProvider *credProvider = options[GTRepositoryRemoteOptionsCredentialProvider];
76+
GTRemoteConnectionInfo connectionInfo = {
77+
.credProvider = {credProvider},
78+
.direction = GIT_DIRECTION_FETCH,
79+
.fetchProgressBlock = progressBlock,
80+
};
81+
git_remote_callbacks remote_callbacks = {
82+
.version = GIT_REMOTE_CALLBACKS_VERSION,
83+
.credentials = (credProvider != nil ? GTCredentialAcquireCallback : NULL),
84+
.transfer_progress = GTRemoteFetchTransferProgressCallback,
85+
.payload = &connectionInfo,
86+
};
87+
88+
int gitError = git_remote_set_callbacks(remote.git_remote, &remote_callbacks);
89+
if (gitError != GIT_OK) {
90+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to set callbacks on remote"];
91+
return NO;
92+
}
93+
94+
__block git_strarray refspecs;
95+
gitError = git_remote_get_fetch_refspecs(&refspecs, remote.git_remote);
96+
if (gitError != GIT_OK) {
97+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to get fetch refspecs for remote"];
98+
return NO;
99+
}
100+
101+
@onExit {
102+
git_strarray_free(&refspecs);
103+
};
104+
105+
gitError = git_remote_fetch(remote.git_remote, &refspecs, self.userSignatureForNow.git_signature, NULL);
106+
if (gitError != GIT_OK) {
107+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to fetch from remote"];
108+
return NO;
109+
}
110+
111+
return YES;
112+
}
113+
114+
#pragma mark -
115+
#pragma mark Fetch Head enumeration
116+
117+
typedef void (^GTRemoteEnumerateFetchHeadEntryBlock)(GTFetchHeadEntry *entry, BOOL *stop);
118+
119+
typedef struct {
120+
__unsafe_unretained GTRepository *repository;
121+
__unsafe_unretained GTRemoteEnumerateFetchHeadEntryBlock enumerationBlock;
122+
} GTEnumerateHeadEntriesPayload;
123+
124+
int GTFetchHeadEntriesCallback(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload) {
125+
GTEnumerateHeadEntriesPayload *entriesPayload = payload;
126+
127+
GTRepository *repository = entriesPayload->repository;
128+
GTRemoteEnumerateFetchHeadEntryBlock enumerationBlock = entriesPayload->enumerationBlock;
129+
130+
GTReference *reference = [GTReference referenceByLookingUpReferencedNamed:@(ref_name) inRepository:repository error:NULL];
131+
132+
GTFetchHeadEntry *entry = [[GTFetchHeadEntry alloc] initWithReference:reference remoteURLString:@(remote_url) targetOID:[GTOID oidWithGitOid:oid] isMerge:(BOOL)is_merge];
133+
134+
BOOL stop = NO;
135+
136+
enumerationBlock(entry, &stop);
137+
138+
return (stop == YES ? GIT_EUSER : 0);
139+
}
140+
141+
- (BOOL)enumerateFetchHeadEntriesWithError:(NSError **)error usingBlock:(void (^)(GTFetchHeadEntry *fetchHeadEntry, BOOL *stop))block {
142+
NSParameterAssert(block != nil);
143+
144+
GTEnumerateHeadEntriesPayload payload = {
145+
.repository = self,
146+
.enumerationBlock = block,
147+
};
148+
int gitError = git_repository_fetchhead_foreach(self.git_repository, GTFetchHeadEntriesCallback, &payload);
149+
150+
if (gitError != GIT_OK) {
151+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to get fetchhead entries"];
152+
return NO;
153+
}
154+
155+
return YES;
156+
}
157+
158+
- (NSArray *)fetchHeadEntriesWithError:(NSError **)error {
159+
NSMutableArray *entries = [NSMutableArray array];
160+
161+
[self enumerateFetchHeadEntriesWithError:error usingBlock:^(GTFetchHeadEntry *fetchHeadEntry, BOOL *stop) {
162+
[entries addObject:fetchHeadEntry];
163+
164+
*stop = NO;
165+
}];
166+
167+
return entries;
168+
}
169+
170+
#pragma mark - Push (Public)
171+
172+
- (BOOL)pushBranch:(GTBranch *)branch toRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(GTRemotePushTransferProgressBlock)progressBlock {
173+
NSParameterAssert(branch != nil);
174+
NSParameterAssert(remote != nil);
175+
176+
return [self pushBranches:@[ branch ] toRemote:remote withOptions:options error:error progress:progressBlock];
177+
}
178+
179+
- (BOOL)pushBranches:(NSArray *)branches toRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(GTRemotePushTransferProgressBlock)progressBlock {
180+
NSParameterAssert(branches != nil);
181+
NSParameterAssert(branches.count != 0);
182+
NSParameterAssert(remote != nil);
183+
184+
NSMutableArray *refspecs = nil;
185+
// Build refspecs for the passed in branches
186+
refspecs = [NSMutableArray arrayWithCapacity:branches.count];
187+
for (GTBranch *branch in branches) {
188+
// Default remote reference for when branch doesn't exist on remote - create with same short name
189+
NSString *remoteBranchReference = [NSString stringWithFormat:@"refs/heads/%@", branch.shortName];
190+
191+
BOOL success = NO;
192+
GTBranch *trackingBranch = [branch trackingBranchWithError:error success:&success];
193+
194+
if (success && trackingBranch) {
195+
// Use remote branch short name from trackingBranch, which could be different
196+
// (e.g. refs/heads/master:refs/heads/my_master)
197+
remoteBranchReference = [NSString stringWithFormat:@"refs/heads/%@", trackingBranch.shortName];
198+
}
199+
200+
[refspecs addObject:[NSString stringWithFormat:@"refs/heads/%@:%@", branch.shortName, remoteBranchReference]];
201+
}
202+
203+
return [self pushRefspecs:refspecs toRemote:remote withOptions:options error:error progress:progressBlock];
204+
}
205+
206+
#pragma mark - Push (Private)
207+
208+
- (BOOL)pushRefspecs:(NSArray *)refspecs toRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(GTRemotePushTransferProgressBlock)progressBlock {
209+
int gitError;
210+
GTCredentialProvider *credProvider = options[GTRepositoryRemoteOptionsCredentialProvider];
211+
212+
GTRemoteConnectionInfo connectionInfo = {
213+
.credProvider = { .credProvider = credProvider },
214+
.direction = GIT_DIRECTION_PUSH,
215+
.pushProgressBlock = progressBlock,
216+
};
217+
218+
git_remote_callbacks remote_callbacks = GIT_REMOTE_CALLBACKS_INIT;
219+
remote_callbacks.credentials = (credProvider != nil ? GTCredentialAcquireCallback : NULL),
220+
remote_callbacks.transfer_progress = GTRemoteFetchTransferProgressCallback,
221+
remote_callbacks.payload = &connectionInfo,
222+
223+
gitError = git_remote_set_callbacks(remote.git_remote, &remote_callbacks);
224+
if (gitError != GIT_OK) {
225+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to set callbacks on remote"];
226+
return NO;
227+
}
228+
229+
gitError = git_remote_connect(remote.git_remote, GIT_DIRECTION_PUSH);
230+
if (gitError != GIT_OK) {
231+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to connect remote"];
232+
return NO;
233+
}
234+
@onExit {
235+
git_remote_disconnect(remote.git_remote);
236+
// Clear out callbacks by overwriting with an effectively empty git_remote_callbacks struct
237+
git_remote_set_callbacks(remote.git_remote, &((git_remote_callbacks)GIT_REMOTE_CALLBACKS_INIT));
238+
};
239+
240+
git_push *push;
241+
gitError = git_push_new(&push, remote.git_remote);
242+
if (gitError != GIT_OK) {
243+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Push object creation failed" failureReason:@"Failed to create push object for remote \"%@\"", self];
244+
return NO;
245+
}
246+
@onExit {
247+
git_push_free(push);
248+
};
249+
250+
git_push_options push_options = GIT_PUSH_OPTIONS_INIT;
251+
252+
gitError = git_push_set_options(push, &push_options);
253+
if (gitError != GIT_OK) {
254+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to add options"];
255+
return NO;
256+
}
257+
258+
GTRemoteConnectionInfo payload = {
259+
.pushProgressBlock = progressBlock,
260+
};
261+
gitError = git_push_set_callbacks(push, NULL, NULL, GTRemotePushTransferProgressCallback, &payload);
262+
if (gitError != GIT_OK) {
263+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Setting push callbacks failed"];
264+
return NO;
265+
}
266+
267+
for (NSString *refspec in refspecs) {
268+
gitError = git_push_add_refspec(push, refspec.UTF8String);
269+
if (gitError != GIT_OK) {
270+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Adding reference failed" failureReason:@"Failed to add refspec \"%@\" to push object", refspec];
271+
return NO;
272+
}
273+
}
274+
275+
gitError = git_push_finish(push);
276+
if (gitError != GIT_OK) {
277+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Push to remote failed"];
278+
return NO;
279+
}
280+
281+
gitError = git_push_update_tips(push, self.userSignatureForNow.git_signature, NULL);
282+
if (gitError != GIT_OK) {
283+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Update tips failed"];
284+
return NO;
285+
}
286+
287+
gitError = git_push_status_foreach(push, GTRemotePushRefspecStatusCallback, NULL);
288+
if (gitError != GIT_OK) {
289+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"One or references failed to update"];
290+
return NO;
291+
}
292+
293+
return YES;
294+
}
295+
296+
@end

ObjectiveGit/GTTreeBuilder.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ - (id)initWithTree:(GTTree *)treeOrNil repository:(GTRepository *)repository err
6868
self = [super init];
6969
if (self == nil) return nil;
7070

71-
int status = git_treebuilder_new(&_git_treebuilder, repository.git_repository, treeOrNil.git_tree);
71+
int status = git_treebuilder_create(&_git_treebuilder, repository.git_repository, treeOrNil.git_tree);
7272
if (status != GIT_OK) {
7373
if (error != NULL) *error = [NSError git_errorFor:status description:@"Failed to create tree builder with tree %@.", treeOrNil.SHA];
7474
return nil;

0 commit comments

Comments
 (0)