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

Enhance merge support #678

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
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
75 changes: 75 additions & 0 deletions ObjectiveGit/GTAnnotatedCommit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//
// GTAnnotatedCommit.h
// ObjectiveGitFramework
//
// Created by Etienne on 18/12/2016.
// Copyright © 2016 GitHub, Inc. All rights reserved.
//

#import <Foundation/Foundation.h>

#import <git2/annotated_commit.h>

@class GTReference;
@class GTRepository;
@class GTOID;

NS_ASSUME_NONNULL_BEGIN

@interface GTAnnotatedCommit : NSObject

/// Make an annotated commit from a reference.
///
/// @param reference The reference the annotated commit should point to. Must not be nil.
/// @param error An error if one occurred.
///
/// @return Return a newly initialized instance of the receiver.
+ (nullable instancetype)annotatedCommitFromReference:(GTReference *)reference error:(NSError **)error;

/// Make an annotated commit from a fetch head.
///
/// @param branchName The branch name to use. Must not be nil.
/// @param remoteURL The remote URL to use. Must not be nil.
/// @param OID The OID the commit should point to. Must not be nil.
/// @param repository The repository the OID belongs to. Must not be nil.
/// @param error An error if one occurred.
///
/// @return Return a newly initialized instance of the receiver.
+ (nullable instancetype)annotatedCommitFromFetchHead:(NSString *)branchName url:(NSString *)remoteURL oid:(GTOID *)OID inRepository:(GTRepository *)repository error:(NSError **)error;

/// Make an annotated commit from a OID.
///
/// @param OID The OID the commit should point to. Must not be nil.
/// @param repository The repository the OID belongs to. Must not be nil.
/// @param error An error if one occurred.
///
/// @return Return a newly initialized instance of the receiver.
+ (nullable instancetype)annotatedCommitFromOID:(GTOID *)OID inRepository:(GTRepository *)repository error:(NSError **)error;

/// Make an annotated commit by resolving a revspec.
///
/// @param revSpec The revspec to resolve. Must not be nil.
/// @param repository The repository to perform the resolution in. Must not be nil.
/// @param error An error if one occurred.
///
/// @return Return a newly initialized instance of the receiver.
+ (nullable instancetype)annotatedCommitFromRevSpec:(NSString *)revSpec inRepository:(GTRepository *)repository error:(NSError **)error;

- (instancetype)init NS_UNAVAILABLE;

/// Designated initializer
///
/// @param annotated_commit The annotated commit to wrap. Must not be nil.
///
/// @return Return a newly initialized instance of the receiver.
- (nullable instancetype)initWithGitAnnotatedCommit:(git_annotated_commit *)annotated_commit NS_DESIGNATED_INITIALIZER;

/// The underlying `git_annotated_commit` object.
- (git_annotated_commit *)git_annotated_commit __attribute__((objc_returns_inner_pointer));

/// The OID of the underlying commit.
@property (nonatomic, copy, readonly) GTOID *OID;

@end

NS_ASSUME_NONNULL_END
105 changes: 105 additions & 0 deletions ObjectiveGit/GTAnnotatedCommit.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//
// GTAnnotatedCommit.m
// ObjectiveGitFramework
//
// Created by Etienne on 18/12/2016.
// Copyright © 2016 GitHub, Inc. All rights reserved.
//

#import "GTAnnotatedCommit.h"

#import "GTReference.h"
#import "GTRepository.h"
#import "GTOID.h"
#import "NSError+Git.h"

#import "git2/annotated_commit.h"

@interface GTAnnotatedCommit ()
@property (nonatomic, readonly, assign) git_annotated_commit *annotated_commit;
@end

@implementation GTAnnotatedCommit

+ (instancetype)annotatedCommitFromReference:(GTReference *)reference error:(NSError **)error {
NSParameterAssert(reference != nil);

git_annotated_commit *commit;
int gitError = git_annotated_commit_from_ref(&commit, reference.repository.git_repository, reference.git_reference);
if (gitError != 0) {
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Annotated commit creation failed"];
return nil;
}

return [[self alloc] initWithGitAnnotatedCommit:commit];
}

+ (instancetype)annotatedCommitFromFetchHead:(NSString *)branchName url:(NSString *)remoteURL oid:(GTOID *)OID inRepository:(GTRepository *)repository error:(NSError **)error {
NSParameterAssert(branchName != nil);
NSParameterAssert(remoteURL != nil);
NSParameterAssert(OID != nil);
NSParameterAssert(repository != nil);

git_annotated_commit *commit;
int gitError = git_annotated_commit_from_fetchhead(&commit, repository.git_repository, branchName.UTF8String, remoteURL.UTF8String, OID.git_oid);
if (gitError != 0) {
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Annotated commit creation failed"];
return nil;
}

return [[self alloc] initWithGitAnnotatedCommit:commit];
}

+ (instancetype)annotatedCommitFromOID:(GTOID *)OID inRepository:(GTRepository *)repository error:(NSError **)error {
NSParameterAssert(OID != nil);
NSParameterAssert(repository != nil);

git_annotated_commit *commit;
int gitError = git_annotated_commit_lookup(&commit, repository.git_repository, OID.git_oid);
if (gitError != 0) {
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Annotated commit creation failed"];
return nil;
}

return [[self alloc] initWithGitAnnotatedCommit:commit];
}

+ (instancetype)annotatedCommitFromRevSpec:(NSString *)revSpec inRepository:(GTRepository *)repository error:(NSError **)error {
NSParameterAssert(revSpec != nil);
NSParameterAssert(repository != nil);

git_annotated_commit *commit;
int gitError = git_annotated_commit_from_revspec(&commit, repository.git_repository, revSpec.UTF8String);
if (gitError != 0) {
if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Annotated commit creation failed"];
return nil;
}

return [[self alloc] initWithGitAnnotatedCommit:commit];
}

- (instancetype)initWithGitAnnotatedCommit:(git_annotated_commit *)annotated_commit {
NSParameterAssert(annotated_commit != NULL);

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

_annotated_commit = annotated_commit;

return self;
}

- (void)dealloc {
git_annotated_commit_free(_annotated_commit);
}

/// The underlying `git_annotated_commit` object.
- (git_annotated_commit *)git_annotated_commit {
return _annotated_commit;
}

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

@end
2 changes: 1 addition & 1 deletion ObjectiveGit/GTCheckoutOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ typedef NS_OPTIONS(NSInteger, GTCheckoutStrategyType) {
GTCheckoutStrategySkipLockedDirectories = GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES,
GTCheckoutStrategyDoNotOverwriteIgnored = GIT_CHECKOUT_DONT_OVERWRITE_IGNORED,
GTCheckoutStrategyConflictStyleMerge = GIT_CHECKOUT_CONFLICT_STYLE_MERGE,
GTCheckoutStrategyCoflictStyleDiff3 = GIT_CHECKOUT_CONFLICT_STYLE_DIFF3,
GTCheckoutStrategyConflictStyleDiff3 = GIT_CHECKOUT_CONFLICT_STYLE_DIFF3,
GTCheckoutStrategyDoNotRemoveExisting = GIT_CHECKOUT_DONT_REMOVE_EXISTING,
GTCheckoutStrategyDoNotWriteIndex = GIT_CHECKOUT_DONT_WRITE_INDEX,
};
Expand Down
20 changes: 20 additions & 0 deletions ObjectiveGit/GTRepository+Merging.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#import "GTIndexEntry.h"
#import "git2/merge.h"

@class GTAnnotatedCommit;

NS_ASSUME_NONNULL_BEGIN

/// UserInfo key for conflicted files when pulling fails with a merge conflict
Expand All @@ -25,6 +27,14 @@ typedef NS_OPTIONS(NSInteger, GTMergeAnalysis) {
GTMergeAnalysisFastForward = GIT_MERGE_ANALYSIS_FASTFORWARD,
};

/// An enum describing the users' preference w.r.t fast-forward merges.
/// See `git_merge_preference_t`.
typedef NS_OPTIONS(NSInteger, GTMergePreference) {
GTMergePreferenceNone = GIT_MERGE_PREFERENCE_NONE,
GTMergePreferenceNoFastForward = GIT_MERGE_PREFERENCE_NO_FASTFORWARD,
GTMergePreferenceFastForwardOnly = GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY,
};

@interface GTRepository (Merging)

/// Enumerate all available merge head entries.
Expand Down Expand Up @@ -53,6 +63,16 @@ typedef NS_OPTIONS(NSInteger, GTMergeAnalysis) {
/// will point to an error describing what happened).
- (BOOL)mergeBranchIntoCurrentBranch:(GTBranch *)fromBranch withError:(NSError **)error;

/// Complete a pending merge
///
/// This method can be used to complete a merge that has been stopped because
/// of conflicts.
///
/// error - The error if one occurred. Can be NULL
///
/// Returns YES if the merge could be committed, NO otherwise.
- (BOOL)finalizeMerge:(NSError **)error;

/// Gets the file content with conflict markers for the given file
///
/// The parameters taked are the ones received from `enumerateConflictedFiles`.
Expand Down
Loading