1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use gix_refspec::RefSpec;
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
use crate::types::RemoteDetached;
use crate::{Remote, bstr::BStr, remote};
/// Access
impl<'repo> Remote<'repo> {
/// Return the name of this remote or `None` if it wasn't persisted to disk yet.
pub fn name(&self) -> Option<&remote::Name<'static>> {
self.name.as_ref()
}
/// Return our repository reference.
pub fn repo(&self) -> &'repo crate::Repository {
self.repo
}
/// Return the set of ref-specs used for `direction`, which may be empty, in order of occurrence in the configuration.
pub fn refspecs(&self, direction: remote::Direction) -> &[RefSpec] {
match direction {
remote::Direction::Fetch => &self.fetch_specs,
remote::Direction::Push => &self.push_specs,
}
}
/// Return how we handle tags when fetching the remote.
pub fn fetch_tags(&self) -> remote::fetch::Tags {
self.fetch_tags
}
/// Return the url used for the given `direction` with rewrites from `url.<base>.insteadOf|pushInsteadOf`, unless the instance
/// was created with one of the `_without_url_rewrite()` methods.
/// For pushing, this is the `remote.<name>.pushUrl` or the `remote.<name>.url` used for fetching, and for fetching it's
/// the `remote.<name>.url`.
/// Note that it's possible to only have the push url set, in which case there will be no way to fetch from the remote as
/// the push-url isn't used for that.
pub fn url(&self, direction: remote::Direction) -> Option<&gix_url::Url> {
match direction {
remote::Direction::Fetch => self.url_alias.as_ref().or(self.url.as_ref()),
remote::Direction::Push => self
.push_url_alias
.as_ref()
.or(self.push_url.as_ref())
.or_else(|| self.url(remote::Direction::Fetch)),
}
}
/// Return a clone of this remote without its repository reference.
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
pub(crate) fn detached(&self) -> RemoteDetached {
self.clone().into()
}
}
/// Access
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
impl RemoteDetached {
/// Return the name of this remote or `None` if it wasn't persisted to disk yet.
pub(crate) fn name(&self) -> Option<&remote::Name<'static>> {
self.name.as_ref()
}
/// Return the set of ref-specs used for fetching, which may be empty, in order of occurrence in the configuration.
pub(crate) fn fetch_refspecs(&self) -> &[RefSpec] {
&self.fetch_specs
}
/// Return the fetch URL with rewrites from `url.<base>.insteadOf`.
pub(crate) fn fetch_url(&self) -> Option<&gix_url::Url> {
self.url_alias.as_ref().or(self.url.as_ref())
}
}
/// Modification
impl Remote<'_> {
/// Read `url.<base>.insteadOf|pushInsteadOf` configuration variables and apply them to our urls, changing them in place.
///
/// This happens only once, and one if them may be changed even when reporting an error.
/// If both urls fail, only the first error (for fetch urls) is reported.
pub fn rewrite_urls(&mut self) -> Result<&mut Self, remote::init::Error> {
let url_err = match remote::init::rewrite_url(&self.repo.config, self.url.as_ref(), remote::Direction::Fetch) {
Ok(url) => {
self.url_alias = url;
None
}
Err(err) => err.into(),
};
let push_url_err =
match remote::init::rewrite_url(&self.repo.config, self.push_url.as_ref(), remote::Direction::Push) {
Ok(url) => {
self.push_url_alias = url;
None
}
Err(err) => err.into(),
};
url_err.or(push_url_err).map(Err::<&mut Self, _>).transpose()?;
Ok(self)
}
/// Replace all currently set refspecs, typically from configuration, with the given `specs` for `direction`,
/// or `None` if one of the input specs could not be parsed.
pub fn replace_refspecs<Spec>(
&mut self,
specs: impl IntoIterator<Item = Spec>,
direction: remote::Direction,
) -> Result<(), gix_refspec::parse::Error>
where
Spec: AsRef<BStr>,
{
use remote::Direction::*;
let specs: Vec<_> = specs
.into_iter()
.map(|spec| {
gix_refspec::parse(
spec.as_ref(),
match direction {
Push => gix_refspec::parse::Operation::Push,
Fetch => gix_refspec::parse::Operation::Fetch,
},
)
.map(|url| url.to_owned())
})
.collect::<Result<_, _>>()?;
let dst = match direction {
Push => &mut self.push_specs,
Fetch => &mut self.fetch_specs,
};
*dst = specs;
Ok(())
}
}
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
impl From<Remote<'_>> for RemoteDetached {
fn from(
Remote {
name,
url,
url_alias,
fetch_specs,
fetch_tags,
push_url: _,
push_url_alias: _,
push_specs: _,
repo: _,
}: Remote<'_>,
) -> Self {
RemoteDetached {
name,
url,
url_alias,
fetch_specs,
fetch_tags,
}
}
}