Skip to content

Commit 947058d

Browse files
committed
Push branches and notes in one operation
Added -[GTRepository pushBranches:toRemote:withOptions:withNotesReferenceName:error:progress:] to push both a set of branches and stored Git notes at the same operation to save on network ops.
1 parent 6df9faf commit 947058d

File tree

4 files changed

+71
-22
lines changed

4 files changed

+71
-22
lines changed

ObjectiveGit/GTNote.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ NS_ASSUME_NONNULL_BEGIN
7777

7878
- (instancetype)init NS_UNAVAILABLE;
7979

80+
81+
/// Return a default reference name (that is used if you pass nil to any referenceName parameter)
82+
///
83+
/// repository - Repository for which to get the default notes reference name.
84+
/// error - Will be filled with a git error code in case of error.
85+
/// May be NULL.
86+
///
87+
/// Returns default reference name (usually "refs/notes/commits").
88+
+ (NSString*)defaultReferenceNameForRepository:(GTRepository *)repository error:(NSError **)error;
89+
8090
@end
8191

8292
NS_ASSUME_NONNULL_END

ObjectiveGit/GTNote.m

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,25 @@ - (instancetype)init {
8989
return nil;
9090
}
9191

92+
+ (NSString*)defaultReferenceNameForRepository:(GTRepository *)repository error:(NSError **)error {
93+
NSString* noteRef = nil;
94+
95+
git_buf default_ref_name = { 0 };
96+
int gitErr = git_note_default_ref(&default_ref_name, repository.git_repository);
97+
if (gitErr != GIT_OK) {
98+
git_buf_free(&default_ref_name);
99+
100+
if (error != NULL) {
101+
*error = [NSError git_errorFor:gitErr description:@"Unable to get default git notes reference name"];
102+
}
103+
104+
return nil;
105+
}
106+
107+
noteRef = [NSString stringWithUTF8String:default_ref_name.ptr];
108+
109+
git_buf_free(&default_ref_name);
110+
111+
return noteRef;
112+
}
92113
@end

ObjectiveGit/GTRepository+RemoteOperations.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,39 @@ typedef NS_ENUM(NSInteger, GTFetchPruneOption) {
9797
/// will point to an error describing what happened).
9898
- (BOOL)pushBranches:(NSArray<GTBranch *> *)branches toRemote:(GTRemote *)remote withOptions:(nullable NSDictionary *)options error:(NSError **)error progress:(nullable void (^)(unsigned int current, unsigned int total, size_t bytes, BOOL *stop))progressBlock;
9999

100-
/// Push a given Git notes reference name to a remote.
100+
/// Push an array of branches to a remote, together with notes (in one push).
101+
/// Normally, if you use Git notes functionality, to push the notes to remote, you would have to
102+
/// do two operations: pushBranches followed by pushNotes. This is unrational, so we offer you a handy
103+
/// shortcut that allows to push the branches together with the notes.
101104
///
102-
/// noteRef - Name of the notes reference. If NULL, will default to whatever the default is (e.g. "refs/notes/commits")
105+
/// branches - An array of branches to push. Must not be nil.
103106
/// remote - The remote to push to. Must not be nil.
104107
/// options - Options applied to the push operation. Can be NULL.
105108
/// Recognized options are:
106109
/// `GTRepositoryRemoteOptionsCredentialProvider`
110+
/// referenceName - Reference name for notes, if they should be pushed together with the branches.
111+
/// Use +[GTNote defaultReferenceNameWithError:] to push the default note reference.
112+
/// Passing NULL here will make notes NOT to be pushed.
107113
/// error - The error if one occurred. Can be NULL.
108114
/// progressBlock - An optional callback for monitoring progress. May be NULL.
109115
///
110116
/// Returns YES if the push was successful, NO otherwise (and `error`, if provided,
111117
/// will point to an error describing what happened).
112-
- (BOOL)pushNotes:(nullable NSString *)noteRef toRemote:(GTRemote *)remote withOptions:(nullable NSDictionary *)options error:(NSError **)error progress:(nullable void (^)(unsigned int current, unsigned int total, size_t bytes, BOOL *stop))progressBlock;
118+
- (BOOL)pushBranches:(NSArray<GTBranch *> *)branches toRemote:(GTRemote *)remote withOptions:(nullable NSDictionary *)options withNotesReferenceName:(nullable NSString*)notesReferenceName error:(NSError **)error progress:(nullable void (^)(unsigned int current, unsigned int total, size_t bytes, BOOL *stop))progressBlock;
119+
120+
/// Push a given Git notes reference name to a remote.
121+
///
122+
/// noteReferenceName - Name of the notes reference. If NULL, will default to whatever the default is (e.g. "refs/notes/commits")
123+
/// remote - The remote to push to. Must not be nil.
124+
/// options - Options applied to the push operation. Can be NULL.
125+
/// Recognized options are:
126+
/// `GTRepositoryRemoteOptionsCredentialProvider`
127+
/// error - The error if one occurred. Can be NULL.
128+
/// progressBlock - An optional callback for monitoring progress. May be NULL.
129+
///
130+
/// Returns YES if the push was successful, NO otherwise (and `error`, if provided,
131+
/// will point to an error describing what happened).
132+
- (BOOL)pushNotes:(nullable NSString *)noteReferenceName toRemote:(GTRemote *)remote withOptions:(nullable NSDictionary *)options error:(NSError **)error progress:(nullable void (^)(unsigned int current, unsigned int total, size_t bytes, BOOL *stop))progressBlock;
113133

114134
/// Delete a remote branch
115135
///

ObjectiveGit/GTRepository+RemoteOperations.m

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#import "NSArray+StringArray.h"
1919
#import "NSError+Git.h"
2020
#import "GTRepository+References.h"
21+
#import "GTNote.h"
2122

2223
#import "git2/errors.h"
2324
#import "git2/remote.h"
@@ -174,51 +175,48 @@ - (BOOL)pushBranch:(GTBranch *)branch toRemote:(GTRemote *)remote withOptions:(N
174175
}
175176

176177
- (BOOL)pushBranches:(NSArray *)branches toRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(GTRemotePushTransferProgressBlock)progressBlock {
178+
return [self pushBranches:branches toRemote:remote withOptions:options withNotesReferenceName:nil error:error progress:progressBlock];
179+
}
180+
181+
- (BOOL)pushBranches:(NSArray *)branches toRemote:(GTRemote *)remote withOptions:(NSDictionary *)options withNotesReferenceName:(NSString*)referenceName error:(NSError **)error progress:(GTRemotePushTransferProgressBlock)progressBlock {
177182
NSParameterAssert(branches != nil);
178183
NSParameterAssert(branches.count != 0);
179184
NSParameterAssert(remote != nil);
180-
185+
181186
NSMutableArray *refspecs = nil;
182187
// Build refspecs for the passed in branches
183188
refspecs = [NSMutableArray arrayWithCapacity:branches.count];
184189
for (GTBranch *branch in branches) {
185190
// Default remote reference for when branch doesn't exist on remote - create with same short name
186191
NSString *remoteBranchReference = [NSString stringWithFormat:@"refs/heads/%@", branch.shortName];
187-
192+
188193
BOOL success = NO;
189194
GTBranch *trackingBranch = [branch trackingBranchWithError:error success:&success];
190-
195+
191196
if (success && trackingBranch != nil) {
192197
// Use remote branch short name from trackingBranch, which could be different
193198
// (e.g. refs/heads/master:refs/heads/my_master)
194199
remoteBranchReference = [NSString stringWithFormat:@"refs/heads/%@", trackingBranch.shortName];
195200
}
196-
201+
197202
[refspecs addObject:[NSString stringWithFormat:@"refs/heads/%@:%@", branch.shortName, remoteBranchReference]];
198203
}
199-
204+
205+
// Also push the notes reference, if needed.
206+
if (referenceName != nil) {
207+
[refspecs addObject:[NSString stringWithFormat:@"%@:%@", referenceName, referenceName]];
208+
}
209+
200210
return [self pushRefspecs:refspecs toRemote:remote withOptions:options error:error progress:progressBlock];
201211
}
202212

203213
- (BOOL)pushNotes:(NSString *)noteRef toRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(GTRemotePushTransferProgressBlock)progressBlock {
204214
NSParameterAssert(remote != nil);
205215

206216
if (noteRef == nil) {
207-
git_buf default_ref_name = { 0 };
208-
int gitErr = git_note_default_ref(&default_ref_name, self.git_repository);
209-
if (gitErr != GIT_OK) {
210-
git_buf_free(&default_ref_name);
211-
212-
if (error != NULL) {
213-
*error = [NSError git_errorFor:gitErr description:@"Unable to get default git notes reference name"];
214-
}
215-
216-
return NO;
217-
}
218-
219-
noteRef = [NSString stringWithUTF8String:default_ref_name.ptr];
217+
noteRef = [GTNote defaultReferenceNameForRepository:self error:error];
220218

221-
git_buf_free(&default_ref_name);
219+
if (noteRef == nil) return NO;
222220
}
223221

224222
return [self pushRefspecs:@[[NSString stringWithFormat:@"%@:%@", noteRef, noteRef]] toRemote:remote withOptions:options error:error progress:progressBlock];

0 commit comments

Comments
 (0)