feat(pack): add raw advertise refs and stateless protocol support
- Add raw flag to AdvertiseRefsRequest to enable raw pkt-line output - Implement advertise_refs_raw function that calls git upload-pack/receive-pack with --advertise-refs - Add stateless flag to GitProtocolFeatures for HTTP smart protocol support - Modify upload_pack and receive_pack to accept stateless parameter - Update command construction to include --stateless-rpc flag when enabled - Add raw_data field to AdvertiseRefsResponse for raw output - Update pack cache key computation to include raw service differentiation - Initialize raw field to false in all request creation calls
This commit is contained in:
+59
-2
@@ -1,12 +1,15 @@
|
||||
use crate::bare::GitBare;
|
||||
use crate::error::GitResult;
|
||||
use crate::error::{GitError, GitResult};
|
||||
use crate::pb::{AdvertiseRefsRequest, AdvertiseRefsResponse, ReferenceAdvertisement};
|
||||
|
||||
impl GitBare {
|
||||
pub fn advertise_refs(
|
||||
&self,
|
||||
_request: AdvertiseRefsRequest,
|
||||
request: AdvertiseRefsRequest,
|
||||
) -> GitResult<AdvertiseRefsResponse> {
|
||||
if request.raw {
|
||||
return self.advertise_refs_raw(&request);
|
||||
}
|
||||
let repo = self.gix_repo()?;
|
||||
let mut references = Vec::new();
|
||||
for r in repo.references()?.all()? {
|
||||
@@ -52,6 +55,60 @@ impl GitBare {
|
||||
"multi_ack".into(),
|
||||
"symref=HEAD".into(),
|
||||
],
|
||||
raw_data: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Return raw pkt-line output from git upload-pack/receive-pack --advertise-refs.
|
||||
/// Used by transparent proxies (gitshell) that forward bytes verbatim to git clients.
|
||||
fn advertise_refs_raw(
|
||||
&self,
|
||||
request: &AdvertiseRefsRequest,
|
||||
) -> GitResult<AdvertiseRefsResponse> {
|
||||
let bare_dir_str = self.bare_dir.to_string_lossy().into_owned();
|
||||
let stateless = request.protocol.as_ref().is_some_and(|p| p.stateless);
|
||||
|
||||
// Default to upload-pack if service is unspecified
|
||||
let subcommand = if request.service == "git-receive-pack" {
|
||||
"receive-pack"
|
||||
} else {
|
||||
"upload-pack"
|
||||
};
|
||||
|
||||
let mut args: Vec<String> = vec![
|
||||
"--git-dir".into(),
|
||||
bare_dir_str,
|
||||
subcommand.into(),
|
||||
"--advertise-refs".into(),
|
||||
];
|
||||
if stateless {
|
||||
args.push("--stateless-rpc".into());
|
||||
}
|
||||
|
||||
let result = duct::cmd("git", &args)
|
||||
.stdout_capture()
|
||||
.stderr_capture()
|
||||
.unchecked()
|
||||
.run()?;
|
||||
|
||||
if !result.status.success() {
|
||||
return Err(GitError::CommandFailed {
|
||||
status_code: result.status.code(),
|
||||
stderr: String::from_utf8_lossy(&result.stderr).into_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
tracing::debug!(
|
||||
raw_len = result.stdout.len(),
|
||||
service = %request.service,
|
||||
stateless = stateless,
|
||||
"advertise_refs raw output"
|
||||
);
|
||||
|
||||
Ok(AdvertiseRefsResponse {
|
||||
references: Vec::new(),
|
||||
capabilities: Vec::new(),
|
||||
raw_data: result.stdout,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user