Modularise command handling
Diff
chartered-git/src/main.rs | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
chartered-git/src/command_handlers/fetch.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
chartered-git/src/command_handlers/ls_refs.rs | 31 +++++++++++++++++++++++++++++++
chartered-git/src/command_handlers/mod.rs | 2 ++
4 files changed, 128 insertions(+), 80 deletions(-)
@@ -1,14 +1,16 @@
#![deny(clippy::pedantic)]
mod command_handlers;
mod generators;
mod tree;
#[allow(clippy::missing_errors_doc)]
pub mod git;
mod tree;
use crate::{
generators::CargoConfig,
git::{
codec::{Encoder, GitCodec},
packfile::{high_level::GitRepository, low_level::PackFile},
packfile::high_level::GitRepository,
PktLine,
},
tree::Tree,
@@ -249,10 +251,6 @@
self.input_bytes.extend_from_slice(data);
Box::pin(async move {
let mut ls_refs = false;
let mut fetch = false;
let mut done = false;
while let Some(frame) = self.codec.decode(&mut self.input_bytes)? {
eprintln!("{:#?}", frame);
@@ -265,82 +263,48 @@
return Ok((self, session));
}
if frame.command.as_ref() == "command=ls-refs".as_bytes() {
ls_refs = true;
} else if frame.command.as_ref() == "command=fetch".as_bytes() {
if frame.metadata.iter().any(|v| v.as_ref() == b"done") {
done = true;
} else {
fetch = true;
let authed = self.authed()?;
let org_name = self.org_name()?;
let mut packfile = GitRepository::default();
let config = CargoConfig::new(
Url::parse("http://127.0.0.1:8888/")?,
&authed.auth_key,
org_name,
);
let config = serde_json::to_vec(&config)?;
packfile.insert(ArrayVec::<_, 0>::new(), "config.json", &config);
let tree = Tree::build(self.db.clone(), authed.user.id, org_name.to_string()).await;
tree.write_to_packfile(&mut packfile);
let (commit_hash, packfile_entries) =
packfile.commit("computer", "john@computer.no", "Update crates");
match frame.command.as_ref() {
b"command=ls-refs" => {
command_handlers::ls_refs::handle(
&mut self,
&mut session,
channel,
frame.metadata,
&commit_hash,
)
.await?
}
b"command=fetch" => {
command_handlers::fetch::handle(
&mut self,
&mut session,
channel,
frame.metadata,
packfile_entries,
)
.await?
}
v => eprintln!("unknown command {:?}", v),
}
}
let authed = self.authed()?;
let org_name = self.org_name()?;
if !ls_refs && !fetch && !done {
return Ok((self, session));
}
let mut packfile = GitRepository::default();
let config = CargoConfig::new(
Url::parse("http://127.0.0.1:8888/")?,
&authed.auth_key,
org_name,
);
let config = serde_json::to_vec(&config)?;
packfile.insert(ArrayVec::<_, 0>::new(), "config.json", &config);
let tree = Tree::build(self.db.clone(), authed.user.id, org_name.to_string()).await;
tree.write_to_packfile(&mut packfile);
let (commit_hash, packfile_entries) =
packfile.commit("computer", "john@computer.no", "Update crates");
eprintln!("commit hash: {}", hex::encode(&commit_hash));
if ls_refs {
let commit_hash = hex::encode(&commit_hash);
self.write(PktLine::Data(
format!("{} HEAD symref-target:refs/heads/master\n", commit_hash).as_bytes(),
))?;
self.write(PktLine::Flush)?;
self.flush(&mut session, channel);
}
if fetch {
self.write(PktLine::Data(b"acknowledgments\n"))?;
self.write(PktLine::Data(b"ready\n"))?;
self.write(PktLine::Delimiter)?;
done = true;
}
if done {
self.write(PktLine::Data(b"packfile\n"))?;
self.write(PktLine::SidebandMsg(b"Hello from chartered!\n"))?;
self.flush(&mut session, channel);
let packfile = PackFile::new(packfile_entries);
self.write(PktLine::SidebandData(packfile))?;
self.write(PktLine::Flush)?;
self.flush(&mut session, channel);
session.exit_status_request(channel, 0);
session.eof(channel);
session.close(channel);
}
Ok((self, session))
@@ -1,0 +1,51 @@
use bytes::Bytes;
use thrussh::{server::Session, ChannelId};
use crate::{
git::{
packfile::low_level::{PackFile, PackFileEntry},
PktLine,
},
Handler,
};
pub(crate) async fn handle(
handle: &mut Handler,
session: &mut Session,
channel: ChannelId,
metadata: Vec<Bytes>,
packfile_entries: Vec<PackFileEntry<'_>>,
) -> Result<(), anyhow::Error> {
let done = metadata.iter().any(|v| v.as_ref() == b"done");
if !done {
handle.write(PktLine::Data(b"acknowledgments\n"))?;
handle.write(PktLine::Data(b"ready\n"))?;
handle.write(PktLine::Delimiter)?;
}
handle.write(PktLine::Data(b"packfile\n"))?;
handle.write(PktLine::SidebandMsg(b"Hello from chartered!\n"))?;
handle.flush(session, channel);
let packfile = PackFile::new(packfile_entries);
handle.write(PktLine::SidebandData(packfile))?;
handle.write(PktLine::Flush)?;
handle.flush(session, channel);
session.exit_status_request(channel, 0);
session.eof(channel);
session.close(channel);
Ok(())
}
@@ -1,0 +1,31 @@
use bytes::Bytes;
use thrussh::{server::Session, ChannelId};
use crate::{
git::{packfile::low_level::HashOutput, PktLine},
Handler,
};
pub(crate) async fn handle(
handle: &mut Handler,
session: &mut Session,
channel: ChannelId,
_metadata: Vec<Bytes>,
commit_hash: &HashOutput,
) -> Result<(), anyhow::Error> {
let commit_hash = hex::encode(&commit_hash);
handle.write(PktLine::Data(
format!("{} HEAD symref-target:refs/heads/master\n", commit_hash).as_bytes(),
))?;
handle.write(PktLine::Flush)?;
handle.flush(session, channel);
Ok(())
}
@@ -1,0 +1,2 @@
pub mod fetch;
pub mod ls_refs;