Gift provides Swift bindings to the libgit2 library.
That means you can clone a Git repository, list its commits, or even make a commit of your own--all from within your Swift program.
For example, we can grab the latest commit message of this repository:
let url = NSURL(fileURLWithPath: "/Users/modocache/Gift")!
let latestCommitMessage = openRepository(url)
.flatMap { $0.headReference }
.flatMap { $0.commit }
.flatMap { $0.message }
Gift returns result objects for any operation that might fail. The type
of lastCommitMessage
above is Result<String, NSError>
. If every
operation succeeded, you can access the commit message String
. But if
any of the operations failed, you'll have an NSError
that describes
what went wrong.
You can list all branches in a repository. Gift uses ReactiveCocoa to represent a sequence of values:
repository.branches().start(next: { (reference) in
println("Branch name: \(reference.name)")
})
You can list commits as well:
repository.commits().start { (commit) in
println("Commit message: \(commit.message)")
}
You can order the commits as you please, of course:
let commits = repository.commits(sorting: CommitSorting.Time | CommitSorting.Reverse)
You can make a commit, too:
let tree = repository.index // Grab the index for the repository
.flatMap { $0.add() } // Add any modified entries to that index
.flatMap { $0.writeTree() } // Grab a tree representing the changeset
.flatMap { $0.commit("Zing!") } // Commit
Swift allows Gift to provide default parameters. If you want to use the default behavior, you can easily clone a remote repository:
let remoteURL = NSURL(string: "git://git.libssh2.org/libssh2.git")!
let destinationURL = NSURL(fileURLWithPath: "/Users/modocache/libssh2")!
let repository = cloneRepository(remoteURL, destinationURL)
But you can also customize that behavior and have Gift issue download progress updates:
let options = CloneOptions(
checkoutOptions: CheckoutOptions(
strategy: CheckoutStrategy.SafeCreate,
progressCallback: { (path, completedSteps, totalSteps) in
// ...do something with checkout progress.
}
),
remoteCallbacks: RemoteCallbacks(
transportMessageCallback: { (message) in
// ...do something with messages from remote, like "Compressing objects: 1% (47/4619)"
},
transferProgressCallback: { (progress) in
// ...do something with progress (bytes received, etc.) updates.
})
)
let repository = cloneRepository(remoteURL, destinationURL, options: options)
You'll need to have homebrew installed. If you don't already have CMake installed, run:
$ brew install cmake
Then, to build the dependencies for Gift, just run:
$ rake dependencies build
If it's your first time running the script, it'll take a while--it needs to build static libraries for OpenSSL, libssh2, and libgit2. And that's for both OS X and iOS.
You can test your changes by running:
$ rake
If you see a non-descript error like "Cannot build module Gift", there's an extremely sophisticated workaround: first, remove all the source files from the main and test target you're trying to build.
Then, build the framework. It should work fine (magic, I know). Now that
it builds, revert the removal of the files by running
git checkout -- Gift.xcodeproj
. And voila! Now everything builds fine.
You can find an example iOS app that uses Gift in the
Examples
directory. Using Gift
is (sort of) easy:
- Drag
Gift.xcodeproj
,LlamaKit.xcodeproj
,Quick.xcodeproj
, andNimble.xcodeproj
into your app's workspace. - In the "Link Binary with Libraries" build phase of your app, link your app to Gift.framework.
- Set the “Header Search Paths” (
HEADER_SEARCH_PATHS
) build setting to the correct path for the libgit2 headers in your project. For example, if you added the submodule to your project asExternal/Gift
, you would set this build setting toExternal/Gift/External/libgit2/include
. import Gift
in any Swift file, and you're off to the races!