From 3fe9872e4320217bcc8b353460c8d9bd063e668b Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sun, 13 Mar 2022 17:15:26 +0000 Subject: [PATCH] Sort tree before inserting into packfile --- src/git_command_handlers/ls_refs.rs | 2 +- src/main.rs | 11 ++++++++--- src/protocol/high_level.rs | 7 +++++++ src/protocol/low_level.rs | 1 + 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/git_command_handlers/ls_refs.rs b/src/git_command_handlers/ls_refs.rs index 4b77740..3c67aa6 100644 --- a/src/git_command_handlers/ls_refs.rs +++ b/src/git_command_handlers/ls_refs.rs @@ -22,7 +22,7 @@ pub fn handle( let commit_hash = hex::encode(&commit_hash); handle.write(PktLine::Data( - format!("{} HEAD symref-target:refs/heads/master\n", commit_hash).as_bytes(), + format!("{} HEAD symref-target:refs/heads/master", commit_hash).as_bytes(), ))?; handle.write(PktLine::Flush)?; handle.flush(session, channel); diff --git a/src/main.rs b/src/main.rs index a9d07cd..772f5e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ use anyhow::anyhow; use bytes::{BufMut, Bytes, BytesMut}; use clap::Parser; use futures::Future; +use indexmap::IndexMap; use parking_lot::RwLock; use std::{ borrow::Cow, collections::HashMap, fmt::Write, net::SocketAddr, net::SocketAddrV6, pin::Pin, @@ -35,7 +36,7 @@ use thrussh::{ }; use thrussh_keys::key::PublicKey; use tokio_util::{codec::Decoder, codec::Encoder as CodecEncoder}; -use tracing::{error, info, info_span, Instrument, Span}; +use tracing::{debug, error, info, info_span, Instrument, Span}; use uuid::Uuid; const AGENT: &str = concat!( @@ -110,6 +111,8 @@ type MetadataCache = Arc, Arc { gitlab: Arc, + // todo: we could make our commit hash stable by leaving an update time + // in this cache and using that as our commit time metadata_cache: MetadataCache, } @@ -184,11 +187,11 @@ impl Handler { /// and groups them by crate. async fn fetch_releases_by_crate( &self, - ) -> anyhow::Result>> { + ) -> anyhow::Result>> { let user = self.user()?; let group = self.group()?; - let mut res = HashMap::new(); + let mut res = IndexMap::new(); for (path, release) in Arc::clone(&self.gitlab) .fetch_releases_for_group(group, user) @@ -297,6 +300,8 @@ impl Handler { let checksum = &release.checksum; let version = &release.version; + debug!("Fetching metadata for {}-{}", crate_name, version); + // parses the `cargo metadata` stored in the release, which // should be stored under `metadata.json`. let meta = self diff --git a/src/protocol/high_level.rs b/src/protocol/high_level.rs index 917b065..e7dae0d 100644 --- a/src/protocol/high_level.rs +++ b/src/protocol/high_level.rs @@ -132,11 +132,13 @@ impl Tree { tree.push(match *item { TreeItem::Blob(hash) => LowLevelTreeItem { kind: TreeItemKind::File, + sort_name: name.clone(), name, hash, }, TreeItem::Tree(tree) => LowLevelTreeItem { kind: TreeItemKind::Directory, + sort_name: format!("{}/", name), name, // we're essentially working through our tree from the bottom up, // so we can grab the hash of each directory along the way and @@ -146,6 +148,11 @@ impl Tree { }); } + // we need to sort our tree alphabetically, otherwise Git will silently + // stop parsing the rest of the tree once it comes across a non-sorted + // tree entry. + tree.sort_unstable_by(|a, b| a.sort_name.cmp(&b.sort_name)); + // gets the hash of the tree we've just worked on, and // pushes it to the packfile let tree = PackFileEntry::Tree(tree); diff --git a/src/protocol/low_level.rs b/src/protocol/low_level.rs index 1365b27..b013cb8 100644 --- a/src/protocol/low_level.rs +++ b/src/protocol/low_level.rs @@ -143,6 +143,7 @@ pub struct TreeItem { pub kind: TreeItemKind, pub name: String, pub hash: HashOutput, + pub sort_name: String, } // `[mode] [name]\0[hash]` -- libgit2 1.7.2