Skip to content

Commit

Permalink
Add list_repo command and repo listing
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastinez committed Sep 5, 2024
1 parent 8c8d2ae commit ccfb54c
Show file tree
Hide file tree
Showing 22 changed files with 540 additions and 8 deletions.
16 changes: 15 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"dependencies": {
"@tauri-apps/api": "^2.0.0-beta.15",
"@tauri-apps/plugin-shell": "^2.0.0-beta.8",
"@tauri-apps/plugin-window-state": "^2.0.0-rc.0"
"@tauri-apps/plugin-window-state": "^2.0.0-rc.0",
"bs58": "^6.0.0"
},
"devDependencies": {
"@eslint/js": "^9.9.1",
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ tauri = { version = "2.0.0-rc.0", features = ["isolation"] }
tauri-plugin-shell = { version = "2.0.0-rc.0" }
tauri-plugin-window-state = "2.0.0-rc.1"
thiserror = { version = "1.0.63" }
ts-rs = { version = "9.0.1", features = ["serde-json-impl"] }
ts-rs = { version = "9.0.1", features = ["serde-json-impl", "no-serde-warnings"] }

[features]
# by default Tauri runs in production mode
Expand Down
15 changes: 15 additions & 0 deletions src-tauri/bindings/RepoInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { JsonValue } from "./serde_json/JsonValue";
import type { SupportedPayloads } from "./SupportedPayloads";

/**
* Repos info.
*/
export type RepoInfo = {
payloads: SupportedPayloads;
delegates: Array<JsonValue>;
threshold: number;
visibility: { type: "public" } | { type: "private"; allow?: string[] };
rid: string;
seeding: number;
};
25 changes: 25 additions & 0 deletions src-tauri/bindings/SupportedPayloads.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type SupportedPayloads = {
"xyz.radicle.project"?: {
data: {
defaultBranch: string;
description: string;
name: string;
};
meta: {
head: string;
issues: {
open: number;
closed: number;
};
patches: {
open: number;
draft: number;
archived: number;
merged: number;
};
lastCommit: number;
};
};
};
7 changes: 7 additions & 0 deletions src-tauri/bindings/serde_json/JsonValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type JsonValue =
| number
| string
| Array<JsonValue>
| { [key: string]: JsonValue };
2 changes: 2 additions & 0 deletions src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod auth;
pub mod repos;
File renamed without changes.
30 changes: 30 additions & 0 deletions src-tauri/src/commands/repos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use radicle::storage::ReadStorage;

use crate::error::Error;
use crate::types;
use crate::AppState;

/// List all repos.
#[tauri::command]
pub fn list_repos(ctx: tauri::State<AppState>) -> Result<Vec<types::repo::RepoInfo>, Error> {
let storage = &ctx.profile.storage;
let policies = ctx.profile.policies()?;

let mut repos = storage.repositories()?.into_iter().collect::<Vec<_>>();
repos.sort_by_key(|p| p.rid);

let infos = repos
.into_iter()
.filter_map(|info| {
if !policies.is_seeding(&info.rid).unwrap_or_default() {
return None;
}
let (repo, doc) = ctx.repo(info.rid).ok()?;
let repo_info = ctx.repo_info(&repo, doc).ok()?;

Some(repo_info)
})
.collect::<Vec<_>>();

Ok::<_, Error>(infos)
}
19 changes: 19 additions & 0 deletions src-tauri/src/json.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use serde_json::{json, Value};

use radicle::identity;
use radicle::node::AliasStore;

pub(crate) struct Author<'a>(&'a identity::Did);

impl<'a> Author<'a> {
pub fn new(did: &'a identity::Did) -> Self {
Self(did)
}

pub fn as_json(&self, aliases: &impl AliasStore) -> Value {
aliases.alias(self.0).map_or(
json!({ "id": self.0 }),
|alias| json!({ "id": self.0, "alias": alias, }),
)
}
}
82 changes: 79 additions & 3 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,86 @@
mod auth;
mod commands;
mod error;
mod json;
mod types;

use auth::authenticate;
use serde_json::json;
use tauri::Manager;

use radicle::identity::doc::PayloadId;
use radicle::identity::DocAt;
use radicle::identity::RepoId;
use radicle::issue::cache::Issues;
use radicle::node::routing::Store;
use radicle::patch::cache::Patches;
use radicle::storage::git::Repository;
use radicle::storage::{ReadRepository, ReadStorage};

use commands::{auth, repos};
use types::repo::SupportedPayloads;

struct AppState {
profile: radicle::Profile,
}

impl AppState {
pub fn repo_info<R: ReadRepository + radicle::cob::Store>(
&self,
repo: &R,
doc: DocAt,
) -> Result<types::repo::RepoInfo, error::Error> {
let DocAt { doc, .. } = doc;
let rid = repo.id();

let aliases = self.profile.aliases();
let delegates = doc
.delegates
.into_iter()
.map(|did| json::Author::new(&did).as_json(&aliases))
.collect::<Vec<_>>();
let db = &self.profile.database()?;
let seeding = db.count(&rid).unwrap_or_default();

let project = doc
.payload
.get(&PayloadId::project())
.map(|payload| {
let (_, head) = repo.head().ok()?;
let commit = repo.commit(head).ok()?;
let patches = self.profile.patches(repo).ok()?;
let patches = patches.counts().ok()?;
let issues = self.profile.issues(repo).ok()?;
let issues = issues.counts().ok()?;

Some(json!({
"data": payload,
"meta": {
"issues": issues,
"patches": patches,
"head": head,
"lastCommit": commit.time().seconds(),
},
}))
})
.flatten();

Ok(types::repo::RepoInfo {
payloads: SupportedPayloads { project },
delegates,
threshold: doc.threshold,
visibility: doc.visibility,
rid,
seeding,
})
}

/// Get a repository by RID, checking to make sure we're allowed to view it.
pub fn repo(&self, rid: RepoId) -> Result<(Repository, DocAt), error::Error> {
let repo = self.profile.storage.repository(rid)?;
let doc = repo.identity_doc()?;
Ok((repo, doc))
}
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
Expand All @@ -30,7 +103,10 @@ pub fn run() {
})
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_window_state::Builder::default().build())
.invoke_handler(tauri::generate_handler![authenticate])
.invoke_handler(tauri::generate_handler![
auth::authenticate,
repos::list_repos
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
1 change: 1 addition & 0 deletions src-tauri/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod repo;
49 changes: 49 additions & 0 deletions src-tauri/src/types/repo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use serde::Serialize;
use serde_json::Value;
use ts_rs::TS;

use radicle::identity::RepoId;

/// Repos info.
#[derive(Serialize, TS)]
#[ts(export)]
pub struct RepoInfo {
pub payloads: SupportedPayloads,
pub delegates: Vec<Value>,
pub threshold: usize,
#[ts(type = "{ type: 'public' } | { type: 'private', allow?: string[] }")]
pub visibility: radicle::identity::Visibility,
#[ts(as = "String")]
pub rid: RepoId,
pub seeding: usize,
}

#[derive(Serialize, TS)]
#[ts(export)]
pub struct SupportedPayloads {
#[serde(rename = "xyz.radicle.project")]
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
#[ts(type = r#"{
data: {
defaultBranch: string,
description: string,
name: string,
},
meta: {
head: string,
issues: {
open: number,
closed: number,
},
patches: {
open: number,
draft: number,
archived: number,
merged: number,
}
lastCommit: number,
}
}"#)]
pub project: Option<Value>,
}
5 changes: 4 additions & 1 deletion src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
import { theme } from "@app/components/ThemeSwitch.svelte";
import { unreachable } from "@app/lib/utils";
import AuthenticationError from "@app/views/AuthenticationError.svelte";
import DesignSystem from "@app/views/DesignSystem.svelte";
import Home from "@app/views/Home.svelte";
import AuthenticationError from "@app/views/AuthenticationError.svelte";
import Repos from "@app/views/Repos.svelte";
const activeRouteStore = router.activeRouteStore;
void router.loadFromLocation();
Expand Down Expand Up @@ -41,6 +42,8 @@
<AuthenticationError {...$activeRouteStore.params} />
{:else if $activeRouteStore.resource === "designSystem"}
<DesignSystem />
{:else if $activeRouteStore.resource === "repos"}
<Repos {...$activeRouteStore.params} />
{:else}
{unreachable($activeRouteStore)}
{/if}
7 changes: 6 additions & 1 deletion src/components/Border.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
export let variant: "primary" | "secondary" | "ghost";
export let stylePadding: string | undefined = undefined;
export let styleHeight: string | undefined = undefined;
export let styleTextOverflow: boolean = false;
export let styleFontWeight: string = "txt-semibold";
$: style = `--button-color-1: var(--color-fill-${variant});`;
</script>
Expand Down Expand Up @@ -146,7 +148,10 @@

<div class="pixel p3-1"></div>
<div class="pixel p3-2"></div>
<div class="pixel p3-3 txt-semibold txt-small" style:padding={stylePadding}>
<div
class:txt-overflow={styleTextOverflow}
class={`pixel p3-3 txt-overflow ${styleFontWeight} txt-small`}
style:padding={stylePadding}>
<slot />
</div>
<div class="pixel p3-4"></div>
Expand Down
22 changes: 22 additions & 0 deletions src/components/Icon.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
| "diff"
| "file"
| "inbox"
| "issue"
| "moon"
| "offline"
| "patch"
| "plus"
| "repo"
| "seedling"
Expand Down Expand Up @@ -133,6 +135,18 @@
<path d="M6 9H10L10 10H6L6 9Z" />
<path d="M3 13H13V14H3L3 13Z" />
<path d="M3 2H13V3H3L3 2Z" />
{:else if name === "issue"}
<path d="M10 4H11V5H10V4Z" />
<path d="M11 5L12 5V6H11V5Z" />
<path d="M10 6L12 6V7H10V6Z" />
<path d="M9 6H10V7H9V6Z" />
<path d="M8 5H9L9 6L8 6V5Z" />
<path d="M8 3H9V5H8V3Z" />
<path d="M9 3L10 3V4H9V3Z" />
<path d="M4 13H12V14H4V13Z" />
<path d="M4 2H9V3L4 3V2Z" />
<path d="M13 6V13H12V6L13 6Z" />
<path d="M4 3V13H3L3 3L4 3Z" />
{:else if name === "moon"}
<path d="M4 3H6V4H4V3Z" />
<path d="M3 4L4 4L4 6H3V4Z" />
Expand Down Expand Up @@ -195,6 +209,14 @@
<path d="M4 11L5 11V12L4 12L4 11Z" />
<path d="M3 12H4L4 13H3L3 12Z" />
<path d="M2 13L3 13L3 14H2V13Z" />
{:else if name === "patch"}
<path d="M2 3H3V13H2V3Z" />
<path d="M3 13H12V14H3L3 13Z" />
<path d="M3 2H12V3L3 3L3 2Z" />
<path d="M12 3L13 3V13H12V3Z" />
<path d="M7 4H8V9H7V4Z" />
<path d="M5 6H10V7H5V6Z" />
<path d="M5 10H10V11H5V10Z" />
{:else if name === "plus"}
<path d="M7.00002 2H9.00002V14H7.00002V2Z" />
<path d="M14 7V9L2.00002 9L2.00002 7L14 7Z" />
Expand Down
Loading

0 comments on commit ccfb54c

Please sign in to comment.