Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ members = [
"crates/but-error", # 📄Error codes to communicate specific failures; JSON Error for frontends.
"crates/but-testsupport", # 📄Despite lacking tests, it is the foundation for all tests.
"crates/but-feedback", # 📄It's very small and very special, but documented and well-enough tested.
"crates/but-project-handle", # 📄Temporary home of ProjectHandle until `gitbutler-project` is gone and it can merge back into `but-ctx`.

##
### 👷Needs work
Expand Down Expand Up @@ -175,6 +176,7 @@ but-update = { path = "crates/but-update" }
but-installer = { path = "crates/but-installer" }
but-secret = { path = "crates/but-secret" }
but-feedback = { path = "crates/but-feedback" }
but-project-handle = { path = "crates/but-project-handle" }
but-forge-storage = { path = "crates/but-forge-storage" }
but-settings = { path = "crates/but-settings" }
but-oxidize = { path = "crates/but-oxidize" }
Expand Down Expand Up @@ -252,6 +254,7 @@ reqwest = { version = "0.12.28", default-features = false, features = [
"json",
] }
chrono = { version = "0.4.42", default-features = false, features = ["std"] }
hex = "0.4.3"
md5 = "0.8.0"
sha2 = "0.10"
bitflags = "2.9.4"
Expand Down Expand Up @@ -292,6 +295,7 @@ ratatui = "0.30"
crossterm = "0.29"
self_cell = "1.2.2"
unicode-segmentation = "1.12.0"
urlencoding = "2.1"
Comment thread
Byron marked this conversation as resolved.

[workspace.lints.clippy]
all = "deny"
Expand Down
1 change: 0 additions & 1 deletion crates/but-action/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ gitbutler-operating-modes.workspace = true
gitbutler-branch-actions.workspace = true
gitbutler-branch.workspace = true
gitbutler-oplog.workspace = true
gitbutler-project.workspace = true
gitbutler-reference.workspace = true

serde.workspace = true
Expand Down
32 changes: 19 additions & 13 deletions crates/but-action/src/auto_commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use std::path::Path;

use bstr::BString;
use but_core::sync::RepoExclusiveGuard;
use but_ctx::ProjectHandleOrLegacyProjectId;
use but_hunk_assignment::{CommitMap, convert_assignments_to_diff_specs};
use but_workspace::commit_engine;
use gitbutler_project::ProjectId;
use serde::Serialize;

type AutoCommitEmitter = dyn Fn(&str, serde_json::Value) + Send + Sync + 'static;
Expand Down Expand Up @@ -48,7 +48,7 @@ enum AutoCommitEvent {
}

impl AutoCommitEvent {
fn event_name(&self, project_id: ProjectId) -> String {
fn event_name(&self, project_id: &ProjectHandleOrLegacyProjectId) -> String {
format!("project://{project_id}/auto-commit")
}

Expand All @@ -61,7 +61,7 @@ impl AutoCommitEvent {

#[allow(clippy::too_many_arguments)]
pub(crate) fn auto_commit(
project_id: ProjectId,
project_id: ProjectHandleOrLegacyProjectId,
repo: &gix::Repository,
project_data_dir: &Path,
context_lines: u32,
Expand All @@ -78,11 +78,11 @@ pub(crate) fn auto_commit(
let event = AutoCommitEvent::Started {
steps_length: absorption_plan.len(),
};
let event_name = event.event_name(project_id);
let event_name = event.event_name(&project_id);
emitter(&event_name, event.emit_payload());

match apply_commit_changes(
Some(project_id),
Some(project_id.clone()),
repo,
project_data_dir,
context_lines,
Expand All @@ -97,14 +97,14 @@ pub(crate) fn auto_commit(
let event = AutoCommitEvent::CommitError {
error_message: e.to_string(),
};
let event_name = event.event_name(project_id);
let event_name = event.event_name(&project_id);
let emitter = emitter.clone();
emitter(&event_name, event.emit_payload());
Err(e)
}
Ok(number_of_rejections) => {
let event = AutoCommitEvent::Completed;
let event_name = event.event_name(project_id);
let event_name = event.event_name(&project_id);
let emitter = emitter.clone();
emitter(&event_name, event.emit_payload());
Ok(number_of_rejections)
Expand Down Expand Up @@ -137,7 +137,7 @@ pub(crate) fn auto_commit_simple(

#[allow(clippy::too_many_arguments)]
fn apply_commit_changes(
project_id: Option<ProjectId>,
project_id: Option<ProjectHandleOrLegacyProjectId>,
repo: &gix::Repository,
project_data_dir: &Path,
context_lines: u32,
Expand All @@ -159,8 +159,13 @@ fn apply_commit_changes(
let diff_infos = absorption_files_to_diff_infos(&absorption.files);
let commit_id = commit_map.find_mapped_id(absorption.commit_id);
let stack_id = absorption.stack_id;
let commit_message =
commit_message_generation(project_id, commit_id, llm, emitter.as_ref(), &diff_infos)?;
let commit_message = commit_message_generation(
project_id.as_ref(),
commit_id,
llm,
emitter.as_ref(),
&diff_infos,
)?;
let outcome =
but_workspace::legacy::commit_engine::create_commit_and_update_refs_with_project(
repo,
Expand All @@ -177,7 +182,7 @@ fn apply_commit_changes(
)?;

if let Some(new_commit_id) = outcome.new_commit
&& let Some(project_id) = project_id
&& let Some(project_id) = project_id.as_ref()
&& let Some(emitter) = &emitter
{
let event = AutoCommitEvent::CommitSuccess {
Expand Down Expand Up @@ -231,7 +236,7 @@ fn absorption_files_to_diff_infos(
///
/// If no project and no emitter are provided, the function will not stream tokens.
fn commit_message_generation(
project_id: Option<ProjectId>,
project_id: Option<&ProjectHandleOrLegacyProjectId>,
parent_commit_id: gix::ObjectId,
llm: Option<&but_llm::LLMProvider>,
emitter: Option<&std::sync::Arc<AutoCommitEmitter>>,
Expand Down Expand Up @@ -276,12 +281,13 @@ fn commit_message_generation(
(Some(project_id), Some(emitter)) => {
llm.stream_response(system_message, vec![prompt.into()], &model, {
let emitter = std::sync::Arc::clone(emitter);
let project_id = project_id.clone();
move |token| {
let event = AutoCommitEvent::CommitGeneration {
parent_commit_id,
token: token.to_string(),
};
let event_name = event.event_name(project_id);
let event_name = event.event_name(&project_id);
emitter(&event_name, event.emit_payload());
}
})?
Expand Down
5 changes: 2 additions & 3 deletions crates/but-action/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ use std::{
};

use but_core::{TreeChange, sync::RepoExclusiveGuard};
use but_ctx::{Context, access::RepoExclusive};
use but_ctx::{Context, ProjectHandleOrLegacyProjectId, access::RepoExclusive};
use but_hunk_assignment::CommitAbsorption;
use but_oxidize::ObjectIdExt;
use but_workspace::legacy::ui::StackEntry;
use gitbutler_branch::BranchCreateRequest;
use gitbutler_project::ProjectId;
use gitbutler_stack::{Target, VirtualBranchesHandle};
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -43,7 +42,7 @@ pub fn branch_changes(

#[allow(clippy::too_many_arguments)]
pub fn auto_commit(
project_id: ProjectId,
project_id: ProjectHandleOrLegacyProjectId,
repo: &gix::Repository,
project_data_dir: &Path,
context_lines: u32,
Expand Down
22 changes: 12 additions & 10 deletions crates/but-api-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ use syn::{FnArg, ItemFn, Pat, parse_macro_input};
/// - This is also annotated with the `tauri` macro when the feature is enabled in the `but-api` crate.
/// - **Parameter Transformation**
/// - It supports `but_ctx::Context`, `&Context`, `&mut Context` or `ThreadSafeContext` as parameter,
/// which will be translated to `LegacyProjectId` with the `project_id` parameter name.
/// which will be translated to `project_id`:
/// - `but_ctx::ProjectHandleOrLegacyProjectId`
/// - `gix::ObjectId` will be translated into `json::HexHash`.
/// * `func_cmd` for calls from the `but-server`, taking `(params: Params) ` and returning `Result<serde_json::Value, json::Error>`.
/// - It performs all **Parameter Transformations** of `func_json`.
Expand Down Expand Up @@ -299,7 +300,7 @@ pub fn but_api(attr: TokenStream, item: TokenStream) -> TokenStream {
fn keep_json(_json: #json_ty) {}
};

/// Cmd function - this is legacy just while most of its functionality depend on `LegacyProjectId`.
/// Cmd function - this is legacy while most of its functionality depends on legacy project integration.
/// parameter struct input via json value, json output.
#[cfg(feature = "legacy")]
#vis #asyncness fn #fn_cmd_name(
Expand Down Expand Up @@ -459,7 +460,7 @@ fn build_wrapper_parameter_mapping(
if is_context_path(path) {
let binding_ty: syn::Type = (*reference.elem).clone();
return Ok(Some(WrapperParameterMapping {
transport_ty: syn::parse_quote! { but_ctx::LegacyProjectId },
transport_ty: syn::parse_quote! { but_ctx::ProjectHandleOrLegacyProjectId },
binding_ty,
json_ident: Some(syn::parse_str("project_id")?),
conversion_kind: WrapperConversionKind::TryFrom,
Expand Down Expand Up @@ -488,7 +489,7 @@ fn build_wrapper_parameter_mapping(
let path = &type_path.path;
if is_context_path(path) {
return Ok(Some(WrapperParameterMapping {
transport_ty: syn::parse_quote! { but_ctx::LegacyProjectId },
transport_ty: syn::parse_quote! { but_ctx::ProjectHandleOrLegacyProjectId },
binding_ty: ty.clone(),
json_ident: Some(syn::parse_str("project_id")?),
conversion_kind: WrapperConversionKind::TryFrom,
Expand Down Expand Up @@ -637,7 +638,7 @@ fn build_json_type_mapping<'a>(
(
pat_ident.ident.to_string(),
JsonParameterMapping {
json_ty: syn::parse_str("but_ctx::LegacyProjectId")?,
json_ty: syn::parse_str("but_ctx::ProjectHandleOrLegacyProjectId")?,
json_ident: Some(syn::parse_str("project_id")?),
},
)
Expand Down Expand Up @@ -871,17 +872,18 @@ fn build_napi_params<'a>(
let last_segment = mapping.json_ty.segments.last().unwrap();
let last_ident = &last_segment.ident;

if *last_ident == "LegacyProjectId" {
if *last_ident == "LegacyProjectId" || *last_ident == "ProjectHandleOrLegacyProjectId" {
// Context → String project_id, then convert to Context
params.push(quote! { #param_name: String });
// Determine the actual type we need to produce (stripping references)
let actual_ty = match &*pat_ty.ty {
syn::Type::Reference(r) => &*r.elem,
other => other,
};
let json_ty = &mapping.json_ty;
conversions.push(quote! {
let project_id: but_ctx::LegacyProjectId = #param_name.parse()
.map_err(|e: <but_ctx::LegacyProjectId as ::std::str::FromStr>::Err| {
let project_id: #json_ty = #param_name.parse()
.map_err(|e: <#json_ty as ::std::str::FromStr>::Err| {
napi::Error::new(napi::Status::InvalidArg, format!("{e:#}"))
})?;
let mut #ident = <#actual_ty>::try_from(project_id)
Expand Down Expand Up @@ -1213,11 +1215,11 @@ mod tests {

assert_eq!(
quote!(#(#struct_fields),*).to_string(),
quote!(pub project_id: but_ctx::LegacyProjectId).to_string()
quote!(pub project_id: but_ctx::ProjectHandleOrLegacyProjectId).to_string()
);
assert_eq!(
quote!(#(#json_inputs),*).to_string(),
quote!(project_id: but_ctx::LegacyProjectId).to_string()
quote!(project_id: but_ctx::ProjectHandleOrLegacyProjectId).to_string()
);
assert_eq!(
quote!(#(#call_args),*).to_string(),
Expand Down
4 changes: 2 additions & 2 deletions crates/but-api-macros/tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ doctest = false

[features]
default = []
legacy = []
legacy = ["but-ctx/legacy"]
tauri = ["dep:tauri", "legacy"]
napi = ["dep:napi", "dep:napi-derive", "dep:tokio", "legacy"]

[dependencies]
but-api-macros = { path = ".." }
but-error.workspace = true
but-ctx = { workspace = true , features = ["legacy"] }
but-ctx.workspace = true
anyhow.workspace = true
serde.workspace = true
serde_json.workspace = true
Expand Down
5 changes: 3 additions & 2 deletions crates/but-api-macros/tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
//! This crate exists to give trybuild UI tests a small, controlled environment that
//! resembles the parts of `but-api` the `#[but_api]` macro expands against.
//! In particular it provides lightweight stand-ins for modules and types the *macro*
//! references directly (for example `json`, `panic_capture`) so expansion can be
//! validated without depending on the full `but-api` crate graph.
//! references directly from the `but-api` crate, (for example `json`, `panic_capture`) so
//! expansion can be validated without running the macro from the `but-api` crate that
//! it was designed for.
//!
//! Keep this crate intentionally minimal. Extend it only when macro output starts
//! referencing new paths, traits, or conversion behavior that existing test shims
Expand Down
Loading
Loading