v1 git status

This commit is contained in:
Scott Chacon 2023-03-09 11:24:21 -08:00
parent 940a51a33e
commit 2d9e738038
4 changed files with 100 additions and 4 deletions

View File

@ -370,6 +370,24 @@ fn list_deltas(
Ok(deltas)
}
#[tauri::command]
fn git_status(
handle: tauri::AppHandle,
project_id: &str,
) -> Result<HashMap<String, String>, Error> {
let app_state = handle.state::<App>();
let repo = repositories::Repository::open(
&app_state.projects_storage,
&app_state.users_storage,
project_id,
)?;
let files = repo.status();
Ok(files)
}
fn main() {
let quit = tauri::CustomMenuItem::new("quit".to_string(), "Quit");
let hide = tauri::CustomMenuItem::new("toggle".to_string(), format!("Hide {}", app_title()));
@ -480,7 +498,8 @@ fn main() {
set_user,
delete_user,
get_user,
search
search,
git_status
]);
let tauri_context = generate_context!();

View File

@ -69,6 +69,49 @@ impl Repository {
session_id,
)
}
// get file status from git
pub fn status(&self) -> HashMap<String, String> {
println!("Git Status");
let mut options = git2::StatusOptions::new();
options.include_untracked(true);
options.include_ignored(false);
options.recurse_untracked_dirs(true);
// get the status of the repository
let statuses = self
.git_repository
.statuses(Some(&mut options))
.with_context(|| "failed to get repository status");
let mut files = HashMap::new();
match statuses {
Ok(statuses) => {
// iterate over the statuses
for entry in statuses.iter() {
// get the path of the entry
let path = entry.path().unwrap();
// get the status as a string
let istatus = match entry.status() {
s if s.contains(git2::Status::WT_NEW) => "added",
s if s.contains(git2::Status::WT_MODIFIED) => "modified",
s if s.contains(git2::Status::WT_DELETED) => "deleted",
s if s.contains(git2::Status::WT_RENAMED) => "renamed",
s if s.contains(git2::Status::WT_TYPECHANGE) => "typechange",
_ => continue,
};
files.insert(path.to_string(), istatus.to_string());
}
}
Err(_) => {
println!("Error getting status");
}
}
return files;
}
}
fn init(

View File

@ -6,11 +6,16 @@ import type { UISession } from '$lib/uisessions';
import { asyncDerived } from '@square/svelte-store';
import type { Delta } from '$lib/deltas';
import { startOfDay } from 'date-fns';
import { invoke } from '@tauri-apps/api';
export const prerender = false;
export const load: LayoutLoad = async ({ parent, params }) => {
const { projects } = await parent();
const filesStatus = building
? readable<Record<string, string>>({})
: await invoke<Record<string, string>>('git_status', { projectId: params.projectId });
const sessions = building
? readable<Session[]>([])
: await (await import('$lib/sessions')).default({ projectId: params.projectId });
@ -66,6 +71,7 @@ export const load: LayoutLoad = async ({ parent, params }) => {
});
});
return dateSessions;
});
}
@ -74,6 +80,7 @@ export const load: LayoutLoad = async ({ parent, params }) => {
project: projects.get(params.projectId),
projectId: params.projectId,
sessions: orderedSessions,
dateSessions: dateSessions
dateSessions: dateSessions,
filesStatus: filesStatus
};
};

View File

@ -4,6 +4,20 @@
export let data: LayoutData;
$: project = data.project;
$: dateSessions = data.dateSessions;
$: filesStatus = data.filesStatus;
function shortPath(path, max = 3) {
if (path.length < 30) {
return path;
}
const pathParts = path.split('/');
const file = pathParts.pop();
if (pathParts.length > 0) {
const pp = pathParts.map((p) => p.slice(0, max)).join('/');
return `${pp}/${file}`;
}
return file;
}
// convert a list of timestamps to a sparkline
function timestampsToSpark(tsArray) {
@ -138,8 +152,21 @@
</div>
<div class="col-span-1 space-y-6">
<div>
<h2 class="text-lg font-bold text-zinc-500">Work in Progress</h2>
<div class="text-zinc-400 mt-4 mb-1 bg-zinc-700 rounded p-4">No uncommitted work</div>
<h2 class="text-lg font-bold text-zinc-500 mb-2">Work in Progress</h2>
{#if Object.entries(filesStatus).length == 0}
<div class="bg-green-900 text-green-500 p-4 rounded">Everything is committed</div>
{:else}
<div class="bg-blue-900 p-4 rounded">
<ul class="">
{#each Object.entries(filesStatus) as activity}
<li>
{activity[1].slice(0, 1)}
{shortPath(activity[0])}
</li>
{/each}
</ul>
</div>
{/if}
</div>
<div>