Skip to content

Commit

Permalink
Merge pull request SwiftGit2#60 from drkibitz/feature/remove-pub-impl…
Browse files Browse the repository at this point in the history
…-detail

Remove the implementation detail leak, implemented in swift
  • Loading branch information
mdiep committed Apr 2, 2016
2 parents fe02162 + 86fcebd commit b8885e6
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 32 deletions.
41 changes: 39 additions & 2 deletions SwiftGit2/Repository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,44 @@
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 got_checkout_options.
///
/// :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(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)

if progress != nil {
options.progress_cb = checkoutProgressCallback
let blockPointer = UnsafeMutablePointer<CheckoutProgressBlock>.alloc(1)
blockPointer.initialize(progress!)
options.progress_payload = UnsafeMutablePointer<Void>(blockPointer)
}

return options
}

/// A git repository.
final public class Repository {
Expand Down Expand Up @@ -359,7 +396,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)
var options = checkoutOptions(progress)
options.checkout_strategy = strategy.git_checkout_strategy.rawValue

let result = git_checkout_head(self.pointer, &options)
Expand Down
8 changes: 0 additions & 8 deletions SwiftGit2/SwiftGit2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
23 changes: 1 addition & 22 deletions SwiftGit2/SwiftGit2.m
Original file line number Diff line number Diff line change
Expand Up @@ -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_retained void *)[progress copy];
}

return result;
}

0 comments on commit b8885e6

Please sign in to comment.