Merged origin/master into keyboard-shortcuts

This commit is contained in:
estib 2024-09-12 09:13:39 +02:00
commit 5352eb1717
7 changed files with 74 additions and 25 deletions

View File

@ -1,7 +1,9 @@
<script lang="ts">
/* eslint svelte/valid-compile: "off" */
/* - Required because spreading in prop destructuring still throws eslint errors */
import { renderers } from '$lib/utils/markdownRenderers';
import type { Tokens, Token } from 'marked';
import type { Component } from 'svelte';
type Props =
| { type: 'init'; tokens: Token[] }
@ -16,34 +18,33 @@
| Tokens.ListItem
| Tokens.List;
let { type, ...rest }: Props = $props();
const { type, ...rest }: Props = $props();
// @ts-expect-error indexing on string union is having trouble
const CurrentComponent = renderers[type as Props['type']];
const CurrentComponent = renderers[type] as Component<Props>;
</script>
{#if type && CurrentComponent}
{#if (!type || type === 'init') && 'tokens' in rest && rest.tokens}
{#each rest.tokens as token}
<svelte:self {...token} />
{/each}
{:else if renderers[type]}
{#if type === 'list'}
{@const listItems = (rest as Extract<Props, { type: typeof type }>).items}
{@const listItems = (rest as Extract<Props, { type: 'list' }>).items}
<CurrentComponent {...rest}>
{#each listItems as item}
{@const ChildComponent = renderers[item.type]}
<ChildComponent {...item}>
<svelte:self tokens={item.tokens} {renderers} />
<svelte:self tokens={item.tokens} />
</ChildComponent>
{/each}
</CurrentComponent>
{:else}
<CurrentComponent {...rest}>
{#if 'tokens' in rest}
<CurrentComponent this={renderers[type]} {...rest}>
{#if 'tokens' in rest && rest.tokens}
<svelte:self tokens={rest.tokens} />
{:else if 'raw' in rest}
{rest.raw}
{/if}
</CurrentComponent>
{/if}
{:else if 'tokens' in rest && rest.tokens}
{#each rest.tokens as token}
<svelte:self {...token} />
{/each}
{:else if 'raw' in rest}
{@html rest.raw?.replaceAll('\n', '') ?? ''}
{/if}

View File

@ -0,0 +1,9 @@
<script lang="ts">
interface Props {
raw: string;
}
const { raw }: Props = $props();
</script>
{@html raw}

View File

@ -1,11 +1,13 @@
<script lang="ts">
import { type Snippet } from 'svelte';
interface Props {
text: string;
children: Snippet;
}
const { text }: Props = $props();
const { children }: Props = $props();
</script>
<span>
{text}
{@render children()}
</span>

View File

@ -2,6 +2,7 @@ import Blockquote from '$lib/components/markdownRenderers/Blockquote.svelte';
import Code from '$lib/components/markdownRenderers/Code.svelte';
import Codespan from '$lib/components/markdownRenderers/Codespan.svelte';
import Heading from '$lib/components/markdownRenderers/Heading.svelte';
import Html from '$lib/components/markdownRenderers/Html.svelte';
import Image from '$lib/components/markdownRenderers/Image.svelte';
import List from '$lib/components/markdownRenderers/List.svelte';
import ListItem from '$lib/components/markdownRenderers/ListItem.svelte';
@ -16,10 +17,12 @@ export const renderers = {
code: Code,
codespan: Codespan,
text: Text,
html: Html,
list: List,
list_item: ListItem,
heading: Heading,
paragraph: Paragraph
paragraph: Paragraph,
init: null
};
export const options = {

View File

@ -159,7 +159,7 @@ pub fn unapply_ownership(
},
)?;
let final_tree_oid = gitbutler_diff::write::hunks_onto_tree(ctx, &final_tree, diff)?;
let final_tree_oid = gitbutler_diff::write::hunks_onto_tree(ctx, &final_tree, diff, true)?;
let final_tree = repo
.find_tree(final_tree_oid)
.context("failed to find tree")?;

View File

@ -78,7 +78,7 @@ impl GitHunk {
new_lines: 0,
diff_lines: Default::default(),
binary: false,
change_type: ChangeType::Modified,
change_type: ChangeType::Added,
}
}
}
@ -387,6 +387,11 @@ fn reverse_patch(patch: &BStr) -> Option<BString> {
// returns `None` if the reversal failed
pub fn reverse_hunk(hunk: &GitHunk) -> Option<GitHunk> {
let new_change_type = match hunk.change_type {
ChangeType::Added => ChangeType::Deleted,
ChangeType::Deleted => ChangeType::Added,
ChangeType::Modified => ChangeType::Modified,
};
if hunk.binary {
None
} else {
@ -397,7 +402,7 @@ pub fn reverse_hunk(hunk: &GitHunk) -> Option<GitHunk> {
new_lines: hunk.old_lines,
diff_lines: diff.into(),
binary: hunk.binary,
change_type: hunk.change_type,
change_type: new_change_type,
})
}
}

View File

@ -1,6 +1,6 @@
#[cfg(target_family = "unix")]
use std::os::unix::prelude::PermissionsExt;
use std::{borrow::Borrow, path::PathBuf};
use std::{borrow::Borrow, fs, path::PathBuf};
use anyhow::{anyhow, Context, Result};
use bstr::{BString, ByteSlice, ByteVec};
@ -38,13 +38,14 @@ where
let head_commit = git_repository.find_commit(commit_oid)?;
let base_tree = head_commit.tree()?;
hunks_onto_tree(ctx, &base_tree, files)
hunks_onto_tree(ctx, &base_tree, files, false)
}
pub fn hunks_onto_tree<T>(
ctx: &CommandContext,
base_tree: &git2::Tree,
files: impl IntoIterator<Item = (impl Borrow<PathBuf>, impl Borrow<Vec<T>>)>,
allow_new_file: bool,
) -> Result<git2::Oid>
where
T: Into<GitHunk> + Clone,
@ -62,7 +63,21 @@ where
&& hunks[0].diff_lines.contains_str(b"Subproject commit");
// if file exists
if full_path.exists() {
let full_path_exists = full_path.exists();
let discard_hunk = (hunks.len() == 1).then(|| &hunks[0]);
if full_path_exists || allow_new_file {
if discard_hunk.map_or(false, |hunk| hunk.change_type == crate::ChangeType::Deleted) {
// File was created but now that hunk is being discarded with an inversed hunk
builder.remove(rel_path);
fs::remove_file(full_path.clone()).or_else(|err| {
if err.kind() == std::io::ErrorKind::NotFound {
Ok(())
} else {
Err(err)
}
})?;
continue;
}
// if file is executable, use 755, otherwise 644
let mut filemode = git2::FileMode::Blob;
// check if full_path file is executable
@ -115,7 +130,7 @@ where
)?;
builder.upsert(rel_path, blob_oid, filemode);
} else if let Ok(tree_entry) = base_tree.get_path(rel_path) {
if hunks.len() == 1 && hunks[0].binary {
if discard_hunk.map_or(false, |hunk| hunk.binary) {
let new_blob_oid = &hunks[0].diff_lines;
// convert string to Oid
let new_blob_oid = new_blob_oid
@ -178,6 +193,20 @@ where
let new_blob_oid = git_repository.blob(blob_contents.as_bytes())?;
// upsert into the builder
builder.upsert(rel_path, new_blob_oid, filemode);
} else if !full_path_exists
&& discard_hunk.map_or(false, |hunk| hunk.change_type == crate::ChangeType::Added)
{
// File was deleted but now that hunk is being discarded with an inversed hunk
let mut all_diffs = BString::default();
for hunk in hunks {
all_diffs.push_str(&hunk.diff_lines);
}
let patch = Patch::from_bytes(&all_diffs)?;
let blob_contents =
apply([], &patch).context(format!("failed to apply {}", all_diffs))?;
let new_blob_oid = git_repository.blob(&blob_contents)?;
builder.upsert(rel_path, new_blob_oid, filemode);
} else {
// create a git blob from a file on disk
let blob_oid = git_repository