Feature/fe new registry (#2647)

* bugfixes

* update fe types

* implement new registry types in marketplace and ui

* fix marketplace types to have default params

* add alt implementation toggle

* merge cleanup

* more cleanup and notes

* fix build

* cleanup sync with next/minor

* add exver JS parser

* parse ValidExVer to string

* update types to interface

* add VersionRange and comparative functions

* Parse ExtendedVersion from string

* add conjunction, disjunction, and inversion logic

* consider flavor in satisfiedBy fn

* consider prerelease for ordering

* add compare fn for sorting

* rename fns for consistency

* refactoring

* update compare fn to return null if flavors don't match

* begin simplifying dependencies

* under construction

* wip

* add dependency metadata to CurrentDependencyInfo

* ditch inheritance for recursive VersionRange constructor. Recursive 'satisfiedBy' fn wip

* preprocess manifest

* misc fixes

* use sdk version as osVersion in manifest

* chore: Change the type to just validate and not generate all solutions.

* add publishedAt

* fix pegjs exports

* integrate exver into sdk

* misc fixes

* complete satisfiedBy fn

* refactor - use greaterThanOrEqual and lessThanOrEqual fns

* fix tests

* update dependency details

* update types

* remove interim types

* rename alt implementation to flavor

* cleanup os update

* format exver.ts

* add s9pk parsing endpoints

* fix build

* update to exver

* exver and bug fixes

* update static endpoints + cleanup

* cleanup

* update static proxy verification

* make mocks more robust; fix dep icon fallback; cleanup

* refactor alert versions and update fixtures

* registry bugfixes

* misc fixes

* cleanup unused

* convert patchdb ui seed to camelCase

* update otherVersions type

* change otherVersions: null to 'none'

* refactor and complete feature

* improve static endpoints

* fix install params

* mask systemd-networkd-wait-online

* fix static file fetching

* include non-matching versions in otherVersions

* convert release notes to modal and clean up displayExver

* alert for no other versions

* Fix ack-instructions casing

* fix indeterminate loader on service install

---------

Co-authored-by: Aiden McClelland <me@drbonez.dev>
Co-authored-by: Shadowy Super Coder <musashidisciple@proton.me>
Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
Co-authored-by: J H <dragondef@gmail.com>
Co-authored-by: Matt Hill <mattnine@protonmail.com>
This commit is contained in:
Lucy
2024-07-22 20:48:12 -04:00
committed by GitHub
parent 0fbb18b315
commit a535fc17c3
196 changed files with 7002 additions and 2162 deletions

View File

@@ -1,13 +1,16 @@
use std::collections::{BTreeMap, VecDeque};
use std::fmt;
use std::future::Future;
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::pin::Pin;
use std::process::Stdio;
use std::str::FromStr;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::time::Duration;
use ::serde::{Deserialize, Serialize};
use async_trait::async_trait;
use color_eyre::eyre::{self, eyre};
use fd_lock_rs::FdLock;
@@ -24,9 +27,12 @@ use tokio::fs::File;
use tokio::io::{AsyncRead, AsyncReadExt, BufReader};
use tokio::sync::{oneshot, Mutex, OwnedMutexGuard, RwLock};
use tracing::instrument;
use ts_rs::TS;
use url::Url;
use crate::shutdown::Shutdown;
use crate::util::io::create_file;
use crate::util::serde::{deserialize_from_str, serialize_display};
use crate::{Error, ErrorKind, ResultExt as _};
pub mod actor;
pub mod clap;
@@ -648,3 +654,48 @@ pub fn new_guid() -> InternedString {
&buf,
))
}
#[derive(Debug, Clone, TS)]
#[ts(type = "string")]
pub enum PathOrUrl {
Path(PathBuf),
Url(Url),
}
impl FromStr for PathOrUrl {
type Err = <PathBuf as FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(url) = s.parse::<Url>() {
if url.scheme() == "file" {
Ok(Self::Path(url.path().parse()?))
} else {
Ok(Self::Url(url))
}
} else {
Ok(Self::Path(s.parse()?))
}
}
}
impl fmt::Display for PathOrUrl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Path(p) => write!(f, "file://{}", p.display()),
Self::Url(u) => write!(f, "{u}"),
}
}
}
impl<'de> Deserialize<'de> for PathOrUrl {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
deserialize_from_str(deserializer)
}
}
impl Serialize for PathOrUrl {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ::serde::Serializer,
{
serialize_display(self, serializer)
}
}

View File

@@ -1,19 +1,25 @@
use core::fmt;
use std::borrow::Cow;
use std::sync::Mutex;
use axum::extract::ws::{self, CloseFrame};
use futures::Future;
use futures::{Future, Stream, StreamExt};
use crate::prelude::*;
pub trait WebSocketExt {
fn normal_close(
self,
msg: impl Into<Cow<'static, str>>,
) -> impl Future<Output = Result<(), Error>>;
msg: impl Into<Cow<'static, str>> + Send,
) -> impl Future<Output = Result<(), Error>> + Send;
fn close_result(
self,
result: Result<impl Into<Cow<'static, str>> + Send, impl fmt::Display + Send>,
) -> impl Future<Output = Result<(), Error>> + Send;
}
impl WebSocketExt for ws::WebSocket {
async fn normal_close(mut self, msg: impl Into<Cow<'static, str>>) -> Result<(), Error> {
async fn normal_close(mut self, msg: impl Into<Cow<'static, str>> + Send) -> Result<(), Error> {
self.send(ws::Message::Close(Some(CloseFrame {
code: 1000,
reason: msg.into(),
@@ -21,4 +27,41 @@ impl WebSocketExt for ws::WebSocket {
.await
.with_kind(ErrorKind::Network)
}
async fn close_result(
mut self,
result: Result<impl Into<Cow<'static, str>> + Send, impl fmt::Display + Send>,
) -> Result<(), Error> {
match result {
Ok(msg) => self
.send(ws::Message::Close(Some(CloseFrame {
code: 1000,
reason: msg.into(),
})))
.await
.with_kind(ErrorKind::Network),
Err(e) => self
.send(ws::Message::Close(Some(CloseFrame {
code: 1011,
reason: e.to_string().into(),
})))
.await
.with_kind(ErrorKind::Network),
}
}
}
pub struct SyncBody(Mutex<axum::body::BodyDataStream>);
impl From<axum::body::Body> for SyncBody {
fn from(value: axum::body::Body) -> Self {
SyncBody(Mutex::new(value.into_data_stream()))
}
}
impl Stream for SyncBody {
type Item = <axum::body::BodyDataStream as Stream>::Item;
fn poll_next(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Option<Self::Item>> {
self.0.lock().unwrap().poll_next_unpin(cx)
}
}

View File

@@ -12,7 +12,7 @@ use crate::s9pk::merkle_archive::source::multi_cursor_file::MultiCursorFile;
use crate::s9pk::merkle_archive::source::ArchiveSource;
use crate::util::io::{open_file, ParallelBlake3Writer};
use crate::util::serde::Base16;
use crate::util::Apply;
use crate::util::{Apply, PathOrUrl};
use crate::CAP_10_MiB;
pub fn util<C: Context>() -> ParentHandler<C> {
@@ -45,21 +45,20 @@ pub async fn b3sum(
}
b3sum_source(file).await
}
if let Ok(url) = file.parse::<Url>() {
if url.scheme() == "file" {
b3sum_file(url.path(), allow_mmap).await
} else if url.scheme() == "http" || url.scheme() == "https" {
HttpSource::new(ctx.client.clone(), url)
.await?
.apply(b3sum_source)
.await
} else {
return Err(Error::new(
eyre!("unknown scheme: {}", url.scheme()),
ErrorKind::InvalidRequest,
));
match file.parse::<PathOrUrl>()? {
PathOrUrl::Path(path) => b3sum_file(path, allow_mmap).await,
PathOrUrl::Url(url) => {
if url.scheme() == "http" || url.scheme() == "https" {
HttpSource::new(ctx.client.clone(), url)
.await?
.apply(b3sum_source)
.await
} else {
Err(Error::new(
eyre!("unknown scheme: {}", url.scheme()),
ErrorKind::InvalidRequest,
))
}
}
} else {
b3sum_file(file, allow_mmap).await
}
}

View File

@@ -1,8 +1,10 @@
use std::any::Any;
use std::collections::VecDeque;
use std::marker::PhantomData;
use std::ops::Deref;
use std::str::FromStr;
use base64::Engine;
use clap::builder::ValueParserFactory;
use clap::{ArgMatches, CommandFactory, FromArgMatches};
use color_eyre::eyre::eyre;
@@ -37,7 +39,11 @@ pub fn deserialize_from_str<
{
type Value = T;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(formatter, "a parsable string")
write!(
formatter,
"a string that can be parsed as a {}",
std::any::type_name::<T>()
)
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
@@ -988,18 +994,24 @@ impl<T: AsRef<[u8]>> Serialize for Base32<T> {
}
}
pub const BASE64: base64::engine::GeneralPurpose = base64::engine::GeneralPurpose::new(
&base64::alphabet::STANDARD,
base64::engine::GeneralPurposeConfig::new(),
);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TS)]
#[ts(type = "string", concrete(T = Vec<u8>))]
pub struct Base64<T>(pub T);
impl<T: AsRef<[u8]>> std::fmt::Display for Base64<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&base64::encode(self.0.as_ref()))
f.write_str(&BASE64.encode(self.0.as_ref()))
}
}
impl<T: TryFrom<Vec<u8>>> FromStr for Base64<T> {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
base64::decode(&s)
BASE64
.decode(&s)
.with_kind(ErrorKind::Deserialization)?
.apply(TryFrom::try_from)
.map(Self)