#![feature(unsafe_destructor)]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]
extern crate libc;
extern crate url;
extern crate "libgit2-sys" as raw;
use std::ffi::{self, CString};
use std::fmt;
use std::mem;
use std::str;
use std::sync::{Once, ONCE_INIT};
pub use blob::Blob;
pub use branch::{Branch, Branches};
pub use buf::Buf;
pub use commit::{Commit, Parents};
pub use config::{Config, ConfigEntry, ConfigEntries};
pub use cred::{Cred, CredentialHelper};
pub use diff::{Diff, DiffDelta, DiffFile, DiffOptions, Deltas};
pub use diff::{DiffLine, DiffHunk, DiffStats};
pub use error::Error;
pub use index::{Index, IndexEntry, IndexEntries, IndexMatchedPath};
pub use note::{Note, Notes};
pub use object::Object;
pub use oid::Oid;
pub use pathspec::{Pathspec, PathspecMatchList, PathspecFailedEntries};
pub use pathspec::{PathspecDiffEntries, PathspecEntries};
pub use push::{Push, PushStatus};
pub use reference::{Reference, References, ReferenceNames};
pub use refspec::Refspec;
pub use remote::{Remote, Refspecs, RemoteHead};
pub use remote_callbacks::{RemoteCallbacks, Credentials, TransferProgress};
pub use remote_callbacks::{TransportMessage, Progress, UpdateTips};
pub use repo::{Repository, RepositoryInitOptions};
pub use revspec::Revspec;
pub use revwalk::Revwalk;
pub use signature::Signature;
pub use status::{StatusOptions, Statuses, StatusIter, StatusEntry, StatusShow};
pub use string_array::{StringArray, StringArrayItems, StringArrayBytes};
pub use submodule::Submodule;
pub use tag::Tag;
pub use time::{Time, IndexTime};
pub use tree::{Tree, TreeEntry};
#[derive(PartialEq, Eq, Clone, Show, Copy)]
pub enum ErrorCode {
GenericError,
NotFound,
Exists,
Ambiguous,
BufSize,
User,
BareRepo,
UnbornBranch,
Unmerged,
NotFastForward,
InvalidSpec,
MergeConflict,
Locked,
Modified,
}
#[derive(PartialEq, Eq, Clone, Show, Copy)]
#[allow(missing_docs)]
pub enum RepositoryState {
Clean,
Merge,
Revert,
CherryPick,
Bisect,
Rebase,
RebaseInteractive,
RebaseMerge,
ApplyMailbox,
ApplyMailboxOrRebase,
}
#[derive(Copy)]
pub enum Direction {
Fetch,
Push,
}
#[derive(Copy)]
pub enum ResetType {
Soft,
Mixed,
Hard,
}
#[derive(PartialEq, Eq, Copy)]
pub enum ObjectType {
Any,
Commit,
Tree,
Blob,
Tag,
}
#[derive(PartialEq, Eq, Show, Copy)]
pub enum BranchType {
Local,
Remote,
}
#[derive(PartialEq, Eq, Show, Copy)]
pub enum ConfigLevel {
System,
XDG,
Global,
Local,
App,
Highest,
}
bitflags! {
#[doc = "
Orderings that may be specified for Revwalk iteration.
"]
flags Sort: uint {
const SORT_NONE = raw::GIT_SORT_NONE as uint,
const SORT_TOPOLOGICAL = raw::GIT_SORT_TOPOLOGICAL as uint,
const SORT_TIME = raw::GIT_SORT_TIME as uint,
const SORT_REVERSE = raw::GIT_SORT_REVERSE as uint,
}
}
bitflags! {
#[doc = "
Types of credentials that can be requested by a credential callback.
"]
flags CredentialType: uint {
const USER_PASS_PLAINTEXT = raw::GIT_CREDTYPE_USERPASS_PLAINTEXT as uint,
const SSH_KEY = raw::GIT_CREDTYPE_SSH_KEY as uint,
const SSH_CUSTOM = raw::GIT_CREDTYPE_SSH_CUSTOM as uint,
const DEFAULT = raw::GIT_CREDTYPE_DEFAULT as uint,
const SSH_INTERACTIVE = raw::GIT_CREDTYPE_SSH_INTERACTIVE as uint,
}
}
bitflags! {
#[doc = "
Flags for APIs that add files matching pathspec
"]
flags IndexAddOption: u32 {
const ADD_DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32,
const ADD_FORCE = raw::GIT_INDEX_ADD_FORCE as u32,
const ADD_DISABLE_PATHSPEC_MATCH =
raw::GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH as u32,
const ADD_CHECK_PATHSPEC = raw::GIT_INDEX_ADD_CHECK_PATHSPEC as u32,
}
}
bitflags! {
#[doc = "
Flags for the return value of `Repository::revparse`
"]
flags RevparseMode: u32 {
const REVPARSE_SINGLE = raw::GIT_REVPARSE_SINGLE as u32,
const REVPARSE_RANGE = raw::GIT_REVPARSE_RANGE as u32,
const REVPARSE_MERGE_BASE = raw::GIT_REVPARSE_MERGE_BASE as u32,
}
}
#[macro_use]
mod call;
mod panic;
mod util;
pub mod build;
mod blob;
mod branch;
mod buf;
mod commit;
mod config;
mod cred;
mod diff;
mod error;
mod index;
mod note;
mod object;
mod oid;
mod pathspec;
mod push;
mod reference;
mod refspec;
mod remote;
mod remote_callbacks;
mod repo;
mod revspec;
mod revwalk;
mod signature;
mod status;
mod string_array;
mod submodule;
mod tag;
mod time;
mod tree;
#[cfg(test)] mod test;
fn init() {
static INIT: Once = ONCE_INIT;
INIT.call_once(|| unsafe {
raw::openssl_init();
let r = raw::git_libgit2_init();
assert!(r >= 0,
"couldn't initialize the libgit2 library: {}", r);
assert_eq!(libc::atexit(shutdown), 0);
});
extern fn shutdown() { unsafe { raw::git_libgit2_shutdown() } }
}
unsafe fn opt_bytes<'a, T>(_: &'a T,
c: *const libc::c_char) -> Option<&'a [u8]> {
if c.is_null() {
None
} else {
Some(mem::transmute(ffi::c_str_to_bytes(&c)))
}
}
impl ObjectType {
pub fn str(&self) -> &'static str {
unsafe {
let ptr = call!(raw::git_object_type2string(*self));
let bytes = ffi::c_str_to_bytes(&ptr);
let s = str::from_utf8(bytes).unwrap();
mem::transmute::<&str, &'static str>(s)
}
}
pub fn is_loose(&self) -> bool {
unsafe { (call!(raw::git_object_typeisloose(*self)) == 1) }
}
pub fn from_raw(raw: raw::git_otype) -> Option<ObjectType> {
match raw {
raw::GIT_OBJ_ANY => Some(ObjectType::Any),
raw::GIT_OBJ_BAD => None,
raw::GIT_OBJ__EXT1 => None,
raw::GIT_OBJ_COMMIT => Some(ObjectType::Commit),
raw::GIT_OBJ_TREE => Some(ObjectType::Tree),
raw::GIT_OBJ_BLOB => Some(ObjectType::Blob),
raw::GIT_OBJ_TAG => Some(ObjectType::Tag),
raw::GIT_OBJ__EXT2 => None,
raw::GIT_OBJ_OFS_DELTA => None,
raw::GIT_OBJ_REF_DELTA => None,
}
}
pub fn raw(&self) -> raw::git_otype {
call::convert(self)
}
pub fn from_str(s: &str) -> Option<ObjectType> {
let s = CString::from_slice(s.as_bytes());
let raw = unsafe { call!(raw::git_object_string2type(s)) };
ObjectType::from_raw(raw)
}
}
impl fmt::Show for ObjectType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.str().fmt(f)
}
}
impl ConfigLevel {
pub fn from_raw(raw: raw::git_config_level_t) -> ConfigLevel {
match raw {
raw::GIT_CONFIG_LEVEL_SYSTEM => ConfigLevel::System,
raw::GIT_CONFIG_LEVEL_XDG => ConfigLevel::XDG,
raw::GIT_CONFIG_LEVEL_GLOBAL => ConfigLevel::Global,
raw::GIT_CONFIG_LEVEL_LOCAL => ConfigLevel::Local,
raw::GIT_CONFIG_LEVEL_APP => ConfigLevel::App,
raw::GIT_CONFIG_HIGHEST_LEVEL => ConfigLevel::Highest,
}
}
}
bitflags! {
#[doc = "
Flags for repository status
"]
flags Status: u32 {
const STATUS_CURRENT = raw::GIT_STATUS_CURRENT as u32,
const STATUS_INDEX_NEW = raw::GIT_STATUS_INDEX_NEW as u32,
const STATUS_INDEX_MODIFIED = raw::GIT_STATUS_INDEX_MODIFIED as u32,
const STATUS_INDEX_DELETED = raw::GIT_STATUS_INDEX_DELETED as u32,
const STATUS_INDEX_RENAMED = raw::GIT_STATUS_INDEX_RENAMED as u32,
const STATUS_INDEX_TYPECHANGE = raw::GIT_STATUS_INDEX_TYPECHANGE as u32,
const STATUS_WT_NEW = raw::GIT_STATUS_WT_NEW as u32,
const STATUS_WT_MODIFIED = raw::GIT_STATUS_WT_MODIFIED as u32,
const STATUS_WT_DELETED = raw::GIT_STATUS_WT_DELETED as u32,
const STATUS_WT_TYPECHANGE = raw::GIT_STATUS_WT_TYPECHANGE as u32,
const STATUS_WT_RENAMED = raw::GIT_STATUS_WT_RENAMED as u32,
const STATUS_IGNORED = raw::GIT_STATUS_IGNORED as u32,
}
}
bitflags! {
#[doc = "
Mode options for RepositoryInitOptions
"]
flags RepositoryInitMode: u32 {
#[doc = "Use permissions configured by umask - the default"]
const REPOSITORY_INIT_SHARED_UMASK =
raw::GIT_REPOSITORY_INIT_SHARED_UMASK as u32,
#[doc = "Use `--shared=group` behavior, chmod'ing the new repo to be \
group writable and \"g+sx\" for sticky group assignment"]
const REPOSITORY_INIT_SHARED_GROUP =
raw::GIT_REPOSITORY_INIT_SHARED_GROUP as u32,
#[doc = "Use `--shared=all` behavior, adding world readability."]
const REPOSITORY_INIT_SHARED_ALL =
raw::GIT_REPOSITORY_INIT_SHARED_ALL as u32,
}
}
#[derive(Copy)]
pub enum Delta {
Unmodified,
Added,
Deleted,
Modified,
Renamed,
Copied,
Ignored,
Untracked,
Typechange,
Unreadable,
}
bitflags! {
#[doc = r#"
Return codes for submodule status.
A combination of these flags will be returned to describe the status of a
submodule. Depending on the "ignore" property of the submodule, some of
the flags may never be returned because they indicate changes that are
supposed to be ignored.
Submodule info is contained in 4 places: the HEAD tree, the index, config
files (both .git/config and .gitmodules), and the working directory. Any
or all of those places might be missing information about the submodule
depending on what state the repo is in. We consider all four places to
build the combination of status flags.
There are four values that are not really status, but give basic info
about what sources of submodule data are available. These will be
returned even if ignore is set to "ALL".
* IN_HEAD - superproject head contains submodule
* IN_INDEX - superproject index contains submodule
* IN_CONFIG - superproject gitmodules has submodule
* IN_WD - superproject workdir has submodule
The following values will be returned so long as ignore is not "ALL".
* INDEX_ADDED - in index, not in head
* INDEX_DELETED - in head, not in index
* INDEX_MODIFIED - index and head don't match
* WD_UNINITIALIZED - workdir contains empty directory
* WD_ADDED - in workdir, not index
* WD_DELETED - in index, not workdir
* WD_MODIFIED - index and workdir head don't match
The following can only be returned if ignore is "NONE" or "UNTRACKED".
* WD_INDEX_MODIFIED - submodule workdir index is dirty
* WD_WD_MODIFIED - submodule workdir has modified files
Lastly, the following will only be returned for ignore "NONE".
* WD_UNTRACKED - wd contains untracked files
"#]
flags SubmoduleStatus: u32 {
const SUBMODULE_STATUS_IN_HEAD =
raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32,
const SUBMODULE_STATUS_IN_INDEX =
raw::GIT_SUBMODULE_STATUS_IN_INDEX as u32,
const SUBMODULE_STATUS_IN_CONFIG =
raw::GIT_SUBMODULE_STATUS_IN_CONFIG as u32,
const SUBMODULE_STATUS_IN_WD =
raw::GIT_SUBMODULE_STATUS_IN_WD as u32,
const SUBMODULE_STATUS_INDEX_ADDED =
raw::GIT_SUBMODULE_STATUS_INDEX_ADDED as u32,
const SUBMODULE_STATUS_INDEX_DELETED =
raw::GIT_SUBMODULE_STATUS_INDEX_DELETED as u32,
const SUBMODULE_STATUS_INDEX_MODIFIED =
raw::GIT_SUBMODULE_STATUS_INDEX_MODIFIED as u32,
const SUBMODULE_STATUS_WD_UNINITIALIZED =
raw::GIT_SUBMODULE_STATUS_WD_UNINITIALIZED as u32,
const SUBMODULE_STATUS_WD_ADDED =
raw::GIT_SUBMODULE_STATUS_WD_ADDED as u32,
const SUBMODULE_STATUS_WD_DELETED =
raw::GIT_SUBMODULE_STATUS_WD_DELETED as u32,
const SUBMODULE_STATUS_WD_MODIFIED =
raw::GIT_SUBMODULE_STATUS_WD_MODIFIED as u32,
const SUBMODULE_STATUS_WD_INDEX_MODIFIED =
raw::GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED as u32,
const SUBMODULE_STATUS_WD_WD_MODIFIED =
raw::GIT_SUBMODULE_STATUS_WD_WD_MODIFIED as u32,
const SUBMODULE_STATUS_WD_UNTRACKED =
raw::GIT_SUBMODULE_STATUS_WD_UNTRACKED as u32,
}
}
bitflags! {
#[doc = r#"
"#]
flags PathspecFlags: u32 {
const PATHSPEC_DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32,
const PATHSPEC_IGNORE_CASE = raw::GIT_PATHSPEC_IGNORE_CASE as u32,
const PATHSPEC_USE_CASE = raw::GIT_PATHSPEC_USE_CASE as u32,
const PATHSPEC_NO_GLOB = raw::GIT_PATHSPEC_NO_GLOB as u32,
const PATHSPEC_NO_MATCH_ERROR = raw::GIT_PATHSPEC_NO_MATCH_ERROR as u32,
const PATHSPEC_FIND_FAILURES = raw::GIT_PATHSPEC_FIND_FAILURES as u32,
const PATHSPEC_FAILURES_ONLY = raw::GIT_PATHSPEC_FAILURES_ONLY as u32,
}
}
#[derive(Copy)]
pub enum DiffFormat {
Patch,
PatchHeader,
Raw,
NameOnly,
NameStatus,
}
#[cfg(test)]
mod tests {
use super::ObjectType;
#[test]
fn convert() {
assert_eq!(ObjectType::Blob.str(), "blob");
assert_eq!(ObjectType::from_str("blob"), Some(ObjectType::Blob));
assert!(ObjectType::Blob.is_loose());
}
}