Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweaks #587

Merged
merged 15 commits into from
Nov 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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