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

Worktree support #642

Open
wants to merge 3 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
4 changes: 3 additions & 1 deletion ObjectiveGit/GTBlameHunk.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ - (GTSignature *)finalSignature {
}

- (NSString *)originalPath {
return @(self.git_blame_hunk.orig_path);
NSString *path = @(self.git_blame_hunk.orig_path);
NSAssert(path, @"string was nil");
return path;
}

- (BOOL)isBoundary {
Expand Down
5 changes: 4 additions & 1 deletion ObjectiveGit/GTConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ - (BOOL)deleteValueForKey:(NSString *)key error:(NSError **)error {
static int configCallback(const git_config_entry *entry, void *payload) {
NSMutableArray *configurationKeysArray = (__bridge NSMutableArray *)payload;

[configurationKeysArray addObject:@(entry->name)];
NSString *name = @(entry->name);
NSCAssert(name, @"string was nil");

[configurationKeysArray addObject:name];

return 0;
}
Expand Down
5 changes: 3 additions & 2 deletions ObjectiveGit/GTDiffFile.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ - (instancetype)initWithGitDiffFile:(git_diff_file)file {
self = [super init];
if (self == nil) return nil;

_path = @(file.path);
if (_path == nil) return nil;
NSString *path = @(file.path);
if (path == nil) return nil;
_path = path;

_git_diff_file = file;
_size = (NSUInteger)file.size;
Expand Down
11 changes: 7 additions & 4 deletions ObjectiveGit/GTFilterSource.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@ - (instancetype)initWithGitFilterSource:(const git_filter_source *)source {
self = [super init];
if (self == nil) return nil;

const char *path = git_repository_workdir(git_filter_source_repo(source));
_repositoryURL = [NSURL fileURLWithPath:@(path)];

_path = @(git_filter_source_path(source));
NSString *path = @(git_repository_workdir(git_filter_source_repo(source)));
NSAssert(path, @"workdir was nil");
_repositoryURL = [NSURL fileURLWithPath:path];

path = @(git_filter_source_path(source));
NSAssert(path, @"path was nil");
_path = path;

const git_oid *gitOid = git_filter_source_id(source);
if (gitOid != NULL) _OID = [[GTOID alloc] initWithGitOid:gitOid];
Expand Down
4 changes: 3 additions & 1 deletion ObjectiveGit/GTIndexEntry.m
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ - (instancetype)initWithGitIndexEntry:(const git_index_entry *)entry {
#pragma mark Properties

- (NSString *)path {
return @(self.git_index_entry->path);
NSString *path = @(self.git_index_entry->path);
NSAssert(path, @"path is nil");
return path;
}

- (int)flags {
Expand Down
4 changes: 3 additions & 1 deletion ObjectiveGit/GTNote.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ - (git_note *)git_note {
}

- (NSString *)note {
return @(git_note_message(self.git_note));
NSString *message = @(git_note_message(self.git_note));
NSAssert(message, @"message is nil");
return message;
}

- (GTSignature *)author {
Expand Down
8 changes: 5 additions & 3 deletions ObjectiveGit/GTReference.m
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,12 @@ - (BOOL)isNote {
}

- (NSString *)name {
const char *refName = git_reference_name(self.git_reference);
NSAssert(refName != nil, @"Unexpected nil name");
const char *cRefName = git_reference_name(self.git_reference);
NSAssert(cRefName != nil, @"Unexpected nil name");

return @(refName);
NSString *refName = @(cRefName);
NSAssert(refName, @"refname is nil");
return refName;
}

- (GTReference *)referenceByRenaming:(NSString *)newName error:(NSError **)error {
Expand Down
10 changes: 8 additions & 2 deletions ObjectiveGit/GTRepository+RemoteOperations.m
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,15 @@ int GTFetchHeadEntriesCallback(const char *ref_name, const char *remote_url, con
GTRepository *repository = entriesPayload->repository;
GTRemoteEnumerateFetchHeadEntryBlock enumerationBlock = entriesPayload->enumerationBlock;

GTReference *reference = [repository lookUpReferenceWithName:@(ref_name) error:NULL];
NSString *refName = @(ref_name);
NSCAssert(refName, @"refName is nil");

GTFetchHeadEntry *entry = [[GTFetchHeadEntry alloc] initWithReference:reference remoteURLString:@(remote_url) targetOID:[GTOID oidWithGitOid:oid] isMerge:(BOOL)is_merge];
NSString *remoteURL = @(remote_url);
NSCAssert(remote_url, @"remoteURL is nil");

GTReference *reference = [repository lookUpReferenceWithName:refName error:NULL];

GTFetchHeadEntry *entry = [[GTFetchHeadEntry alloc] initWithReference:reference remoteURLString:remoteURL targetOID:[GTOID oidWithGitOid:oid] isMerge:(BOOL)is_merge];

BOOL stop = NO;

Expand Down
42 changes: 42 additions & 0 deletions ObjectiveGit/GTRepository+Worktree.h
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
117 changes: 117 additions & 0 deletions ObjectiveGit/GTRepository+Worktree.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//
// 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 {
const char *cPath = git_repository_commondir(self.git_repository);
NSAssert(cPath, @"commondir is nil");

NSString *path = @(cPath);
NSAssert(path, @"commondir is nil");
return [NSURL fileURLWithPath:path 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
2 changes: 1 addition & 1 deletion ObjectiveGit/GTRepository.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ typedef NS_ENUM(NSInteger, GTRepositoryStateType) {
/// Returns nil for a bare repository.
@property (nonatomic, readonly, strong) NSURL * _Nullable fileURL;
/// The file URL for the repository's .git directory.
@property (nonatomic, readonly, strong) NSURL * _Nullable gitDirectoryURL;
@property (nonatomic, readonly, strong) NSURL *gitDirectoryURL;

/// Is this a bare repository (one without a working directory)?
@property (nonatomic, readonly, getter = isBare) BOOL bare;
Expand Down
20 changes: 13 additions & 7 deletions ObjectiveGit/GTRepository.m
Original file line number Diff line number Diff line change
Expand Up @@ -637,18 +637,22 @@ - (NSArray *)referenceNamesWithError:(NSError **)error {
}

- (NSURL *)fileURL {
const char *path = git_repository_workdir(self.git_repository);
const char *cPath = git_repository_workdir(self.git_repository);
// bare repository, you may be looking for gitDirectoryURL
if (path == NULL) return nil;
if (cPath == NULL) return nil;

return [NSURL fileURLWithPath:@(path) isDirectory:YES];
NSString *path = @(cPath);
NSAssert(path, @"workdir is nil");
return [NSURL fileURLWithPath:path isDirectory:YES];
}

- (NSURL *)gitDirectoryURL {
const char *path = git_repository_path(self.git_repository);
if (path == NULL) return nil;
const char *cPath = git_repository_path(self.git_repository);
NSAssert(cPath, @"gitdirectory is nil");

return [NSURL fileURLWithPath:@(path) isDirectory:YES];
NSString *path = @(cPath);
NSAssert(path, @"gitdirectory is nil");
return [NSURL fileURLWithPath:path isDirectory:YES];
}

- (BOOL)isBare {
Expand Down Expand Up @@ -737,7 +741,9 @@ static int submoduleEnumerationCallback(git_submodule *git_submodule, const char

NSError *error;
// Use -submoduleWithName:error: so that we get a git_submodule that we own.
GTSubmodule *submodule = [info->parentRepository submoduleWithName:@(name) error:&error];
NSString *submoduleName = @(name);
NSCAssert(submoduleName, @"submodule name is nil");
GTSubmodule *submodule = [info->parentRepository submoduleWithName:submoduleName error:&error];

BOOL stop = NO;
info->block(submodule, error, &stop);
Expand Down
15 changes: 12 additions & 3 deletions ObjectiveGit/GTSubmodule.m
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,30 @@ - (NSString *)name {
const char *cName = git_submodule_name(self.git_submodule);
NSAssert(cName != NULL, @"Unexpected nil submodule name");

return @(cName);
NSString *name = @(cName);
NSAssert(name, @"name is nil");

return name;
}

- (NSString *)path {
const char *cPath = git_submodule_path(self.git_submodule);
NSAssert(cPath != NULL, @"Unexpected nil submodule path");

return @(cPath);
NSString *path = @(cPath);
NSAssert(path, @"message is nil");

return path;
}

- (NSString *)URLString {
const char *cURL = git_submodule_url(self.git_submodule);
NSAssert(cURL != NULL, @"Unexpected nil submodule URL");

return @(cURL);
NSString *URL = @(cURL);
NSAssert(URL, @"URL is nil");

return URL;
}

#pragma mark Lifecycle
Expand Down
8 changes: 6 additions & 2 deletions ObjectiveGit/GTTag.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,15 @@ - (NSString *)description {
#pragma mark API

- (NSString *)message {
return @(git_tag_message(self.git_tag));
NSString *message = @(git_tag_message(self.git_tag));
NSAssert(message, @"message is nil");
return message;
}

- (NSString *)name {
return @(git_tag_name(self.git_tag));
NSString *name = @(git_tag_name(self.git_tag));
NSAssert(name, @"message is nil");
return name;
}

- (GTObject *)target {
Expand Down
4 changes: 3 additions & 1 deletion ObjectiveGit/GTTreeEntry.m
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ + (instancetype)entryWithEntry:(const git_tree_entry *)theEntry parentTree:(GTTr
}

- (NSString *)name {
return @(git_tree_entry_name(self.git_tree_entry));
NSString *name = @(git_tree_entry_name(self.git_tree_entry));
NSAssert(name, @"name was nil");
return name;
}

- (NSInteger)attributes {
Expand Down
Loading