mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-24 18:12:48 +03:00
Merged origin/master into keyboard-shortcuts
This commit is contained in:
commit
5352eb1717
@ -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}
|
||||
|
@ -0,0 +1,9 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
raw: string;
|
||||
}
|
||||
|
||||
const { raw }: Props = $props();
|
||||
</script>
|
||||
|
||||
{@html raw}
|
@ -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>
|
||||
|
@ -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 = {
|
||||
|
@ -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")?;
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user