httpd: Add patch update endpoint
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
This commit is contained in:
parent
dd97ac8384
commit
f2d31aa9c0
|
|
@ -12,8 +12,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use tower_http::set_header::SetResponseHeaderLayer;
|
use tower_http::set_header::SetResponseHeaderLayer;
|
||||||
|
|
||||||
use radicle::cob::{issue, patch};
|
use radicle::cob::{issue, patch, thread, ActorId, Tag};
|
||||||
use radicle::cob::{thread, ActorId, Tag};
|
|
||||||
use radicle::identity::Id;
|
use radicle::identity::Id;
|
||||||
use radicle::node::NodeId;
|
use radicle::node::NodeId;
|
||||||
use radicle::storage::git::paths;
|
use radicle::storage::git::paths;
|
||||||
|
|
@ -61,7 +60,10 @@ pub fn router(ctx: Context) -> Router {
|
||||||
"/projects/:project/patches",
|
"/projects/:project/patches",
|
||||||
post(patch_create_handler).get(patches_handler),
|
post(patch_create_handler).get(patches_handler),
|
||||||
)
|
)
|
||||||
.route("/projects/:project/patches/:id", get(patch_handler))
|
.route(
|
||||||
|
"/projects/:project/patches/:id",
|
||||||
|
get(patch_handler).patch(patch_update_handler),
|
||||||
|
)
|
||||||
.with_state(ctx)
|
.with_state(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -595,6 +597,81 @@ async fn patch_create_handler(
|
||||||
Json(json!({ "success": true, "id": patch.id.to_string() })),
|
Json(json!({ "success": true, "id": patch.id.to_string() })),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
/// Update an patch.
|
||||||
|
/// `PATCH /projects/:project/patches/:id`
|
||||||
|
async fn patch_update_handler(
|
||||||
|
State(ctx): State<Context>,
|
||||||
|
AuthBearer(token): AuthBearer,
|
||||||
|
Path((project, patch_id)): Path<(Id, Oid)>,
|
||||||
|
Json(action): Json<patch::Action>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
ctx.sessions
|
||||||
|
.write()
|
||||||
|
.await
|
||||||
|
.get(&token)
|
||||||
|
.ok_or(Error::Auth("Unauthorized"))?;
|
||||||
|
let storage = &ctx.profile.storage;
|
||||||
|
let signer = ctx
|
||||||
|
.profile
|
||||||
|
.signer()
|
||||||
|
.map_err(|_| Error::Auth("Unauthorized"))?;
|
||||||
|
let repo = storage.repository(project)?;
|
||||||
|
let mut patches = patch::Patches::open(&repo)?;
|
||||||
|
let mut patch = patches.get_mut(&patch_id.into())?;
|
||||||
|
match action {
|
||||||
|
patch::Action::Edit {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
target,
|
||||||
|
} => {
|
||||||
|
patch.edit(title, description, target, &signer)?;
|
||||||
|
}
|
||||||
|
patch::Action::Tag { add, remove } => {
|
||||||
|
patch.tag(add, remove, &signer)?;
|
||||||
|
}
|
||||||
|
patch::Action::Revision {
|
||||||
|
description,
|
||||||
|
base,
|
||||||
|
oid,
|
||||||
|
} => {
|
||||||
|
patch.update(description, base, oid, &signer)?;
|
||||||
|
}
|
||||||
|
patch::Action::Redact { .. } => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
patch::Action::Review {
|
||||||
|
revision,
|
||||||
|
comment,
|
||||||
|
verdict,
|
||||||
|
inline,
|
||||||
|
} => {
|
||||||
|
patch.review(revision, verdict, comment, inline, &signer)?;
|
||||||
|
}
|
||||||
|
patch::Action::Merge { revision, commit } => {
|
||||||
|
patch.merge(revision, commit, &signer)?;
|
||||||
|
}
|
||||||
|
patch::Action::Thread { action, revision } => match action {
|
||||||
|
thread::Action::Comment { body, reply_to } => {
|
||||||
|
if let Some(reply_to) = reply_to {
|
||||||
|
patch.comment(revision, body, Some(reply_to), &signer)?;
|
||||||
|
} else {
|
||||||
|
patch.thread(revision, body, &signer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thread::Action::Edit { .. } => {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
thread::Action::Redact { .. } => {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
thread::Action::React { .. } => {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok::<_, Error>(Json(json!({ "success": true })))
|
||||||
|
}
|
||||||
|
|
||||||
/// Get project patches list.
|
/// Get project patches list.
|
||||||
/// `GET /projects/:project/patches`
|
/// `GET /projects/:project/patches`
|
||||||
|
|
@ -643,16 +720,12 @@ mod routes {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::test::{
|
use crate::test::*;
|
||||||
self, get, patch, post, CONTRIBUTOR_ISSUE_ID, CONTRIBUTOR_PUB_KEY, CONTRIBUTOR_RID, HEAD,
|
|
||||||
INITIAL_COMMIT, ISSUE_COMMENT_ID, ISSUE_DISCUSSION_ID, ISSUE_ID, PARENT, PATCH_ID, RID,
|
|
||||||
SESSION_ID, TIMESTAMP,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_root() {
|
async fn test_projects_root() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(&app, "/projects").await;
|
let response = get(&app, "/projects").await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
@ -663,7 +736,7 @@ mod routes {
|
||||||
"name": "hello-world",
|
"name": "hello-world",
|
||||||
"description": "Rad repository for tests",
|
"description": "Rad repository for tests",
|
||||||
"defaultBranch": "master",
|
"defaultBranch": "master",
|
||||||
"delegates": ["did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"],
|
"delegates": [DID],
|
||||||
"head": HEAD,
|
"head": HEAD,
|
||||||
"patches": {
|
"patches": {
|
||||||
"proposed": 1,
|
"proposed": 1,
|
||||||
|
|
@ -683,7 +756,7 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects() {
|
async fn test_projects() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(&app, format!("/projects/{RID}")).await;
|
let response = get(&app, format!("/projects/{RID}")).await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
@ -693,7 +766,7 @@ mod routes {
|
||||||
"name": "hello-world",
|
"name": "hello-world",
|
||||||
"description": "Rad repository for tests",
|
"description": "Rad repository for tests",
|
||||||
"defaultBranch": "master",
|
"defaultBranch": "master",
|
||||||
"delegates": ["did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"],
|
"delegates": [DID],
|
||||||
"head": HEAD,
|
"head": HEAD,
|
||||||
"patches": {
|
"patches": {
|
||||||
"proposed": 1,
|
"proposed": 1,
|
||||||
|
|
@ -712,7 +785,7 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_commits_root() {
|
async fn test_projects_commits_root() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(&app, format!("/projects/{RID}/commits")).await;
|
let response = get(&app, format!("/projects/{RID}/commits")).await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
@ -945,7 +1018,7 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_commits() {
|
async fn test_projects_commits() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(&app, format!("/projects/{RID}/commits/{HEAD}")).await;
|
let response = get(&app, format!("/projects/{RID}/commits/{HEAD}")).await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
@ -1047,7 +1120,7 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_tree() {
|
async fn test_projects_tree() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(&app, format!("/projects/{RID}/tree/{HEAD}/")).await;
|
let response = get(&app, format!("/projects/{RID}/tree/{HEAD}/")).await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
@ -1132,7 +1205,7 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_remotes_root() {
|
async fn test_projects_remotes_root() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(&app, format!("/projects/{RID}/remotes")).await;
|
let response = get(&app, format!("/projects/{RID}/remotes")).await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
@ -1153,7 +1226,7 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_remotes() {
|
async fn test_projects_remotes() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(
|
let response = get(
|
||||||
&app,
|
&app,
|
||||||
format!("/projects/{RID}/remotes/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"),
|
format!("/projects/{RID}/remotes/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"),
|
||||||
|
|
@ -1176,7 +1249,7 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_blob() {
|
async fn test_projects_blob() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(&app, format!("/projects/{RID}/blob/{HEAD}/README")).await;
|
let response = get(&app, format!("/projects/{RID}/blob/{HEAD}/README")).await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
@ -1208,7 +1281,7 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_readme() {
|
async fn test_projects_readme() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(&app, format!("/projects/{RID}/readme/{INITIAL_COMMIT}")).await;
|
let response = get(&app, format!("/projects/{RID}/readme/{INITIAL_COMMIT}")).await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
@ -1240,7 +1313,7 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_diff() {
|
async fn test_projects_diff() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(
|
let response = get(
|
||||||
&app,
|
&app,
|
||||||
format!("/projects/{RID}/diff/{INITIAL_COMMIT}/{HEAD}"),
|
format!("/projects/{RID}/diff/{INITIAL_COMMIT}/{HEAD}"),
|
||||||
|
|
@ -1320,7 +1393,7 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_issues_root() {
|
async fn test_projects_issues_root() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let app = super::router(seed(tmp.path()));
|
||||||
let response = get(&app, format!("/projects/{RID}/issues")).await;
|
let response = get(&app, format!("/projects/{RID}/issues")).await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
@ -1330,7 +1403,7 @@ mod routes {
|
||||||
{
|
{
|
||||||
"id": ISSUE_ID,
|
"id": ISSUE_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
|
"id": DID
|
||||||
},
|
},
|
||||||
"title": "Issue #1",
|
"title": "Issue #1",
|
||||||
"state": {
|
"state": {
|
||||||
|
|
@ -1341,7 +1414,7 @@ mod routes {
|
||||||
{
|
{
|
||||||
"id": ISSUE_ID,
|
"id": ISSUE_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
|
"id": DID
|
||||||
},
|
},
|
||||||
"body": "Change 'hello world' to 'hello everyone'",
|
"body": "Change 'hello world' to 'hello everyone'",
|
||||||
"reactions": [],
|
"reactions": [],
|
||||||
|
|
@ -1360,10 +1433,10 @@ mod routes {
|
||||||
const CREATED_ISSUE_ID: &str = "b457364fbe2ef0eac69a835a087f60ee13ccb367";
|
const CREATED_ISSUE_ID: &str = "b457364fbe2ef0eac69a835a087f60ee13ccb367";
|
||||||
|
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let ctx = test::contributor(tmp.path());
|
let ctx = contributor(tmp.path());
|
||||||
let app = super::router(ctx.to_owned());
|
let app = super::router(ctx.to_owned());
|
||||||
|
|
||||||
test::create_session(ctx).await;
|
create_session(ctx).await;
|
||||||
|
|
||||||
let body = serde_json::to_vec(&json!({
|
let body = serde_json::to_vec(&json!({
|
||||||
"title": "Issue #2",
|
"title": "Issue #2",
|
||||||
|
|
@ -1398,7 +1471,7 @@ mod routes {
|
||||||
json!({
|
json!({
|
||||||
"id": CREATED_ISSUE_ID,
|
"id": CREATED_ISSUE_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": CONTRIBUTOR_PUB_KEY,
|
"id": CONTRIBUTOR_DID,
|
||||||
},
|
},
|
||||||
"assignees": [],
|
"assignees": [],
|
||||||
"title": "Issue #2",
|
"title": "Issue #2",
|
||||||
|
|
@ -1408,7 +1481,7 @@ mod routes {
|
||||||
"discussion": [{
|
"discussion": [{
|
||||||
"id": CREATED_ISSUE_ID,
|
"id": CREATED_ISSUE_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": CONTRIBUTOR_PUB_KEY,
|
"id": CONTRIBUTOR_DID,
|
||||||
},
|
},
|
||||||
"body": "Change 'hello world' to 'hello everyone'",
|
"body": "Change 'hello world' to 'hello everyone'",
|
||||||
"reactions": [],
|
"reactions": [],
|
||||||
|
|
@ -1425,10 +1498,10 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_issues_comment() {
|
async fn test_projects_issues_comment() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let ctx = test::contributor(tmp.path());
|
let ctx = contributor(tmp.path());
|
||||||
let app = super::router(ctx.to_owned());
|
let app = super::router(ctx.to_owned());
|
||||||
|
|
||||||
test::create_session(ctx).await;
|
create_session(ctx).await;
|
||||||
|
|
||||||
let body = serde_json::to_vec(&json!({
|
let body = serde_json::to_vec(&json!({
|
||||||
"type": "thread",
|
"type": "thread",
|
||||||
|
|
@ -1461,7 +1534,7 @@ mod routes {
|
||||||
json!({
|
json!({
|
||||||
"id": CONTRIBUTOR_ISSUE_ID,
|
"id": CONTRIBUTOR_ISSUE_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": CONTRIBUTOR_PUB_KEY,
|
"id": CONTRIBUTOR_DID,
|
||||||
},
|
},
|
||||||
"assignees": [],
|
"assignees": [],
|
||||||
"title": "Issue #1",
|
"title": "Issue #1",
|
||||||
|
|
@ -1472,7 +1545,7 @@ mod routes {
|
||||||
{
|
{
|
||||||
"id": ISSUE_DISCUSSION_ID,
|
"id": ISSUE_DISCUSSION_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": CONTRIBUTOR_PUB_KEY,
|
"id": CONTRIBUTOR_DID,
|
||||||
},
|
},
|
||||||
"body": "Change 'hello world' to 'hello everyone'",
|
"body": "Change 'hello world' to 'hello everyone'",
|
||||||
"reactions": [],
|
"reactions": [],
|
||||||
|
|
@ -1482,7 +1555,7 @@ mod routes {
|
||||||
{
|
{
|
||||||
"id": "9685b141c2e939c3d60f8ca34f8c7bf01a609af1",
|
"id": "9685b141c2e939c3d60f8ca34f8c7bf01a609af1",
|
||||||
"author": {
|
"author": {
|
||||||
"id": CONTRIBUTOR_PUB_KEY,
|
"id": CONTRIBUTOR_DID,
|
||||||
},
|
},
|
||||||
"body": "This is first-level comment",
|
"body": "This is first-level comment",
|
||||||
"reactions": [],
|
"reactions": [],
|
||||||
|
|
@ -1498,10 +1571,10 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_issues_reply() {
|
async fn test_projects_issues_reply() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let ctx = test::contributor(tmp.path());
|
let ctx = contributor(tmp.path());
|
||||||
let app = super::router(ctx.to_owned());
|
let app = super::router(ctx.to_owned());
|
||||||
|
|
||||||
test::create_session(ctx).await;
|
create_session(ctx).await;
|
||||||
|
|
||||||
let body = serde_json::to_vec(&json!({
|
let body = serde_json::to_vec(&json!({
|
||||||
"type": "thread",
|
"type": "thread",
|
||||||
|
|
@ -1536,7 +1609,7 @@ mod routes {
|
||||||
json!({
|
json!({
|
||||||
"id": CONTRIBUTOR_ISSUE_ID,
|
"id": CONTRIBUTOR_ISSUE_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": CONTRIBUTOR_PUB_KEY,
|
"id": CONTRIBUTOR_DID,
|
||||||
},
|
},
|
||||||
"assignees": [],
|
"assignees": [],
|
||||||
"title": "Issue #1",
|
"title": "Issue #1",
|
||||||
|
|
@ -1547,7 +1620,7 @@ mod routes {
|
||||||
{
|
{
|
||||||
"id": ISSUE_DISCUSSION_ID,
|
"id": ISSUE_DISCUSSION_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": CONTRIBUTOR_PUB_KEY,
|
"id": CONTRIBUTOR_DID,
|
||||||
},
|
},
|
||||||
"body": "Change 'hello world' to 'hello everyone'",
|
"body": "Change 'hello world' to 'hello everyone'",
|
||||||
"reactions": [],
|
"reactions": [],
|
||||||
|
|
@ -1557,7 +1630,7 @@ mod routes {
|
||||||
{
|
{
|
||||||
"id": ISSUE_COMMENT_ID,
|
"id": ISSUE_COMMENT_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": CONTRIBUTOR_PUB_KEY,
|
"id": CONTRIBUTOR_DID,
|
||||||
},
|
},
|
||||||
"body": "This is a reply to the first comment",
|
"body": "This is a reply to the first comment",
|
||||||
"reactions": [],
|
"reactions": [],
|
||||||
|
|
@ -1573,32 +1646,33 @@ mod routes {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_projects_patches() {
|
async fn test_projects_patches() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let app = super::router(test::seed(tmp.path()));
|
let ctx = contributor(tmp.path());
|
||||||
let response = get(&app, format!("/projects/{RID}/patches")).await;
|
let app = super::router(ctx.to_owned());
|
||||||
|
let response = get(&app, format!("/projects/{CONTRIBUTOR_RID}/patches")).await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response.json().await,
|
response.json().await,
|
||||||
json!([
|
json!([
|
||||||
{
|
{
|
||||||
"id": PATCH_ID,
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
|
"id": CONTRIBUTOR_DID
|
||||||
},
|
},
|
||||||
"title": "A new `hello word`",
|
"title": "A new `hello world`",
|
||||||
"description": "change `hello world` in README to something else",
|
"description": "change `hello world` in README to something else",
|
||||||
"state": { "status": "proposed" },
|
"state": { "status": "proposed" },
|
||||||
"target": "delegates",
|
"target": "delegates",
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"revisions": [
|
"revisions": [
|
||||||
{
|
{
|
||||||
"id": PATCH_ID,
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
"description": "",
|
"description": "",
|
||||||
"base": PARENT,
|
"base": PARENT,
|
||||||
"oid": HEAD,
|
"oid": HEAD,
|
||||||
"merges": [],
|
"merges": [],
|
||||||
"discussions": [],
|
"discussions": [],
|
||||||
"timestamp": 1671125284,
|
"timestamp": TIMESTAMP,
|
||||||
"reviews": [],
|
"reviews": [],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -1606,31 +1680,35 @@ mod routes {
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
let response = get(&app, format!("/projects/{RID}/patches/{PATCH_ID}")).await;
|
let response = get(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response.json().await,
|
response.json().await,
|
||||||
json!(
|
json!(
|
||||||
{
|
{
|
||||||
"id": PATCH_ID,
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
|
"id": CONTRIBUTOR_DID
|
||||||
},
|
},
|
||||||
"title": "A new `hello word`",
|
"title": "A new `hello world`",
|
||||||
"description": "change `hello world` in README to something else",
|
"description": "change `hello world` in README to something else",
|
||||||
"state": { "status": "proposed" },
|
"state": { "status": "proposed" },
|
||||||
"target": "delegates",
|
"target": "delegates",
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"revisions": [
|
"revisions": [
|
||||||
{
|
{
|
||||||
"id": PATCH_ID,
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
"description": "",
|
"description": "",
|
||||||
"base": PARENT,
|
"base": PARENT,
|
||||||
"oid": HEAD,
|
"oid": HEAD,
|
||||||
"merges": [],
|
"merges": [],
|
||||||
"discussions": [],
|
"discussions": [],
|
||||||
"timestamp": 1671125284,
|
"timestamp": TIMESTAMP,
|
||||||
"reviews": [],
|
"reviews": [],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -1644,10 +1722,10 @@ mod routes {
|
||||||
const CREATED_PATCH_ID: &str = "f69641cba6d7df2c22844d7f39225b5cda54d363";
|
const CREATED_PATCH_ID: &str = "f69641cba6d7df2c22844d7f39225b5cda54d363";
|
||||||
|
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let ctx = test::contributor(tmp.path());
|
let ctx = contributor(tmp.path());
|
||||||
let app = super::router(ctx.to_owned());
|
let app = super::router(ctx.to_owned());
|
||||||
|
|
||||||
test::create_session(ctx).await;
|
create_session(ctx).await;
|
||||||
|
|
||||||
let body = serde_json::to_vec(&json!({
|
let body = serde_json::to_vec(&json!({
|
||||||
"title": "Update README",
|
"title": "Update README",
|
||||||
|
|
@ -1690,7 +1768,7 @@ mod routes {
|
||||||
{
|
{
|
||||||
"id": CREATED_PATCH_ID,
|
"id": CREATED_PATCH_ID,
|
||||||
"author": {
|
"author": {
|
||||||
"id": CONTRIBUTOR_PUB_KEY
|
"id": CONTRIBUTOR_DID
|
||||||
},
|
},
|
||||||
"title": "Update README",
|
"title": "Update README",
|
||||||
"description": "Do some changes to README",
|
"description": "Do some changes to README",
|
||||||
|
|
@ -1705,7 +1783,7 @@ mod routes {
|
||||||
"oid": HEAD,
|
"oid": HEAD,
|
||||||
"merges": [],
|
"merges": [],
|
||||||
"discussions": [],
|
"discussions": [],
|
||||||
"timestamp": 1671125284,
|
"timestamp": TIMESTAMP,
|
||||||
"reviews": [],
|
"reviews": [],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -1713,4 +1791,443 @@ mod routes {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_projects_patches_tag() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let ctx = contributor(tmp.path());
|
||||||
|
let app = super::router(ctx.to_owned());
|
||||||
|
create_session(ctx).await;
|
||||||
|
let body = serde_json::to_vec(&json!({
|
||||||
|
"type": "tag",
|
||||||
|
"add": ["bug","design"],
|
||||||
|
"remove": []
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
let response = patch(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
Some(Body::from(body)),
|
||||||
|
Some(SESSION_ID.to_string()),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
let response = get(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
response.json().await,
|
||||||
|
json!({
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"author": {
|
||||||
|
"id": CONTRIBUTOR_DID,
|
||||||
|
},
|
||||||
|
"title": "A new `hello world`",
|
||||||
|
"description": "change `hello world` in README to something else",
|
||||||
|
"state": { "status": "proposed" },
|
||||||
|
"target": "delegates",
|
||||||
|
"tags": [
|
||||||
|
"bug",
|
||||||
|
"design"
|
||||||
|
],
|
||||||
|
"revisions": [
|
||||||
|
{
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"description": "",
|
||||||
|
"base": PARENT,
|
||||||
|
"oid": HEAD,
|
||||||
|
"merges": [],
|
||||||
|
"discussions": [],
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
"reviews": [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_projects_patches_revisions() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let ctx = contributor(tmp.path());
|
||||||
|
let app = super::router(ctx.to_owned());
|
||||||
|
create_session(ctx).await;
|
||||||
|
let body = serde_json::to_vec(&json!({
|
||||||
|
"type": "revision",
|
||||||
|
"description": "This is a new revision",
|
||||||
|
"base": PARENT,
|
||||||
|
"oid": HEAD,
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
let response = patch(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
Some(Body::from(body)),
|
||||||
|
Some(SESSION_ID.to_string()),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
let response = get(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
response.json().await,
|
||||||
|
json!({
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"author": {
|
||||||
|
"id": CONTRIBUTOR_DID,
|
||||||
|
},
|
||||||
|
"title": "A new `hello world`",
|
||||||
|
"description": "change `hello world` in README to something else",
|
||||||
|
"state": { "status": "proposed" },
|
||||||
|
"target": "delegates",
|
||||||
|
"tags": [],
|
||||||
|
"revisions": [
|
||||||
|
{
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"description": "",
|
||||||
|
"base": PARENT,
|
||||||
|
"oid": HEAD,
|
||||||
|
"merges": [],
|
||||||
|
"discussions": [],
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
"reviews": [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bdc0364b51a3346653a795b73332eb792283be37",
|
||||||
|
"description": "This is a new revision",
|
||||||
|
"base": PARENT,
|
||||||
|
"oid": HEAD,
|
||||||
|
"merges": [],
|
||||||
|
"discussions": [],
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
"reviews": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_projects_patches_edit() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let ctx = contributor(tmp.path());
|
||||||
|
let app = super::router(ctx.to_owned());
|
||||||
|
create_session(ctx).await;
|
||||||
|
let body = serde_json::to_vec(&json!({
|
||||||
|
"type": "edit",
|
||||||
|
"title": "This is a updated title",
|
||||||
|
"description": "Let's write some description",
|
||||||
|
"target": "delegates",
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
let response = patch(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
Some(Body::from(body)),
|
||||||
|
Some(SESSION_ID.to_string()),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
let response = get(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
response.json().await,
|
||||||
|
json!({
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"author": {
|
||||||
|
"id": CONTRIBUTOR_DID,
|
||||||
|
},
|
||||||
|
"title": "This is a updated title",
|
||||||
|
"description": "Let's write some description",
|
||||||
|
"state": { "status": "proposed" },
|
||||||
|
"target": "delegates",
|
||||||
|
"tags": [],
|
||||||
|
"revisions": [
|
||||||
|
{
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"description": "",
|
||||||
|
"base": PARENT,
|
||||||
|
"oid": HEAD,
|
||||||
|
"merges": [],
|
||||||
|
"discussions": [],
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
"reviews": [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_projects_patches_discussions() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let ctx = contributor(tmp.path());
|
||||||
|
let app = super::router(ctx.to_owned());
|
||||||
|
create_session(ctx).await;
|
||||||
|
let thread_body = serde_json::to_vec(&json!({
|
||||||
|
"type": "thread",
|
||||||
|
"revision": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"action": {
|
||||||
|
"type": "comment",
|
||||||
|
"body": "This is a root level comment"
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
let response = patch(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
Some(Body::from(thread_body)),
|
||||||
|
Some(SESSION_ID.to_string()),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
let reply_body = serde_json::to_vec(&json!({
|
||||||
|
"type": "thread",
|
||||||
|
"revision": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"action": {
|
||||||
|
"type": "comment",
|
||||||
|
"body": "This is a root level comment",
|
||||||
|
"replyTo": CONTRIBUTOR_COMMENT_1,
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
let response = patch(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
Some(Body::from(reply_body)),
|
||||||
|
Some(SESSION_ID.to_string()),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
let response = get(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
response.json().await,
|
||||||
|
json!({
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"author": {
|
||||||
|
"id": CONTRIBUTOR_DID,
|
||||||
|
},
|
||||||
|
"title": "A new `hello world`",
|
||||||
|
"description": "change `hello world` in README to something else",
|
||||||
|
"state": { "status": "proposed" },
|
||||||
|
"target": "delegates",
|
||||||
|
"tags": [],
|
||||||
|
"revisions": [
|
||||||
|
{
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"description": "",
|
||||||
|
"base": PARENT,
|
||||||
|
"oid": HEAD,
|
||||||
|
"merges": [],
|
||||||
|
"discussions": [
|
||||||
|
{
|
||||||
|
"id": CONTRIBUTOR_COMMENT_1,
|
||||||
|
"author": {
|
||||||
|
"id": CONTRIBUTOR_DID,
|
||||||
|
},
|
||||||
|
"body": "This is a root level comment",
|
||||||
|
"reactions": [],
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
"replyTo": null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": CONTRIBUTOR_COMMENT_2,
|
||||||
|
"author": {
|
||||||
|
"id": CONTRIBUTOR_DID,
|
||||||
|
},
|
||||||
|
"body": "This is a root level comment",
|
||||||
|
"reactions": [],
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
"replyTo": CONTRIBUTOR_COMMENT_1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
"reviews": [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_projects_patches_reviews() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let ctx = contributor(tmp.path());
|
||||||
|
let app = super::router(ctx.to_owned());
|
||||||
|
create_session(ctx).await;
|
||||||
|
let thread_body = serde_json::to_vec(&json!({
|
||||||
|
"type": "review",
|
||||||
|
"revision": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"comment": "A small review",
|
||||||
|
"verdict": "accept",
|
||||||
|
"inline": [
|
||||||
|
{
|
||||||
|
"location": {
|
||||||
|
"blob": HEAD,
|
||||||
|
"commit": HEAD,
|
||||||
|
"lines": {
|
||||||
|
"start": 1,
|
||||||
|
"end": 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"comment": "This is a comment on line 1",
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
let response = patch(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
Some(Body::from(thread_body)),
|
||||||
|
Some(SESSION_ID.to_string()),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
let response = get(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
response.json().await,
|
||||||
|
json!({
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"author": {
|
||||||
|
"id": CONTRIBUTOR_DID,
|
||||||
|
},
|
||||||
|
"title": "A new `hello world`",
|
||||||
|
"description": "change `hello world` in README to something else",
|
||||||
|
"state": { "status": "proposed" },
|
||||||
|
"target": "delegates",
|
||||||
|
"tags": [],
|
||||||
|
"revisions": [
|
||||||
|
{
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"description": "",
|
||||||
|
"base": PARENT,
|
||||||
|
"oid": HEAD,
|
||||||
|
"merges": [],
|
||||||
|
"discussions": [],
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
"reviews": [
|
||||||
|
[
|
||||||
|
CONTRIBUTOR_NID,
|
||||||
|
{
|
||||||
|
"verdict": "accept",
|
||||||
|
"comment": "A small review",
|
||||||
|
"inline": [
|
||||||
|
{
|
||||||
|
"location": {
|
||||||
|
"blob": HEAD,
|
||||||
|
"commit": HEAD,
|
||||||
|
"lines": {
|
||||||
|
"start": 1,
|
||||||
|
"end": 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"comment": "This is a comment on line 1",
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_projects_patches_merges() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let ctx = contributor(tmp.path());
|
||||||
|
let app = super::router(ctx.to_owned());
|
||||||
|
create_session(ctx).await;
|
||||||
|
let thread_body = serde_json::to_vec(&json!({
|
||||||
|
"type": "merge",
|
||||||
|
"revision": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"commit": PARENT,
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
let response = patch(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
Some(Body::from(thread_body)),
|
||||||
|
Some(SESSION_ID.to_string()),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
let response = get(
|
||||||
|
&app,
|
||||||
|
format!("/projects/{CONTRIBUTOR_RID}/patches/{CONTRIBUTOR_PATCH_ID}"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
response.json().await,
|
||||||
|
json!({
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"author": {
|
||||||
|
"id": CONTRIBUTOR_DID,
|
||||||
|
},
|
||||||
|
"title": "A new `hello world`",
|
||||||
|
"description": "change `hello world` in README to something else",
|
||||||
|
"state": { "status": "proposed" },
|
||||||
|
"target": "delegates",
|
||||||
|
"tags": [],
|
||||||
|
"revisions": [
|
||||||
|
{
|
||||||
|
"id": CONTRIBUTOR_PATCH_ID,
|
||||||
|
"description": "",
|
||||||
|
"base": PARENT,
|
||||||
|
"oid": HEAD,
|
||||||
|
"merges": [
|
||||||
|
{
|
||||||
|
"node": CONTRIBUTOR_NID,
|
||||||
|
"commit": PARENT,
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"discussions": [],
|
||||||
|
"timestamp": TIMESTAMP,
|
||||||
|
"reviews": [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,15 +27,19 @@ pub const RID: &str = "rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp";
|
||||||
pub const HEAD: &str = "e8c676b9e3b42308dc9d218b70faa5408f8e58ca";
|
pub const HEAD: &str = "e8c676b9e3b42308dc9d218b70faa5408f8e58ca";
|
||||||
pub const PARENT: &str = "ee8d6a29304623a78ebfa5eeed5af674d0e58f83";
|
pub const PARENT: &str = "ee8d6a29304623a78ebfa5eeed5af674d0e58f83";
|
||||||
pub const INITIAL_COMMIT: &str = "f604ce9fd5b7cc77b7609beda45ea8760bee78f7";
|
pub const INITIAL_COMMIT: &str = "f604ce9fd5b7cc77b7609beda45ea8760bee78f7";
|
||||||
pub const PATCH_ID: &str = "a6afa179631163169bf9fb0921229317ec3950af";
|
pub const DID: &str = "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi";
|
||||||
pub const ISSUE_ID: &str = "5ad77fa3f476beed9a26f49b2b3b844e61bef792";
|
pub const ISSUE_ID: &str = "5ad77fa3f476beed9a26f49b2b3b844e61bef792";
|
||||||
pub const ISSUE_DISCUSSION_ID: &str = "f1dff128a22e8183a23516dd9812e72e80914c92";
|
pub const ISSUE_DISCUSSION_ID: &str = "f1dff128a22e8183a23516dd9812e72e80914c92";
|
||||||
pub const ISSUE_COMMENT_ID: &str = "845218041bf9eb8155bfa4aaa8f0c91ce18e5c13";
|
pub const ISSUE_COMMENT_ID: &str = "845218041bf9eb8155bfa4aaa8f0c91ce18e5c13";
|
||||||
pub const SESSION_ID: &str = "u9MGAkkfkMOv0uDDB2WeUHBT7HbsO2Dy";
|
pub const SESSION_ID: &str = "u9MGAkkfkMOv0uDDB2WeUHBT7HbsO2Dy";
|
||||||
pub const TIMESTAMP: u64 = 1671125284;
|
pub const TIMESTAMP: u64 = 1671125284;
|
||||||
pub const CONTRIBUTOR_RID: &str = "rad:z4XaCmN3jLSeiMvW15YTDpNbDHFhG";
|
pub const CONTRIBUTOR_RID: &str = "rad:z4XaCmN3jLSeiMvW15YTDpNbDHFhG";
|
||||||
pub const CONTRIBUTOR_PUB_KEY: &str = "did:key:z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8";
|
pub const CONTRIBUTOR_DID: &str = "did:key:z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8";
|
||||||
|
pub const CONTRIBUTOR_NID: &str = "z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8";
|
||||||
pub const CONTRIBUTOR_ISSUE_ID: &str = "f1dff128a22e8183a23516dd9812e72e80914c92";
|
pub const CONTRIBUTOR_ISSUE_ID: &str = "f1dff128a22e8183a23516dd9812e72e80914c92";
|
||||||
|
pub const CONTRIBUTOR_PATCH_ID: &str = "4b7ea91da1f551bc5ea5d2057125d7ba42d451cb";
|
||||||
|
pub const CONTRIBUTOR_COMMENT_1: &str = "8f6e72c20da0e6ee2af004f059ced23d409a285a";
|
||||||
|
pub const CONTRIBUTOR_COMMENT_2: &str = "c88ce78b17a705f389e72ec5c80da7360a675e51";
|
||||||
|
|
||||||
const PASSWORD: &str = "radicle";
|
const PASSWORD: &str = "radicle";
|
||||||
|
|
||||||
|
|
@ -178,7 +182,7 @@ fn seed_with_signer<G: Signer>(dir: &Path, profile: radicle::Profile, signer: &G
|
||||||
let base = radicle::git::Oid::from_str(PARENT).unwrap();
|
let base = radicle::git::Oid::from_str(PARENT).unwrap();
|
||||||
let _ = patches
|
let _ = patches
|
||||||
.create(
|
.create(
|
||||||
"A new `hello word`",
|
"A new `hello world`",
|
||||||
"change `hello world` in README to something else",
|
"change `hello world` in README to something else",
|
||||||
MergeTarget::Delegates,
|
MergeTarget::Delegates,
|
||||||
base,
|
base,
|
||||||
|
|
|
||||||
|
|
@ -519,9 +519,10 @@ impl Serialize for Review {
|
||||||
where
|
where
|
||||||
S: serde::ser::Serializer,
|
S: serde::ser::Serializer,
|
||||||
{
|
{
|
||||||
let mut state = serializer.serialize_struct("Review", 3)?;
|
let mut state = serializer.serialize_struct("Review", 4)?;
|
||||||
state.serialize_field("verdict", &self.verdict())?;
|
state.serialize_field("verdict", &self.verdict())?;
|
||||||
state.serialize_field("comment", &self.comment())?;
|
state.serialize_field("comment", &self.comment())?;
|
||||||
|
state.serialize_field("inline", &self.inline().collect::<Vec<_>>())?;
|
||||||
state.serialize_field("timestamp", &self.timestamp())?;
|
state.serialize_field("timestamp", &self.timestamp())?;
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
|
|
@ -560,6 +561,10 @@ impl Review {
|
||||||
self.verdict.get().as_ref().copied()
|
self.verdict.get().as_ref().copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn inline(&self) -> impl Iterator<Item = &CodeComment> {
|
||||||
|
self.inline.iter().map(|m| m.get())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn comment(&self) -> Option<&str> {
|
pub fn comment(&self) -> Option<&str> {
|
||||||
self.comment.get().as_ref().map(|m| m.get().as_str())
|
self.comment.get().as_ref().map(|m| m.get().as_str())
|
||||||
}
|
}
|
||||||
|
|
@ -721,6 +726,16 @@ impl<'a, 'g> PatchMut<'a, 'g> {
|
||||||
self.transaction("Edit", signer, |tx| tx.edit(title, description, target))
|
self.transaction("Edit", signer, |tx| tx.edit(title, description, target))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a thread on a patch revision.
|
||||||
|
pub fn thread<G: Signer, S: ToString>(
|
||||||
|
&mut self,
|
||||||
|
revision: RevisionId,
|
||||||
|
body: S,
|
||||||
|
signer: &G,
|
||||||
|
) -> Result<CommentId, Error> {
|
||||||
|
self.transaction("Create thread", signer, |tx| tx.thread(revision, body))
|
||||||
|
}
|
||||||
|
|
||||||
/// Comment on a patch revision.
|
/// Comment on a patch revision.
|
||||||
pub fn comment<G: Signer, S: ToString>(
|
pub fn comment<G: Signer, S: ToString>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue