]> git.proxmox.com Git - rustc.git/blob - vendor/git2/src/lib.rs
New upstream version 1.72.1+dfsg1
[rustc.git] / vendor / git2 / src / lib.rs
1 //! # libgit2 bindings for Rust
2 //!
3 //! This library contains bindings to the [libgit2][1] C library which is used
4 //! to manage git repositories. The library itself is a work in progress and is
5 //! likely lacking some bindings here and there, so be warned.
6 //!
7 //! [1]: https://libgit2.github.com/
8 //!
9 //! The git2-rs library strives to be as close to libgit2 as possible, but also
10 //! strives to make using libgit2 as safe as possible. All resource management
11 //! is automatic as well as adding strong types to all interfaces (including
12 //! `Result`)
13 //!
14 //! ## Creating a `Repository`
15 //!
16 //! The `Repository` is the source from which almost all other objects in git-rs
17 //! are spawned. A repository can be created through opening, initializing, or
18 //! cloning.
19 //!
20 //! ### Initializing a new repository
21 //!
22 //! The `init` method will create a new repository, assuming one does not
23 //! already exist.
24 //!
25 //! ```no_run
26 //! # #![allow(unstable)]
27 //! use git2::Repository;
28 //!
29 //! let repo = match Repository::init("/path/to/a/repo") {
30 //! Ok(repo) => repo,
31 //! Err(e) => panic!("failed to init: {}", e),
32 //! };
33 //! ```
34 //!
35 //! ### Opening an existing repository
36 //!
37 //! ```no_run
38 //! # #![allow(unstable)]
39 //! use git2::Repository;
40 //!
41 //! let repo = match Repository::open("/path/to/a/repo") {
42 //! Ok(repo) => repo,
43 //! Err(e) => panic!("failed to open: {}", e),
44 //! };
45 //! ```
46 //!
47 //! ### Cloning an existing repository
48 //!
49 //! ```no_run
50 //! # #![allow(unstable)]
51 //! use git2::Repository;
52 //!
53 //! let url = "https://github.com/alexcrichton/git2-rs";
54 //! let repo = match Repository::clone(url, "/path/to/a/repo") {
55 //! Ok(repo) => repo,
56 //! Err(e) => panic!("failed to clone: {}", e),
57 //! };
58 //! ```
59 //!
60 //! To clone using SSH, refer to [RepoBuilder](./build/struct.RepoBuilder.html).
61 //!
62 //! ## Working with a `Repository`
63 //!
64 //! All derivative objects, references, etc are attached to the lifetime of the
65 //! source `Repository`, to ensure that they do not outlive the repository
66 //! itself.
67
68 #![doc(html_root_url = "https://docs.rs/git2/0.17")]
69 #![allow(trivial_numeric_casts, trivial_casts)]
70 #![deny(missing_docs)]
71 #![warn(rust_2018_idioms)]
72 #![cfg_attr(test, deny(warnings))]
73
74 use bitflags::bitflags;
75 use libgit2_sys as raw;
76
77 use std::ffi::{CStr, CString};
78 use std::fmt;
79 use std::str;
80 use std::sync::Once;
81
82 pub use crate::apply::{ApplyLocation, ApplyOptions};
83 pub use crate::attr::AttrValue;
84 pub use crate::blame::{Blame, BlameHunk, BlameIter, BlameOptions};
85 pub use crate::blob::{Blob, BlobWriter};
86 pub use crate::branch::{Branch, Branches};
87 pub use crate::buf::Buf;
88 pub use crate::cherrypick::CherrypickOptions;
89 pub use crate::commit::{Commit, Parents};
90 pub use crate::config::{Config, ConfigEntries, ConfigEntry};
91 pub use crate::cred::{Cred, CredentialHelper};
92 pub use crate::describe::{Describe, DescribeFormatOptions, DescribeOptions};
93 pub use crate::diff::{Deltas, Diff, DiffDelta, DiffFile, DiffOptions};
94 pub use crate::diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind};
95 pub use crate::diff::{DiffFindOptions, DiffHunk, DiffLine, DiffLineType, DiffStats};
96 pub use crate::email::{Email, EmailCreateOptions};
97 pub use crate::error::Error;
98 pub use crate::index::{
99 Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath,
100 };
101 pub use crate::indexer::{Indexer, IndexerProgress, Progress};
102 pub use crate::mailmap::Mailmap;
103 pub use crate::mempack::Mempack;
104 pub use crate::merge::{AnnotatedCommit, MergeOptions};
105 pub use crate::message::{
106 message_prettify, message_trailers_bytes, message_trailers_strs, MessageTrailersBytes,
107 MessageTrailersBytesIterator, MessageTrailersStrs, MessageTrailersStrsIterator,
108 DEFAULT_COMMENT_CHAR,
109 };
110 pub use crate::note::{Note, Notes};
111 pub use crate::object::Object;
112 pub use crate::odb::{Odb, OdbObject, OdbPackwriter, OdbReader, OdbWriter};
113 pub use crate::oid::Oid;
114 pub use crate::packbuilder::{PackBuilder, PackBuilderStage};
115 pub use crate::patch::Patch;
116 pub use crate::pathspec::{Pathspec, PathspecFailedEntries, PathspecMatchList};
117 pub use crate::pathspec::{PathspecDiffEntries, PathspecEntries};
118 pub use crate::proxy_options::ProxyOptions;
119 pub use crate::push_update::PushUpdate;
120 pub use crate::rebase::{Rebase, RebaseOperation, RebaseOperationType, RebaseOptions};
121 pub use crate::reference::{Reference, ReferenceNames, References};
122 pub use crate::reflog::{Reflog, ReflogEntry, ReflogIter};
123 pub use crate::refspec::Refspec;
124 pub use crate::remote::{
125 FetchOptions, PushOptions, Refspecs, Remote, RemoteConnection, RemoteHead, RemoteRedirect,
126 };
127 pub use crate::remote_callbacks::{CertificateCheckStatus, Credentials, RemoteCallbacks};
128 pub use crate::remote_callbacks::{TransportMessage, UpdateTips};
129 pub use crate::repo::{Repository, RepositoryInitOptions};
130 pub use crate::revert::RevertOptions;
131 pub use crate::revspec::Revspec;
132 pub use crate::revwalk::Revwalk;
133 pub use crate::signature::Signature;
134 pub use crate::stash::{StashApplyOptions, StashApplyProgressCb, StashCb};
135 pub use crate::status::{StatusEntry, StatusIter, StatusOptions, StatusShow, Statuses};
136 pub use crate::submodule::{Submodule, SubmoduleUpdateOptions};
137 pub use crate::tag::Tag;
138 pub use crate::time::{IndexTime, Time};
139 pub use crate::tracing::{trace_set, TraceLevel};
140 pub use crate::transaction::Transaction;
141 pub use crate::tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult};
142 pub use crate::treebuilder::TreeBuilder;
143 pub use crate::util::IntoCString;
144 pub use crate::version::Version;
145 pub use crate::worktree::{Worktree, WorktreeAddOptions, WorktreeLockStatus, WorktreePruneOptions};
146
147 // Create a convinience method on bitflag struct which checks the given flag
148 macro_rules! is_bit_set {
149 ($name:ident, $flag:expr) => {
150 #[allow(missing_docs)]
151 pub fn $name(&self) -> bool {
152 self.intersects($flag)
153 }
154 };
155 }
156
157 /// An enumeration of possible errors that can happen when working with a git
158 /// repository.
159 // Note: We omit a few native error codes, as they are unlikely to be propagated
160 // to the library user. Currently:
161 //
162 // * GIT_EPASSTHROUGH
163 // * GIT_ITEROVER
164 // * GIT_RETRY
165 #[derive(PartialEq, Eq, Clone, Debug, Copy)]
166 pub enum ErrorCode {
167 /// Generic error
168 GenericError,
169 /// Requested object could not be found
170 NotFound,
171 /// Object exists preventing operation
172 Exists,
173 /// More than one object matches
174 Ambiguous,
175 /// Output buffer too short to hold data
176 BufSize,
177 /// User-generated error
178 User,
179 /// Operation not allowed on bare repository
180 BareRepo,
181 /// HEAD refers to branch with no commits
182 UnbornBranch,
183 /// Merge in progress prevented operation
184 Unmerged,
185 /// Reference was not fast-forwardable
186 NotFastForward,
187 /// Name/ref spec was not in a valid format
188 InvalidSpec,
189 /// Checkout conflicts prevented operation
190 Conflict,
191 /// Lock file prevented operation
192 Locked,
193 /// Reference value does not match expected
194 Modified,
195 /// Authentication error
196 Auth,
197 /// Server certificate is invalid
198 Certificate,
199 /// Patch/merge has already been applied
200 Applied,
201 /// The requested peel operation is not possible
202 Peel,
203 /// Unexpected EOF
204 Eof,
205 /// Invalid operation or input
206 Invalid,
207 /// Uncommitted changes in index prevented operation
208 Uncommitted,
209 /// Operation was not valid for a directory
210 Directory,
211 /// A merge conflict exists and cannot continue
212 MergeConflict,
213 /// Hashsum mismatch in object
214 HashsumMismatch,
215 /// Unsaved changes in the index would be overwritten
216 IndexDirty,
217 /// Patch application failed
218 ApplyFail,
219 /// The object is not owned by the current user
220 Owner,
221 }
222
223 /// An enumeration of possible categories of things that can have
224 /// errors when working with a git repository.
225 #[derive(PartialEq, Eq, Clone, Debug, Copy)]
226 pub enum ErrorClass {
227 /// Uncategorized
228 None,
229 /// Out of memory or insufficient allocated space
230 NoMemory,
231 /// Syscall or standard system library error
232 Os,
233 /// Invalid input
234 Invalid,
235 /// Error resolving or manipulating a reference
236 Reference,
237 /// ZLib failure
238 Zlib,
239 /// Bad repository state
240 Repository,
241 /// Bad configuration
242 Config,
243 /// Regex failure
244 Regex,
245 /// Bad object
246 Odb,
247 /// Invalid index data
248 Index,
249 /// Error creating or obtaining an object
250 Object,
251 /// Network error
252 Net,
253 /// Error manipulating a tag
254 Tag,
255 /// Invalid value in tree
256 Tree,
257 /// Hashing or packing error
258 Indexer,
259 /// Error from SSL
260 Ssl,
261 /// Error involving submodules
262 Submodule,
263 /// Threading error
264 Thread,
265 /// Error manipulating a stash
266 Stash,
267 /// Checkout failure
268 Checkout,
269 /// Invalid FETCH_HEAD
270 FetchHead,
271 /// Merge failure
272 Merge,
273 /// SSH failure
274 Ssh,
275 /// Error manipulating filters
276 Filter,
277 /// Error reverting commit
278 Revert,
279 /// Error from a user callback
280 Callback,
281 /// Error cherry-picking commit
282 CherryPick,
283 /// Can't describe object
284 Describe,
285 /// Error during rebase
286 Rebase,
287 /// Filesystem-related error
288 Filesystem,
289 /// Invalid patch data
290 Patch,
291 /// Error involving worktrees
292 Worktree,
293 /// Hash library error or SHA-1 collision
294 Sha1,
295 /// HTTP error
296 Http,
297 }
298
299 /// A listing of the possible states that a repository can be in.
300 #[derive(PartialEq, Eq, Clone, Debug, Copy)]
301 #[allow(missing_docs)]
302 pub enum RepositoryState {
303 Clean,
304 Merge,
305 Revert,
306 RevertSequence,
307 CherryPick,
308 CherryPickSequence,
309 Bisect,
310 Rebase,
311 RebaseInteractive,
312 RebaseMerge,
313 ApplyMailbox,
314 ApplyMailboxOrRebase,
315 }
316
317 /// An enumeration of the possible directions for a remote.
318 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
319 pub enum Direction {
320 /// Data will be fetched (read) from this remote.
321 Fetch,
322 /// Data will be pushed (written) to this remote.
323 Push,
324 }
325
326 /// An enumeration of the operations that can be performed for the `reset`
327 /// method on a `Repository`.
328 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
329 pub enum ResetType {
330 /// Move the head to the given commit.
331 Soft,
332 /// Soft plus reset the index to the commit.
333 Mixed,
334 /// Mixed plus changes in the working tree are discarded.
335 Hard,
336 }
337
338 /// An enumeration all possible kinds objects may have.
339 #[derive(PartialEq, Eq, Copy, Clone, Debug)]
340 pub enum ObjectType {
341 /// Any kind of git object
342 Any,
343 /// An object which corresponds to a git commit
344 Commit,
345 /// An object which corresponds to a git tree
346 Tree,
347 /// An object which corresponds to a git blob
348 Blob,
349 /// An object which corresponds to a git tag
350 Tag,
351 }
352
353 /// An enumeration of all possible kinds of references.
354 #[derive(PartialEq, Eq, Copy, Clone, Debug)]
355 pub enum ReferenceType {
356 /// A reference which points at an object id.
357 Direct,
358
359 /// A reference which points at another reference.
360 Symbolic,
361 }
362
363 /// An enumeration for the possible types of branches
364 #[derive(PartialEq, Eq, Debug, Copy, Clone)]
365 pub enum BranchType {
366 /// A local branch not on a remote.
367 Local,
368 /// A branch for a remote.
369 Remote,
370 }
371
372 /// An enumeration of the possible priority levels of a config file.
373 ///
374 /// The levels corresponding to the escalation logic (higher to lower) when
375 /// searching for config entries.
376 #[derive(PartialEq, Eq, Debug, Copy, Clone)]
377 pub enum ConfigLevel {
378 /// System-wide on Windows, for compatibility with portable git
379 ProgramData = 1,
380 /// System-wide configuration file, e.g. /etc/gitconfig
381 System,
382 /// XDG-compatible configuration file, e.g. ~/.config/git/config
383 XDG,
384 /// User-specific configuration, e.g. ~/.gitconfig
385 Global,
386 /// Repository specific config, e.g. $PWD/.git/config
387 Local,
388 /// Application specific configuration file
389 App,
390 /// Highest level available
391 Highest = -1,
392 }
393
394 /// Merge file favor options for `MergeOptions` instruct the file-level
395 /// merging functionality how to deal with conflicting regions of the files.
396 #[derive(PartialEq, Eq, Debug, Copy, Clone)]
397 pub enum FileFavor {
398 /// When a region of a file is changed in both branches, a conflict will be
399 /// recorded in the index so that git_checkout can produce a merge file with
400 /// conflict markers in the working directory. This is the default.
401 Normal,
402 /// When a region of a file is changed in both branches, the file created
403 /// in the index will contain the "ours" side of any conflicting region.
404 /// The index will not record a conflict.
405 Ours,
406 /// When a region of a file is changed in both branches, the file created
407 /// in the index will contain the "theirs" side of any conflicting region.
408 /// The index will not record a conflict.
409 Theirs,
410 /// When a region of a file is changed in both branches, the file created
411 /// in the index will contain each unique line from each side, which has
412 /// the result of combining both files. The index will not record a conflict.
413 Union,
414 }
415
416 bitflags! {
417 /// Orderings that may be specified for Revwalk iteration.
418 pub struct Sort: u32 {
419 /// Sort the repository contents in no particular ordering.
420 ///
421 /// This sorting is arbitrary, implementation-specific, and subject to
422 /// change at any time. This is the default sorting for new walkers.
423 const NONE = raw::GIT_SORT_NONE as u32;
424
425 /// Sort the repository contents in topological order (children before
426 /// parents).
427 ///
428 /// This sorting mode can be combined with time sorting.
429 const TOPOLOGICAL = raw::GIT_SORT_TOPOLOGICAL as u32;
430
431 /// Sort the repository contents by commit time.
432 ///
433 /// This sorting mode can be combined with topological sorting.
434 const TIME = raw::GIT_SORT_TIME as u32;
435
436 /// Iterate through the repository contents in reverse order.
437 ///
438 /// This sorting mode can be combined with any others.
439 const REVERSE = raw::GIT_SORT_REVERSE as u32;
440 }
441 }
442
443 impl Sort {
444 is_bit_set!(is_none, Sort::NONE);
445 is_bit_set!(is_topological, Sort::TOPOLOGICAL);
446 is_bit_set!(is_time, Sort::TIME);
447 is_bit_set!(is_reverse, Sort::REVERSE);
448 }
449
450 bitflags! {
451 /// Types of credentials that can be requested by a credential callback.
452 pub struct CredentialType: u32 {
453 #[allow(missing_docs)]
454 const USER_PASS_PLAINTEXT = raw::GIT_CREDTYPE_USERPASS_PLAINTEXT as u32;
455 #[allow(missing_docs)]
456 const SSH_KEY = raw::GIT_CREDTYPE_SSH_KEY as u32;
457 #[allow(missing_docs)]
458 const SSH_MEMORY = raw::GIT_CREDTYPE_SSH_MEMORY as u32;
459 #[allow(missing_docs)]
460 const SSH_CUSTOM = raw::GIT_CREDTYPE_SSH_CUSTOM as u32;
461 #[allow(missing_docs)]
462 const DEFAULT = raw::GIT_CREDTYPE_DEFAULT as u32;
463 #[allow(missing_docs)]
464 const SSH_INTERACTIVE = raw::GIT_CREDTYPE_SSH_INTERACTIVE as u32;
465 #[allow(missing_docs)]
466 const USERNAME = raw::GIT_CREDTYPE_USERNAME as u32;
467 }
468 }
469
470 impl CredentialType {
471 is_bit_set!(is_user_pass_plaintext, CredentialType::USER_PASS_PLAINTEXT);
472 is_bit_set!(is_ssh_key, CredentialType::SSH_KEY);
473 is_bit_set!(is_ssh_memory, CredentialType::SSH_MEMORY);
474 is_bit_set!(is_ssh_custom, CredentialType::SSH_CUSTOM);
475 is_bit_set!(is_default, CredentialType::DEFAULT);
476 is_bit_set!(is_ssh_interactive, CredentialType::SSH_INTERACTIVE);
477 is_bit_set!(is_username, CredentialType::USERNAME);
478 }
479
480 impl Default for CredentialType {
481 fn default() -> Self {
482 CredentialType::DEFAULT
483 }
484 }
485
486 bitflags! {
487 /// Flags for the `flags` field of an IndexEntry.
488 pub struct IndexEntryFlag: u16 {
489 /// Set when the `extended_flags` field is valid.
490 const EXTENDED = raw::GIT_INDEX_ENTRY_EXTENDED as u16;
491 /// "Assume valid" flag
492 const VALID = raw::GIT_INDEX_ENTRY_VALID as u16;
493 }
494 }
495
496 impl IndexEntryFlag {
497 is_bit_set!(is_extended, IndexEntryFlag::EXTENDED);
498 is_bit_set!(is_valid, IndexEntryFlag::VALID);
499 }
500
501 bitflags! {
502 /// Flags for the `extended_flags` field of an IndexEntry.
503 pub struct IndexEntryExtendedFlag: u16 {
504 /// An "intent to add" entry from "git add -N"
505 const INTENT_TO_ADD = raw::GIT_INDEX_ENTRY_INTENT_TO_ADD as u16;
506 /// Skip the associated worktree file, for sparse checkouts
507 const SKIP_WORKTREE = raw::GIT_INDEX_ENTRY_SKIP_WORKTREE as u16;
508
509 #[allow(missing_docs)]
510 const UPTODATE = raw::GIT_INDEX_ENTRY_UPTODATE as u16;
511 }
512 }
513
514 impl IndexEntryExtendedFlag {
515 is_bit_set!(is_intent_to_add, IndexEntryExtendedFlag::INTENT_TO_ADD);
516 is_bit_set!(is_skip_worktree, IndexEntryExtendedFlag::SKIP_WORKTREE);
517 is_bit_set!(is_up_to_date, IndexEntryExtendedFlag::UPTODATE);
518 }
519
520 bitflags! {
521 /// Flags for APIs that add files matching pathspec
522 pub struct IndexAddOption: u32 {
523 #[allow(missing_docs)]
524 const DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32;
525 #[allow(missing_docs)]
526 const FORCE = raw::GIT_INDEX_ADD_FORCE as u32;
527 #[allow(missing_docs)]
528 const DISABLE_PATHSPEC_MATCH =
529 raw::GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH as u32;
530 #[allow(missing_docs)]
531 const CHECK_PATHSPEC = raw::GIT_INDEX_ADD_CHECK_PATHSPEC as u32;
532 }
533 }
534
535 impl IndexAddOption {
536 is_bit_set!(is_default, IndexAddOption::DEFAULT);
537 is_bit_set!(is_force, IndexAddOption::FORCE);
538 is_bit_set!(
539 is_disable_pathspec_match,
540 IndexAddOption::DISABLE_PATHSPEC_MATCH
541 );
542 is_bit_set!(is_check_pathspec, IndexAddOption::CHECK_PATHSPEC);
543 }
544
545 impl Default for IndexAddOption {
546 fn default() -> Self {
547 IndexAddOption::DEFAULT
548 }
549 }
550
551 bitflags! {
552 /// Flags for `Repository::open_ext`
553 pub struct RepositoryOpenFlags: u32 {
554 /// Only open the specified path; don't walk upward searching.
555 const NO_SEARCH = raw::GIT_REPOSITORY_OPEN_NO_SEARCH as u32;
556 /// Search across filesystem boundaries.
557 const CROSS_FS = raw::GIT_REPOSITORY_OPEN_CROSS_FS as u32;
558 /// Force opening as bare repository, and defer loading its config.
559 const BARE = raw::GIT_REPOSITORY_OPEN_BARE as u32;
560 /// Don't try appending `/.git` to the specified repository path.
561 const NO_DOTGIT = raw::GIT_REPOSITORY_OPEN_NO_DOTGIT as u32;
562 /// Respect environment variables like `$GIT_DIR`.
563 const FROM_ENV = raw::GIT_REPOSITORY_OPEN_FROM_ENV as u32;
564 }
565 }
566
567 impl RepositoryOpenFlags {
568 is_bit_set!(is_no_search, RepositoryOpenFlags::NO_SEARCH);
569 is_bit_set!(is_cross_fs, RepositoryOpenFlags::CROSS_FS);
570 is_bit_set!(is_bare, RepositoryOpenFlags::BARE);
571 is_bit_set!(is_no_dotgit, RepositoryOpenFlags::NO_DOTGIT);
572 is_bit_set!(is_from_env, RepositoryOpenFlags::FROM_ENV);
573 }
574
575 bitflags! {
576 /// Flags for the return value of `Repository::revparse`
577 pub struct RevparseMode: u32 {
578 /// The spec targeted a single object
579 const SINGLE = raw::GIT_REVPARSE_SINGLE as u32;
580 /// The spec targeted a range of commits
581 const RANGE = raw::GIT_REVPARSE_RANGE as u32;
582 /// The spec used the `...` operator, which invokes special semantics.
583 const MERGE_BASE = raw::GIT_REVPARSE_MERGE_BASE as u32;
584 }
585 }
586
587 impl RevparseMode {
588 is_bit_set!(is_no_single, RevparseMode::SINGLE);
589 is_bit_set!(is_range, RevparseMode::RANGE);
590 is_bit_set!(is_merge_base, RevparseMode::MERGE_BASE);
591 }
592
593 bitflags! {
594 /// The results of `merge_analysis` indicating the merge opportunities.
595 pub struct MergeAnalysis: u32 {
596 /// No merge is possible.
597 const ANALYSIS_NONE = raw::GIT_MERGE_ANALYSIS_NONE as u32;
598 /// A "normal" merge; both HEAD and the given merge input have diverged
599 /// from their common ancestor. The divergent commits must be merged.
600 const ANALYSIS_NORMAL = raw::GIT_MERGE_ANALYSIS_NORMAL as u32;
601 /// All given merge inputs are reachable from HEAD, meaning the
602 /// repository is up-to-date and no merge needs to be performed.
603 const ANALYSIS_UP_TO_DATE = raw::GIT_MERGE_ANALYSIS_UP_TO_DATE as u32;
604 /// The given merge input is a fast-forward from HEAD and no merge
605 /// needs to be performed. Instead, the client can check out the
606 /// given merge input.
607 const ANALYSIS_FASTFORWARD = raw::GIT_MERGE_ANALYSIS_FASTFORWARD as u32;
608 /// The HEAD of the current repository is "unborn" and does not point to
609 /// a valid commit. No merge can be performed, but the caller may wish
610 /// to simply set HEAD to the target commit(s).
611 const ANALYSIS_UNBORN = raw::GIT_MERGE_ANALYSIS_UNBORN as u32;
612 }
613 }
614
615 impl MergeAnalysis {
616 is_bit_set!(is_none, MergeAnalysis::ANALYSIS_NONE);
617 is_bit_set!(is_normal, MergeAnalysis::ANALYSIS_NORMAL);
618 is_bit_set!(is_up_to_date, MergeAnalysis::ANALYSIS_UP_TO_DATE);
619 is_bit_set!(is_fast_forward, MergeAnalysis::ANALYSIS_FASTFORWARD);
620 is_bit_set!(is_unborn, MergeAnalysis::ANALYSIS_UNBORN);
621 }
622
623 bitflags! {
624 /// The user's stated preference for merges.
625 pub struct MergePreference: u32 {
626 /// No configuration was found that suggests a preferred behavior for
627 /// merge.
628 const NONE = raw::GIT_MERGE_PREFERENCE_NONE as u32;
629 /// There is a `merge.ff=false` configuration setting, suggesting that
630 /// the user does not want to allow a fast-forward merge.
631 const NO_FAST_FORWARD = raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD as u32;
632 /// There is a `merge.ff=only` configuration setting, suggesting that
633 /// the user only wants fast-forward merges.
634 const FASTFORWARD_ONLY = raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY as u32;
635 }
636 }
637
638 impl MergePreference {
639 is_bit_set!(is_none, MergePreference::NONE);
640 is_bit_set!(is_no_fast_forward, MergePreference::NO_FAST_FORWARD);
641 is_bit_set!(is_fastforward_only, MergePreference::FASTFORWARD_ONLY);
642 }
643
644 bitflags! {
645 /// Flags controlling the behavior of ODB lookup operations
646 pub struct OdbLookupFlags: u32 {
647 /// Don't call `git_odb_refresh` if the lookup fails. Useful when doing
648 /// a batch of lookup operations for objects that may legitimately not
649 /// exist. When using this flag, you may wish to manually call
650 /// `git_odb_refresh` before processing a batch of objects.
651 const NO_REFRESH = raw::GIT_ODB_LOOKUP_NO_REFRESH as u32;
652 }
653 }
654
655 #[cfg(test)]
656 #[macro_use]
657 mod test;
658 #[macro_use]
659 mod panic;
660 mod attr;
661 mod call;
662 mod util;
663
664 pub mod build;
665 pub mod cert;
666 pub mod oid_array;
667 pub mod opts;
668 pub mod string_array;
669 pub mod transport;
670
671 mod apply;
672 mod blame;
673 mod blob;
674 mod branch;
675 mod buf;
676 mod cherrypick;
677 mod commit;
678 mod config;
679 mod cred;
680 mod describe;
681 mod diff;
682 mod email;
683 mod error;
684 mod index;
685 mod indexer;
686 mod mailmap;
687 mod mempack;
688 mod merge;
689 mod message;
690 mod note;
691 mod object;
692 mod odb;
693 mod oid;
694 mod packbuilder;
695 mod patch;
696 mod pathspec;
697 mod proxy_options;
698 mod push_update;
699 mod rebase;
700 mod reference;
701 mod reflog;
702 mod refspec;
703 mod remote;
704 mod remote_callbacks;
705 mod repo;
706 mod revert;
707 mod revspec;
708 mod revwalk;
709 mod signature;
710 mod stash;
711 mod status;
712 mod submodule;
713 mod tag;
714 mod tagforeach;
715 mod time;
716 mod tracing;
717 mod transaction;
718 mod tree;
719 mod treebuilder;
720 mod version;
721 mod worktree;
722
723 fn init() {
724 static INIT: Once = Once::new();
725
726 INIT.call_once(|| {
727 openssl_env_init();
728 });
729
730 raw::init();
731 }
732
733 #[cfg(all(
734 unix,
735 not(target_os = "macos"),
736 not(target_os = "ios"),
737 feature = "https"
738 ))]
739 fn openssl_env_init() {
740 // Currently, libgit2 leverages OpenSSL for SSL support when cloning
741 // repositories over HTTPS. This means that we're picking up an OpenSSL
742 // dependency on non-Windows platforms (where it has its own HTTPS
743 // subsystem). As a result, we need to link to OpenSSL.
744 //
745 // Now actually *linking* to OpenSSL isn't so hard. We just need to make
746 // sure to use pkg-config to discover any relevant system dependencies for
747 // differences between distributions like CentOS and Ubuntu. The actual
748 // trickiness comes about when we start *distributing* the resulting
749 // binaries. Currently Cargo is distributed in binary form as nightlies,
750 // which means we're distributing a binary with OpenSSL linked in.
751 //
752 // For historical reasons, the Linux nightly builder is running a CentOS
753 // distribution in order to have as much ABI compatibility with other
754 // distributions as possible. Sadly, however, this compatibility does not
755 // extend to OpenSSL. Currently OpenSSL has two major versions, 0.9 and 1.0,
756 // which are incompatible (many ABI differences). The CentOS builder we
757 // build on has version 1.0, as do most distributions today. Some still have
758 // 0.9, however. This means that if we are to distribute the binaries built
759 // by the CentOS machine, we would only be compatible with OpenSSL 1.0 and
760 // we would fail to run (a dynamic linker error at runtime) on systems with
761 // only 9.8 installed (hopefully).
762 //
763 // But wait, the plot thickens! Apparently CentOS has dubbed their OpenSSL
764 // library as `libssl.so.10`, notably the `10` is included at the end. On
765 // the other hand Ubuntu, for example, only distributes `libssl.so`. This
766 // means that the binaries created at CentOS are hard-wired to probe for a
767 // file called `libssl.so.10` at runtime (using the LD_LIBRARY_PATH), which
768 // will not be found on ubuntu. The conclusion of this is that binaries
769 // built on CentOS cannot be distributed to Ubuntu and run successfully.
770 //
771 // There are a number of sneaky things we could do, including, but not
772 // limited to:
773 //
774 // 1. Create a shim program which runs "just before" cargo runs. The
775 // responsibility of this shim program would be to locate `libssl.so`,
776 // whatever it's called, on the current system, make sure there's a
777 // symlink *somewhere* called `libssl.so.10`, and then set up
778 // LD_LIBRARY_PATH and run the actual cargo.
779 //
780 // This approach definitely seems unconventional, and is borderline
781 // overkill for this problem. It's also dubious if we can find a
782 // libssl.so reliably on the target system.
783 //
784 // 2. Somehow re-work the CentOS installation so that the linked-against
785 // library is called libssl.so instead of libssl.so.10
786 //
787 // The problem with this approach is that systems with 0.9 installed will
788 // start to silently fail, due to also having libraries called libssl.so
789 // (probably symlinked under a more appropriate version).
790 //
791 // 3. Compile Cargo against both OpenSSL 1.0 *and* OpenSSL 0.9, and
792 // distribute both. Also make sure that the linked-against name of the
793 // library is `libssl.so`. At runtime we determine which version is
794 // installed, and we then the appropriate binary.
795 //
796 // This approach clearly has drawbacks in terms of infrastructure and
797 // feasibility.
798 //
799 // 4. Build a nightly of Cargo for each distribution we'd like to support.
800 // You would then pick the appropriate Cargo nightly to install locally.
801 //
802 // So, with all this in mind, the decision was made to *statically* link
803 // OpenSSL. This solves any problem of relying on a downstream OpenSSL
804 // version being available. This does, however, open a can of worms related
805 // to security issues. It's generally a good idea to dynamically link
806 // OpenSSL as you'll get security updates over time without having to do
807 // anything (the system administrator will update the local openssl
808 // package). By statically linking, we're forfeiting this feature.
809 //
810 // The conclusion was made it is likely appropriate for the Cargo nightlies
811 // to statically link OpenSSL, but highly encourage distributions and
812 // packagers of Cargo to dynamically link OpenSSL. Packagers are targeting
813 // one system and are distributing to only that system, so none of the
814 // problems mentioned above would arise.
815 //
816 // In order to support this, a new package was made: openssl-static-sys.
817 // This package currently performs a fairly simple task:
818 //
819 // 1. Run pkg-config to discover where openssl is installed.
820 // 2. If openssl is installed in a nonstandard location, *and* static copies
821 // of the libraries are available, copy them to $OUT_DIR.
822 //
823 // This library will bring in libssl.a and libcrypto.a into the local build,
824 // allowing them to be picked up by this crate. This allows us to configure
825 // our own buildbots to have pkg-config point to these local pre-built
826 // copies of a static OpenSSL (with very few dependencies) while allowing
827 // most other builds of Cargo to naturally dynamically link OpenSSL.
828 //
829 // So in summary, if you're with me so far, we've statically linked OpenSSL
830 // to the Cargo binary (or any binary, for that matter) and we're ready to
831 // distribute it to *all* linux distributions. Remember that our original
832 // intent for openssl was for HTTPS support, which implies that we need some
833 // for of CA certificate store to validate certificates. This is normally
834 // installed in a standard system location.
835 //
836 // Unfortunately, as one might imagine, OpenSSL is configured for where this
837 // standard location is at *build time*, but it often varies widely
838 // per-system. Consequently, it was discovered that OpenSSL will respect the
839 // SSL_CERT_FILE and SSL_CERT_DIR environment variables in order to assist
840 // in discovering the location of this file (hurray!).
841 //
842 // So, finally getting to the point, this function solely exists to support
843 // our static builds of OpenSSL by probing for the "standard system
844 // location" of certificates and setting relevant environment variable to
845 // point to them.
846 //
847 // Ah, and as a final note, this is only a problem on Linux, not on OS X. On
848 // OS X the OpenSSL binaries are stable enough that we can just rely on
849 // dynamic linkage (plus they have some weird modifications to OpenSSL which
850 // means we wouldn't want to link statically).
851 openssl_probe::init_ssl_cert_env_vars();
852 }
853
854 #[cfg(any(
855 windows,
856 target_os = "macos",
857 target_os = "ios",
858 not(feature = "https")
859 ))]
860 fn openssl_env_init() {}
861
862 unsafe fn opt_bytes<'a, T>(_anchor: &'a T, c: *const libc::c_char) -> Option<&'a [u8]> {
863 if c.is_null() {
864 None
865 } else {
866 Some(CStr::from_ptr(c).to_bytes())
867 }
868 }
869
870 fn opt_cstr<T: IntoCString>(o: Option<T>) -> Result<Option<CString>, Error> {
871 match o {
872 Some(s) => s.into_c_string().map(Some),
873 None => Ok(None),
874 }
875 }
876
877 impl ObjectType {
878 /// Convert an object type to its string representation.
879 pub fn str(&self) -> &'static str {
880 unsafe {
881 let ptr = call!(raw::git_object_type2string(*self)) as *const _;
882 let data = CStr::from_ptr(ptr).to_bytes();
883 str::from_utf8(data).unwrap()
884 }
885 }
886
887 /// Determine if the given git_object_t is a valid loose object type.
888 pub fn is_loose(&self) -> bool {
889 unsafe { call!(raw::git_object_typeisloose(*self)) == 1 }
890 }
891
892 /// Convert a raw git_object_t to an ObjectType
893 pub fn from_raw(raw: raw::git_object_t) -> Option<ObjectType> {
894 match raw {
895 raw::GIT_OBJECT_ANY => Some(ObjectType::Any),
896 raw::GIT_OBJECT_COMMIT => Some(ObjectType::Commit),
897 raw::GIT_OBJECT_TREE => Some(ObjectType::Tree),
898 raw::GIT_OBJECT_BLOB => Some(ObjectType::Blob),
899 raw::GIT_OBJECT_TAG => Some(ObjectType::Tag),
900 _ => None,
901 }
902 }
903
904 /// Convert this kind into its raw representation
905 pub fn raw(&self) -> raw::git_object_t {
906 call::convert(self)
907 }
908
909 /// Convert a string object type representation to its object type.
910 pub fn from_str(s: &str) -> Option<ObjectType> {
911 let raw = unsafe { call!(raw::git_object_string2type(CString::new(s).unwrap())) };
912 ObjectType::from_raw(raw)
913 }
914 }
915
916 impl fmt::Display for ObjectType {
917 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
918 self.str().fmt(f)
919 }
920 }
921
922 impl ReferenceType {
923 /// Convert an object type to its string representation.
924 pub fn str(&self) -> &'static str {
925 match self {
926 ReferenceType::Direct => "direct",
927 ReferenceType::Symbolic => "symbolic",
928 }
929 }
930
931 /// Convert a raw git_reference_t to a ReferenceType.
932 pub fn from_raw(raw: raw::git_reference_t) -> Option<ReferenceType> {
933 match raw {
934 raw::GIT_REFERENCE_DIRECT => Some(ReferenceType::Direct),
935 raw::GIT_REFERENCE_SYMBOLIC => Some(ReferenceType::Symbolic),
936 _ => None,
937 }
938 }
939 }
940
941 impl fmt::Display for ReferenceType {
942 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
943 self.str().fmt(f)
944 }
945 }
946
947 impl ConfigLevel {
948 /// Converts a raw configuration level to a ConfigLevel
949 pub fn from_raw(raw: raw::git_config_level_t) -> ConfigLevel {
950 match raw {
951 raw::GIT_CONFIG_LEVEL_PROGRAMDATA => ConfigLevel::ProgramData,
952 raw::GIT_CONFIG_LEVEL_SYSTEM => ConfigLevel::System,
953 raw::GIT_CONFIG_LEVEL_XDG => ConfigLevel::XDG,
954 raw::GIT_CONFIG_LEVEL_GLOBAL => ConfigLevel::Global,
955 raw::GIT_CONFIG_LEVEL_LOCAL => ConfigLevel::Local,
956 raw::GIT_CONFIG_LEVEL_APP => ConfigLevel::App,
957 raw::GIT_CONFIG_HIGHEST_LEVEL => ConfigLevel::Highest,
958 n => panic!("unknown config level: {}", n),
959 }
960 }
961 }
962
963 impl SubmoduleIgnore {
964 /// Converts a [`raw::git_submodule_ignore_t`] to a [`SubmoduleIgnore`]
965 pub fn from_raw(raw: raw::git_submodule_ignore_t) -> Self {
966 match raw {
967 raw::GIT_SUBMODULE_IGNORE_UNSPECIFIED => SubmoduleIgnore::Unspecified,
968 raw::GIT_SUBMODULE_IGNORE_NONE => SubmoduleIgnore::None,
969 raw::GIT_SUBMODULE_IGNORE_UNTRACKED => SubmoduleIgnore::Untracked,
970 raw::GIT_SUBMODULE_IGNORE_DIRTY => SubmoduleIgnore::Dirty,
971 raw::GIT_SUBMODULE_IGNORE_ALL => SubmoduleIgnore::All,
972 n => panic!("unknown submodule ignore rule: {}", n),
973 }
974 }
975 }
976
977 impl SubmoduleUpdate {
978 /// Converts a [`raw::git_submodule_update_t`] to a [`SubmoduleUpdate`]
979 pub fn from_raw(raw: raw::git_submodule_update_t) -> Self {
980 match raw {
981 raw::GIT_SUBMODULE_UPDATE_CHECKOUT => SubmoduleUpdate::Checkout,
982 raw::GIT_SUBMODULE_UPDATE_REBASE => SubmoduleUpdate::Rebase,
983 raw::GIT_SUBMODULE_UPDATE_MERGE => SubmoduleUpdate::Merge,
984 raw::GIT_SUBMODULE_UPDATE_NONE => SubmoduleUpdate::None,
985 raw::GIT_SUBMODULE_UPDATE_DEFAULT => SubmoduleUpdate::Default,
986 n => panic!("unknown submodule update strategy: {}", n),
987 }
988 }
989 }
990
991 bitflags! {
992 /// Status flags for a single file
993 ///
994 /// A combination of these values will be returned to indicate the status of
995 /// a file. Status compares the working directory, the index, and the
996 /// current HEAD of the repository. The `STATUS_INDEX_*` set of flags
997 /// represents the status of file in the index relative to the HEAD, and the
998 /// `STATUS_WT_*` set of flags represent the status of the file in the
999 /// working directory relative to the index.
1000 pub struct Status: u32 {
1001 #[allow(missing_docs)]
1002 const CURRENT = raw::GIT_STATUS_CURRENT as u32;
1003
1004 #[allow(missing_docs)]
1005 const INDEX_NEW = raw::GIT_STATUS_INDEX_NEW as u32;
1006 #[allow(missing_docs)]
1007 const INDEX_MODIFIED = raw::GIT_STATUS_INDEX_MODIFIED as u32;
1008 #[allow(missing_docs)]
1009 const INDEX_DELETED = raw::GIT_STATUS_INDEX_DELETED as u32;
1010 #[allow(missing_docs)]
1011 const INDEX_RENAMED = raw::GIT_STATUS_INDEX_RENAMED as u32;
1012 #[allow(missing_docs)]
1013 const INDEX_TYPECHANGE = raw::GIT_STATUS_INDEX_TYPECHANGE as u32;
1014
1015 #[allow(missing_docs)]
1016 const WT_NEW = raw::GIT_STATUS_WT_NEW as u32;
1017 #[allow(missing_docs)]
1018 const WT_MODIFIED = raw::GIT_STATUS_WT_MODIFIED as u32;
1019 #[allow(missing_docs)]
1020 const WT_DELETED = raw::GIT_STATUS_WT_DELETED as u32;
1021 #[allow(missing_docs)]
1022 const WT_TYPECHANGE = raw::GIT_STATUS_WT_TYPECHANGE as u32;
1023 #[allow(missing_docs)]
1024 const WT_RENAMED = raw::GIT_STATUS_WT_RENAMED as u32;
1025
1026 #[allow(missing_docs)]
1027 const IGNORED = raw::GIT_STATUS_IGNORED as u32;
1028 #[allow(missing_docs)]
1029 const CONFLICTED = raw::GIT_STATUS_CONFLICTED as u32;
1030 }
1031 }
1032
1033 impl Status {
1034 is_bit_set!(is_index_new, Status::INDEX_NEW);
1035 is_bit_set!(is_index_modified, Status::INDEX_MODIFIED);
1036 is_bit_set!(is_index_deleted, Status::INDEX_DELETED);
1037 is_bit_set!(is_index_renamed, Status::INDEX_RENAMED);
1038 is_bit_set!(is_index_typechange, Status::INDEX_TYPECHANGE);
1039 is_bit_set!(is_wt_new, Status::WT_NEW);
1040 is_bit_set!(is_wt_modified, Status::WT_MODIFIED);
1041 is_bit_set!(is_wt_deleted, Status::WT_DELETED);
1042 is_bit_set!(is_wt_typechange, Status::WT_TYPECHANGE);
1043 is_bit_set!(is_wt_renamed, Status::WT_RENAMED);
1044 is_bit_set!(is_ignored, Status::IGNORED);
1045 is_bit_set!(is_conflicted, Status::CONFLICTED);
1046 }
1047
1048 bitflags! {
1049 /// Mode options for RepositoryInitOptions
1050 pub struct RepositoryInitMode: u32 {
1051 /// Use permissions configured by umask - the default
1052 const SHARED_UMASK = raw::GIT_REPOSITORY_INIT_SHARED_UMASK as u32;
1053 /// Use `--shared=group` behavior, chmod'ing the new repo to be
1054 /// group writable and \"g+sx\" for sticky group assignment
1055 const SHARED_GROUP = raw::GIT_REPOSITORY_INIT_SHARED_GROUP as u32;
1056 /// Use `--shared=all` behavior, adding world readability.
1057 const SHARED_ALL = raw::GIT_REPOSITORY_INIT_SHARED_ALL as u32;
1058 }
1059 }
1060
1061 impl RepositoryInitMode {
1062 is_bit_set!(is_shared_umask, RepositoryInitMode::SHARED_UMASK);
1063 is_bit_set!(is_shared_group, RepositoryInitMode::SHARED_GROUP);
1064 is_bit_set!(is_shared_all, RepositoryInitMode::SHARED_ALL);
1065 }
1066
1067 /// What type of change is described by a `DiffDelta`?
1068 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1069 pub enum Delta {
1070 /// No changes
1071 Unmodified,
1072 /// Entry does not exist in old version
1073 Added,
1074 /// Entry does not exist in new version
1075 Deleted,
1076 /// Entry content changed between old and new
1077 Modified,
1078 /// Entry was renamed between old and new
1079 Renamed,
1080 /// Entry was copied from another old entry
1081 Copied,
1082 /// Entry is ignored item in workdir
1083 Ignored,
1084 /// Entry is untracked item in workdir
1085 Untracked,
1086 /// Type of entry changed between old and new
1087 Typechange,
1088 /// Entry is unreadable
1089 Unreadable,
1090 /// Entry in the index is conflicted
1091 Conflicted,
1092 }
1093
1094 /// Valid modes for index and tree entries.
1095 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1096 pub enum FileMode {
1097 /// Unreadable
1098 Unreadable,
1099 /// Tree
1100 Tree,
1101 /// Blob
1102 Blob,
1103 /// Group writable blob. Obsolete mode kept for compatibility reasons
1104 BlobGroupWritable,
1105 /// Blob executable
1106 BlobExecutable,
1107 /// Link
1108 Link,
1109 /// Commit
1110 Commit,
1111 }
1112
1113 impl From<FileMode> for i32 {
1114 fn from(mode: FileMode) -> i32 {
1115 match mode {
1116 FileMode::Unreadable => raw::GIT_FILEMODE_UNREADABLE as i32,
1117 FileMode::Tree => raw::GIT_FILEMODE_TREE as i32,
1118 FileMode::Blob => raw::GIT_FILEMODE_BLOB as i32,
1119 FileMode::BlobGroupWritable => raw::GIT_FILEMODE_BLOB_GROUP_WRITABLE as i32,
1120 FileMode::BlobExecutable => raw::GIT_FILEMODE_BLOB_EXECUTABLE as i32,
1121 FileMode::Link => raw::GIT_FILEMODE_LINK as i32,
1122 FileMode::Commit => raw::GIT_FILEMODE_COMMIT as i32,
1123 }
1124 }
1125 }
1126
1127 impl From<FileMode> for u32 {
1128 fn from(mode: FileMode) -> u32 {
1129 match mode {
1130 FileMode::Unreadable => raw::GIT_FILEMODE_UNREADABLE as u32,
1131 FileMode::Tree => raw::GIT_FILEMODE_TREE as u32,
1132 FileMode::Blob => raw::GIT_FILEMODE_BLOB as u32,
1133 FileMode::BlobGroupWritable => raw::GIT_FILEMODE_BLOB_GROUP_WRITABLE as u32,
1134 FileMode::BlobExecutable => raw::GIT_FILEMODE_BLOB_EXECUTABLE as u32,
1135 FileMode::Link => raw::GIT_FILEMODE_LINK as u32,
1136 FileMode::Commit => raw::GIT_FILEMODE_COMMIT as u32,
1137 }
1138 }
1139 }
1140
1141 bitflags! {
1142 /// Return codes for submodule status.
1143 ///
1144 /// A combination of these flags will be returned to describe the status of a
1145 /// submodule. Depending on the "ignore" property of the submodule, some of
1146 /// the flags may never be returned because they indicate changes that are
1147 /// supposed to be ignored.
1148 ///
1149 /// Submodule info is contained in 4 places: the HEAD tree, the index, config
1150 /// files (both .git/config and .gitmodules), and the working directory. Any
1151 /// or all of those places might be missing information about the submodule
1152 /// depending on what state the repo is in. We consider all four places to
1153 /// build the combination of status flags.
1154 ///
1155 /// There are four values that are not really status, but give basic info
1156 /// about what sources of submodule data are available. These will be
1157 /// returned even if ignore is set to "ALL".
1158 ///
1159 /// * IN_HEAD - superproject head contains submodule
1160 /// * IN_INDEX - superproject index contains submodule
1161 /// * IN_CONFIG - superproject gitmodules has submodule
1162 /// * IN_WD - superproject workdir has submodule
1163 ///
1164 /// The following values will be returned so long as ignore is not "ALL".
1165 ///
1166 /// * INDEX_ADDED - in index, not in head
1167 /// * INDEX_DELETED - in head, not in index
1168 /// * INDEX_MODIFIED - index and head don't match
1169 /// * WD_UNINITIALIZED - workdir contains empty directory
1170 /// * WD_ADDED - in workdir, not index
1171 /// * WD_DELETED - in index, not workdir
1172 /// * WD_MODIFIED - index and workdir head don't match
1173 ///
1174 /// The following can only be returned if ignore is "NONE" or "UNTRACKED".
1175 ///
1176 /// * WD_INDEX_MODIFIED - submodule workdir index is dirty
1177 /// * WD_WD_MODIFIED - submodule workdir has modified files
1178 ///
1179 /// Lastly, the following will only be returned for ignore "NONE".
1180 ///
1181 /// * WD_UNTRACKED - workdir contains untracked files
1182 pub struct SubmoduleStatus: u32 {
1183 #[allow(missing_docs)]
1184 const IN_HEAD = raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32;
1185 #[allow(missing_docs)]
1186 const IN_INDEX = raw::GIT_SUBMODULE_STATUS_IN_INDEX as u32;
1187 #[allow(missing_docs)]
1188 const IN_CONFIG = raw::GIT_SUBMODULE_STATUS_IN_CONFIG as u32;
1189 #[allow(missing_docs)]
1190 const IN_WD = raw::GIT_SUBMODULE_STATUS_IN_WD as u32;
1191 #[allow(missing_docs)]
1192 const INDEX_ADDED = raw::GIT_SUBMODULE_STATUS_INDEX_ADDED as u32;
1193 #[allow(missing_docs)]
1194 const INDEX_DELETED = raw::GIT_SUBMODULE_STATUS_INDEX_DELETED as u32;
1195 #[allow(missing_docs)]
1196 const INDEX_MODIFIED = raw::GIT_SUBMODULE_STATUS_INDEX_MODIFIED as u32;
1197 #[allow(missing_docs)]
1198 const WD_UNINITIALIZED =
1199 raw::GIT_SUBMODULE_STATUS_WD_UNINITIALIZED as u32;
1200 #[allow(missing_docs)]
1201 const WD_ADDED = raw::GIT_SUBMODULE_STATUS_WD_ADDED as u32;
1202 #[allow(missing_docs)]
1203 const WD_DELETED = raw::GIT_SUBMODULE_STATUS_WD_DELETED as u32;
1204 #[allow(missing_docs)]
1205 const WD_MODIFIED = raw::GIT_SUBMODULE_STATUS_WD_MODIFIED as u32;
1206 #[allow(missing_docs)]
1207 const WD_INDEX_MODIFIED =
1208 raw::GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED as u32;
1209 #[allow(missing_docs)]
1210 const WD_WD_MODIFIED = raw::GIT_SUBMODULE_STATUS_WD_WD_MODIFIED as u32;
1211 #[allow(missing_docs)]
1212 const WD_UNTRACKED = raw::GIT_SUBMODULE_STATUS_WD_UNTRACKED as u32;
1213 }
1214 }
1215
1216 impl SubmoduleStatus {
1217 is_bit_set!(is_in_head, SubmoduleStatus::IN_HEAD);
1218 is_bit_set!(is_in_index, SubmoduleStatus::IN_INDEX);
1219 is_bit_set!(is_in_config, SubmoduleStatus::IN_CONFIG);
1220 is_bit_set!(is_in_wd, SubmoduleStatus::IN_WD);
1221 is_bit_set!(is_index_added, SubmoduleStatus::INDEX_ADDED);
1222 is_bit_set!(is_index_deleted, SubmoduleStatus::INDEX_DELETED);
1223 is_bit_set!(is_index_modified, SubmoduleStatus::INDEX_MODIFIED);
1224 is_bit_set!(is_wd_uninitialized, SubmoduleStatus::WD_UNINITIALIZED);
1225 is_bit_set!(is_wd_added, SubmoduleStatus::WD_ADDED);
1226 is_bit_set!(is_wd_deleted, SubmoduleStatus::WD_DELETED);
1227 is_bit_set!(is_wd_modified, SubmoduleStatus::WD_MODIFIED);
1228 is_bit_set!(is_wd_wd_modified, SubmoduleStatus::WD_WD_MODIFIED);
1229 is_bit_set!(is_wd_untracked, SubmoduleStatus::WD_UNTRACKED);
1230 }
1231
1232 /// Submodule ignore values
1233 ///
1234 /// These values represent settings for the `submodule.$name.ignore`
1235 /// configuration value which says how deeply to look at the working
1236 /// directory when getting the submodule status.
1237 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1238 pub enum SubmoduleIgnore {
1239 /// Use the submodule's configuration
1240 Unspecified,
1241 /// Any change or untracked file is considered dirty
1242 None,
1243 /// Only dirty if tracked files have changed
1244 Untracked,
1245 /// Only dirty if HEAD has moved
1246 Dirty,
1247 /// Never dirty
1248 All,
1249 }
1250
1251 /// Submodule update values
1252 ///
1253 /// These values represent settings for the `submodule.$name.update`
1254 /// configuration value which says how to handle `git submodule update`
1255 /// for this submodule. The value is usually set in the ".gitmodules"
1256 /// file and copied to ".git/config" when the submodule is initialized.
1257 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1258 pub enum SubmoduleUpdate {
1259 /// The default; when a submodule is updated, checkout the new detached
1260 /// HEAD to the submodule directory.
1261 Checkout,
1262 /// Update by rebasing the current checked out branch onto the commit from
1263 /// the superproject.
1264 Rebase,
1265 /// Update by merging the commit in the superproject into the current
1266 /// checkout out branch of the submodule.
1267 Merge,
1268 /// Do not update this submodule even when the commit in the superproject
1269 /// is updated.
1270 None,
1271 /// Not used except as static initializer when we don't want any particular
1272 /// update rule to be specified.
1273 Default,
1274 }
1275
1276 bitflags! {
1277 /// ...
1278 pub struct PathspecFlags: u32 {
1279 /// Use the default pathspec matching configuration.
1280 const DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32;
1281 /// Force matching to ignore case, otherwise matching will use native
1282 /// case sensitivity of the platform filesystem.
1283 const IGNORE_CASE = raw::GIT_PATHSPEC_IGNORE_CASE as u32;
1284 /// Force case sensitive matches, otherwise match will use the native
1285 /// case sensitivity of the platform filesystem.
1286 const USE_CASE = raw::GIT_PATHSPEC_USE_CASE as u32;
1287 /// Disable glob patterns and just use simple string comparison for
1288 /// matching.
1289 const NO_GLOB = raw::GIT_PATHSPEC_NO_GLOB as u32;
1290 /// Means that match functions return the error code `NotFound` if no
1291 /// matches are found. By default no matches is a success.
1292 const NO_MATCH_ERROR = raw::GIT_PATHSPEC_NO_MATCH_ERROR as u32;
1293 /// Means that the list returned should track which patterns matched
1294 /// which files so that at the end of the match we can identify patterns
1295 /// that did not match any files.
1296 const FIND_FAILURES = raw::GIT_PATHSPEC_FIND_FAILURES as u32;
1297 /// Means that the list returned does not need to keep the actual
1298 /// matching filenames. Use this to just test if there were any matches
1299 /// at all or in combination with `PATHSPEC_FAILURES` to validate a
1300 /// pathspec.
1301 const FAILURES_ONLY = raw::GIT_PATHSPEC_FAILURES_ONLY as u32;
1302 }
1303 }
1304
1305 impl PathspecFlags {
1306 is_bit_set!(is_default, PathspecFlags::DEFAULT);
1307 is_bit_set!(is_ignore_case, PathspecFlags::IGNORE_CASE);
1308 is_bit_set!(is_use_case, PathspecFlags::USE_CASE);
1309 is_bit_set!(is_no_glob, PathspecFlags::NO_GLOB);
1310 is_bit_set!(is_no_match_error, PathspecFlags::NO_MATCH_ERROR);
1311 is_bit_set!(is_find_failures, PathspecFlags::FIND_FAILURES);
1312 is_bit_set!(is_failures_only, PathspecFlags::FAILURES_ONLY);
1313 }
1314
1315 impl Default for PathspecFlags {
1316 fn default() -> Self {
1317 PathspecFlags::DEFAULT
1318 }
1319 }
1320
1321 bitflags! {
1322 /// Types of notifications emitted from checkouts.
1323 pub struct CheckoutNotificationType: u32 {
1324 /// Notification about a conflict.
1325 const CONFLICT = raw::GIT_CHECKOUT_NOTIFY_CONFLICT as u32;
1326 /// Notification about a dirty file.
1327 const DIRTY = raw::GIT_CHECKOUT_NOTIFY_DIRTY as u32;
1328 /// Notification about an updated file.
1329 const UPDATED = raw::GIT_CHECKOUT_NOTIFY_UPDATED as u32;
1330 /// Notification about an untracked file.
1331 const UNTRACKED = raw::GIT_CHECKOUT_NOTIFY_UNTRACKED as u32;
1332 /// Notification about an ignored file.
1333 const IGNORED = raw::GIT_CHECKOUT_NOTIFY_IGNORED as u32;
1334 }
1335 }
1336
1337 impl CheckoutNotificationType {
1338 is_bit_set!(is_conflict, CheckoutNotificationType::CONFLICT);
1339 is_bit_set!(is_dirty, CheckoutNotificationType::DIRTY);
1340 is_bit_set!(is_updated, CheckoutNotificationType::UPDATED);
1341 is_bit_set!(is_untracked, CheckoutNotificationType::UNTRACKED);
1342 is_bit_set!(is_ignored, CheckoutNotificationType::IGNORED);
1343 }
1344
1345 /// Possible output formats for diff data
1346 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1347 pub enum DiffFormat {
1348 /// full git diff
1349 Patch,
1350 /// just the headers of the patch
1351 PatchHeader,
1352 /// like git diff --raw
1353 Raw,
1354 /// like git diff --name-only
1355 NameOnly,
1356 /// like git diff --name-status
1357 NameStatus,
1358 /// git diff as used by git patch-id
1359 PatchId,
1360 }
1361
1362 bitflags! {
1363 /// Formatting options for diff stats
1364 pub struct DiffStatsFormat: raw::git_diff_stats_format_t {
1365 /// Don't generate any stats
1366 const NONE = raw::GIT_DIFF_STATS_NONE;
1367 /// Equivalent of `--stat` in git
1368 const FULL = raw::GIT_DIFF_STATS_FULL;
1369 /// Equivalent of `--shortstat` in git
1370 const SHORT = raw::GIT_DIFF_STATS_SHORT;
1371 /// Equivalent of `--numstat` in git
1372 const NUMBER = raw::GIT_DIFF_STATS_NUMBER;
1373 /// Extended header information such as creations, renames and mode
1374 /// changes, equivalent of `--summary` in git
1375 const INCLUDE_SUMMARY = raw::GIT_DIFF_STATS_INCLUDE_SUMMARY;
1376 }
1377 }
1378
1379 impl DiffStatsFormat {
1380 is_bit_set!(is_none, DiffStatsFormat::NONE);
1381 is_bit_set!(is_full, DiffStatsFormat::FULL);
1382 is_bit_set!(is_short, DiffStatsFormat::SHORT);
1383 is_bit_set!(is_number, DiffStatsFormat::NUMBER);
1384 is_bit_set!(is_include_summary, DiffStatsFormat::INCLUDE_SUMMARY);
1385 }
1386
1387 /// Automatic tag following options.
1388 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1389 pub enum AutotagOption {
1390 /// Use the setting from the remote's configuration
1391 Unspecified,
1392 /// Ask the server for tags pointing to objects we're already downloading
1393 Auto,
1394 /// Don't ask for any tags beyond the refspecs
1395 None,
1396 /// Ask for all the tags
1397 All,
1398 }
1399
1400 /// Configuration for how pruning is done on a fetch
1401 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1402 pub enum FetchPrune {
1403 /// Use the setting from the configuration
1404 Unspecified,
1405 /// Force pruning on
1406 On,
1407 /// Force pruning off
1408 Off,
1409 }
1410
1411 #[allow(missing_docs)]
1412 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1413 pub enum StashApplyProgress {
1414 /// None
1415 None,
1416 /// Loading the stashed data from the object database
1417 LoadingStash,
1418 /// The stored index is being analyzed
1419 AnalyzeIndex,
1420 /// The modified files are being analyzed
1421 AnalyzeModified,
1422 /// The untracked and ignored files are being analyzed
1423 AnalyzeUntracked,
1424 /// The untracked files are being written to disk
1425 CheckoutUntracked,
1426 /// The modified files are being written to disk
1427 CheckoutModified,
1428 /// The stash was applied successfully
1429 Done,
1430 }
1431
1432 bitflags! {
1433 #[allow(missing_docs)]
1434 pub struct StashApplyFlags: u32 {
1435 #[allow(missing_docs)]
1436 const DEFAULT = raw::GIT_STASH_APPLY_DEFAULT as u32;
1437 /// Try to reinstate not only the working tree's changes,
1438 /// but also the index's changes.
1439 const REINSTATE_INDEX = raw::GIT_STASH_APPLY_REINSTATE_INDEX as u32;
1440 }
1441 }
1442
1443 impl StashApplyFlags {
1444 is_bit_set!(is_default, StashApplyFlags::DEFAULT);
1445 is_bit_set!(is_reinstate_index, StashApplyFlags::REINSTATE_INDEX);
1446 }
1447
1448 impl Default for StashApplyFlags {
1449 fn default() -> Self {
1450 StashApplyFlags::DEFAULT
1451 }
1452 }
1453
1454 bitflags! {
1455 #[allow(missing_docs)]
1456 pub struct StashFlags: u32 {
1457 #[allow(missing_docs)]
1458 const DEFAULT = raw::GIT_STASH_DEFAULT as u32;
1459 /// All changes already added to the index are left intact in
1460 /// the working directory
1461 const KEEP_INDEX = raw::GIT_STASH_KEEP_INDEX as u32;
1462 /// All untracked files are also stashed and then cleaned up
1463 /// from the working directory
1464 const INCLUDE_UNTRACKED = raw::GIT_STASH_INCLUDE_UNTRACKED as u32;
1465 /// All ignored files are also stashed and then cleaned up from
1466 /// the working directory
1467 const INCLUDE_IGNORED = raw::GIT_STASH_INCLUDE_IGNORED as u32;
1468 /// All changes in the index and working directory are left intact
1469 const KEEP_ALL = raw::GIT_STASH_KEEP_ALL as u32;
1470 }
1471 }
1472
1473 impl StashFlags {
1474 is_bit_set!(is_default, StashFlags::DEFAULT);
1475 is_bit_set!(is_keep_index, StashFlags::KEEP_INDEX);
1476 is_bit_set!(is_include_untracked, StashFlags::INCLUDE_UNTRACKED);
1477 is_bit_set!(is_include_ignored, StashFlags::INCLUDE_IGNORED);
1478 }
1479
1480 impl Default for StashFlags {
1481 fn default() -> Self {
1482 StashFlags::DEFAULT
1483 }
1484 }
1485
1486 bitflags! {
1487 #[allow(missing_docs)]
1488 pub struct AttrCheckFlags: u32 {
1489 /// Check the working directory, then the index.
1490 const FILE_THEN_INDEX = raw::GIT_ATTR_CHECK_FILE_THEN_INDEX as u32;
1491 /// Check the index, then the working directory.
1492 const INDEX_THEN_FILE = raw::GIT_ATTR_CHECK_INDEX_THEN_FILE as u32;
1493 /// Check the index only.
1494 const INDEX_ONLY = raw::GIT_ATTR_CHECK_INDEX_ONLY as u32;
1495 /// Do not use the system gitattributes file.
1496 const NO_SYSTEM = raw::GIT_ATTR_CHECK_NO_SYSTEM as u32;
1497 }
1498 }
1499
1500 impl Default for AttrCheckFlags {
1501 fn default() -> Self {
1502 AttrCheckFlags::FILE_THEN_INDEX
1503 }
1504 }
1505
1506 bitflags! {
1507 #[allow(missing_docs)]
1508 pub struct DiffFlags: u32 {
1509 /// File(s) treated as binary data.
1510 const BINARY = raw::GIT_DIFF_FLAG_BINARY as u32;
1511 /// File(s) treated as text data.
1512 const NOT_BINARY = raw::GIT_DIFF_FLAG_NOT_BINARY as u32;
1513 /// `id` value is known correct.
1514 const VALID_ID = raw::GIT_DIFF_FLAG_VALID_ID as u32;
1515 /// File exists at this side of the delta.
1516 const EXISTS = raw::GIT_DIFF_FLAG_EXISTS as u32;
1517 }
1518 }
1519
1520 impl DiffFlags {
1521 is_bit_set!(is_binary, DiffFlags::BINARY);
1522 is_bit_set!(is_not_binary, DiffFlags::NOT_BINARY);
1523 is_bit_set!(has_valid_id, DiffFlags::VALID_ID);
1524 is_bit_set!(exists, DiffFlags::EXISTS);
1525 }
1526
1527 bitflags! {
1528 /// Options for [`Reference::normalize_name`].
1529 pub struct ReferenceFormat: u32 {
1530 /// No particular normalization.
1531 const NORMAL = raw::GIT_REFERENCE_FORMAT_NORMAL as u32;
1532 /// Control whether one-level refname are accepted (i.e., refnames that
1533 /// do not contain multiple `/`-separated components). Those are
1534 /// expected to be written only using uppercase letters and underscore
1535 /// (e.g. `HEAD`, `FETCH_HEAD`).
1536 const ALLOW_ONELEVEL = raw::GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL as u32;
1537 /// Interpret the provided name as a reference pattern for a refspec (as
1538 /// used with remote repositories). If this option is enabled, the name
1539 /// is allowed to contain a single `*` in place of a full pathname
1540 /// components (e.g., `foo/*/bar` but not `foo/bar*`).
1541 const REFSPEC_PATTERN = raw::GIT_REFERENCE_FORMAT_REFSPEC_PATTERN as u32;
1542 /// Interpret the name as part of a refspec in shorthand form so the
1543 /// `ALLOW_ONELEVEL` naming rules aren't enforced and `main` becomes a
1544 /// valid name.
1545 const REFSPEC_SHORTHAND = raw::GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND as u32;
1546 }
1547 }
1548
1549 impl ReferenceFormat {
1550 is_bit_set!(is_allow_onelevel, ReferenceFormat::ALLOW_ONELEVEL);
1551 is_bit_set!(is_refspec_pattern, ReferenceFormat::REFSPEC_PATTERN);
1552 is_bit_set!(is_refspec_shorthand, ReferenceFormat::REFSPEC_SHORTHAND);
1553 }
1554
1555 impl Default for ReferenceFormat {
1556 fn default() -> Self {
1557 ReferenceFormat::NORMAL
1558 }
1559 }
1560
1561 #[cfg(test)]
1562 mod tests {
1563 use super::{FileMode, ObjectType};
1564
1565 #[test]
1566 fn convert() {
1567 assert_eq!(ObjectType::Blob.str(), "blob");
1568 assert_eq!(ObjectType::from_str("blob"), Some(ObjectType::Blob));
1569 assert!(ObjectType::Blob.is_loose());
1570 }
1571
1572 #[test]
1573 fn convert_filemode() {
1574 assert_eq!(i32::from(FileMode::Blob), 0o100644);
1575 assert_eq!(i32::from(FileMode::BlobGroupWritable), 0o100664);
1576 assert_eq!(i32::from(FileMode::BlobExecutable), 0o100755);
1577 assert_eq!(u32::from(FileMode::Blob), 0o100644);
1578 assert_eq!(u32::from(FileMode::BlobGroupWritable), 0o100664);
1579 assert_eq!(u32::from(FileMode::BlobExecutable), 0o100755);
1580 }
1581 }