diff --git a/ObjectiveGit/GTDiffPatch.h b/ObjectiveGit/GTDiffPatch.h index f2f372e36..3a27bf218 100644 --- a/ObjectiveGit/GTDiffPatch.h +++ b/ObjectiveGit/GTDiffPatch.h @@ -50,6 +50,9 @@ /// Returns the raw size of the delta, in bytes. - (NSUInteger)sizeWithContext:(BOOL)includeContext hunkHeaders:(BOOL)includeHunkHeaders fileHeaders:(BOOL)includeFileHeaders; +/// Returns the raw patch data. +- (NSData *)patchData; + /// Enumerate the hunks contained in the patch. /// /// This enumeration is synchronous, and will block the calling thread while diff --git a/ObjectiveGit/GTDiffPatch.m b/ObjectiveGit/GTDiffPatch.m index 2136e3add..6826d80a2 100644 --- a/ObjectiveGit/GTDiffPatch.m +++ b/ObjectiveGit/GTDiffPatch.m @@ -59,6 +59,16 @@ - (NSUInteger)sizeWithContext:(BOOL)includeContext hunkHeaders:(BOOL)includeHunk return git_patch_size(self.git_patch, includeContext, includeHunkHeaders, includeFileHeaders); } +- (NSData *)patchData { + git_buf buf = GIT_BUF_INIT_CONST(0, NULL); + git_patch_to_buf(&buf, self.git_patch); + + NSData *buffer = [[NSData alloc] initWithBytes:buf.ptr length:buf.size]; + git_buf_free(&buf); + + return buffer; +} + #pragma mark Hunks - (BOOL)enumerateHunksUsingBlock:(void (^)(GTDiffHunk *hunk, BOOL *stop))block { diff --git a/ObjectiveGit/GTTree.h b/ObjectiveGit/GTTree.h index b27f508eb..f3c521e8e 100644 --- a/ObjectiveGit/GTTree.h +++ b/ObjectiveGit/GTTree.h @@ -50,20 +50,27 @@ typedef NS_ENUM(NSInteger, GTTreeEnumerationOptions) { /// The underlying `git_object` as a `git_tree` object. - (git_tree *)git_tree __attribute__((objc_returns_inner_pointer)); -/// Get a entry at the specified index +/// Get an entry at the specified index /// /// index - index to retreive entry from /// /// returns a GTTreeEntry or nil if there is nothing at the index - (GTTreeEntry *)entryAtIndex:(NSUInteger)index; -/// Get a entry by name +/// Get an entry by name /// /// name - the name of the entry /// /// returns a GTTreeEntry or nil if there is nothing with the specified name - (GTTreeEntry *)entryWithName:(NSString *)name; +/// Get an entry by path +/// +/// path - the path of the entry relative to the repository root +/// +/// returns a GTTreeEntry or nil if there is nothing with the specified path +- (GTTreeEntry *)entryWithPath:(NSString *)path error:(NSError **)error; + /// Enumerates the contents of the tree /// /// options - One of `GTTreeEnumerationOptionPre` (for pre-order walks) or diff --git a/ObjectiveGit/GTTree.m b/ObjectiveGit/GTTree.m index cba186322..6fbf1a848 100644 --- a/ObjectiveGit/GTTree.m +++ b/ObjectiveGit/GTTree.m @@ -56,16 +56,29 @@ - (NSUInteger)entryCount { return (NSUInteger)git_tree_entrycount(self.git_tree); } -- (GTTreeEntry *)createEntryWithEntry:(const git_tree_entry *)entry { - return (entry != NULL ? [GTTreeEntry entryWithEntry:entry parentTree:self] : nil); +- (GTTreeEntry *)createEntryWithEntry:(const git_tree_entry *)entry error:(NSError **)error { + return (entry != NULL ? [GTTreeEntry entryWithEntry:entry parentTree:self error:nil] : nil); } - (GTTreeEntry *)entryAtIndex:(NSUInteger)index { - return [self createEntryWithEntry:git_tree_entry_byindex(self.git_tree, index)]; + return [self createEntryWithEntry:git_tree_entry_byindex(self.git_tree, index) error:nil]; } - (GTTreeEntry *)entryWithName:(NSString *)name { - return [self createEntryWithEntry:git_tree_entry_byname(self.git_tree, name.UTF8String)]; + return [self createEntryWithEntry:git_tree_entry_byname(self.git_tree, name.UTF8String) error:nil]; +} + +- (GTTreeEntry *)entryWithPath:(NSString *)path error:(NSError **)error { + git_tree_entry *internalEntry = NULL; + int gitError = git_tree_entry_bypath(&internalEntry, self.git_tree, path.UTF8String); + if (error != GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to get tree entry %@", path]; + return nil; + } + + GTTreeEntry *entry = [self createEntryWithEntry:internalEntry error:error]; + git_tree_entry_free(internalEntry); + return entry; } - (git_tree *)git_tree { @@ -79,7 +92,7 @@ static int treewalk_cb(const char *root, const git_tree_entry *git_entry, void * NSString *rootString = @(root); GTTreeEntry *parentEntry = enumerationStruct->directoryStructure[rootString]; GTTree *parentTree = parentEntry != nil ? parentEntry.tree : enumerationStruct->myself; - GTTreeEntry *entry = [GTTreeEntry entryWithEntry:git_entry parentTree:parentTree]; + GTTreeEntry *entry = [GTTreeEntry entryWithEntry:git_entry parentTree:parentTree error:nil]; if (entry.type == GTObjectTypeTree) { NSString *path = [rootString stringByAppendingPathComponent:entry.name]; diff --git a/ObjectiveGit/GTTreeBuilder.m b/ObjectiveGit/GTTreeBuilder.m index 6e6bdbab7..50a51a892 100644 --- a/ObjectiveGit/GTTreeBuilder.m +++ b/ObjectiveGit/GTTreeBuilder.m @@ -110,7 +110,7 @@ - (GTTreeEntry *)entryWithFileName:(NSString *)fileName { const git_tree_entry *entry = git_treebuilder_get(self.git_treebuilder, fileName.UTF8String); if (entry == NULL) return nil; - return [GTTreeEntry entryWithEntry:entry parentTree:nil]; + return [GTTreeEntry entryWithEntry:entry parentTree:nil error:nil]; } - (GTTreeEntry *)addEntryWithData:(NSData *)data fileName:(NSString *)fileName fileMode:(GTFileMode)fileMode error:(NSError **)error { @@ -139,7 +139,7 @@ - (GTTreeEntry *)addEntryWithOID:(GTOID *)oid fileName:(NSString *)fileName file return nil; } - return [GTTreeEntry entryWithEntry:entry parentTree:nil]; + return [GTTreeEntry entryWithEntry:entry parentTree:nil error:error]; } - (BOOL)removeEntryWithFileName:(NSString *)fileName error:(NSError **)error { diff --git a/ObjectiveGit/GTTreeEntry.h b/ObjectiveGit/GTTreeEntry.h index 67e3c1027..35182e754 100644 --- a/ObjectiveGit/GTTreeEntry.h +++ b/ObjectiveGit/GTTreeEntry.h @@ -34,11 +34,11 @@ @interface GTTreeEntry : NSObject /// Initializer and convience methods. -- (instancetype)initWithEntry:(const git_tree_entry *)theEntry parentTree:(GTTree *)parent; -+ (instancetype)entryWithEntry:(const git_tree_entry *)theEntry parentTree:(GTTree *)parent; +- (instancetype)initWithEntry:(const git_tree_entry *)theEntry parentTree:(GTTree *)parent error:(NSError **)error; ++ (instancetype)entryWithEntry:(const git_tree_entry *)theEntry parentTree:(GTTree *)parent error:(NSError **)error; /// The underlying `git_tree_entry`. -- (const git_tree_entry *)git_tree_entry __attribute__((objc_returns_inner_pointer)); +- (git_tree_entry *)git_tree_entry __attribute__((objc_returns_inner_pointer)); /// The entry's parent tree. This may be nil if nil is passed in to -initWithEntry: @property (nonatomic, strong, readonly) GTTree *tree; diff --git a/ObjectiveGit/GTTreeEntry.m b/ObjectiveGit/GTTreeEntry.m index b29bb4cf2..809ae0eae 100644 --- a/ObjectiveGit/GTTreeEntry.m +++ b/ObjectiveGit/GTTreeEntry.m @@ -38,7 +38,7 @@ #import "git2/errors.h" @interface GTTreeEntry () -@property (nonatomic, assign, readonly) const git_tree_entry *git_tree_entry; +@property (nonatomic, assign, readonly) git_tree_entry *git_tree_entry; @end @implementation GTTreeEntry @@ -64,19 +64,33 @@ - (BOOL)isEqualToEntry:(GTTreeEntry *)treeEntry { return git_tree_entry_cmp(self.git_tree_entry, treeEntry.git_tree_entry) == 0 ? YES : NO; } +- (void)dealloc { + git_tree_entry_free(_git_tree_entry); +} + #pragma mark API -- (instancetype)initWithEntry:(const git_tree_entry *)theEntry parentTree:(GTTree *)parent { +- (instancetype)initWithEntry:(const git_tree_entry *)theEntry parentTree:(GTTree *)parent error:(NSError **)error { NSParameterAssert(theEntry != NULL); - if((self = [super init])) { - _git_tree_entry = theEntry; - _tree = parent; + + self = [super init]; + if (self == nil) return nil; + + git_tree_entry *copyOfEntry = nil; + int gitError = git_tree_entry_dup(©OfEntry, theEntry); + if (gitError != GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to duplicate tree entry."]; + return nil; } + + _git_tree_entry = copyOfEntry; + _tree = parent; + return self; } -+ (instancetype)entryWithEntry:(const git_tree_entry *)theEntry parentTree:(GTTree *)parent { - return [[self alloc] initWithEntry:theEntry parentTree:parent]; ++ (instancetype)entryWithEntry:(const git_tree_entry *)theEntry parentTree:(GTTree *)parent error:(NSError **)error { + return [[self alloc] initWithEntry:theEntry parentTree:parent error:error]; } - (NSString *)name { diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index 009d9faeb..26d1bc541 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -311,6 +311,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 3D6123BD1A6432F6008F831A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D0A330ED16027F1E00A616FA; + remoteInfo = libgit2; + }; 6A28265A17C69D6300C6A948 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; @@ -346,13 +353,6 @@ remoteGlobalIDString = D0A330F216027F3600A616FA; remoteInfo = "libgit2-iOS"; }; - D0A330F716027F4900A616FA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; - proxyType = 1; - remoteGlobalIDString = D0A330ED16027F1E00A616FA; - remoteInfo = libgit2; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -1094,7 +1094,7 @@ buildRules = ( ); dependencies = ( - D0A330F816027F4900A616FA /* PBXTargetDependency */, + 3D6123BE1A6432F6008F831A /* PBXTargetDependency */, ); name = "ObjectiveGit-Mac"; productInstallPath = "$(HOME)/Library/Frameworks"; @@ -1396,6 +1396,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 3D6123BE1A6432F6008F831A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D0A330ED16027F1E00A616FA /* libgit2 */; + targetProxy = 3D6123BD1A6432F6008F831A /* PBXContainerItemProxy */; + }; 6A28265B17C69D6300C6A948 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 6A28265217C69CB400C6A948 /* OpenSSL-iOS */; @@ -1421,11 +1426,6 @@ target = D0A330F216027F3600A616FA /* libgit2-iOS */; targetProxy = D019779619F8335100F523DA /* PBXContainerItemProxy */; }; - D0A330F816027F4900A616FA /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = D0A330ED16027F1E00A616FA /* libgit2 */; - targetProxy = D0A330F716027F4900A616FA /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */