Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion Sources/SwiftGitX/Collections/ConfigCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public struct ConfigCollection {
/// This is the branch that is checked out when the repository is initialized.
public var defaultBranchName: String {
get throws(SwiftGitXError) {
try initializeRuntimeIfNeeded()
defer { try? shutdownRuntimeIfNeeded() }
Comment thread
ibrahimcetin marked this conversation as resolved.

let configPointer = try self.configPointer()
defer { git_config_free(configPointer) }

Expand Down Expand Up @@ -78,6 +81,9 @@ public struct ConfigCollection {
/// try Repository.config.set("user.email", to: "john.doe@example.com")
/// ```
public func set(_ key: String, to value: String) throws(SwiftGitXError) {
try initializeRuntimeIfNeeded()
defer { try? shutdownRuntimeIfNeeded() }
Comment thread
ibrahimcetin marked this conversation as resolved.

let configPointer = try self.configPointer()
defer { git_config_free(configPointer) }

Expand All @@ -95,6 +101,9 @@ public struct ConfigCollection {
/// All config files will be looked into, in the order of their defined level. A higher level means a higher
/// priority. The first occurrence of the variable will be returned here.
public func string(forKey key: String) throws(SwiftGitXError) -> String? {
try initializeRuntimeIfNeeded()
defer { try? shutdownRuntimeIfNeeded() }
Comment thread
ibrahimcetin marked this conversation as resolved.

let configPointer = try self.configPointer()
defer { git_config_free(configPointer) }

Expand All @@ -117,7 +126,7 @@ public struct ConfigCollection {
///
/// - Important: The caller is responsible for freeing the returned pointer using `git_config_free()`.
private func configPointer() throws(SwiftGitXError) -> OpaquePointer {
try git(operation: .config) {
return try git(operation: .config) {
var configPointer: OpaquePointer?
let status =
if let repositoryPointer {
Expand All @@ -128,4 +137,19 @@ public struct ConfigCollection {
return (configPointer, status)
}
}

/// Initializes the SwiftGitXRuntime if needed.
///
/// While managing global configurations, the runtime may not have been initialized yet.
private func initializeRuntimeIfNeeded() throws(SwiftGitXError) {
if repositoryPointer == nil {
try SwiftGitXRuntime.initialize()
}
}

private func shutdownRuntimeIfNeeded() throws(SwiftGitXError) {
if repositoryPointer == nil {
try SwiftGitXRuntime.shutdown()
}
}
}
52 changes: 37 additions & 15 deletions Sources/SwiftGitX/Repository/Repository+clone.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ extension Repository {
to localURL: URL,
options: CloneOptions = .default
) async throws(SwiftGitXError) -> Repository {
// Initialize the SwiftGitXRuntime
try SwiftGitXRuntime.initialize()
Comment thread
ibrahimcetin marked this conversation as resolved.

// Initialize the clone options
var options = options.gitCloneOptions

Expand All @@ -37,16 +40,24 @@ extension Repository {
Task.isCancelled ? 1 : 0
}

let pointer = try git(operation: .clone) {
// Repository pointer
var pointer: OpaquePointer?
// Perform the clone operation
let status = git_clone(&pointer, remoteURL.absoluteString, localURL.path, &options)
do {
let pointer = try git(operation: .clone) {
// Repository pointer
var pointer: OpaquePointer?
// Perform the clone operation
let status = git_clone(&pointer, remoteURL.absoluteString, localURL.path, &options)

return (pointer, status)
}
return (pointer, status)
}

return Repository(pointer: pointer)
} catch {
// Shutdown the SwiftGitXRuntime
_ = try? SwiftGitXRuntime.shutdown()

return Repository(pointer: pointer)
// Rethrow the error
throw error
}
}

/// Clone a repository from the specified URL to the specified path with a transfer progress handler.
Expand All @@ -65,6 +76,9 @@ extension Repository {
options: CloneOptions = .default,
transferProgressHandler: @escaping TransferProgressHandler
) async throws(SwiftGitXError) -> Repository {
// Initialize the SwiftGitXRuntime
try SwiftGitXRuntime.initialize()
Comment thread
ibrahimcetin marked this conversation as resolved.

// Define the transferProgress callback
let transferProgress: git_indexer_progress_cb = { stats, payload in
guard let stats = stats?.pointee,
Expand Down Expand Up @@ -105,13 +119,21 @@ extension Repository {
// Set the transferProgressHandler as the payload
options.fetch_opts.callbacks.payload = UnsafeMutableRawPointer(transferProgressHandlerPointer)

// Perform the clone operation
let pointer = try git(operation: .clone) {
var pointer: OpaquePointer?
let status = git_clone(&pointer, remoteURL.absoluteString, localURL.path, &options)
return (pointer, status)
}
do {
// Perform the clone operation
let pointer = try git(operation: .clone) {
var pointer: OpaquePointer?
let status = git_clone(&pointer, remoteURL.absoluteString, localURL.path, &options)
return (pointer, status)
}

return Repository(pointer: pointer)
} catch {
// Shutdown the SwiftGitXRuntime
_ = try? SwiftGitXRuntime.shutdown()

return Repository(pointer: pointer)
// Rethrow the error
throw error
}
}
}
60 changes: 47 additions & 13 deletions Sources/SwiftGitX/Repository/Repository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public final class Repository: Sendable {
///
/// The `path` argument must point to either an existing working directory, or a `.git` repository folder to open.
public init(at path: URL, createIfNotExists: Bool = true) throws(SwiftGitXError) {
// Initialize the SwiftGitXRuntime
try SwiftGitXRuntime.initialize()
Comment thread
ibrahimcetin marked this conversation as resolved.

let pointerOpen = try? git(operation: .repositoryOpen) {
var pointer: OpaquePointer?
// Try to open the repository at the specified path
Expand All @@ -50,6 +53,10 @@ public final class Repository: Sendable {

self.pointer = pointerCreate
} else {
// Shutdown the SwiftGitXRuntime
_ = try? SwiftGitXRuntime.shutdown()

// If the repository does not exist and createIfNotExists is false, throw an error
throw SwiftGitXError(
code: .notFound, category: .repository,
message: "Repository not found at \(path.path)"
Expand All @@ -58,7 +65,11 @@ public final class Repository: Sendable {
}

deinit {
// Free the repository pointer
git_repository_free(pointer)

// Shutdown the SwiftGitXRuntime
_ = try? SwiftGitXRuntime.shutdown()
}
}

Expand Down Expand Up @@ -163,13 +174,25 @@ extension Repository {
///
/// - Returns: The repository at the specified path.
public static func open(at path: URL) throws(SwiftGitXError) -> Repository {
let pointer = try git(operation: .repositoryOpen) {
var pointer: OpaquePointer?
let status = git_repository_open(&pointer, path.path)
return (pointer, status)
}
// Initialize the SwiftGitXRuntime
try SwiftGitXRuntime.initialize()
Comment thread
ibrahimcetin marked this conversation as resolved.

do {
// Open the repository at the specified path
let pointer = try git(operation: .repositoryOpen) {
var pointer: OpaquePointer?
let status = git_repository_open(&pointer, path.path)
return (pointer, status)
}

return Repository(pointer: pointer)
return Repository(pointer: pointer)
} catch {
// Shutdown the SwiftGitXRuntime
_ = try? SwiftGitXRuntime.shutdown()

// Rethrow the error
throw error
}
}

/// Create a new repository at the specified path.
Expand All @@ -180,14 +203,25 @@ extension Repository {
///
/// - Returns: The repository at the specified path.
public static func create(at path: URL, isBare: Bool = false) throws(SwiftGitXError) -> Repository {
// Create a new repository at the specified URL
let pointer = try git(operation: .repositoryCreate) {
var pointer: OpaquePointer?
let status = git_repository_init(&pointer, path.path, isBare ? 1 : 0)
return (pointer, status)
}
// Initialize the SwiftGitXRuntime
try SwiftGitXRuntime.initialize()
Comment thread
ibrahimcetin marked this conversation as resolved.

return Repository(pointer: pointer)
do {
// Create a new repository at the specified URL
let pointer = try git(operation: .repositoryCreate) {
var pointer: OpaquePointer?
let status = git_repository_init(&pointer, path.path, isBare ? 1 : 0)
return (pointer, status)
}

return Repository(pointer: pointer)
} catch {
// Shutdown the SwiftGitXRuntime
_ = try? SwiftGitXRuntime.shutdown()

// Rethrow the error
throw error
}
}
}

Expand Down
8 changes: 0 additions & 8 deletions Tests/SwiftGitXTests/SwiftGitXTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,6 @@ class SwiftGitXTest {

return directory
}

init() throws {
try SwiftGitXRuntime.initialize()
}

deinit {
_ = try? SwiftGitXRuntime.shutdown()
}
}

// Test the SwiftGitXRuntime enum to initialize and shutdown the library
Expand Down