From 618570bb0f89717de7fb3715732b58a8e4052ded Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 7 Nov 2013 18:36:47 +0100 Subject: [PATCH 01/61] Rewrite tests for GTBlob. --- .../project.pbxproj | 8 +- ObjectiveGitTests/GTBlobSpec.m | 92 ++++++++++++++ ObjectiveGitTests/GTBlobTest.m | 118 ------------------ 3 files changed, 96 insertions(+), 122 deletions(-) create mode 100644 ObjectiveGitTests/GTBlobSpec.m delete mode 100644 ObjectiveGitTests/GTBlobTest.m diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index a42b5973a..d2f777562 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -139,6 +139,7 @@ 3E0A23E5159E0FDB00A6068F /* GTObjectDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 55C8054C13861F34004DCB0F /* GTObjectDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4D103ADD1819CFAA0029DB24 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D103ADC1819CFAA0029DB24 /* libiconv.dylib */; }; 4D123240178E009E0048F785 /* GTRepositoryCommittingSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D12323F178E009E0048F785 /* GTRepositoryCommittingSpec.m */; }; + 4D1C40D8182C006D00BE2960 /* GTBlobSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D1C40D7182C006D00BE2960 /* GTBlobSpec.m */; }; 4D26799F178DAF31002A2795 /* GTTreeEntry+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D26799D178DAF31002A2795 /* GTTreeEntry+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4D79C0EE17DF9F4D00997DE4 /* GTCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D79C0EC17DF9F4D00997DE4 /* GTCredential.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4D79C0EF17DF9F4D00997DE4 /* GTCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79C0ED17DF9F4D00997DE4 /* GTCredential.m */; }; @@ -199,7 +200,6 @@ 88EB7E4E14AEBA600046FEA4 /* GTConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 88EB7E4C14AEBA600046FEA4 /* GTConfiguration.m */; }; 88F05A9D16011F6A00B7AD1D /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88F05A9C16011F6A00B7AD1D /* SenTestingKit.framework */; }; 88F05A9E16011F6E00B7AD1D /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ObjectiveGit.framework */; }; - 88F05AB316011FFD00B7AD1D /* GTBlobTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA216011FFD00B7AD1D /* GTBlobTest.m */; }; 88F05AB416011FFD00B7AD1D /* GTBranchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA316011FFD00B7AD1D /* GTBranchTest.m */; }; 88F05AB516011FFD00B7AD1D /* GTCommitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA416011FFD00B7AD1D /* GTCommitTest.m */; }; 88F05AB916011FFD00B7AD1D /* GTObjectTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */; }; @@ -515,6 +515,7 @@ 32DBCF5E0370ADEE00C91783 /* ObjectiveGitFramework_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectiveGitFramework_Prefix.pch; sourceTree = ""; }; 4D103ADC1819CFAA0029DB24 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; 4D12323F178E009E0048F785 /* GTRepositoryCommittingSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTRepositoryCommittingSpec.m; sourceTree = ""; }; + 4D1C40D7182C006D00BE2960 /* GTBlobSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTBlobSpec.m; sourceTree = ""; }; 4D26799D178DAF31002A2795 /* GTTreeEntry+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTTreeEntry+Private.h"; sourceTree = ""; }; 4D79C0EC17DF9F4D00997DE4 /* GTCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTCredential.h; sourceTree = ""; }; 4D79C0ED17DF9F4D00997DE4 /* GTCredential.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCredential.m; sourceTree = ""; }; @@ -566,7 +567,6 @@ 88F05A7916011E5400B7AD1D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 88F05A7E16011E5400B7AD1D /* ObjectiveGitTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ObjectiveGitTests-Prefix.pch"; sourceTree = ""; }; 88F05A9C16011F6A00B7AD1D /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; - 88F05AA216011FFD00B7AD1D /* GTBlobTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTBlobTest.m; sourceTree = ""; }; 88F05AA316011FFD00B7AD1D /* GTBranchTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTBranchTest.m; sourceTree = ""; }; 88F05AA416011FFD00B7AD1D /* GTCommitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCommitTest.m; sourceTree = ""; }; 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTObjectTest.m; sourceTree = ""; }; @@ -821,7 +821,7 @@ isa = PBXGroup; children = ( 88F05A7616011E5400B7AD1D /* Supporting Files */, - 88F05AA216011FFD00B7AD1D /* GTBlobTest.m */, + 4D1C40D7182C006D00BE2960 /* GTBlobSpec.m */, 88A994B916FCE7D400402C7B /* GTBranchSpec.m */, 88F05AA316011FFD00B7AD1D /* GTBranchTest.m */, 88F05AA416011FFD00B7AD1D /* GTCommitTest.m */, @@ -1523,8 +1523,8 @@ files = ( 88F05AC816012CEE00B7AD1D /* NSData+Git.m in Sources */, 88F05AC716012CE500B7AD1D /* NSString+Git.m in Sources */, - 88F05AB316011FFD00B7AD1D /* GTBlobTest.m in Sources */, 88F05AB416011FFD00B7AD1D /* GTBranchTest.m in Sources */, + 4D1C40D8182C006D00BE2960 /* GTBlobSpec.m in Sources */, 88F05AB516011FFD00B7AD1D /* GTCommitTest.m in Sources */, 88F05AB916011FFD00B7AD1D /* GTObjectTest.m in Sources */, 88F05ABA16011FFD00B7AD1D /* GTReferenceTest.m in Sources */, diff --git a/ObjectiveGitTests/GTBlobSpec.m b/ObjectiveGitTests/GTBlobSpec.m new file mode 100644 index 000000000..1344b6bf7 --- /dev/null +++ b/ObjectiveGitTests/GTBlobSpec.m @@ -0,0 +1,92 @@ +// +// GTBlobSpec.m +// ObjectiveGitFramework +// +// Created by Etienne Samson on 2013-11-07. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "GTBlob.h" + +SpecBegin(GTBlob) + +__block GTRepository *repository; +__block NSString *blobSHA; +__block GTBlob *blob; +__block NSError *error; + +beforeEach(^{ + error = nil; +}); + +describe(@"blob properties can be accessed", ^{ + beforeEach(^{ + repository = self.bareFixtureRepository; + blobSHA = @"fa49b077972391ad58037050f2a75f74e3671e92"; + blob = [repository lookupObjectBySHA:blobSHA objectType:GTObjectTypeBlob error:NULL]; + expect(blob).notTo.beNil(); + }); + + it(@"has a size", ^{ + expect(blob.size).to.equal(9); + }); + + it(@"has content", ^{ + expect(blob.content).to.equal(@"new file\n"); + }); + + it(@"has type", ^{ + expect(blob.type).to.equal(@"blob"); + }); + + it(@"has a SHA", ^{ + expect(blob.SHA).to.equal(blobSHA); + }); +}); + +describe(@"blobs can be created", ^{ + beforeEach(^{ + repository = self.testAppFixtureRepository; + }); + + describe(@"+blobWithString:inRepository:error", ^{ + it(@"works with valid parameters", ^{ + blob = [GTBlob blobWithString:@"a new blob content" inRepository:repository error:&error]; + expect(error).to.beNil(); + expect(blob).notTo.beNil(); + expect(blob.SHA).notTo.beNil(); + }); + }); + + describe(@"+blobWithData:inRepository:error", ^{ + it(@"works with valid parameters", ^{ + char bytes[] = "100644 example_helper.rb\00\xD3\xD5\xED\x9D A4_\x00 40000 examples"; + NSData *content = [NSData dataWithBytes:bytes length:sizeof(bytes)]; + + blob = [GTBlob blobWithData:content inRepository:repository error:&error]; + expect(error).to.beNil(); + expect(blob).notTo.beNil(); + expect(blob.SHA).notTo.beNil(); + }); + }); + + describe(@"+blobWithFile:inRepository:error", ^{ + it(@"works with valid parameters", ^{ + NSString *fileContent = @"Test contents\n"; + NSString *fileName = @"myfile.txt"; + NSURL *fileURL = [repository.fileURL URLByAppendingPathComponent:fileName]; + + BOOL success = [fileContent writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:&error]; + expect(success).to.beTruthy(); + expect(error).to.beNil(); + + blob = [GTBlob blobWithFile:fileURL inRepository:repository error:&error]; + expect(error).to.beNil(); + expect(blob).notTo.beNil(); + expect(blob.SHA).notTo.beNil(); + expect(blob.content).to.equal(fileContent); + }); + }); +}); + +SpecEnd diff --git a/ObjectiveGitTests/GTBlobTest.m b/ObjectiveGitTests/GTBlobTest.m deleted file mode 100644 index 69de7b34e..000000000 --- a/ObjectiveGitTests/GTBlobTest.m +++ /dev/null @@ -1,118 +0,0 @@ -// -// GTBlobTest.m -// ObjectiveGitFramework -// -// Created by Timothy Clem on 2/25/11. -// -// The MIT License -// -// Copyright (c) 2011 Tim Clem -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -@interface GTBlobTest : GTTestCase { - - GTRepository *repo; - NSString *blobSHA; -} -@end - -@implementation GTBlobTest - -- (void)setUp { - repo = self.bareFixtureRepository; - blobSHA = @"fa49b077972391ad58037050f2a75f74e3671e92"; -} - -- (void)testCanReadBlobData { - NSError *error = nil; - GTBlob *blob = [repo lookupObjectBySHA:blobSHA error:&error]; - STAssertEquals(9, (int)blob.size, nil); - STAssertEqualObjects(@"new file\n", blob.content, nil); - STAssertEqualObjects(@"blob", blob.type, nil); - STAssertEqualObjects(blobSHA, blob.SHA, nil); -} - -// todo -/* -- (void)testCanRewriteBlobData { - - NSError *error = nil; - GTBlob *blob = (GTBlob *)[repo lookupBySha:sha error:&error]; - blob.content = @"my new content"; - STAssertEqualObjects(sha, blob.sha, nil); - - NSString *newSha = [blob writeAndReturnError:&error]; - - STAssertNil(error, [error localizedDescription]); - STAssertEqualObjects(@"2dd916ea1ff086d61fbc1c286079305ffad4e92e", blob.sha, nil); - STAssertEqualObjects(@"2dd916ea1ff086d61fbc1c286079305ffad4e92e", newSha, nil); - rm_loose(blob.sha); -} -*/ - -- (void)testCanWriteNewBlobData { - - NSError *error = nil; - GTBlob *blob = [GTBlob blobWithString:@"a new blob content" inRepository:repo error:&error]; - NSString *newSHA = [blob SHA]; - STAssertNotNil(newSHA, [error localizedDescription]); -} - -- (void)testCanWriteNewBlobData2 { - - NSError *error = nil; - GTBlob *blob = [GTBlob blobWithString:@"a new blob content" inRepository:repo error:&error]; - STAssertNotNil(blob, [error localizedDescription]); -} - -//- (void)testCanGetCompleteContentWithNulls { -// -// NSError *error = nil; -// char bytes[] = "100644 example_helper.rb\00\xD3\xD5\xED\x9D A4_\x00 40000 examples"; -// NSData *content = [NSData dataWithBytes:bytes length:sizeof(bytes)]; -// -// GTBlob *blob = [GTBlob blobWithData:content inRepository:repo error:&error]; -// NSString *newSha = [blob sha]; -// STAssertNotNil(newSha, [error localizedDescription]); -// -// rm_loose(self.class, newSha); -// -// //todo -// /*GTRawObject *obj = [GTRawObject rawObjectWithType:GTObjectTypeBlob data:content]; -// NSString *newSha = [repo write:obj error:&error]; -// -// STAssertNil(error, [error localizedDescription]); -// STAssertNotNil(newSha, nil); -// GTBlob *blob = (GTBlob *)[repo lookupBySha:newSha error:&error]; -// GTRawObject *newObj = [blob readRawAndReturnError:&error]; -// STAssertNil(error, [error localizedDescription]); -// NSLog(@"original content = %@", [obj data]); -// NSLog(@"lookup content = %@", [newObj data]); -// STAssertEqualObjects(newObj.data, obj.data, nil); -// rm_loose(newSha);*/ -//} - -// todo -//- (void)testCanCreateBlobFromFile { -// -//} - -@end From ed0a2a80e4098b83284bb129c8a357a7e1265872 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 7 Nov 2013 18:38:13 +0100 Subject: [PATCH 02/61] Use `git_blob_create_fromdisk` instead of going through the `fromworkdir` version. Because I don't want to handle the pain of relativizing the passed URL. --- Classes/GTBlob.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/GTBlob.m b/Classes/GTBlob.m index e65b11b91..4bd5ff1cf 100644 --- a/Classes/GTBlob.m +++ b/Classes/GTBlob.m @@ -87,7 +87,7 @@ - (id)initWithData:(NSData *)data inRepository:(GTRepository *)repository error: - (id)initWithFile:(NSURL *)file inRepository:(GTRepository *)repository error:(NSError **)error { git_oid oid; - int gitError = git_blob_create_fromworkdir(&oid, repository.git_repository, [[file path] UTF8String]); + int gitError = git_blob_create_fromdisk(&oid, repository.git_repository, [[file path] fileSystemRepresentation]); if(gitError < GIT_OK) { if(error != NULL) { *error = [NSError git_errorFor:gitError description:@"Failed to create blob from NSURL"]; From b7f671f431798324aebb7c72c8884bde058a3c16 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 7 Nov 2013 18:39:48 +0100 Subject: [PATCH 03/61] Asserts. --- Classes/GTBlob.m | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Classes/GTBlob.m b/Classes/GTBlob.m index 4bd5ff1cf..c522e8be8 100644 --- a/Classes/GTBlob.m +++ b/Classes/GTBlob.m @@ -55,6 +55,9 @@ + (id)blobWithFile:(NSURL *)file inRepository:(GTRepository *)repository error:( } - (id)initWithOid:(const git_oid *)oid inRepository:(GTRepository *)repository error:(NSError **)error { + NSParameterAssert(oid != NULL); + NSParameterAssert(repository != nil); + git_object *obj; int gitError = git_object_lookup(&obj, repository.git_repository, oid, (git_otype) GTObjectTypeBlob); if (gitError < GIT_OK) { @@ -73,6 +76,9 @@ - (id)initWithString:(NSString *)string inRepository:(GTRepository *)repository } - (id)initWithData:(NSData *)data inRepository:(GTRepository *)repository error:(NSError **)error { + NSParameterAssert(data != nil); + NSParameterAssert(repository != nil); + git_oid oid; int gitError = git_blob_create_frombuffer(&oid, repository.git_repository, [data bytes], data.length); if(gitError < GIT_OK) { @@ -86,6 +92,9 @@ - (id)initWithData:(NSData *)data inRepository:(GTRepository *)repository error: } - (id)initWithFile:(NSURL *)file inRepository:(GTRepository *)repository error:(NSError **)error { + NSParameterAssert(file != nil); + NSParameterAssert(repository != nil); + git_oid oid; int gitError = git_blob_create_fromdisk(&oid, repository.git_repository, [[file path] fileSystemRepresentation]); if(gitError < GIT_OK) { From 709c2b31e00fbeec9eb39fe2ee2689c0a3f3a7c5 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 7 Nov 2013 19:39:57 +0100 Subject: [PATCH 04/61] Move the contents of `GTBranchTest` where they belong. --- ObjectiveGitTests/GTBranchSpec.m | 78 ++++++++++++++++++++++++++++ ObjectiveGitTests/GTBranchTest.m | 60 --------------------- ObjectiveGitTests/GTRepositorySpec.m | 29 +++++++++++ 3 files changed, 107 insertions(+), 60 deletions(-) diff --git a/ObjectiveGitTests/GTBranchSpec.m b/ObjectiveGitTests/GTBranchSpec.m index 7b1e30e0f..ed8c0a318 100644 --- a/ObjectiveGitTests/GTBranchSpec.m +++ b/ObjectiveGitTests/GTBranchSpec.m @@ -127,4 +127,82 @@ }); }); +describe(@"-numberOfCommitsWithError:", ^{ + it(@"should return the count of commits in the branch", ^{ + NSError *error = nil; + NSUInteger commitCount = [masterBranch numberOfCommitsWithError:&error]; + expect(commitCount).to.equal(164); + }); +}); + +describe(@"-trackingBranchWithError:success:", ^{ + it(@"should return the tracking branch for a local branch that tracks a remote branch", ^{ + NSError *error = nil; + GTBranch *masterBranch = [GTBranch branchWithName:@"refs/heads/master" repository:repository error:&error]; + expect(masterBranch).notTo.beNil(); + expect(error).to.beNil(); + + BOOL success = NO; + GTBranch *trackingBranch = [masterBranch trackingBranchWithError:&error success:&success]; + expect(trackingBranch).notTo.beNil(); + expect(success).to.beTruthy(); + }); + + it(@"should return nil for a local branch that doesn't track a remote branch", ^{ + NSError *error = nil; + GTReference *otherRef = [GTReference referenceByCreatingReferenceNamed:@"refs/heads/yet-another-branch" fromReferenceTarget:@"6b0c1c8b8816416089c534e474f4c692a76ac14f" inRepository:repository error:&error]; + expect(otherRef).notTo.beNil(); + expect(error).to.beNil(); + + GTBranch *otherBranch = [GTBranch branchWithReference:otherRef repository:repository]; + expect(otherBranch).notTo.beNil(); + expect(error).to.beNil(); + + BOOL success = NO; + trackingBranch = [otherBranch trackingBranchWithError:&error success:&success]; + expect(trackingBranch).to.beNil(); + expect(success).to.beTruthy(); + }); + + it(@"should return itself for a remote branch", ^{ + NSError *error = nil; + GTReference *remoteRef = [GTReference referenceByLookingUpReferencedNamed:@"refs/remotes/origin/master" inRepository:repository error:&error]; + expect(remoteRef).notTo.beNil(); + expect(error).to.beNil(); + + GTBranch *remoteBranch = [GTBranch branchWithReference:remoteRef repository:repository]; + expect(remoteBranch).notTo.beNil(); + + BOOL success = NO; + GTBranch *remoteTrackingBranch = [remoteBranch trackingBranchWithError:&error success:&success]; + expect(remoteTrackingBranch).to.equal(remoteBranch); + expect(success).to.beTruthy(); + }); +}); + +// TODO: Test branch renaming, branch upstream +/* + - (void)testCanRenameBranch { + + NSError *error = nil; + GTRepository *repo = [GTRepository repoByOpeningRepositoryInDirectory:[NSURL URLWithString:TEST_REPO_PATH()] error:&error]; + STAssertNil(error, [error localizedDescription]); + + NSArray *branches = [GTBranch listAllLocalBranchesInRepository:repo error:&error]; + STAssertNotNil(branches, [error localizedDescription], nil); + STAssertEquals(2, (int)branches.count, nil); + + NSString *newBranchName = [NSString stringWithFormat:@"%@%@", [GTBranch localNamePrefix], @"this_is_the_renamed_branch"]; + GTBranch *firstBranch = [branches objectAtIndex:0]; + NSString *originalBranchName = firstBranch.name; + BOOL success = [firstBranch.reference setName:newBranchName error:&error]; + STAssertTrue(success, [error localizedDescription]); + STAssertEqualObjects(firstBranch.name, newBranchName, nil); + + success = [firstBranch.reference setName:originalBranchName error:&error]; + STAssertTrue(success, [error localizedDescription]); + STAssertEqualObjects(firstBranch.name, originalBranchName, nil); + } + */ + SpecEnd diff --git a/ObjectiveGitTests/GTBranchTest.m b/ObjectiveGitTests/GTBranchTest.m index 83252e65a..4f9ff2077 100644 --- a/ObjectiveGitTests/GTBranchTest.m +++ b/ObjectiveGitTests/GTBranchTest.m @@ -18,42 +18,6 @@ - (void)setUp { repo = self.bareFixtureRepository; } -- (void)testCanOpenHeadInRepo { - - NSError *error = nil; - GTBranch *current = [repo currentBranchWithError:&error]; - STAssertNil(error, [error localizedDescription]); - STAssertNotNil(current, nil); -} - -- (void)testCanListLocalBranchesInRepo { - - NSError *error = nil; - NSArray *branches = [repo localBranchesWithError:&error]; - STAssertNotNil(branches, [error localizedDescription], nil); - STAssertEquals(2, (int)branches.count, nil); -} - -- (void)testCanListRemoteBranchesInRepo { - - NSError *error = nil; - NSArray *branches = [repo remoteBranchesWithError:&error]; - STAssertNotNil(branches, [error localizedDescription], nil); - STAssertEquals(0, (int)branches.count, nil); -} - -- (void)testCanCountCommitsInBranch { - - NSError *error = nil; - GTReference *head = [repo headReferenceWithError:&error]; - STAssertNotNil(head, [error localizedDescription]); - GTBranch *master = [GTBranch branchWithReference:head repository:repo]; - STAssertNotNil(master, [error localizedDescription]); - - NSUInteger n = [master numberOfCommitsWithError:&error]; - STAssertEquals((NSUInteger)3, n, nil); -} - - (void)testRetainOfBranchCreatedWithRef { // Hard to test the autoreleasepool, so manually alloc/init instead. @@ -69,28 +33,4 @@ - (void)testRetainOfBranchCreatedWithRef { STAssertNotNil(current.reference, nil); } -/* -- (void)testCanRenameBranch { - - NSError *error = nil; - GTRepository *repo = [GTRepository repoByOpeningRepositoryInDirectory:[NSURL URLWithString:TEST_REPO_PATH()] error:&error]; - STAssertNil(error, [error localizedDescription]); - - NSArray *branches = [GTBranch listAllLocalBranchesInRepository:repo error:&error]; - STAssertNotNil(branches, [error localizedDescription], nil); - STAssertEquals(2, (int)branches.count, nil); - - NSString *newBranchName = [NSString stringWithFormat:@"%@%@", [GTBranch localNamePrefix], @"this_is_the_renamed_branch"]; - GTBranch *firstBranch = [branches objectAtIndex:0]; - NSString *originalBranchName = firstBranch.name; - BOOL success = [firstBranch.reference setName:newBranchName error:&error]; - STAssertTrue(success, [error localizedDescription]); - STAssertEqualObjects(firstBranch.name, newBranchName, nil); - - success = [firstBranch.reference setName:originalBranchName error:&error]; - STAssertTrue(success, [error localizedDescription]); - STAssertEqualObjects(firstBranch.name, originalBranchName, nil); -} - */ - @end diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index f430d147f..ff49f2717 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -87,6 +87,35 @@ }); }); +describe(@"-currentBranchWithError:", ^{ + it(@"should return the current branch", ^{ + NSError *error = nil; + GTBranch *currentBranch = [repository currentBranchWithError:&error]; + expect(currentBranch).notTo.beNil(); + expect(error).to.beNil(); + }); +}); + +describe(@"-localBranchesWithError:", ^{ + it(@"should return the local branches", ^{ + NSError *error = nil; + NSArray *branches = [repository localBranchesWithError:&error]; + expect(branches).notTo.beNil(); + expect(error).to.beNil(); + expect(branches.count).to.equal(13); + }); +}); + +describe(@"-remoteBranchesWithError:", ^{ + it(@"should return remote branches", ^{ + NSError *error = nil; + NSArray *branches = [repository remoteBranchesWithError:&error]; + expect(branches).notTo.beNil(); + expect(error).to.beNil(); + expect(branches.count).to.equal(1); + }); +}); + describe(@"-OIDByCreatingTagNamed:target:tagger:message:error", ^{ it(@"should create a new tag",^{ NSError *error = nil; From 9e69d7c90933877d27cb1c9718e201e2d71361db Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 7 Nov 2013 19:40:51 +0100 Subject: [PATCH 05/61] Remove `GTBranchTest`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I know there's still a test in here, but I'm not sure what it's testing since we're ARC now… --- .../project.pbxproj | 4 --- ObjectiveGitTests/GTBranchTest.m | 36 ------------------- 2 files changed, 40 deletions(-) delete mode 100644 ObjectiveGitTests/GTBranchTest.m diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index d2f777562..bd596d4e5 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -200,7 +200,6 @@ 88EB7E4E14AEBA600046FEA4 /* GTConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 88EB7E4C14AEBA600046FEA4 /* GTConfiguration.m */; }; 88F05A9D16011F6A00B7AD1D /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88F05A9C16011F6A00B7AD1D /* SenTestingKit.framework */; }; 88F05A9E16011F6E00B7AD1D /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ObjectiveGit.framework */; }; - 88F05AB416011FFD00B7AD1D /* GTBranchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA316011FFD00B7AD1D /* GTBranchTest.m */; }; 88F05AB516011FFD00B7AD1D /* GTCommitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA416011FFD00B7AD1D /* GTCommitTest.m */; }; 88F05AB916011FFD00B7AD1D /* GTObjectTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */; }; 88F05ABA16011FFD00B7AD1D /* GTReferenceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA916011FFD00B7AD1D /* GTReferenceTest.m */; }; @@ -567,7 +566,6 @@ 88F05A7916011E5400B7AD1D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 88F05A7E16011E5400B7AD1D /* ObjectiveGitTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ObjectiveGitTests-Prefix.pch"; sourceTree = ""; }; 88F05A9C16011F6A00B7AD1D /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; - 88F05AA316011FFD00B7AD1D /* GTBranchTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTBranchTest.m; sourceTree = ""; }; 88F05AA416011FFD00B7AD1D /* GTCommitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCommitTest.m; sourceTree = ""; }; 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTObjectTest.m; sourceTree = ""; }; 88F05AA916011FFD00B7AD1D /* GTReferenceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTReferenceTest.m; sourceTree = ""; }; @@ -823,7 +821,6 @@ 88F05A7616011E5400B7AD1D /* Supporting Files */, 4D1C40D7182C006D00BE2960 /* GTBlobSpec.m */, 88A994B916FCE7D400402C7B /* GTBranchSpec.m */, - 88F05AA316011FFD00B7AD1D /* GTBranchTest.m */, 88F05AA416011FFD00B7AD1D /* GTCommitTest.m */, 88C0BC5817038CF3009E99AA /* GTConfigurationSpec.m */, 30865A90167F503400B1AB6E /* GTDiffSpec.m */, @@ -1523,7 +1520,6 @@ files = ( 88F05AC816012CEE00B7AD1D /* NSData+Git.m in Sources */, 88F05AC716012CE500B7AD1D /* NSString+Git.m in Sources */, - 88F05AB416011FFD00B7AD1D /* GTBranchTest.m in Sources */, 4D1C40D8182C006D00BE2960 /* GTBlobSpec.m in Sources */, 88F05AB516011FFD00B7AD1D /* GTCommitTest.m in Sources */, 88F05AB916011FFD00B7AD1D /* GTObjectTest.m in Sources */, diff --git a/ObjectiveGitTests/GTBranchTest.m b/ObjectiveGitTests/GTBranchTest.m deleted file mode 100644 index 4f9ff2077..000000000 --- a/ObjectiveGitTests/GTBranchTest.m +++ /dev/null @@ -1,36 +0,0 @@ -// -// GTBranchTest.m -// ObjectiveGitFramework -// -// Created by Timothy Clem on 3/10/11. -// Copyright 2011 GitHub, Inc. All rights reserved. -// - -@interface GTBranchTest : GTTestCase { - - GTRepository *repo; -} -@end - -@implementation GTBranchTest - -- (void)setUp { - repo = self.bareFixtureRepository; -} - -- (void)testRetainOfBranchCreatedWithRef { - - // Hard to test the autoreleasepool, so manually alloc/init instead. - // This allows us to release the object and test that the branch - // is retaining properly. - NSError *error = nil; - GTReference *head = [[GTReference alloc] initByLookingUpReferenceNamed:@"HEAD" inRepository:repo error:&error]; - STAssertNotNil(head, [error localizedDescription]); - GTBranch *current = [GTBranch branchWithReference:head repository:repo]; - STAssertNotNil(current, [error localizedDescription]); - - - STAssertNotNil(current.reference, nil); -} - -@end From 04fd3e714844b14c9f9e5bc2c5b8d9b244c85993 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 7 Nov 2013 19:56:50 +0100 Subject: [PATCH 06/61] Convert `GTCommitTest` to Expecta. --- .../project.pbxproj | 8 +- ObjectiveGitTests/GTCommitSpec.m | 65 ++++++++++++++ ObjectiveGitTests/GTCommitTest.m | 89 ------------------- 3 files changed, 69 insertions(+), 93 deletions(-) create mode 100644 ObjectiveGitTests/GTCommitSpec.m delete mode 100644 ObjectiveGitTests/GTCommitTest.m diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index bd596d4e5..a5e002075 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -200,7 +200,7 @@ 88EB7E4E14AEBA600046FEA4 /* GTConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 88EB7E4C14AEBA600046FEA4 /* GTConfiguration.m */; }; 88F05A9D16011F6A00B7AD1D /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88F05A9C16011F6A00B7AD1D /* SenTestingKit.framework */; }; 88F05A9E16011F6E00B7AD1D /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ObjectiveGit.framework */; }; - 88F05AB516011FFD00B7AD1D /* GTCommitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA416011FFD00B7AD1D /* GTCommitTest.m */; }; + 88F05AB516011FFD00B7AD1D /* GTCommitSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA416011FFD00B7AD1D /* GTCommitSpec.m */; }; 88F05AB916011FFD00B7AD1D /* GTObjectTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */; }; 88F05ABA16011FFD00B7AD1D /* GTReferenceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA916011FFD00B7AD1D /* GTReferenceTest.m */; }; 88F05ABC16011FFD00B7AD1D /* GTRepositoryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AAB16011FFD00B7AD1D /* GTRepositoryTest.m */; }; @@ -566,7 +566,7 @@ 88F05A7916011E5400B7AD1D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 88F05A7E16011E5400B7AD1D /* ObjectiveGitTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ObjectiveGitTests-Prefix.pch"; sourceTree = ""; }; 88F05A9C16011F6A00B7AD1D /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; - 88F05AA416011FFD00B7AD1D /* GTCommitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCommitTest.m; sourceTree = ""; }; + 88F05AA416011FFD00B7AD1D /* GTCommitSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCommitSpec.m; sourceTree = ""; }; 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTObjectTest.m; sourceTree = ""; }; 88F05AA916011FFD00B7AD1D /* GTReferenceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTReferenceTest.m; sourceTree = ""; }; 88F05AAB16011FFD00B7AD1D /* GTRepositoryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTRepositoryTest.m; sourceTree = ""; }; @@ -821,7 +821,7 @@ 88F05A7616011E5400B7AD1D /* Supporting Files */, 4D1C40D7182C006D00BE2960 /* GTBlobSpec.m */, 88A994B916FCE7D400402C7B /* GTBranchSpec.m */, - 88F05AA416011FFD00B7AD1D /* GTCommitTest.m */, + 88F05AA416011FFD00B7AD1D /* GTCommitSpec.m */, 88C0BC5817038CF3009E99AA /* GTConfigurationSpec.m */, 30865A90167F503400B1AB6E /* GTDiffSpec.m */, D06D9E001755D10000558C17 /* GTEnumeratorSpec.m */, @@ -1521,7 +1521,7 @@ 88F05AC816012CEE00B7AD1D /* NSData+Git.m in Sources */, 88F05AC716012CE500B7AD1D /* NSString+Git.m in Sources */, 4D1C40D8182C006D00BE2960 /* GTBlobSpec.m in Sources */, - 88F05AB516011FFD00B7AD1D /* GTCommitTest.m in Sources */, + 88F05AB516011FFD00B7AD1D /* GTCommitSpec.m in Sources */, 88F05AB916011FFD00B7AD1D /* GTObjectTest.m in Sources */, 88F05ABA16011FFD00B7AD1D /* GTReferenceTest.m in Sources */, 88F05ABC16011FFD00B7AD1D /* GTRepositoryTest.m in Sources */, diff --git a/ObjectiveGitTests/GTCommitSpec.m b/ObjectiveGitTests/GTCommitSpec.m new file mode 100644 index 000000000..81013008e --- /dev/null +++ b/ObjectiveGitTests/GTCommitSpec.m @@ -0,0 +1,65 @@ +// +// GTCommitSpec.m +// ObjectiveGitFramework +// +// Created by Etienne Samson on 2013-11-07. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "GTCommit.h" + +SpecBegin(GTCommit) + +__block GTRepository *repository; +__block NSError *error; + +beforeEach(^{ + repository = self.bareFixtureRepository; + error = nil; +}); + +it(@"can read commit data", ^{ + NSString *commitSHA = @"8496071c1b46c854b31185ea97743be6a8774479"; + GTCommit *commit = [repository lookupObjectBySHA:commitSHA error:&error]; + + expect(commit).notTo.beNil(); + expect(error).to.beNil(); + + expect(commit).to.beInstanceOf([GTCommit class]); + expect(commit.type).to.equal(@"commit"); + expect(commit.SHA).to.equal(commitSHA); + + expect(commit.message).to.equal(@"testing\n"); + expect(commit.messageSummary).to.equal(@"testing"); + expect(commit.messageDetails).to.equal(@""); + expect(commit.commitDate).to.equal([NSDate dateWithTimeIntervalSince1970:1273360386]); + +// STAssertEquals((int)[commit.commitDate timeIntervalSince1970], 1273360386, nil); + + GTSignature *author = commit.author; + expect(author).notTo.beNil(); + expect(author.name).to.equal(@"Scott Chacon"); + expect(author.email).to.equal(@"schacon@gmail.com"); + expect(author.time).to.equal([NSDate dateWithTimeIntervalSince1970:1273360386]); +// STAssertEquals((int)[author.time timeIntervalSince1970], 1273360386, nil); + + GTSignature *committer = commit.committer; + expect(committer).notTo.beNil(); + expect(committer.name).to.equal(@"Scott Chacon"); + expect(committer.email).to.equal(@"schacon@gmail.com"); + expect(committer.time).to.equal([NSDate dateWithTimeIntervalSince1970:1273360386]); + + expect(commit.tree.SHA).to.equal(@"181037049a54a1eb5fab404658a3a250b44335d7"); + expect(commit.parents.count).to.equal(0); +}); + +it(@"canHaveMultipleParents", ^{ + NSString *commitSHA = @"a4a7dce85cf63874e984719f4fdd239f5145052f"; + GTCommit *commit = [repository lookupObjectBySHA:commitSHA error:&error]; + expect(commit).notTo.beNil(); + expect(error).to.beNil(); + + expect(commit.parents.count).to.equal(2); +}); + +SpecEnd diff --git a/ObjectiveGitTests/GTCommitTest.m b/ObjectiveGitTests/GTCommitTest.m deleted file mode 100644 index e872ba4ac..000000000 --- a/ObjectiveGitTests/GTCommitTest.m +++ /dev/null @@ -1,89 +0,0 @@ -// -// GTCommitTest.m -// ObjectiveGitFramework -// -// Created by Timothy Clem on 2/22/11. -// -// The MIT License -// -// Copyright (c) 2011 Tim Clem -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -@interface GTCommitTest : GTTestCase { - - GTRepository *repo; -} -@end - -@implementation GTCommitTest - - -- (void)setUp { - repo = self.bareFixtureRepository; - STAssertNotNil(repo, @"Could not create fixture repository."); -} - -- (void)testCanReadCommitData { - - NSString *commitSHA = @"8496071c1b46c854b31185ea97743be6a8774479"; - NSError *error = nil; - GTObject *obj = [repo lookupObjectBySHA:commitSHA error:&error]; - - STAssertNil(error, [error localizedDescription]); - STAssertNotNil(obj, nil); - STAssertTrue([obj isKindOfClass:[GTCommit class]], nil); - STAssertEqualObjects(obj.type, @"commit", nil); - STAssertEqualObjects(obj.SHA, commitSHA, nil); - - GTCommit *commit = (GTCommit *)obj; - STAssertEqualObjects(commit.message, @"testing\n", nil); - STAssertEqualObjects(commit.messageSummary, @"testing", nil); - STAssertEqualObjects(commit.messageDetails, @"", nil); - STAssertEquals((int)[commit.commitDate timeIntervalSince1970], 1273360386, nil); - - GTSignature *author = commit.author; - STAssertEqualObjects(author.name, @"Scott Chacon", nil); - STAssertEqualObjects(author.email, @"schacon@gmail.com", nil); - STAssertEquals((int)[author.time timeIntervalSince1970], 1273360386, nil); - - GTSignature *committer = commit.committer; - STAssertEqualObjects(committer.name, @"Scott Chacon", nil); - STAssertEqualObjects(committer.email, @"schacon@gmail.com", nil); - STAssertEquals((int)[committer.time timeIntervalSince1970], 1273360386, nil); - - STAssertEqualObjects(commit.tree.SHA, @"181037049a54a1eb5fab404658a3a250b44335d7", nil); - STAssertTrue([commit.parents count] == 0, nil); -} - -- (void)testCanHaveMultipleParents { - - NSString *commitSHA = @"a4a7dce85cf63874e984719f4fdd239f5145052f"; - NSError *error = nil; - GTObject *obj = [repo lookupObjectBySHA:commitSHA error:&error]; - - STAssertNil(error, [error localizedDescription]); - STAssertNotNil(obj, nil); - - GTCommit *commit = (GTCommit *)obj; - STAssertTrue([commit.parents count] == 2, nil); -} - -@end From f578c4c6f4deea223bb03339c1da2d584d35a033 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 7 Nov 2013 20:47:31 +0100 Subject: [PATCH 07/61] Convert `GTReferenceTest`. --- .../project.pbxproj | 4 - ObjectiveGitTests/GTReferenceSpec.m | 65 ++++++++++++++ ObjectiveGitTests/GTReferenceTest.m | 90 ------------------- ObjectiveGitTests/GTRepositorySpec.m | 15 ++++ 4 files changed, 80 insertions(+), 94 deletions(-) delete mode 100644 ObjectiveGitTests/GTReferenceTest.m diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index a5e002075..437c5cda8 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -202,7 +202,6 @@ 88F05A9E16011F6E00B7AD1D /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ObjectiveGit.framework */; }; 88F05AB516011FFD00B7AD1D /* GTCommitSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA416011FFD00B7AD1D /* GTCommitSpec.m */; }; 88F05AB916011FFD00B7AD1D /* GTObjectTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */; }; - 88F05ABA16011FFD00B7AD1D /* GTReferenceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA916011FFD00B7AD1D /* GTReferenceTest.m */; }; 88F05ABC16011FFD00B7AD1D /* GTRepositoryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AAB16011FFD00B7AD1D /* GTRepositoryTest.m */; }; 88F05AC41601204200B7AD1D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 88F05A7816011E5400B7AD1D /* InfoPlist.strings */; }; 88F05AC61601209A00B7AD1D /* ObjectiveGit.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AC51601209A00B7AD1D /* ObjectiveGit.m */; }; @@ -568,7 +567,6 @@ 88F05A9C16011F6A00B7AD1D /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 88F05AA416011FFD00B7AD1D /* GTCommitSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCommitSpec.m; sourceTree = ""; }; 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTObjectTest.m; sourceTree = ""; }; - 88F05AA916011FFD00B7AD1D /* GTReferenceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTReferenceTest.m; sourceTree = ""; }; 88F05AAB16011FFD00B7AD1D /* GTRepositoryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTRepositoryTest.m; sourceTree = ""; }; 88F05AAF16011FFD00B7AD1D /* ObjectiveGitTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ObjectiveGitTests-Info.plist"; sourceTree = ""; }; 88F05AC51601209A00B7AD1D /* ObjectiveGit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ObjectiveGit.m; path = Classes/ObjectiveGit.m; sourceTree = ""; }; @@ -828,7 +826,6 @@ 8832811E173D8816006D7DCF /* GTIndexSpec.m */, 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */, D00F6815175D373C004DB9D6 /* GTReferenceSpec.m */, - 88F05AA916011FFD00B7AD1D /* GTReferenceTest.m */, 88215482171499BE00D76B76 /* GTReflogSpec.m */, D0AC906B172F941F00347DC4 /* GTRepositorySpec.m */, F6ED8DA0180E713200A32D40 /* GTRemoteSpec.m */, @@ -1523,7 +1520,6 @@ 4D1C40D8182C006D00BE2960 /* GTBlobSpec.m in Sources */, 88F05AB516011FFD00B7AD1D /* GTCommitSpec.m in Sources */, 88F05AB916011FFD00B7AD1D /* GTObjectTest.m in Sources */, - 88F05ABA16011FFD00B7AD1D /* GTReferenceTest.m in Sources */, 88F05ABC16011FFD00B7AD1D /* GTRepositoryTest.m in Sources */, 30865A91167F503400B1AB6E /* GTDiffSpec.m in Sources */, 88A994BA16FCE7D400402C7B /* GTBranchSpec.m in Sources */, diff --git a/ObjectiveGitTests/GTReferenceSpec.m b/ObjectiveGitTests/GTReferenceSpec.m index 6c29d2ad5..ad6a52bcb 100644 --- a/ObjectiveGitTests/GTReferenceSpec.m +++ b/ObjectiveGitTests/GTReferenceSpec.m @@ -107,4 +107,69 @@ }); }); +__block GTRepository *bareRepository; +__block NSError *error; +__block void (^isValidReference)(GTReference *ref, NSString *SHA, GTReferenceType type, NSString *name); + +beforeEach(^{ + bareRepository = self.bareFixtureRepository; + error = nil; + isValidReference = ^(GTReference *ref, NSString *SHA, GTReferenceType type, NSString *name) { + expect(ref).notTo.beNil(); + expect(ref.targetSHA).to.equal(SHA); + expect(ref.referenceType).to.equal(type); + expect(ref.name).to.equal(name); + }; +}); + +describe(@"+referenceByLookingUpReferenceNamed:inRepository:error:", ^{ + it(@"should return a valid reference to a branch", ^{ + GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:@"refs/heads/master" inRepository:bareRepository error:&error]; + expect(ref).notTo.beNil(); + expect(error).to.beNil(); + + isValidReference(ref, @"36060c58702ed4c2a40832c51758d5344201d89a", GTReferenceTypeOid, @"refs/heads/master"); + }); + + it(@"should return a valid reference to a tag", ^{ + GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:@"refs/tags/v0.9" inRepository:bareRepository error:&error]; + expect(ref).notTo.beNil(); + expect(error).to.beNil(); + + isValidReference(ref, @"5b5b025afb0b4c913b4c338a42934a3863bf3644", GTReferenceTypeOid, @"refs/tags/v0.9"); + }); +}); + +describe(@"+referenceByCreatingReferenceNamed:fromReferenceTarget:inRepository:error:", ^{ + it(@"can create a reference from a symbolic reference", ^{ + GTReference *ref = [GTReference referenceByCreatingReferenceNamed:@"refs/heads/unit_test" fromReferenceTarget:@"refs/heads/master" inRepository:bareRepository error:&error]; + expect(error).to.beNil(); + expect(ref).notTo.beNil(); + + isValidReference(ref, @"36060c58702ed4c2a40832c51758d5344201d89a", GTReferenceTypeSymbolic, @"refs/heads/unit_test"); + expect(ref.resolvedReference.name).to.equal(@"refs/heads/master"); + }); + + it(@"can create a reference from an SHA/OID", ^{ + GTReference *ref = [GTReference referenceByCreatingReferenceNamed:@"refs/heads/unit_test" fromReferenceTarget:@"36060c58702ed4c2a40832c51758d5344201d89a" inRepository:bareRepository error:&error]; + expect(error).to.beNil(); + expect(ref).notTo.beNil(); + + isValidReference(ref, @"36060c58702ed4c2a40832c51758d5344201d89a", GTReferenceTypeOid, @"refs/heads/unit_test"); + }); +}); + +describe(@"-deleteWithError:", ^{ + it(@"can delete references", ^{ + GTReference *ref = [GTReference referenceByCreatingReferenceNamed:@"refs/heads/unit_test" fromReferenceTarget:@"36060c58702ed4c2a40832c51758d5344201d89a" inRepository:bareRepository error:&error]; + + expect(error).to.beNil(); + expect(ref).notTo.beNil(); + + BOOL success = [ref deleteWithError:&error]; + expect(success).to.beTruthy(); + expect(error).to.beNil(); + }); +}); + SpecEnd diff --git a/ObjectiveGitTests/GTReferenceTest.m b/ObjectiveGitTests/GTReferenceTest.m deleted file mode 100644 index 22b80d09e..000000000 --- a/ObjectiveGitTests/GTReferenceTest.m +++ /dev/null @@ -1,90 +0,0 @@ -// -// GTReferenceTest.m -// ObjectiveGitFramework -// -// Created by Timothy Clem on 3/2/11. -// Copyright 2011 GitHub Inc. All rights reserved. -// - -@interface GTReferenceTest : GTTestCase { - NSArray *expectedRefs; -} -@end - -@implementation GTReferenceTest - -- (void)setUp { - - expectedRefs = [NSArray arrayWithObjects:@"refs/heads/packed", @"refs/heads/master", @"refs/tags/v0.9", @"refs/tags/v1.0", nil]; -} - -- (void)testCanOpenRef { - GTRepository *repo = self.bareFixtureRepository; - STAssertNotNil(repo, @"Could not create reposiotry"); - NSError *error = nil; - GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:@"refs/heads/master" inRepository:repo error:&error]; - STAssertNil(error, [error localizedDescription]); - STAssertNotNil(ref, nil); - - STAssertEqualObjects(@"36060c58702ed4c2a40832c51758d5344201d89a", ref.targetSHA, nil); - STAssertEquals(GTReferenceTypeOid, ref.referenceType, nil); - STAssertEqualObjects(@"refs/heads/master", ref.name, nil); -} - -- (void)testCanOpenTagRef { - GTRepository *repo = self.bareFixtureRepository; - NSError *error = nil; - GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:@"refs/tags/v0.9" inRepository:repo error:&error]; - STAssertNil(error, [error localizedDescription]); - STAssertNotNil(ref, nil); - - STAssertEqualObjects(@"5b5b025afb0b4c913b4c338a42934a3863bf3644", ref.targetSHA, nil); - STAssertEquals(GTReferenceTypeOid, ref.referenceType, nil); - STAssertEqualObjects(@"refs/tags/v0.9", ref.name, nil); -} - -- (void)testCanCreateRefFromSymbolicRef { - GTRepository *repo = self.bareFixtureRepository; - NSError *error = nil; - GTReference *ref = [GTReference referenceByCreatingReferenceNamed:@"refs/heads/unit_test" fromReferenceTarget:@"refs/heads/master" inRepository:repo error:&error]; - STAssertNil(error, [error localizedDescription]); - STAssertNotNil(ref, nil); - - STAssertEqualObjects(@"refs/heads/master", ref.resolvedReference.name, nil); - STAssertEquals(GTReferenceTypeSymbolic, ref.referenceType, nil); - STAssertEqualObjects(@"refs/heads/unit_test", ref.name, nil); - - BOOL success = [ref deleteWithError:&error]; - STAssertTrue(success, [error localizedDescription]); -} - -- (void)testCanCreateRefFromSha { - - GTRepository *repo = self.bareFixtureRepository; - NSError *error = nil; - GTReference *ref = [GTReference referenceByCreatingReferenceNamed:@"refs/heads/unit_test" fromReferenceTarget:@"36060c58702ed4c2a40832c51758d5344201d89a" inRepository:repo error:&error]; - STAssertNil(error, [error localizedDescription]); - STAssertNotNil(ref, nil); - - STAssertEqualObjects(@"36060c58702ed4c2a40832c51758d5344201d89a", ref.targetSHA, nil); - STAssertEquals(GTReferenceTypeOid, ref.referenceType, nil); - STAssertEqualObjects(@"refs/heads/unit_test", ref.name, nil); - - BOOL success = [ref deleteWithError:&error]; - STAssertTrue(success, [error localizedDescription]); -} - -- (void)testCanListAllReferences { - GTRepository *repo = self.bareFixtureRepository; - NSError *error = nil; - NSArray *refs = [repo referenceNamesWithError:&error]; - STAssertNil(error, [error localizedDescription]); - STAssertEquals(4, (int)refs.count, nil); - - for (NSUInteger i = 0; i < refs.count; i++) { - NSLog(@"%@", [refs objectAtIndex:i]); - STAssertTrue([expectedRefs containsObject:[refs objectAtIndex:i]], nil); - } -} - -@end diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index ff49f2717..f4debc20b 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -116,6 +116,21 @@ }); }); +describe(@"-referenceNamesWithError:", ^{ + it(@"should return reference names", ^{ + NSError *error = nil; + NSArray *refs = [self.bareFixtureRepository referenceNamesWithError:&error]; + expect(refs).notTo.beNil(); + expect(error).to.beNil(); + + expect(refs.count).to.equal(4); + expect(refs).to.contain(@"refs/heads/packed"); + expect(refs).to.contain(@"refs/heads/master"); + expect(refs).to.contain(@"refs/tags/v0.9"); + expect(refs).to.contain(@"refs/tags/v1.0"); + }); +}); + describe(@"-OIDByCreatingTagNamed:target:tagger:message:error", ^{ it(@"should create a new tag",^{ NSError *error = nil; From 9c2c3e2741d58dce8bcdb694ce173a3dccff410e Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 7 Nov 2013 21:35:23 +0100 Subject: [PATCH 08/61] Convert `GTRepositoryTest`. --- .../project.pbxproj | 4 - ObjectiveGitTests/GTRepositorySpec.m | 161 ++++++++++++- ObjectiveGitTests/GTRepositoryTest.m | 223 ------------------ 3 files changed, 160 insertions(+), 228 deletions(-) delete mode 100644 ObjectiveGitTests/GTRepositoryTest.m diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index 437c5cda8..a0a2b90a7 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -202,7 +202,6 @@ 88F05A9E16011F6E00B7AD1D /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ObjectiveGit.framework */; }; 88F05AB516011FFD00B7AD1D /* GTCommitSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA416011FFD00B7AD1D /* GTCommitSpec.m */; }; 88F05AB916011FFD00B7AD1D /* GTObjectTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */; }; - 88F05ABC16011FFD00B7AD1D /* GTRepositoryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AAB16011FFD00B7AD1D /* GTRepositoryTest.m */; }; 88F05AC41601204200B7AD1D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 88F05A7816011E5400B7AD1D /* InfoPlist.strings */; }; 88F05AC61601209A00B7AD1D /* ObjectiveGit.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AC51601209A00B7AD1D /* ObjectiveGit.m */; }; 88F05AC716012CE500B7AD1D /* NSString+Git.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C8057313874CDF004DCB0F /* NSString+Git.m */; }; @@ -567,7 +566,6 @@ 88F05A9C16011F6A00B7AD1D /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 88F05AA416011FFD00B7AD1D /* GTCommitSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCommitSpec.m; sourceTree = ""; }; 88F05AA816011FFD00B7AD1D /* GTObjectTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTObjectTest.m; sourceTree = ""; }; - 88F05AAB16011FFD00B7AD1D /* GTRepositoryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTRepositoryTest.m; sourceTree = ""; }; 88F05AAF16011FFD00B7AD1D /* ObjectiveGitTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ObjectiveGitTests-Info.plist"; sourceTree = ""; }; 88F05AC51601209A00B7AD1D /* ObjectiveGit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ObjectiveGit.m; path = Classes/ObjectiveGit.m; sourceTree = ""; }; 88F05AC91601335C00B7AD1D /* Specta.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Specta.xcodeproj; path = specta/Specta.xcodeproj; sourceTree = ""; }; @@ -830,7 +828,6 @@ D0AC906B172F941F00347DC4 /* GTRepositorySpec.m */, F6ED8DA0180E713200A32D40 /* GTRemoteSpec.m */, 4D12323F178E009E0048F785 /* GTRepositoryCommittingSpec.m */, - 88F05AAB16011FFD00B7AD1D /* GTRepositoryTest.m */, D03B7C401756AB370034A610 /* GTSubmoduleSpec.m */, 2089E43B17D9A58000F451DA /* GTTagSpec.m */, 30B1E7FF1703871900D0814D /* GTTimeAdditionsSpec.m */, @@ -1520,7 +1517,6 @@ 4D1C40D8182C006D00BE2960 /* GTBlobSpec.m in Sources */, 88F05AB516011FFD00B7AD1D /* GTCommitSpec.m in Sources */, 88F05AB916011FFD00B7AD1D /* GTObjectTest.m in Sources */, - 88F05ABC16011FFD00B7AD1D /* GTRepositoryTest.m in Sources */, 30865A91167F503400B1AB6E /* GTDiffSpec.m in Sources */, 88A994BA16FCE7D400402C7B /* GTBranchSpec.m in Sources */, 2089E43C17D9A58000F451DA /* GTTagSpec.m in Sources */, diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index f4debc20b..9387be9b0 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -12,13 +12,15 @@ SpecBegin(GTRepository) __block GTRepository *repository; +__block NSError *error = nil; beforeEach(^{ repository = self.testAppFixtureRepository; expect(repository).notTo.beNil(); + error = nil; }); -describe(@"-initializeEmptyRepositoryAtFileURL:bare:error:", ^{ +describe(@"+initializeEmptyRepositoryAtFileURL:bare:error:", ^{ __block GTRepository * (^createRepository)(BOOL bare); beforeEach(^{ @@ -44,6 +46,100 @@ }); }); +describe(@"+repositoryWithURL:error:", ^{ + it(@"should fail to initialize non-existent repos", ^{ + GTRepository *badRepo = [GTRepository repositoryWithURL:[NSURL fileURLWithPath:@"fake/1235"] error:&error]; + expect(badRepo).to.beNil(); + expect(error).notTo.beNil(); + }); +}); + +describe(@"+cloneFromURL:toWorkingDirectory:...", ^{ + __block BOOL transferProgressCalled = NO; + __block BOOL checkoutProgressCalled = NO; + __block void (^transferProgressBlock)(const git_transfer_progress *); + __block void (^checkoutProgressBlock)(NSString *, NSUInteger, NSUInteger); + __block NSURL *originURL; + __block NSURL *workdirURL; + + beforeEach(^{ + error = nil; + transferProgressCalled = NO; + checkoutProgressCalled = NO; + transferProgressBlock = ^(const git_transfer_progress *progress) { transferProgressCalled = YES; }; + checkoutProgressBlock = ^(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps) { checkoutProgressCalled = YES; }; + + originURL = self.bareFixtureRepository.gitDirectoryURL; //[NSURL URLWithString: @"https://github.com/libgit2/TestGitRepository"]; + workdirURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"unit_test"]]; + }); + + afterEach(^{ + if ([NSFileManager.defaultManager fileExistsAtPath:workdirURL.path isDirectory:NULL]) { + NSError *error = nil; + BOOL success = [NSFileManager.defaultManager removeItemAtURL:workdirURL error:&error]; + expect(success).to.beTruthy(); + expect(error).to.beNil(); + } + }); + + it(@"should handle normal clones", ^{ + repository = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:nil error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; + expect(repository).notTo.beNil(); + expect(error).to.beNil(); + expect(transferProgressCalled).to.beTruthy(); + expect(checkoutProgressCalled).to.beTruthy(); + + expect(repository.isBare).to.beFalsy(); + + GTReference *head = [repository headReferenceWithError:&error]; + expect(head).notTo.beNil(); + expect(error).to.beNil(); + expect(head.targetSHA).to.equal(@"36060c58702ed4c2a40832c51758d5344201d89a"); + expect(head.referenceType).to.equal(GTReferenceTypeOid); + }); + + it(@"should handle bare clones", ^{ + NSDictionary *options = @{ GTRepositoryCloneOptionsBare: @YES }; + repository = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:options error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; + expect(repository).notTo.beNil(); + expect(error).to.beNil(); + expect(transferProgressCalled).to.beTruthy(); + expect(checkoutProgressCalled).to.beTruthy(); + + expect(repository.isBare).to.beTruthy(); + + GTReference *head = [repository headReferenceWithError:&error]; + expect(head).notTo.beNil(); + expect(error).to.beNil(); + expect(head.targetSHA).to.equal(@"36060c58702ed4c2a40832c51758d5344201d89a"); + expect(head.referenceType).to.equal(GTReferenceTypeOid); + + }); +}); + +describe(@"-headReferenceWithError:", ^{ + it(@"should allow HEAD to be looked up", ^{ + GTReference *head = [self.bareFixtureRepository headReferenceWithError:&error]; + expect(head).notTo.beNil(); + expect(error).to.beNil(); + expect(head.targetSHA).to.equal(@"36060c58702ed4c2a40832c51758d5344201d89a"); + expect(head.referenceType).to.equal(GTReferenceTypeOid); + }); +}); + +describe(@"-isEmpty", ^{ + it(@"should return NO for a non-empty repository", ^{ + expect(repository.isEmpty).to.beFalsy(); + }); + + it(@"should return YES for a new repository", ^{ + NSURL *fileURL = [self.tempDirectoryFileURL URLByAppendingPathComponent:@"newrepo"]; + GTRepository *newRepo = [GTRepository initializeEmptyRepositoryAtFileURL:fileURL error:&error]; + expect(newRepo.isEmpty).to.beTruthy(); + [NSFileManager.defaultManager removeItemAtURL:fileURL error:NULL]; + }); +}); + describe(@"-preparedMessage", ^{ it(@"should return nil by default", ^{ __block NSError *error = nil; @@ -186,4 +282,67 @@ }); }); +describe(@"-resetToCommit:withResetType:error:", ^{ + beforeEach(^{ + repository = self.bareFixtureRepository; + }); + + it(@"should move HEAD when used", ^{ + GTReference *originalHead = [repository headReferenceWithError:NULL]; + NSString *resetTargetSHA = @"8496071c1b46c854b31185ea97743be6a8774479"; + + GTCommit *commit = [repository lookupObjectBySHA:resetTargetSHA error:NULL]; + expect(commit).notTo.beNil(); + GTCommit *originalHeadCommit = [repository lookupObjectBySHA:originalHead.targetSHA error:NULL]; + expect(originalHeadCommit).notTo.beNil(); + + BOOL success = [repository resetToCommit:commit withResetType:GTRepositoryResetTypeSoft error:&error]; + expect(success).to.beTruthy(); + expect(error).to.beNil(); + + GTReference *head = [repository headReferenceWithError:&error]; + expect(head).notTo.beNil(); + expect(head.targetSHA).to.equal(resetTargetSHA); + + success = [repository resetToCommit:originalHeadCommit withResetType:GTRepositoryResetTypeSoft error:&error]; + expect(success).to.beTruthy(); + expect(error).to.beNil(); + + head = [repository headReferenceWithError:&error]; + expect(head.targetSHA).to.equal(originalHead.targetSHA); + }); +}); + +describe(@"-lookupObjectByRefspec:error:", ^{ + __block void (^expectSHAForRevspec)(NSString *SHA, NSString *revspec); + + beforeEach(^{ + repository = self.bareFixtureRepository; + error = nil; + + expectSHAForRevspec = ^(NSString *SHA, NSString *revspec) { + error = nil; + GTObject *obj = [repository lookupObjectByRefspec:revspec error:&error]; + + if (SHA != nil) { + expect(error).to.beNil(); + expect(obj).notTo.beNil(); + expect(obj.SHA).to.equal(SHA); + } else { + expect(error).notTo.beNil(); + expect(obj).to.beNil(); + } + }; + }); + + it(@"should parse various revspecs", ^{ + expectSHAForRevspec(@"36060c58702ed4c2a40832c51758d5344201d89a", @"master"); + expectSHAForRevspec(@"5b5b025afb0b4c913b4c338a42934a3863bf3644", @"master~"); + expectSHAForRevspec(@"8496071c1b46c854b31185ea97743be6a8774479", @"master@{2}"); + expectSHAForRevspec(nil, @"master^2"); + expectSHAForRevspec(nil, @""); + expectSHAForRevspec(@"0c37a5391bbff43c37f0d0371823a5509eed5b1d", @"v1.0"); + }); +}); + SpecEnd diff --git a/ObjectiveGitTests/GTRepositoryTest.m b/ObjectiveGitTests/GTRepositoryTest.m deleted file mode 100644 index 4656ee0ca..000000000 --- a/ObjectiveGitTests/GTRepositoryTest.m +++ /dev/null @@ -1,223 +0,0 @@ -// -// GTRepositoryTest.m -// ObjectiveGitFramework -// -// Created by Timothy Clem on 2/21/11. -// -// The MIT License -// -// Copyright (c) 2011 Tim Clem -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -@interface GTRepositoryTest : GTTestCase { - - GTRepository *repo; - NSString *testContent; - GTObjectType testContentType; -} -@end - - -@implementation GTRepositoryTest - -- (void)setUp { - repo = self.bareFixtureRepository; - testContent = @"my test data\n"; - testContentType = GTObjectTypeBlob; -} - -- (void)removeDirectoryAtURL:(NSURL *)url { - NSFileManager *fm = [[NSFileManager alloc] init]; - NSError *error = nil; - - if([fm fileExistsAtPath:url.path]) { - STAssertTrue([fm removeItemAtPath:url.path error:&error], [error localizedDescription]); - } -} - -- (void)testFailsToOpenNonExistentRepo { - - NSError *error = nil; - GTRepository *badRepo = [GTRepository repositoryWithURL:[NSURL fileURLWithPath:@"fake/1235"] error:&error]; - - STAssertNil(badRepo, nil); - STAssertNotNil(error, nil); - NSLog(@"error = %@", [error localizedDescription]); -} - -- (void)testLookupHead { - - NSError *error = nil; - GTReference *head = [repo headReferenceWithError:&error]; - STAssertNil(error, [error localizedDescription]); - STAssertEqualObjects(head.targetSHA, @"36060c58702ed4c2a40832c51758d5344201d89a", nil); - STAssertEquals(head.referenceType, GTReferenceTypeOid, nil); -} - -- (void)testIsEmpty { - STAssertFalse([repo isEmpty], nil); -} - -- (void)testCanReset { - NSError *err = nil; - GTRepository *aRepo = self.bareFixtureRepository; - STAssertNotNil(aRepo, @"Repository failed to initialise"); - GTReference *originalHead = [aRepo headReferenceWithError:NULL]; - NSString *resetTargetSha = @"8496071c1b46c854b31185ea97743be6a8774479"; - - GTCommit *commit = (GTCommit *)[aRepo lookupObjectBySHA:resetTargetSha error:NULL]; - - BOOL success = [aRepo resetToCommit:commit withResetType:GTRepositoryResetTypeSoft error:&err]; - STAssertTrue(success, @"Failed to reset, error given: %@", err); - GTReference *head = [aRepo headReferenceWithError:&err]; - STAssertEqualObjects(head.targetSHA, resetTargetSha, @"Reset failed to move head to given commit"); - - GTCommit *originalHeadCommit = (GTCommit *)[aRepo lookupObjectBySHA:originalHead.targetSHA error:NULL]; - [aRepo resetToCommit:originalHeadCommit withResetType:GTRepositoryResetTypeSoft error:NULL]; - head = [aRepo headReferenceWithError:&err]; - STAssertEqualObjects(head.unresolvedTarget, originalHead.unresolvedTarget, @"Reset failed to move head back to the original position"); -} - -- (void)expectSHA:(NSString*)sha forRefspec:(NSString*)refspec { - NSError *err = nil; - GTObject *obj = [repo lookupObjectByRefspec:refspec error:&err]; - - if (sha != nil) { - STAssertEquals((NSInteger)GIT_OK, err.code, @"git_revparse_single didn't return 0: %d", err.code); - STAssertNotNil(obj, @"Couldn't find object for %@", refspec); - STAssertEqualObjects(sha, obj.SHA, @"Revparse '%@': expected %@, got %@", refspec, sha, obj.SHA); - } else { - STAssertTrue(err.code != (NSInteger)GIT_OK, @"Expected error code, got 0"); - STAssertNil(obj, @"Got object when expected none for %@", refspec); - } -} - -- (void)testCanRevparse { - [self expectSHA:@"36060c58702ed4c2a40832c51758d5344201d89a" forRefspec:@"master"]; - [self expectSHA:@"5b5b025afb0b4c913b4c338a42934a3863bf3644" forRefspec:@"master~"]; - [self expectSHA:@"8496071c1b46c854b31185ea97743be6a8774479" forRefspec:@"master@{2}"]; - [self expectSHA:nil forRefspec:@"master^2"]; - [self expectSHA:nil forRefspec:@""]; - [self expectSHA:@"0c37a5391bbff43c37f0d0371823a5509eed5b1d" forRefspec:@"v1.0"]; - - GTObject *obj = [repo lookupObjectByRefspec:@"master" error:nil]; - STAssertNotNil(obj, @"Call with nil error should still work"); -} - - -- (void)testCanClone { - __block BOOL transferProgressCalled = NO; - __block BOOL checkoutProgressCalled = NO; - void (^transferProgressBlock)(const git_transfer_progress *) = ^(const git_transfer_progress *progress) { - transferProgressCalled = YES; - }; - void (^checkoutProgressBlock)(NSString *, NSUInteger, NSUInteger) = ^(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps) { - checkoutProgressCalled = YES; - }; - NSURL *originURL = self.bareFixtureRepository.fileURL; //[NSURL URLWithString: @"https://github.com/libgit2/TestGitRepository"]; - NSURL *workdirURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"unit_test"]]; - NSError *err; - - [self removeDirectoryAtURL:workdirURL]; - - repo = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:NULL error:&err transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; - - STAssertNotNil(repo, err.localizedDescription); - STAssertFalse([repo isBare], @"Standard repo should not be bare"); - STAssertTrue(transferProgressCalled, @"Transfer progress handler never called"); - STAssertTrue(checkoutProgressCalled, @"checkout progress handler never called"); - - GTReference *head = [repo headReferenceWithError:&err]; - STAssertNotNil(head, err.localizedDescription); - STAssertEqualObjects(head.targetSHA, @"36060c58702ed4c2a40832c51758d5344201d89a", nil); - STAssertEquals(head.referenceType, GTReferenceTypeOid, nil); -} - -- (void)testCanCloneBarely { - __block BOOL transferProgressCalled = NO; - __block BOOL checkoutProgressCalled = NO; - void (^transferProgressBlock)(const git_transfer_progress *) = ^(const git_transfer_progress *progress) { - transferProgressCalled = YES; - }; - void (^checkoutProgressBlock)(NSString *, NSUInteger, NSUInteger) = ^(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps) { - checkoutProgressCalled = YES; - }; - NSURL *originURL = self.bareFixtureRepository.fileURL; //[NSURL URLWithString: @"https://github.com/libgit2/TestGitRepository"]; - NSURL *workdirURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"unit_test"]]; - NSDictionary *options = @{ GTRepositoryCloneOptionsBare: @YES }; - NSError *err; - - [self removeDirectoryAtURL:workdirURL]; - - repo = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:options error:&err transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; - - STAssertNotNil(repo, err.localizedDescription); - STAssertTrue([repo isBare], @"Bare repo should be bare"); - STAssertTrue(transferProgressCalled, @"Transfer progress handler never called"); - STAssertFalse(checkoutProgressCalled, @"Checkout progress handler was called for bare repo"); - - GTReference *head = [repo headReferenceWithError:&err]; - STAssertNotNil(head, err.localizedDescription); - STAssertEqualObjects(head.targetSHA, @"36060c58702ed4c2a40832c51758d5344201d89a", nil); - STAssertEquals(head.referenceType, GTReferenceTypeOid, nil); -} - -//- (void) testCanGetRemotes { -// NSArray* remotesArray = [repo remoteNames]; -// -// STAssertTrue( [remotesArray containsObject: @"github"], @"remotes name did not contain expected remote" ); -// STAssertTrue( [repo hasRemoteNamed: @"github"], @"remotes name was not found by query function" ); -// -//} - -// This messes other tests up b/c it writes a new HEAD, but doesn't set it back again -/* -- (void)testLookupHeadThenCommitAndThenLookupHeadAgain { - - NSError *error = nil; - GTReference *head = [repo headAndReturnError:&error]; - STAssertNil(error, [error localizedDescription]); - STAssertEqualObjects(head.target, @"36060c58702ed4c2a40832c51758d5344201d89a", nil); - STAssertEqualObjects(head.type, @"commit", nil); - - NSString *tsha = @"c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b"; - GTObject *aObj = [repo lookupBySha:tsha error:&error]; - - STAssertNotNil(aObj, [error localizedDescription]); - STAssertTrue([aObj isKindOfClass:[GTTree class]], nil); - GTTree *tree = (GTTree *)aObj; - GTSignature *person = [[[GTSignature alloc] - initWithName:@"Tim" - email:@"tclem@github.com" - time:[NSDate date]] autorelease]; - GTCommit *commit = [GTCommit commitInRepo:repo updateRefNamed:@"HEAD" author:person committer:person message:@"new message" tree:tree parents:nil error:&error]; - STAssertNotNil(commit, [error localizedDescription]); - NSLog(@"wrote sha %@", commit.sha); - - head = [repo headAndReturnError:&error]; - STAssertNotNil(head, [error localizedDescription]); - - STAssertEqualObjects(head.target, commit.sha, nil); - - rm_loose(commit.sha); -} -*/ -@end From f655dec66f61f1d4d3c512c5d303b7e0bc35544c Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 11:52:41 +0100 Subject: [PATCH 09/61] Cleanup `GTBlob`'s header. --- Classes/GTBlob.h | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/Classes/GTBlob.h b/Classes/GTBlob.h index 42c350535..7e42beb44 100644 --- a/Classes/GTBlob.h +++ b/Classes/GTBlob.h @@ -31,15 +31,37 @@ #import "GTObject.h" -@interface GTBlob : GTObject {} +@interface GTBlob : GTObject -+ (id)blobWithString:(NSString *)string inRepository:(GTRepository *)repository error:(NSError **)error; -+ (id)blobWithData:(NSData *)data inRepository:(GTRepository *)repository error:(NSError **)error; -+ (id)blobWithFile:(NSURL *)file inRepository:(GTRepository *)repository error:(NSError **)error; +// Convenience class methods ++ (instancetype)blobWithString:(NSString *)string inRepository:(GTRepository *)repository error:(NSError **)error; ++ (instancetype)blobWithData:(NSData *)data inRepository:(GTRepository *)repository error:(NSError **)error; ++ (instancetype)blobWithFile:(NSURL *)file inRepository:(GTRepository *)repository error:(NSError **)error; -- (id)initWithString:(NSString *)string inRepository:(GTRepository *)repository error:(NSError **)error; -- (id)initWithData:(NSData *)data inRepository:(GTRepository *)repository error:(NSError **)error; -- (id)initWithFile:(NSURL *)file inRepository:(GTRepository *)repository error:(NSError **)error; +// Convenience wrapper around `-initWithData:inRepository:error` that converts the string to UTF8 data +- (instancetype)initWithString:(NSString *)string inRepository:(GTRepository *)repository error:(NSError **)error; + +// Creates a new blob from the passed data. +// +// This writes data to the repository's object database. +// +// data - The data to write. +// repository - The repository to put the object in. +// error - Will be set if an error occurs. +// +// Returns a newly created blob object, or nil if an error occurs. +- (instancetype)initWithData:(NSData *)data inRepository:(GTRepository *)repository error:(NSError **)error; + +// Creates a new blob from the specified file. +// +// This copies the data from the file to the repository's object database. +// +// data - The file to copy contents from. +// repository - The repository to put the object in. +// error - Will be set if an error occurs. +// +// Returns a newly created blob object, or nil if an error occurs. +- (instancetype)initWithFile:(NSURL *)file inRepository:(GTRepository *)repository error:(NSError **)error; // The underlying `git_object` as a `git_blob` object. - (git_blob *)git_blob __attribute__((objc_returns_inner_pointer)); From 1ea8499b6b9240c805f15f93a8e8777b20a97175 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 11:57:45 +0100 Subject: [PATCH 10/61] Make `error` a local variable. --- ObjectiveGitTests/GTBlobSpec.m | 8 +++----- ObjectiveGitTests/GTCommitSpec.m | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ObjectiveGitTests/GTBlobSpec.m b/ObjectiveGitTests/GTBlobSpec.m index 1344b6bf7..93d8e9e8e 100644 --- a/ObjectiveGitTests/GTBlobSpec.m +++ b/ObjectiveGitTests/GTBlobSpec.m @@ -13,11 +13,6 @@ __block GTRepository *repository; __block NSString *blobSHA; __block GTBlob *blob; -__block NSError *error; - -beforeEach(^{ - error = nil; -}); describe(@"blob properties can be accessed", ^{ beforeEach(^{ @@ -51,6 +46,7 @@ describe(@"+blobWithString:inRepository:error", ^{ it(@"works with valid parameters", ^{ + NSError *error = nil; blob = [GTBlob blobWithString:@"a new blob content" inRepository:repository error:&error]; expect(error).to.beNil(); expect(blob).notTo.beNil(); @@ -63,6 +59,7 @@ char bytes[] = "100644 example_helper.rb\00\xD3\xD5\xED\x9D A4_\x00 40000 examples"; NSData *content = [NSData dataWithBytes:bytes length:sizeof(bytes)]; + NSError *error = nil; blob = [GTBlob blobWithData:content inRepository:repository error:&error]; expect(error).to.beNil(); expect(blob).notTo.beNil(); @@ -76,6 +73,7 @@ NSString *fileName = @"myfile.txt"; NSURL *fileURL = [repository.fileURL URLByAppendingPathComponent:fileName]; + NSError *error = nil; BOOL success = [fileContent writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:&error]; expect(success).to.beTruthy(); expect(error).to.beNil(); diff --git a/ObjectiveGitTests/GTCommitSpec.m b/ObjectiveGitTests/GTCommitSpec.m index 81013008e..9ead391be 100644 --- a/ObjectiveGitTests/GTCommitSpec.m +++ b/ObjectiveGitTests/GTCommitSpec.m @@ -11,14 +11,13 @@ SpecBegin(GTCommit) __block GTRepository *repository; -__block NSError *error; beforeEach(^{ repository = self.bareFixtureRepository; - error = nil; }); it(@"can read commit data", ^{ + NSError *error = nil; NSString *commitSHA = @"8496071c1b46c854b31185ea97743be6a8774479"; GTCommit *commit = [repository lookupObjectBySHA:commitSHA error:&error]; @@ -54,6 +53,7 @@ }); it(@"canHaveMultipleParents", ^{ + NSError *error = nil; NSString *commitSHA = @"a4a7dce85cf63874e984719f4fdd239f5145052f"; GTCommit *commit = [repository lookupObjectBySHA:commitSHA error:&error]; expect(commit).notTo.beNil(); From 49ed41f86b5abab8951658accb8932153e5e06dd Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 11:58:01 +0100 Subject: [PATCH 11/61] Expect errors to be nil here. --- ObjectiveGitTests/GTBranchSpec.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ObjectiveGitTests/GTBranchSpec.m b/ObjectiveGitTests/GTBranchSpec.m index ed8c0a318..18aaa3f49 100644 --- a/ObjectiveGitTests/GTBranchSpec.m +++ b/ObjectiveGitTests/GTBranchSpec.m @@ -132,6 +132,7 @@ NSError *error = nil; NSUInteger commitCount = [masterBranch numberOfCommitsWithError:&error]; expect(commitCount).to.equal(164); + expect(error).to.beNil(); }); }); @@ -146,6 +147,7 @@ GTBranch *trackingBranch = [masterBranch trackingBranchWithError:&error success:&success]; expect(trackingBranch).notTo.beNil(); expect(success).to.beTruthy(); + expect(error).to.beNil(); }); it(@"should return nil for a local branch that doesn't track a remote branch", ^{ @@ -156,12 +158,12 @@ GTBranch *otherBranch = [GTBranch branchWithReference:otherRef repository:repository]; expect(otherBranch).notTo.beNil(); - expect(error).to.beNil(); BOOL success = NO; trackingBranch = [otherBranch trackingBranchWithError:&error success:&success]; expect(trackingBranch).to.beNil(); expect(success).to.beTruthy(); + expect(error).to.beNil(); }); it(@"should return itself for a remote branch", ^{ @@ -177,6 +179,7 @@ GTBranch *remoteTrackingBranch = [remoteBranch trackingBranchWithError:&error success:&success]; expect(remoteTrackingBranch).to.equal(remoteBranch); expect(success).to.beTruthy(); + expect(error).to.beNil(); }); }); From 9b1bd6ce911cb4f8607fd3d347115c259f669330 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 11:58:56 +0100 Subject: [PATCH 12/61] Reindent commented test. --- ObjectiveGitTests/GTBranchSpec.m | 44 +++++++++++++++----------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/ObjectiveGitTests/GTBranchSpec.m b/ObjectiveGitTests/GTBranchSpec.m index 18aaa3f49..e1ff7c0ac 100644 --- a/ObjectiveGitTests/GTBranchSpec.m +++ b/ObjectiveGitTests/GTBranchSpec.m @@ -184,28 +184,26 @@ }); // TODO: Test branch renaming, branch upstream -/* - - (void)testCanRenameBranch { - - NSError *error = nil; - GTRepository *repo = [GTRepository repoByOpeningRepositoryInDirectory:[NSURL URLWithString:TEST_REPO_PATH()] error:&error]; - STAssertNil(error, [error localizedDescription]); - - NSArray *branches = [GTBranch listAllLocalBranchesInRepository:repo error:&error]; - STAssertNotNil(branches, [error localizedDescription], nil); - STAssertEquals(2, (int)branches.count, nil); - - NSString *newBranchName = [NSString stringWithFormat:@"%@%@", [GTBranch localNamePrefix], @"this_is_the_renamed_branch"]; - GTBranch *firstBranch = [branches objectAtIndex:0]; - NSString *originalBranchName = firstBranch.name; - BOOL success = [firstBranch.reference setName:newBranchName error:&error]; - STAssertTrue(success, [error localizedDescription]); - STAssertEqualObjects(firstBranch.name, newBranchName, nil); - - success = [firstBranch.reference setName:originalBranchName error:&error]; - STAssertTrue(success, [error localizedDescription]); - STAssertEqualObjects(firstBranch.name, originalBranchName, nil); - } - */ +//- (void)testCanRenameBranch { +// +// NSError *error = nil; +// GTRepository *repo = [GTRepository repoByOpeningRepositoryInDirectory:[NSURL URLWithString:TEST_REPO_PATH()] error:&error]; +// STAssertNil(error, [error localizedDescription]); +// +// NSArray *branches = [GTBranch listAllLocalBranchesInRepository:repo error:&error]; +// STAssertNotNil(branches, [error localizedDescription], nil); +// STAssertEquals(2, (int)branches.count, nil); +// +// NSString *newBranchName = [NSString stringWithFormat:@"%@%@", [GTBranch localNamePrefix], @"this_is_the_renamed_branch"]; +// GTBranch *firstBranch = [branches objectAtIndex:0]; +// NSString *originalBranchName = firstBranch.name; +// BOOL success = [firstBranch.reference setName:newBranchName error:&error]; +// STAssertTrue(success, [error localizedDescription]); +// STAssertEqualObjects(firstBranch.name, newBranchName, nil); +// +// success = [firstBranch.reference setName:originalBranchName error:&error]; +// STAssertTrue(success, [error localizedDescription]); +// STAssertEqualObjects(firstBranch.name, originalBranchName, nil); +//} SpecEnd From 83469744d9294af7903c68ec7b98bd1f87ceee96 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 12:00:16 +0100 Subject: [PATCH 13/61] Rename test. --- ObjectiveGitTests/GTCommitSpec.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ObjectiveGitTests/GTCommitSpec.m b/ObjectiveGitTests/GTCommitSpec.m index 9ead391be..29c3ed3e5 100644 --- a/ObjectiveGitTests/GTCommitSpec.m +++ b/ObjectiveGitTests/GTCommitSpec.m @@ -52,7 +52,7 @@ expect(commit.parents.count).to.equal(0); }); -it(@"canHaveMultipleParents", ^{ +it(@"can have multiple parents", ^{ NSError *error = nil; NSString *commitSHA = @"a4a7dce85cf63874e984719f4fdd239f5145052f"; GTCommit *commit = [repository lookupObjectBySHA:commitSHA error:&error]; From bc98f3c8d59e9a5e700a78824485ceb4e2bbe12c Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 12:00:25 +0100 Subject: [PATCH 14/61] Cruft--; --- ObjectiveGitTests/GTCommitSpec.m | 3 --- 1 file changed, 3 deletions(-) diff --git a/ObjectiveGitTests/GTCommitSpec.m b/ObjectiveGitTests/GTCommitSpec.m index 29c3ed3e5..a0f749e78 100644 --- a/ObjectiveGitTests/GTCommitSpec.m +++ b/ObjectiveGitTests/GTCommitSpec.m @@ -33,14 +33,11 @@ expect(commit.messageDetails).to.equal(@""); expect(commit.commitDate).to.equal([NSDate dateWithTimeIntervalSince1970:1273360386]); -// STAssertEquals((int)[commit.commitDate timeIntervalSince1970], 1273360386, nil); - GTSignature *author = commit.author; expect(author).notTo.beNil(); expect(author.name).to.equal(@"Scott Chacon"); expect(author.email).to.equal(@"schacon@gmail.com"); expect(author.time).to.equal([NSDate dateWithTimeIntervalSince1970:1273360386]); -// STAssertEquals((int)[author.time timeIntervalSince1970], 1273360386, nil); GTSignature *committer = commit.committer; expect(committer).notTo.beNil(); From 86d4f7b17f25bd509b3f4bbed8db5016f0d13172 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 12:01:02 +0100 Subject: [PATCH 15/61] Dot-syntaxify. --- ObjectiveGitTests/GTCommitSpec.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ObjectiveGitTests/GTCommitSpec.m b/ObjectiveGitTests/GTCommitSpec.m index a0f749e78..b304f6066 100644 --- a/ObjectiveGitTests/GTCommitSpec.m +++ b/ObjectiveGitTests/GTCommitSpec.m @@ -24,7 +24,7 @@ expect(commit).notTo.beNil(); expect(error).to.beNil(); - expect(commit).to.beInstanceOf([GTCommit class]); + expect(commit).to.beInstanceOf(GTCommit.class); expect(commit.type).to.equal(@"commit"); expect(commit.SHA).to.equal(commitSHA); From 173e1776de22990834ce5b0e441b83ab08347532 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 12:02:39 +0100 Subject: [PATCH 16/61] Rename `isValidReference` and define it at declaration time. --- ObjectiveGitTests/GTReferenceSpec.m | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ObjectiveGitTests/GTReferenceSpec.m b/ObjectiveGitTests/GTReferenceSpec.m index ad6a52bcb..fc3bf472e 100644 --- a/ObjectiveGitTests/GTReferenceSpec.m +++ b/ObjectiveGitTests/GTReferenceSpec.m @@ -109,17 +109,17 @@ __block GTRepository *bareRepository; __block NSError *error; -__block void (^isValidReference)(GTReference *ref, NSString *SHA, GTReferenceType type, NSString *name); + +void (^expectValidReference)(GTReference *ref, NSString *SHA, GTReferenceType type, NSString *name) = ^(GTReference *ref, NSString *SHA, GTReferenceType type, NSString *name) { + expect(ref).notTo.beNil(); + expect(ref.targetSHA).to.equal(SHA); + expect(ref.referenceType).to.equal(type); + expect(ref.name).to.equal(name); +}; beforeEach(^{ bareRepository = self.bareFixtureRepository; error = nil; - isValidReference = ^(GTReference *ref, NSString *SHA, GTReferenceType type, NSString *name) { - expect(ref).notTo.beNil(); - expect(ref.targetSHA).to.equal(SHA); - expect(ref.referenceType).to.equal(type); - expect(ref.name).to.equal(name); - }; }); describe(@"+referenceByLookingUpReferenceNamed:inRepository:error:", ^{ @@ -128,7 +128,7 @@ expect(ref).notTo.beNil(); expect(error).to.beNil(); - isValidReference(ref, @"36060c58702ed4c2a40832c51758d5344201d89a", GTReferenceTypeOid, @"refs/heads/master"); + expectValidReference(ref, @"36060c58702ed4c2a40832c51758d5344201d89a", GTReferenceTypeOid, @"refs/heads/master"); }); it(@"should return a valid reference to a tag", ^{ @@ -136,7 +136,7 @@ expect(ref).notTo.beNil(); expect(error).to.beNil(); - isValidReference(ref, @"5b5b025afb0b4c913b4c338a42934a3863bf3644", GTReferenceTypeOid, @"refs/tags/v0.9"); + expectValidReference(ref, @"5b5b025afb0b4c913b4c338a42934a3863bf3644", GTReferenceTypeOid, @"refs/tags/v0.9"); }); }); @@ -146,7 +146,7 @@ expect(error).to.beNil(); expect(ref).notTo.beNil(); - isValidReference(ref, @"36060c58702ed4c2a40832c51758d5344201d89a", GTReferenceTypeSymbolic, @"refs/heads/unit_test"); + expectValidReference(ref, @"36060c58702ed4c2a40832c51758d5344201d89a", GTReferenceTypeSymbolic, @"refs/heads/unit_test"); expect(ref.resolvedReference.name).to.equal(@"refs/heads/master"); }); @@ -155,7 +155,7 @@ expect(error).to.beNil(); expect(ref).notTo.beNil(); - isValidReference(ref, @"36060c58702ed4c2a40832c51758d5344201d89a", GTReferenceTypeOid, @"refs/heads/unit_test"); + expectValidReference(ref, @"36060c58702ed4c2a40832c51758d5344201d89a", GTReferenceTypeOid, @"refs/heads/unit_test"); }); }); From 524653562eaa3f67450cc149703c9f27e1f6518c Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 12:03:34 +0100 Subject: [PATCH 17/61] Make `error` a local variable. --- ObjectiveGitTests/GTReferenceSpec.m | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ObjectiveGitTests/GTReferenceSpec.m b/ObjectiveGitTests/GTReferenceSpec.m index fc3bf472e..dac0588b0 100644 --- a/ObjectiveGitTests/GTReferenceSpec.m +++ b/ObjectiveGitTests/GTReferenceSpec.m @@ -108,7 +108,6 @@ }); __block GTRepository *bareRepository; -__block NSError *error; void (^expectValidReference)(GTReference *ref, NSString *SHA, GTReferenceType type, NSString *name) = ^(GTReference *ref, NSString *SHA, GTReferenceType type, NSString *name) { expect(ref).notTo.beNil(); @@ -119,11 +118,11 @@ beforeEach(^{ bareRepository = self.bareFixtureRepository; - error = nil; }); describe(@"+referenceByLookingUpReferenceNamed:inRepository:error:", ^{ it(@"should return a valid reference to a branch", ^{ + NSError *error = nil; GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:@"refs/heads/master" inRepository:bareRepository error:&error]; expect(ref).notTo.beNil(); expect(error).to.beNil(); @@ -132,6 +131,7 @@ }); it(@"should return a valid reference to a tag", ^{ + NSError *error = nil; GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:@"refs/tags/v0.9" inRepository:bareRepository error:&error]; expect(ref).notTo.beNil(); expect(error).to.beNil(); @@ -142,6 +142,7 @@ describe(@"+referenceByCreatingReferenceNamed:fromReferenceTarget:inRepository:error:", ^{ it(@"can create a reference from a symbolic reference", ^{ + NSError *error = nil; GTReference *ref = [GTReference referenceByCreatingReferenceNamed:@"refs/heads/unit_test" fromReferenceTarget:@"refs/heads/master" inRepository:bareRepository error:&error]; expect(error).to.beNil(); expect(ref).notTo.beNil(); @@ -151,6 +152,7 @@ }); it(@"can create a reference from an SHA/OID", ^{ + NSError *error = nil; GTReference *ref = [GTReference referenceByCreatingReferenceNamed:@"refs/heads/unit_test" fromReferenceTarget:@"36060c58702ed4c2a40832c51758d5344201d89a" inRepository:bareRepository error:&error]; expect(error).to.beNil(); expect(ref).notTo.beNil(); @@ -161,6 +163,7 @@ describe(@"-deleteWithError:", ^{ it(@"can delete references", ^{ + NSError *error = nil; GTReference *ref = [GTReference referenceByCreatingReferenceNamed:@"refs/heads/unit_test" fromReferenceTarget:@"36060c58702ed4c2a40832c51758d5344201d89a" inRepository:bareRepository error:&error]; expect(error).to.beNil(); From 79fcc2d8bbfbc4651335c485ad5a26c86428f0f5 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 12:06:29 +0100 Subject: [PATCH 18/61] Fix the `lookupObjectByRefspec:error:` name. --- Classes/GTDiff.m | 2 +- Classes/GTRepository.h | 2 +- Classes/GTRepository.m | 2 +- ObjectiveGitTests/GTRepositorySpec.m | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Classes/GTDiff.m b/Classes/GTDiff.m index 10f763058..013244425 100644 --- a/Classes/GTDiff.m +++ b/Classes/GTDiff.m @@ -151,7 +151,7 @@ + (GTDiff *)diffWorkingDirectoryFromTree:(GTTree *)tree inRepository:(GTReposito + (GTDiff *)diffWorkingDirectoryToHEADInRepository:(GTRepository *)repository options:(NSDictionary *)options error:(NSError **)error { NSParameterAssert(repository != nil); - GTCommit *HEADCommit = [repository lookupObjectByRefspec:@"HEAD" error:NULL]; + GTCommit *HEADCommit = [repository lookupObjectByRevspec:@"HEAD" error:NULL]; GTDiff *HEADIndexDiff = [GTDiff diffIndexFromTree:HEADCommit.tree inRepository:repository options:options error:error]; if (HEADIndexDiff == nil) return nil; diff --git a/Classes/GTRepository.h b/Classes/GTRepository.h index 2cddad3cf..92abed5c1 100644 --- a/Classes/GTRepository.h +++ b/Classes/GTRepository.h @@ -176,7 +176,7 @@ extern NSString *const GTRepositoryCloneOptionsCredentialProvider; - (id)lookupObjectBySHA:(NSString *)sha error:(NSError **)error; // Lookup an object in the repo using a revparse spec -- (id)lookupObjectByRefspec:(NSString *)spec error:(NSError **)error; +- (id)lookupObjectByRevspec:(NSString *)spec error:(NSError **)error; // List all references in the repository // diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index 2b252151a..cbcc70749 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -269,7 +269,7 @@ - (id)lookupObjectBySHA:(NSString *)sha error:(NSError **)error { return [self lookupObjectBySHA:sha objectType:GTObjectTypeAny error:error]; } -- (id)lookupObjectByRefspec:(NSString *)spec error:(NSError **)error { +- (id)lookupObjectByRevspec:(NSString *)spec error:(NSError **)error { git_object *obj; int gitError = git_revparse_single(&obj, self.git_repository, spec.UTF8String); if (gitError < GIT_OK) { diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 9387be9b0..6032e87b2 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -313,7 +313,7 @@ }); }); -describe(@"-lookupObjectByRefspec:error:", ^{ +describe(@"-lookupObjectByRevspec:error:", ^{ __block void (^expectSHAForRevspec)(NSString *SHA, NSString *revspec); beforeEach(^{ @@ -322,7 +322,7 @@ expectSHAForRevspec = ^(NSString *SHA, NSString *revspec) { error = nil; - GTObject *obj = [repository lookupObjectByRefspec:revspec error:&error]; + GTObject *obj = [repository lookupObjectByRevspec:revspec error:&error]; if (SHA != nil) { expect(error).to.beNil(); From d4a1ae8b995e268f8822534ecaa03e83dd0e2097 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 13:14:30 +0100 Subject: [PATCH 19/61] Whitespace. --- ObjectiveGitTests/GTRepositorySpec.m | 1 - 1 file changed, 1 deletion(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 6032e87b2..c897e6502 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -113,7 +113,6 @@ expect(error).to.beNil(); expect(head.targetSHA).to.equal(@"36060c58702ed4c2a40832c51758d5344201d89a"); expect(head.referenceType).to.equal(GTReferenceTypeOid); - }); }); From e09ebb5c5a7822d06f3698606df2564897c5e1b1 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 13:22:06 +0100 Subject: [PATCH 20/61] Test that the returned branches are the expected ones. --- ObjectiveGitTests/GTRepositorySpec.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index c897e6502..ed8de94e9 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -188,6 +188,7 @@ GTBranch *currentBranch = [repository currentBranchWithError:&error]; expect(currentBranch).notTo.beNil(); expect(error).to.beNil(); + expect(currentBranch.name).to.equal(@"refs/heads/master"); }); }); @@ -208,6 +209,8 @@ expect(branches).notTo.beNil(); expect(error).to.beNil(); expect(branches.count).to.equal(1); + GTBranch *remoteBranch = branches[0]; + expect(remoteBranch.name).to.equal(@"refs/remotes/origin/master"); }); }); From d07941e5d528caeeb3f547c4597fb18833a942fa Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 13:25:20 +0100 Subject: [PATCH 21/61] Test the complete reference array in one step. --- ObjectiveGitTests/GTRepositorySpec.m | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index ed8de94e9..ff3be837b 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -222,10 +222,8 @@ expect(error).to.beNil(); expect(refs.count).to.equal(4); - expect(refs).to.contain(@"refs/heads/packed"); - expect(refs).to.contain(@"refs/heads/master"); - expect(refs).to.contain(@"refs/tags/v0.9"); - expect(refs).to.contain(@"refs/tags/v1.0"); + NSArray *expectedRefs = @[ @"refs/heads/master", @"refs/tags/v0.9", @"refs/tags/v1.0", @"refs/heads/packed" ]; + expect(refs).to.equal(expectedRefs); }); }); From 8f47b339636aee3d75dd3812365647b9d8b06138 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 13:27:10 +0100 Subject: [PATCH 22/61] Clarify comment. --- ObjectiveGitTests/GTRepositorySpec.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index ff3be837b..b1eced893 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -62,6 +62,8 @@ __block NSURL *originURL; __block NSURL *workdirURL; + // TODO: Make real remote tests using a repo somewhere + beforeEach(^{ error = nil; transferProgressCalled = NO; @@ -69,7 +71,7 @@ transferProgressBlock = ^(const git_transfer_progress *progress) { transferProgressCalled = YES; }; checkoutProgressBlock = ^(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps) { checkoutProgressCalled = YES; }; - originURL = self.bareFixtureRepository.gitDirectoryURL; //[NSURL URLWithString: @"https://github.com/libgit2/TestGitRepository"]; + originURL = self.bareFixtureRepository.gitDirectoryURL; workdirURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"unit_test"]]; }); From 9bc13e26f008b02d62e6f5ef0797845f5d332cde Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 13:29:36 +0100 Subject: [PATCH 23/61] Test the actual error domain & code. --- ObjectiveGitTests/GTRepositorySpec.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index b1eced893..54ef4e10b 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -51,6 +51,8 @@ GTRepository *badRepo = [GTRepository repositoryWithURL:[NSURL fileURLWithPath:@"fake/1235"] error:&error]; expect(badRepo).to.beNil(); expect(error).notTo.beNil(); + expect(error.domain).to.equal(GTGitErrorDomain); + expect(error.code).to.equal(GIT_ENOTFOUND); }); }); From b88903d17b98c317467a42a87aed884d316bc167 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 24 Oct 2013 20:52:57 +0200 Subject: [PATCH 24/61] Convert local `file:` URLs to paths before handing over to `git_clone`. Fixes a bug where a locally-cloned remote would get a `file:` URL as it's origin URL, making the push machinery shrivel in fear. --- Classes/GTRepository.m | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index cbcc70749..50fff7263 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -218,8 +218,14 @@ + (id)cloneFromURL:(NSURL *)originURL toWorkingDirectory:(NSURL *)workdirURL opt cloneOptions.remote_callbacks.transfer_progress = transferProgressCallback; cloneOptions.remote_callbacks.payload = &payload; - const char *remoteURL = originURL.absoluteString.UTF8String; - const char *workingDirectoryPath = workdirURL.path.UTF8String; + // If our originURL is local, convert to a path before handing down. + const char *remoteURL = NULL; + if (originURL.isFileURL || originURL.isFileReferenceURL) { + remoteURL = originURL.filePathURL.path.fileSystemRepresentation; + } else { + remoteURL = originURL.absoluteString.UTF8String; + } + const char *workingDirectoryPath = workdirURL.path.fileSystemRepresentation; git_repository *repository; int gitError = git_clone(&repository, remoteURL, workingDirectoryPath, &cloneOptions); if (gitError < GIT_OK) { From 2b2be90ef782e9a5fafa9c2ba4e75e7706ab1825 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 29 Oct 2013 18:37:53 +0100 Subject: [PATCH 25/61] Dot-syntaxify. --- Classes/GTRepository.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index 50fff7263..681d87211 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -112,7 +112,7 @@ + (instancetype)initializeEmptyRepositoryAtFileURL:(NSURL *)localFileURL error:( } + (instancetype)initializeEmptyRepositoryAtFileURL:(NSURL *)localFileURL bare:(BOOL)bare error:(NSError **)error { - if (![localFileURL isFileURL] || localFileURL.path == nil) { + if (!localFileURL.isFileURL || localFileURL.path == nil) { if (error != NULL) *error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnsupportedSchemeError userInfo:@{ NSLocalizedDescriptionKey: NSLocalizedString(@"Invalid file path URL to initialize repository.", @"") }]; return NO; } From 8265839fcde15333a40999763eb683f7f72b2fc4 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 29 Oct 2013 18:38:09 +0100 Subject: [PATCH 26/61] Use `-fileSystemRepresentation` here. --- Classes/GTRepository.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index 681d87211..bb15198e0 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -150,7 +150,7 @@ - (id)initWithURL:(NSURL *)localFileURL error:(NSError **)error { } git_repository *r; - int gitError = git_repository_open(&r, localFileURL.path.UTF8String); + int gitError = git_repository_open(&r, localFileURL.path.fileSystemRepresentation); if (gitError < GIT_OK) { if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to open repository at URL %@.", localFileURL]; return nil; From bcdd9278e76e7b767d9f3214afe7a747a5baefad Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 29 Oct 2013 18:39:31 +0100 Subject: [PATCH 27/61] File reference URLs are file URLs; no need for a separate test. --- Classes/GTRepository.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index bb15198e0..a0cb0ef04 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -220,7 +220,7 @@ + (id)cloneFromURL:(NSURL *)originURL toWorkingDirectory:(NSURL *)workdirURL opt // If our originURL is local, convert to a path before handing down. const char *remoteURL = NULL; - if (originURL.isFileURL || originURL.isFileReferenceURL) { + if (originURL.isFileURL) { remoteURL = originURL.filePathURL.path.fileSystemRepresentation; } else { remoteURL = originURL.absoluteString.UTF8String; From aa510a6a666e1d4228f4281263cf2d4ef48a36c3 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 29 Oct 2013 18:40:19 +0100 Subject: [PATCH 28/61] Useless call; file reference URLs know how to path-ify themselves. --- Classes/GTRepository.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index a0cb0ef04..324729f8b 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -221,7 +221,7 @@ + (id)cloneFromURL:(NSURL *)originURL toWorkingDirectory:(NSURL *)workdirURL opt // If our originURL is local, convert to a path before handing down. const char *remoteURL = NULL; if (originURL.isFileURL) { - remoteURL = originURL.filePathURL.path.fileSystemRepresentation; + remoteURL = originURL.path.fileSystemRepresentation; } else { remoteURL = originURL.absoluteString.UTF8String; } From 7f7cb21829049715a31a05887b6b56090ef4a036 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 29 Oct 2013 19:01:33 +0100 Subject: [PATCH 29/61] =?UTF-8?q?Test=20that=20the=20remote=20set=20by=20`?= =?UTF-8?q?+clone=E2=80=A6`=20looks=20fine=20to=20libgit2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ObjectiveGitTests/GTRepositorySpec.m | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 54ef4e10b..485d787d5 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -83,8 +83,8 @@ BOOL success = [NSFileManager.defaultManager removeItemAtURL:workdirURL error:&error]; expect(success).to.beTruthy(); expect(error).to.beNil(); - } - }); + } + }); it(@"should handle normal clones", ^{ repository = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:nil error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; @@ -118,6 +118,20 @@ expect(head.targetSHA).to.equal(@"36060c58702ed4c2a40832c51758d5344201d89a"); expect(head.referenceType).to.equal(GTReferenceTypeOid); }); + + it(@"should have set a valid remote URL", ^{ + NSError *error = nil; + GTRepository *repo = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:nil error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; + expect(repo).notTo.beNil(); + expect(error).to.beNil(); + + // FIXME: Move that to a method in GTRepository ? + // Or use the new initializers in GTRemote that are waiting in #224 + git_remote *remote; + git_remote_load(&remote, repo.git_repository, "origin"); + GTRemote *originRemote = [[GTRemote alloc] initWithGitRemote:remote]; + expect(originRemote.URLString).to.equal(originURL.path); + }); }); describe(@"-headReferenceWithError:", ^{ From 2986a6b99d6ffde59265cb70cdc4d263849a9959 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 13:53:33 +0100 Subject: [PATCH 30/61] De-oneline-ify. --- ObjectiveGitTests/GTRepositorySpec.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 485d787d5..2a9ebedbb 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -70,8 +70,12 @@ error = nil; transferProgressCalled = NO; checkoutProgressCalled = NO; - transferProgressBlock = ^(const git_transfer_progress *progress) { transferProgressCalled = YES; }; - checkoutProgressBlock = ^(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps) { checkoutProgressCalled = YES; }; + transferProgressBlock = ^(const git_transfer_progress *progress) { + transferProgressCalled = YES; + }; + checkoutProgressBlock = ^(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps) { + checkoutProgressCalled = YES; + }; originURL = self.bareFixtureRepository.gitDirectoryURL; workdirURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"unit_test"]]; From cff180a6b61cfb4b8dd8b1633fc3720fb4a5d1aa Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 14:15:49 +0100 Subject: [PATCH 31/61] Make `error` a local. --- ObjectiveGitTests/GTRepositorySpec.m | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 2a9ebedbb..30aa2c84a 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -12,12 +12,10 @@ SpecBegin(GTRepository) __block GTRepository *repository; -__block NSError *error = nil; beforeEach(^{ repository = self.testAppFixtureRepository; expect(repository).notTo.beNil(); - error = nil; }); describe(@"+initializeEmptyRepositoryAtFileURL:bare:error:", ^{ @@ -48,6 +46,7 @@ describe(@"+repositoryWithURL:error:", ^{ it(@"should fail to initialize non-existent repos", ^{ + NSError *error = nil; GTRepository *badRepo = [GTRepository repositoryWithURL:[NSURL fileURLWithPath:@"fake/1235"] error:&error]; expect(badRepo).to.beNil(); expect(error).notTo.beNil(); @@ -67,7 +66,6 @@ // TODO: Make real remote tests using a repo somewhere beforeEach(^{ - error = nil; transferProgressCalled = NO; checkoutProgressCalled = NO; transferProgressBlock = ^(const git_transfer_progress *progress) { @@ -91,6 +89,7 @@ }); it(@"should handle normal clones", ^{ + NSError *error = nil; repository = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:nil error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; expect(repository).notTo.beNil(); expect(error).to.beNil(); @@ -107,6 +106,7 @@ }); it(@"should handle bare clones", ^{ + NSError *error = nil; NSDictionary *options = @{ GTRepositoryCloneOptionsBare: @YES }; repository = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:options error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; expect(repository).notTo.beNil(); @@ -140,6 +140,7 @@ describe(@"-headReferenceWithError:", ^{ it(@"should allow HEAD to be looked up", ^{ + NSError *error = nil; GTReference *head = [self.bareFixtureRepository headReferenceWithError:&error]; expect(head).notTo.beNil(); expect(error).to.beNil(); @@ -154,6 +155,7 @@ }); it(@"should return YES for a new repository", ^{ + NSError *error = nil; NSURL *fileURL = [self.tempDirectoryFileURL URLByAppendingPathComponent:@"newrepo"]; GTRepository *newRepo = [GTRepository initializeEmptyRepositoryAtFileURL:fileURL error:&error]; expect(newRepo.isEmpty).to.beTruthy(); @@ -310,6 +312,7 @@ }); it(@"should move HEAD when used", ^{ + NSError *error = nil; GTReference *originalHead = [repository headReferenceWithError:NULL]; NSString *resetTargetSHA = @"8496071c1b46c854b31185ea97743be6a8774479"; @@ -340,10 +343,9 @@ beforeEach(^{ repository = self.bareFixtureRepository; - error = nil; expectSHAForRevspec = ^(NSString *SHA, NSString *revspec) { - error = nil; + NSError *error = nil; GTObject *obj = [repository lookupObjectByRevspec:revspec error:&error]; if (SHA != nil) { From cbe71f8bca3e5447ee9c7ce36de01525157afd82 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 14:24:53 +0100 Subject: [PATCH 32/61] Add methods to create new bare and non-bare repositories to `GTTestCase`. --- ObjectiveGitTests/GTRepositorySpec.m | 36 +++++++++------------------- ObjectiveGitTests/GTTestCase.h | 6 +++++ ObjectiveGitTests/GTTestCase.m | 16 +++++++++++++ 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 30aa2c84a..dd719fe23 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -19,27 +19,22 @@ }); describe(@"+initializeEmptyRepositoryAtFileURL:bare:error:", ^{ - __block GTRepository * (^createRepository)(BOOL bare); - - beforeEach(^{ - createRepository = ^(BOOL bare) { - NSURL *newRepoURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"unit_test"]]; - [NSFileManager.defaultManager removeItemAtURL:newRepoURL error:NULL]; - - GTRepository *repository = [GTRepository initializeEmptyRepositoryAtFileURL:newRepoURL bare:bare error:NULL]; - expect(repository).notTo.beNil(); - expect(repository.gitDirectoryURL).notTo.beNil(); - return repository; - }; - }); - it(@"should initialize a repository with a working directory by default", ^{ - GTRepository *repository = createRepository(NO); + NSURL *newRepoURL = [self.tempDirectoryFileURL URLByAppendingPathComponent:@"init-repo"]; + + GTRepository *repository = [GTRepository initializeEmptyRepositoryAtFileURL:newRepoURL bare:NO error:NULL]; + expect(repository).notTo.beNil(); + expect(repository.gitDirectoryURL).notTo.beNil(); expect(repository.bare).to.beFalsy(); }); it(@"should initialize a bare repository", ^{ - GTRepository *repository = createRepository(YES); + NSURL *newRepoURL = [self.tempDirectoryFileURL URLByAppendingPathComponent:@"init-repo.git"]; + + GTRepository *repository = [GTRepository initializeEmptyRepositoryAtFileURL:newRepoURL bare:YES error:NULL]; + expect(repository).notTo.beNil(); + expect(repository.gitDirectoryURL).notTo.beNil(); + return repository; expect(repository.bare).to.beTruthy(); }); }); @@ -79,15 +74,6 @@ workdirURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"unit_test"]]; }); - afterEach(^{ - if ([NSFileManager.defaultManager fileExistsAtPath:workdirURL.path isDirectory:NULL]) { - NSError *error = nil; - BOOL success = [NSFileManager.defaultManager removeItemAtURL:workdirURL error:&error]; - expect(success).to.beTruthy(); - expect(error).to.beNil(); - } - }); - it(@"should handle normal clones", ^{ NSError *error = nil; repository = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:nil error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; diff --git a/ObjectiveGitTests/GTTestCase.h b/ObjectiveGitTests/GTTestCase.h index 2d67cc2d8..b29edee85 100644 --- a/ObjectiveGitTests/GTTestCase.h +++ b/ObjectiveGitTests/GTTestCase.h @@ -29,4 +29,10 @@ // A repository containing conflicts. - (GTRepository *)conflictedFixtureRepository; +// A pristine repository (bare). +- (GTRepository *)blankBareFixtureRepository; + +// A pristine repository. +- (GTRepository *)blankFixtureRepository; + @end diff --git a/ObjectiveGitTests/GTTestCase.m b/ObjectiveGitTests/GTTestCase.m index 14651cbc1..6b2b2cf2a 100644 --- a/ObjectiveGitTests/GTTestCase.m +++ b/ObjectiveGitTests/GTTestCase.m @@ -114,6 +114,22 @@ - (GTRepository *)conflictedFixtureRepository { return [self fixtureRepositoryNamed:@"conflicted-repo"]; } +- (GTRepository *)blankFixtureRepository { + NSURL *repoURL = [self.tempDirectoryFileURL URLByAppendingPathComponent:@"blank-repo"]; + + GTRepository *repository = [GTRepository initializeEmptyRepositoryAtFileURL:repoURL bare:NO error:NULL]; + STAssertNotNil(repository, @"Couldn't create a blank repository"); + return repository; +} + +- (GTRepository *)blankBareFixtureRepository { + NSURL *repoURL = [self.tempDirectoryFileURL URLByAppendingPathComponent:@"blank-repo.git"]; + + GTRepository *repository = [GTRepository initializeEmptyRepositoryAtFileURL:repoURL bare:YES error:NULL]; + STAssertNotNil(repository, @"Couldn't create a blank repository"); + return repository; +} + #pragma mark Properties - (NSBundle *)mainTestBundle { From c43cad57a8131bd395dc4f9064cf892c169dd528 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 13:56:40 +0100 Subject: [PATCH 33/61] Test that new repos have unborn HEADs. --- ObjectiveGitTests/GTRepositorySpec.m | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index dd719fe23..12034b488 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -133,6 +133,18 @@ expect(head.targetSHA).to.equal(@"36060c58702ed4c2a40832c51758d5344201d89a"); expect(head.referenceType).to.equal(GTReferenceTypeOid); }); + + it(@"should fail to return HEAD for an unborn repo", ^{ + GTRepository *repo = self.blankFixtureRepository; + expect(repo.isHEADUnborn).to.beTruthy(); + + NSError *error = nil; + GTReference *head = [repo headReferenceWithError:&error]; + expect(head).to.beNil(); + expect(error).notTo.beNil(); + expect(error.domain).to.equal(GTGitErrorDomain); + expect(error.code).to.equal(GIT_EUNBORNBRANCH); + }); }); describe(@"-isEmpty", ^{ From 3dd9c7027e58e9f0743fd53c7c2c32782141f18f Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 14:16:15 +0100 Subject: [PATCH 34/61] Define `expectSHAForRevspec` inline. --- ObjectiveGitTests/GTRepositorySpec.m | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 12034b488..fe0010e5f 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -337,24 +337,22 @@ }); describe(@"-lookupObjectByRevspec:error:", ^{ - __block void (^expectSHAForRevspec)(NSString *SHA, NSString *revspec); + void (^expectSHAForRevspec)(NSString *SHA, NSString *revspec) = ^(NSString *SHA, NSString *revspec) { + NSError *error = nil; + GTObject *obj = [repository lookupObjectByRevspec:revspec error:&error]; + + if (SHA != nil) { + expect(error).to.beNil(); + expect(obj).notTo.beNil(); + expect(obj.SHA).to.equal(SHA); + } else { + expect(error).notTo.beNil(); + expect(obj).to.beNil(); + } + };; beforeEach(^{ repository = self.bareFixtureRepository; - - expectSHAForRevspec = ^(NSString *SHA, NSString *revspec) { - NSError *error = nil; - GTObject *obj = [repository lookupObjectByRevspec:revspec error:&error]; - - if (SHA != nil) { - expect(error).to.beNil(); - expect(obj).notTo.beNil(); - expect(obj.SHA).to.equal(SHA); - } else { - expect(error).notTo.beNil(); - expect(obj).to.beNil(); - } - }; }); it(@"should parse various revspecs", ^{ From 378b31d915f2797e21fd64391fcf2f51e95c41f8 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 14:36:07 +0100 Subject: [PATCH 35/61] Use the clone tests from #280. --- ObjectiveGitTests/GTRepositorySpec.m | 92 +++++++++++++++------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index fe0010e5f..5907cf064 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -50,7 +50,7 @@ }); }); -describe(@"+cloneFromURL:toWorkingDirectory:...", ^{ +describe(@"+cloneFromURL:toWorkingDirectory:options:error:transferProgressBlock:checkoutProgressBlock:", ^{ __block BOOL transferProgressCalled = NO; __block BOOL checkoutProgressCalled = NO; __block void (^transferProgressBlock)(const git_transfer_progress *); @@ -74,54 +74,60 @@ workdirURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"unit_test"]]; }); - it(@"should handle normal clones", ^{ - NSError *error = nil; - repository = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:nil error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; - expect(repository).notTo.beNil(); - expect(error).to.beNil(); - expect(transferProgressCalled).to.beTruthy(); - expect(checkoutProgressCalled).to.beTruthy(); + describe(@"with local repositories", ^{ + beforeEach(^{ + originURL = self.bareFixtureRepository.gitDirectoryURL; + }); - expect(repository.isBare).to.beFalsy(); + it(@"should handle normal clones", ^{ + NSError *error = nil; + repository = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:nil error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; + expect(repository).notTo.beNil(); + expect(error).to.beNil(); + expect(transferProgressCalled).to.beTruthy(); + expect(checkoutProgressCalled).to.beTruthy(); - GTReference *head = [repository headReferenceWithError:&error]; - expect(head).notTo.beNil(); - expect(error).to.beNil(); - expect(head.targetSHA).to.equal(@"36060c58702ed4c2a40832c51758d5344201d89a"); - expect(head.referenceType).to.equal(GTReferenceTypeOid); - }); + expect(repository.isBare).to.beFalsy(); - it(@"should handle bare clones", ^{ - NSError *error = nil; - NSDictionary *options = @{ GTRepositoryCloneOptionsBare: @YES }; - repository = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:options error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; - expect(repository).notTo.beNil(); - expect(error).to.beNil(); - expect(transferProgressCalled).to.beTruthy(); - expect(checkoutProgressCalled).to.beTruthy(); + GTReference *head = [repository headReferenceWithError:&error]; + expect(head).notTo.beNil(); + expect(error).to.beNil(); + expect(head.targetSHA).to.equal(@"36060c58702ed4c2a40832c51758d5344201d89a"); + expect(head.referenceType).to.equal(GTReferenceTypeOid); + }); + + it(@"should handle bare clones", ^{ + NSError *error = nil; + NSDictionary *options = @{ GTRepositoryCloneOptionsBare: @YES }; + repository = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:options error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; + expect(repository).notTo.beNil(); + expect(error).to.beNil(); + expect(transferProgressCalled).to.beTruthy(); + expect(checkoutProgressCalled).to.beTruthy(); - expect(repository.isBare).to.beTruthy(); + expect(repository.isBare).to.beTruthy(); - GTReference *head = [repository headReferenceWithError:&error]; - expect(head).notTo.beNil(); - expect(error).to.beNil(); - expect(head.targetSHA).to.equal(@"36060c58702ed4c2a40832c51758d5344201d89a"); - expect(head.referenceType).to.equal(GTReferenceTypeOid); - }); + GTReference *head = [repository headReferenceWithError:&error]; + expect(head).notTo.beNil(); + expect(error).to.beNil(); + expect(head.targetSHA).to.equal(@"36060c58702ed4c2a40832c51758d5344201d89a"); + expect(head.referenceType).to.equal(GTReferenceTypeOid); + }); + + it(@"should have set a valid remote URL", ^{ + NSError *error = nil; + GTRepository *repo = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:nil error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; + expect(repo).notTo.beNil(); + expect(error).to.beNil(); - it(@"should have set a valid remote URL", ^{ - NSError *error = nil; - GTRepository *repo = [GTRepository cloneFromURL:originURL toWorkingDirectory:workdirURL options:nil error:&error transferProgressBlock:transferProgressBlock checkoutProgressBlock:checkoutProgressBlock]; - expect(repo).notTo.beNil(); - expect(error).to.beNil(); - - // FIXME: Move that to a method in GTRepository ? - // Or use the new initializers in GTRemote that are waiting in #224 - git_remote *remote; - git_remote_load(&remote, repo.git_repository, "origin"); - GTRemote *originRemote = [[GTRemote alloc] initWithGitRemote:remote]; - expect(originRemote.URLString).to.equal(originURL.path); - }); + // FIXME: Move that to a method in GTRepository ? + // Or use the new initializers in GTRemote that are waiting in #224 + git_remote *remote; + git_remote_load(&remote, repo.git_repository, "origin"); + GTRemote *originRemote = [[GTRemote alloc] initWithGitRemote:remote]; + expect(originRemote.URLString).to.equal(originURL.path); + }); + }); }); describe(@"-headReferenceWithError:", ^{ From 87efa7465ad142e793b3012537f3366720affc9c Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 14:36:34 +0100 Subject: [PATCH 36/61] Put the newly-cloned repo in the test-case managed temporary directory. --- ObjectiveGitTests/GTRepositorySpec.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 5907cf064..0e51e213c 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -70,8 +70,7 @@ checkoutProgressCalled = YES; }; - originURL = self.bareFixtureRepository.gitDirectoryURL; - workdirURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"unit_test"]]; + workdirURL = [self.tempDirectoryFileURL URLByAppendingPathComponent:@"temp-repo"]; }); describe(@"with local repositories", ^{ From 87fff3b27b354ee87f6cb6732b3cf465a74dfa40 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 14:39:34 +0100 Subject: [PATCH 37/61] Huh, bare clones don't checkout... --- ObjectiveGitTests/GTRepositorySpec.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 0e51e213c..4d1ddee5a 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -102,7 +102,7 @@ expect(repository).notTo.beNil(); expect(error).to.beNil(); expect(transferProgressCalled).to.beTruthy(); - expect(checkoutProgressCalled).to.beTruthy(); + expect(checkoutProgressCalled).to.beFalsy(); expect(repository.isBare).to.beTruthy(); From 60b6c7e76c30cca7bb038c531b61d2feb68fcd0a Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 29 Oct 2013 22:52:10 +0100 Subject: [PATCH 38/61] Reorganize methods. --- Classes/GTReference.h | 31 +++++----- Classes/GTReference.m | 131 +++++++++++++++++++++++------------------- 2 files changed, 87 insertions(+), 75 deletions(-) diff --git a/Classes/GTReference.h b/Classes/GTReference.h index 715681775..336119324 100644 --- a/Classes/GTReference.h +++ b/Classes/GTReference.h @@ -48,12 +48,28 @@ typedef enum { @property (nonatomic, readonly) const git_oid *git_oid; @property (nonatomic, strong, readonly) GTOID *OID; + +// The name of the reference. +@property (nonatomic, readonly, copy) NSString *name; + // Whether this is a remote-tracking branch. @property (nonatomic, readonly, getter = isRemote) BOOL remote; // The reflog for the reference. @property (nonatomic, readonly, strong) GTReflog *reflog; +// The target (either GTObject or GTReference) to which the reference points. +@property (nonatomic, readonly, copy) id unresolvedTarget; + +// The resolved object to which the reference points. +@property (nonatomic, readonly, copy) id resolvedTarget; + +// The last direct reference in a chain +@property (nonatomic, readonly, copy) GTReference *resolvedReference; + +// The SHA of the target object +@property (nonatomic, readonly, copy) NSString *targetSHA; + // Convenience initializers + (id)referenceByLookingUpReferencedNamed:(NSString *)refName inRepository:(GTRepository *)theRepo error:(NSError **)error; - (id)initByLookingUpReferenceNamed:(NSString *)refName inRepository:(GTRepository *)theRepo error:(NSError **)error; @@ -69,18 +85,6 @@ typedef enum { // The underlying `git_reference` object. - (git_reference *)git_reference __attribute__((objc_returns_inner_pointer)); -// The target (either GTObject or GTReference) to which the reference points. -@property (nonatomic, readonly, copy) id unresolvedTarget; - -// The resolved object to which the reference points. -@property (nonatomic, readonly, copy) id resolvedTarget; - -// The last direct reference in a chain -@property (nonatomic, readonly, copy) GTReference *resolvedReference; - -// The SHA of the target object -@property (nonatomic, readonly, copy) NSString *targetSHA; - // Updates the on-disk reference to point to the target and returns the updated // reference. // @@ -92,9 +96,6 @@ typedef enum { // Returns the updated reference, or nil if an error occurred. - (GTReference *)referenceByUpdatingTarget:(NSString *)newTarget error:(NSError **)error; -// The name of the reference. -@property (nonatomic, readonly, copy) NSString *name; - // Updates the on-disk reference to the name and returns the renamed reference. // // Note that this does *not* change the receiver's name. diff --git a/Classes/GTReference.m b/Classes/GTReference.m index e09b905b1..4ee96ece8 100644 --- a/Classes/GTReference.m +++ b/Classes/GTReference.m @@ -51,20 +51,20 @@ @interface GTReference () @implementation GTReference -- (void)dealloc { - if (_git_reference != NULL) { - git_reference_free(_git_reference); - _git_reference = NULL; - } -} +#pragma mark - +#pragma mark Class methods ++ (NSError *)invalidReferenceError { + return [NSError git_errorFor:GTReferenceErrorCodeInvalidReference description:@"Invalid git_reference."]; +} -#pragma mark API - -- (BOOL)isRemote { - return git_reference_is_remote(self.git_reference) != 0; ++ (BOOL)isValidReferenceName:(NSString *)refName { + return git_reference_is_valid_name(refName.UTF8String) == 1; } +#pragma mark - +#pragma mark Lifecycle + + (id)referenceByLookingUpReferencedNamed:(NSString *)refName inRepository:(GTRepository *)theRepo error:(NSError **)error { return [[self alloc] initByLookingUpReferenceNamed:refName inRepository:theRepo error:error]; } @@ -139,6 +139,38 @@ - (id)initWithGitReference:(git_reference *)ref repository:(GTRepository *)repo return self; } +- (void)dealloc { + if (_git_reference != NULL) { + git_reference_free(_git_reference); + _git_reference = NULL; + } +} + +#pragma mark - +#pragma mark NSObject + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p>{ OID: %@, type: %@, remote: %i }", self.class, self, self.OID, referenceTypeToString(self.referenceType), (int)self.remote]; +} + +- (NSUInteger)hash { + return self.name.hash; +} + +- (BOOL)isEqual:(GTReference *)reference { + if (self == reference) return YES; + if (![reference isKindOfClass:GTReference.class]) return NO; + + return [self.repository isEqual:reference.repository] && [self.name isEqual:reference.name] && [self.unresolvedTarget isEqual:reference.unresolvedTarget]; +} + +#pragma mark - +#pragma mark Properties + +- (BOOL)isRemote { + return git_reference_is_remote(self.git_reference) != 0; +} + - (NSString *)name { const char *refName = git_reference_name(self.git_reference); if (refName == NULL) return nil; @@ -146,17 +178,15 @@ - (NSString *)name { return @(refName); } -- (GTReference *)referenceByRenaming:(NSString *)newName error:(NSError **)error { - NSParameterAssert(newName != nil); - - git_reference *newRef = NULL; - int gitError = git_reference_rename(&newRef, self.git_reference, newName.UTF8String, 0); - if (gitError != GIT_OK) { - if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to rename reference %@ to %@.", self.name, newName]; - return NO; - } +- (const git_oid *)git_oid { + return git_reference_target(self.git_reference); +} - return [[self.class alloc] initWithGitReference:newRef repository:self.repository]; +- (GTOID *)OID { + const git_oid *oid = self.git_oid; + if (oid == NULL) return nil; + + return [[GTOID alloc] initWithGitOid:oid]; } - (GTReferenceType)referenceType { @@ -194,6 +224,27 @@ - (NSString *)targetSHA { return [self.resolvedTarget SHA]; } +- (GTReflog *)reflog { + return [[GTReflog alloc] initWithReference:self]; +} + + +#pragma mark - +#pragma mark API + +- (GTReference *)referenceByRenaming:(NSString *)newName error:(NSError **)error { + NSParameterAssert(newName != nil); + + git_reference *newRef = NULL; + int gitError = git_reference_rename(&newRef, self.git_reference, newName.UTF8String, 0); + if (gitError != GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to rename reference %@ to %@.", self.name, newName]; + return NO; + } + + return [[self.class alloc] initWithGitReference:newRef repository:self.repository]; +} + - (GTReference *)referenceByUpdatingTarget:(NSString *)newTarget error:(NSError **)error { NSParameterAssert(newTarget != nil); @@ -230,48 +281,8 @@ - (GTReference *)resolvedReferenceWithError:(NSError **)error { return [GTReference referenceByResolvingSymbolicReference:self error:error]; } -- (const git_oid *)git_oid { - return git_reference_target(self.git_reference); -} - -- (GTOID *)OID { - const git_oid *oid = self.git_oid; - if (oid == NULL) return nil; - - return [[GTOID alloc] initWithGitOid:oid]; -} - - (GTReference *)reloadedReferenceWithError:(NSError **)error { return [[self.class alloc] initByLookingUpReferenceNamed:self.name inRepository:self.repository error:error]; } -+ (NSError *)invalidReferenceError { - return [NSError git_errorFor:GTReferenceErrorCodeInvalidReference description:@"Invalid git_reference."]; -} - -- (GTReflog *)reflog { - return [[GTReflog alloc] initWithReference:self]; -} - -+ (BOOL)isValidReferenceName:(NSString *)refName { - return git_reference_is_valid_name(refName.UTF8String) == 1; -} - -#pragma mark NSObject - -- (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p>{ OID: %@, type: %@, remote: %i }", self.class, self, self.OID, referenceTypeToString(self.referenceType), (int)self.remote]; -} - -- (NSUInteger)hash { - return self.name.hash; -} - -- (BOOL)isEqual:(GTReference *)reference { - if (self == reference) return YES; - if (![reference isKindOfClass:GTReference.class]) return NO; - - return [self.repository isEqual:reference.repository] && [self.name isEqual:reference.name] && [self.unresolvedTarget isEqual:reference.unresolvedTarget]; -} - @end From 7d686badc31167777aced5e19e5703900b1eb8fb Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 29 Oct 2013 22:55:12 +0100 Subject: [PATCH 39/61] Add `isTag` and `isBranch` to `GTReference`. --- Classes/GTReference.h | 6 ++++++ Classes/GTReference.m | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/Classes/GTReference.h b/Classes/GTReference.h index 336119324..f34ef3d24 100644 --- a/Classes/GTReference.h +++ b/Classes/GTReference.h @@ -52,6 +52,12 @@ typedef enum { // The name of the reference. @property (nonatomic, readonly, copy) NSString *name; +// 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; diff --git a/Classes/GTReference.m b/Classes/GTReference.m index 4ee96ece8..ed71cf6bc 100644 --- a/Classes/GTReference.m +++ b/Classes/GTReference.m @@ -167,6 +167,14 @@ - (BOOL)isEqual:(GTReference *)reference { #pragma mark - #pragma mark Properties +- (BOOL)isBranch { + return git_reference_is_branch(self.git_reference) != 0; +} + +- (BOOL)isTag { + return git_reference_is_tag(self.git_reference) != 0; +} + - (BOOL)isRemote { return git_reference_is_remote(self.git_reference) != 0; } From e16488a2ed026d11dbf524c4248f097de317d8f8 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Wed, 30 Oct 2013 00:55:19 +0100 Subject: [PATCH 40/61] Add a branch enumerator using `git_branch_foreach` and use it. --- Classes/GTRepository.m | 55 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index 38ddd9475..821972a6c 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -297,22 +297,57 @@ - (GTReference *)headReferenceWithError:(NSError **)error { return [[GTReference alloc] initWithGitReference:headRef repository:self]; } +typedef void (^GTRepositoryBranchEnumerationBlock)(GTBranch *branch, BOOL *stop); + +struct GTRepositoryBranchEnumerationInfo { + __unsafe_unretained GTRepository *myself; + __unsafe_unretained GTRepositoryBranchEnumerationBlock block; +}; + +int GTRepositoryForeachBranchCallback(const char *name, git_branch_t type, void *payload) { + struct GTRepositoryBranchEnumerationInfo *info = payload; + + GTBranch *branch = [GTBranch branchWithName:@(name) repository:info->myself error:NULL]; + if (!branch) return -1; + + BOOL stop = NO; + info->block(branch, &stop); + + return stop == YES ? -1 : 0; +} + +- (BOOL)enumerateBranchesWithType:(GTBranchType)type error:(NSError **)error usingBlock:(GTRepositoryBranchEnumerationBlock)block { + struct GTRepositoryBranchEnumerationInfo info = { .myself = self, .block = block }; + int gitError = git_branch_foreach(self.git_repository, type, GTRepositoryForeachBranchCallback, &info); + if (gitError != GIT_OK) { + if (error) *error = [NSError git_errorFor:gitError description:@"Branch enumeration failed"]; + return NO; + } + + return YES; +} + - (NSArray *)localBranchesWithError:(NSError **)error { - return [self branchesWithPrefix:[GTBranch localNamePrefix] error:error]; + NSMutableArray *localBranches = [NSMutableArray array]; + BOOL success = [self enumerateBranchesWithType:GTBranchTypeLocal error:error usingBlock:^(GTBranch *branch, BOOL *stop) { + [localBranches addObject:branch]; + }]; + + if (success != YES) return nil; + + return [localBranches copy]; } - (NSArray *)remoteBranchesWithError:(NSError **)error { - NSArray *remoteBranches = [self branchesWithPrefix:[GTBranch remoteNamePrefix] error:error]; - if (remoteBranches == nil) return nil; + NSMutableArray *remoteBranches = [NSMutableArray array]; + BOOL success = [self enumerateBranchesWithType:GTBranchTypeRemote error:error usingBlock:^(GTBranch *branch, BOOL *stop) { + if (![branch.shortName isEqualToString:@"HEAD"]) + [remoteBranches addObject:branch]; + }]; - NSMutableArray *filteredList = [NSMutableArray arrayWithCapacity:remoteBranches.count]; - for (GTBranch *branch in remoteBranches) { - if (![branch.shortName isEqualToString:@"HEAD"]) { - [filteredList addObject:branch]; - } - } + if (success != YES) return nil; - return filteredList; + return [remoteBranches copy]; } - (NSArray *)branchesWithPrefix:(NSString *)prefix error:(NSError **)error { From a73a08b5584889b369b2be5971cb556d03b5ec72 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 29 Oct 2013 18:48:28 +0100 Subject: [PATCH 41/61] Add a method to enumerate a repository's references. --- Classes/GTRepository.h | 11 +++++++++++ Classes/GTRepository.m | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/Classes/GTRepository.h b/Classes/GTRepository.h index 92abed5c1..63bc447e1 100644 --- a/Classes/GTRepository.h +++ b/Classes/GTRepository.h @@ -187,6 +187,17 @@ extern NSString *const GTRepositoryCloneOptionsCredentialProvider; // returns nil if an error occurred and fills the error parameter - (NSArray *)referenceNamesWithError:(NSError **)error; +// Enumerate over all references is the repository. +// +// error - If not NULL, this pointer will be set to the actual error that occurred. +// block - A block which will be called for each reference. You will be passed +// the reference object in `ref`, `error` will be set to something if `ref` +// is nil, and `stop` will stop the enumeration if it's set to YES. +// +// Returns YES if enumeration was successful, NO otherwise (and the `error` +// parameter will be set to the actual error that occurred). +- (BOOL)enumerateReferencesWithError:(NSError **)error usingBlock:(void (^)(GTReference *reference, NSError *error, BOOL *stop))block; + - (GTReference *)headReferenceWithError:(NSError **)error; // Convenience methods to return branches in the repository diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index 821972a6c..8d2ebcfe7 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -479,6 +479,23 @@ - (NSArray *)referenceNamesWithError:(NSError **)error { return referenceNames; } +- (BOOL)enumerateReferencesWithError:(NSError **)error usingBlock:(void (^)(GTReference *reference, NSError *error, BOOL *stop))block { + NSArray *references = [self referenceNamesWithError:error]; + if (!references) return NO; + + for (NSString *refName in references) { + NSError *refError; + BOOL stop = NO; + + GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:refName inRepository:self error:&refError]; + + block(ref, refError, &stop); + + if (stop == YES) break; + } + return YES; +} + - (NSURL *)fileURL { const char *path = git_repository_workdir(self.git_repository); // bare repository, you may be looking for gitDirectoryURL From bac8e98f7ad3d0becf4d53a5275d9cca407bf5f8 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 29 Oct 2013 18:48:37 +0100 Subject: [PATCH 42/61] Fix the documentation of that one. --- Classes/GTRepository.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Classes/GTRepository.h b/Classes/GTRepository.h index 63bc447e1..d36c9cf67 100644 --- a/Classes/GTRepository.h +++ b/Classes/GTRepository.h @@ -178,13 +178,12 @@ extern NSString *const GTRepositoryCloneOptionsCredentialProvider; // Lookup an object in the repo using a revparse spec - (id)lookupObjectByRevspec:(NSString *)spec error:(NSError **)error; -// List all references in the repository +// List all reference names in the repository. // -// repository - The GTRepository to list references in -// error(out) - will be filled if an error occurs +// error - If not NULL, this pointer will be set to the actual error that occurred. // -// returns an array of NSStrings holding the names of the references -// returns nil if an error occurred and fills the error parameter +// Returns an array of NSStrings holding the names of the references, nil otherwise +// (and the `error` parameter will be set to the actual error that occurred). - (NSArray *)referenceNamesWithError:(NSError **)error; // Enumerate over all references is the repository. From 126b39434523087a490541ba77c3b6571c75123c Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 13:36:12 +0100 Subject: [PATCH 43/61] Reorganize GTBranch. --- Classes/GTBranch.h | 34 +++++++------ Classes/GTBranch.m | 124 +++++++++++++++++++++++++-------------------- 2 files changed, 86 insertions(+), 72 deletions(-) diff --git a/Classes/GTBranch.h b/Classes/GTBranch.h index 7addf9399..d16eb7fbe 100644 --- a/Classes/GTBranch.h +++ b/Classes/GTBranch.h @@ -36,13 +36,14 @@ typedef enum { @interface GTBranch : NSObject +@property (nonatomic, readonly, strong) GTRepository *repository; +@property (nonatomic, readonly, strong) GTReference *reference; @property (nonatomic, readonly) NSString *name; @property (nonatomic, readonly) NSString *shortName; -@property (nonatomic, readonly) NSString *SHA; @property (nonatomic, readonly) NSString *remoteName; +@property (nonatomic, readonly) NSString *SHA; @property (nonatomic, readonly) GTBranchType branchType; -@property (nonatomic, readonly, strong) GTRepository *repository; -@property (nonatomic, readonly, strong) GTReference *reference; +@property (nonatomic) GTBranch *upstreamBranch; + (NSString *)localNamePrefix; + (NSString *)remoteNamePrefix; @@ -61,22 +62,9 @@ typedef enum { // returns a GTCommit object or nil if an error occurred - (GTCommit *)targetCommitAndReturnError:(NSError **)error; -// Count all commits in this branch -// -// error(out) - will be filled if an error occurs -// -// returns number of commits in the branch or NSNotFound if an error occurred -- (NSUInteger)numberOfCommitsWithError:(NSError **)error; - -- (NSArray *)uniqueCommitsRelativeToBranch:(GTBranch *)otherBranch error:(NSError **)error; - // Deletes the local branch and nils out the reference. - (BOOL)deleteWithError:(NSError **)error; -// If the receiver is a local branch, looks up and returns its tracking branch. -// If the receiver is a remote branch, returns self. If no tracking branch was -// found, returns nil and sets `success` to YES. -- (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success; // Reloads the branch's reference and creates a new branch based off that newly // loaded reference. @@ -88,6 +76,20 @@ typedef enum { // Returns the reloaded branch, or nil if an error occurred. - (GTBranch *)reloadedBranchWithError:(NSError **)error; +// If the receiver is a local branch, looks up and returns its tracking branch. +// If the receiver is a remote branch, returns self. If no tracking branch was +// found, returns nil and sets `success` to YES. +- (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success; + +// Count all commits in this branch +// +// error(out) - will be filled if an error occurs +// +// returns number of commits in the branch or NSNotFound if an error occurred +- (NSUInteger)numberOfCommitsWithError:(NSError **)error; + +- (NSArray *)uniqueCommitsRelativeToBranch:(GTBranch *)otherBranch error:(NSError **)error; + // Calculate the ahead/behind count from this branch to the given branch. // // ahead - The number of commits which are unique to the receiver. Cannot be diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index 7d57c3db6..5c869918a 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -32,23 +32,8 @@ @implementation GTBranch -- (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p> name: %@, shortName: %@, sha: %@, remoteName: %@, repository: %@", NSStringFromClass([self class]), self, self.name, self.shortName, self.SHA, self.remoteName, self.repository]; -} - -- (BOOL)isEqual:(GTBranch *)otherBranch { - if (otherBranch == self) return YES; - if (![otherBranch isKindOfClass:self.class]) return NO; - - return [self.name isEqual:otherBranch.name] && [self.SHA isEqual:otherBranch.SHA]; -} - -- (NSUInteger)hash { - return self.name.hash ^ self.SHA.hash; -} - - -#pragma mark API +#pragma mark - +#pragma mark Class methods + (NSString *)localNamePrefix { return @"refs/heads/"; @@ -58,6 +43,9 @@ + (NSString *)remoteNamePrefix { return @"refs/remotes/"; } +#pragma mark - +#pragma mark Lifecycle + + (id)branchWithName:(NSString *)branchName repository:(GTRepository *)repo error:(NSError **)error { return [[self alloc] initWithName:branchName repository:repo error:error]; } @@ -89,6 +77,27 @@ - (id)initWithReference:(GTReference *)ref repository:(GTRepository *)repo { return self; } +#pragma mark - +#pragma mark NSObject + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p> name: %@, shortName: %@, sha: %@, remoteName: %@, repository: %@", NSStringFromClass([self class]), self, self.name, self.shortName, self.SHA, self.remoteName, self.repository]; +} + +- (BOOL)isEqual:(GTBranch *)otherBranch { + if (otherBranch == self) return YES; + if (![otherBranch isKindOfClass:self.class]) return NO; + + return [self.name isEqual:otherBranch.name] && [self.SHA isEqual:otherBranch.SHA]; +} + +- (NSUInteger)hash { + return self.name.hash ^ self.SHA.hash; +} + +#pragma mark - +#pragma mark Properties + - (NSString *)name { return self.reference.name; } @@ -109,10 +118,6 @@ - (NSString *)shortName { return @(name); } -- (NSString *)SHA { - return self.reference.targetSHA; -} - - (NSString *)remoteName { if (self.branchType == GTBranchTypeLocal) return nil; @@ -127,21 +132,8 @@ - (NSString *)remoteName { return [[NSString alloc] initWithBytes:name length:end - name encoding:NSUTF8StringEncoding]; } -- (GTCommit *)targetCommitAndReturnError:(NSError **)error { - if (self.SHA == nil) { - if (error != NULL) *error = GTReference.invalidReferenceError; - return nil; - } - - return [self.repository lookupObjectBySHA:self.SHA objectType:GTObjectTypeCommit error:error]; -} - -- (NSUInteger)numberOfCommitsWithError:(NSError **)error { - GTEnumerator *enumerator = [[GTEnumerator alloc] initWithRepository:self.repository error:error]; - if (enumerator == nil) return NSNotFound; - - if (![enumerator pushSHA:self.SHA error:error]) return NSNotFound; - return [enumerator countRemainingObjects:error]; +- (NSString *)SHA { + return self.reference.targetSHA; } - (GTBranchType)branchType { @@ -152,24 +144,16 @@ - (GTBranchType)branchType { } } -- (NSArray *)uniqueCommitsRelativeToBranch:(GTBranch *)otherBranch error:(NSError **)error { - NSParameterAssert(otherBranch != nil); - - GTCommit *mergeBase = [self.repository mergeBaseBetweenFirstOID:self.reference.OID secondOID:otherBranch.reference.OID error:error]; - if (mergeBase == nil) return nil; - - GTEnumerator *enumerator = [[GTEnumerator alloc] initWithRepository:self.repository error:error]; - if (enumerator == nil) return nil; - - [enumerator resetWithOptions:GTEnumeratorOptionsTimeSort]; - - BOOL success = [enumerator pushSHA:self.SHA error:error]; - if (!success) return nil; +#pragma mark - +#pragma mark API - success = [enumerator hideSHA:mergeBase.SHA error:error]; - if (!success) return nil; +- (GTCommit *)targetCommitAndReturnError:(NSError **)error { + if (self.SHA == nil) { + if (error != NULL) *error = GTReference.invalidReferenceError; + return nil; + } - return [enumerator allObjectsWithError:error]; + return [self.repository lookupObjectBySHA:self.SHA objectType:GTObjectTypeCommit error:error]; } - (BOOL)deleteWithError:(NSError **)error { @@ -182,6 +166,13 @@ - (BOOL)deleteWithError:(NSError **)error { return YES; } +- (GTBranch *)reloadedBranchWithError:(NSError **)error { + GTReference *reloadedRef = [self.reference reloadedReferenceWithError:error]; + if (reloadedRef == nil) return nil; + + return [[self.class alloc] initWithReference:reloadedRef repository:self.repository]; +} + - (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success { if (self.branchType == GTBranchTypeRemote) { if (success != NULL) *success = YES; @@ -214,11 +205,32 @@ - (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success return [[self class] branchWithReference:[[GTReference alloc] initWithGitReference:trackingRef repository:self.repository] repository:self.repository]; } -- (GTBranch *)reloadedBranchWithError:(NSError **)error { - GTReference *reloadedRef = [self.reference reloadedReferenceWithError:error]; - if (reloadedRef == nil) return nil; +- (NSUInteger)numberOfCommitsWithError:(NSError **)error { + GTEnumerator *enumerator = [[GTEnumerator alloc] initWithRepository:self.repository error:error]; + if (enumerator == nil) return NSNotFound; - return [[self.class alloc] initWithReference:reloadedRef repository:self.repository]; + if (![enumerator pushSHA:self.SHA error:error]) return NSNotFound; + return [enumerator countRemainingObjects:error]; +} + +- (NSArray *)uniqueCommitsRelativeToBranch:(GTBranch *)otherBranch error:(NSError **)error { + NSParameterAssert(otherBranch != nil); + + GTCommit *mergeBase = [self.repository mergeBaseBetweenFirstOID:self.reference.OID secondOID:otherBranch.reference.OID error:error]; + if (mergeBase == nil) return nil; + + GTEnumerator *enumerator = [[GTEnumerator alloc] initWithRepository:self.repository error:error]; + if (enumerator == nil) return nil; + + [enumerator resetWithOptions:GTEnumeratorOptionsTimeSort]; + + BOOL success = [enumerator pushSHA:self.SHA error:error]; + if (!success) return nil; + + success = [enumerator hideSHA:mergeBase.SHA error:error]; + if (!success) return nil; + + return [enumerator allObjectsWithError:error]; } - (BOOL)calculateAhead:(size_t *)ahead behind:(size_t *)behind relativeTo:(GTBranch *)branch error:(NSError **)error { From 361e671a3b71c9690b95bcfc7d2c18c48722a760 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 19:13:05 +0100 Subject: [PATCH 44/61] Gotta love documentation. --- Classes/GTBranch.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Classes/GTBranch.h b/Classes/GTBranch.h index d16eb7fbe..2383a89fb 100644 --- a/Classes/GTBranch.h +++ b/Classes/GTBranch.h @@ -57,9 +57,9 @@ typedef enum { // Get the target commit for this branch // -// error(out) - will be filled if an error occurs +// error - A pointer which will point to a valid error if the target can't be found. // -// returns a GTCommit object or nil if an error occurred +// Returns a GTCommit object or nil if an error occurred. - (GTCommit *)targetCommitAndReturnError:(NSError **)error; // Deletes the local branch and nils out the reference. @@ -83,11 +83,20 @@ typedef enum { // Count all commits in this branch // -// error(out) - will be filled if an error occurs +// error - will be filled if an error occurs // -// returns number of commits in the branch or NSNotFound if an error occurred +// Returns the number of commits in the receiver or `NSNotFound` if an error occurred - (NSUInteger)numberOfCommitsWithError:(NSError **)error; +// Get the unique commits between branches. +// +// This method returns an array representing the unique commits +// that exist between the receiver and `otherBranch`. +// +// otherBranch - The branch to compare against. +// error - Will be set if an error occurs. +// +// Returns an array of GTCommits, or nil if an error occurred. - (NSArray *)uniqueCommitsRelativeToBranch:(GTBranch *)otherBranch error:(NSError **)error; // Calculate the ahead/behind count from this branch to the given branch. From 0cdd6bedd423e4eda30944e5c1d7c050212cc091 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sat, 9 Nov 2013 11:44:29 +0100 Subject: [PATCH 45/61] Add new branch initializers based on the libgit2 functions. --- Classes/GTBranch.h | 24 ++++++++++++++++++++++- Classes/GTBranch.m | 29 ++++++++++++++++++++++++++++ ObjectiveGitTests/GTBranchSpec.m | 2 +- ObjectiveGitTests/GTRepositorySpec.m | 4 ++-- 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/Classes/GTBranch.h b/Classes/GTBranch.h index 2383a89fb..942eca4aa 100644 --- a/Classes/GTBranch.h +++ b/Classes/GTBranch.h @@ -48,13 +48,35 @@ typedef enum { + (NSString *)localNamePrefix; + (NSString *)remoteNamePrefix; +// Lookup a branch by name. +// +// name - The branch name to lookup. +// repository - The repository to lookup the branch in. +// error - A pointer which will point to a valid error if the lookup fails. +// +// Returns the branch object with that name, or nil if an error occurred. ++ (instancetype)branchByLookingUpBranchNamed:(NSString *)name inRepository:(GTRepository *)repository error:(NSError **)error; + +// Create a branch from a name and target. +// +// name - The name of the branch to create. +// commit - The commit the branch should point to. +// force - If set to YES, a branch with same name would be deleted. +// repository - The repository to create the branch in. +// error - A pointer which will point to a valid error if the creation fails. +// +// Returns a newly created branch object, or nil if the branch couldn't be created. ++ (instancetype)branchByCreatingBranchNamed:(NSString *)name target:(GTCommit *)commit force:(BOOL)force inRepository:(GTRepository *)repository error:(NSError **)error; + // Convenience initializers - (id)initWithName:(NSString *)branchName repository:(GTRepository *)repo error:(NSError **)error; + (id)branchWithName:(NSString *)branchName repository:(GTRepository *)repo error:(NSError **)error; -- (id)initWithReference:(GTReference *)ref repository:(GTRepository *)repo; + (id)branchWithReference:(GTReference *)ref repository:(GTRepository *)repo; +// Designated initializer +- (id)initWithReference:(GTReference *)ref repository:(GTRepository *)repo; + // Get the target commit for this branch // // error - A pointer which will point to a valid error if the target can't be found. diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index 5c869918a..33456fb0a 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -46,6 +46,34 @@ + (NSString *)remoteNamePrefix { #pragma mark - #pragma mark Lifecycle ++ (instancetype)branchByCreatingBranchNamed:(NSString *)name target:(GTCommit *)commit force:(BOOL)force inRepository:(GTRepository *)repository error:(NSError **)error { + git_reference *git_ref; + int gitError = git_branch_create(&git_ref, repository.git_repository, name.UTF8String, commit.git_commit, (force ? 1 : 0)); + if (gitError != GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Branch creation failed"]; + return nil; + } + + GTReference *ref = [[GTReference alloc] initWithGitReference:git_ref repository:repository]; + return [[self alloc] initWithReference:ref repository:repository]; +} + ++ (instancetype)branchByLookingUpBranchNamed:(NSString *)name inRepository:(GTRepository *)repository error:(NSError **)error { + git_reference *git_ref; + // First try local branches + int gitError = git_branch_lookup(&git_ref, repository.git_repository, name.UTF8String, GIT_BRANCH_LOCAL); + if (gitError != GIT_OK) { + int gitError = git_branch_lookup(&git_ref, repository.git_repository, name.UTF8String, GIT_BRANCH_REMOTE); + if (gitError != GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Branch lookup failed"]; + return nil; + } + } + + GTReference *ref = [[GTReference alloc] initWithGitReference:git_ref repository:repository]; + return [[self alloc] initWithReference:ref repository:repository]; +} + + (id)branchWithName:(NSString *)branchName repository:(GTRepository *)repo error:(NSError **)error { return [[self alloc] initWithName:branchName repository:repo error:error]; } @@ -64,6 +92,7 @@ - (id)initWithName:(NSString *)branchName repository:(GTRepository *)repo error: return [self initWithReference:ref repository:repo]; } +// Designated initializer - (id)initWithReference:(GTReference *)ref repository:(GTRepository *)repo { NSParameterAssert(ref != nil); NSParameterAssert(repo != nil); diff --git a/ObjectiveGitTests/GTBranchSpec.m b/ObjectiveGitTests/GTBranchSpec.m index e1ff7c0ac..b06a04f14 100644 --- a/ObjectiveGitTests/GTBranchSpec.m +++ b/ObjectiveGitTests/GTBranchSpec.m @@ -139,7 +139,7 @@ describe(@"-trackingBranchWithError:success:", ^{ it(@"should return the tracking branch for a local branch that tracks a remote branch", ^{ NSError *error = nil; - GTBranch *masterBranch = [GTBranch branchWithName:@"refs/heads/master" repository:repository error:&error]; + GTBranch *masterBranch = [GTBranch branchByLookingUpBranchNamed:@"master" inRepository:repository error:&error]; expect(masterBranch).notTo.beNil(); expect(error).to.beNil(); diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 4d1ddee5a..8b6d58c81 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -186,11 +186,11 @@ describe(@"-mergeBaseBetweenFirstOID:secondOID:error:", ^{ it(@"should find the merge base between two branches", ^{ NSError *error = nil; - GTBranch *masterBranch = [[GTBranch alloc] initWithName:@"refs/heads/master" repository:repository error:&error]; + GTBranch *masterBranch = [GTBranch branchByLookingUpBranchNamed:@"master" inRepository:repository error:&error]; expect(masterBranch).notTo.beNil(); expect(error).to.beNil(); - GTBranch *otherBranch = [[GTBranch alloc] initWithName:@"refs/heads/other-branch" repository:repository error:&error]; + GTBranch *otherBranch = [GTBranch branchByLookingUpBranchNamed:@"other-branch" inRepository:repository error:&error]; expect(otherBranch).notTo.beNil(); expect(error).to.beNil(); From f211658f934a10aecffcfcb2cfada33df90398e4 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 16:20:51 +0100 Subject: [PATCH 46/61] Use the reference's repository instead of asking for one. --- Classes/GTBranch.h | 8 +++----- Classes/GTBranch.m | 34 +++++++++++++++----------------- Classes/GTRepository.m | 10 +++++----- ObjectiveGitTests/GTBranchSpec.m | 4 ++-- 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/Classes/GTBranch.h b/Classes/GTBranch.h index 942eca4aa..be75c9311 100644 --- a/Classes/GTBranch.h +++ b/Classes/GTBranch.h @@ -69,13 +69,11 @@ typedef enum { + (instancetype)branchByCreatingBranchNamed:(NSString *)name target:(GTCommit *)commit force:(BOOL)force inRepository:(GTRepository *)repository error:(NSError **)error; // Convenience initializers -- (id)initWithName:(NSString *)branchName repository:(GTRepository *)repo error:(NSError **)error; -+ (id)branchWithName:(NSString *)branchName repository:(GTRepository *)repo error:(NSError **)error; - -+ (id)branchWithReference:(GTReference *)ref repository:(GTRepository *)repo; ++ (id)branchWithReferenceNamed:(NSString *)referenceName inRepository:(GTRepository *)repo error:(NSError **)error; ++ (id)branchWithReference:(GTReference *)ref; // Designated initializer -- (id)initWithReference:(GTReference *)ref repository:(GTRepository *)repo; +- (id)initWithReference:(GTReference *)ref; // Get the target commit for this branch // diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index 33456fb0a..44ef9f9f5 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -55,7 +55,7 @@ + (instancetype)branchByCreatingBranchNamed:(NSString *)name target:(GTCommit *) } GTReference *ref = [[GTReference alloc] initWithGitReference:git_ref repository:repository]; - return [[self alloc] initWithReference:ref repository:repository]; + return [[self alloc] initWithReference:ref]; } + (instancetype)branchByLookingUpBranchNamed:(NSString *)name inRepository:(GTRepository *)repository error:(NSError **)error { @@ -71,36 +71,30 @@ + (instancetype)branchByLookingUpBranchNamed:(NSString *)name inRepository:(GTRe } GTReference *ref = [[GTReference alloc] initWithGitReference:git_ref repository:repository]; - return [[self alloc] initWithReference:ref repository:repository]; + return [[self alloc] initWithReference:ref]; } -+ (id)branchWithName:(NSString *)branchName repository:(GTRepository *)repo error:(NSError **)error { - return [[self alloc] initWithName:branchName repository:repo error:error]; -} - -+ (id)branchWithReference:(GTReference *)ref repository:(GTRepository *)repo { - return [[self alloc] initWithReference:ref repository:repo]; -} - -- (id)initWithName:(NSString *)branchName repository:(GTRepository *)repo error:(NSError **)error { - NSParameterAssert(branchName != nil); ++ (id)branchWithReferenceNamed:(NSString *)referenceName inRepository:(GTRepository *)repo error:(NSError **)error { + NSParameterAssert(referenceName != nil); NSParameterAssert(repo != nil); GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:branchName inRepository:repo error:error]; if (ref == nil) return nil; - return [self initWithReference:ref repository:repo]; + return [[self alloc] initWithReference:ref]; +} + ++ (id)branchWithReference:(GTReference *)ref { + return [[self alloc] initWithReference:ref]; } // Designated initializer -- (id)initWithReference:(GTReference *)ref repository:(GTRepository *)repo { +- (id)initWithReference:(GTReference *)ref { NSParameterAssert(ref != nil); - NSParameterAssert(repo != nil); self = [super init]; if (self == nil) return nil; - _repository = repo; _reference = ref; return self; @@ -161,6 +155,10 @@ - (NSString *)remoteName { return [[NSString alloc] initWithBytes:name length:end - name encoding:NSUTF8StringEncoding]; } +- (GTRepository *)repository { + return self.reference.repository; +} + - (NSString *)SHA { return self.reference.targetSHA; } @@ -199,7 +197,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]; } - (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success { @@ -231,7 +229,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]]; } - (NSUInteger)numberOfCommitsWithError:(NSError **)error { diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index 38ddd9475..d2634923c 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -320,9 +320,9 @@ - (NSArray *)branchesWithPrefix:(NSString *)prefix error:(NSError **)error { if (references == nil) return nil; NSMutableArray *branches = [NSMutableArray array]; - for (NSString *ref in references) { - if ([ref hasPrefix:prefix]) { - GTBranch *b = [GTBranch branchWithName:ref repository:self error:error]; + for (NSString *refName in references) { + if ([refName hasPrefix:prefix]) { + GTBranch *b = [GTBranch branchWithReferenceNamed:refName inRepository:self error:error]; if (b != nil) [branches addObject:b]; } } @@ -408,7 +408,7 @@ - (GTBranch *)createBranchNamed:(NSString *)name fromReference:(GTReference *)re GTReference *newRef = [GTReference referenceByCreatingReferenceNamed:[NSString stringWithFormat:@"%@%@", [GTBranch localNamePrefix], name] fromReferenceTarget:[ref.resolvedTarget SHA] inRepository:self error:error]; if (newRef == nil) return nil; - return [GTBranch branchWithReference:newRef repository:self]; + return [GTBranch branchWithReference:newRef]; } - (BOOL)isEmpty { @@ -419,7 +419,7 @@ - (GTBranch *)currentBranchWithError:(NSError **)error { GTReference *head = [self headReferenceWithError:error]; if (head == nil) return nil; - return [GTBranch branchWithReference:head repository:self]; + return [GTBranch branchWithReference:head]; } - (NSArray *)localCommitsRelativeToRemoteBranch:(GTBranch *)remoteBranch error:(NSError **)error { diff --git a/ObjectiveGitTests/GTBranchSpec.m b/ObjectiveGitTests/GTBranchSpec.m index b06a04f14..ae8b38c32 100644 --- a/ObjectiveGitTests/GTBranchSpec.m +++ b/ObjectiveGitTests/GTBranchSpec.m @@ -156,7 +156,7 @@ expect(otherRef).notTo.beNil(); expect(error).to.beNil(); - GTBranch *otherBranch = [GTBranch branchWithReference:otherRef repository:repository]; + GTBranch *otherBranch = [GTBranch branchWithReference:otherRef]; expect(otherBranch).notTo.beNil(); BOOL success = NO; @@ -172,7 +172,7 @@ expect(remoteRef).notTo.beNil(); expect(error).to.beNil(); - GTBranch *remoteBranch = [GTBranch branchWithReference:remoteRef repository:repository]; + GTBranch *remoteBranch = [GTBranch branchWithReference:remoteRef]; expect(remoteBranch).notTo.beNil(); BOOL success = NO; From b00b007f7e1cc73a2e97c2164880e0599ba6f0ce Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 16:37:10 +0100 Subject: [PATCH 47/61] Use the libgit2 enum for those. --- Classes/GTBranch.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/GTBranch.h b/Classes/GTBranch.h index be75c9311..7f68a29b6 100644 --- a/Classes/GTBranch.h +++ b/Classes/GTBranch.h @@ -30,8 +30,8 @@ @class GTRepository; typedef enum { - GTBranchTypeLocal = 1, - GTBranchTypeRemote + GTBranchTypeLocal = GIT_BRANCH_LOCAL, + GTBranchTypeRemote = GIT_BRANCH_REMOTE, } GTBranchType; @interface GTBranch : NSObject From 04a4b82c531f5b0a87059f10c50b399c0e7491c8 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 16:39:34 +0100 Subject: [PATCH 48/61] Cut down the number of initialization methods on GTReference. --- Classes/GTBranch.m | 2 +- Classes/GTReference.h | 7 +---- Classes/GTReference.m | 44 ++++++++++------------------ ObjectiveGitTests/GTBranchSpec.m | 2 +- ObjectiveGitTests/GTReferenceSpec.m | 16 ++++++---- ObjectiveGitTests/GTRepositorySpec.m | 2 +- 6 files changed, 30 insertions(+), 43 deletions(-) diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index 44ef9f9f5..72ce93a05 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -78,7 +78,7 @@ + (id)branchWithReferenceNamed:(NSString *)referenceName inRepository:(GTReposit NSParameterAssert(referenceName != nil); NSParameterAssert(repo != nil); - GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:branchName inRepository:repo error:error]; + GTReference *ref = [GTReference referenceByLookingUpReferenceNamed:referenceName inRepository:repo error:error]; if (ref == nil) return nil; return [[self alloc] initWithReference:ref]; diff --git a/Classes/GTReference.h b/Classes/GTReference.h index 715681775..34749f2f2 100644 --- a/Classes/GTReference.h +++ b/Classes/GTReference.h @@ -55,14 +55,9 @@ typedef enum { @property (nonatomic, readonly, strong) GTReflog *reflog; // Convenience initializers -+ (id)referenceByLookingUpReferencedNamed:(NSString *)refName inRepository:(GTRepository *)theRepo error:(NSError **)error; -- (id)initByLookingUpReferenceNamed:(NSString *)refName inRepository:(GTRepository *)theRepo error:(NSError **)error; - ++ (id)referenceByLookingUpReferenceNamed:(NSString *)refName inRepository:(GTRepository *)theRepo error:(NSError **)error; + (id)referenceByCreatingReferenceNamed:(NSString *)refName fromReferenceTarget:(NSString *)target inRepository:(GTRepository *)theRepo error:(NSError **)error; -- (id)initByCreatingReferenceNamed:(NSString *)refName fromReferenceTarget:(NSString *)target inRepository:(GTRepository *)theRepo error:(NSError **)error; - + (id)referenceByResolvingSymbolicReference:(GTReference *)symbolicRef error:(NSError **)error; -- (id)initByResolvingSymbolicReference:(GTReference *)symbolicRef error:(NSError **)error; - (id)initWithGitReference:(git_reference *)ref repository:(GTRepository *)repository; diff --git a/Classes/GTReference.m b/Classes/GTReference.m index e09b905b1..31eea1306 100644 --- a/Classes/GTReference.m +++ b/Classes/GTReference.m @@ -65,44 +65,32 @@ - (BOOL)isRemote { return git_reference_is_remote(self.git_reference) != 0; } -+ (id)referenceByLookingUpReferencedNamed:(NSString *)refName inRepository:(GTRepository *)theRepo error:(NSError **)error { - return [[self alloc] initByLookingUpReferenceNamed:refName inRepository:theRepo error:error]; -} - -+ (id)referenceByCreatingReferenceNamed:(NSString *)refName fromReferenceTarget:(NSString *)target inRepository:(GTRepository *)theRepo error:(NSError **)error { - return [[self alloc] initByCreatingReferenceNamed:refName fromReferenceTarget:target inRepository:theRepo error:error]; -} - -+ (id)referenceByResolvingSymbolicReference:(GTReference *)symbolicRef error:(NSError **)error { - return [[self alloc] initByResolvingSymbolicReference:symbolicRef error:error]; -} - -- (id)initByLookingUpReferenceNamed:(NSString *)refName inRepository:(GTRepository *)repo error:(NSError **)error { - NSParameterAssert(refName != nil); - NSParameterAssert(repo != nil); ++ (id)referenceByLookingUpReferenceNamed:(NSString *)referenceName inRepository:(GTRepository *)repository error:(NSError **)error { + NSParameterAssert(referenceName != nil); + NSParameterAssert(repository != nil); git_reference *ref = NULL; - int gitError = git_reference_lookup(&ref, repo.git_repository, refName.UTF8String); + int gitError = git_reference_lookup(&ref, repository.git_repository, referenceName.UTF8String); if (gitError != GIT_OK) { - if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to lookup reference %@.", refName]; + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Reference lookup failed" failureReason:@"The reference named \"%@\" couldn't be resolved in \"%@\"", referenceName, repository.gitDirectoryURL.path]; return nil; } - return [self initWithGitReference:ref repository:repo]; + return [[self alloc] initWithGitReference:ref repository:repository]; } -- (id)initByCreatingReferenceNamed:(NSString *)refName fromReferenceTarget:(NSString *)target inRepository:(GTRepository *)repo error:(NSError **)error { - NSParameterAssert(refName != nil); ++ (id)referenceByCreatingReferenceNamed:(NSString *)referenceName fromReferenceTarget:(NSString *)target inRepository:(GTRepository *)repository error:(NSError **)error { + NSParameterAssert(referenceName != nil); NSParameterAssert(target != nil); - NSParameterAssert(repo != nil); + NSParameterAssert(repository != nil); GTOID *oid = [GTOID oidWithSHA:target]; int gitError = GIT_OK; git_reference *ref; if (oid != nil) { - gitError = git_reference_create(&ref, repo.git_repository, refName.UTF8String, oid.git_oid, 0); + gitError = git_reference_create(&ref, repository.git_repository, referenceName.UTF8String, oid.git_oid, 0); } else { - gitError = git_reference_symbolic_create(&ref, repo.git_repository, refName.UTF8String, target.UTF8String, 0); + gitError = git_reference_symbolic_create(&ref, repository.git_repository, referenceName.UTF8String, target.UTF8String, 0); } if (gitError != GIT_OK) { @@ -110,10 +98,10 @@ - (id)initByCreatingReferenceNamed:(NSString *)refName fromReferenceTarget:(NSSt return nil; } - return [self initWithGitReference:ref repository:repo]; + return [[self alloc] initWithGitReference:ref repository:repository]; } -- (id)initByResolvingSymbolicReference:(GTReference *)symbolicRef error:(NSError **)error { ++ (id)referenceByResolvingSymbolicReference:(GTReference *)symbolicRef error:(NSError **)error { NSParameterAssert(symbolicRef != nil); git_reference *ref = NULL; @@ -123,7 +111,7 @@ - (id)initByResolvingSymbolicReference:(GTReference *)symbolicRef error:(NSError return nil; } - return [self initWithGitReference:ref repository:symbolicRef.repository]; + return [[self alloc] initWithGitReference:ref repository:symbolicRef.repository]; } - (id)initWithGitReference:(git_reference *)ref repository:(GTRepository *)repo { @@ -173,7 +161,7 @@ - (id)unresolvedTarget { NSString *refName = @(git_reference_symbolic_target(self.git_reference)); if (refName == NULL) return nil; - return [self.class referenceByLookingUpReferencedNamed:refName inRepository:self.repository error:NULL]; + return [self.class referenceByLookingUpReferenceNamed:refName inRepository:self.repository error:NULL]; } return nil; } @@ -242,7 +230,7 @@ - (GTOID *)OID { } - (GTReference *)reloadedReferenceWithError:(NSError **)error { - return [[self.class alloc] initByLookingUpReferenceNamed:self.name inRepository:self.repository error:error]; + return [self.class referenceByLookingUpReferenceNamed:self.name inRepository:self.repository error:error]; } + (NSError *)invalidReferenceError { diff --git a/ObjectiveGitTests/GTBranchSpec.m b/ObjectiveGitTests/GTBranchSpec.m index ae8b38c32..13a3f1258 100644 --- a/ObjectiveGitTests/GTBranchSpec.m +++ b/ObjectiveGitTests/GTBranchSpec.m @@ -168,7 +168,7 @@ it(@"should return itself for a remote branch", ^{ NSError *error = nil; - GTReference *remoteRef = [GTReference referenceByLookingUpReferencedNamed:@"refs/remotes/origin/master" inRepository:repository error:&error]; + GTReference *remoteRef = [GTReference referenceByLookingUpReferenceNamed:@"refs/remotes/origin/master" inRepository:repository error:&error]; expect(remoteRef).notTo.beNil(); expect(error).to.beNil(); diff --git a/ObjectiveGitTests/GTReferenceSpec.m b/ObjectiveGitTests/GTReferenceSpec.m index dac0588b0..759de5280 100644 --- a/ObjectiveGitTests/GTReferenceSpec.m +++ b/ObjectiveGitTests/GTReferenceSpec.m @@ -16,17 +16,21 @@ }); it(@"should compare equal to the same reference", ^{ - expect([[GTReference alloc] initByLookingUpReferenceNamed:@"refs/heads/master" inRepository:repository error:NULL]).to.equal([[GTReference alloc] initByLookingUpReferenceNamed:@"refs/heads/master" inRepository:repository error:NULL]); + GTReference *firstRef = [GTReference referenceByLookingUpReferenceNamed:@"refs/heads/master" inRepository:repository error:NULL]; + GTReference *secondRef = [GTReference referenceByLookingUpReferenceNamed:@"refs/heads/master" inRepository:repository error:NULL]; + expect(firstRef).to.equal(secondRef); }); it(@"should compare unequal to a different reference", ^{ - expect([[GTReference alloc] initByLookingUpReferenceNamed:@"refs/heads/master" inRepository:repository error:NULL]).notTo.equal([[GTReference alloc] initByLookingUpReferenceNamed:@"refs/remotes/origin/master" inRepository:repository error:NULL]); + GTReference *masterRef = [GTReference referenceByLookingUpReferenceNamed:@"refs/heads/master" inRepository:repository error:NULL]; + GTReference *originMasterRef = [GTReference referenceByLookingUpReferenceNamed:@"refs/remotes/origin/master" inRepository:repository error:NULL]; + expect(masterRef).notTo.equal(originMasterRef); }); describe(@"remote property", ^{ it(@"should be YES for a remote-tracking branch", ^{ NSError *error = nil; - GTReference *ref = [[GTReference alloc] initByLookingUpReferenceNamed:@"refs/remotes/origin/master" inRepository:repository error:&error]; + GTReference *ref = [GTReference referenceByLookingUpReferenceNamed:@"refs/remotes/origin/master" inRepository:repository error:&error]; expect(ref).notTo.beNil(); expect(error).to.beNil(); @@ -36,7 +40,7 @@ it(@"should be NO for a local branch", ^{ NSError *error = nil; - GTReference *ref = [[GTReference alloc] initByLookingUpReferenceNamed:@"refs/heads/master" inRepository:repository error:&error]; + GTReference *ref = [GTReference referenceByLookingUpReferenceNamed:@"refs/heads/master" inRepository:repository error:&error]; expect(ref).notTo.beNil(); expect(error).to.beNil(); @@ -123,7 +127,7 @@ describe(@"+referenceByLookingUpReferenceNamed:inRepository:error:", ^{ it(@"should return a valid reference to a branch", ^{ NSError *error = nil; - GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:@"refs/heads/master" inRepository:bareRepository error:&error]; + GTReference *ref = [GTReference referenceByLookingUpReferenceNamed:@"refs/heads/master" inRepository:bareRepository error:&error]; expect(ref).notTo.beNil(); expect(error).to.beNil(); @@ -132,7 +136,7 @@ it(@"should return a valid reference to a tag", ^{ NSError *error = nil; - GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:@"refs/tags/v0.9" inRepository:bareRepository error:&error]; + GTReference *ref = [GTReference referenceByLookingUpReferenceNamed:@"refs/tags/v0.9" inRepository:bareRepository error:&error]; expect(ref).notTo.beNil(); expect(error).to.beNil(); diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 8b6d58c81..61c1fe16e 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -290,7 +290,7 @@ describe(@"-checkout:strategy:error:progressBlock:", ^{ it(@"should allow references", ^{ NSError *error = nil; - GTReference *ref = [GTReference referenceByLookingUpReferencedNamed:@"refs/heads/other-branch" inRepository:repository error:&error]; + GTReference *ref = [GTReference referenceByLookingUpReferenceNamed:@"refs/heads/other-branch" inRepository:repository error:&error]; expect(ref).to.beTruthy(); expect(error.localizedDescription).to.beNil(); BOOL result = [repository checkoutReference:ref strategy:GTCheckoutStrategyAllowConflicts error:&error progressBlock:nil]; From bb261eeb0115a7f3ea13a4bf91debd5297f95b6f Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 16:42:16 +0100 Subject: [PATCH 49/61] Use libgit2 function to get the branch name. --- Classes/GTBranch.m | 6 +++++- ObjectiveGitTests/GTBranchSpec.m | 10 ++++++++++ ObjectiveGitTests/GTRepositorySpec.m | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index 72ce93a05..19e7c2d81 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -122,7 +122,11 @@ - (NSUInteger)hash { #pragma mark Properties - (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 { diff --git a/ObjectiveGitTests/GTBranchSpec.m b/ObjectiveGitTests/GTBranchSpec.m index 13a3f1258..8f7ab0e7b 100644 --- a/ObjectiveGitTests/GTBranchSpec.m +++ b/ObjectiveGitTests/GTBranchSpec.m @@ -30,6 +30,16 @@ expect(error).to.beNil(); }); +describe(@"name", ^{ + it(@"should use just the branch name for a local branch", ^{ + expect(masterBranch.name).to.equal(@"master"); + }); + + it(@"should include the remote name for a tracking branch", ^{ + expect(trackingBranch.name).to.equal(@"origin/master"); + }); +}); + describe(@"shortName", ^{ it(@"should use just the branch name for a local branch", ^{ expect(masterBranch.shortName).to.equal(@"master"); diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 61c1fe16e..63507fb32 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -215,7 +215,7 @@ GTBranch *currentBranch = [repository currentBranchWithError:&error]; expect(currentBranch).notTo.beNil(); expect(error).to.beNil(); - expect(currentBranch.name).to.equal(@"refs/heads/master"); + expect(currentBranch.reference.name).to.equal(@"refs/heads/master"); }); }); @@ -237,7 +237,7 @@ expect(error).to.beNil(); expect(branches.count).to.equal(1); GTBranch *remoteBranch = branches[0]; - expect(remoteBranch.name).to.equal(@"refs/remotes/origin/master"); + expect(remoteBranch.reference.name).to.equal(@"refs/remotes/origin/master"); }); }); From b5616525ceb5ed3fc5c16d0270dec2376ae76202 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 16:51:16 +0100 Subject: [PATCH 50/61] Use libgit2 function to get remote name. --- Classes/GTBranch.m | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index 19e7c2d81..c46e36a24 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -146,17 +146,14 @@ - (NSString *)shortName { } - (NSString *)remoteName { - if (self.branchType == GTBranchTypeLocal) return nil; + int nameLength = git_branch_remote_name(NULL, 0, self.repository.git_repository, self.reference.name.UTF8String); + if (nameLength <= GIT_OK) return nil; - const char *name; - int gitError = git_branch_name(&name, self.reference.git_reference); - 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; + char *nameChar = malloc(nameLength); + int gitError = git_branch_remote_name(nameChar, nameLength, self.repository.git_repository, self.reference.name.UTF8String); + if (gitError <= GIT_OK) return nil; - return [[NSString alloc] initWithBytes:name length:end - name encoding:NSUTF8StringEncoding]; + return @(nameChar); } - (GTRepository *)repository { From 9c50e6921e1908252ba9d060225117d75a9c2249 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 16:51:38 +0100 Subject: [PATCH 51/61] Some more API for GTBranch. --- Classes/GTBranch.h | 5 ++++- Classes/GTBranch.m | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Classes/GTBranch.h b/Classes/GTBranch.h index 7f68a29b6..493b29d56 100644 --- a/Classes/GTBranch.h +++ b/Classes/GTBranch.h @@ -43,7 +43,8 @@ typedef enum { @property (nonatomic, readonly) NSString *remoteName; @property (nonatomic, readonly) NSString *SHA; @property (nonatomic, readonly) GTBranchType branchType; -@property (nonatomic) GTBranch *upstreamBranch; +@property (nonatomic, assign) GTBranch *trackingBranch; +@property (nonatomic, readonly, getter=isHead) BOOL head; + (NSString *)localNamePrefix; + (NSString *)remoteNamePrefix; @@ -85,6 +86,8 @@ typedef enum { // Deletes the local branch and nils out the reference. - (BOOL)deleteWithError:(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; // Reloads the branch's reference and creates a new branch based off that newly // loaded reference. diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index c46e36a24..e85de44d1 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -172,6 +172,23 @@ - (GTBranchType)branchType { } } +- (GTBranch *)upstreamBranch { + git_reference *git_ref; + int gitError = git_branch_upstream(&git_ref, self.reference.git_reference); + if (gitError != GIT_OK) return nil; + + GTReference *ref = [[GTReference alloc] initWithGitReference:git_ref repository:self.repository]; + return [GTBranch branchWithReference:ref]; +} + +- (void)setUpstreamBranch:(GTBranch *)branch { + git_branch_set_upstream(self.reference.git_reference, (branch ? branch.name.UTF8String : NULL)); +} + +- (BOOL)isHead { + return (git_branch_is_head(self.reference.git_reference) ? YES : NO); +} + #pragma mark - #pragma mark API @@ -194,6 +211,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 ? 0 : 1)); + 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 *)reloadedBranchWithError:(NSError **)error { GTReference *reloadedRef = [self.reference reloadedReferenceWithError:error]; if (reloadedRef == nil) return nil; From 2db69381b764a2ca9f7bd2e38fbf4db9347b53df Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 17:23:40 +0100 Subject: [PATCH 52/61] Add a way to restrict branch lookups by type. --- Classes/GTBranch.h | 11 +++++++++-- Classes/GTBranch.m | 23 ++++++++++++++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/Classes/GTBranch.h b/Classes/GTBranch.h index 493b29d56..02f93985f 100644 --- a/Classes/GTBranch.h +++ b/Classes/GTBranch.h @@ -32,6 +32,7 @@ typedef enum { GTBranchTypeLocal = GIT_BRANCH_LOCAL, GTBranchTypeRemote = GIT_BRANCH_REMOTE, + GTBranchTypeAny = GIT_BRANCH_REMOTE|GIT_BRANCH_LOCAL, } GTBranchType; @interface GTBranch : NSObject @@ -49,14 +50,20 @@ typedef enum { + (NSString *)localNamePrefix; + (NSString *)remoteNamePrefix; -// Lookup a branch by name. +// Lookup a branch by name. Performs a `GTBranchTypeAny` lookup. +// See `+branchByLookingUpBranchNamed:type:inRepository:error:`. ++ (instancetype)branchByLookingUpBranchNamed:(NSString *)name inRepository:(GTRepository *)repository error:(NSError **)error; + +// Lookup a branch by name and branch type. // // name - The branch name to lookup. +// type - The type of lookup to perform. If `GTBranchTypeAny` is passed, +// local branches are checked first. // repository - The repository to lookup the branch in. // error - A pointer which will point to a valid error if the lookup fails. // // Returns the branch object with that name, or nil if an error occurred. -+ (instancetype)branchByLookingUpBranchNamed:(NSString *)name inRepository:(GTRepository *)repository error:(NSError **)error; ++ (instancetype)branchByLookingUpBranchNamed:(NSString *)name type:(GTBranchType)type inRepository:(GTRepository *)repository error:(NSError **)error; // Create a branch from a name and target. // diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index e85de44d1..f22b42196 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -59,13 +59,26 @@ + (instancetype)branchByCreatingBranchNamed:(NSString *)name target:(GTCommit *) } + (instancetype)branchByLookingUpBranchNamed:(NSString *)name inRepository:(GTRepository *)repository error:(NSError **)error { - git_reference *git_ref; - // First try local branches - int gitError = git_branch_lookup(&git_ref, repository.git_repository, name.UTF8String, GIT_BRANCH_LOCAL); - if (gitError != GIT_OK) { + return [self branchByLookingUpBranchNamed:name type:GTBranchTypeAny inRepository:repository error:error]; +} + ++ (instancetype)branchByLookingUpBranchNamed:(NSString *)name type:(GTBranchType)type inRepository:(GTRepository *)repository error:(NSError **)error { + git_reference *git_ref = NULL; + + // If any is requested, we'll perform the local lookup first. + int gitError = GIT_ENOTFOUND; // Must be != GIT_OK for "any" lookups + if ((type & GTBranchTypeLocal)) { + gitError = git_branch_lookup(&git_ref, repository.git_repository, name.UTF8String, GIT_BRANCH_LOCAL); + if (gitError != GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Local branch lookup failed"]; + if (type == GTBranchTypeLocal) return nil; // Local-only lookup failed, bail with nil. + if (error != NULL) *error = nil; // We're doing 'any' lookup, so drop the error. + } + } + if ((gitError != GIT_OK) && (type & ~GTBranchTypeLocal)) { int gitError = git_branch_lookup(&git_ref, repository.git_repository, name.UTF8String, GIT_BRANCH_REMOTE); if (gitError != GIT_OK) { - if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Branch lookup failed"]; + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Remote branch lookup failed"]; return nil; } } From a17178f00725df5bb40674cb7cd2f1fc4dd02707 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 18:20:38 +0100 Subject: [PATCH 53/61] Remove `success` parameter from `-trackingBranchWithError:success`. --- Classes/GTBranch.h | 14 +++++++++++--- Classes/GTBranch.m | 10 +++------- ObjectiveGitTests/GTBranchSpec.m | 16 ++++------------ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/Classes/GTBranch.h b/Classes/GTBranch.h index 02f93985f..9e5224fff 100644 --- a/Classes/GTBranch.h +++ b/Classes/GTBranch.h @@ -106,10 +106,18 @@ typedef enum { // Returns the reloaded branch, or nil if an error occurred. - (GTBranch *)reloadedBranchWithError:(NSError **)error; +// Fetch the branch's remote tracking branch. +// // If the receiver is a local branch, looks up and returns its tracking branch. -// If the receiver is a remote branch, returns self. If no tracking branch was -// found, returns nil and sets `success` to YES. -- (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success; +// If the receiver is a remote branch, returns self. +// If no tracking branch was found, returns nil with a nil error. +// +// error - The error if one occurred. +// +// Returns the tracking branch for the reciever if it's a local branch, +// nil if the receiver is a remote branch but without an error set, +// or nil if there was an error (and the error pointer will be set. +- (GTBranch *)trackingBranchWithError:(NSError **)error; // Count all commits in this branch // diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index f22b42196..ea046ee6e 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -244,9 +244,9 @@ - (GTBranch *)reloadedBranchWithError:(NSError **)error { return [[self.class alloc] initWithReference:reloadedRef]; } -- (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success { +- (GTBranch *)trackingBranchWithError:(NSError **)error { if (self.branchType == GTBranchTypeRemote) { - if (success != NULL) *success = YES; + if (error != NULL) *error = nil; return self; } @@ -255,24 +255,20 @@ - (GTBranch *)trackingBranchWithError:(NSError **)error success:(BOOL *)success // GIT_ENOTFOUND means no tracking branch found. if (gitError == GIT_ENOTFOUND) { - if (success != NULL) *success = YES; + if (error != NULL) *error = nil; return nil; } if (gitError != GIT_OK) { - if (success != NULL) *success = NO; if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to create reference to tracking branch from %@", self]; return nil; } if (trackingRef == NULL) { - if (success != NULL) *success = NO; if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Got a NULL remote ref for %@", self]; return nil; } - if (success != NULL) *success = YES; - return [[self class] branchWithReference:[[GTReference alloc] initWithGitReference:trackingRef repository:self.repository]]; } diff --git a/ObjectiveGitTests/GTBranchSpec.m b/ObjectiveGitTests/GTBranchSpec.m index 8f7ab0e7b..a804f1872 100644 --- a/ObjectiveGitTests/GTBranchSpec.m +++ b/ObjectiveGitTests/GTBranchSpec.m @@ -23,10 +23,8 @@ expect(masterBranch).notTo.beNil(); expect(error).to.beNil(); - BOOL success = NO; - trackingBranch = [masterBranch trackingBranchWithError:&error success:&success]; + trackingBranch = [masterBranch trackingBranchWithError:&error]; expect(trackingBranch).notTo.equal(masterBranch); - expect(success).to.beTruthy(); expect(error).to.beNil(); }); @@ -153,10 +151,8 @@ expect(masterBranch).notTo.beNil(); expect(error).to.beNil(); - BOOL success = NO; - GTBranch *trackingBranch = [masterBranch trackingBranchWithError:&error success:&success]; + GTBranch *trackingBranch = [masterBranch trackingBranchWithError:&error]; expect(trackingBranch).notTo.beNil(); - expect(success).to.beTruthy(); expect(error).to.beNil(); }); @@ -169,10 +165,8 @@ GTBranch *otherBranch = [GTBranch branchWithReference:otherRef]; expect(otherBranch).notTo.beNil(); - BOOL success = NO; - trackingBranch = [otherBranch trackingBranchWithError:&error success:&success]; + trackingBranch = [otherBranch trackingBranchWithError:&error]; expect(trackingBranch).to.beNil(); - expect(success).to.beTruthy(); expect(error).to.beNil(); }); @@ -185,10 +179,8 @@ GTBranch *remoteBranch = [GTBranch branchWithReference:remoteRef]; expect(remoteBranch).notTo.beNil(); - BOOL success = NO; - GTBranch *remoteTrackingBranch = [remoteBranch trackingBranchWithError:&error success:&success]; + GTBranch *remoteTrackingBranch = [remoteBranch trackingBranchWithError:&error]; expect(remoteTrackingBranch).to.equal(remoteBranch); - expect(success).to.beTruthy(); expect(error).to.beNil(); }); }); From 865c48aca709ba4b5d94ade289d0e19df29d9a68 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 21:54:12 +0100 Subject: [PATCH 54/61] Tests. --- ObjectiveGitTests/GTBranchSpec.m | 159 ++++++++++++++++++++++++++----- 1 file changed, 133 insertions(+), 26 deletions(-) diff --git a/ObjectiveGitTests/GTBranchSpec.m b/ObjectiveGitTests/GTBranchSpec.m index a804f1872..a64370152 100644 --- a/ObjectiveGitTests/GTBranchSpec.m +++ b/ObjectiveGitTests/GTBranchSpec.m @@ -28,43 +28,150 @@ expect(error).to.beNil(); }); -describe(@"name", ^{ - it(@"should use just the branch name for a local branch", ^{ - expect(masterBranch.name).to.equal(@"master"); +describe(@"branch initialization", ^{ + describe(@"+branchByLookingUpBranchNamed:type:inRepository:error:", ^{ + it(@"works for local branches", ^{ + NSError *error = nil; + GTBranch *branch = [GTBranch branchByLookingUpBranchNamed:@"master" type:GTBranchTypeLocal inRepository:repository error:&error]; + expect(branch).notTo.beNil(); + expect(error).to.beNil(); + expect(branch.branchType).to.equal(GTBranchTypeLocal); + }); + + it(@"works for remote branches", ^{ + NSError *error = nil; + GTBranch *branch = [GTBranch branchByLookingUpBranchNamed:@"origin/master" type:GTBranchTypeRemote inRepository:repository error:&error]; + expect(branch).notTo.beNil(); + expect(error).to.beNil(); + expect(branch.branchType).to.equal(GTBranchTypeRemote); + }); + + it(@"fails for non-existing branches", ^{ + NSError *error = nil; + GTBranch *branch = [GTBranch branchByLookingUpBranchNamed:@"plonk" type:GTBranchTypeRemote inRepository:repository error:&error]; + expect(branch).to.beNil(); + expect(error.domain).to.equal(GTGitErrorDomain); + expect(error.code).to.equal(GIT_ENOTFOUND); + }); + + it(@"finds local branches before remote ones in an 'any' lookup", ^{ + NSError *error = nil; + GTReference *ref = [GTReference referenceByCreatingReferenceNamed:@"refs/heads/origin/master" fromReferenceTarget:@"refs/heads/master" inRepository:repository error:NULL]; + expect(ref).notTo.beNil(); + + GTBranch *duplicateBranch = [GTBranch branchWithReference:ref]; + expect(duplicateBranch).notTo.beNil(); + expect(duplicateBranch.branchType).to.equal(GTBranchTypeLocal); + + GTBranch *remoteBranch = [GTBranch branchByLookingUpBranchNamed:@"origin/master" type:GTBranchTypeRemote inRepository:repository error:NULL]; + expect(remoteBranch).notTo.beNil(); + expect(remoteBranch.branchType).to.equal(GTBranchTypeRemote); + + GTBranch *branch = [GTBranch branchByLookingUpBranchNamed:@"origin/master" type:GTBranchTypeAny inRepository:repository error:&error]; + expect(branch).notTo.beNil(); + expect(error).to.beNil(); + expect(branch.branchType).to.equal(GTBranchTypeLocal); + expect(branch).to.equal(duplicateBranch); + }); + + it(@"find remote branches if there's no ambiguity in an 'any' lookup", ^{ + NSError *error = nil; + + GTBranch *branch = [GTBranch branchByLookingUpBranchNamed:@"origin/master" type:GTBranchTypeAny inRepository:repository error:&error]; + expect(branch).notTo.beNil(); + expect(error).to.beNil(); + expect(branch.branchType).to.equal(GTBranchTypeRemote); + }); }); - it(@"should include the remote name for a tracking branch", ^{ - expect(trackingBranch.name).to.equal(@"origin/master"); - }); -}); - -describe(@"shortName", ^{ - it(@"should use just the branch name for a local branch", ^{ - expect(masterBranch.shortName).to.equal(@"master"); + describe(@"+branchByCreatingBranchNamed:target:force:inRepository:error:", ^{ + it(@"works with a non-conflicting name", ^{ + NSError *error = nil; + GTCommit *targetCommit = [masterBranch targetCommitAndReturnError:NULL]; + GTBranch *branch = [GTBranch branchByCreatingBranchNamed:@"my-branch" target:targetCommit force:NO inRepository:repository error:&error]; + expect(branch).notTo.beNil(); + expect(error).to.beNil(); + expect(branch.branchType).to.equal(GTBranchTypeLocal); + }); + + it(@"fails with an already existing name", ^{ + NSError *error = nil; + GTCommit *targetCommit = [masterBranch targetCommitAndReturnError:NULL]; + GTBranch *branch = [GTBranch branchByCreatingBranchNamed:@"1-and_more" target:targetCommit force:NO inRepository:repository error:&error]; + expect(branch).to.beNil(); + expect(error.domain).to.equal(GTGitErrorDomain); + expect(error.code).to.equal(GIT_EEXISTS); + }); + + it(@"delete the offending branch if creation is forced", ^{ + NSError *error = nil; + GTCommit *targetCommit = [masterBranch targetCommitAndReturnError:NULL]; + GTBranch *branch = [GTBranch branchByCreatingBranchNamed:@"1-and_more" target:targetCommit force:YES inRepository:repository error:&error]; + expect(branch).notTo.beNil(); + expect(error).to.beNil(); + }); }); - it(@"should not include the remote name for a tracking branch", ^{ - expect(trackingBranch.shortName).to.equal(@"master"); + describe(@"+branchWithReferenceNamed:inRepository:error:", ^{ + it(@"works for existing local references", ^{ + NSError *error = nil; + GTBranch *branch = [GTBranch branchWithReferenceNamed:@"refs/heads/1-and_more" inRepository:repository error:&error]; + expect(branch).notTo.beNil(); + expect(error).to.beNil(); + }); + + it(@"works for existing remote references", ^{ + NSError *error = nil; + GTBranch *branch = [GTBranch branchWithReferenceNamed:@"refs/remotes/origin/master" inRepository:repository error:&error]; + expect(branch).notTo.beNil(); + expect(error).to.beNil(); + }); + + it(@"fails for non existent references", ^{ + NSError *error = nil; + GTBranch *branch = [GTBranch branchWithReferenceNamed:@"refs/heads/nowhere" inRepository:repository error:&error]; + expect(branch).to.beNil(); + expect(error.domain).to.equal(GTGitErrorDomain); + expect(error.code).to.equal(GIT_ENOTFOUND); + }); }); }); -describe(@"remoteName", ^{ - it(@"should return nil for a local branch", ^{ - expect(masterBranch.remoteName).to.beNil(); - }); +describe(@"basic properties", ^{ + describe(@"local branches", ^{ + it(@"should be GTBranchTypeLocal for a local branch", ^{ + expect(masterBranch.branchType).to.equal(GTBranchTypeLocal); + }); - it(@"should return the remote name for a tracking branch", ^{ - expect(trackingBranch.remoteName).to.equal(@"origin"); - }); -}); + it(@"should use just the branch name in their name", ^{ + expect(masterBranch.name).to.equal(@"master"); + }); + + it(@"should use just the branch name in their short name", ^{ + expect(masterBranch.shortName).to.equal(@"master"); + }); -describe(@"branchType", ^{ - it(@"should be GTBranchTypeLocal for a local branch", ^{ - expect(masterBranch.branchType).to.equal(GTBranchTypeLocal); + it(@"should return nil for their remote name", ^{ + expect(masterBranch.remoteName).to.beNil(); + }); }); - it(@"should be GTBranchTypeRemote for a tracking branch", ^{ - expect(trackingBranch.branchType).to.equal(GTBranchTypeRemote); + describe(@"remote branches", ^{ + it(@"should have a GTBranchTypeLocal branch type", ^{ + expect(trackingBranch.branchType).to.equal(GTBranchTypeRemote); + }); + + it(@"should include the remote name in their name", ^{ + expect(trackingBranch.name).to.equal(@"origin/master"); + }); + + it(@"should not include the remote name in their short name", ^{ + expect(trackingBranch.shortName).to.equal(@"master"); + }); + + it(@"should return the remote name for their remote name", ^{ + expect(trackingBranch.remoteName).to.equal(@"origin"); + }); }); }); From 15735d37e86912b84db40a1cec39f06c1bbcc5ba Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 7 Nov 2013 23:43:25 +0100 Subject: [PATCH 55/61] Move the object lookup methods in `GTObject`. You use the concrete subclass to restrict the object type you're expecting. Good bye, `GTObjectType` ;-). --- Classes/GTBranch.m | 2 +- Classes/GTEnumerator.m | 4 +- Classes/GTIndex.m | 6 +-- Classes/GTObject+Private.h | 13 +++++ Classes/GTObject.h | 19 ++++++++ Classes/GTObject.m | 39 +++++++++++++++ Classes/GTReference.m | 4 +- Classes/GTRepository+Committing.m | 4 +- Classes/GTRepository+Private.h | 14 ------ Classes/GTRepository+Stashing.m | 6 +-- Classes/GTRepository.h | 6 --- Classes/GTRepository.m | 47 ++----------------- .../project.pbxproj | 16 +++---- ObjectiveGitTests/GTBlobSpec.m | 2 +- ObjectiveGitTests/GTCommitSpec.m | 4 +- ObjectiveGitTests/GTDiffSpec.m | 8 ++-- ObjectiveGitTests/GTObjectTest.m | 12 ++--- ObjectiveGitTests/GTRepositorySpec.m | 12 ++--- ObjectiveGitTests/GTSubmoduleSpec.m | 2 +- ObjectiveGitTests/GTTagSpec.m | 2 +- ObjectiveGitTests/GTTreeBuilderSpec.m | 8 ++-- ObjectiveGitTests/GTTreeSpec.m | 2 +- 22 files changed, 122 insertions(+), 110 deletions(-) create mode 100644 Classes/GTObject+Private.h delete mode 100644 Classes/GTRepository+Private.h diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index 7d57c3db6..bf5d6a4b2 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -133,7 +133,7 @@ - (GTCommit *)targetCommitAndReturnError:(NSError **)error { return nil; } - return [self.repository lookupObjectBySHA:self.SHA objectType:GTObjectTypeCommit error:error]; + return [GTCommit lookupWithSHA:self.SHA inRepository:self.repository error:error]; } - (NSUInteger)numberOfCommitsWithError:(NSError **)error { diff --git a/Classes/GTEnumerator.m b/Classes/GTEnumerator.m index da54395a0..af72708cc 100644 --- a/Classes/GTEnumerator.m +++ b/Classes/GTEnumerator.m @@ -32,7 +32,7 @@ #import "NSError+Git.h" #import "NSString+Git.h" #import "GTRepository.h" -#import "GTRepository+Private.h" +#import "GTObject+Private.h" #import "GTOID.h" @interface GTEnumerator () @@ -147,7 +147,7 @@ - (GTCommit *)nextObjectWithSuccess:(BOOL *)success error:(NSError **)error { } // Ignore error if we can't lookup object and just return nil. - GTCommit *commit = [self.repository lookupObjectByGitOid:&oid objectType:GTObjectTypeCommit error:error]; + GTCommit *commit = [GTCommit lookupWithGitOID:&oid inRepository:self.repository error:error]; if (success != NULL) *success = (commit != nil); return commit; } diff --git a/Classes/GTIndex.m b/Classes/GTIndex.m index f5d946fda..f74d2e0ea 100644 --- a/Classes/GTIndex.m +++ b/Classes/GTIndex.m @@ -31,7 +31,7 @@ #import "GTIndexEntry.h" #import "NSError+Git.h" #import "GTRepository.h" -#import "GTRepository+Private.h" +#import "GTObject+Private.h" #import "GTOID.h" #import "GTTree.h" @@ -164,10 +164,10 @@ - (GTTree *)writeTree:(NSError **)error { int status = git_index_write_tree(&oid, self.git_index); if (status != GIT_OK) { if (error != NULL) *error = [NSError git_errorFor:status description:@"Failed to write index."]; - return NULL; + return nil; } - return [self.repository lookupObjectByGitOid:&oid objectType:GTObjectTypeTree error:NULL]; + return [GTTree lookupWithGitOID:&oid inRepository:self.repository error:error]; } - (NSArray *)entries { diff --git a/Classes/GTObject+Private.h b/Classes/GTObject+Private.h new file mode 100644 index 000000000..b0406b9cb --- /dev/null +++ b/Classes/GTObject+Private.h @@ -0,0 +1,13 @@ +// +// GTObject+Private.h +// ObjectiveGitFramework +// +// Created by Etienne on 15/07/13. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import + +@interface GTObject () ++ (instancetype)lookupWithGitOID:(const git_oid *)git_oid inRepository:(GTRepository *)repository error:(NSError **)error; +@end diff --git a/Classes/GTObject.h b/Classes/GTObject.h index fc6ec0b39..4ceb939f4 100644 --- a/Classes/GTObject.h +++ b/Classes/GTObject.h @@ -54,6 +54,25 @@ typedef enum { @property (nonatomic, readonly, strong) GTRepository *repository; @property (nonatomic, readonly) GTOID *OID; +// Lookup an object in a repository. +// +// This method will automatically restrict the requested object type depending on +// the class of the receiver. +// For example, if you expect the OID to point to a commit, call it on `GTCommit`. +// Performing the lookup on `GTObject` will give you back an object of the class +// corresponding to the actual object type. +// +// OID - The OID of the object to lookup. +// repository - The repository to perform the lookup in. +// error - Will be set if an error occurs. +// +// Returns the object corresponding to the OID, or nil if an error occurred. ++ (instancetype)lookupWithOID:(GTOID *)OID inRepository:(GTRepository *)repository error:(NSError **)error; + +// Convenience method to lookup an object given its SHA. +// See +lookupObjectWithOID:inRepository:error: ++ (instancetype)lookupWithSHA:(NSString *)SHA inRepository:(GTRepository *)repository error:(NSError **)error; + // Convenience initializers - (id)initWithObj:(git_object *)theObject inRepository:(GTRepository *)theRepo; + (id)objectWithObj:(git_object *)theObject inRepository:(GTRepository *)theRepo; diff --git a/Classes/GTObject.m b/Classes/GTObject.m index e16ac1ff0..6a9e14ae7 100644 --- a/Classes/GTObject.m +++ b/Classes/GTObject.m @@ -44,6 +44,45 @@ @interface GTObject () @implementation GTObject ++ (git_otype)_lookupType { + git_otype type = GIT_OBJ_BAD; + if (self == [GTObject class]) { + type = GIT_OBJ_ANY; + } else if (self == [GTCommit class]) { + type = GIT_OBJ_COMMIT; + } else if (self == [GTTree class]) { + type = GIT_OBJ_TREE; + } else if (self == [GTBlob class]) { + type = GIT_OBJ_BLOB; + } else if (self == [GTTag class]) { + type = GIT_OBJ_TAG; + } + return type; +} + ++ (instancetype)lookupWithGitOID:(const git_oid *)git_oid inRepository:(GTRepository *)repository error:(NSError **)error { + NSParameterAssert(git_oid != nil); + NSParameterAssert(repository != nil); + + git_object *obj; + int gitError = git_object_lookup(&obj, repository.git_repository, git_oid, self._lookupType); + if (gitError != GIT_OK) { + if (error) *error = [NSError git_errorFor:gitError description:@"Object lookup failed"]; + return nil; + } + + return [self objectWithObj:obj inRepository:repository]; + +} + ++ (instancetype)lookupWithOID:(GTOID *)OID inRepository:(GTRepository *)repository error:(NSError **)error { + return [self lookupWithGitOID:OID.git_oid inRepository:repository error:error]; +} + ++ (instancetype)lookupWithSHA:(NSString *)SHA inRepository:(GTRepository *)repository error:(NSError **)error { + return [self lookupWithOID:[GTOID oidWithSHA:SHA] inRepository:repository error:error]; +} + - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p> type: %@, shortSha: %@, sha: %@", NSStringFromClass([self class]), self, self.type, self.shortSHA, self.SHA]; } diff --git a/Classes/GTReference.m b/Classes/GTReference.m index e09b905b1..2ba0e3108 100644 --- a/Classes/GTReference.m +++ b/Classes/GTReference.m @@ -27,7 +27,7 @@ #import "GTOID.h" #import "GTReflog+Private.h" #import "GTRepository.h" -#import "GTRepository+Private.h" +#import "GTObject+Private.h" #import "NSError+Git.h" #import "NSString+Git.h" @@ -168,7 +168,7 @@ - (id)unresolvedTarget { const git_oid *oid = git_reference_target(self.git_reference); if (oid == NULL) return nil; - return [self.repository lookupObjectByGitOid:oid error:NULL]; + return [GTObject lookupWithGitOID:oid inRepository:self.repository error:NULL]; } else if (self.referenceType == GTReferenceTypeSymbolic) { NSString *refName = @(git_reference_symbolic_target(self.git_reference)); if (refName == NULL) return nil; diff --git a/Classes/GTRepository+Committing.m b/Classes/GTRepository+Committing.m index 4ea745b7d..e2df95bd6 100644 --- a/Classes/GTRepository+Committing.m +++ b/Classes/GTRepository+Committing.m @@ -7,7 +7,7 @@ // #import "GTRepository+Committing.h" -#import "GTRepository+Private.h" +#import "GTObject+Private.h" @implementation GTRepository (Committing) @@ -43,7 +43,7 @@ - (GTCommit *)createCommitWithTree:(GTTree *)tree message:(NSString *)message au return nil; } - return [self lookupObjectByGitOid:&oid objectType:GTObjectTypeCommit error:error]; + return [GTCommit lookupWithGitOID:&oid inRepository:self error:error]; } @end diff --git a/Classes/GTRepository+Private.h b/Classes/GTRepository+Private.h deleted file mode 100644 index 43968ee95..000000000 --- a/Classes/GTRepository+Private.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// GTRepository+Private.h -// ObjectiveGitFramework -// -// Created by Etienne on 15/07/13. -// Copyright (c) 2013 GitHub, Inc. All rights reserved. -// - -#import - -@interface GTRepository () -- (id)lookupObjectByGitOid:(const git_oid *)oid objectType:(GTObjectType)type error:(NSError **)error; -- (id)lookupObjectByGitOid:(const git_oid *)oid error:(NSError **)error; -@end diff --git a/Classes/GTRepository+Stashing.m b/Classes/GTRepository+Stashing.m index a69f885f9..9c6f904b7 100644 --- a/Classes/GTRepository+Stashing.m +++ b/Classes/GTRepository+Stashing.m @@ -8,7 +8,7 @@ #import "GTRepository+Stashing.h" #import "GTOID.h" -#import "GTRepository+Private.h" +#import "GTObject+Private.h" #import "GTSignature.h" #import "NSError+Git.h" @@ -24,8 +24,8 @@ - (GTCommit *)stashChangesWithMessage:(NSString *)message flags:(GTRepositorySta if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to stash."]; return nil; } - - return [self lookupObjectByGitOid:&git_oid error:error]; + + return [GTCommit lookupWithGitOID:&git_oid inRepository:self error:error]; } static int stashEnumerationCallback(size_t index, const char *message, const git_oid *stash_id, void *payload) { diff --git a/Classes/GTRepository.h b/Classes/GTRepository.h index 92abed5c1..e0d11f07a 100644 --- a/Classes/GTRepository.h +++ b/Classes/GTRepository.h @@ -169,12 +169,6 @@ extern NSString *const GTRepositoryCloneOptionsCredentialProvider; // returns nil (and fills the error parameter) if an error occurred, or a GTRepository object if successful. + (id)cloneFromURL:(NSURL *)originURL toWorkingDirectory:(NSURL *)workdirURL options:(NSDictionary *)options error:(NSError **)error transferProgressBlock:(void (^)(const git_transfer_progress *))transferProgressBlock checkoutProgressBlock:(void (^)(NSString *path, NSUInteger completedSteps, NSUInteger totalSteps))checkoutProgressBlock; -// Lookup objects in the repo by oid or sha1 -- (id)lookupObjectByOID:(GTOID *)oid objectType:(GTObjectType)type error:(NSError **)error; -- (id)lookupObjectByOID:(GTOID *)oid error:(NSError **)error; -- (id)lookupObjectBySHA:(NSString *)sha objectType:(GTObjectType)type error:(NSError **)error; -- (id)lookupObjectBySHA:(NSString *)sha error:(NSError **)error; - // Lookup an object in the repo using a revparse spec - (id)lookupObjectByRevspec:(NSString *)spec error:(NSError **)error; diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index 38ddd9475..c6c1f2bf9 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -237,45 +237,6 @@ + (id)cloneFromURL:(NSURL *)originURL toWorkingDirectory:(NSURL *)workdirURL opt return [[self alloc] initWithGitRepository:repository]; } -- (id)lookupObjectByGitOid:(const git_oid *)oid objectType:(GTObjectType)type error:(NSError **)error { - git_object *obj; - - int gitError = git_object_lookup(&obj, self.git_repository, oid, (git_otype)type); - if (gitError < GIT_OK) { - if (error != NULL) { - char oid_str[GIT_OID_HEXSZ+1]; - git_oid_tostr(oid_str, sizeof(oid_str), oid); - *error = [NSError git_errorFor:gitError description:@"Failed to lookup object %s in repository.", oid_str]; - } - return nil; - } - - return [GTObject objectWithObj:obj inRepository:self]; -} - -- (id)lookupObjectByGitOid:(const git_oid *)oid error:(NSError **)error { - return [self lookupObjectByGitOid:oid objectType:GTObjectTypeAny error:error]; -} - -- (id)lookupObjectByOID:(GTOID *)oid objectType:(GTObjectType)type error:(NSError **)error { - return [self lookupObjectByGitOid:oid.git_oid objectType:type error:error]; -} - -- (id)lookupObjectByOID:(GTOID *)oid error:(NSError **)error { - return [self lookupObjectByOID:oid objectType:GTObjectTypeAny error:error]; -} - -- (id)lookupObjectBySHA:(NSString *)sha objectType:(GTObjectType)type error:(NSError **)error { - GTOID *oid = [[GTOID alloc] initWithSHA:sha error:error]; - if (!oid) return nil; - - return [self lookupObjectByOID:oid objectType:type error:error]; -} - -- (id)lookupObjectBySHA:(NSString *)sha error:(NSError **)error { - return [self lookupObjectBySHA:sha objectType:GTObjectTypeAny error:error]; -} - - (id)lookupObjectByRevspec:(NSString *)spec error:(NSError **)error { git_object *obj; int gitError = git_revparse_single(&obj, self.git_repository, spec.UTF8String); @@ -361,7 +322,7 @@ - (NSArray *)allBranchesWithError:(NSError **)error { static int GTRepositoryForeachTagCallback(const char *name, git_oid *oid, void *payload) { struct GTRepositoryTagEnumerationInfo *info = payload; - GTTag *tag = (GTTag *)[info->myself lookupObjectByGitOid:oid objectType:GTObjectTypeTag error:NULL]; + GTTag *tag = [GTTag lookupWithOID:[GTOID oidWithGitOid:oid] inRepository:info->myself error:NULL]; BOOL stop = NO; info->block(tag, &stop); @@ -541,8 +502,8 @@ - (GTCommit *)mergeBaseBetweenFirstOID:(GTOID *)firstOID secondOID:(GTOID *)seco if (error != NULL) *error = [NSError git_errorFor:errorCode description:@"Failed to find merge base between commits %@ and %@.", firstOID.SHA, secondOID.SHA]; return nil; } - - return [self lookupObjectByGitOid:&mergeBase objectType:GTObjectTypeCommit error:error]; + + return [GTCommit lookupWithOID:[GTOID oidWithGitOid:&mergeBase] inRepository:self error:error]; } - (GTObjectDatabase *)objectDatabaseWithError:(NSError **)error { @@ -674,7 +635,7 @@ - (GTOID *)OIDByCreatingTagNamed:(NSString *)tagName target:(GTObject *)theTarge - (GTTag *)createTagNamed:(NSString *)tagName target:(GTObject *)theTarget tagger:(GTSignature *)theTagger message:(NSString *)theMessage error:(NSError **)error { GTOID *oid = [self OIDByCreatingTagNamed:tagName target:theTarget tagger:theTagger message:theMessage error:error]; - return oid ? [self lookupObjectByOID:oid objectType:GTObjectTypeTag error:error] : nil; + return (oid ? [GTTag lookupWithOID:oid inRepository:self error:error] : nil); } #pragma mark Checkout diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index a0a2b90a7..4160952b3 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -144,8 +144,8 @@ 4D79C0EE17DF9F4D00997DE4 /* GTCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D79C0EC17DF9F4D00997DE4 /* GTCredential.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4D79C0EF17DF9F4D00997DE4 /* GTCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79C0ED17DF9F4D00997DE4 /* GTCredential.m */; }; 4D79C0F717DFAA7100997DE4 /* GTCredential+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D79C0F617DFAA7100997DE4 /* GTCredential+Private.h */; }; - 4DE864351794A37E00371A65 /* GTRepository+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE864341794A37E00371A65 /* GTRepository+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4DE864361794A37E00371A65 /* GTRepository+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE864341794A37E00371A65 /* GTRepository+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4DE864351794A37E00371A65 /* GTObject+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE864341794A37E00371A65 /* GTObject+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4DE864361794A37E00371A65 /* GTObject+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE864341794A37E00371A65 /* GTObject+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 55C8054F13861FE7004DCB0F /* GTObjectDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C8054D13861F34004DCB0F /* GTObjectDatabase.m */; }; 55C8055013861FE7004DCB0F /* GTObjectDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C8054D13861F34004DCB0F /* GTObjectDatabase.m */; }; 55C8057A13875578004DCB0F /* NSString+Git.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C8057313874CDF004DCB0F /* NSString+Git.m */; }; @@ -299,7 +299,7 @@ F6CBB47617FFD50500404926 /* NSDate+GTTimeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B1E7EC1703522100D0814D /* NSDate+GTTimeAdditions.h */; }; F6CBB47717FFD50500404926 /* GTSubmodule.h in Headers */ = {isa = PBXBuildFile; fileRef = D09C2E341755F16200065E36 /* GTSubmodule.h */; settings = {ATTRIBUTES = (Public, ); }; }; F6CBB47817FFD50500404926 /* GTRepository+Stashing.h in Headers */ = {isa = PBXBuildFile; fileRef = D015F7C817F695E800AD5E1F /* GTRepository+Stashing.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F6CBB47917FFD50500404926 /* GTRepository+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE864341794A37E00371A65 /* GTRepository+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F6CBB47917FFD50500404926 /* GTObject+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DE864341794A37E00371A65 /* GTObject+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; F6CBB47B17FFD50500404926 /* ObjectiveGit.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F05AC51601209A00B7AD1D /* ObjectiveGit.m */; }; F6CBB47C17FFD50500404926 /* NSData+Git.m in Sources */ = {isa = PBXBuildFile; fileRef = BD6C2267131459E700992935 /* NSData+Git.m */; }; F6CBB47D17FFD50500404926 /* GTRemote.m in Sources */ = {isa = PBXBuildFile; fileRef = 883CD6AA1600EBC600F57354 /* GTRemote.m */; }; @@ -518,7 +518,7 @@ 4D79C0ED17DF9F4D00997DE4 /* GTCredential.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCredential.m; sourceTree = ""; }; 4D79C0F617DFAA7100997DE4 /* GTCredential+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTCredential+Private.h"; sourceTree = ""; }; 4D8DADBE181A7D9F001B1202 /* libgit2 */ = {isa = PBXFileReference; lastKnownFileType = folder; name = libgit2; path = External/libgit2; sourceTree = ""; }; - 4DE864341794A37E00371A65 /* GTRepository+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTRepository+Private.h"; sourceTree = ""; }; + 4DE864341794A37E00371A65 /* GTObject+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTObject+Private.h"; sourceTree = ""; }; 55C8054C13861F34004DCB0F /* GTObjectDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTObjectDatabase.h; sourceTree = ""; }; 55C8054D13861F34004DCB0F /* GTObjectDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTObjectDatabase.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 55C8057213874CDF004DCB0F /* NSString+Git.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Git.h"; sourceTree = ""; }; @@ -888,7 +888,7 @@ children = ( BDE4C05F130EFE2C00851650 /* Categories */, BDE4C062130EFE2C00851650 /* GTRepository.h */, - 4DE864341794A37E00371A65 /* GTRepository+Private.h */, + 4DE864341794A37E00371A65 /* GTObject+Private.h */, BDE4C063130EFE2C00851650 /* GTRepository.m */, 30DCBA6117B45A78009B0EBD /* GTRepository+Status.h */, 30DCBA6217B45A78009B0EBD /* GTRepository+Status.m */, @@ -1090,7 +1090,7 @@ 30B1E7EF1703522100D0814D /* NSDate+GTTimeAdditions.h in Headers */, D09C2E371755F16200065E36 /* GTSubmodule.h in Headers */, D015F7CB17F695E800AD5E1F /* GTRepository+Stashing.h in Headers */, - 4DE864361794A37E00371A65 /* GTRepository+Private.h in Headers */, + 4DE864361794A37E00371A65 /* GTObject+Private.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1139,7 +1139,7 @@ D09C2E361755F16200065E36 /* GTSubmodule.h in Headers */, 4D26799F178DAF31002A2795 /* GTTreeEntry+Private.h in Headers */, 306123B117EA5261006591D4 /* metamacros.h in Headers */, - 4DE864351794A37E00371A65 /* GTRepository+Private.h in Headers */, + 4DE864351794A37E00371A65 /* GTObject+Private.h in Headers */, 4D79C0EE17DF9F4D00997DE4 /* GTCredential.h in Headers */, 4D79C0F717DFAA7100997DE4 /* GTCredential+Private.h in Headers */, ); @@ -1183,7 +1183,7 @@ F6CBB47617FFD50500404926 /* NSDate+GTTimeAdditions.h in Headers */, F6CBB47717FFD50500404926 /* GTSubmodule.h in Headers */, F6CBB47817FFD50500404926 /* GTRepository+Stashing.h in Headers */, - F6CBB47917FFD50500404926 /* GTRepository+Private.h in Headers */, + F6CBB47917FFD50500404926 /* GTObject+Private.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ObjectiveGitTests/GTBlobSpec.m b/ObjectiveGitTests/GTBlobSpec.m index 93d8e9e8e..77dc0a1fa 100644 --- a/ObjectiveGitTests/GTBlobSpec.m +++ b/ObjectiveGitTests/GTBlobSpec.m @@ -18,7 +18,7 @@ beforeEach(^{ repository = self.bareFixtureRepository; blobSHA = @"fa49b077972391ad58037050f2a75f74e3671e92"; - blob = [repository lookupObjectBySHA:blobSHA objectType:GTObjectTypeBlob error:NULL]; + blob = [GTBlob lookupWithSHA:blobSHA inRepository:repository error:NULL]; expect(blob).notTo.beNil(); }); diff --git a/ObjectiveGitTests/GTCommitSpec.m b/ObjectiveGitTests/GTCommitSpec.m index b304f6066..a309a0d20 100644 --- a/ObjectiveGitTests/GTCommitSpec.m +++ b/ObjectiveGitTests/GTCommitSpec.m @@ -19,7 +19,7 @@ it(@"can read commit data", ^{ NSError *error = nil; NSString *commitSHA = @"8496071c1b46c854b31185ea97743be6a8774479"; - GTCommit *commit = [repository lookupObjectBySHA:commitSHA error:&error]; + GTCommit *commit = [GTCommit lookupWithSHA:commitSHA inRepository:repository error:&error]; expect(commit).notTo.beNil(); expect(error).to.beNil(); @@ -52,7 +52,7 @@ it(@"can have multiple parents", ^{ NSError *error = nil; NSString *commitSHA = @"a4a7dce85cf63874e984719f4fdd239f5145052f"; - GTCommit *commit = [repository lookupObjectBySHA:commitSHA error:&error]; + GTCommit *commit = [GTCommit lookupWithSHA:commitSHA inRepository:repository error:&error]; expect(commit).notTo.beNil(); expect(error).to.beNil(); diff --git a/ObjectiveGitTests/GTDiffSpec.m b/ObjectiveGitTests/GTDiffSpec.m index 899a748f2..3da289fdd 100644 --- a/ObjectiveGitTests/GTDiffSpec.m +++ b/ObjectiveGitTests/GTDiffSpec.m @@ -18,10 +18,10 @@ repository = self.testAppFixtureRepository; expect(repository).toNot.beNil(); - firstCommit = (GTCommit *)[repository lookupObjectBySHA:@"8e0e65988d3007867a9f59ca8639ba975ef97e69" objectType:GTObjectTypeCommit error:NULL]; + firstCommit = [GTCommit lookupWithSHA:@"8e0e65988d3007867a9f59ca8639ba975ef97e69" inRepository:repository error:NULL]; expect(firstCommit).toNot.beNil(); - secondCommit = (GTCommit *)[repository lookupObjectBySHA:@"a5840674db1a58cac0b2e7d046b627837a16f217" objectType:GTObjectTypeCommit error:NULL]; + secondCommit = [GTCommit lookupWithSHA:@"a5840674db1a58cac0b2e7d046b627837a16f217" inRepository:repository error:NULL]; expect(secondCommit).toNot.beNil(); }); @@ -70,9 +70,9 @@ expect(repository).toNot.beNil(); setupDiffFromCommitSHAsAndOptions = [^(NSString *firstCommitSHA, NSString *secondCommitSHA, NSDictionary *options) { - firstCommit = (GTCommit *)[repository lookupObjectBySHA:firstCommitSHA objectType:GTObjectTypeCommit error:NULL]; + firstCommit = [GTCommit lookupWithSHA:firstCommitSHA inRepository:repository error:NULL]; expect(firstCommit).toNot.beNil(); - secondCommit = (GTCommit *)[repository lookupObjectBySHA:secondCommitSHA objectType:GTObjectTypeCommit error:NULL]; + secondCommit = [GTCommit lookupWithSHA:secondCommitSHA inRepository:repository error:NULL]; expect(secondCommit).toNot.beNil(); diff = [GTDiff diffOldTree:firstCommit.tree withNewTree:secondCommit.tree inRepository:repository options:options error:NULL]; diff --git a/ObjectiveGitTests/GTObjectTest.m b/ObjectiveGitTests/GTObjectTest.m index ef1014e9f..09b5c0c74 100644 --- a/ObjectiveGitTests/GTObjectTest.m +++ b/ObjectiveGitTests/GTObjectTest.m @@ -42,7 +42,7 @@ - (void)setUp { - (void)testCanLookupEmptyStringFails { NSError *error = nil; - GTObject *obj = [repo lookupObjectBySHA:@"" error:&error]; + GTObject *obj = [GTObject lookupWithSHA:@"" inRepository:repo error:&error]; STAssertNotNil(error, nil); STAssertNil(obj, nil); @@ -52,7 +52,7 @@ - (void)testCanLookupEmptyStringFails { - (void)testCanLookupBadObjectFails { NSError *error = nil; - GTObject *obj = [repo lookupObjectBySHA:@"a496071c1b46c854b31185ea97743be6a8774479" error:&error]; + GTObject *obj = [GTObject lookupWithSHA:@"a496071c1b46c854b31185ea97743be6a8774479" inRepository:repo error:&error]; STAssertNotNil(error, nil); STAssertNil(obj, nil); @@ -62,7 +62,7 @@ - (void)testCanLookupBadObjectFails { - (void)testCanLookupAnObject { NSError *error = nil; - GTObject *obj = [repo lookupObjectBySHA:@"8496071c1b46c854b31185ea97743be6a8774479" error:&error]; + GTObject *obj = [GTObject lookupWithSHA:@"8496071c1b46c854b31185ea97743be6a8774479" inRepository:repo error:&error]; STAssertNil(error, [error localizedDescription]); STAssertNotNil(obj, nil); @@ -73,8 +73,8 @@ - (void)testCanLookupAnObject { - (void)testTwoObjectsAreTheSame { NSError *error = nil; - GTObject *obj1 = [repo lookupObjectBySHA:@"8496071c1b46c854b31185ea97743be6a8774479" error:&error]; - GTObject *obj2 = [repo lookupObjectBySHA:@"8496071c1b46c854b31185ea97743be6a8774479" error:&error]; + GTObject *obj1 = [GTObject lookupWithSHA:@"8496071c1b46c854b31185ea97743be6a8774479" inRepository:repo error:&error]; + GTObject *obj2 = [GTObject lookupWithSHA:@"8496071c1b46c854b31185ea97743be6a8774479" inRepository:repo error:&error]; STAssertNotNil(obj1, nil); STAssertNotNil(obj2, nil); @@ -84,7 +84,7 @@ - (void)testTwoObjectsAreTheSame { - (void)testCanReadRawDataFromObject { NSError *error = nil; - GTObject *obj = [repo lookupObjectBySHA:@"8496071c1b46c854b31185ea97743be6a8774479" error:&error]; + GTObject *obj = [GTObject lookupWithSHA:@"8496071c1b46c854b31185ea97743be6a8774479" inRepository:repo error:&error]; STAssertNotNil(obj, nil); diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 4d1ddee5a..cb93da243 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -259,12 +259,12 @@ NSError *error = nil; NSString *SHA = @"0c37a5391bbff43c37f0d0371823a5509eed5b1d"; GTRepository *repo = self.bareFixtureRepository; - GTTag *tag = (GTTag *)[repo lookupObjectBySHA:SHA error:&error]; + GTTag *tag = [GTTag lookupWithSHA:SHA inRepository:repo error:&error]; GTOID *newOID = [repo OIDByCreatingTagNamed:@"a_new_tag" target:tag.target tagger:tag.tagger message:@"my tag\n" error:&error]; expect(newOID).notTo.beNil(); - tag = (GTTag *)[repo lookupObjectByOID:newOID error:&error]; + tag = [GTTag lookupWithOID:newOID inRepository:repo error:&error]; expect(error).to.beNil(); expect(tag).notTo.beNil(); expect(newOID.SHA).to.equal(tag.SHA); @@ -279,7 +279,7 @@ NSError *error = nil; NSString *SHA = @"0c37a5391bbff43c37f0d0371823a5509eed5b1d"; GTRepository *repo = self.bareFixtureRepository; - GTTag *tag = (GTTag *)[repo lookupObjectBySHA:SHA error:&error]; + GTTag *tag = [GTTag lookupWithSHA:SHA inRepository:repo error:&error]; GTOID *OID = [repo OIDByCreatingTagNamed:tag.name target:tag.target tagger:tag.tagger message:@"new message" error:&error]; expect(OID).to.beNil(); @@ -300,7 +300,7 @@ it(@"should allow commits", ^{ NSError *error = nil; - GTCommit *commit = [repository lookupObjectBySHA:@"1d69f3c0aeaf0d62e25591987b93b8ffc53abd77" objectType:GTObjectTypeCommit error:&error]; + GTCommit *commit = [GTCommit lookupWithSHA:@"1d69f3c0aeaf0d62e25591987b93b8ffc53abd77" inRepository:repository error:&error]; expect(commit).to.beTruthy(); expect(error.localizedDescription).to.beNil(); BOOL result = [repository checkoutCommit:commit strategy:GTCheckoutStrategyAllowConflicts error:&error progressBlock:nil]; @@ -319,9 +319,9 @@ GTReference *originalHead = [repository headReferenceWithError:NULL]; NSString *resetTargetSHA = @"8496071c1b46c854b31185ea97743be6a8774479"; - GTCommit *commit = [repository lookupObjectBySHA:resetTargetSHA error:NULL]; + GTCommit *commit = [GTCommit lookupWithSHA:resetTargetSHA inRepository:repository error:NULL]; expect(commit).notTo.beNil(); - GTCommit *originalHeadCommit = [repository lookupObjectBySHA:originalHead.targetSHA error:NULL]; + GTCommit *originalHeadCommit = [GTCommit lookupWithSHA:originalHead.targetSHA inRepository:repository error:NULL]; expect(originalHeadCommit).notTo.beNil(); BOOL success = [repository resetToCommit:commit withResetType:GTRepositoryResetTypeSoft error:&error]; diff --git a/ObjectiveGitTests/GTSubmoduleSpec.m b/ObjectiveGitTests/GTSubmoduleSpec.m index a20f0779a..cd973686c 100644 --- a/ObjectiveGitTests/GTSubmoduleSpec.m +++ b/ObjectiveGitTests/GTSubmoduleSpec.m @@ -154,7 +154,7 @@ GTRepository *submoduleRepo = [submodule submoduleRepository:NULL]; expect(submoduleRepo).notTo.beNil(); - GTCommit *newHEAD = (id)[submoduleRepo lookupObjectBySHA:@"82dc47f6ba3beecab33080a1136d8913098e1801" objectType:GTObjectTypeCommit error:NULL]; + GTCommit *newHEAD = [GTCommit lookupWithSHA:@"82dc47f6ba3beecab33080a1136d8913098e1801" inRepository:submoduleRepo error:NULL]; expect(newHEAD).notTo.beNil(); expect([submoduleRepo resetToCommit:newHEAD withResetType:GTRepositoryResetTypeHard error:NULL]).to.beTruthy(); diff --git a/ObjectiveGitTests/GTTagSpec.m b/ObjectiveGitTests/GTTagSpec.m index f1416c53a..09490f790 100644 --- a/ObjectiveGitTests/GTTagSpec.m +++ b/ObjectiveGitTests/GTTagSpec.m @@ -16,7 +16,7 @@ NSError *error = nil; GTRepository *repo = self.bareFixtureRepository; NSString *tagSHA = @"0c37a5391bbff43c37f0d0371823a5509eed5b1d"; - tag = (GTTag *)[repo lookupObjectBySHA:tagSHA error:&error]; + tag = [GTTag lookupWithSHA:tagSHA inRepository:repo error:&error]; expect(error).to.beFalsy(); expect(tag).to.beTruthy(); expect(tagSHA).to.equal(tag.SHA); diff --git a/ObjectiveGitTests/GTTreeBuilderSpec.m b/ObjectiveGitTests/GTTreeBuilderSpec.m index f36b4ec64..62eb8476b 100644 --- a/ObjectiveGitTests/GTTreeBuilderSpec.m +++ b/ObjectiveGitTests/GTTreeBuilderSpec.m @@ -29,8 +29,8 @@ GTRepository *repo = self.bareFixtureRepository; expect(repo).notTo.beNil(); - - GTTree *tree = (GTTree *)[repo lookupObjectBySHA:testTreeSHA error:NULL]; + + GTTree *tree = [GTTree lookupWithSHA:testTreeSHA inRepository:repo error:NULL]; expect(tree).notTo.beNil(); GTTreeBuilder *builder = [[GTTreeBuilder alloc] initWithTree:tree error:&error]; @@ -134,8 +134,8 @@ GTTree *writtenTree = [builder writeTreeToRepository:repo error:&error]; expect(writtenTree).notTo.beNil(); expect(error).to.beNil(); - - GTTree *readTree = (GTTree *)[repo lookupObjectBySHA:writtenTree.SHA objectType:GTObjectTypeTree error:&error]; + + GTTree *readTree = [GTTree lookupWithSHA:writtenTree.SHA inRepository:repo error:&error]; expect(readTree).notTo.beNil(); expect(error).to.beNil(); }); diff --git a/ObjectiveGitTests/GTTreeSpec.m b/ObjectiveGitTests/GTTreeSpec.m index fc0f12454..cda740817 100644 --- a/ObjectiveGitTests/GTTreeSpec.m +++ b/ObjectiveGitTests/GTTreeSpec.m @@ -19,7 +19,7 @@ GTRepository *repo = self.bareFixtureRepository; expect(repo).notTo.beNil(); - tree = (GTTree *)[repo lookupObjectBySHA:testTreeSHA error:NULL]; + tree = [GTTree lookupWithSHA:testTreeSHA inRepository:repo error:NULL]; expect(tree).notTo.beNil(); }); From 7d8449e1bab72a665d5b45a043b9ec051fe1976c Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 11 Nov 2013 13:20:15 +0100 Subject: [PATCH 56/61] Rename `-fileURL` to `-workingDirectoryURL` and provide `-displayURL`. --- Classes/GTRepository.h | 8 ++++++- Classes/GTRepository.m | 8 +++++-- .../project.pbxproj | 22 +++++++++---------- ObjectiveGitTests/GTBlobSpec.m | 2 +- ObjectiveGitTests/GTRepository+StatusSpec.m | 6 ++--- ObjectiveGitTests/GTRepositoryStashingSpec.m | 10 ++++----- ObjectiveGitTests/GTSubmoduleSpec.m | 6 ++--- 7 files changed, 36 insertions(+), 26 deletions(-) diff --git a/Classes/GTRepository.h b/Classes/GTRepository.h index e0d11f07a..fa7f4a1c0 100644 --- a/Classes/GTRepository.h +++ b/Classes/GTRepository.h @@ -106,10 +106,16 @@ extern NSString *const GTRepositoryCloneOptionsCredentialProvider; @interface GTRepository : NSObject // The file URL for the repository's working directory. -@property (nonatomic, readonly, strong) NSURL *fileURL; +@property (nonatomic, readonly, strong) NSURL *workingDirectoryURL; + // The file URL for the repository's .git directory. @property (nonatomic, readonly, strong) NSURL *gitDirectoryURL; +// Get an URL appropriate for displaying. +// If the repository is bare, returns the `-gitDirectoryURL`. Otherwise returns +// the `-workingDirectoryURL`. +@property (nonatomic, readonly, strong) NSURL *displayURL; + // Is this a bare repository (one without a working directory)? @property (nonatomic, readonly, getter = isBare) BOOL bare; diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index 08d73007e..86680be69 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -76,7 +76,7 @@ @interface GTRepository () @implementation GTRepository - (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p> fileURL: %@", self.class, self, self.fileURL]; + return [NSString stringWithFormat:@"<%@: %p> displayURL: %@", self.class, self, self.displayURL]; } - (BOOL)isEqual:(GTRepository *)repo { @@ -405,7 +405,7 @@ - (NSArray *)referenceNamesWithError:(NSError **)error { return referenceNames; } -- (NSURL *)fileURL { +- (NSURL *)workingDirectoryURL { const char *path = git_repository_workdir(self.git_repository); // bare repository, you may be looking for gitDirectoryURL if (path == NULL) return nil; @@ -420,6 +420,10 @@ - (NSURL *)gitDirectoryURL { return [NSURL fileURLWithPath:@(path) isDirectory:YES]; } +- (NSURL *)displayURL { + return (self.isBare == YES ? self.gitDirectoryURL : self.workingDirectoryURL); +} + - (BOOL)isBare { return (BOOL)git_repository_is_bare(self.git_repository); } diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index 4160952b3..aa2e152a8 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -495,7 +495,7 @@ 306123AB17EA5261006591D4 /* metamacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metamacros.h; sourceTree = ""; }; 307623AA17C6C8BD00E2CDF1 /* NSArray+StringArraySpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+StringArraySpec.m"; sourceTree = ""; }; 30865A90167F503400B1AB6E /* GTDiffSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTDiffSpec.m; sourceTree = ""; }; - 30A269AC17B4878C000FE64E /* GTRepository+StatusSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTRepository+StatusSpec.m"; sourceTree = ""; }; + 30A269AC17B4878C000FE64E /* GTRepository+StatusSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = "GTRepository+StatusSpec.m"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 30A3D6521667F11C00C49A39 /* GTDiff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTDiff.h; sourceTree = ""; }; 30A3D6531667F11C00C49A39 /* GTDiff.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTDiff.m; sourceTree = ""; }; 30B1E7EC1703522100D0814D /* NSDate+GTTimeAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+GTTimeAdditions.h"; sourceTree = ""; }; @@ -503,16 +503,16 @@ 30B1E7FF1703871900D0814D /* GTTimeAdditionsSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTTimeAdditionsSpec.m; sourceTree = ""; }; 30DCBA5A17B45213009B0EBD /* GTStatusDelta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTStatusDelta.h; sourceTree = ""; }; 30DCBA5B17B45213009B0EBD /* GTStatusDelta.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTStatusDelta.m; sourceTree = ""; }; - 30DCBA6117B45A78009B0EBD /* GTRepository+Status.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTRepository+Status.h"; sourceTree = ""; }; - 30DCBA6217B45A78009B0EBD /* GTRepository+Status.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTRepository+Status.m"; sourceTree = ""; }; + 30DCBA6117B45A78009B0EBD /* GTRepository+Status.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "GTRepository+Status.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 30DCBA6217B45A78009B0EBD /* GTRepository+Status.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = "GTRepository+Status.m"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 30DCBA6F17B4791A009B0EBD /* NSArray+StringArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+StringArray.h"; sourceTree = ""; }; 30DCBA7017B4791A009B0EBD /* NSArray+StringArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+StringArray.m"; sourceTree = ""; }; 30FDC07D16835A8100654BF0 /* GTDiffLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTDiffLine.h; sourceTree = ""; }; 30FDC07E16835A8100654BF0 /* GTDiffLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTDiffLine.m; sourceTree = ""; }; 32DBCF5E0370ADEE00C91783 /* ObjectiveGitFramework_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectiveGitFramework_Prefix.pch; sourceTree = ""; }; 4D103ADC1819CFAA0029DB24 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; - 4D12323F178E009E0048F785 /* GTRepositoryCommittingSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTRepositoryCommittingSpec.m; sourceTree = ""; }; - 4D1C40D7182C006D00BE2960 /* GTBlobSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTBlobSpec.m; sourceTree = ""; }; + 4D12323F178E009E0048F785 /* GTRepositoryCommittingSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTRepositoryCommittingSpec.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 4D1C40D7182C006D00BE2960 /* GTBlobSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTBlobSpec.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 4D26799D178DAF31002A2795 /* GTTreeEntry+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTTreeEntry+Private.h"; sourceTree = ""; }; 4D79C0EC17DF9F4D00997DE4 /* GTCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTCredential.h; sourceTree = ""; }; 4D79C0ED17DF9F4D00997DE4 /* GTCredential.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTCredential.m; sourceTree = ""; }; @@ -603,17 +603,17 @@ BDD9C3FF133BA604003708E7 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; BDE4C060130EFE2C00851650 /* NSError+Git.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+Git.h"; sourceTree = ""; }; BDE4C061130EFE2C00851650 /* NSError+Git.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+Git.m"; sourceTree = ""; }; - BDE4C062130EFE2C00851650 /* GTRepository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTRepository.h; sourceTree = ""; }; + BDE4C062130EFE2C00851650 /* GTRepository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = GTRepository.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; BDE4C063130EFE2C00851650 /* GTRepository.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTRepository.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - BDFAF9C1131C1845000508BC /* GTIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTIndex.h; sourceTree = ""; }; - BDFAF9C2131C1845000508BC /* GTIndex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTIndex.m; sourceTree = ""; }; + BDFAF9C1131C1845000508BC /* GTIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = GTIndex.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + BDFAF9C2131C1845000508BC /* GTIndex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTIndex.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; BDFAF9C7131C1868000508BC /* GTIndexEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTIndexEntry.h; sourceTree = ""; }; BDFAF9C8131C1868000508BC /* GTIndexEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTIndexEntry.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; D00F6815175D373C004DB9D6 /* GTReferenceSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTReferenceSpec.m; sourceTree = ""; }; D015F7C817F695E800AD5E1F /* GTRepository+Stashing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTRepository+Stashing.h"; sourceTree = ""; }; D015F7C917F695E800AD5E1F /* GTRepository+Stashing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTRepository+Stashing.m"; sourceTree = ""; }; - D015F7D417F6965400AD5E1F /* GTRepositoryStashingSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTRepositoryStashingSpec.m; sourceTree = ""; }; - D03B7C401756AB370034A610 /* GTSubmoduleSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTSubmoduleSpec.m; sourceTree = ""; }; + D015F7D417F6965400AD5E1F /* GTRepositoryStashingSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTRepositoryStashingSpec.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + D03B7C401756AB370034A610 /* GTSubmoduleSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTSubmoduleSpec.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; D040AF6F177B9779001AD9EB /* GTOIDSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTOIDSpec.m; sourceTree = ""; }; D040AF77177B9A9E001AD9EB /* GTSignatureSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTSignatureSpec.m; sourceTree = ""; }; D06D9E001755D10000558C17 /* GTEnumeratorSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTEnumeratorSpec.m; sourceTree = ""; }; @@ -627,7 +627,7 @@ D0A463DB17E57C45000F5021 /* Test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Test.xcconfig; sourceTree = ""; }; D0A463DD17E57C45000F5021 /* Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Application.xcconfig; sourceTree = ""; }; D0A463DE17E57C45000F5021 /* StaticLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = StaticLibrary.xcconfig; sourceTree = ""; }; - D0AC906B172F941F00347DC4 /* GTRepositorySpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTRepositorySpec.m; sourceTree = ""; }; + D0AC906B172F941F00347DC4 /* GTRepositorySpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GTRepositorySpec.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; D0D81863174421EB00995A2E /* iOS-Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-Application.xcconfig"; sourceTree = ""; }; D0D81864174421EB00995A2E /* iOS-Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-Base.xcconfig"; sourceTree = ""; }; D0D81865174421EB00995A2E /* iOS-StaticLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-StaticLibrary.xcconfig"; sourceTree = ""; }; diff --git a/ObjectiveGitTests/GTBlobSpec.m b/ObjectiveGitTests/GTBlobSpec.m index 77dc0a1fa..69bad1f98 100644 --- a/ObjectiveGitTests/GTBlobSpec.m +++ b/ObjectiveGitTests/GTBlobSpec.m @@ -71,7 +71,7 @@ it(@"works with valid parameters", ^{ NSString *fileContent = @"Test contents\n"; NSString *fileName = @"myfile.txt"; - NSURL *fileURL = [repository.fileURL URLByAppendingPathComponent:fileName]; + NSURL *fileURL = [repository.workingDirectoryURL URLByAppendingPathComponent:fileName]; NSError *error = nil; BOOL success = [fileContent writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:&error]; diff --git a/ObjectiveGitTests/GTRepository+StatusSpec.m b/ObjectiveGitTests/GTRepository+StatusSpec.m index 5398595ee..e8e5c01d7 100644 --- a/ObjectiveGitTests/GTRepository+StatusSpec.m +++ b/ObjectiveGitTests/GTRepository+StatusSpec.m @@ -17,7 +17,7 @@ beforeEach(^{ repository = self.testAppFixtureRepository; - targetFileURL = [repository.fileURL URLByAppendingPathComponent:@"main.m"]; + targetFileURL = [repository.workingDirectoryURL URLByAppendingPathComponent:@"main.m"]; expect(repository).toNot.beNil(); }); @@ -68,7 +68,7 @@ }); it(@"should recognize copied files", ^{ - NSURL *copyLocation = [repository.fileURL URLByAppendingPathComponent:@"main2.m"]; + NSURL *copyLocation = [repository.workingDirectoryURL URLByAppendingPathComponent:@"main2.m"]; expect([NSFileManager.defaultManager copyItemAtURL:targetFileURL toURL:copyLocation error:&err]).to.beTruthy(); expect(err).to.beNil(); updateIndexForSubpathAndExpectStatus(copyLocation.lastPathComponent, GTStatusDeltaStatusCopied); @@ -81,7 +81,7 @@ }); it(@"should recognize renamed files", ^{ - NSURL *moveLocation = [repository.fileURL URLByAppendingPathComponent:@"main-moved.m"]; + NSURL *moveLocation = [repository.workingDirectoryURL URLByAppendingPathComponent:@"main-moved.m"]; expect([NSFileManager.defaultManager moveItemAtURL:targetFileURL toURL:moveLocation error:&err]).to.beTruthy(); expect(err).to.beNil(); expectSubpathToHaveWorkDirStatus(moveLocation.lastPathComponent, GTStatusDeltaStatusRenamed); diff --git a/ObjectiveGitTests/GTRepositoryStashingSpec.m b/ObjectiveGitTests/GTRepositoryStashingSpec.m index 892083dcb..c32334310 100644 --- a/ObjectiveGitTests/GTRepositoryStashingSpec.m +++ b/ObjectiveGitTests/GTRepositoryStashingSpec.m @@ -28,7 +28,7 @@ }); it(@"should create a stash with modified file content", ^{ - NSURL *fileURL = [repository.fileURL URLByAppendingPathComponent:@"README.md"]; + NSURL *fileURL = [repository.workingDirectoryURL URLByAppendingPathComponent:@"README.md"]; NSString *newContent = @"foobar"; NSString *oldContent = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:NULL]; @@ -46,7 +46,7 @@ }); it(@"should create a stash with uncommitted changes", ^{ - NSURL *fileURL = [repository.fileURL URLByAppendingPathComponent:@"README.md"]; + NSURL *fileURL = [repository.workingDirectoryURL URLByAppendingPathComponent:@"README.md"]; NSString *newContent = @"foobar"; NSString *oldContent = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:NULL]; @@ -64,7 +64,7 @@ }); it(@"should fail to create a stash with an untracked file using default options", ^{ - expect([@"foobar" writeToURL:[repository.fileURL URLByAppendingPathComponent:@"new-test-file"] atomically:YES encoding:NSUTF8StringEncoding error:NULL]).to.beTruthy(); + expect([@"foobar" writeToURL:[repository.workingDirectoryURL URLByAppendingPathComponent:@"new-test-file"] atomically:YES encoding:NSUTF8StringEncoding error:NULL]).to.beTruthy(); NSError *error = nil; GTCommit *stash = [repository stashChangesWithMessage:nil flags:GTRepositoryStashFlagDefault error:&error]; @@ -76,7 +76,7 @@ }); it(@"should stash an untracked file when enabled", ^{ - expect([@"foobar" writeToURL:[repository.fileURL URLByAppendingPathComponent:@"new-test-file"] atomically:YES encoding:NSUTF8StringEncoding error:NULL]).to.beTruthy(); + expect([@"foobar" writeToURL:[repository.workingDirectoryURL URLByAppendingPathComponent:@"new-test-file"] atomically:YES encoding:NSUTF8StringEncoding error:NULL]).to.beTruthy(); NSError *error = nil; GTCommit *stash = [repository stashChangesWithMessage:nil flags:GTRepositoryStashFlagIncludeUntracked error:&error]; @@ -90,7 +90,7 @@ for (int i = stashCount; i >= 0; i--) { NSString *filename = [NSString stringWithFormat:@"new-test-file-%i", i]; - expect([@"foobar" writeToURL:[repository.fileURL URLByAppendingPathComponent:filename] atomically:YES encoding:NSUTF8StringEncoding error:NULL]).to.beTruthy(); + expect([@"foobar" writeToURL:[repository.workingDirectoryURL URLByAppendingPathComponent:filename] atomically:YES encoding:NSUTF8StringEncoding error:NULL]).to.beTruthy(); NSString *message = [NSString stringWithFormat:@"stash %i", i]; diff --git a/ObjectiveGitTests/GTSubmoduleSpec.m b/ObjectiveGitTests/GTSubmoduleSpec.m index cd973686c..8999a4e69 100644 --- a/ObjectiveGitTests/GTSubmoduleSpec.m +++ b/ObjectiveGitTests/GTSubmoduleSpec.m @@ -80,7 +80,7 @@ GTSubmodule *submodule = [repo submoduleWithName:@"new_submodule" error:NULL]; expect(submodule).to.beNil(); - NSURL *gitmodulesURL = [repo.fileURL URLByAppendingPathComponent:@".gitmodules"]; + NSURL *gitmodulesURL = [repo.workingDirectoryURL URLByAppendingPathComponent:@".gitmodules"]; NSMutableString *gitmodules = [NSMutableString stringWithContentsOfURL:gitmodulesURL usedEncoding:NULL error:NULL]; expect(gitmodules).notTo.beNil(); @@ -143,7 +143,7 @@ expect(submoduleRepo).notTo.beNil(); expect(error).to.beNil(); - expect(submoduleRepo.fileURL).to.equal([repo.fileURL URLByAppendingPathComponent:@"Test_App"]); + expect(submoduleRepo.workingDirectoryURL).to.equal([repo.workingDirectoryURL URLByAppendingPathComponent:@"Test_App"]); expect(submoduleRepo.bare).to.beFalsy(); expect(submoduleRepo.empty).to.beFalsy(); expect(submoduleRepo.HEADDetached).to.beTruthy(); @@ -225,7 +225,7 @@ expect(submoduleRepo).notTo.beNil(); expect(error).to.beNil(); - expect(submoduleRepo.fileURL).to.equal([repo.fileURL URLByAppendingPathComponent:@"Test_App2"]); + expect(submoduleRepo.workingDirectoryURL).to.equal([repo.workingDirectoryURL URLByAppendingPathComponent:@"Test_App2"]); expect(submoduleRepo.bare).to.beFalsy(); expect(submoduleRepo.empty).to.beFalsy(); expect(submoduleRepo.HEADDetached).to.beTruthy(); From fb0359d6c4d21b91aa3ffb59b00b9308eb709437 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 11 Nov 2013 14:03:05 +0100 Subject: [PATCH 57/61] `#pragma mark`s. --- Classes/GTTag.m | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Classes/GTTag.m b/Classes/GTTag.m index e497c0085..2182fb624 100644 --- a/Classes/GTTag.m +++ b/Classes/GTTag.m @@ -37,11 +37,15 @@ @implementation GTTag +#pragma mark - +#pragma mark NSObject + - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p> name: %@, message: %@, targetType: %d", NSStringFromClass([self class]), self,self.name, self.message, self.targetType]; } -#pragma mark API +#pragma mark - +#pragma mark Properties - (NSString *)message { return @(git_tag_message(self.git_tag)); @@ -70,6 +74,9 @@ - (git_tag *)git_tag { return (git_tag *) self.git_object; } +#pragma mark - +#pragma mark API + - (id)objectByPeelingTagError:(NSError **)error { git_object *target = nil; int gitError = git_tag_peel(&target, self.git_tag); From 066cfad42877783c16b5877a6aa73defaf74b619 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 11 Nov 2013 14:09:33 +0100 Subject: [PATCH 58/61] Tag creation & deletion methods. --- Classes/GTTag.h | 36 +++++++++++++++++++++++++++++++++++- Classes/GTTag.m | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/Classes/GTTag.h b/Classes/GTTag.h index 645327349..45fa67b02 100644 --- a/Classes/GTTag.h +++ b/Classes/GTTag.h @@ -31,6 +31,7 @@ @class GTSignature; @class GTRepository; +@class GTReference; @interface GTTag : GTObject {} @@ -49,14 +50,47 @@ // The type of the 'tagged' object. @property (nonatomic, readonly) GTObjectType targetType; +// Creates a tag in a repository. +// +// tagName - Name for the tag; this name is validated for consistency. +// If `force` is `NO`, it should also not conflict with an +// already existing tag name. +// targetObject - The object the tag should point to. It must belong to `repository`. +// message - The message attached to the tag. +// tagger - Signature of the tagger for this tag, and of the tagging time +// force - If YES, an underlying duplicate reference would be deleted. +// repository - The repository to create the tag in. +// error - This optional pointer will be set to a NSError instance if +// the tag's creation fails. +// +// Returns a newly created tag, or nil if the tag creation failed. ++ (instancetype)tagByCreatingTagNamed:(NSString *)tagName target:(GTObject *)targetObject message:(NSString *)message tagger:(GTSignature *)tagger force:(BOOL)force inRepository:(GTRepository *)repository error:(NSError **)error; + +// Creates a lightweight tag in a repository. +// +// tagName - Name for the tag; this name is validated for consistency. +// If `force` is `NO`, it should also not conflict with an +// already existing tag name. +// targetObject - The object the tag should point to. It must belong to `repository`. +// force - If YES, an underlying duplicate reference would be deleted. +// repository - The repository to create the tag in. +// error - This optional pointer will be set to a NSError instance if +// the tag's creation fails. +// +// Returns the reference underlying the new tag, or nil if the tag creation failed. ++ (GTReference *)tagByCreatingLightweightTagNamed:(NSString *)tagName target:(GTObject *)targetObject force:(BOOL)force inRepository:(GTRepository *)repository error:(NSError **)error; + // Recursively peel a tag until a non tag GTObject is found // -// errro - Will be filled with a NSError object on failure. +// error - Will be filled with a NSError object on failure. // May be NULL. // // Returns the found object or nil on error. - (id)objectByPeelingTagError:(NSError **)error; +// Delete the receiver. +- (BOOL)delete:(NSError **)error; + // The underlying `git_object` as a `git_tag` object. - (git_tag *)git_tag __attribute__((objc_returns_inner_pointer)); diff --git a/Classes/GTTag.m b/Classes/GTTag.m index 2182fb624..679dc3c5c 100644 --- a/Classes/GTTag.m +++ b/Classes/GTTag.m @@ -37,6 +37,41 @@ @implementation GTTag +#pragma mark - +#pragma mark Class methods + ++ (instancetype)tagByCreatingTagNamed:(NSString *)tagName target:(GTObject *)targetObject message:(NSString *)message tagger:(GTSignature *)tagger force:(BOOL)force inRepository:(GTRepository *)repository error:(NSError **)error { + NSParameterAssert(tagName != nil); + NSParameterAssert(targetObject != nil); + NSParameterAssert(message != nil); + NSParameterAssert(tagger != nil); + NSParameterAssert(repository != nil); + + git_oid git_oid; + int gitError = git_tag_create(&git_oid, repository.git_repository, tagName.UTF8String, targetObject.git_object, tagger.git_signature, message.UTF8String, (force == YES ? 1 : 0)); + if (gitError != GIT_OK) { + if (error) *error = [NSError git_errorFor:gitError description:@"Tag creation failed"]; + return nil; + } + + return [repository lookupObjectByOID:[GTOID oidWithGitOid:&git_oid] objectType:GTObjectTypeTag error:error]; +} + ++ (GTReference *)tagByCreatingLightweightTagNamed:(NSString *)tagName target:(GTObject *)targetObject force:(BOOL)force inRepository:(GTRepository *)repository error:(NSError **)error { + NSParameterAssert(tagName != nil); + NSParameterAssert(targetObject != nil); + NSParameterAssert(repository != nil); + + git_oid gitOid; + int gitError = git_tag_create_lightweight(&gitOid, repository.git_repository, tagName.UTF8String, targetObject.git_object, (force == YES ? 1 : 0)); + if (gitError != GIT_OK) { + if (error) *error = [NSError git_errorFor:gitError description:@"Lightweight tag creation failed"]; + return nil; + } + + return [GTReference referenceByLookingUpReferencedNamed:[NSString stringWithFormat:@"refs/tags/%@", tagName] inRepository:repository error:error]; +} + #pragma mark - #pragma mark NSObject @@ -88,4 +123,13 @@ - (id)objectByPeelingTagError:(NSError **)error { return [[GTObject alloc] initWithObj:target inRepository:self.repository]; } +- (BOOL)delete:(NSError **)error { + int gitError = git_tag_delete(self.repository.git_repository, self.name.UTF8String); + if (gitError != GIT_OK) { + if (error) *error = [NSError git_errorFor:gitError description:@"Tag deletion failed"]; + return NO; + } + return YES; +} + @end From cc40bbbebd560920a6e751fce54fb4b03b184767 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 11 Nov 2013 14:15:29 +0100 Subject: [PATCH 59/61] Remove tag creation methods from `GTRepository`. --- Classes/GTRepository.h | 45 ------------------------------------------ Classes/GTRepository.m | 32 ------------------------------ 2 files changed, 77 deletions(-) diff --git a/Classes/GTRepository.h b/Classes/GTRepository.h index 92abed5c1..4d197f15a 100644 --- a/Classes/GTRepository.h +++ b/Classes/GTRepository.h @@ -312,51 +312,6 @@ extern NSString *const GTRepositoryCloneOptionsCredentialProvider; // Returns the index, or nil if an error occurred. - (GTIndex *)indexWithError:(NSError **)error; -// Creates a new lightweight tag in this repository. -// -// name - Name for the tag; this name is validated -// for consistency. It should also not conflict with an -// already existing tag name -// target - Object to which this tag points. This object -// must belong to this repository. -// error - Will be filled with a NSError instance on failuer. -// May be NULL. -// -// Returns YES on success or NO otherwise. -- (BOOL)createLightweightTagNamed:(NSString *)tagName target:(GTObject *)target error:(NSError **)error; - -// Creates an annotated tag in this repo. Existing tags are not overwritten. -// -// tagName - Name for the tag; this name is validated -// for consistency. It should also not conflict with an -// already existing tag name -// theTarget - Object to which this tag points. This object -// must belong to this repository. -// tagger - Signature of the tagger for this tag, and -// of the tagging time -// message - Full message for this tag -// error - Will be filled with a NSError object in case of error. -// May be NULL. -// -// Returns the object ID of the newly created tag or nil on error. -- (GTOID *)OIDByCreatingTagNamed:(NSString *)tagName target:(GTObject *)theTarget tagger:(GTSignature *)theTagger message:(NSString *)theMessage error:(NSError **)error; - -// Creates an annotated tag in this repo. Existing tags are not overwritten. -// -// tagName - Name for the tag; this name is validated -// for consistency. It should also not conflict with an -// already existing tag name -// theTarget - Object to which this tag points. This object -// must belong to this repository. -// tagger - Signature of the tagger for this tag, and -// of the tagging time -// message - Full message for this tag -// error - Will be filled with a NSError object in case of error. -// May be NULL. -// -// Returns the newly created tag or nil on error. -- (GTTag *)createTagNamed:(NSString *)tagName target:(GTObject *)theTarget tagger:(GTSignature *)theTagger message:(NSString *)theMessage error:(NSError **)error; - // Checkout a commit // // targetCommit - The commit to checkout. diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index 38ddd9475..f3d32a9f3 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -645,38 +645,6 @@ - (GTSignature *)userSignatureForNow { return [[GTSignature alloc] initWithName:name email:email time:[NSDate date]]; } -#pragma mark Tagging - -- (BOOL)createLightweightTagNamed:(NSString *)tagName target:(GTObject *)target error:(NSError **)error { - NSParameterAssert(tagName != nil); - NSParameterAssert(target != nil); - - git_oid oid; - int gitError = git_tag_create_lightweight(&oid, self.git_repository, tagName.UTF8String, target.git_object, 0); - if (gitError != GIT_OK) { - if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Cannot create lightweight tag"]; - return NO; - } - - return YES; -} - -- (GTOID *)OIDByCreatingTagNamed:(NSString *)tagName target:(GTObject *)theTarget tagger:(GTSignature *)theTagger message:(NSString *)theMessage error:(NSError **)error { - git_oid oid; - int gitError = git_tag_create(&oid, self.git_repository, [tagName UTF8String], theTarget.git_object, theTagger.git_signature, [theMessage UTF8String], 0); - if (gitError != GIT_OK) { - if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to create tag in repository"]; - return nil; - } - - return [GTOID oidWithGitOid:&oid]; -} - -- (GTTag *)createTagNamed:(NSString *)tagName target:(GTObject *)theTarget tagger:(GTSignature *)theTagger message:(NSString *)theMessage error:(NSError **)error { - GTOID *oid = [self OIDByCreatingTagNamed:tagName target:theTarget tagger:theTagger message:theMessage error:error]; - return oid ? [self lookupObjectByOID:oid objectType:GTObjectTypeTag error:error] : nil; -} - #pragma mark Checkout // The type of block passed to -checkout:strategy:progressBlock:notifyBlock:notifyFlags:error: for progress reporting From b373d5d2275c0972faec93c01273d3210148c87e Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 11 Nov 2013 15:22:34 +0100 Subject: [PATCH 60/61] Move tag creation specs to `GTTagSpec`. --- ObjectiveGitTests/GTRepositorySpec.m | 33 ------------ ObjectiveGitTests/GTTagSpec.m | 75 +++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 35 deletions(-) diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 4d1ddee5a..934cc6ebe 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -254,39 +254,6 @@ }); }); -describe(@"-OIDByCreatingTagNamed:target:tagger:message:error", ^{ - it(@"should create a new tag",^{ - NSError *error = nil; - NSString *SHA = @"0c37a5391bbff43c37f0d0371823a5509eed5b1d"; - GTRepository *repo = self.bareFixtureRepository; - GTTag *tag = (GTTag *)[repo lookupObjectBySHA:SHA error:&error]; - - GTOID *newOID = [repo OIDByCreatingTagNamed:@"a_new_tag" target:tag.target tagger:tag.tagger message:@"my tag\n" error:&error]; - expect(newOID).notTo.beNil(); - - tag = (GTTag *)[repo lookupObjectByOID:newOID error:&error]; - expect(error).to.beNil(); - expect(tag).notTo.beNil(); - expect(newOID.SHA).to.equal(tag.SHA); - expect(tag.type).to.equal(@"tag"); - expect(tag.message).to.equal(@"my tag\n"); - expect(tag.name).to.equal(@"a_new_tag"); - expect(tag.target.SHA).to.equal(@"5b5b025afb0b4c913b4c338a42934a3863bf3644"); - expect(tag.targetType).to.equal(GTObjectTypeCommit); - }); - - it(@"should fail to create an already existing tag", ^{ - NSError *error = nil; - NSString *SHA = @"0c37a5391bbff43c37f0d0371823a5509eed5b1d"; - GTRepository *repo = self.bareFixtureRepository; - GTTag *tag = (GTTag *)[repo lookupObjectBySHA:SHA error:&error]; - - GTOID *OID = [repo OIDByCreatingTagNamed:tag.name target:tag.target tagger:tag.tagger message:@"new message" error:&error]; - expect(OID).to.beNil(); - expect(error).notTo.beNil(); - }); -}); - describe(@"-checkout:strategy:error:progressBlock:", ^{ it(@"should allow references", ^{ NSError *error = nil; diff --git a/ObjectiveGitTests/GTTagSpec.m b/ObjectiveGitTests/GTTagSpec.m index f1416c53a..d34433b04 100644 --- a/ObjectiveGitTests/GTTagSpec.m +++ b/ObjectiveGitTests/GTTagSpec.m @@ -11,12 +11,13 @@ SpecBegin(GTTag) __block GTTag *tag; +__block GTRepository *repository; beforeEach(^{ NSError *error = nil; - GTRepository *repo = self.bareFixtureRepository; + repository = self.bareFixtureRepository; NSString *tagSHA = @"0c37a5391bbff43c37f0d0371823a5509eed5b1d"; - tag = (GTTag *)[repo lookupObjectBySHA:tagSHA error:&error]; + tag = (GTTag *)[repository lookupObjectBySHA:tagSHA error:&error]; expect(error).to.beFalsy(); expect(tag).to.beTruthy(); expect(tagSHA).to.equal(tag.SHA); @@ -35,4 +36,74 @@ expect(signature.email).to.equal(@"schacon@gmail.com"); }); + +describe(@"+tagByCreatingTagNamed:target:message:tagger:force:inRepository:error:", ^{ + __block NSString *originalTagSHA = nil; + __block GTTag *originalTag = nil; + beforeEach(^{ + originalTagSHA = @"0c37a5391bbff43c37f0d0371823a5509eed5b1d"; + originalTag = [repository lookupObjectBySHA:originalTagSHA objectType:GTObjectTypeTag error:NULL]; + }); + + it(@"should create a new tag",^{ + NSError *error = nil; + + GTTag *tag = [GTTag tagByCreatingTagNamed:@"a_new_tag" target:originalTag.target message:@"my tag\n" tagger:originalTag.tagger force:NO inRepository:repository error:&error]; + expect(error).to.beNil(); + expect(tag).notTo.beNil(); + expect(tag.type).to.equal(@"tag"); + expect(tag.message).to.equal(@"my tag\n"); + expect(tag.name).to.equal(@"a_new_tag"); + expect(tag.target.SHA).to.equal(@"5b5b025afb0b4c913b4c338a42934a3863bf3644"); + expect(tag.targetType).to.equal(GTObjectTypeCommit); + }); + + it(@"should fail to create an already existing tag", ^{ + NSError *error = nil; + GTTag *tag = [GTTag tagByCreatingTagNamed:originalTag.name target:originalTag.target message:@"my tag\n" tagger:originalTag.tagger force:NO inRepository:repository error:&error]; + expect(tag).to.beNil(); + expect(error.domain).to.equal(GTGitErrorDomain); + expect(error.code).to.equal(GIT_EEXISTS); + }); + + it(@"should delete an existing tag if `force` is YES", ^{ + NSError *error = nil; + GTTag *tag = [GTTag tagByCreatingTagNamed:originalTag.name target:originalTag.target message:@"my tag\n" tagger:originalTag.tagger force:YES inRepository:repository error:&error]; + expect(tag).notTo.beNil(); + expect(error).to.beNil(); + }); +}); + +describe(@"+tagByCreatingLightweightTagNamed:target:force:inRepository:error:", ^{ + __block NSString *originalTagSHA = nil; + __block GTTag *originalTag = nil; + beforeEach(^{ + originalTagSHA = @"0c37a5391bbff43c37f0d0371823a5509eed5b1d"; + originalTag = [repository lookupObjectBySHA:originalTagSHA objectType:GTObjectTypeTag error:NULL]; + }); + + it(@"should create a new lightweight tag", ^{ + NSError *error = nil; + GTReference *tagReference = [GTTag tagByCreatingLightweightTagNamed:@"another-tag" target:originalTag.target force:NO inRepository:repository error:&error]; + expect(tagReference).notTo.beNil(); + expect(error).to.beNil(); + expect(tagReference.targetSHA).to.equal(originalTag.target.SHA); + }); + + it(@"should fail to create an already existing tag", ^{ + NSError *error = nil; + GTReference *tagReference = [GTTag tagByCreatingLightweightTagNamed:originalTag.name target:originalTag.target force:NO inRepository:repository error:&error]; + expect(tagReference).to.beNil(); + expect(error.domain).to.equal(GTGitErrorDomain); + expect(error.code).to.equal(GIT_EEXISTS); + }); + + it(@"should delete an existing tag if `force` is YES", ^{ + NSError *error = nil; + GTReference *tagReference = [GTTag tagByCreatingLightweightTagNamed:originalTag.name target:originalTag.target force:YES inRepository:repository error:&error]; + expect(tagReference).notTo.beNil(); + expect(error).to.beNil(); + }); +}); + SpecEnd From 14d6a5a42534cf0a23a3e7047c6dfbf4ddc2351c Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Sun, 10 Nov 2013 16:45:11 +0100 Subject: [PATCH 61/61] Remove branch creation method from GTRepository. --- Classes/GTBranch.h | 3 --- Classes/GTBranch.m | 11 ----------- Classes/GTRepository.h | 9 --------- Classes/GTRepository.m | 11 ----------- 4 files changed, 34 deletions(-) diff --git a/Classes/GTBranch.h b/Classes/GTBranch.h index 9e5224fff..1fd5ad2da 100644 --- a/Classes/GTBranch.h +++ b/Classes/GTBranch.h @@ -47,9 +47,6 @@ typedef enum { @property (nonatomic, assign) GTBranch *trackingBranch; @property (nonatomic, readonly, getter=isHead) BOOL head; -+ (NSString *)localNamePrefix; -+ (NSString *)remoteNamePrefix; - // Lookup a branch by name. Performs a `GTBranchTypeAny` lookup. // See `+branchByLookingUpBranchNamed:type:inRepository:error:`. + (instancetype)branchByLookingUpBranchNamed:(NSString *)name inRepository:(GTRepository *)repository error:(NSError **)error; diff --git a/Classes/GTBranch.m b/Classes/GTBranch.m index fd7a6df09..1ade2a117 100644 --- a/Classes/GTBranch.m +++ b/Classes/GTBranch.m @@ -32,17 +32,6 @@ @implementation GTBranch -#pragma mark - -#pragma mark Class methods - -+ (NSString *)localNamePrefix { - return @"refs/heads/"; -} - -+ (NSString *)remoteNamePrefix { - return @"refs/remotes/"; -} - #pragma mark - #pragma mark Lifecycle diff --git a/Classes/GTRepository.h b/Classes/GTRepository.h index eb3db16a9..0e17a5af9 100644 --- a/Classes/GTRepository.h +++ b/Classes/GTRepository.h @@ -216,15 +216,6 @@ extern NSString *const GTRepositoryCloneOptionsCredentialProvider; // returns number of commits in the current branch or NSNotFound if an error occurred - (NSUInteger)numberOfCommitsInCurrentBranch:(NSError **)error; -// Create a new branch with this name and based off this reference. -// -// name - the name for the new branch -// ref - the reference to create the new branch off -// error(out) - will be filled if an error occurs -// -// returns the new branch or nil if an error occurred. -- (GTBranch *)createBranchNamed:(NSString *)name fromReference:(GTReference *)ref error:(NSError **)error; - // Get the current branch. // // error(out) - will be filled if an error occurs diff --git a/Classes/GTRepository.m b/Classes/GTRepository.m index d6f7664e3..77b01b7ec 100644 --- a/Classes/GTRepository.m +++ b/Classes/GTRepository.m @@ -396,17 +396,6 @@ - (NSUInteger)numberOfCommitsInCurrentBranch:(NSError **)error { return [currentBranch numberOfCommitsWithError:error]; } -- (GTBranch *)createBranchNamed:(NSString *)name fromReference:(GTReference *)ref error:(NSError **)error { - // make sure the ref is up to date before we branch off it, otherwise we could branch off an older sha - ref = [ref reloadedReferenceWithError:error]; - if (ref == nil) return nil; - - GTReference *newRef = [GTReference referenceByCreatingReferenceNamed:[NSString stringWithFormat:@"%@%@", [GTBranch localNamePrefix], name] fromReferenceTarget:[ref.resolvedTarget SHA] inRepository:self error:error]; - if (newRef == nil) return nil; - - return [GTBranch branchWithReference:newRef]; -} - - (BOOL)isEmpty { return (BOOL) git_repository_is_empty(self.git_repository); }