Files
GitLite/src/lib/types.ts
T
Christoph 6a40159f9f feat(integrations): add merge-method selection and provider-specific payloads
Introduce dedicated merge handling for integration review merges:

- Add src-tauri/src/integrations/merge.rs: implements merge_options (read provider repo settings), merge_payload (build provider-specific merge body) and a Tauri command get_integration_review_merge_options. Includes unit tests for behavior.
- Wire merge module into integrations.rs and pass an optional merge_method into provider-specific review action functions (GitHub, GitLab, Gitea, Azure DevOps). run_integration_review_action now accepts an optional merge_method, validates it early, and includes provider-specific merge payloads when performing a merge.
- Export the new command in src-tauri/src/main.rs so the frontend can request merge options.

Frontend changes to support selecting a merge method before merging:

- ConfirmDialog.svelte: add SelectMenu support and a select field to confirm requests.
- ReviewCenter.svelte: fetch integration merge options, show a merge-method selector in the merge confirmation, and pass the chosen method to the review action.
- Update types and git bindings to surface IntegrationMergeOptions / IntegrationMergeMethod and the getIntegrationReviewMergeOptions call (git.ts / types.ts changes staged).

Effect: users can pick a merge method appropriate to the provider/project; the integration layer generates the correct API payload per provider. Tests added for merge logic.
2026-09-18 15:12:25 +02:00

512 lines
11 KiB
TypeScript

export type FileStatusKind =
| "modified"
| "added"
| "deleted"
| "renamed"
| "untracked"
| "conflicted"
| "unknown";
export type GitIgnoreKind = "file" | "extension" | "folder";
export type CommitAiProvider = "openai" | "anthropic" | "custom";
export type AppTheme = "system" | "light" | "dark";
export type AppAppearance = "modern" | "classic" | "custom";
export type AppLanguage = "en" | "de";
export type GitIntegrationProvider = "github" | "gitlab" | "gitlab-self-hosted" | "azure-devops" | "gitea";
export interface GitIntegrationConfig {
provider: GitIntegrationProvider;
enabled: boolean;
baseUrl: string;
username: string;
tokenStored: boolean;
}
export interface GitIntegrationSettings {
providers: Record<GitIntegrationProvider, GitIntegrationConfig>;
azureDevOpsOrganizations: AzureDevOpsOrganization[];
}
export interface AzureDevOpsOrganization {
id: string;
name: string;
enabled: boolean;
baseUrl: string;
username: string;
tokenStored: boolean;
}
export interface GitIntegrationSecretUpdate {
provider: GitIntegrationProvider;
accountId?: string;
token?: string;
removeToken?: boolean;
}
export interface GitIntegrationSource {
id: string;
provider: GitIntegrationProvider;
accountId?: string;
label: string;
baseUrl: string;
}
export interface GitIntegrationRepository {
id: string;
name: string;
fullName: string;
description: string;
cloneUrl: string;
sshUrl: string;
webUrl: string;
updatedAt: string;
private: boolean;
}
export type IntegrationReviewState = "open" | "draft" | "merged" | "closed";
export type IntegrationMergeMethod = "default" | "merge" | "squash" | "rebase" | "rebase-merge" | "fast-forward-only";
export interface IntegrationMergeOptions { methods: IntegrationMergeMethod[]; defaultMethod: IntegrationMergeMethod; }
export type IntegrationReviewAction = "merge" | "approve" | "close" | "reopen";
export interface IntegrationReviewComment {
id: string;
author: string;
body: string;
createdAt: string;
}
export interface IntegrationReviewRequest {
id: string;
number: number;
provider: GitIntegrationProvider;
repositoryId: string;
repositoryName: string;
title: string;
description: string;
author: string;
state: IntegrationReviewState;
sourceBranch: string;
targetBranch: string;
webUrl: string;
createdAt: string;
updatedAt: string;
collaborators: string[];
additions: number | null;
deletions: number | null;
changedFiles: number | null;
mergeStatus: "" | "mergeable" | "conflicts" | "checking" | "blocked";
comments: IntegrationReviewComment[];
}
export interface CustomThemeColors {
background: string;
surface: string;
accent: string;
text: string;
}
export type AiReviewRisk = "low" | "medium" | "high";
export type AiReviewSeverity = "critical" | "warning" | "info";
export interface AiReviewFinding {
severity: AiReviewSeverity;
title: string;
description: string;
file: string | null;
line: number | null;
suggestion: string;
}
export interface AiReviewResult {
summary: string;
risk: AiReviewRisk;
findings: AiReviewFinding[];
}
export interface AiCommitGroup {
message: string;
reason: string;
files: string[];
}
export interface AiCommitPlan {
summary: string;
groups: AiCommitGroup[];
}
export interface AiSettings {
provider: CommitAiProvider;
openaiModel: string;
anthropicModel: string;
customBaseUrl: string;
customModel: string;
}
export interface AnalyticsSettings {
enabled: boolean;
noticeSeen: boolean;
}
export interface ExternalToolCommand {
program: string;
args: string[];
}
export interface ExternalToolSetting extends ExternalToolCommand {
preset: string;
}
export type ExternalToolKind = "editor" | "diff" | "merge" | "terminal" | "fileManager";
export type ToolOpenMode = "gitty" | "external";
export type ExternalDiffScope = "head" | "staged" | "unstaged";
export interface ExternalToolsSettings {
editor: ExternalToolSetting;
diff: ExternalToolSetting;
merge: ExternalToolSetting;
terminal: ExternalToolSetting;
fileManager: ExternalToolSetting;
diffOpenMode: ToolOpenMode;
mergeOpenMode: ToolOpenMode;
}
export interface DetectedExternalTool {
id: string;
label: string;
program: string;
kinds: ExternalToolKind[];
}
export interface GitStatus {
repo_path: string;
current_branch: string | null;
upstream: string | null;
ahead: number;
behind: number;
files: GitFileStatus[];
clean: boolean;
rebase_in_progress: boolean;
cherry_pick_in_progress: boolean;
merge_in_progress: boolean;
}
export interface GitRemote { name: string; fetch_url: string; push_url: string; }
export type PullStrategy = "merge" | "rebase" | "ff-only";
export type MergeStrategy = "default" | "squash" | "ff-only" | "no-ff";
export interface CloneOptions {
branch: string | null;
blobless: boolean;
customFlags: string;
shallowDepth: number | null;
shallowSince: string | null;
sparse: boolean;
sparsePaths: string[];
}
export interface GitFileStatus {
path: string;
old_path: string | null;
staged: FileStatusKind | null;
unstaged: FileStatusKind | null;
}
export type PatchApplyAction = "stage" | "unstage" | "discard-unstaged" | "discard-staged";
export interface GitBranch {
name: string;
current: boolean;
remote: boolean;
upstream: string | null;
}
export interface GitWorktree {
path: string;
head: string | null;
short_head: string | null;
branch: string | null;
bare: boolean;
detached: boolean;
locked: boolean;
lock_reason: string | null;
prunable: boolean;
prune_reason: string | null;
missing: boolean;
is_main: boolean;
is_current: boolean;
clean: boolean;
changed_files: number;
}
export interface GitTag {
name: string;
hash: string;
short_hash: string;
message: string | null;
date: string;
annotated: boolean;
}
export interface GitStash {
selector: string;
index: number;
hash: string;
branch: string | null;
message: string;
date: string;
}
export interface GitCommit {
hash: string;
short_hash: string;
summary: string;
author_name: string;
author_email: string;
date: string;
refs: string[];
parents: string[];
files: GitCommitFile[];
has_note: boolean;
}
export interface BisectCommit {
hash: string;
short_hash: string;
summary: string;
author_name: string;
date: string;
}
export interface BisectState {
active: boolean;
finished: boolean;
current: BisectCommit | null;
culprit: BisectCommit | null;
remaining_revisions: number | null;
remaining_steps: number | null;
message: string;
}
export interface GitCommitFile {
path: string;
old_path: string | null;
status: FileStatusKind;
}
export interface GitRepositoryFile {
path: string;
tracked: boolean;
status: FileStatusKind | null;
}
export interface GitLfsPattern {
pattern: string;
source: string;
lockable: boolean;
tracked: boolean;
}
export interface GitLfsFile {
name: string;
size: number;
checkout: boolean;
downloaded: boolean;
oid_type: string;
oid: string;
version: string;
}
export interface GitLfsStatus {
available: boolean;
bundled: boolean;
version: string | null;
filters_configured: boolean;
hook_installed: boolean;
repository_uses_lfs: boolean;
patterns: GitLfsPattern[];
files: GitLfsFile[];
}
export interface RepositoryBundle {
status: GitStatus;
branches: GitBranch[];
tags: GitTag[];
stashes: GitStash[];
commits: GitCommit[];
files: GitRepositoryFile[];
warning: string | null;
}
export interface GitDiffFile {
path: string;
old_path: string | null;
status: FileStatusKind;
additions: number;
deletions: number;
}
export interface GitCommitComparison {
from_hash: string;
from_short: string;
to_hash: string;
to_short: string;
files: GitDiffFile[];
patch: string;
}
export interface GitSearchHit {
commit_hash: string;
short_hash: string;
summary: string;
author_name: string;
author_email: string;
date: string;
file: string;
old_file: string | null;
line_number: number | null;
line: string;
matches_added: number;
}
export type ExplorerNodeKind = "folder" | "file";
export interface ExplorerNode {
name: string;
path: string;
kind: ExplorerNodeKind;
status: FileStatusKind | null;
tracked: boolean;
depth: number;
children: ExplorerNode[];
}
export type ConflictChoice = "ours" | "theirs" | "both-ot" | "both-to";
export type ConflictPart =
| { kind: "text"; lines: string[] }
| { kind: "conflict"; index: number; oursLines: string[]; theirsLines: string[] };
export type PreparedResolution =
| { kind: "content"; content: string }
| { kind: "side"; side: "ours" | "theirs" };
export interface ConflictFile {
path: string;
content: string;
ours: string | null;
theirs: string | null;
base: string | null;
binary: boolean;
ours_size: number | null;
theirs_size: number | null;
}
export interface GitBlameLine {
line_number: number;
content: string;
commit_hash: string;
short_hash: string;
author_name: string;
author_email: string;
author_time: number;
summary: string;
is_uncommitted: boolean;
}
export interface GitBlameResult {
path: string;
lines: GitBlameLine[];
}
export type RebaseAction = "pick" | "reword" | "squash" | "fixup" | "drop";
export interface RebaseCommit {
hash: string;
short_hash: string;
summary: string;
author_name: string;
date: string;
}
export interface RebasePlanItem {
hash: string;
action: RebaseAction;
message: string | null;
}
export interface ReflogEntry {
hash: string;
short_hash: string;
selector: string;
action: string;
author_name: string;
date: string;
}
export interface StoredCredential {
username: string;
password: string;
mode?: "credentials" | "token";
}
export interface IntegrationIssue {
id: string;
number: number;
title: string;
description: string;
descriptionHtml: boolean;
repositoryName: string;
author: string;
state: string;
labels: string[];
assignees: string[];
webUrl: string;
updatedAt: string;
}
export interface IntegrationIssuePage {
issues: IntegrationIssue[];
nextCursor: string | null;
}
export interface IntegrationBoardCard {
id: string;
title: string;
number: number;
webUrl: string;
repository: string;
description: string;
labels: string[];
assignees: string[];
lane: string;
}
export interface IntegrationBoard {
title: string;
webUrl: string;
notice: string;
columns: Array<{ id: string; title: string; limit: number; moveTarget?: Record<string, unknown> | null; cards: IntegrationBoardCard[] }>;
}
export interface IntegrationBoardReference { title: string; webUrl: string; scope: string }
export interface IssueComment { id: string; author: string; body: string; createdAt: string; bodyHtml: boolean }
export interface GitSubmodule {
name: string;
path: string;
owner_path: string;
relative_path: string;
full_path: string;
url: string;
branch: string | null;
recorded_commit: string;
local_commit: string | null;
dirty: boolean;
conflicted: boolean;
depth: number;
}