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}