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}