Skip to content

Commit

Permalink
Merge pull request #587 from tiennou/tweaks
Browse files Browse the repository at this point in the history
Tweaks
  • Loading branch information
pietbrauer authored Nov 26, 2017
2 parents ee84447 + ce78f5f commit 13fd094
Show file tree
Hide file tree
Showing 18 changed files with 301 additions and 74 deletions.
10 changes: 6 additions & 4 deletions ObjectiveGit/GTBranch.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) GTBranchType branchType;
@property (nonatomic, readonly, strong) GTRepository *repository;
@property (nonatomic, readonly, strong) GTReference *reference;
@property (nonatomic, readonly, getter=isHEAD) BOOL HEAD;

+ (NSString *)localNamePrefix;
+ (NSString *)remoteNamePrefix;
Expand All @@ -59,18 +60,16 @@ NS_ASSUME_NONNULL_BEGIN
/// Designated initializer.
///
/// ref - The branch reference to wrap. Must not be nil.
/// repo - The repository containing the branch. Must not be nil.
///
/// Returns the initialized receiver.
- (instancetype _Nullable)initWithReference:(GTReference *)ref repository:(GTRepository *)repo NS_DESIGNATED_INITIALIZER;
- (instancetype _Nullable)initWithReference:(GTReference *)ref NS_DESIGNATED_INITIALIZER;

/// Convenience class initializer.
///
/// ref - The branch reference to wrap. Must not be nil.
/// repo - The repository containing the branch. Must not be nil.
///
/// Returns an initialized instance.
+ (instancetype _Nullable)branchWithReference:(GTReference *)ref repository:(GTRepository *)repo;
+ (instancetype _Nullable)branchWithReference:(GTReference *)ref;

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

/// Renames the branch. Setting `force` to YES to delete another branch with the same name.
- (BOOL)rename:(NSString *)name force:(BOOL)force error:(NSError **)error;

/// Count all commits in this branch
///
/// error(out) - will be filled if an error occurs
Expand Down
53 changes: 36 additions & 17 deletions ObjectiveGit/GTBranch.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#import "GTRemote.h"
#import "GTRepository.h"
#import "NSError+Git.h"
#import "NSData+Git.h"

#import "git2/branch.h"
#import "git2/errors.h"
Expand Down Expand Up @@ -65,30 +66,32 @@ + (NSString *)remoteNamePrefix {
return @"refs/remotes/";
}

+ (instancetype)branchWithReference:(GTReference *)ref repository:(GTRepository *)repo {
return [[self alloc] initWithReference:ref repository:repo];
+ (instancetype)branchWithReference:(GTReference *)ref {
return [[self alloc] initWithReference:ref];
}

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

- (instancetype)initWithReference:(GTReference *)ref repository:(GTRepository *)repo {
- (instancetype)initWithReference:(GTReference *)ref {
NSParameterAssert(ref != nil);
NSParameterAssert(repo != nil);

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

_repository = repo;
_reference = ref;

return self;
}

- (NSString *)name {
return self.reference.name;
const char *charName;
int gitError = git_branch_name(&charName, self.reference.git_reference);
if (gitError != GIT_OK || charName == NULL) return nil;

return @(charName);
}

- (NSString *)shortName {
Expand All @@ -112,17 +115,12 @@ - (GTOID *)OID {
}

- (NSString *)remoteName {
if (self.branchType == GTBranchTypeLocal) return nil;

const char *name;
int gitError = git_branch_name(&name, self.reference.git_reference);
git_buf remote_name = GIT_BUF_INIT_CONST(0, NULL);
int gitError = git_branch_remote_name(&remote_name, self.repository.git_repository, self.reference.name.UTF8String);
if (gitError != GIT_OK) return nil;

// Find out where the remote name ends.
const char *end = strchr(name, '/');
if (end == NULL || end == name) return nil;

return [[NSString alloc] initWithBytes:name length:end - name encoding:NSUTF8StringEncoding];
NSData *data = [NSData git_dataWithBuffer:&remote_name];
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

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

- (GTRepository *)repository {
return self.reference.repository;
}

- (GTBranchType)branchType {
if (self.reference.remote) {
return GTBranchTypeRemote;
Expand All @@ -150,6 +152,10 @@ - (GTBranchType)branchType {
}
}

- (BOOL)isHEAD {
return (git_branch_is_head(self.reference.git_reference) ? YES : NO);
}

- (NSArray *)uniqueCommitsRelativeToBranch:(GTBranch *)otherBranch error:(NSError **)error {
GTEnumerator *enumerator = [self.repository enumeratorForUniqueCommitsFromOID:self.OID relativeToOID:otherBranch.OID error:error];
return [enumerator allObjectsWithError:error];
Expand All @@ -165,6 +171,19 @@ - (BOOL)deleteWithError:(NSError **)error {
return YES;
}

- (BOOL)rename:(NSString *)name force:(BOOL)force error:(NSError **)error {
git_reference *git_ref;
int gitError = git_branch_move(&git_ref, self.reference.git_reference, name.UTF8String, (force ? 1 : 0));
if (gitError != GIT_OK) {
if (error) *error = [NSError git_errorFor:gitError description:@"Rename branch failed"];
return NO;
}

_reference = [[GTReference alloc] initWithGitReference:git_ref repository:self.repository];

return YES;
}

- (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success {
if (self.branchType == GTBranchTypeRemote) {
if (success != NULL) *success = YES;
Expand Down Expand Up @@ -194,7 +213,7 @@ - (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success

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

return [[self class] branchWithReference:[[GTReference alloc] initWithGitReference:trackingRef repository:self.repository] repository:self.repository];
return [[self class] branchWithReference:[[GTReference alloc] initWithGitReference:trackingRef repository:self.repository]];
}

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

return [[self.class alloc] initWithReference:reloadedRef repository:self.repository];
return [[self.class alloc] initWithReference:reloadedRef];
}

- (BOOL)calculateAhead:(size_t *)ahead behind:(size_t *)behind relativeTo:(GTBranch *)branch error:(NSError **)error {
Expand Down
2 changes: 2 additions & 0 deletions ObjectiveGit/GTCommit.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ NS_ASSUME_NONNULL_BEGIN

@interface GTCommit : GTObject {}

@property (nonatomic, readonly, strong) GTOID *OID;
@property (nonatomic, readonly, strong) GTSignature * _Nullable author;
@property (nonatomic, readonly, strong) GTSignature * _Nullable committer;
@property (nonatomic, readonly, copy) NSArray<GTCommit *> *parents;
@property (nonatomic, readonly, copy) NSArray<GTOID *> *parentOIDs;
@property (nonatomic, readonly) NSString * _Nullable message;
@property (nonatomic, readonly) NSString *messageDetails;
@property (nonatomic, readonly) NSString *messageSummary;
Expand Down
17 changes: 17 additions & 0 deletions ObjectiveGit/GTCommit.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ - (git_commit *)git_commit {

#pragma mark API

- (GTOID *)OID {
return [GTOID oidWithGitOid:git_commit_id(self.git_commit)];
}

- (NSString *)message {
const char *s = git_commit_message(self.git_commit);
if(s == NULL) return nil;
Expand Down Expand Up @@ -117,6 +121,19 @@ - (BOOL)isMerge {
return git_commit_parentcount(self.git_commit) > 1;
}

- (NSArray <GTOID *> *)parentOIDs {
unsigned numberOfParents = git_commit_parentcount(self.git_commit);
NSMutableArray <GTOID *> *parents = [NSMutableArray arrayWithCapacity:numberOfParents];

for (unsigned i = 0; i < numberOfParents; i++) {
const git_oid *parent = git_commit_parent_id(self.git_commit, i);

[parents addObject:[GTOID oidWithGitOid:parent]];
}

return parents;
}

- (NSArray *)parents {
unsigned numberOfParents = git_commit_parentcount(self.git_commit);
NSMutableArray *parents = [NSMutableArray arrayWithCapacity:numberOfParents];
Expand Down
34 changes: 34 additions & 0 deletions ObjectiveGit/GTEnumerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ NS_ASSUME_NONNULL_BEGIN

- (instancetype)init NS_UNAVAILABLE;

/// The underlying `git_revwalk` from libgit2.
- (git_revwalk *)git_revwalk __attribute__((objc_returns_inner_pointer));

/// Initializes the receiver to enumerate the commits in the given repository. Designated initializer.
///
/// repo - The repository to enumerate the commits of. This must not be nil.
Expand All @@ -89,6 +92,21 @@ NS_ASSUME_NONNULL_BEGIN
/// Returns whether pushing matching references was successful.
- (BOOL)pushGlob:(NSString *)refGlob error:(NSError **)error;

/// Push HEAD reference.
///
/// error - If not NULL, this will be set to any error that occurs.
///
/// Returns whether pushing the HEAD reference was successful.
- (BOOL)pushHEAD:(NSError **)error;

/// Push a reference by name.
///
/// refName - The reference name to push. Must not be nil.
/// error - If not NULL, this will be set to any error that occurs.
///
/// Returns whether pushing the reference name was successful.
- (BOOL)pushReferenceName:(NSString *)refName error:(NSError **)error;

/// Hides the specified commit and all of its ancestors when enumerating.
///
/// sha - The SHA of a commit in the receiver's repository. This must not be
Expand All @@ -106,6 +124,22 @@ NS_ASSUME_NONNULL_BEGIN
/// Returns whether marking matching references for hiding was successful.
- (BOOL)hideGlob:(NSString *)refGlob error:(NSError **)error;

/// Hide HEAD reference.
///
/// error - If not NULL, this will be set to any error that occurs.
///
/// Returns whether marking HEAD for hiding was successful.
- (BOOL)hideHEAD:(NSError **)error;


/// Hide a reference by name.
///
/// refName - The reference name to hide. Must not be nil.
/// error - If not NULL, this will be set to any error that occurs.
///
/// Returns whether hiding the reference name was successful.
- (BOOL)hideReferenceName:(NSString *)refName error:(NSError **)error;

/// Resets the receiver, putting it back into a clean state for reuse, and
/// replacing the receiver's `options`.
- (void)resetWithOptions:(GTEnumeratorOptions)options;
Expand Down
46 changes: 45 additions & 1 deletion ObjectiveGit/GTEnumerator.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ - (instancetype)init {
return nil;
}

- (git_revwalk *)git_revwalk {
return self.walk;
}

- (instancetype)initWithRepository:(GTRepository *)repo error:(NSError **)error {
NSParameterAssert(repo != nil);

Expand Down Expand Up @@ -107,6 +111,26 @@ - (BOOL)pushGlob:(NSString *)refGlob error:(NSError **)error {
return YES;
}

- (BOOL)pushHEAD:(NSError **)error {
int gitError = git_revwalk_push_head(self.walk);
if (gitError != GIT_OK) {
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to push HEAD onto rev walker."];
return NO;
}
return YES;
}

- (BOOL)pushReferenceName:(NSString *)refName error:(NSError **)error {
NSParameterAssert(refName != nil);

int gitError = git_revwalk_push_ref(self.walk, refName.UTF8String);
if (gitError != 0) {
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to push reference %@", refName];
return NO;
}
return YES;
}

- (BOOL)hideSHA:(NSString *)sha error:(NSError **)error {
NSParameterAssert(sha != nil);

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

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

return YES;
}

- (BOOL)hideHEAD:(NSError **)error {
int gitError = git_revwalk_hide_head(self.walk);
if (gitError != GIT_OK) {
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to hide HEAD onto rev walker."];
return NO;
}
return YES;
}

- (BOOL)hideReferenceName:(NSString *)refName error:(NSError **)error {
NSParameterAssert(refName != nil);

int gitError = git_revwalk_hide_ref(self.walk, refName.UTF8String);
if (gitError != 0) {
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to hide reference %@", refName];
return NO;
}
return YES;
}

#pragma mark Resetting

- (void)resetWithOptions:(GTEnumeratorOptions)options {
Expand Down
9 changes: 9 additions & 0 deletions ObjectiveGit/GTReference.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,18 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) const git_oid *git_oid;
@property (nonatomic, strong, readonly) GTOID * _Nullable OID;

/// Whether this is a tag.
@property (nonatomic, readonly, getter = isTag) BOOL tag;

/// Whether this is a local branch.
@property (nonatomic, readonly, getter = isBranch) BOOL branch;

/// Whether this is a remote-tracking branch.
@property (nonatomic, readonly, getter = isRemote) BOOL remote;

/// Whether this is a note ref.
@property (nonatomic, readonly, getter = isNote) BOOL note;

/// The reflog for the reference.
@property (nonatomic, readonly, strong) GTReflog *reflog;

Expand Down
12 changes: 12 additions & 0 deletions ObjectiveGit/GTReference.m
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ - (instancetype)initWithGitReference:(git_reference *)ref repository:(GTReposito
return self;
}

- (BOOL)isBranch {
return git_reference_is_branch(self.git_reference) != 0;
}

- (BOOL)isTag {
return git_reference_is_tag(self.git_reference) != 0;
}

- (BOOL)isNote {
return git_reference_is_note(self.git_reference) != 0;
}

- (NSString *)name {
const char *refName = git_reference_name(self.git_reference);
if (refName == NULL) return nil;
Expand Down
2 changes: 1 addition & 1 deletion ObjectiveGit/GTRepository+Merging.m
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ - (BOOL)mergeBranchIntoCurrentBranch:(GTBranch *)branch withError:(NSError **)er
NSArray *parents = @[ localCommit, remoteCommit ];

// FIXME: This is stepping on the local tree
GTCommit *mergeCommit = [self createCommitWithTree:newTree message:message parents:parents updatingReferenceNamed:localBranch.name error:error];
GTCommit *mergeCommit = [self createCommitWithTree:newTree message:message parents:parents updatingReferenceNamed:localBranch.reference.name error:error];
if (!mergeCommit) {
return NO;
}
Expand Down
Loading

0 comments on commit 13fd094

Please sign in to comment.