Skip to main content

gix_archive/
lib.rs

1//! The implementation of creating an archive from a worktree stream, similar to `git archive`.
2//!
3//! ## Deviation
4//!
5//! This implementation is early and just does the basics. Git does more to support more context when filtering and to keep
6//! more information about entries in the various archive formats.
7//! `tar` is implemented in a very basic fashion only.
8//!
9//! ## Feature Flags
10//! All features are related to which container formats are available.
11#![cfg_attr(
12    all(doc, feature = "document-features"),
13    doc = ::document_features::document_features!()
14)]
15#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]
16#![deny(rust_2018_idioms, missing_docs)]
17#![forbid(unsafe_code)]
18
19use bstr::BString;
20
21/// The error returned by [`write_stream()`].
22pub type Error = gix_error::Exn<gix_error::Message>;
23
24/// The supported container formats for use in [`write_stream()`].
25#[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
26pub enum Format {
27    /// An internal format that is suitable only for intra-process communication.
28    ///
29    /// All transformations in the options are ignored. Calling [`write_stream`] is disallowed
30    /// as it's more efficient to call [gix_worktree_stream::Stream::into_read()] right away.
31    /// It is provided here as a basis available without extra dependencies, and as a debugging tool.
32    #[default]
33    InternalTransientNonPersistable,
34    /// A standard `tar` archive.
35    ///
36    /// Use it as well if a custom container format is desired. The idea is to decode it on a separate thread
37    /// to rewrite the data to the desired format.
38    Tar,
39    /// A convenience format that will `gzip` deflate the `tar` stream.
40    TarGz {
41        /// If `None`, use the default compression level. Otherwise use the given one which
42        /// ranges from 0-9 for the deflate algorithm.
43        compression_level: Option<u8>,
44    },
45    /// A standard `zip` archive. Note that this format silently converts illformed UTF-8 to UTF-8, which will
46    /// equal a change of path.
47    ///
48    /// Requires the `zip` feature toggle to have an effect.
49    ///
50    /// ### Shortcoming
51    ///
52    /// Even though symlinks are stored as such, for some reason at least on MacOS those aren't restored. That works,
53    /// however, when letting `git` create the archive.
54    Zip {
55        /// If `None`, use the default compression level. Otherwise use the given one which
56        /// ranges from 0-9 for the deflate algorithm.
57        compression_level: Option<u8>,
58    },
59}
60
61/// Options for configuring [`write_stream()`].
62#[derive(Clone, Debug)]
63pub struct Options {
64    /// The archive's format.
65    pub format: Format,
66    /// Given a `path`, originating in the git tree, to place into the archive, put `<prefix>/path` in front of it.
67    ///
68    /// Note that `/` should be used as separator, and that a prefix directory has to end with `/`.
69    pub tree_prefix: Option<BString>,
70    /// The modification time for all entries in the archive as seen since UNIX epoch.
71    ///
72    /// Defaults to the current time. The caller may set this to the commit time if available.
73    pub modification_time: gix_date::SecondsSinceUnixEpoch,
74}
75
76impl Default for Options {
77    fn default() -> Self {
78        Options {
79            format: Default::default(),
80            tree_prefix: None,
81            modification_time: std::time::SystemTime::now()
82                .duration_since(std::time::UNIX_EPOCH)
83                .map(|t| t.as_secs() as i64)
84                .unwrap_or_default(),
85        }
86    }
87}
88
89mod write;
90pub use write::{write_stream, write_stream_seek};