Skip to content

Commit

Permalink
feat: Support for user-costomizable user agent strings.
Browse files Browse the repository at this point in the history
Doable by setting the `gitoxide.userAgent` variable.
  • Loading branch information
Byron committed Nov 10, 2022
1 parent f5499a5 commit 709a732
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 4 deletions.
14 changes: 14 additions & 0 deletions git-repository/src/config/cache/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ impl Cache {
.copied()
}

/// Returns a user agent for use with servers.
pub(crate) fn user_agent_tuple(&self) -> (&'static str, Option<Cow<'static, str>>) {
let agent = self
.user_agent
.get_or_init(|| {
self.resolved
.string("gitoxide", None, "userAgent")
.map(|s| s.to_string())
.unwrap_or_else(|| crate::env::agent().into())
})
.to_owned();
("agent", Some(git_protocol::fetch::agent(agent).into()))
}

pub(crate) fn personas(&self) -> &identity::Personas {
self.personas
.get_or_init(|| identity::Personas::from_config_and_env(&self.resolved, self.git_prefix))
Expand Down
2 changes: 2 additions & 0 deletions git-repository/src/config/cache/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ impl Cache {
xdg_config_home_env,
home_env,
lenient_config,
user_agent: Default::default(),
personas: Default::default(),
url_rewrite: Default::default(),
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
Expand Down Expand Up @@ -177,6 +178,7 @@ impl Cache {
self.object_kind_hint = object_kind_hint;
self.reflog = reflog;

self.user_agent = Default::default();
self.personas = Default::default();
self.url_rewrite = Default::default();
self.diff_algorithm = Default::default();
Expand Down
2 changes: 2 additions & 0 deletions git-repository/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ pub(crate) struct Cache {
pub use_multi_pack_index: bool,
/// The representation of `core.logallrefupdates`, or `None` if the variable wasn't set.
pub reflog: Option<git_ref::store::WriteReflog>,
/// The configured user agent for presentation to servers.
pub(crate) user_agent: OnceCell<String>,
/// identities for later use, lazy initialization.
pub(crate) personas: OnceCell<identity::Personas>,
/// A lazily loaded rewrite list for remote urls
Expand Down
14 changes: 11 additions & 3 deletions git-repository/src/remote/connection/fetch/receive_pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,30 @@ where
/// We explicitly don't special case those refs and expect the user to take control. Note that by its nature,
/// force only applies to refs pointing to commits and if they don't, they will be updated either way in our
/// implementation as well.
///
/// ### Configuration
///
/// - `gitoxide.userAgent` is read to obtain the application user agent for git servers and for HTTP servers as well.
pub fn receive(mut self, should_interrupt: &AtomicBool) -> Result<Outcome, Error> {
let mut con = self.con.take().expect("receive() can only be called once");

let handshake = &self.ref_map.handshake;
let protocol_version = handshake.server_protocol_version;

let fetch = git_protocol::fetch::Command::Fetch;
let fetch_features = fetch.default_features(protocol_version, &handshake.capabilities);
let progress = &mut con.progress;
let repo = con.remote.repo;
let fetch_features = {
let mut f = fetch.default_features(protocol_version, &handshake.capabilities);
f.push(repo.config.user_agent_tuple());
f
};

git_protocol::fetch::Response::check_required_features(protocol_version, &fetch_features)?;
let sideband_all = fetch_features.iter().any(|(n, _)| *n == "sideband-all");
let mut arguments = git_protocol::fetch::Arguments::new(protocol_version, fetch_features);
let mut previous_response = None::<git_protocol::fetch::Response>;
let mut round = 1;
let progress = &mut con.progress;
let repo = con.remote.repo;

if self.ref_map.object_hash != repo.object_hash() {
return Err(Error::IncompatibleObjectHash {
Expand Down
8 changes: 7 additions & 1 deletion git-repository/src/remote/connection/ref_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ where
///
/// Due to management of the transport, it's cleanest to only use it for a single interaction. Thus it's consumed along with
/// the connection.
///
/// ### Configuration
///
/// - `gitoxide.userAgent` is read to obtain the application user agent for git servers and for HTTP servers as well.
#[allow(clippy::result_large_err)]
#[git_protocol::maybe_async::maybe_async]
pub async fn ref_map(mut self, options: Options) -> Result<fetch::RefMap, Error> {
Expand Down Expand Up @@ -157,11 +161,13 @@ where
Some(refs) => refs,
None => {
let specs = &self.remote.fetch_specs;
let agent_feature = self.remote.repo.config.user_agent_tuple();
git_protocol::fetch::refs(
&mut self.transport,
outcome.server_protocol_version,
&outcome.capabilities,
|_capabilities, arguments, _features| {
move |_capabilities, arguments, features| {
features.push(agent_feature);
if filter_by_prefix {
let mut seen = HashSet::new();
for spec in specs {
Expand Down

0 comments on commit 709a732

Please sign in to comment.