crates_index_diff/index/
init.rs

1use crate::index::{CloneOptions, LAST_SEEN_REFNAME};
2use crate::Index;
3use std::borrow::Cow;
4use std::path::Path;
5use std::sync::atomic::AtomicBool;
6
7/// The error returned by various initialization methods.
8#[derive(Debug, thiserror::Error)]
9#[allow(missing_docs)]
10pub enum Error {
11    #[error(transparent)]
12    PrepareClone(#[from] Box<gix::clone::Error>),
13    #[error(transparent)]
14    Fetch(#[from] Box<gix::clone::fetch::Error>),
15    #[error(transparent)]
16    Open(#[from] Box<gix::open::Error>),
17}
18
19impl_from_boxed!(gix::clone::Error => Error::PrepareClone);
20impl_from_boxed!(gix::clone::fetch::Error => Error::Fetch);
21impl_from_boxed!(gix::open::Error => Error::Open);
22
23/// Initialization
24impl Index {
25    /// Return a new `Index` instance from the given `path`, which should contain a bare clone of the `crates.io` index.
26    /// If the directory does not contain the repository or does not exist, it will be cloned from
27    /// the official location automatically (with complete history).
28    ///
29    /// An error will occour if the repository exists and the remote URL does not match the given repository URL.
30    ///
31    /// # Examples
32    ///
33    /// ```no_run
34    /// use std::sync::atomic::AtomicBool;
35    /// use crates_index_diff::{Index, index, git};
36    ///
37    /// # let path = tempdir::TempDir::new("index").unwrap();
38    /// // Note that credentials are automatically picked up from the standard git configuration.
39    /// let mut options = index::CloneOptions {
40    ///   url: "https://github.com/rust-lang/staging.crates.io-index".into(),
41    /// };
42    ///
43    ///
44    /// let index = Index::from_path_or_cloned_with_options(path, gix::progress::Discard, &AtomicBool::default(), options)?;
45    /// # Ok::<(), crates_index_diff::index::init::Error>(())
46    /// ```
47    pub fn from_path_or_cloned_with_options<P>(
48        path: impl AsRef<Path>,
49        progress: P,
50        should_interrupt: &AtomicBool,
51        CloneOptions { url }: CloneOptions,
52    ) -> Result<Index, Error>
53    where
54        P: gix::NestedProgress,
55        P::SubProgress: 'static,
56    {
57        let path = path.as_ref();
58        let mut repo = match gix::open(path) {
59            Ok(repo) => repo,
60            Err(gix::open::Error::NotARepository { .. }) => {
61                let (repo, _out) =
62                    gix::prepare_clone_bare(url, path)?.fetch_only(progress, should_interrupt)?;
63                repo
64            }
65            Err(err) => return Err(err.into()),
66        };
67
68        repo.object_cache_size_if_unset(4 * 1024 * 1024);
69        let remote_name = repo.remote_names().into_iter().next().map(Cow::into_owned);
70        Ok(Index {
71            repo,
72            remote_name,
73            branch_name: "master",
74            seen_ref_name: LAST_SEEN_REFNAME,
75        })
76    }
77
78    /// Return a new `Index` instance from the given `path`, which should contain a bare or non-bare
79    /// clone of the `crates.io` index.
80    /// If the directory does not contain the repository or does not exist, it will be cloned from
81    /// the official location automatically (with complete history).
82    pub fn from_path_or_cloned(path: impl AsRef<Path>) -> Result<Index, Error> {
83        Index::from_path_or_cloned_with_options(
84            path,
85            gix::progress::Discard,
86            &AtomicBool::default(),
87            CloneOptions::default(),
88        )
89    }
90}