Unified · Split
| @@ -1,7 +1,7 @@ | |||
| 1 | use quick_error::quick_error; | 1 | use quick_error::quick_error; |
| 2 | 2 | ||
| 3 | use crate::{ | 3 | use crate::{ |
| 4 | file::{self}, | 4 | file, |
| 5 | mutable::Target, | 5 | mutable::Target, |
| 6 | store::{ | 6 | store::{ |
| 7 | file::{find, loose}, | 7 | file::{find, loose}, |
| @@ -10,7 +10,7 @@ use crate::{ · 2 unmodified lines | |||
| 10 | }; | 10 | }; |
| 11 | 11 | ||
| 12 | quick_error! { | 12 | quick_error! { |
| 13 | /// The error returned by [`Reference::peel_one_level()`]. | 13 | /// The error returned by [`loose::Reference::follow_symbolic()`]. |
| 14 | #[derive(Debug)] | 14 | #[derive(Debug)] |
| 15 | #[allow(missing_docs)] | 15 | #[allow(missing_docs)] |
| 16 | pub enum Error { | 16 | pub enum Error { |
| @@ -18,13 +18,18 @@ quick_error! { · 1 unmodified line | |||
| 18 | display("Could not resolve symbolic reference name that is expected to exist") | 18 | display("Could not resolve symbolic reference name that is expected to exist") |
| 19 | source(err) | 19 | source(err) |
| 20 | } | 20 | } |
| 21 | Decode(err: file::loose::reference::decode::Error) { | 21 | Decode(err: loose::reference::decode::Error) { |
| 22 | display("The reference could not be decoded.") | 22 | display("The reference could not be decoded.") |
| 23 | source(err) | 23 | source(err) |
| 24 | } | 24 | } |
| 25 | } | 25 | } |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | /// A function for use in [`loose::Reference::peel_to_id_in_place()`] to indicate no peeling should happen. | ||
| 29 | pub fn none(_id: &git_hash::oid) -> Result<Option<(git_object::Kind, &'_ [u8])>, Box<dyn std::error::Error>> { | ||
| 30 | Ok(Some((git_object::Kind::Commit, &[]))) | ||
| 31 | } | ||
| 32 | |||
| 28 | impl loose::Reference { | 33 | impl loose::Reference { |
| 29 | /// Follow this symbolic reference one level and return the ref it refers to, possibly providing access to `packed` references for lookup. | 34 | /// Follow this symbolic reference one level and return the ref it refers to, possibly providing access to `packed` references for lookup. |
| 30 | /// | 35 | /// |
| @@ -89,6 +94,7 @@ pub mod to_id { · 58 unmodified lines | |||
| 89 | &mut self, | 94 | &mut self, |
| 90 | store: &file::Store, | 95 | store: &file::Store, |
| 91 | packed: Option<&packed::Buffer>, | 96 | packed: Option<&packed::Buffer>, |
| 97 | _find: impl FnMut(&git_hash::oid) -> Result<Option<(git_object::Kind, &[u8])>, Box<dyn std::error::Error>>, | ||
| 92 | ) -> Result<&oid, Error> { | 98 | ) -> Result<&oid, Error> { |
| 93 | let mut seen = BTreeSet::new(); | 99 | let mut seen = BTreeSet::new(); |
| 94 | let mut storage; | 100 | let mut storage; |
| @@ -56,9 +56,10 @@ impl<'p> Reference<'p> { · 55 unmodified lines | |||
| 56 | &mut self, | 56 | &mut self, |
| 57 | store: &file::Store, | 57 | store: &file::Store, |
| 58 | packed: Option<&packed::Buffer>, | 58 | packed: Option<&packed::Buffer>, |
| 59 | find: impl FnMut(&git_hash::oid) -> Result<Option<(git_object::Kind, &[u8])>, Box<dyn std::error::Error>>, | ||
| 59 | ) -> Result<ObjectId, crate::store::file::loose::reference::peel::to_id::Error> { | 60 | ) -> Result<ObjectId, crate::store::file::loose::reference::peel::to_id::Error> { |
| 60 | match self { | 61 | match self { |
| 61 | Reference::Loose(r) => r.peel_to_id_in_place(store, packed).map(ToOwned::to_owned), | 62 | Reference::Loose(r) => r.peel_to_id_in_place(store, packed, find).map(ToOwned::to_owned), |
| 62 | Reference::Packed(p) => { | 63 | Reference::Packed(p) => { |
| 63 | if let Some(object) = p.object { | 64 | if let Some(object) = p.object { |
| 64 | p.target = object; | 65 | p.target = object; |
| @@ -69,7 +70,7 @@ impl<'p> Reference<'p> { · 4 unmodified lines | |||
| 69 | } | 70 | } |
| 70 | } | 71 | } |
| 71 | 72 | ||
| 72 | /// For details, see [crate::file::loose::Reference::peel_one_level]. | 73 | /// For details, see [crate::file::loose::Reference::follow_symbolic()]. |
| 73 | pub fn peel_one_level<'p2>( | 74 | pub fn peel_one_level<'p2>( |
| 74 | &self, | 75 | &self, |
| 75 | store: &file::Store, | 76 | store: &file::Store, |
| @@ -50,6 +50,7 @@ mod reflog { · 49 unmodified lines | |||
| 50 | 50 | ||
| 51 | mod peel { | 51 | mod peel { |
| 52 | use crate::{file, file::store_with_packed_refs}; | 52 | use crate::{file, file::store_with_packed_refs}; |
| 53 | use git_ref::file::loose::reference::peel; | ||
| 53 | use git_testtools::hex_to_id; | 54 | use git_testtools::hex_to_id; |
| 54 | use std::convert::TryFrom; | 55 | use std::convert::TryFrom; |
| 55 | 56 | ||
| @@ -82,11 +83,11 @@ mod peel { · 26 unmodified lines | |||
| 82 | let mut head = store.loose_find_existing("HEAD")?; | 83 | let mut head = store.loose_find_existing("HEAD")?; |
| 83 | let packed = store.packed()?; | 84 | let packed = store.packed()?; |
| 84 | let expected = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03"); | 85 | let expected = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03"); |
| 85 | assert_eq!(head.peel_to_id_in_place(&store, packed.as_ref())?, expected); | 86 | assert_eq!(head.peel_to_id_in_place(&store, packed.as_ref(), peel::none)?, expected); |
| 86 | assert_eq!(head.target.as_id().map(ToOwned::to_owned), Some(expected)); | 87 | assert_eq!(head.target.as_id().map(ToOwned::to_owned), Some(expected)); |
| 87 | 88 | ||
| 88 | let mut head = store.find_existing("dt1", packed.as_ref())?; | 89 | let mut head = store.find_existing("dt1", packed.as_ref())?; |
| 89 | assert_eq!(head.peel_to_id_in_place(&store, packed.as_ref())?, expected); | 90 | assert_eq!(head.peel_to_id_in_place(&store, packed.as_ref(), peel::none)?, expected); |
| 90 | assert_eq!(head.target().as_id().map(ToOwned::to_owned), Some(expected)); | 91 | assert_eq!(head.target().as_id().map(ToOwned::to_owned), Some(expected)); |
| 91 | Ok(()) | 92 | Ok(()) |
| 92 | } | 93 | } |
| @@ -128,7 +129,7 @@ mod peel { · 35 unmodified lines | |||
| 128 | assert_eq!(r.kind(), git_ref::Kind::Symbolic, "there is something to peel"); | 129 | assert_eq!(r.kind(), git_ref::Kind::Symbolic, "there is something to peel"); |
| 129 | 130 | ||
| 130 | assert_eq!( | 131 | assert_eq!( |
| 131 | r.peel_to_id_in_place(&store, None)?, | 132 | r.peel_to_id_in_place(&store, None, peel::none)?, |
| 132 | hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03") | 133 | hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03") |
| 133 | ); | 134 | ); |
| 134 | assert_eq!(r.name.as_bstr(), "refs/remotes/origin/multi-link-target3"); | 135 | assert_eq!(r.name.as_bstr(), "refs/remotes/origin/multi-link-target3"); |
| @@ -144,7 +145,7 @@ mod peel { · 9 unmodified lines | |||
| 144 | assert_eq!(r.name.as_bstr(), "refs/loop-a"); | 145 | assert_eq!(r.name.as_bstr(), "refs/loop-a"); |
| 145 | 146 | ||
| 146 | assert!(matches!( | 147 | assert!(matches!( |
| 147 | r.peel_to_id_in_place(&store, None).unwrap_err(), | 148 | r.peel_to_id_in_place(&store, None, peel::none).unwrap_err(), |
| 148 | git_ref::file::loose::reference::peel::to_id::Error::Cycle { .. } | 149 | git_ref::file::loose::reference::peel::to_id::Error::Cycle { .. } |
| 149 | )); | 150 | )); |
| 150 | assert_eq!(r.name.as_bstr(), "refs/loop-a", "the ref is not changed on error"); | 151 | assert_eq!(r.name.as_bstr(), "refs/loop-a", "the ref is not changed on error"); |
| @@ -1,6 +1,8 @@ | |||
| 1 | use anyhow::{anyhow, bail}; | 1 | use anyhow::{anyhow, bail}; |
| 2 | use bstr::BString; | 2 | use bstr::BString; |
| 3 | use git_repository::{actor, interrupt, object, odb, prelude::*, progress, Progress}; | 3 | use git_repository::{ |
| 4 | actor, interrupt, object, odb, prelude::*, progress, refs::file::loose::reference::peel, Progress, | ||
| 5 | }; | ||
| 4 | use itertools::Itertools; | 6 | use itertools::Itertools; |
| 5 | use rayon::prelude::*; | 7 | use rayon::prelude::*; |
| 6 | use std::{ | 8 | use std::{ |
| @@ -49,7 +51,7 @@ where · 42 unmodified lines | |||
| 49 | let commit_id = repo | 51 | let commit_id = repo |
| 50 | .refs | 52 | .refs |
| 51 | .find_existing(refname.to_string_lossy().as_ref(), packed.as_ref())? | 53 | .find_existing(refname.to_string_lossy().as_ref(), packed.as_ref())? |
| 52 | .peel_to_id_in_place(&repo.refs, packed.as_ref())? | 54 | .peel_to_id_in_place(&repo.refs, packed.as_ref(), peel::none)? |
| 53 | .to_owned(); | 55 | .to_owned(); |
| 54 | 56 | ||
| 55 | let all_commits = { | 57 | let all_commits = { |
| @@ -1,14 +1,15 @@ | |||
| 1 | use crate::OutputFormat; | 1 | use crate::OutputFormat; |
| 2 | use anyhow::anyhow; | 2 | use anyhow::anyhow; |
| 3 | use git_repository::odb::pack::cache::DecodeEntry; | ||
| 4 | use git_repository::{ | 3 | use git_repository::{ |
| 5 | hash, | 4 | hash, |
| 6 | hash::ObjectId, | 5 | hash::ObjectId, |
| 7 | interrupt, | 6 | interrupt, |
| 8 | object::bstr::ByteVec, | 7 | object::bstr::ByteVec, |
| 9 | odb::pack, | 8 | odb::{pack, pack::cache::DecodeEntry}, |
| 10 | prelude::{Finalize, FindExt}, | 9 | prelude::{Finalize, FindExt}, |
| 11 | progress, traverse, Progress, | 10 | progress, |
| 11 | refs::file::loose::reference::peel, | ||
| 12 | traverse, Progress, | ||
| 12 | }; | 13 | }; |
| 13 | use std::{ffi::OsStr, io, path::Path, str::FromStr, sync::Arc, time::Instant}; | 14 | use std::{ffi::OsStr, io, path::Path, str::FromStr, sync::Arc, time::Instant}; |
| 14 | 15 | ||
| @@ -113,7 +114,7 @@ where · 98 unmodified lines | |||
| 113 | refs.find_existing(tip.as_ref().to_string_lossy().as_ref(), packed.as_ref()) | 114 | refs.find_existing(tip.as_ref().to_string_lossy().as_ref(), packed.as_ref()) |
| 114 | .map_err(anyhow::Error::from) | 115 | .map_err(anyhow::Error::from) |
| 115 | .and_then(|mut r| { | 116 | .and_then(|mut r| { |
| 116 | r.peel_to_id_in_place(refs, packed.as_ref()) | 117 | r.peel_to_id_in_place(refs, packed.as_ref(), peel::none) |
| 117 | .map(|oid| oid.to_owned()) | 118 | .map(|oid| oid.to_owned()) |
| 118 | .map_err(anyhow::Error::from) | 119 | .map_err(anyhow::Error::from) |
| 119 | }) | 120 | }) |