-
Notifications
You must be signed in to change notification settings - Fork 280
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
309 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// | ||
// GTRepository+GTRepository_Worktree.h | ||
// ObjectiveGitFramework | ||
// | ||
// Created by Etienne on 25/07/2017. | ||
// Copyright © 2017 GitHub, Inc. All rights reserved. | ||
// | ||
|
||
#import <ObjectiveGit/ObjectiveGit.h> | ||
|
||
@class GTWorktree; | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface GTRepository (Worktree) | ||
|
||
/// Is this the worktree of another repository ? | ||
@property (nonatomic, readonly, getter = isWorktree) BOOL worktree; | ||
|
||
/// The URL for the underlying repository's git directory. | ||
/// Returns the same as -gitDirectoryURL if this is not a worktree. | ||
@property (nonatomic, readonly, strong) NSURL *commonGitDirectoryURL; | ||
|
||
+ (instancetype _Nullable)repositoryWithWorktree:(GTWorktree *)worktree error:(NSError **)error; | ||
|
||
- (instancetype _Nullable)initWithWorktree:(GTWorktree *)worktree error:(NSError **)error; | ||
|
||
- (GTReference * _Nullable)HEADReferenceInWorktreeWithName:(NSString *)name error:(NSError **)error; | ||
|
||
- (BOOL)isHEADDetached:(BOOL *)detached inWorktreeWithName:(NSString *)name error:(NSError **)error; | ||
|
||
- (BOOL)setWorkingDirectoryURL:(NSURL *)URL updateGitLink:(BOOL)update error:(NSError **)error; | ||
|
||
- (NSArray <NSString *> * _Nullable)worktreeNamesWithError:(NSError **)error; | ||
|
||
- (GTWorktree * _Nullable)lookupWorktreeWithName:(NSString *)name error:(NSError **)error; | ||
|
||
- (GTWorktree * _Nullable)openWorktree:(NSError **)error; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// | ||
// GTRepository+Worktree.m | ||
// ObjectiveGitFramework | ||
// | ||
// Created by Etienne on 25/07/2017. | ||
// Copyright © 2017 GitHub, Inc. All rights reserved. | ||
// | ||
|
||
#import "GTRepository+Worktree.h" | ||
|
||
@implementation GTRepository (Worktree) | ||
|
||
+ (instancetype)repositoryWithWorktree:(GTWorktree *)worktree error:(NSError **)error { | ||
return [[self alloc] initWithWorktree:worktree error:error]; | ||
} | ||
|
||
- (instancetype)initWithWorktree:(GTWorktree *)worktree error:(NSError **)error { | ||
NSParameterAssert(worktree != nil); | ||
|
||
git_repository *repo; | ||
int gitError = git_repository_open_from_worktree(&repo, worktree.git_worktree); | ||
if (gitError != GIT_OK) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to open worktree"]; | ||
return nil; | ||
} | ||
return [self initWithGitRepository:repo]; | ||
} | ||
|
||
- (BOOL)isWorktree { | ||
return (BOOL)git_repository_is_worktree(self.git_repository); | ||
} | ||
|
||
- (NSURL *)commonGitDirectoryURL { | ||
return [NSURL fileURLWithPath:@(git_repository_commondir(self.git_repository)) isDirectory:YES]; | ||
} | ||
|
||
- (GTReference *)HEADReferenceInWorktreeWithName:(NSString *)name error:(NSError **)error { | ||
NSParameterAssert(name != nil); | ||
|
||
git_reference *ref; | ||
int gitError = git_repository_head_for_worktree(&ref, self.git_repository, name.UTF8String); | ||
if (gitError != GIT_OK) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to resolve HEAD in worktree"]; | ||
return nil; | ||
} | ||
|
||
return [[GTReference alloc] initWithGitReference:ref repository:self]; | ||
} | ||
|
||
- (BOOL)isHEADDetached:(BOOL *)detached inWorktreeWithName:(NSString *)name error:(NSError **)error { | ||
NSParameterAssert(detached != nil); | ||
NSParameterAssert(name != nil); | ||
|
||
int gitError = git_repository_head_detached_for_worktree(self.git_repository, name.UTF8String); | ||
if (gitError < 0) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to resolve HEAD in worktree"]; | ||
return NO; | ||
} | ||
|
||
*detached = (gitError == 1); | ||
|
||
return YES; | ||
} | ||
|
||
- (BOOL)setWorkingDirectoryURL:(NSURL *)URL updateGitLink:(BOOL)update error:(NSError **)error { | ||
NSParameterAssert(URL != nil); | ||
|
||
int gitError = git_repository_set_workdir(self.git_repository, URL.fileSystemRepresentation, update); | ||
if (gitError != GIT_OK) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to set workdir"]; | ||
return NO; | ||
} | ||
|
||
return YES; | ||
} | ||
|
||
- (NSArray<NSString *> *)worktreeNamesWithError:(NSError **)error { | ||
git_strarray names; | ||
int gitError = git_worktree_list(&names, self.git_repository); | ||
if (gitError != GIT_OK) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to load worktree names"]; | ||
return nil; | ||
} | ||
|
||
return [NSArray git_arrayWithStrarray:names]; | ||
} | ||
|
||
- (GTWorktree *)lookupWorktreeWithName:(NSString *)name error:(NSError **)error { | ||
NSParameterAssert(name != nil); | ||
|
||
git_worktree *worktree; | ||
int gitError = git_worktree_lookup(&worktree, self.git_repository, name.UTF8String); | ||
if (gitError != GIT_OK) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to lookup worktree"]; | ||
return nil; | ||
} | ||
|
||
return [[GTWorktree alloc] initWithGitWorktree:worktree]; | ||
} | ||
|
||
- (GTWorktree *)openWorktree:(NSError **)error { | ||
git_worktree *worktree; | ||
int gitError = git_worktree_open_from_repository(&worktree, self.git_repository); | ||
if (gitError != GIT_OK) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to open worktree"]; | ||
return nil; | ||
} | ||
|
||
return [[GTWorktree alloc] initWithGitWorktree:worktree]; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// | ||
// GTWorktree.h | ||
// ObjectiveGitFramework | ||
// | ||
// Created by Etienne on 25/07/2017. | ||
// Copyright © 2017 GitHub, Inc. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
#import "GTRepository.h" | ||
|
||
#import "git2/worktree.h" | ||
|
||
typedef struct { | ||
BOOL lock; | ||
} GTWorktreeAddOptions; | ||
|
||
@interface GTWorktree : NSObject | ||
|
||
+ (instancetype)addWorktreeWithName:(NSString *)name URL:(NSURL *)worktreeURL forRepository:(GTRepository *)repository options:(const GTWorktreeAddOptions *)options error:(NSError **)error; | ||
|
||
- (instancetype)initWithGitWorktree:(git_worktree *)worktree; | ||
|
||
/// The underlying `git_worktree` object. | ||
- (git_worktree *)git_worktree __attribute__((objc_returns_inner_pointer)); | ||
|
||
- (BOOL)isValid:(NSError **)error; | ||
|
||
- (BOOL)lockWithReason:(NSString *)reason error:(NSError **)error; | ||
- (BOOL)unlock:(BOOL *)wasLocked error:(NSError **)error; | ||
|
||
- (BOOL)isLocked:(BOOL *)locked reason:(NSString **)reason error:(NSError **)error; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// | ||
// GTWorktree.m | ||
// ObjectiveGitFramework | ||
// | ||
// Created by Etienne on 25/07/2017. | ||
// Copyright © 2017 GitHub, Inc. All rights reserved. | ||
// | ||
|
||
#import "NSError+Git.h" | ||
#import "GTWorktree.h" | ||
|
||
#import "git2/errors.h" | ||
#import "git2/buffer.h" | ||
|
||
@interface GTWorktree () | ||
@property (nonatomic, assign, readonly) git_worktree *git_worktree; | ||
@end | ||
|
||
@implementation GTWorktree | ||
|
||
+ (instancetype)addWorktreeWithName:(NSString *)name URL:(NSURL *)worktreeURL forRepository:(GTRepository *)repository options:(const GTWorktreeAddOptions *)options error:(NSError **)error { | ||
git_worktree *worktree; | ||
git_worktree_add_options git_options = GIT_WORKTREE_ADD_OPTIONS_INIT; | ||
|
||
if (options) { | ||
git_options.lock = options->lock; | ||
} | ||
|
||
int gitError = git_worktree_add(&worktree, repository.git_repository, name.UTF8String, worktreeURL.fileSystemRepresentation, &git_options); | ||
if (gitError != GIT_OK) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to add worktree"]; | ||
return nil; | ||
} | ||
|
||
return [[self alloc] initWithGitWorktree:worktree]; | ||
} | ||
|
||
- (instancetype)initWithGitWorktree:(git_worktree *)worktree { | ||
self = [super init]; | ||
if (!self) return nil; | ||
|
||
_git_worktree = worktree; | ||
|
||
return self; | ||
} | ||
|
||
- (void)dealloc { | ||
git_worktree_free(_git_worktree); | ||
} | ||
|
||
- (BOOL)isValid:(NSError **)error { | ||
int gitError = git_worktree_validate(self.git_worktree); | ||
if (gitError < 0) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to validate worktree"]; | ||
return NO; | ||
} | ||
|
||
return YES; | ||
} | ||
|
||
- (BOOL)lockWithReason:(NSString *)reason error:(NSError **)error { | ||
int gitError = git_worktree_lock(self.git_worktree, (char *)reason.UTF8String); /* WIP: I don't like that cast */ | ||
if (gitError != GIT_OK) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to lock worktree"]; | ||
return NO; | ||
} | ||
|
||
return YES; | ||
} | ||
|
||
- (BOOL)unlock:(BOOL *)wasLocked error:(NSError **)error { | ||
int gitError = git_worktree_unlock(self.git_worktree); | ||
if (gitError < 0) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to unlock worktree"]; | ||
return NO; | ||
} | ||
|
||
if (wasLocked) { | ||
*wasLocked = (gitError == 0); | ||
} | ||
|
||
return YES; | ||
} | ||
|
||
- (BOOL)isLocked:(BOOL *)locked reason:(NSString **)reason error:(NSError **)error { | ||
git_buf reasonBuf; | ||
int gitError = git_worktree_is_locked(&reasonBuf, self.git_worktree); | ||
if (gitError < 0) { | ||
if (error) *error = [NSError git_errorFor:gitError description:@"Failed to check lock state of worktree"]; | ||
return NO; | ||
} | ||
|
||
if (locked) *locked = (gitError > 0); | ||
|
||
/* WIP: reason */ | ||
|
||
return YES; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters