Skip to content

Commit

Permalink
Merge branch 'improvements'
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Aug 7, 2024
2 parents 2e00b5e + 6ac2867 commit 29898e3
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 8 deletions.
2 changes: 1 addition & 1 deletion gix/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ max-control = ["parallel", "pack-cache-lru-static", "pack-cache-lru-dynamic"]
## on some platforms.
## Note that this configuration still uses a pure Rust zlib implementation which isn't the fastest compared to its C-alternatives.
## No C toolchain is involved.
max-performance-safe = ["max-control", "parallel-walkdir"]
max-performance-safe = ["max-control"]

## If set, walkdir iterators will be multi-threaded which affects the listing of loose objects and references.
## Note, however, that this will use `rayon` under the hood and spawn threads for each traversal to avoid a global rayon thread pool.
Expand Down
14 changes: 14 additions & 0 deletions gix/src/reference/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ impl<'repo> Reference<'repo> {
Ok(Id::from_id(oid, self.repo))
}

/// Follow all symbolic targets this reference might point to and peel the underlying object
/// to the end of the chain, and return it, reusing the `packed` buffer if available.
///
/// This is useful to learn where this reference is ultimately pointing to.
pub fn peel_to_id_in_place_packed(
&mut self,
packed: Option<&gix_ref::packed::Buffer>,
) -> Result<Id<'repo>, peel::Error> {
let oid = self
.inner
.peel_to_id_in_place_packed(&self.repo.refs, &self.repo.objects, packed)?;
Ok(Id::from_id(oid, self.repo))
}

/// Similar to [`peel_to_id_in_place()`][Reference::peel_to_id_in_place()], but consumes this instance.
pub fn into_fully_peeled_id(mut self) -> Result<Id<'repo>, peel::Error> {
self.peel_to_id_in_place()
Expand Down
30 changes: 27 additions & 3 deletions gix/src/reference/remote.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::bstr::ByteSlice;
use crate::repository::{branch_remote_ref_name, branch_remote_tracking_ref_name};
use crate::{remote, Reference};
use gix_ref::FullNameRef;
use gix_ref::{Category, FullNameRef};
use std::borrow::Cow;

/// Remotes
Expand All @@ -9,8 +10,31 @@ impl<'repo> Reference<'repo> {
/// Return `None` if no remote is configured.
///
/// See also [`Repository::branch_remote_name()`](crate::Repository::branch_remote_name()) for more details.
pub fn remote_name(&self, direction: remote::Direction) -> Option<remote::Name<'repo>> {
self.repo.branch_remote_name(self.name().shorten(), direction)
pub fn remote_name(&self, direction: remote::Direction) -> Option<remote::Name<'_>> {
let (category, shortname) = self.name().category_and_short_name()?;
match category {
Category::RemoteBranch => {
if shortname.find_iter("/").take(2).count() == 1 {
let slash_pos = shortname.find_byte(b'/').expect("it was just found");
shortname[..slash_pos]
.as_bstr()
.to_str()
.ok()
.map(|n| remote::Name::Symbol(n.into()))
} else {
let remotes = self.repo.remote_names();
for slash_pos in shortname.rfind_iter("/") {
let candidate = shortname[..slash_pos].as_bstr();
if remotes.contains(candidate) {
return candidate.to_str().ok().map(|n| remote::Name::Symbol(n.into()));
}
}
None
}
}
Category::LocalBranch => self.repo.branch_remote_name(shortname, direction),
_ => None,
}
}

/// Find the remote along with all configuration associated with it suitable for handling this reference.
Expand Down
7 changes: 5 additions & 2 deletions gix/src/remote/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::borrow::Cow;

use crate::bstr::BStr;
use std::borrow::Cow;
use std::collections::BTreeSet;

/// The direction of an operation carried out (or to be carried out) through a remote.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
Expand Down Expand Up @@ -31,6 +31,9 @@ pub enum Name<'repo> {
Url(Cow<'repo, BStr>),
}

/// A type-definition for a sorted list of unvalidated remote names - they have been read straight from the configuration.
pub type Names<'a> = BTreeSet<Cow<'a, BStr>>;

///
#[allow(clippy::empty_docs)]
pub mod name;
Expand Down
4 changes: 2 additions & 2 deletions gix/src/repository/config/remote.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::bstr::BStr;
use std::{borrow::Cow, collections::BTreeSet};
use std::borrow::Cow;

use crate::config::tree::{Remote, Section};
use crate::remote;
Expand All @@ -8,7 +8,7 @@ use crate::remote;
impl crate::Repository {
/// Returns a sorted list unique of symbolic names of remotes that
/// we deem [trustworthy][crate::open::Options::filter_config_section()].
pub fn remote_names(&self) -> BTreeSet<Cow<'_, BStr>> {
pub fn remote_names(&self) -> remote::Names<'_> {
self.config
.resolved
.sections_by_name(Remote.name())
Expand Down
Binary file not shown.
10 changes: 10 additions & 0 deletions gix/tests/fixtures/make_remote_config_repos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,13 @@ EOF
pushDefault = push-origin
EOF
)

git clone fetch multiple-remotes
(cd multiple-remotes
git remote add other ../fetch && git fetch other
git remote add with/two/slashes ../fetch && git fetch with/two/slashes
git remote add with/two ../fetch && git fetch with/two

git checkout -b main --track origin/main
git checkout -b other-main --track other/main
)
27 changes: 27 additions & 0 deletions gix/tests/reference/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use gix::remote::Direction;

mod log {

#[test]
Expand All @@ -17,6 +19,31 @@ mod log {
);
}
}

#[test]
fn remote_name() -> crate::Result {
let repo = crate::named_subrepo_opts(
"make_remote_config_repos.sh",
"multiple-remotes",
gix::open::Options::isolated(),
)?;
for (ref_name, expected_remote) in [
("main", "origin"),
("other-main", "other"),
("refs/remotes/origin/main", "origin"),
("refs/remotes/other/main", "other"),
("with/two/slashes/main", "with/two/slashes"),
("with/two/main", "with/two"),
] {
let r = repo.find_reference(ref_name)?;
assert_eq!(
r.remote_name(Direction::Fetch).map(|name| name.as_bstr().to_owned()),
Some(expected_remote.into())
);
}
Ok(())
}

mod find {
use gix_ref as refs;
use gix_ref::{FullName, FullNameRef, Target};
Expand Down

0 comments on commit 29898e3

Please sign in to comment.