Skip to content

Commit 39d585d

Browse files
committed
Merge branch 'remote-ls-refs'
2 parents f90d772 + dcd6619 commit 39d585d

File tree

122 files changed

+4143
-1911
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+4143
-1911
lines changed

Cargo.lock

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ check: ## Build all code in suitable configurations
110110
cd git-transport && cargo check \
111111
&& cargo check --features blocking-client \
112112
&& cargo check --features async-client \
113+
&& cargo check --features async-client,async-std \
113114
&& cargo check --features http-client-curl
114115
cd git-transport && if cargo check --all-features 2>/dev/null; then false; else true; fi
115116
cd git-protocol && cargo check \
@@ -118,6 +119,7 @@ check: ## Build all code in suitable configurations
118119
cd git-protocol && if cargo check --all-features 2>/dev/null; then false; else true; fi
119120
cd git-repository && cargo check --no-default-features --features local \
120121
&& cargo check --no-default-features --features async-network-client \
122+
&& cargo check --no-default-features --features async-network-client-async-std \
121123
&& cargo check --no-default-features --features blocking-network-client \
122124
&& cargo check --no-default-features --features blocking-network-client,blocking-http-transport \
123125
&& cargo check --no-default-features --features one-stop-shop \
@@ -151,6 +153,8 @@ unit-tests: ## run all unit tests
151153
&& cargo test --features async-client \
152154
&& cargo test
153155
cd git-repository && cargo test \
156+
&& cargo test --features async-network-client \
157+
&& cargo test --features blocking-network-client \
154158
&& cargo test --features regex
155159
cd gitoxide-core && cargo test --lib
156160

cargo-smart-release/src/changelog/write.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl From<git::Url> for RepositoryUrl {
5050

5151
impl RepositoryUrl {
5252
pub fn is_github(&self) -> bool {
53-
self.inner.host.as_ref().map(|h| h == "github.com").unwrap_or(false)
53+
self.inner.host().map(|h| h == "github.com").unwrap_or(false)
5454
}
5555

5656
fn cleaned_path(&self) -> String {
@@ -59,15 +59,14 @@ impl RepositoryUrl {
5959
}
6060

6161
pub fn github_https(&self) -> Option<String> {
62-
match &self.inner.host {
63-
Some(host) if host == "github.com" => match self.inner.scheme {
62+
match &self.inner.host() {
63+
Some(host) if *host == "github.com" => match self.inner.scheme {
6464
Scheme::Http | Scheme::Https | Scheme::Git => {
6565
format!("https://github.com{}", self.cleaned_path()).into()
6666
}
6767
Scheme::Ssh => self
6868
.inner
69-
.user
70-
.as_ref()
69+
.user()
7170
.map(|user| format!("https://github.com{}/{}", user, self.cleaned_path())),
7271
Scheme::Radicle | Scheme::File => None,
7372
},

crate-status.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ Check out the [performance discussion][git-traverse-performance] as well.
237237
### git-refspec
238238
* [x] parse
239239
* [ ] matching of references and object names
240+
* [ ] for fetch
241+
* [ ] for push
240242

241243
### git-note
242244

@@ -459,9 +461,19 @@ See its [README.md](https://github.com/Byron/gitoxide/blob/main/git-lock/README.
459461
* **references**
460462
* [x] peel to end
461463
* [x] ref-log access
462-
* [ ] clone from remote
463-
* [ ] shallow
464-
* [ ] execute hooks
464+
* [x] remote name
465+
* [x] find remote itself
466+
- [ ] respect `branch.<name>.merge` in the returned remote.
467+
* **remotes**
468+
* [ ] clone
469+
* [ ] shallow
470+
* [ ] fetch
471+
* [ ] push
472+
* [ ] ls-refs
473+
* [ ] list, find by name, create in memory.
474+
* [ ] groups
475+
* [ ] [remote and branch files](https://github.com/git/git/blob/master/remote.c#L300)
476+
* [ ] execute hooks
465477
* **refs**
466478
* [ ] run transaction hooks and handle special repository states like quarantine
467479
* [ ] support for different backends like `files` and `reftable`
@@ -488,7 +500,6 @@ See its [README.md](https://github.com/Byron/gitoxide/blob/main/git-lock/README.
488500
* [x] read and interpolate trusted paths
489501
* [x] low-level API for more elaborate access to all details of `git-config` files
490502
* [ ] a way to make changes to individual configuration files
491-
* [ ] remotes with push and pull
492503
* [x] mailmap
493504
* [x] object replacements (`git replace`)
494505
* [ ] configuration

etc/check-package-size.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@ echo "in root: gitoxide CLI"
5353
(enter git-odb && indent cargo diet -n --package-size-limit 120KB)
5454
(enter git-protocol && indent cargo diet -n --package-size-limit 50KB)
5555
(enter git-packetline && indent cargo diet -n --package-size-limit 35KB)
56-
(enter git-repository && indent cargo diet -n --package-size-limit 140KB)
56+
(enter git-repository && indent cargo diet -n --package-size-limit 150KB)
5757
(enter git-transport && indent cargo diet -n --package-size-limit 50KB)
5858
(enter gitoxide-core && indent cargo diet -n --package-size-limit 80KB)

git-config/src/file/access/comfort.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use std::{borrow::Cow, convert::TryFrom};
22

33
use bstr::BStr;
44

5-
use crate::{file::MetadataFilter, value, File};
5+
use crate::parse::section;
6+
use crate::{file::MetadataFilter, lookup, value, File};
67

78
/// Comfortable API for accessing values
89
impl<'event> File<'event> {
@@ -80,9 +81,20 @@ impl<'event> File<'event> {
8081
key: impl AsRef<str>,
8182
filter: &mut MetadataFilter,
8283
) -> Option<Result<bool, value::Error>> {
83-
self.raw_value_filter(section_name, subsection_name, key, filter)
84-
.ok()
85-
.map(|v| crate::Boolean::try_from(v).map(|b| b.into()))
84+
let section_name = section_name.as_ref();
85+
let key = key.as_ref();
86+
match self.raw_value_filter(section_name, subsection_name, key, filter) {
87+
Ok(v) => Some(crate::Boolean::try_from(v).map(|b| b.into())),
88+
Err(lookup::existing::Error::KeyMissing) => {
89+
let section = self
90+
.section_filter(section_name, subsection_name, filter)
91+
.ok()
92+
.flatten()?;
93+
let key = section::Key::try_from(key).ok()?;
94+
section.key_and_value_range_by(&key).map(|_| Ok(true))
95+
}
96+
Err(_err) => None,
97+
}
8698
}
8799

88100
/// Like [`value()`][File::value()], but returning an `Option` if the integer wasn't found.

git-config/src/file/access/mutate.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111

1212
/// Mutating low-level access methods.
1313
impl<'event> File<'event> {
14-
/// Returns an mutable section with a given `name` and optional `subsection_name`.
14+
/// Returns an mutable section with a given `name` and optional `subsection_name`, _if it exists_.
1515
pub fn section_mut<'a>(
1616
&'a mut self,
1717
name: impl AsRef<str>,
@@ -29,8 +29,46 @@ impl<'event> File<'event> {
2929
.expect("BUG: Section did not have id from lookup")
3030
.to_mut(nl))
3131
}
32+
/// Returns an mutable section with a given `name` and optional `subsection_name`, _if it exists_, or create a new section.
33+
pub fn section_mut_or_create_new<'a>(
34+
&'a mut self,
35+
name: impl AsRef<str>,
36+
subsection_name: Option<&str>,
37+
) -> Result<SectionMut<'a, 'event>, section::header::Error> {
38+
self.section_mut_or_create_new_filter(name, subsection_name, &mut |_| true)
39+
}
40+
41+
/// Returns an mutable section with a given `name` and optional `subsection_name`, _if it exists_ **and** passes `filter`, or create
42+
/// a new section.
43+
pub fn section_mut_or_create_new_filter<'a>(
44+
&'a mut self,
45+
name: impl AsRef<str>,
46+
subsection_name: Option<&str>,
47+
filter: &mut MetadataFilter,
48+
) -> Result<SectionMut<'a, 'event>, section::header::Error> {
49+
let name = name.as_ref();
50+
match self
51+
.section_ids_by_name_and_subname(name.as_ref(), subsection_name)
52+
.ok()
53+
.and_then(|it| {
54+
it.rev().find(|id| {
55+
let s = &self.sections[id];
56+
filter(s.meta())
57+
})
58+
}) {
59+
Some(id) => {
60+
let nl = self.detect_newline_style_smallvec();
61+
Ok(self
62+
.sections
63+
.get_mut(&id)
64+
.expect("BUG: Section did not have id from lookup")
65+
.to_mut(nl))
66+
}
67+
None => self.new_section(name.to_owned(), subsection_name.map(|n| Cow::Owned(n.to_owned()))),
68+
}
69+
}
3270

33-
/// Returns the last found mutable section with a given `name` and optional `subsection_name`, that matches `filter`.
71+
/// Returns the last found mutable section with a given `name` and optional `subsection_name`, that matches `filter`, _if it exists_.
3472
///
3573
/// If there are sections matching `section_name` and `subsection_name` but the `filter` rejects all of them, `Ok(None)`
3674
/// is returned.
@@ -78,7 +116,7 @@ impl<'event> File<'event> {
78116
/// # use git_config::parse::section;
79117
/// let mut git_config = git_config::File::default();
80118
/// let mut section = git_config.new_section("hello", Some("world".into()))?;
81-
/// section.push(section::Key::try_from("a")?, "b");
119+
/// section.push(section::Key::try_from("a")?, Some("b".into()));
82120
/// let nl = section.newline().to_owned();
83121
/// assert_eq!(git_config.to_string(), format!("[hello \"world\"]{nl}\ta = b{nl}"));
84122
/// let _section = git_config.new_section("core", None);

git-config/src/file/access/raw.rs

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::convert::TryInto;
12
use std::{borrow::Cow, collections::HashMap};
23

34
use bstr::BStr;
@@ -329,7 +330,9 @@ impl<'event> File<'event> {
329330
}
330331
}
331332

332-
/// Sets a value in a given section, optional subsection, and key value.
333+
/// Sets a value in a given `section_name`, optional `subsection_name`, and `key`.
334+
/// Note sections named `section_name` and `subsection_name` (if not `None`)
335+
/// must exist for this method to work.
333336
///
334337
/// # Examples
335338
///
@@ -351,7 +354,7 @@ impl<'event> File<'event> {
351354
/// # use bstr::BStr;
352355
/// # use std::convert::TryFrom;
353356
/// # let mut git_config = git_config::File::try_from("[core]a=b\n[core]\na=c\na=d").unwrap();
354-
/// git_config.set_raw_value("core", None, "a", "e".into())?;
357+
/// git_config.set_existing_raw_value("core", None, "a", "e")?;
355358
/// assert_eq!(git_config.raw_value("core", None, "a")?, Cow::<BStr>::Borrowed("e".into()));
356359
/// assert_eq!(
357360
/// git_config.raw_values("core", None, "a")?,
@@ -363,17 +366,76 @@ impl<'event> File<'event> {
363366
/// );
364367
/// # Ok::<(), Box<dyn std::error::Error>>(())
365368
/// ```
366-
pub fn set_raw_value(
369+
pub fn set_existing_raw_value<'b>(
367370
&mut self,
368371
section_name: impl AsRef<str>,
369372
subsection_name: Option<&str>,
370373
key: impl AsRef<str>,
371-
new_value: &BStr,
374+
new_value: impl Into<&'b BStr>,
372375
) -> Result<(), lookup::existing::Error> {
373376
self.raw_value_mut(section_name, subsection_name, key.as_ref())
374377
.map(|mut entry| entry.set(new_value))
375378
}
376379

380+
/// Sets a value in a given `section_name`, optional `subsection_name`, and `key`.
381+
/// Creates the section if necessary and the key as well, or overwrites the last existing value otherwise.
382+
///
383+
/// # Examples
384+
///
385+
/// Given the config,
386+
///
387+
/// ```text
388+
/// [core]
389+
/// a = b
390+
/// ```
391+
///
392+
/// Setting a new value to the key `core.a` will yield the following:
393+
///
394+
/// ```
395+
/// # use git_config::File;
396+
/// # use std::borrow::Cow;
397+
/// # use bstr::BStr;
398+
/// # use std::convert::TryFrom;
399+
/// # let mut git_config = git_config::File::try_from("[core]a=b").unwrap();
400+
/// let prev = git_config.set_raw_value("core", None, "a", "e")?;
401+
/// git_config.set_raw_value("core", None, "b", "f")?;
402+
/// assert_eq!(prev.expect("present").as_ref(), "b");
403+
/// assert_eq!(git_config.raw_value("core", None, "a")?, Cow::<BStr>::Borrowed("e".into()));
404+
/// assert_eq!(git_config.raw_value("core", None, "b")?, Cow::<BStr>::Borrowed("f".into()));
405+
/// # Ok::<(), Box<dyn std::error::Error>>(())
406+
/// ```
407+
pub fn set_raw_value<'b, Key, E>(
408+
&mut self,
409+
section_name: impl AsRef<str>,
410+
subsection_name: Option<&str>,
411+
key: Key,
412+
new_value: impl Into<&'b BStr>,
413+
) -> Result<Option<Cow<'event, BStr>>, crate::file::set_raw_value::Error>
414+
where
415+
Key: TryInto<section::Key<'event>, Error = E>,
416+
section::key::Error: From<E>,
417+
{
418+
self.set_raw_value_filter(section_name, subsection_name, key, new_value, &mut |_| true)
419+
}
420+
421+
/// Similar to [`set_raw_value()`][Self::set_raw_value()], but only sets existing values in sections matching
422+
/// `filter`, creating a new section otherwise.
423+
pub fn set_raw_value_filter<'b, Key, E>(
424+
&mut self,
425+
section_name: impl AsRef<str>,
426+
subsection_name: Option<&str>,
427+
key: Key,
428+
new_value: impl Into<&'b BStr>,
429+
filter: &mut MetadataFilter,
430+
) -> Result<Option<Cow<'event, BStr>>, crate::file::set_raw_value::Error>
431+
where
432+
Key: TryInto<section::Key<'event>, Error = E>,
433+
section::key::Error: From<E>,
434+
{
435+
let mut section = self.section_mut_or_create_new_filter(section_name, subsection_name, filter)?;
436+
Ok(section.set(key.try_into().map_err(section::key::Error::from)?, new_value))
437+
}
438+
377439
/// Sets a multivar in a given section, optional subsection, and key value.
378440
///
379441
/// This internally zips together the new values and the existing values.
@@ -413,7 +475,7 @@ impl<'event> File<'event> {
413475
/// "y",
414476
/// "z",
415477
/// ];
416-
/// git_config.set_raw_multi_value("core", None, "a", new_values.into_iter())?;
478+
/// git_config.set_existing_raw_multi_value("core", None, "a", new_values.into_iter())?;
417479
/// let fetched_config = git_config.raw_values("core", None, "a")?;
418480
/// assert!(fetched_config.contains(&Cow::<BStr>::Borrowed("x".into())));
419481
/// assert!(fetched_config.contains(&Cow::<BStr>::Borrowed("y".into())));
@@ -433,7 +495,7 @@ impl<'event> File<'event> {
433495
/// "x",
434496
/// "y",
435497
/// ];
436-
/// git_config.set_raw_multi_value("core", None, "a", new_values.into_iter())?;
498+
/// git_config.set_existing_raw_multi_value("core", None, "a", new_values.into_iter())?;
437499
/// let fetched_config = git_config.raw_values("core", None, "a")?;
438500
/// assert!(fetched_config.contains(&Cow::<BStr>::Borrowed("x".into())));
439501
/// assert!(fetched_config.contains(&Cow::<BStr>::Borrowed("y".into())));
@@ -454,11 +516,11 @@ impl<'event> File<'event> {
454516
/// "z",
455517
/// "discarded",
456518
/// ];
457-
/// git_config.set_raw_multi_value("core", None, "a", new_values)?;
519+
/// git_config.set_existing_raw_multi_value("core", None, "a", new_values)?;
458520
/// assert!(!git_config.raw_values("core", None, "a")?.contains(&Cow::<BStr>::Borrowed("discarded".into())));
459521
/// # Ok::<(), git_config::lookup::existing::Error>(())
460522
/// ```
461-
pub fn set_raw_multi_value<'a, Iter, Item>(
523+
pub fn set_existing_raw_multi_value<'a, Iter, Item>(
462524
&mut self,
463525
section_name: impl AsRef<str>,
464526
subsection_name: Option<&str>,

0 commit comments

Comments
 (0)