From 52375c75b823dce9fae1b5b99ee1b22d3e225dd5 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Tue, 30 Aug 2022 01:42:22 +0100 Subject: [PATCH] Fix issue with git ignoring some trees and files due to being unsorted --- chartered-git/src/command_handlers/ls_refs.rs | 2 +- chartered-git/src/git/packfile/high_level.rs | 9 +++++++++ chartered-git/src/git/packfile/low_level.rs | 5 +++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/chartered-git/src/command_handlers/ls_refs.rs b/chartered-git/src/command_handlers/ls_refs.rs index d4dee55..34f757b 100644 --- a/chartered-git/src/command_handlers/ls_refs.rs +++ a/chartered-git/src/command_handlers/ls_refs.rs @@ -22,7 +22,7 @@ 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/chartered-git/src/git/packfile/high_level.rs b/chartered-git/src/git/packfile/high_level.rs index b610bd6..0b0d984 100644 --- a/chartered-git/src/git/packfile/high_level.rs +++ a/chartered-git/src/git/packfile/high_level.rs @@ -6,6 +6,8 @@ //! for our purposes because `cargo` will `git pull --force` from our Git //! server, allowing us to ignore any history the client may have. +use std::borrow::Cow; + use arrayvec::ArrayVec; use indexmap::IndexMap; @@ -141,11 +143,13 @@ TreeItem::Blob(hash) => LowLevelTreeItem { kind: TreeItemKind::File, name, + sort_name: Cow::Borrowed(name), hash: *hash, }, TreeItem::Tree(tree) => LowLevelTreeItem { kind: TreeItemKind::Directory, name, + sort_name: Cow::Owned(format!("{}/", 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 // reference it from the parent directory @@ -153,6 +157,11 @@ }, }); } + + // we need to sort our tree alphabetically, otherwise Git will silently + // stop parsing the rest of the tree once it comes across an unsorted + // 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 diff --git a/chartered-git/src/git/packfile/low_level.rs b/chartered-git/src/git/packfile/low_level.rs index acfec41..d1cb6f8 100644 --- a/chartered-git/src/git/packfile/low_level.rs +++ a/chartered-git/src/git/packfile/low_level.rs @@ -1,10 +1,10 @@ use bytes::{BufMut, BytesMut}; use flate2::{write::ZlibEncoder, Compression}; use sha1::{ digest::{generic_array::GenericArray, OutputSizeUser}, Digest, Sha1, }; -use std::{convert::TryInto, fmt::Write, io::Write as IoWrite}; +use std::{borrow::Cow, convert::TryInto, fmt::Write, io::Write as IoWrite}; pub type HashOutput = GenericArray::OutputSize>; // [u8; 20], but sha-1 returns a GenericArray @@ -141,10 +141,11 @@ } } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone)] pub struct TreeItem<'a> { pub kind: TreeItemKind, pub name: &'a str, + pub sort_name: Cow<'a, str>, pub hash: HashOutput, } -- rgit 0.1.3