1use super::{FileLock, IndexCache};
2use crate::{Error, IndexKrate, KrateName, PathBuf};
3
4pub const CRATES_IO_INDEX: &str = "https://github.com/rust-lang/crates.io-index";
6
7pub struct GitIndex {
11 pub(super) cache: IndexCache,
12 #[allow(dead_code)]
13 pub(super) url: String,
14 pub head: Option<[u8; 40]>,
16}
17
18impl GitIndex {
19 #[inline]
21 pub fn new(il: crate::index::IndexLocation<'_>) -> Result<Self, Error> {
22 if il.url.is_sparse() {
23 return Err(crate::InvalidUrl {
24 url: il.url.as_str().to_owned(),
25 source: crate::InvalidUrlError::SparseForGit,
26 }
27 .into());
28 }
29
30 let (path, url) = il.into_parts()?;
31 Ok(Self {
32 cache: IndexCache::at_path(path),
33 url,
34 head: None,
35 })
36 }
37
38 #[inline]
42 pub fn set_head_commit(&mut self, commit_id: Option<[u8; 20]>) {
43 if let Some(id) = &commit_id {
44 let mut hex_head = [0u8; 40];
45 crate::utils::encode_hex(id, &mut hex_head);
46 self.head = Some(hex_head);
47 } else {
48 self.head = None;
49 }
50 }
51
52 #[inline]
54 pub fn head_commit(&self) -> Option<&str> {
55 self.head.as_ref().map(|hc| {
56 #[allow(unsafe_code)]
58 unsafe {
59 std::str::from_utf8_unchecked(hc)
60 }
61 })
62 }
63
64 #[inline]
69 pub fn cached_krate(
70 &self,
71 name: KrateName<'_>,
72 lock: &FileLock,
73 ) -> Result<Option<IndexKrate>, Error> {
74 self.cache.cached_krate(name, self.head_commit(), lock)
75 }
76
77 #[inline]
82 pub fn write_to_cache(
83 &self,
84 krate: &IndexKrate,
85 blob_id: Option<&str>,
86 lock: &FileLock,
87 ) -> Result<Option<PathBuf>, Error> {
88 let Some(id) = blob_id.or_else(|| self.head_commit()) else {
89 return Ok(None);
90 };
91 self.cache.write_to_cache(krate, id, lock).map(Some)
92 }
93}