Skip to content

Commit afb1960

Browse files
authored
Merge pull request #1012 from NobodyXu/optimization/try-into-de-momo
Optimize `gix`: de-momo `impl TryInto` by hand
2 parents 1f2ffb6 + 3eb8653 commit afb1960

File tree

5 files changed

+98
-26
lines changed

5 files changed

+98
-26
lines changed

gix/src/clone/mod.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,30 @@ impl PrepareFetch {
6868
url: Url,
6969
path: impl AsRef<std::path::Path>,
7070
kind: crate::create::Kind,
71-
mut create_opts: crate::create::Options,
71+
create_opts: crate::create::Options,
7272
open_opts: crate::open::Options,
7373
) -> Result<Self, Error>
7474
where
7575
Url: TryInto<gix_url::Url, Error = E>,
7676
gix_url::parse::Error: From<E>,
7777
{
78-
let mut url = url.try_into().map_err(gix_url::parse::Error::from)?;
78+
Self::new_inner(
79+
url.try_into().map_err(gix_url::parse::Error::from)?,
80+
path.as_ref(),
81+
kind,
82+
create_opts,
83+
open_opts,
84+
)
85+
}
86+
87+
#[allow(clippy::result_large_err)]
88+
fn new_inner(
89+
mut url: gix_url::Url,
90+
path: &std::path::Path,
91+
kind: crate::create::Kind,
92+
mut create_opts: crate::create::Options,
93+
open_opts: crate::open::Options,
94+
) -> Result<Self, Error> {
7995
create_opts.destination_must_be_empty = true;
8096
let mut repo = crate::ThreadSafeRepository::init_opts(path, kind, create_opts, open_opts)?.to_thread_local();
8197
url.canonicalize(repo.options.current_dir_or_empty())

gix/src/remote/build.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ impl Remote<'_> {
1010
Url: TryInto<gix_url::Url, Error = E>,
1111
gix_url::parse::Error: From<E>,
1212
{
13-
self.push_url_inner(url, true)
13+
self.push_url_inner(
14+
url.try_into().map_err(|err| remote::init::Error::Url(err.into()))?,
15+
true,
16+
)
1417
}
1518

1619
/// Set the `url` to be used when pushing data to a remote, without applying rewrite rules in case these could be faulty,
@@ -20,7 +23,10 @@ impl Remote<'_> {
2023
Url: TryInto<gix_url::Url, Error = E>,
2124
gix_url::parse::Error: From<E>,
2225
{
23-
self.push_url_inner(url, false)
26+
self.push_url_inner(
27+
url.try_into().map_err(|err| remote::init::Error::Url(err.into()))?,
28+
false,
29+
)
2430
}
2531

2632
/// Configure how tags should be handled when fetching from the remote.
@@ -29,14 +35,11 @@ impl Remote<'_> {
2935
self
3036
}
3137

32-
fn push_url_inner<Url, E>(mut self, push_url: Url, should_rewrite_urls: bool) -> Result<Self, remote::init::Error>
33-
where
34-
Url: TryInto<gix_url::Url, Error = E>,
35-
gix_url::parse::Error: From<E>,
36-
{
37-
let push_url = push_url
38-
.try_into()
39-
.map_err(|err| remote::init::Error::Url(err.into()))?;
38+
fn push_url_inner(
39+
mut self,
40+
push_url: gix_url::Url,
41+
should_rewrite_urls: bool,
42+
) -> Result<Self, remote::init::Error> {
4043
self.push_url = push_url.into();
4144

4245
let (_, push_url_alias) = should_rewrite_urls

gix/src/remote/init.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,18 @@ impl<'repo> Remote<'repo> {
6767
Url: TryInto<gix_url::Url, Error = E>,
6868
gix_url::parse::Error: From<E>,
6969
{
70-
let url = url.try_into().map_err(|err| Error::Url(err.into()))?;
70+
Self::from_fetch_url_inner(
71+
url.try_into().map_err(|err| Error::Url(err.into()))?,
72+
should_rewrite_urls,
73+
repo,
74+
)
75+
}
76+
77+
fn from_fetch_url_inner(
78+
url: gix_url::Url,
79+
should_rewrite_urls: bool,
80+
repo: &'repo Repository,
81+
) -> Result<Self, Error> {
7182
let (url_alias, _) = should_rewrite_urls
7283
.then(|| rewrite_urls(&repo.config, Some(&url), None))
7384
.unwrap_or(Ok((None, None)))?;

gix/src/repository/object.rs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use gix_ref::{
88
transaction::{LogChange, PreviousValue, RefLog},
99
FullName,
1010
};
11+
use smallvec::SmallVec;
1112

1213
use crate::{commit, ext::ObjectIdExt, object, tag, Id, Object, Reference, Tree};
1314

@@ -115,13 +116,17 @@ impl crate::Repository {
115116
let mut buf = self.shared_empty_buf();
116117
object.write_to(buf.deref_mut()).expect("write to memory works");
117118

118-
let oid = gix_object::compute_hash(self.object_hash(), object.kind(), &buf);
119+
self.write_object_inner(&buf, object.kind())
120+
}
121+
122+
fn write_object_inner(&self, buf: &[u8], kind: gix_object::Kind) -> Result<Id<'_>, object::write::Error> {
123+
let oid = gix_object::compute_hash(self.object_hash(), kind, buf);
119124
if self.objects.contains(&oid) {
120125
return Ok(oid.attach(self));
121126
}
122127

123128
self.objects
124-
.write_buf(object.kind(), &buf)
129+
.write_buf(kind, buf)
125130
.map(|oid| oid.attach(self))
126131
.map_err(Into::into)
127132
}
@@ -130,6 +135,7 @@ impl crate::Repository {
130135
///
131136
/// We avoid writing duplicate objects to slow disks that will eventually have to be garbage collected by
132137
/// pre-hashing the data, and checking if the object is already present.
138+
#[momo]
133139
pub fn write_blob(&self, bytes: impl AsRef<[u8]>) -> Result<Id<'_>, object::write::Error> {
134140
let bytes = bytes.as_ref();
135141
let oid = gix_object::compute_hash(self.object_hash(), gix_object::Kind::Blob, bytes);
@@ -154,13 +160,18 @@ impl crate::Repository {
154160
) -> Result<Id<'_>, object::write::Error> {
155161
let mut buf = self.shared_empty_buf();
156162
std::io::copy(&mut bytes, buf.deref_mut()).expect("write to memory works");
157-
let oid = gix_object::compute_hash(self.object_hash(), gix_object::Kind::Blob, &buf);
163+
164+
self.write_blob_stream_inner(&buf)
165+
}
166+
167+
fn write_blob_stream_inner(&self, buf: &[u8]) -> Result<Id<'_>, object::write::Error> {
168+
let oid = gix_object::compute_hash(self.object_hash(), gix_object::Kind::Blob, buf);
158169
if self.objects.contains(&oid) {
159170
return Ok(oid.attach(self));
160171
}
161172

162173
self.objects
163-
.write_buf(gix_object::Kind::Blob, &buf)
174+
.write_buf(gix_object::Kind::Blob, buf)
164175
.map_err(Into::into)
165176
.map(|oid| oid.attach(self))
166177
}
@@ -208,21 +219,39 @@ impl crate::Repository {
208219
Name: TryInto<FullName, Error = E>,
209220
commit::Error: From<E>,
210221
{
222+
self.commit_as_inner(
223+
committer.into(),
224+
author.into(),
225+
reference.try_into()?,
226+
message.as_ref(),
227+
tree.into(),
228+
parents.into_iter().map(Into::into).collect(),
229+
)
230+
}
231+
232+
fn commit_as_inner(
233+
&self,
234+
committer: gix_actor::SignatureRef<'_>,
235+
author: gix_actor::SignatureRef<'_>,
236+
reference: FullName,
237+
message: &str,
238+
tree: ObjectId,
239+
parents: SmallVec<[gix_hash::ObjectId; 1]>,
240+
) -> Result<Id<'_>, commit::Error> {
211241
use gix_ref::{
212242
transaction::{Change, RefEdit},
213243
Target,
214244
};
215245

216246
// TODO: possibly use CommitRef to save a few allocations (but will have to allocate for object ids anyway.
217247
// This can be made vastly more efficient though if we wanted to, so we lie in the API
218-
let reference = reference.try_into()?;
219248
let commit = gix_object::Commit {
220-
message: message.as_ref().into(),
221-
tree: tree.into(),
222-
author: author.into().to_owned(),
223-
committer: committer.into().to_owned(),
249+
message: message.into(),
250+
tree,
251+
author: author.into(),
252+
committer: committer.into(),
224253
encoding: None,
225-
parents: parents.into_iter().map(Into::into).collect(),
254+
parents,
226255
extra_headers: Default::default(),
227256
};
228257

gix/src/repository/reference.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,27 @@ impl crate::Repository {
8787
Name: TryInto<FullName, Error = E>,
8888
gix_validate::reference::name::Error: From<E>,
8989
{
90-
let name = name.try_into().map_err(gix_validate::reference::name::Error::from)?;
91-
let id = target.into();
90+
self.reference_inner(
91+
name.try_into().map_err(gix_validate::reference::name::Error::from)?,
92+
target.into(),
93+
constraint,
94+
log_message.into(),
95+
)
96+
}
97+
98+
fn reference_inner(
99+
&self,
100+
name: FullName,
101+
id: ObjectId,
102+
constraint: PreviousValue,
103+
log_message: BString,
104+
) -> Result<Reference<'_>, reference::edit::Error> {
92105
let mut edits = self.edit_reference(RefEdit {
93106
change: Change::Update {
94107
log: LogChange {
95108
mode: RefLog::AndReference,
96109
force_create_reflog: false,
97-
message: log_message.into(),
110+
message: log_message,
98111
},
99112
expected: constraint,
100113
new: Target::Peeled(id),

0 commit comments

Comments
 (0)