Skip to content

Commit

Permalink
Merge branch 'main' into fetch-pack
Browse files Browse the repository at this point in the history
Conflicts:
	git-transport/src/client/blocking_io/http/mod.rs
  • Loading branch information
Byron committed Sep 28, 2022
2 parents 5a6c102 + 6c9d18b commit 93917cb
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 17 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ check: ## Build all code in suitable configurations
&& cargo check --features blocking-client \
&& cargo check --features async-client \
&& cargo check --features async-client,async-std \
&& cargo check --features http-client \
&& cargo check --features http-client-curl
cd git-transport && if cargo check --all-features 2>/dev/null; then false; else true; fi
cd git-protocol && cargo check \
Expand Down
4 changes: 4 additions & 0 deletions git-discover/tests/upwards/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ fn cross_fs() -> crate::Result {
use std::{os::unix::fs::symlink, process::Command};

use git_discover::upwards::Options;
if git_testtools::is_ci::cached() {
// Don't run on CI as it's too slow there, resource busy, it fails more often than it succeeds by now.
return Ok(());
}

let top_level_repo = git_testtools::scripted_fixture_repo_writable("make_basic_repo.sh")?;

Expand Down
9 changes: 8 additions & 1 deletion git-object/src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,14 @@ impl<'a> ObjectRef<'a> {
/// Deserialize an object from a loose serialisation
pub fn from_loose(data: &'a [u8]) -> Result<ObjectRef<'a>, LooseDecodeError> {
let (kind, size, offset) = loose_header(data)?;
Ok(Self::from_bytes(kind, &data[offset..][..size])?)

let body = &data[offset..]
.get(..size)
.ok_or(LooseHeaderDecodeError::InvalidHeader {
message: "object data was shorter than its size declared in the header",
})?;

Ok(Self::from_bytes(kind, body)?)
}

/// Deserialize an object of `kind` from the given `data`.
Expand Down
10 changes: 9 additions & 1 deletion git-object/tests/loose.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bstr::ByteSlice;
use git_object::{decode, encode, Kind};
use git_object::{decode, encode, Kind, ObjectRef};

#[test]
fn all() -> Result<(), Box<dyn std::error::Error>> {
Expand All @@ -18,3 +18,11 @@ fn all() -> Result<(), Box<dyn std::error::Error>> {
}
Ok(())
}

#[test]
fn shorter_than_advertised() {
assert_eq!(
ObjectRef::from_loose(b"tree 1000\x00").unwrap_err().to_string(),
"object data was shorter than its size declared in the header"
);
}
10 changes: 7 additions & 3 deletions git-transport/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ default = []

## If set, blocking implementations of the typical git transports become available in `crate::client`
blocking-client = ["git-packetline/blocking-io"]
## Implies `blocking-client`, and adds support for the http and https transports using the Rust bindings for `libcurl`.
http-client-curl = ["curl", "base64", "git-features/io-pipe", "blocking-client"]
## Implies `blocking-client`, and adds support for the http and https transports.
http-client = ["base64", "git-features/io-pipe", "blocking-client"]
## Implies `http-client`, and adds support for the http and https transports using the Rust bindings for `libcurl`.
http-client-curl = ["curl", "http-client"]
## If set, an async implementations of the git transports becomes available in `crate::client`.
## Suitable for implementing your own transports while using git's way of communication, typically in conjunction with a custom server.
## **Note** that the _blocking_ client has a wide range of available transports, with the _async_ version of it supporting only the TCP based `git` transport leaving you
Expand Down Expand Up @@ -62,11 +64,13 @@ futures-io = { version = "0.3.16", optional = true }
futures-lite = { version = "1.12.0", optional = true }
pin-project-lite = { version = "0.2.6", optional = true }

# for http-client
base64 = { version = "0.13.0", optional = true }

# for http-client-curl
# zlib-ng-compat doesn't force zlib-ng
curl = { version = "0.4", optional = true, features = ["static-curl", "static-ssl", "zlib-ng-compat"] }
thiserror = "1.0.26"
base64 = { version = "0.13.0", optional = true }

## If used in conjunction with `async-client`, the `connect()` method will be come available along with supporting the git protocol over TCP,
## where the TCP stream is created using this crate.
Expand Down
29 changes: 23 additions & 6 deletions git-transport/src/client/blocking_io/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,31 +35,41 @@ pub struct Transport<H: Http> {
identity: Option<git_sec::identity::Account>,
}

impl Transport<Impl> {
/// Create a new instance to communicate to `url` using the given `desired_version` of the `git` protocol.
pub fn new(url: &str, desired_version: Protocol) -> Self {
impl<H: Http> Transport<H> {
/// Create a new instance with `http` as implementation to communicate to `url` using the given `desired_version` of the `git` protocol.
pub fn new_http(http: H, url: &str, desired_version: Protocol) -> Self {
Transport {
url: url.to_owned(),
user_agent_header: concat!("User-Agent: git/oxide-", env!("CARGO_PKG_VERSION")),
desired_version,
actual_version: desired_version,
supported_versions: [desired_version],
service: None,
http: Impl::default(),
http,
line_provider: None,
identity: None,
}
}
}

#[cfg(feature = "http-client-curl")]
impl Transport<Impl> {
/// Create a new instance to communicate to `url` using the given `desired_version` of the `git` protocol.
///
/// Note that the actual implementation depends on feature toggles.
pub fn new(url: &str, desired_version: Protocol) -> Self {
Self::new_http(Impl::default(), url, desired_version)
}
}

impl<H: Http> Transport<H> {
fn check_content_type(service: Service, kind: &str, headers: <H as Http>::Headers) -> Result<(), client::Error> {
let wanted_content_type = format!("Content-Type: application/x-{}-{}", service.as_str(), kind);
let wanted_content_type = format!("content-type: application/x-{}-{}", service.as_str(), kind);
if !headers
.lines()
.collect::<Result<Vec<_>, _>>()?
.iter()
.any(|l| l == &wanted_content_type)
.any(|l| l.to_lowercase() == wanted_content_type)
{
return Err(client::Error::Http(Error::Detail {
description: format!(
Expand Down Expand Up @@ -289,7 +299,14 @@ impl<H: Http, B: ExtendedBufRead + Unpin> ExtendedBufRead for HeadersThenBody<H,
}
}

/// Connect to the given `url` via HTTP/S using the `desired_version` of the `git` protocol, with `http` as implementation.
#[cfg(all(feature = "http-client", not(feature = "http-client-curl")))]
pub fn connect_http<H: Http>(http: H, url: &str, desired_version: Protocol) -> Transport<H> {
Transport::new_http(http, url, desired_version)
}

/// Connect to the given `url` via HTTP/S using the `desired_version` of the `git` protocol.
#[cfg(feature = "http-client-curl")]
pub fn connect(url: &str, desired_version: Protocol) -> Transport<Impl> {
Transport::new(url, desired_version)
}
2 changes: 1 addition & 1 deletion git-transport/src/client/blocking_io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod connect;
///
pub mod file;
///
#[cfg(feature = "http-client-curl")]
#[cfg(feature = "http-client")]
pub mod http;

mod bufread_ext;
Expand Down
2 changes: 1 addition & 1 deletion git-transport/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use traits::TransportWithoutIO;

#[cfg(feature = "blocking-client")]
mod blocking_io;
#[cfg(all(feature = "blocking-client", feature = "http-client-curl"))]
#[cfg(feature = "http-client")]
pub use blocking_io::http;
#[cfg(feature = "blocking-client")]
pub use blocking_io::{
Expand Down
6 changes: 3 additions & 3 deletions git-transport/src/client/non_io_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ mod error {
use bstr::BString;

use crate::client::capabilities;
#[cfg(feature = "http-client-curl")]
#[cfg(feature = "http-client")]
use crate::client::http;

#[cfg(feature = "http-client-curl")]
#[cfg(feature = "http-client")]
type HttpError = http::Error;
#[cfg(not(feature = "http-client-curl"))]
#[cfg(not(feature = "http-client"))]
type HttpError = std::convert::Infallible;

/// The error used in most methods of the [`client`][crate::client] module
Expand Down
12 changes: 12 additions & 0 deletions git-transport/tests/client/blocking_io/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,3 +455,15 @@ Git-Protocol: version=2
);
Ok(())
}

#[test]
fn check_content_type_is_case_insensitive() -> crate::Result {
let (_server, mut client) = mock::serve_and_connect(
"v2/http-handshake-lowercase-headers.response",
"path/not/important/due/to/mock",
Protocol::V2,
)?;
let result = client.handshake(Service::UploadPack, &[]);
assert!(result.is_ok());
Ok(())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
HTTP/1.1 200 OK
server: GitHub Babel 2.0
content-type: application/x-git-upload-pack-advertisement
content-length: 1000
expires: Fri, 01 Jan 1980 00:00:00 GMT
pragma: no-cache
cache-control: no-cache, max-age=0, must-revalidate
vary: Accept-Encoding
x-frame-options: DENY
x-github-request-id: 737D:544E:C932CB:113F404:5F3F3EE5

001e# service=git-upload-pack
0000000eversion 2
0023agent=git/github-gdf51a71f0236
000cls-refs
0019fetch=shallow filter
0012server-option
0000
2 changes: 1 addition & 1 deletion tests/tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ fn scripted_fixture_repo_read_only_with_args_inner(

let _marker = git_lock::Marker::acquire_to_hold_resource(
script_basename,
git_lock::acquire::Fail::AfterDurationWithBackoff(Duration::from_secs(if cfg!(windows) { 3 * 60 } else { 30 })),
git_lock::acquire::Fail::AfterDurationWithBackoff(Duration::from_secs(if cfg!(windows) { 3 * 60 } else { 60 })),
None,
)?;
let failure_marker = script_result_directory.join("_invalid_state_due_to_script_failure_");
Expand Down

0 comments on commit 93917cb

Please sign in to comment.