Merge master into scripts

This commit is contained in:
Matt Rubin 2016-12-09 13:39:32 -08:00
commit 853ed3f75a
13 changed files with 320 additions and 75 deletions

View File

@ -1,5 +1,5 @@
github "jspahrsummers/xcconfigs" >= 0.7.2
github "Quick/Quick" "v0.8.0"
github "Quick/Quick" "v0.9.1"
github "Quick/Nimble" ~> 3.0.0
github "modocache/Guanaco" "5031bf67297afbe61ac0f2fbf3e3e8400b3f8888"
github "ZipArchive/ZipArchive" ~> 1.1

View File

@ -1,6 +1,6 @@
github "modocache/Guanaco" "5031bf67297afbe61ac0f2fbf3e3e8400b3f8888"
github "Quick/Nimble" "v3.0.0"
github "Quick/Quick" "v0.8.0"
github "Quick/Quick" "v0.9.1"
github "antitypical/Result" "1.0.1"
github "ZipArchive/ZipArchive" "v1.1"
github "jspahrsummers/xcconfigs" "0.8.1"

@ -1 +1 @@
Subproject commit 46b38c9c06b068baede09586aa281a6f075b2494
Subproject commit 2f037560be197f0f5ae992512549bc29fabb3818

2
External/libgit2 vendored

@ -1 +1 @@
Subproject commit 7c63a33ffe1198b77b481974cd0e74e9ace1745c
Subproject commit e8feafe32007ebd16a61820c70abd221655d053c

View File

@ -9,9 +9,9 @@ if let repo = repo.value {
.HEAD()
.flatMap { repo.commitWithOID($0.oid) }
if let commit = latestCommit.value {
println("Latest Commit: \(commit.message) by \(commit.author.name)")
print("Latest Commit: \(commit.message) by \(commit.author.name)")
} else {
println("Could not get commit: \(latestCommit.error)")
print("Could not get commit: \(latestCommit.error)")
}
} else {
println("Could not open repository: \(repo.error)")

View File

@ -38,7 +38,6 @@
621E66811C72958800A0F352 /* pack.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDBC1AA6A7E200AFE62D /* pack.h */; };
621E66821C72958800A0F352 /* patch.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDBD1AA6A7E200AFE62D /* patch.h */; };
621E66831C72958800A0F352 /* pathspec.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDBE1AA6A7E200AFE62D /* pathspec.h */; };
621E66841C72958800A0F352 /* push.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDBF1AA6A7E200AFE62D /* push.h */; };
621E66851C72958800A0F352 /* rebase.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDC01AA6A7E200AFE62D /* rebase.h */; };
621E66861C72958800A0F352 /* refdb.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDC11AA6A7E200AFE62D /* refdb.h */; };
621E66871C72958800A0F352 /* reflog.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDC21AA6A7E200AFE62D /* reflog.h */; };
@ -95,6 +94,8 @@
621E66E61C729D9600A0F352 /* SwiftGit2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 621E66B41C72958800A0F352 /* SwiftGit2.framework */; };
621E66FE1C72A5FF00A0F352 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 621E66FD1C72A5FF00A0F352 /* libiconv.tbd */; };
621E67001C72A60B00A0F352 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 621E66FF1C72A60B00A0F352 /* libz.tbd */; };
622726341C84E52500C53D17 /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 622726331C84E52500C53D17 /* Credentials.swift */; };
622726351C84E52500C53D17 /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 622726331C84E52500C53D17 /* Credentials.swift */; };
62E6FD8F1C727E9C00A312B0 /* ZipArchive.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 62E6FD8E1C727E9C00A312B0 /* ZipArchive.framework */; };
BE0991F71A578FB1007D4E6A /* Mantle.zip in Resources */ = {isa = PBXBuildFile; fileRef = BE0991F61A578FB1007D4E6A /* Mantle.zip */; };
BE0B1C5D1A9978890004726D /* detached-head.zip in Resources */ = {isa = PBXBuildFile; fileRef = BE0B1C5C1A9978890004726D /* detached-head.zip */; };
@ -143,7 +144,6 @@
BE8DEE6D1AA6A8AD00AFE62D /* pack.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDBC1AA6A7E200AFE62D /* pack.h */; };
BE8DEE6E1AA6A8AD00AFE62D /* patch.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDBD1AA6A7E200AFE62D /* patch.h */; };
BE8DEE6F1AA6A8AD00AFE62D /* pathspec.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDBE1AA6A7E200AFE62D /* pathspec.h */; };
BE8DEE701AA6A8AD00AFE62D /* push.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDBF1AA6A7E200AFE62D /* push.h */; };
BE8DEE711AA6A8AD00AFE62D /* rebase.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDC01AA6A7E200AFE62D /* rebase.h */; };
BE8DEE721AA6A8AD00AFE62D /* refdb.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDC11AA6A7E200AFE62D /* refdb.h */; };
BE8DEE731AA6A8AD00AFE62D /* reflog.h in Copy libgit2 Headers */ = {isa = PBXBuildFile; fileRef = BE8DEDC21AA6A7E200AFE62D /* reflog.h */; };
@ -193,20 +193,6 @@
remoteGlobalIDString = 621E66611C72958800A0F352;
remoteInfo = "SwiftGit2-iOS";
};
621E66F71C729F0200A0F352 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BEB31F1A1A0D6F7A00F525B9 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 621E66E71C729EB800A0F352;
remoteInfo = "OpenSSL-iOS";
};
621E66F91C729F0200A0F352 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BEB31F1A1A0D6F7A00F525B9 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 621E66ED1C729EBB00A0F352;
remoteInfo = "libssh2-iOS";
};
621E66FB1C72A25D00A0F352 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BEB31F1A1A0D6F7A00F525B9 /* Project object */;
@ -214,6 +200,20 @@
remoteGlobalIDString = 621E66DC1C729CE500A0F352;
remoteInfo = "libgit2-iOS";
};
624349871C7CADCD0087C234 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BEB31F1A1A0D6F7A00F525B9 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 621E66ED1C729EBB00A0F352;
remoteInfo = "libssh2-iOS";
};
624349891C7CADD90087C234 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BEB31F1A1A0D6F7A00F525B9 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 621E66E71C729EB800A0F352;
remoteInfo = "OpenSSL-iOS";
};
BEB31F301A0D6F7A00F525B9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BEB31F1A1A0D6F7A00F525B9 /* Project object */;
@ -268,7 +268,6 @@
621E66811C72958800A0F352 /* pack.h in Copy libgit2 Headers */,
621E66821C72958800A0F352 /* patch.h in Copy libgit2 Headers */,
621E66831C72958800A0F352 /* pathspec.h in Copy libgit2 Headers */,
621E66841C72958800A0F352 /* push.h in Copy libgit2 Headers */,
621E66851C72958800A0F352 /* rebase.h in Copy libgit2 Headers */,
621E66861C72958800A0F352 /* refdb.h in Copy libgit2 Headers */,
621E66871C72958800A0F352 /* reflog.h in Copy libgit2 Headers */,
@ -336,7 +335,6 @@
BE8DEE6D1AA6A8AD00AFE62D /* pack.h in Copy libgit2 Headers */,
BE8DEE6E1AA6A8AD00AFE62D /* patch.h in Copy libgit2 Headers */,
BE8DEE6F1AA6A8AD00AFE62D /* pathspec.h in Copy libgit2 Headers */,
BE8DEE701AA6A8AD00AFE62D /* push.h in Copy libgit2 Headers */,
BE8DEE711AA6A8AD00AFE62D /* rebase.h in Copy libgit2 Headers */,
BE8DEE721AA6A8AD00AFE62D /* refdb.h in Copy libgit2 Headers */,
BE8DEE731AA6A8AD00AFE62D /* reflog.h in Copy libgit2 Headers */,
@ -378,6 +376,7 @@
621E66F21C729EBB00A0F352 /* liblibssh2-iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "liblibssh2-iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
621E66FD1C72A5FF00A0F352 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.2.sdk/usr/lib/libiconv.tbd; sourceTree = DEVELOPER_DIR; };
621E66FF1C72A60B00A0F352 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.2.sdk/usr/lib/libz.tbd; sourceTree = DEVELOPER_DIR; };
622726331C84E52500C53D17 /* Credentials.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = "<group>"; };
62E6FD8E1C727E9C00A312B0 /* ZipArchive.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ZipArchive.framework; path = ../Carthage/Checkouts/ZipArchive/build/Debug/ZipArchive.framework; sourceTree = "<group>"; };
BE0991F61A578FB1007D4E6A /* Mantle.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = Mantle.zip; sourceTree = "<group>"; };
BE0B1C5C1A9978890004726D /* detached-head.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "detached-head.zip"; sourceTree = "<group>"; };
@ -427,7 +426,6 @@
BE8DEDBC1AA6A7E200AFE62D /* pack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pack.h; path = git2/pack.h; sourceTree = "<group>"; };
BE8DEDBD1AA6A7E200AFE62D /* patch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = patch.h; path = git2/patch.h; sourceTree = "<group>"; };
BE8DEDBE1AA6A7E200AFE62D /* pathspec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pathspec.h; path = git2/pathspec.h; sourceTree = "<group>"; };
BE8DEDBF1AA6A7E200AFE62D /* push.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = push.h; path = git2/push.h; sourceTree = "<group>"; };
BE8DEDC01AA6A7E200AFE62D /* rebase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rebase.h; path = git2/rebase.h; sourceTree = "<group>"; };
BE8DEDC11AA6A7E200AFE62D /* refdb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = refdb.h; path = git2/refdb.h; sourceTree = "<group>"; };
BE8DEDC21AA6A7E200AFE62D /* reflog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = reflog.h; path = git2/reflog.h; sourceTree = "<group>"; };
@ -607,7 +605,6 @@
BE8DEDBC1AA6A7E200AFE62D /* pack.h */,
BE8DEDBD1AA6A7E200AFE62D /* patch.h */,
BE8DEDBE1AA6A7E200AFE62D /* pathspec.h */,
BE8DEDBF1AA6A7E200AFE62D /* push.h */,
BE8DEDC01AA6A7E200AFE62D /* rebase.h */,
BE8DEDC11AA6A7E200AFE62D /* refdb.h */,
BE8DEDC21AA6A7E200AFE62D /* reflog.h */,
@ -669,6 +666,7 @@
BEB31F281A0D6F7A00F525B9 /* SwiftGit2.h */,
BE14AA4F1A1974010015B439 /* SwiftGit2.m */,
BE276B281ACCD3CF00D6DAD7 /* CheckoutStrategy.swift */,
622726331C84E52500C53D17 /* Credentials.swift */,
DA5914751A94579000AED74C /* Errors.swift */,
BE36354B1A632C9700D37EC8 /* Libgit2.swift */,
BE2E3BE51A31261300C67092 /* Objects.swift */,
@ -873,8 +871,7 @@
buildRules = (
);
dependencies = (
621E66F81C729F0200A0F352 /* PBXTargetDependency */,
621E66FA1C729F0200A0F352 /* PBXTargetDependency */,
624349881C7CADCD0087C234 /* PBXTargetDependency */,
);
name = "libgit2-iOS";
productName = libgit2;
@ -905,6 +902,7 @@
buildRules = (
);
dependencies = (
6243498A1C7CADD90087C234 /* PBXTargetDependency */,
);
name = "libssh2-iOS";
productName = libgit2;
@ -1094,6 +1092,7 @@
621E66A01C72958800A0F352 /* OID.swift in Sources */,
621E66A11C72958800A0F352 /* Remotes.swift in Sources */,
621E66A21C72958800A0F352 /* CheckoutStrategy.swift in Sources */,
622726351C84E52500C53D17 /* Credentials.swift in Sources */,
621E66A31C72958800A0F352 /* Repository.swift in Sources */,
621E66A41C72958800A0F352 /* Objects.swift in Sources */,
621E66A51C72958800A0F352 /* References.swift in Sources */,
@ -1125,6 +1124,7 @@
BE70B3E51A1ACB1A002C3F4E /* OID.swift in Sources */,
BECB5F6E1A57284700999413 /* Remotes.swift in Sources */,
BE276B291ACCD3CF00D6DAD7 /* CheckoutStrategy.swift in Sources */,
622726341C84E52500C53D17 /* Credentials.swift in Sources */,
BEB31F6D1A0D78F300F525B9 /* Repository.swift in Sources */,
BE2E3BE61A31261300C67092 /* Objects.swift in Sources */,
BECB5F6A1A56F19900999413 /* References.swift in Sources */,
@ -1157,21 +1157,21 @@
target = 621E66611C72958800A0F352 /* SwiftGit2-iOS */;
targetProxy = 621E66E41C729D8A00A0F352 /* PBXContainerItemProxy */;
};
621E66F81C729F0200A0F352 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 621E66E71C729EB800A0F352 /* OpenSSL-iOS */;
targetProxy = 621E66F71C729F0200A0F352 /* PBXContainerItemProxy */;
};
621E66FA1C729F0200A0F352 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 621E66ED1C729EBB00A0F352 /* libssh2-iOS */;
targetProxy = 621E66F91C729F0200A0F352 /* PBXContainerItemProxy */;
};
621E66FC1C72A25D00A0F352 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 621E66DC1C729CE500A0F352 /* libgit2-iOS */;
targetProxy = 621E66FB1C72A25D00A0F352 /* PBXContainerItemProxy */;
};
624349881C7CADCD0087C234 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 621E66ED1C729EBB00A0F352 /* libssh2-iOS */;
targetProxy = 624349871C7CADCD0087C234 /* PBXContainerItemProxy */;
};
6243498A1C7CADD90087C234 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 621E66E71C729EB800A0F352 /* OpenSSL-iOS */;
targetProxy = 624349891C7CADD90087C234 /* PBXContainerItemProxy */;
};
BEB31F311A0D6F7A00F525B9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = BEB31F221A0D6F7A00F525B9 /* SwiftGit2-OSX */;
@ -1524,6 +1524,7 @@
/usr/local/lib/libssh2.a,
"-lcrypto",
"-lssl",
"-lcurl",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.libgit2.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftGit2;
@ -1555,6 +1556,7 @@
/usr/local/lib/libssh2.a,
"-lcrypto",
"-lssl",
"-lcurl",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.libgit2.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftGit2;

View File

@ -0,0 +1,50 @@
//
// Credentials.swift
// SwiftGit2
//
// Created by Tom Booth on 29/02/2016.
// Copyright © 2016 GitHub, Inc. All rights reserved.
//
import Foundation
import Result
private class Wrapper<T> {
let value: T
init(_ value: T) {
self.value = value
}
}
public enum Credentials {
case Default()
case Plaintext(username: String, password: String)
case SSHMemory(username: String, publicKey: String, privateKey: String, passphrase: String)
internal static func fromPointer(pointer: UnsafeMutablePointer<()>) -> Credentials {
return Unmanaged<Wrapper<Credentials>>.fromOpaque(COpaquePointer(pointer)).takeRetainedValue().value
}
internal func toPointer() -> UnsafeMutablePointer<()> {
return UnsafeMutablePointer(Unmanaged.passRetained(Wrapper(self)).toOpaque())
}
}
/// Handle the request of credentials, passing through to a wrapped block after converting the arguments.
/// Converts the result to the correct error code required by libgit2 (0 = success, 1 = rejected setting creds, -1 error)
internal func credentialsCallback(cred: UnsafeMutablePointer<UnsafeMutablePointer<git_cred>>, _: UnsafePointer<Int8>, _: UnsafePointer<Int8>, _: UInt32,
payload: UnsafeMutablePointer<()>) -> Int32 {
let result: Int32
switch Credentials.fromPointer(payload) {
case .Default():
result = git_cred_default_new(cred)
case .Plaintext(let username, let password):
result = git_cred_userpass_plaintext_new(cred, username, password)
case .SSHMemory(let username, let publicKey, let privateKey, let passphrase):
result = git_cred_ssh_key_memory_new(cred, username, publicKey, privateKey, passphrase)
}
return (result != GIT_OK.rawValue) ? -1 : 0
}

View File

@ -9,11 +9,92 @@
import Foundation
import Result
public typealias CheckoutProgressBlock = SG2CheckoutProgressBlock
public typealias CheckoutProgressBlock = (String?, Int, Int) -> Void
/// Helper function used as the libgit2 progress callback in git_checkout_options.
/// This is a function with a type signature of git_checkout_progress_cb.
private func checkoutProgressCallback(path: UnsafePointer<Int8>, completed_steps: Int, total_steps: Int, payload: UnsafeMutablePointer<Void>) -> Void {
if (payload != nil) {
let buffer = UnsafeMutablePointer<CheckoutProgressBlock>(payload)
let block: CheckoutProgressBlock
if completed_steps < total_steps {
block = buffer.memory
} else {
block = buffer.move()
buffer.dealloc(1)
}
block(String.fromCString(path), completed_steps, total_steps);
}
}
/// Helper function for initializing libgit2 git_checkout_options.
///
/// :param: strategy The strategy to be used when checking out the repo, see CheckoutStrategy
/// :param: progress A block that's called with the progress of the checkout.
/// :returns: Returns a git_checkout_options struct with the progress members set.
private func checkoutOptions(strategy: CheckoutStrategy, progress: CheckoutProgressBlock? = nil) -> git_checkout_options {
// Do this because GIT_CHECKOUT_OPTIONS_INIT is unavailable in swift
let pointer = UnsafeMutablePointer<git_checkout_options>.alloc(1)
git_checkout_init_options(pointer, UInt32(GIT_CHECKOUT_OPTIONS_VERSION))
var options = pointer.move()
pointer.dealloc(1)
options.checkout_strategy = strategy.git_checkout_strategy.rawValue
if progress != nil {
options.progress_cb = checkoutProgressCallback
let blockPointer = UnsafeMutablePointer<CheckoutProgressBlock>.alloc(1)
blockPointer.initialize(progress!)
options.progress_payload = UnsafeMutablePointer<Void>(blockPointer)
}
return options
}
private func fetchOptions(credentials: Credentials) -> git_fetch_options {
let pointer = UnsafeMutablePointer<git_fetch_options>.alloc(1)
git_fetch_init_options(pointer, UInt32(GIT_FETCH_OPTIONS_VERSION))
var options = pointer.move()
pointer.dealloc(1)
options.callbacks.payload = credentials.toPointer()
options.callbacks.credentials = credentialsCallback
return options
}
private func cloneOptions(bare: Bool = false, localClone: Bool = false, fetchOptions: git_fetch_options? = nil,
checkoutOptions: git_checkout_options? = nil) -> git_clone_options {
let pointer = UnsafeMutablePointer<git_clone_options>.alloc(1)
git_clone_init_options(pointer, UInt32(GIT_CLONE_OPTIONS_VERSION))
var options = pointer.move()
pointer.dealloc(1)
options.bare = bare ? 1 : 0
if localClone {
options.local = GIT_CLONE_NO_LOCAL
}
if let checkoutOptions = checkoutOptions {
options.checkout_opts = checkoutOptions
}
if let fetchOptions = fetchOptions {
options.fetch_opts = fetchOptions
}
return options
}
/// A git repository.
final public class Repository {
// MARK: - Creating Repositories
/// Load the repository at the given URL.
@ -32,6 +113,36 @@ final public class Repository {
let repository = Repository(pointer)
return Result.Success(repository)
}
/// Clone the repository from a given URL.
///
/// remoteURL - The URL of the remote repository
/// localURL - The URL to clone the remote repository into
/// localClone - Will not bypass the git-aware transport, even if remote is local.
/// bare - Clone remote as a bare repository.
/// credentials - Credentials to be used when connecting to the remote.
/// checkoutStrategy - The checkout strategy to use, if being checked out.
/// checkoutProgress - A block that's called with the progress of the checkout.
///
/// Returns a `Result` with a `Repository` or an error.
class public func cloneFromURL(remoteURL: NSURL, toURL: NSURL, localClone: Bool = false, bare: Bool = false,
credentials: Credentials = .Default(), checkoutStrategy: CheckoutStrategy = .Safe, checkoutProgress: CheckoutProgressBlock? = nil) -> Result<Repository, NSError> {
var options = cloneOptions(
bare, localClone: localClone,
fetchOptions: fetchOptions(credentials),
checkoutOptions: checkoutOptions(checkoutStrategy, progress: checkoutProgress))
var pointer: COpaquePointer = nil
let remoteURLString = remoteURL.isFileReferenceURL() ? remoteURL.path! : remoteURL.absoluteString
let result = git_clone(&pointer, remoteURLString, toURL.fileSystemRepresentation, &options)
if result != GIT_OK.rawValue {
return Result.Failure(libGit2Error(result, libGit2PointOfFailure: "git_clone"))
}
let repository = Repository(pointer)
return Result.Success(repository)
}
// MARK: - Initializers
@ -359,8 +470,7 @@ final public class Repository {
/// :param: progress A block that's called with the progress of the checkout.
/// :returns: Returns a result with void or the error that occurred.
public func checkout(strategy strategy: CheckoutStrategy, progress: CheckoutProgressBlock? = nil) -> Result<(), NSError> {
var options = SG2CheckoutOptions(progress)
options.checkout_strategy = strategy.git_checkout_strategy.rawValue
var options = checkoutOptions(strategy, progress: progress)
let result = git_checkout_head(self.pointer, &options)
if result != GIT_OK.rawValue {

View File

@ -15,11 +15,3 @@ FOUNDATION_EXPORT double SwiftGit2VersionNumber;
FOUNDATION_EXPORT const unsigned char SwiftGit2VersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <SwiftGit2/PublicHeader.h>
#import "git2.h"
typedef void (^SG2CheckoutProgressBlock)(NSString * __nullable, NSUInteger, NSUInteger);
/// A C function for working with Libgit2. This shouldn't be called directly. It's an
/// implementation detail that, unfortunately, leaks through to the public headers.
extern git_checkout_options SG2CheckoutOptions(SG2CheckoutProgressBlock __nullable progress);

View File

@ -7,30 +7,9 @@
//
#import "SwiftGit2.h"
#import "git2.h"
__attribute__((constructor))
static void SwiftGit2Init(void) {
git_libgit2_init();
}
static void SG2CheckoutProgressCallback(const char *path, size_t completed_steps, size_t total_steps, void *payload) {
if (payload == NULL) return;
SG2CheckoutProgressBlock block = (__bridge SG2CheckoutProgressBlock)payload;
block((path == nil ? nil : @(path)), completed_steps, total_steps);
}
git_checkout_options SG2CheckoutOptions(SG2CheckoutProgressBlock progress) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
git_checkout_options result = GIT_CHECKOUT_OPTIONS_INIT;
#pragma clang diagnostic pop
if (progress != nil) {
result.progress_cb = SG2CheckoutProgressCallback;
result.progress_payload = (__bridge void *)[progress copy];
}
return result;
}

View File

@ -36,7 +36,6 @@ framework module SwiftGit2 {
header "git2/pack.h"
header "git2/patch.h"
header "git2/pathspec.h"
header "git2/push.h"
header "git2/rebase.h"
header "git2/refdb.h"
header "git2/reflog.h"

View File

@ -29,6 +29,91 @@ class RepositorySpec: QuickSpec {
)))
}
}
describe("Repository.Type.clone()") {
it("should handle local clones") {
let remoteRepo = Fixtures.simpleRepository
let localURL = self.temporaryURLForPurpose("local-clone")
let result = Repository.cloneFromURL(remoteRepo.directoryURL!, toURL: localURL, localClone: true)
expect(result).to(haveSucceeded())
if case .Success(let clonedRepo) = result {
expect(clonedRepo.directoryURL).notTo(beNil())
}
}
it("should handle bare clones") {
let remoteRepo = Fixtures.simpleRepository
let localURL = self.temporaryURLForPurpose("bare-clone")
let result = Repository.cloneFromURL(remoteRepo.directoryURL!, toURL: localURL, localClone: true, bare: true)
expect(result).to(haveSucceeded())
if case .Success(let clonedRepo) = result {
expect(clonedRepo.directoryURL).to(beNil())
}
}
it("should have set a valid remote url") {
let remoteRepo = Fixtures.simpleRepository
let localURL = self.temporaryURLForPurpose("valid-remote-clone")
let cloneResult = Repository.cloneFromURL(remoteRepo.directoryURL!, toURL: localURL, localClone: true)
expect(cloneResult).to(haveSucceeded())
if case .Success(let clonedRepo) = cloneResult {
let remoteResult = clonedRepo.remoteWithName("origin")
expect(remoteResult).to(haveSucceeded())
if case .Success(let remote) = remoteResult {
expect(remote.URL).to(equal(remoteRepo.directoryURL?.absoluteString))
}
}
}
it("should be able to clone a remote repository") {
let remoteRepoURL = NSURL(string: "https://github.com/libgit2/libgit2.github.com.git")
let localURL = self.temporaryURLForPurpose("public-remote-clone")
let cloneResult = Repository.cloneFromURL(remoteRepoURL!, toURL: localURL)
expect(cloneResult).to(haveSucceeded())
if case .Success(let clonedRepo) = cloneResult {
let remoteResult = clonedRepo.remoteWithName("origin")
expect(remoteResult).to(haveSucceeded())
if case .Success(let remote) = remoteResult {
expect(remote.URL).to(equal(remoteRepoURL?.absoluteString))
}
}
}
let env = NSProcessInfo.processInfo().environment
if let privateRepo = env["SG2TestPrivateRepo"], gitUsername = env["SG2TestUsername"], publicKey = env["SG2TestPublicKey"],
privateKey = env["SG2TestPrivateKey"], passphrase = env["SG2TestPassphrase"] {
it("should be able to clone a remote repository requiring credentials") {
let remoteRepoURL = NSURL(string: privateRepo)
let localURL = self.temporaryURLForPurpose("private-remote-clone")
let cloneResult = Repository.cloneFromURL(remoteRepoURL!, toURL: localURL,
credentials: .SSHMemory(username: gitUsername, publicKey: publicKey, privateKey: privateKey, passphrase: passphrase))
expect(cloneResult).to(haveSucceeded())
if case .Success(let clonedRepo) = cloneResult {
let remoteResult = clonedRepo.remoteWithName("origin")
expect(remoteResult).to(haveSucceeded())
if case .Success(let remote) = remoteResult {
expect(remote.URL).to(equal(remoteRepoURL?.absoluteString))
}
}
}
}
}
describe("Repository.blobWithOID()") {
it("should return the commit if it exists") {
@ -475,10 +560,24 @@ class RepositorySpec: QuickSpec {
let HEAD = repo.HEAD().value
expect(HEAD?.longName).to(equal("HEAD"))
expect(HEAD?.oid).to(equal(oid))
expect(repo.checkout(repo.localBranchWithName("master").value!, strategy: CheckoutStrategy.None)).to(haveSucceeded())
expect(repo.HEAD().value?.shortName).to(equal("master"))
}
it("should call block on progress") {
let repo = Fixtures.simpleRepository
let oid = OID(string: "315b3f344221db91ddc54b269f3c9af422da0f2e")!
expect(repo.HEAD().value?.shortName).to(equal("master"))
expect(repo.checkout(oid, strategy: .None, progress: { (path, completedSteps, totalSteps) -> Void in
expect(completedSteps).to(beLessThanOrEqualTo(totalSteps))
})).to(haveSucceeded())
let HEAD = repo.HEAD().value
expect(HEAD?.longName).to(equal("HEAD"))
expect(HEAD?.oid).to(equal(oid))
}
}
describe("Repository.checkout(ReferenceType)") {
@ -496,4 +595,10 @@ class RepositorySpec: QuickSpec {
}
}
}
func temporaryURLForPurpose(purpose: String) -> NSURL {
let globallyUniqueString = NSProcessInfo.processInfo().globallyUniqueString
let path = "\(NSTemporaryDirectory())\(globallyUniqueString)_\(purpose)"
return NSURL(fileURLWithPath: path)
}
}

View File

@ -10,9 +10,12 @@ config ()
{
# A whitespace-separated list of executables that must be present and locatable.
# These will each be installed through Homebrew if not found.
: ${REQUIRED_TOOLS="xctool cmake libssh2 libtool autoconf automake pkg-config"}
: ${REQUIRED_TOOLS="cmake libssh2 libtool autoconf automake pkg-config"}
: ${REQUIRED_GEMS="xcpretty"}
export REQUIRED_TOOLS
export REQUIRED_GEMS
}
##
@ -102,6 +105,11 @@ check_deps ()
sudo ln -s "$brew_prefix/$product" "$destination"
done
fi
for gem in $REQUIRED_GEMS
do
gem install "$gem"
done
}
bootstrap_submodule ()