Fill out Tree

This commit is contained in:
Matt Diephouse 2014-12-07 15:09:12 -05:00
parent 7ef1b5337c
commit 9b3cad3b73
2 changed files with 231 additions and 0 deletions

View File

@ -8,6 +8,53 @@
import Foundation
/// The types of git objects.
public enum ObjectType: Equatable {
case Commit
case Tree
case Blob
case Tag
static func fromLibgit2Type(type: git_otype) -> ObjectType? {
switch type.value {
case GIT_OBJ_COMMIT.value:
return .Commit
case GIT_OBJ_TREE.value:
return .Tree
case GIT_OBJ_BLOB.value:
return .Blob
case GIT_OBJ_TAG.value:
return .Tag
default:
return nil
}
}
}
extension ObjectType: Printable {
public var description: String {
switch self {
case .Commit:
return "commit"
case .Tree:
return "tree"
case .Blob:
return "blob"
case .Tag:
return "tag"
}
}
}
public func == (lhs: ObjectType, rhs: ObjectType) -> Bool {
switch (lhs, rhs) {
case (.Commit, .Commit), (.Tree, .Tree), (.Blob, .Blob), (.Tag, .Tag):
return true
default:
return false
}
}
/// A git object.
public protocol Object {
/// The OID of the object.
@ -98,10 +145,81 @@ public func == (lhs: Commit, rhs: Commit) -> Bool {
/// A git tree.
public struct Tree: Object {
/// An entry in a `Tree`.
public struct Entry {
/// The entry's UNIX file attributes.
public let attributes: Int
/// The type of object pointed to by the entry.
public let type: ObjectType
/// The OID of the object pointed to by the entry.
public let oid: OID
/// The file name of the entry.
public let name: String
/// Create an instance with a libgit2 `git_tree_entry`.
public init(pointer: COpaquePointer) {
attributes = Int(git_tree_entry_filemode(pointer).value)
type = ObjectType.fromLibgit2Type(git_tree_entry_type(pointer))!
oid = OID(oid: git_tree_entry_id(pointer).memory)
name = String.fromCString(git_tree_entry_name(pointer))!
}
/// Create an instance with the individual values.
public init(attributes: Int, type: ObjectType, oid: OID, name: String) {
self.attributes = attributes
self.type = type
self.oid = oid
self.name = name
}
}
/// The OID of the tree.
public let oid: OID
/// The entries in the tree.
public let entries: [String: Entry]
/// Create an instance with a libgit2 `git_tree`.
public init(pointer: COpaquePointer) {
oid = OID(oid: git_object_id(pointer).memory)
var entries: [String: Entry] = [:]
for idx in 0..<git_tree_entrycount(pointer) {
let entry = Entry(pointer: git_tree_entry_byindex(pointer, idx))
entries[entry.name] = entry
}
self.entries = entries
}
}
extension Tree.Entry: Hashable {
public var hashValue: Int {
return attributes ^ oid.hashValue ^ name.hashValue
}
}
extension Tree.Entry: Printable {
public var description: String {
return "\(attributes) \(type) \(oid) \(name)"
}
}
public func == (lhs: Tree.Entry, rhs: Tree.Entry) -> Bool {
return lhs.attributes == rhs.attributes
&& lhs.type == rhs.type
&& lhs.oid == rhs.oid
&& lhs.name == rhs.name
}
extension Tree: Hashable {
public var hashValue: Int {
return oid.hashValue
}
}
public func == (lhs: Tree, rhs: Tree) -> Bool {
return lhs.oid == rhs.oid
}

View File

@ -166,3 +166,116 @@ class CommitSpec: QuickSpec {
}
}
}
class TreeEntrySpec: QuickSpec {
override func spec() {
describe("init(attributes:type:oid:name:)") {
it("should set its properties") {
let attributes = Int(GIT_FILEMODE_BLOB.value)
let type = ObjectType.Blob
let oid = OID(string: "41078396f5187daed5f673e4a13b185bbad71fba")!
let name = "README.md"
let entry = Tree.Entry(attributes: attributes, type: type, oid: oid, name: name)
expect(entry.attributes).to(equal(attributes))
expect(entry.type).to(equal(type))
expect(entry.oid).to(equal(oid))
expect(entry.name).to(equal(name))
}
}
describe("init(pointer:") {
it("should set its properties") {
let repo = Fixtures.simpleRepository
let oid = OID(string: "219e9f39c2fb59ed1dfb3e78ed75055a57528f31")!
let entry = from_git_object(repo, oid) { Tree.Entry(pointer: git_tree_entry_byindex($0, 0)) }
expect(entry.attributes).to(equal(Int(GIT_FILEMODE_BLOB.value)))
expect(entry.type).to(equal(ObjectType.Blob))
expect(entry.oid).to(equal(OID(string: "41078396f5187daed5f673e4a13b185bbad71fba")))
expect(entry.name).to(equal("README.md"))
}
}
describe("==") {
it("should be true with equal objects") {
let repo = Fixtures.simpleRepository
let oid = OID(string: "219e9f39c2fb59ed1dfb3e78ed75055a57528f31")!
let entry1 = from_git_object(repo, oid) { Tree.Entry(pointer: git_tree_entry_byindex($0, 0)) }
let entry2 = entry1
expect(entry1).to(equal(entry2))
}
it("should be false with unequal objects") {
let repo = Fixtures.simpleRepository
let oid1 = OID(string: "219e9f39c2fb59ed1dfb3e78ed75055a57528f31")!
let oid2 = OID(string: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc")!
let entry1 = from_git_object(repo, oid1) { Tree.Entry(pointer: git_tree_entry_byindex($0, 0)) }
let entry2 = from_git_object(repo, oid2) { Tree.Entry(pointer: git_tree_entry_byindex($0, 0)) }
expect(entry1).notTo(equal(entry2))
}
}
describe("hashValue") {
it("should be equal with equal objects") {
let repo = Fixtures.simpleRepository
let oid = OID(string: "219e9f39c2fb59ed1dfb3e78ed75055a57528f31")!
let entry1 = from_git_object(repo, oid) { Tree.Entry(pointer: git_tree_entry_byindex($0, 0)) }
let entry2 = entry1
expect(entry1.hashValue).to(equal(entry2.hashValue))
}
}
}
}
class TreeSpec: QuickSpec {
override func spec() {
describe("init(pointer:)") {
it("should initialize its properties") {
let repo = Fixtures.simpleRepository
let oid = OID(string: "219e9f39c2fb59ed1dfb3e78ed75055a57528f31")!
let tree = from_git_object(repo, oid) { Tree(pointer: $0) }
let entries = [
"README.md": Tree.Entry(attributes: Int(GIT_FILEMODE_BLOB.value), type: .Blob, oid: OID(string: "41078396f5187daed5f673e4a13b185bbad71fba")!, name: "README.md"),
]
expect(tree.entries).to(equal(entries))
}
}
describe("==") {
it("should be true with equal objects") {
let repo = Fixtures.simpleRepository
let oid = OID(string: "219e9f39c2fb59ed1dfb3e78ed75055a57528f31")!
let tree1 = from_git_object(repo, oid) { Tree(pointer: $0) }
let tree2 = tree1
expect(tree1).to(equal(tree2))
}
it("should be false with unequal objects") {
let repo = Fixtures.simpleRepository
let oid1 = OID(string: "219e9f39c2fb59ed1dfb3e78ed75055a57528f31")!
let oid2 = OID(string: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc")!
let tree1 = from_git_object(repo, oid1) { Tree(pointer: $0) }
let tree2 = from_git_object(repo, oid2) { Tree(pointer: $0) }
expect(tree1).notTo(equal(tree2))
}
}
describe("hashValue") {
it("should be equal with equal objects") {
let repo = Fixtures.simpleRepository
let oid = OID(string: "219e9f39c2fb59ed1dfb3e78ed75055a57528f31")!
let tree1 = from_git_object(repo, oid) { Tree(pointer: $0) }
let tree2 = tree1
expect(tree1.hashValue).to(equal(tree2.hashValue))
}
}
}
}