From 1210d352888e1c38d87f323736a52090d8f86429 Mon Sep 17 00:00:00 2001 From: Scott Chacon Date: Sat, 18 Mar 2023 07:52:21 +0100 Subject: [PATCH] Add working directory diff support and auto generate commit messages This update enables the generation of a working directory diff and returns a Git commit message based on the diff changes. It includes changes to the API, Tauri, and frontend code. Notable modifications include: - Added `git_wd_diff` function to Tauri `src/main.rs` - Modified `Repository` struct, added `wd_diff` method to `src/repositories/repository.rs` - New `commit` function added to `src/lib/api.ts` - Added `fetchCommitMessage` function in `src/routes/projects/[projectId]/+page.svelte` - Minor UI adjustments in `src/routes/projects/[projectId]/player/+page.svelte` Overall, this commit improves user experience by automatically generating commit messages based on the changes made in the working directory. --- src-tauri/src/main.rs | 10 +++++- src-tauri/src/repositories/repository.rs | 22 +++++++++++- src/lib/api.ts | 11 ++++++ src/routes/projects/[projectId]/+layout.ts | 12 +++++++ src/routes/projects/[projectId]/+page.svelte | 36 ++++++++++++++++--- src/routes/projects/[projectId]/+page.ts | 20 +++++++++++ .../projects/[projectId]/player/+page.svelte | 27 +++++++------- 7 files changed, 117 insertions(+), 21 deletions(-) create mode 100644 src/routes/projects/[projectId]/+page.ts diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index f2a5d5bed..6b0727a5a 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -369,6 +369,13 @@ async fn git_status( Ok(files) } +#[tauri::command] +async fn git_wd_diff(handle: tauri::AppHandle, project_id: &str) -> Result { + let repo = repo_for_project(handle, project_id)?; + let diff = repo.wd_diff().with_context(|| "Failed to get git diff")?; + Ok(diff) +} + #[tauri::command] async fn git_file_paths(handle: tauri::AppHandle, project_id: &str) -> Result, Error> { let repo = repo_for_project(handle, project_id)?; @@ -579,7 +586,8 @@ fn main() { git_branches, git_branch, git_switch_branch, - git_commit + git_commit, + git_wd_diff ]); let tauri_context = generate_context!(); diff --git a/src-tauri/src/repositories/repository.rs b/src-tauri/src/repositories/repository.rs index 343b0ac67..607930f25 100644 --- a/src-tauri/src/repositories/repository.rs +++ b/src-tauri/src/repositories/repository.rs @@ -1,7 +1,7 @@ use crate::{deltas, fs, projects, sessions, users}; use anyhow::{Context, Result}; use git2::{BranchType, Cred, Signature}; -use std::{collections::HashMap, env, path::Path}; +use std::{collections::HashMap, env, path::Path, str::from_utf8}; use tauri::regex::Regex; use walkdir::WalkDir; @@ -172,6 +172,26 @@ impl Repository { Ok(branch.to_string()) } + pub fn wd_diff(&self) -> Result { + println!("diffing"); + let repo = &self.git_repository; + let head = repo.head()?; + let tree = head.peel_to_tree()?; + let diff = repo.diff_tree_to_workdir_with_index(Some(&tree), None)?; + let mut buf = String::new(); + diff.print(git2::DiffFormat::Patch, |delta, hunk, line| { + buf.push_str(&format!( + "{:?} {}", + delta.status(), + delta.new_file().path().unwrap().to_str().unwrap() + )); + buf.push_str(from_utf8(line.content()).unwrap()); + buf.push_str("\n"); + true + })?; + Ok(buf) + } + pub fn switch_branch(&self, branch_name: &str) -> Result { self.flush_session(&None) .with_context(|| "failed to flush session before switching branch")?; diff --git a/src/lib/api.ts b/src/lib/api.ts index 7e4477472..b47d4466e 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -128,6 +128,17 @@ export default ( }).then(parseResponseJSON); } }, + summarize: { + commit: (token: string, params: { diff: string; uid?: string }): Promise => + fetch(getUrl('summarize/commit.json'), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Auth-Token': token + }, + body: JSON.stringify(params) + }).then(parseResponseJSON) + }, projects: { create: (token: string, params: { name: string; uid?: string }): Promise => fetch(getUrl('projects.json'), { diff --git a/src/routes/projects/[projectId]/+layout.ts b/src/routes/projects/[projectId]/+layout.ts index bbf68cbf0..4c07578c3 100644 --- a/src/routes/projects/[projectId]/+layout.ts +++ b/src/routes/projects/[projectId]/+layout.ts @@ -37,8 +37,20 @@ export const load: LayoutLoad = async ({ parent, params }) => { }); return activitySorted.slice(0, 20); }); + const user = building + ? { + ...readable(undefined), + set: () => { + throw new Error('not implemented'); + }, + delete: () => { + throw new Error('not implemented'); + } + } + : await (await import('$lib/users')).default(); return { + user: user, project: projects.get(params.projectId), projectId: params.projectId, orderedSessionsFromLastFourDays: orderedSessionsFromLastFourDays, diff --git a/src/routes/projects/[projectId]/+page.svelte b/src/routes/projects/[projectId]/+page.svelte index ee0af5f19..682a07480 100644 --- a/src/routes/projects/[projectId]/+page.svelte +++ b/src/routes/projects/[projectId]/+page.svelte @@ -13,14 +13,18 @@ import { navigating } from '$app/stores'; import toast from 'svelte-french-toast'; import { goto } from '$app/navigation'; + import Api from '$lib/api'; + const api = Api({ fetch }); const getBranch = (params: { projectId: string }) => invoke('git_branch', params); + const getDiff = (params: { projectId: string }) => invoke('git_wd_diff', params); export let data: LayoutData; $: project = data.project; $: filesStatus = data.filesStatus; - $: recentActivity = data.recentActivity as Readable; + $: recentActivity = data.recentActivity; $: orderedSessionsFromLastFourDays = data.orderedSessionsFromLastFourDays; + $: user = data.user; const commit = (params: { projectId: string; @@ -31,6 +35,7 @@ let latestDeltasByDateByFile: Record[]> = {}; let commitMessage: string; + let placeholderMessage = 'Description of changes'; let initiatedCommit = false; let filesSelectedForCommit: string[] = []; @@ -183,6 +188,27 @@ return sessionsByFile; } + function fetchCommitMessage() { + if ($project && $user) { + placeholderMessage = 'Summarizing changes...'; + console.log('FETCHING DIFF'); + getDiff({ + projectId: $project.id + }).then((result) => { + console.log('DIFF', result); + api.summarize + .commit($user?.access_token, { + diff: result, + uid: $project.id + }) + .then((result) => { + console.log(result); + commitMessage = result.message; + }); + }); + } + } + // order the sessions and summarize the changes by file function orderedSessions(dateSessions: Record[]>) { return Object.entries(dateSessions) @@ -288,7 +314,7 @@
{toHumanBranchName(gitBranch)}
-
+
-
6 branches
+ {/if} {#if $filesStatus.length == 0} @@ -341,7 +367,7 @@