diff --git a/SwiftGit2.xcodeproj/project.pbxproj b/SwiftGit2.xcodeproj/project.pbxproj index ba52b15..7546a65 100644 --- a/SwiftGit2.xcodeproj/project.pbxproj +++ b/SwiftGit2.xcodeproj/project.pbxproj @@ -15,6 +15,8 @@ BE244A4E1A11707D00F8BE42 /* git2.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB31F9B1A0E581400F525B9 /* git2.h */; settings = {ATTRIBUTES = (Public, ); }; }; BE244A501A11709600F8BE42 /* git2 in Resources */ = {isa = PBXBuildFile; fileRef = BE244A4F1A11709600F8BE42 /* git2 */; }; BE244A511A11709E00F8BE42 /* git2 in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE244A4F1A11709600F8BE42 /* git2 */; }; + BE70B3E51A1ACB1A002C3F4E /* OID.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE70B3E41A1ACB1A002C3F4E /* OID.swift */; }; + BE70B3E71A1ACB37002C3F4E /* OIDSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE70B3E61A1ACB37002C3F4E /* OIDSpec.swift */; }; BEB31F291A0D6F7A00F525B9 /* SwiftGit2.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB31F281A0D6F7A00F525B9 /* SwiftGit2.h */; settings = {ATTRIBUTES = (Public, ); }; }; BEB31F2F1A0D6F7A00F525B9 /* SwiftGit2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BEB31F231A0D6F7A00F525B9 /* SwiftGit2.framework */; }; BEB31F361A0D6F7A00F525B9 /* RepositorySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEB31F351A0D6F7A00F525B9 /* RepositorySpec.swift */; }; @@ -64,6 +66,8 @@ BE14AA581A1996B70015B439 /* FixturesSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FixturesSpec.swift; sourceTree = ""; }; BE244A4F1A11709600F8BE42 /* git2 */ = {isa = PBXFileReference; lastKnownFileType = folder; name = git2; path = External/libgit2/include/git2; sourceTree = ""; }; BE244A521A117DA100F8BE42 /* SwiftGit2.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = SwiftGit2.modulemap; sourceTree = ""; }; + BE70B3E41A1ACB1A002C3F4E /* OID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OID.swift; sourceTree = ""; }; + BE70B3E61A1ACB37002C3F4E /* OIDSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OIDSpec.swift; sourceTree = ""; }; BEB31F231A0D6F7A00F525B9 /* SwiftGit2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftGit2.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BEB31F271A0D6F7A00F525B9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BEB31F281A0D6F7A00F525B9 /* SwiftGit2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftGit2.h; sourceTree = ""; }; @@ -157,6 +161,7 @@ children = ( BEB31F281A0D6F7A00F525B9 /* SwiftGit2.h */, BE14AA4F1A1974010015B439 /* SwiftGit2.m */, + BE70B3E41A1ACB1A002C3F4E /* OID.swift */, BEB31F6C1A0D78F300F525B9 /* Repository.swift */, BEB31F261A0D6F7A00F525B9 /* Supporting Files */, ); @@ -176,6 +181,7 @@ isa = PBXGroup; children = ( BE14AA531A1983520015B439 /* Fixtures */, + BE70B3E61A1ACB37002C3F4E /* OIDSpec.swift */, BEB31F351A0D6F7A00F525B9 /* RepositorySpec.swift */, BE14AA581A1996B70015B439 /* FixturesSpec.swift */, BEB31F331A0D6F7A00F525B9 /* Supporting Files */, @@ -425,6 +431,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + BE70B3E51A1ACB1A002C3F4E /* OID.swift in Sources */, BEB31F6D1A0D78F300F525B9 /* Repository.swift in Sources */, BE14AA501A1974010015B439 /* SwiftGit2.m in Sources */, ); @@ -437,6 +444,7 @@ BEB31F361A0D6F7A00F525B9 /* RepositorySpec.swift in Sources */, BE14AA591A1996B70015B439 /* FixturesSpec.swift in Sources */, BE14AA551A1984550015B439 /* Fixtures.swift in Sources */, + BE70B3E71A1ACB37002C3F4E /* OIDSpec.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/SwiftGit2/OID.swift b/SwiftGit2/OID.swift new file mode 100644 index 0000000..6352ca4 --- /dev/null +++ b/SwiftGit2/OID.swift @@ -0,0 +1,52 @@ +// +// OID.swift +// SwiftGit2 +// +// Created by Matt Diephouse on 11/17/14. +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// + +import Foundation +import LlamaKit + +/// An identifier for a Git object. +public struct OID { + + // MARK: - Initializers + + /// Create an instance from a hex formatted string. + /// + /// string - A 40-byte hex formatted string. + public init?(string: String) { + // libgit2 doesn't enforce a maximum length + if (string.lengthOfBytesUsingEncoding(NSASCIIStringEncoding) > 40) { + return nil + } + + let pointer = UnsafeMutablePointer.alloc(1) + let result = git_oid_fromstr(pointer, string.cStringUsingEncoding(NSASCIIStringEncoding)!) + + if result < GIT_OK.value { + pointer.dealloc(1) + return nil; + } + + oid = pointer.memory; + pointer.dealloc(1) + } + + // MARK: - Properties + + public let oid: git_oid +} + +extension OID: Printable { + public var description: String { + let length = Int(GIT_OID_RAWSZ) * 2 + let string = UnsafeMutablePointer.alloc(length) + var oid = self.oid + git_oid_fmt(string, &oid) + + return String(bytesNoCopy: string, length: length, encoding: NSASCIIStringEncoding, freeWhenDone: true)! + } +} diff --git a/SwiftGit2Tests/OIDSpec.swift b/SwiftGit2Tests/OIDSpec.swift new file mode 100644 index 0000000..fe8c3ae --- /dev/null +++ b/SwiftGit2Tests/OIDSpec.swift @@ -0,0 +1,42 @@ +// +// OIDSpec.swift +// SwiftGit2 +// +// Created by Matt Diephouse on 11/17/14. +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// + +import LlamaKit +import SwiftGit2 +import Nimble +import Quick + +class OIDSpec: QuickSpec { + override func spec() { + describe("init(string:)") { + it("should be nil if string is too short") { + expect(OID(string: "123456789012345678901234567890123456789")).to(beNil()) + } + + it("should be nil if string is too long") { + expect(OID(string: "12345678901234567890123456789012345678901")).to(beNil()) + } + + it("should not be nil if string is just right") { + expect(OID(string: "1234567890123456789012345678901234567890")).notTo(beNil()) + } + + it("should be nil with non-hex characters") { + expect(OID(string: "123456789012345678901234567890123456789j")).to(beNil()) + } + } + + describe("description") { + it("should return the SHA") { + let SHA = "1234567890123456789012345678901234567890" + let oid = OID(string: SHA)! + expect(oid.description).to(equal(SHA)) + } + } + } +}