Skip to content

Commit 13fd094

Browse files
authored
Merge pull request #587 from tiennou/tweaks
Tweaks
2 parents ee84447 + ce78f5f commit 13fd094

18 files changed

+301
-74
lines changed

ObjectiveGit/GTBranch.h

+6-4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
5050
@property (nonatomic, readonly) GTBranchType branchType;
5151
@property (nonatomic, readonly, strong) GTRepository *repository;
5252
@property (nonatomic, readonly, strong) GTReference *reference;
53+
@property (nonatomic, readonly, getter=isHEAD) BOOL HEAD;
5354

5455
+ (NSString *)localNamePrefix;
5556
+ (NSString *)remoteNamePrefix;
@@ -59,18 +60,16 @@ NS_ASSUME_NONNULL_BEGIN
5960
/// Designated initializer.
6061
///
6162
/// ref - The branch reference to wrap. Must not be nil.
62-
/// repo - The repository containing the branch. Must not be nil.
6363
///
6464
/// Returns the initialized receiver.
65-
- (instancetype _Nullable)initWithReference:(GTReference *)ref repository:(GTRepository *)repo NS_DESIGNATED_INITIALIZER;
65+
- (instancetype _Nullable)initWithReference:(GTReference *)ref NS_DESIGNATED_INITIALIZER;
6666

6767
/// Convenience class initializer.
6868
///
6969
/// ref - The branch reference to wrap. Must not be nil.
70-
/// repo - The repository containing the branch. Must not be nil.
7170
///
7271
/// Returns an initialized instance.
73-
+ (instancetype _Nullable)branchWithReference:(GTReference *)ref repository:(GTRepository *)repo;
72+
+ (instancetype _Nullable)branchWithReference:(GTReference *)ref;
7473

7574
/// Get the target commit for this branch
7675
///
@@ -79,6 +78,9 @@ NS_ASSUME_NONNULL_BEGIN
7978
/// returns a GTCommit object or nil if an error occurred
8079
- (GTCommit * _Nullable)targetCommitWithError:(NSError **)error;
8180

81+
/// Renames the branch. Setting `force` to YES to delete another branch with the same name.
82+
- (BOOL)rename:(NSString *)name force:(BOOL)force error:(NSError **)error;
83+
8284
/// Count all commits in this branch
8385
///
8486
/// error(out) - will be filled if an error occurs

ObjectiveGit/GTBranch.m

+36-17
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#import "GTRemote.h"
3333
#import "GTRepository.h"
3434
#import "NSError+Git.h"
35+
#import "NSData+Git.h"
3536

3637
#import "git2/branch.h"
3738
#import "git2/errors.h"
@@ -65,30 +66,32 @@ + (NSString *)remoteNamePrefix {
6566
return @"refs/remotes/";
6667
}
6768

68-
+ (instancetype)branchWithReference:(GTReference *)ref repository:(GTRepository *)repo {
69-
return [[self alloc] initWithReference:ref repository:repo];
69+
+ (instancetype)branchWithReference:(GTReference *)ref {
70+
return [[self alloc] initWithReference:ref];
7071
}
7172

7273
- (instancetype)init {
7374
NSAssert(NO, @"Call to an unavailable initializer.");
7475
return nil;
7576
}
7677

77-
- (instancetype)initWithReference:(GTReference *)ref repository:(GTRepository *)repo {
78+
- (instancetype)initWithReference:(GTReference *)ref {
7879
NSParameterAssert(ref != nil);
79-
NSParameterAssert(repo != nil);
8080

8181
self = [super init];
8282
if (self == nil) return nil;
8383

84-
_repository = repo;
8584
_reference = ref;
8685

8786
return self;
8887
}
8988

9089
- (NSString *)name {
91-
return self.reference.name;
90+
const char *charName;
91+
int gitError = git_branch_name(&charName, self.reference.git_reference);
92+
if (gitError != GIT_OK || charName == NULL) return nil;
93+
94+
return @(charName);
9295
}
9396

9497
- (NSString *)shortName {
@@ -112,17 +115,12 @@ - (GTOID *)OID {
112115
}
113116

114117
- (NSString *)remoteName {
115-
if (self.branchType == GTBranchTypeLocal) return nil;
116-
117-
const char *name;
118-
int gitError = git_branch_name(&name, self.reference.git_reference);
118+
git_buf remote_name = GIT_BUF_INIT_CONST(0, NULL);
119+
int gitError = git_branch_remote_name(&remote_name, self.repository.git_repository, self.reference.name.UTF8String);
119120
if (gitError != GIT_OK) return nil;
120121

121-
// Find out where the remote name ends.
122-
const char *end = strchr(name, '/');
123-
if (end == NULL || end == name) return nil;
124-
125-
return [[NSString alloc] initWithBytes:name length:end - name encoding:NSUTF8StringEncoding];
122+
NSData *data = [NSData git_dataWithBuffer:&remote_name];
123+
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
126124
}
127125

128126
- (GTCommit *)targetCommitWithError:(NSError **)error {
@@ -142,6 +140,10 @@ - (NSUInteger)numberOfCommitsWithError:(NSError **)error {
142140
return [enumerator countRemainingObjects:error];
143141
}
144142

143+
- (GTRepository *)repository {
144+
return self.reference.repository;
145+
}
146+
145147
- (GTBranchType)branchType {
146148
if (self.reference.remote) {
147149
return GTBranchTypeRemote;
@@ -150,6 +152,10 @@ - (GTBranchType)branchType {
150152
}
151153
}
152154

155+
- (BOOL)isHEAD {
156+
return (git_branch_is_head(self.reference.git_reference) ? YES : NO);
157+
}
158+
153159
- (NSArray *)uniqueCommitsRelativeToBranch:(GTBranch *)otherBranch error:(NSError **)error {
154160
GTEnumerator *enumerator = [self.repository enumeratorForUniqueCommitsFromOID:self.OID relativeToOID:otherBranch.OID error:error];
155161
return [enumerator allObjectsWithError:error];
@@ -165,6 +171,19 @@ - (BOOL)deleteWithError:(NSError **)error {
165171
return YES;
166172
}
167173

174+
- (BOOL)rename:(NSString *)name force:(BOOL)force error:(NSError **)error {
175+
git_reference *git_ref;
176+
int gitError = git_branch_move(&git_ref, self.reference.git_reference, name.UTF8String, (force ? 1 : 0));
177+
if (gitError != GIT_OK) {
178+
if (error) *error = [NSError git_errorFor:gitError description:@"Rename branch failed"];
179+
return NO;
180+
}
181+
182+
_reference = [[GTReference alloc] initWithGitReference:git_ref repository:self.repository];
183+
184+
return YES;
185+
}
186+
168187
- (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success {
169188
if (self.branchType == GTBranchTypeRemote) {
170189
if (success != NULL) *success = YES;
@@ -194,7 +213,7 @@ - (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success
194213

195214
if (success != NULL) *success = YES;
196215

197-
return [[self class] branchWithReference:[[GTReference alloc] initWithGitReference:trackingRef repository:self.repository] repository:self.repository];
216+
return [[self class] branchWithReference:[[GTReference alloc] initWithGitReference:trackingRef repository:self.repository]];
198217
}
199218

200219
- (BOOL)updateTrackingBranch:(GTBranch *)trackingBranch error:(NSError **)error {
@@ -216,7 +235,7 @@ - (GTBranch *)reloadedBranchWithError:(NSError **)error {
216235
GTReference *reloadedRef = [self.reference reloadedReferenceWithError:error];
217236
if (reloadedRef == nil) return nil;
218237

219-
return [[self.class alloc] initWithReference:reloadedRef repository:self.repository];
238+
return [[self.class alloc] initWithReference:reloadedRef];
220239
}
221240

222241
- (BOOL)calculateAhead:(size_t *)ahead behind:(size_t *)behind relativeTo:(GTBranch *)branch error:(NSError **)error {

ObjectiveGit/GTCommit.h

+2
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ NS_ASSUME_NONNULL_BEGIN
3939

4040
@interface GTCommit : GTObject {}
4141

42+
@property (nonatomic, readonly, strong) GTOID *OID;
4243
@property (nonatomic, readonly, strong) GTSignature * _Nullable author;
4344
@property (nonatomic, readonly, strong) GTSignature * _Nullable committer;
4445
@property (nonatomic, readonly, copy) NSArray<GTCommit *> *parents;
46+
@property (nonatomic, readonly, copy) NSArray<GTOID *> *parentOIDs;
4547
@property (nonatomic, readonly) NSString * _Nullable message;
4648
@property (nonatomic, readonly) NSString *messageDetails;
4749
@property (nonatomic, readonly) NSString *messageSummary;

ObjectiveGit/GTCommit.m

+17
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ - (git_commit *)git_commit {
5353

5454
#pragma mark API
5555

56+
- (GTOID *)OID {
57+
return [GTOID oidWithGitOid:git_commit_id(self.git_commit)];
58+
}
59+
5660
- (NSString *)message {
5761
const char *s = git_commit_message(self.git_commit);
5862
if(s == NULL) return nil;
@@ -117,6 +121,19 @@ - (BOOL)isMerge {
117121
return git_commit_parentcount(self.git_commit) > 1;
118122
}
119123

124+
- (NSArray <GTOID *> *)parentOIDs {
125+
unsigned numberOfParents = git_commit_parentcount(self.git_commit);
126+
NSMutableArray <GTOID *> *parents = [NSMutableArray arrayWithCapacity:numberOfParents];
127+
128+
for (unsigned i = 0; i < numberOfParents; i++) {
129+
const git_oid *parent = git_commit_parent_id(self.git_commit, i);
130+
131+
[parents addObject:[GTOID oidWithGitOid:parent]];
132+
}
133+
134+
return parents;
135+
}
136+
120137
- (NSArray *)parents {
121138
unsigned numberOfParents = git_commit_parentcount(self.git_commit);
122139
NSMutableArray *parents = [NSMutableArray arrayWithCapacity:numberOfParents];

ObjectiveGit/GTEnumerator.h

+34
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ NS_ASSUME_NONNULL_BEGIN
6464

6565
- (instancetype)init NS_UNAVAILABLE;
6666

67+
/// The underlying `git_revwalk` from libgit2.
68+
- (git_revwalk *)git_revwalk __attribute__((objc_returns_inner_pointer));
69+
6770
/// Initializes the receiver to enumerate the commits in the given repository. Designated initializer.
6871
///
6972
/// repo - The repository to enumerate the commits of. This must not be nil.
@@ -89,6 +92,21 @@ NS_ASSUME_NONNULL_BEGIN
8992
/// Returns whether pushing matching references was successful.
9093
- (BOOL)pushGlob:(NSString *)refGlob error:(NSError **)error;
9194

95+
/// Push HEAD reference.
96+
///
97+
/// error - If not NULL, this will be set to any error that occurs.
98+
///
99+
/// Returns whether pushing the HEAD reference was successful.
100+
- (BOOL)pushHEAD:(NSError **)error;
101+
102+
/// Push a reference by name.
103+
///
104+
/// refName - The reference name to push. Must not be nil.
105+
/// error - If not NULL, this will be set to any error that occurs.
106+
///
107+
/// Returns whether pushing the reference name was successful.
108+
- (BOOL)pushReferenceName:(NSString *)refName error:(NSError **)error;
109+
92110
/// Hides the specified commit and all of its ancestors when enumerating.
93111
///
94112
/// sha - The SHA of a commit in the receiver's repository. This must not be
@@ -106,6 +124,22 @@ NS_ASSUME_NONNULL_BEGIN
106124
/// Returns whether marking matching references for hiding was successful.
107125
- (BOOL)hideGlob:(NSString *)refGlob error:(NSError **)error;
108126

127+
/// Hide HEAD reference.
128+
///
129+
/// error - If not NULL, this will be set to any error that occurs.
130+
///
131+
/// Returns whether marking HEAD for hiding was successful.
132+
- (BOOL)hideHEAD:(NSError **)error;
133+
134+
135+
/// Hide a reference by name.
136+
///
137+
/// refName - The reference name to hide. Must not be nil.
138+
/// error - If not NULL, this will be set to any error that occurs.
139+
///
140+
/// Returns whether hiding the reference name was successful.
141+
- (BOOL)hideReferenceName:(NSString *)refName error:(NSError **)error;
142+
109143
/// Resets the receiver, putting it back into a clean state for reuse, and
110144
/// replacing the receiver's `options`.
111145
- (void)resetWithOptions:(GTEnumeratorOptions)options;

ObjectiveGit/GTEnumerator.m

+45-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ - (instancetype)init {
5353
return nil;
5454
}
5555

56+
- (git_revwalk *)git_revwalk {
57+
return self.walk;
58+
}
59+
5660
- (instancetype)initWithRepository:(GTRepository *)repo error:(NSError **)error {
5761
NSParameterAssert(repo != nil);
5862

@@ -107,6 +111,26 @@ - (BOOL)pushGlob:(NSString *)refGlob error:(NSError **)error {
107111
return YES;
108112
}
109113

114+
- (BOOL)pushHEAD:(NSError **)error {
115+
int gitError = git_revwalk_push_head(self.walk);
116+
if (gitError != GIT_OK) {
117+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to push HEAD onto rev walker."];
118+
return NO;
119+
}
120+
return YES;
121+
}
122+
123+
- (BOOL)pushReferenceName:(NSString *)refName error:(NSError **)error {
124+
NSParameterAssert(refName != nil);
125+
126+
int gitError = git_revwalk_push_ref(self.walk, refName.UTF8String);
127+
if (gitError != 0) {
128+
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to push reference %@", refName];
129+
return NO;
130+
}
131+
return YES;
132+
}
133+
110134
- (BOOL)hideSHA:(NSString *)sha error:(NSError **)error {
111135
NSParameterAssert(sha != nil);
112136

@@ -127,13 +151,33 @@ - (BOOL)hideGlob:(NSString *)refGlob error:(NSError **)error {
127151

128152
int gitError = git_revwalk_hide_glob(self.walk, refGlob.UTF8String);
129153
if (gitError != GIT_OK) {
130-
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to push glob %@ onto rev walker.", refGlob];
154+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to hide glob %@ in rev walker.", refGlob];
131155
return NO;
132156
}
133157

134158
return YES;
135159
}
136160

161+
- (BOOL)hideHEAD:(NSError **)error {
162+
int gitError = git_revwalk_hide_head(self.walk);
163+
if (gitError != GIT_OK) {
164+
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to hide HEAD onto rev walker."];
165+
return NO;
166+
}
167+
return YES;
168+
}
169+
170+
- (BOOL)hideReferenceName:(NSString *)refName error:(NSError **)error {
171+
NSParameterAssert(refName != nil);
172+
173+
int gitError = git_revwalk_hide_ref(self.walk, refName.UTF8String);
174+
if (gitError != 0) {
175+
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to hide reference %@", refName];
176+
return NO;
177+
}
178+
return YES;
179+
}
180+
137181
#pragma mark Resetting
138182

139183
- (void)resetWithOptions:(GTEnumeratorOptions)options {

ObjectiveGit/GTReference.h

+9
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,18 @@ NS_ASSUME_NONNULL_BEGIN
5454
@property (nonatomic, readonly) const git_oid *git_oid;
5555
@property (nonatomic, strong, readonly) GTOID * _Nullable OID;
5656

57+
/// Whether this is a tag.
58+
@property (nonatomic, readonly, getter = isTag) BOOL tag;
59+
60+
/// Whether this is a local branch.
61+
@property (nonatomic, readonly, getter = isBranch) BOOL branch;
62+
5763
/// Whether this is a remote-tracking branch.
5864
@property (nonatomic, readonly, getter = isRemote) BOOL remote;
5965

66+
/// Whether this is a note ref.
67+
@property (nonatomic, readonly, getter = isNote) BOOL note;
68+
6069
/// The reflog for the reference.
6170
@property (nonatomic, readonly, strong) GTReflog *reflog;
6271

ObjectiveGit/GTReference.m

+12
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ - (instancetype)initWithGitReference:(git_reference *)ref repository:(GTReposito
105105
return self;
106106
}
107107

108+
- (BOOL)isBranch {
109+
return git_reference_is_branch(self.git_reference) != 0;
110+
}
111+
112+
- (BOOL)isTag {
113+
return git_reference_is_tag(self.git_reference) != 0;
114+
}
115+
116+
- (BOOL)isNote {
117+
return git_reference_is_note(self.git_reference) != 0;
118+
}
119+
108120
- (NSString *)name {
109121
const char *refName = git_reference_name(self.git_reference);
110122
if (refName == NULL) return nil;

ObjectiveGit/GTRepository+Merging.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ - (BOOL)mergeBranchIntoCurrentBranch:(GTBranch *)branch withError:(NSError **)er
158158
NSArray *parents = @[ localCommit, remoteCommit ];
159159

160160
// FIXME: This is stepping on the local tree
161-
GTCommit *mergeCommit = [self createCommitWithTree:newTree message:message parents:parents updatingReferenceNamed:localBranch.name error:error];
161+
GTCommit *mergeCommit = [self createCommitWithTree:newTree message:message parents:parents updatingReferenceNamed:localBranch.reference.name error:error];
162162
if (!mergeCommit) {
163163
return NO;
164164
}

0 commit comments

Comments
 (0)