From ab8d6b2533ef970edd6b201d0207cc3c86b95376 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Mon, 30 Aug 2021 20:46:09 +0100 Subject: [PATCH] git client successfully pulling a text file from server --- Cargo.lock | 30 ++++++++++++++++++++++++++++++ Cargo.toml | 4 ++++ src/main.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/git/packfile.rs | 6 +++--- 4 files changed, 122 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d019dc2..9fd759c 100644 --- a/Cargo.lock +++ a/Cargo.lock @@ -194,7 +194,9 @@ "crc", "env_logger", "flate2", + "format-bytes", "futures", + "hex", "sha-1", "thrussh", "thrussh-keys", @@ -358,6 +360,28 @@ ] [[package]] +name = "format-bytes" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e244f30e6c9389f9df0c65fe09a81bcd766c766fca74f0f12d0dae34de33a608" +dependencies = [ + "format-bytes-macros", + "proc-macro-hack", +] + +[[package]] +name = "format-bytes-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63987e7c19e6a14fc925a32b82c5d4805c7ca6de815fbdb79c457354ff060e45" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "futures" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -480,6 +504,12 @@ dependencies = [ "libc", ] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hmac" diff --git a/Cargo.toml b/Cargo.toml index d85c62a..b65ea86 100644 --- a/Cargo.toml +++ a/Cargo.toml @@ -23,3 +23,7 @@ sha-1 = "0.9" const-sha1 = "0.2" crc = "2" + + +format-bytes = "0.1" +hex = "0.4"diff --git a/src/main.rs b/src/main.rs index 03b6e7f..06cb08f 100644 --- a/src/main.rs +++ a/src/main.rs @@ -1,9 +1,9 @@ pub mod git; use crate::git::PktLine; -use bytes::BytesMut; use bytes::BufMut; +use bytes::BytesMut; use futures::future::Future; use git::codec::Encoder; use git::codec::GitCodec; @@ -152,9 +152,52 @@ } else if frame.as_ref() == "command=fetch".as_bytes() { fetch = true; } else if frame.as_ref() == "done".as_bytes() { + fetch = false; done = true; } } + + // echo -ne "0012command=fetch\n0001000ethin-pack\n0010include-tag\n000eofs-delta\n0032want d24d8020163b5fee57c9babfd0c595b8c90ba253\n0009done\n" + // echo -ne + + let tree_bytes = format_bytes::format_bytes!( + b"100644 test\0{}", + const_sha1::sha1(&const_sha1::ConstBuffer::from_slice( + "blob 33\0testing this is a test cool test!".as_bytes() + )) + .bytes() + ); + + let tree = format_bytes::format_bytes!( + b"tree {}\0{}", + tree_bytes.len().to_string().as_bytes(), + tree_bytes + ); + + let tree_hash = hex::encode(sha1::Sha1::digest(&tree)); + + let commit_bytes = format!( + "tree {} +author Jordan Doyle 1630244577 +0100 +committer Jordan Doyle 1630244577 +0100 + +test", + tree_hash + ); + + let commit = format!("commit {}\0{}", commit_bytes.len(), commit_bytes); + + let commit_hash = hex::encode(sha1::Sha1::digest(commit.as_bytes())); + + use sha1::Digest; + println!( + "commit hash: {} - tree hash: {} - file hash: {}", + commit_hash, + tree_hash, + const_sha1::sha1(&const_sha1::ConstBuffer::from_slice( + "blob 33\0testing this is a test cool test!".as_bytes() + )) + ); // echo -ne "0014command=ls-refs\n0014agent=git/2.321\n00010008peel000bsymrefs000aunborn0014ref-prefix HEAD\n0000" // GIT_PROTOCOL=version=2 ssh -o SendEnv=GIT_PROTOCOL git@github.com git-upload-pack '/w4/chartered.git' @@ -163,7 +206,9 @@ // sends a 000dpackfile back // https://shafiul.github.io/gitbook/7_the_packfile.html if ls_refs { - self.write(PktLine::Data(b"1a1b25ae7c87a0e87b7a9aa478a6bc4331c6b954 HEAD symref-target:refs/heads/master\n"))?; + 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); } @@ -179,11 +224,31 @@ if done { self.write(PktLine::Data(b"packfile\n"))?; + + { + let mut buf = BytesMut::new(); + buf.put_u8(2); // sideband, 1 = msg + buf.extend_from_slice(b"Hello from chartered!\n"); + self.write(PktLine::Data(buf.as_ref()))?; + self.flush(&mut session, channel); + } - let packfile = git::packfile::PackFile::new(vec![git::packfile::PackFileEntry::new( - git::packfile::PackFileEntryType::Blob, - b"testing this is a test cool test!", - )?]); + // fatal: bad object 4ff484817ca2f1a10183da210a6e74f29764857d + // error: ssh://127.0.0.1:2233/ did not send all necessary objects + let packfile = git::packfile::PackFile::new(vec![ + git::packfile::PackFileEntry::new( + git::packfile::PackFileEntryType::Commit, + commit_bytes.as_bytes(), + )?, + git::packfile::PackFileEntry::new( + git::packfile::PackFileEntryType::Tree, + &tree_bytes, + )?, + git::packfile::PackFileEntry::new( + git::packfile::PackFileEntryType::Blob, + b"testing this is a test cool test!", + )?, + ]); // { // let mut buf = BytesMut::new(); @@ -198,14 +263,26 @@ { let mut buf = BytesMut::new(); - buf.put_u8(1); + buf.put_u8(1); // sideband, 1 = continue packfile.encode_to(&mut buf)?; self.write(PktLine::Data(buf.as_ref()))?; } - self.write(PktLine::Flush)?; + // { + // let mut buf = BytesMut::new(); + // buf.put_u8(2); // sideband, 1 = msg + // buf.extend_from_slice( + // b"Total 3 (delta 0), reused 0 (delta 0), pack-reused 0\n", + // ); + // self.write(PktLine::Data(buf.as_ref()))?; + // self.flush(&mut session, channel); + // } + self.write(PktLine::Flush)?; self.flush(&mut session, channel); + session.exit_status_request(channel, 0); + session.eof(channel); + session.close(channel); } Ok((self, session)) diff --git a/src/git/packfile.rs b/src/git/packfile.rs index cdb78f9..48c06f0 100644 --- a/src/git/packfile.rs +++ a/src/git/packfile.rs @@ -1,9 +1,9 @@ use bytes::{BufMut, BytesMut}; use const_sha1::{sha1, ConstBuffer}; use flate2::{write::ZlibEncoder, Compression}; +use sha1::{Digest, Sha1}; use std::convert::TryInto; use std::io::Write as IoWrite; -use sha1::{Sha1, Digest}; // The offset/sha1[] tables are sorted by sha1[] values (this is to // allow binary search of this table), and fanout[] table points at @@ -173,14 +173,14 @@ entry_type: PackFileEntryType, compressed_data: Vec, compressed_crc32: u32, - uncompressed_sha1: [u8; 20], + pub uncompressed_sha1: [u8; 20], uncompressed_size: usize, } impl PackFileEntry { pub fn new(entry_type: PackFileEntryType, data: &[u8]) -> Result { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); - e.write_all(&data)?; + e.write_all(data)?; let compressed_data = e.finish()?; let compressed_crc32 = crc::Crc::::new(&crc::CRC_32_CKSUM).checksum(&compressed_data); -- rgit 0.1.3