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};