Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
21 kB · 686 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687//! wire output shapes, copied from knot-xrpc until parity is proven.
use std::collections::BTreeMap;
use base64::Engine as _;use base64::engine::general_purpose::STANDARD;use serde::ser::SerializeSeq;use serde::{Serialize, Serializer};
use knot_git::{ BranchInfo, BranchTip, Commit, CommitChangeId, FilePatch, Hunk, Identity, LineOp, PatchStatus, TagInfo,};use knot_types::{ AuthorName, Email, LanguageBytes, LanguageName, Oid, OwnerDid, RepoDid, RepoRkey, TagName,};pub use super::wire::rfc3339;use super::wire::{fold_subject, message_body};
// Origin: knot-xrpc/src/wire.rs: ZERO_TIMEpub const ZERO_TIME: &str = "0001-01-01T00:00:00Z";
// Origin: knot-xrpc/src/wire.rs: HashBytes#[derive(Debug, Clone, Copy, PartialEq, Eq)]pub struct HashBytes(pub Oid);
impl Serialize for HashBytes { fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { let bytes = self.0.object_id(); let slice = bytes.as_bytes(); let mut seq = serializer.serialize_seq(Some(slice.len()))?; for byte in slice { seq.serialize_element(byte)?; } seq.end() }}
// Origin: knot-xrpc/src/wire.rs: Base64Bytes#[derive(Debug, Clone, PartialEq, Eq)]pub struct Base64Bytes(pub Vec<u8>);
impl Serialize for Base64Bytes { fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { serializer.serialize_str(&STANDARD.encode(&self.0)) }}
fn display_opt<S: Serializer>( value: &Option<CommitChangeId>, serializer: S,) -> Result<S::Ok, S::Error> { match value { Some(id) => serializer.serialize_str(id.as_str()), None => serializer.serialize_none(), }}
// Origin: knot-xrpc/src/wire.rs: SignatureWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct SignatureWire { #[serde(rename = "Name")] pub name: AuthorName, #[serde(rename = "Email")] pub email: Email, #[serde(rename = "When")] pub when: String,}
impl SignatureWire { pub fn of(identity: &Identity) -> Self { Self { name: identity.name.clone(), email: identity.email.clone(), when: rfc3339(identity.time.get(), identity.offset_seconds), } }
pub fn utc(identity: &Identity) -> Self { Self { name: identity.name.clone(), email: identity.email.clone(), when: rfc3339(identity.time.get(), 0), } }
pub fn zero() -> Self { Self { name: AuthorName::new(""), email: Email::new(""), when: ZERO_TIME.to_string(), } }}
// Origin: knot-xrpc/src/reads.rs: SignatureOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct SignatureOut { pub name: AuthorName, pub email: Email, pub when: String,}
// Origin: knot-xrpc/src/reads.rs: LastCommitOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct LastCommitOut { pub hash: Oid, pub message: String, pub when: String, #[serde(skip_serializing_if = "Option::is_none")] pub author: Option<SignatureOut>,}
// Origin: knot-xrpc/src/reads.rs: TreeEntryOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct TreeEntryOut { pub name: String, pub mode: String, pub size: i64, #[serde(skip_serializing_if = "Option::is_none")] pub last_commit: Option<LastCommitOut>,}
// Origin: knot-xrpc/src/reads.rs: ReadmeOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct ReadmeOut { pub filename: String, pub contents: String,}
// Origin: knot-xrpc/src/reads.rs: TreeOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct TreeOut { #[serde(rename = "ref")] pub refspec: String, #[serde(skip_serializing_if = "Option::is_none")] pub parent: Option<String>, #[serde(skip_serializing_if = "Option::is_none")] pub dotdot: Option<String>, pub files: Vec<TreeEntryOut>, #[serde(rename = "lastCommit", skip_serializing_if = "Option::is_none")] pub last_commit: Option<LastCommitOut>, pub readme: ReadmeOut,}
// Origin: knot-xrpc/src/wire.rs: CommitWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct CommitWire { pub hash: HashBytes, pub author: SignatureWire, pub committer: SignatureWire, pub message: String, pub tree: Oid, #[serde(skip_serializing_if = "Vec::is_empty")] pub parent_hashes: Vec<HashBytes>, #[serde(skip_serializing_if = "Option::is_none")] pub pgp_signature: Option<String>, #[serde(skip_serializing_if = "Option::is_none")] pub merge_tag: Option<String>, #[serde( skip_serializing_if = "Option::is_none", serialize_with = "display_opt" )] pub change_id: Option<CommitChangeId>, #[serde(skip_serializing_if = "Option::is_none")] pub extra_headers: Option<BTreeMap<String, Base64Bytes>>, pub this: Oid, #[serde(skip_serializing_if = "Option::is_none")] pub parent: Option<Oid>,}
impl CommitWire { pub fn of(commit: &Commit) -> Self { let extra_headers: BTreeMap<String, Base64Bytes> = commit .extra_headers .iter() .map(|(name, value)| (name.clone(), Base64Bytes(value.clone()))) .collect(); Self { hash: HashBytes(commit.id), author: SignatureWire::of(&commit.author), committer: SignatureWire::of(&commit.committer), message: commit.message.clone(), tree: commit.tree, parent_hashes: commit.parents.iter().copied().map(HashBytes).collect(), pgp_signature: commit.pgp_signature.clone(), merge_tag: commit.merge_tag.clone(), change_id: commit.change_id(), extra_headers: (!extra_headers.is_empty()).then_some(extra_headers), this: commit.id, parent: commit.parents.first().copied(), } }}
// Origin: knot-xrpc/src/wire.rs: BranchCommitWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct BranchCommitWire { #[serde(rename = "Hash")] pub hash: HashBytes, #[serde(rename = "Author")] pub author: SignatureWire, #[serde(rename = "Committer")] pub committer: SignatureWire, #[serde(rename = "MergeTag")] pub merge_tag: String, #[serde(rename = "PGPSignature")] pub pgp_signature: String, #[serde(rename = "Message")] pub message: String, #[serde(rename = "TreeHash")] pub tree_hash: HashBytes, #[serde(rename = "ParentHashes")] pub parent_hashes: Vec<HashBytes>, #[serde(rename = "Encoding")] pub encoding: String, #[serde(rename = "ExtraHeaders")] pub extra_headers: Option<()>,}
// Origin: knot-xrpc/src/wire.rs: Reference#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct Reference { pub name: String, pub hash: Oid,}
// Origin: knot-xrpc/src/wire.rs: BranchWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct BranchWire { pub reference: Reference, pub commit: BranchCommitWire, #[serde(skip_serializing_if = "std::ops::Not::not")] pub is_default: bool,}
impl BranchWire { pub fn of(branch: &BranchInfo, is_default: bool, absent: Oid) -> Self { Self { reference: Reference { name: branch.name.to_string(), hash: branch.tip.id(), }, commit: match &branch.tip { BranchTip::Commit(commit) => BranchCommitWire { hash: HashBytes(commit.id), author: SignatureWire::utc(&commit.author), committer: SignatureWire::utc(&commit.committer), merge_tag: String::new(), pgp_signature: String::new(), message: commit.message.trim_end().to_string(), tree_hash: HashBytes(commit.tree), parent_hashes: commit.parents.iter().copied().map(HashBytes).collect(), encoding: String::new(), extra_headers: None, }, BranchTip::Opaque { id, message, .. } => BranchCommitWire { hash: HashBytes(*id), author: SignatureWire::zero(), committer: SignatureWire::zero(), merge_tag: String::new(), pgp_signature: String::new(), message: message.trim_end().to_string(), tree_hash: HashBytes(absent), parent_hashes: Vec::new(), encoding: String::new(), extra_headers: None, }, }, is_default, } }}
// Origin: knot-xrpc/src/reads.rs: BranchesOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct BranchesOut { #[serde(skip_serializing_if = "Vec::is_empty")] pub branches: Vec<BranchWire>,}
// Origin: knot-xrpc/src/reads.rs: BranchOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct BranchOut { pub name: String, pub hash: String, #[serde(rename = "shortHash")] pub short_hash: String, pub when: String, #[serde(skip_serializing_if = "Option::is_none")] pub message: Option<String>, pub author: SignatureOut, #[serde(rename = "isDefault")] pub is_default: bool,}
// Origin: knot-xrpc/src/wire.rs: TagObjectWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct TagObjectWire { #[serde(rename = "Hash")] pub hash: HashBytes, #[serde(rename = "Name")] pub name: TagName, #[serde(rename = "Tagger")] pub tagger: SignatureWire, #[serde(rename = "Message")] pub message: String, #[serde(rename = "PGPSignature")] pub pgp_signature: String, #[serde(rename = "TargetType")] pub target_type: i8, #[serde(rename = "Target")] pub target: HashBytes,}
// Origin: knot-xrpc/src/wire.rs: TagWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct TagWire { pub name: TagName, pub hash: Oid, #[serde(skip_serializing_if = "Option::is_none")] pub tag: Option<TagObjectWire>, #[serde(skip_serializing_if = "String::is_empty")] pub message: String,}
const TARGET_TYPE_TAG: i8 = 4;
fn recombine_message(message: &str) -> String { let subject = fold_subject(message); let body = message_body(message); match (subject.is_empty(), body.is_empty()) { (_, true) => subject, (true, false) => body, (false, false) => format!("{subject}\n\n{body}"), }}
impl TagWire { pub fn of(info: &TagInfo) -> Self { let message = recombine_message(&info.message); let tag = info.annotated.as_ref().map(|annotated| TagObjectWire { hash: HashBytes(info.id), name: info.name.clone(), tagger: annotated .tagger .as_ref() .map(SignatureWire::utc) .unwrap_or_else(|| SignatureWire { name: AuthorName::new(""), email: Email::new(""), when: rfc3339(0, 0), }), message: message.clone(), pgp_signature: annotated.pgp_signature.clone().unwrap_or_default(), target_type: TARGET_TYPE_TAG, target: HashBytes(annotated.target), }); Self { name: info.name.clone(), hash: info.id, tag, message, } }}
// Origin: knot-xrpc/src/reads.rs: TagsOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct TagsOut { #[serde(skip_serializing_if = "Vec::is_empty")] pub tags: Vec<TagWire>,}
// Origin: knot-xrpc/src/reads.rs: TagOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct TagOut { pub tag: TagWire,}
// Origin: knot-xrpc/src/reads.rs: SubmoduleOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct SubmoduleOut { pub name: String, pub url: String, pub branch: String,}
// Origin: knot-xrpc/src/reads.rs: BlobOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct BlobOut { #[serde(rename = "ref")] pub refspec: String, pub path: String, #[serde(skip_serializing_if = "Option::is_none")] pub content: Option<String>, #[serde(skip_serializing_if = "Option::is_none")] pub encoding: Option<&'static str>, #[serde(skip_serializing_if = "Option::is_none")] pub size: Option<i64>, #[serde(rename = "isBinary", skip_serializing_if = "Option::is_none")] pub is_binary: Option<bool>, #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")] pub mime_type: Option<&'static str>, #[serde(rename = "lastCommit", skip_serializing_if = "Option::is_none")] pub last_commit: Option<LastCommitOut>, #[serde(skip_serializing_if = "Option::is_none")] pub submodule: Option<SubmoduleOut>,}
// Origin: knot-xrpc/src/wire.rs: LineWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct LineWire { #[serde(rename = "Op")] pub op: u8, #[serde(rename = "Line")] pub line: String,}
// Origin: knot-xrpc/src/wire.rs: TextFragmentWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct TextFragmentWire { #[serde(rename = "Comment")] pub comment: String, #[serde(rename = "OldPosition")] pub old_position: i64, #[serde(rename = "OldLines")] pub old_lines: i64, #[serde(rename = "NewPosition")] pub new_position: i64, #[serde(rename = "NewLines")] pub new_lines: i64, #[serde(rename = "LinesAdded")] pub lines_added: i64, #[serde(rename = "LinesDeleted")] pub lines_deleted: i64, #[serde(rename = "LeadingContext")] pub leading_context: i64, #[serde(rename = "TrailingContext")] pub trailing_context: i64, #[serde(rename = "Lines")] pub lines: Vec<LineWire>,}
impl TextFragmentWire { pub fn of(hunk: &Hunk) -> Self { let lines: Vec<LineWire> = hunk .lines .iter() .map(|line| LineWire { op: match line.op { LineOp::Context => 0, LineOp::Delete => 1, LineOp::Add => 2, }, line: String::from_utf8_lossy(&line.text).into_owned(), }) .collect(); let leading = lines.iter().take_while(|line| line.op == 0).count(); let trailing = if leading == lines.len() { 0 } else { lines.iter().rev().take_while(|line| line.op == 0).count() }; Self { comment: String::new(), old_position: hunk.old_start.get() as i64, old_lines: hunk.old_lines.get() as i64, new_position: hunk.new_start.get() as i64, new_lines: hunk.new_lines.get() as i64, lines_added: hunk.added().get() as i64, lines_deleted: hunk.deleted().get() as i64, leading_context: leading as i64, trailing_context: trailing as i64, lines, } }}
// Origin: knot-xrpc/src/wire.rs: DiffNameWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct DiffNameWire { pub old: String, pub new: String,}
// Origin: knot-xrpc/src/wire.rs: DiffWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct DiffWire { pub name: DiffNameWire, pub text_fragments: Option<Vec<TextFragmentWire>>, pub is_binary: bool, pub is_new: bool, pub is_delete: bool, pub is_copy: bool, pub is_rename: bool,}
impl DiffWire { pub fn of(patch: &FilePatch) -> Self { let fragments: Vec<TextFragmentWire> = patch.hunks().iter().map(TextFragmentWire::of).collect(); Self { name: DiffNameWire { old: if patch.status == PatchStatus::Added { String::new() } else { patch.path.to_string() }, new: if patch.status == PatchStatus::Deleted { String::new() } else { patch.path.to_string() }, }, text_fragments: (!fragments.is_empty()).then_some(fragments), is_binary: patch.is_binary(), is_new: patch.status == PatchStatus::Added, is_delete: patch.status == PatchStatus::Deleted, is_copy: false, is_rename: false, } }}
// Origin: knot-xrpc/src/wire.rs: DiffStatWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct DiffStatWire { pub insertions: i64, pub deletions: i64, pub files_changed: i64,}
// Origin: knot-xrpc/src/wire.rs: NiceDiffWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct NiceDiffWire { pub commit: CommitWire, pub stat: DiffStatWire, pub diff: Option<Vec<DiffWire>>,}
// Origin: knot-xrpc/src/wire.rs: nice_diffpub fn nice_diff(commit: &Commit, patches: &[FilePatch]) -> NiceDiffWire { let diffs: Vec<DiffWire> = patches.iter().map(DiffWire::of).collect(); let (insertions, deletions) = patches .iter() .flat_map(|patch| patch.hunks()) .fold((0i64, 0i64), |(ins, del), hunk| { ( ins + hunk.added().get() as i64, del + hunk.deleted().get() as i64, ) }); let stat = DiffStatWire { insertions, deletions, files_changed: patches.len() as i64, }; NiceDiffWire { commit: CommitWire::of(commit), stat, diff: (!diffs.is_empty()).then_some(diffs), }}
// Origin: knot-xrpc/src/reads.rs: DiffOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct DiffOut { #[serde(rename = "ref", skip_serializing_if = "String::is_empty")] pub refspec: String, pub diff: NiceDiffWire,}
// Origin: knot-xrpc/src/reads.rs: LanguageOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct LanguageOut { pub name: LanguageName, pub size: LanguageBytes, pub percentage: i64,}
// Origin: knot-xrpc/src/reads.rs: LanguagesOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct LanguagesOut { #[serde(rename = "ref")] pub refspec: String, pub languages: Option<Vec<LanguageOut>>, #[serde(rename = "totalSize", skip_serializing_if = "Option::is_none")] pub total_size: Option<u64>, #[serde(rename = "totalFiles", skip_serializing_if = "Option::is_none")] pub total_files: Option<i64>,}
// Origin: knot-xrpc/src/reads.rs: DefaultBranchOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct DefaultBranchOut { pub name: String, pub hash: String, pub when: String,}
// Origin: knot-xrpc/src/reads.rs: DescribeRepoOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct DescribeRepoOut { #[serde(rename = "repoDid")] pub repo_did: RepoDid, #[serde(rename = "ownerDid")] pub owner_did: OwnerDid, pub rkey: RepoRkey,}
// Origin: knot-xrpc/src/reads.rs: DefaultBranchWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct DefaultBranchWire { #[serde(rename = "ref")] pub name: String, #[serde(skip_serializing_if = "Option::is_none")] pub head: Option<String>,}
// Origin: knot-xrpc/src/reads.rs: RefWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct RefWire { #[serde(rename = "ref")] pub name: String, pub sha: Oid,}
// Origin: knot-xrpc/src/reads.rs: ListRefsOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct ListRefsOut { pub refs: Vec<RefWire>, #[serde(skip_serializing_if = "Option::is_none")] pub cursor: Option<String>, #[serde(rename = "defaultBranch", skip_serializing_if = "Option::is_none")] pub default_branch: Option<DefaultBranchWire>,}
// Origin: knot-xrpc/src/reads.rs: RepoWire#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct RepoWire { pub repo: RepoDid, pub status: &'static str, #[serde(rename = "defaultBranch", skip_serializing_if = "Option::is_none")] pub default_branch: Option<DefaultBranchWire>,}
// Origin: knot-xrpc/src/reads.rs: ListReposOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct ListReposOut { pub repos: Vec<RepoWire>, #[serde(skip_serializing_if = "Option::is_none")] pub cursor: Option<String>,}
// Origin: knot-xrpc/src/reads.rs: BlameOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct BlameAuthorWire { pub name: AuthorName, pub email: Email,}
// Origin: knot-xrpc/src/reads.rs: BlameCommitOut#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct BlameCommitWire { pub sha: Oid, pub subject: String, #[serde(rename = "authoredAt")] pub authored_at: String, pub author: BlameAuthorWire,}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct BlameRunWire { pub start: u32, pub count: u32, pub commit: Oid,}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]pub struct BlameWire { pub commit: Oid, pub commits: Vec<BlameCommitWire>, pub runs: Vec<BlameRunWire>,}