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