mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-09-11 12:25:42 +03:00
fix: commitList path
This commit is contained in:
parent
89a12044c3
commit
7e75780b1a
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import CommitCard from './CommitCard.svelte';
|
||||
import { Project } from '$lib/backend/projects';
|
||||
import { LineManagerFactory } from '$lib/commitLines/lineManager';
|
||||
import { transformAnyCommit } from '$lib/commitLines/transformers';
|
||||
import InsertEmptyCommitAction from '$lib/components/InsertEmptyCommitAction.svelte';
|
||||
import {
|
||||
ReorderDropzoneManagerFactory,
|
||||
@ -19,8 +19,8 @@
|
||||
getRemoteCommits
|
||||
} from '$lib/vbranches/contexts';
|
||||
import { BaseBranch, Branch } from '$lib/vbranches/types';
|
||||
import LineGroup from '@gitbutler/ui/CommitLines/LineGroup.svelte';
|
||||
import { transformAnyCommit } from '@gitbutler/ui/CommitLines/transformers';
|
||||
import LineGroup from '@gitbutler/ui/CommitLines/LineGroup.svelte';
|
||||
import { LineManagerFactory } from '@gitbutler/ui/CommitLines/lineManager';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export let isUnapplied: boolean;
|
||||
|
@ -1,489 +0,0 @@
|
||||
import type { CommitData, LineGroup, Line, Color } from '$lib/commitLines/types';
|
||||
|
||||
interface Commits {
|
||||
remoteCommits: CommitData[];
|
||||
localCommits: CommitData[];
|
||||
localAndRemoteCommits: CommitData[];
|
||||
integratedCommits: CommitData[];
|
||||
}
|
||||
|
||||
function generateSameForkpoint({
|
||||
remoteCommits,
|
||||
localCommits,
|
||||
localAndRemoteCommits,
|
||||
integratedCommits
|
||||
}: Commits) {
|
||||
const LEFT_COLUMN_INDEX = 0;
|
||||
const RIGHT_COLUMN_INDEX = 1;
|
||||
|
||||
const remoteBranchGroups = mapToCommitLineGroupPair(remoteCommits, 3);
|
||||
const localBranchGroups = mapToCommitLineGroupPair(localCommits, 3);
|
||||
const localAndRemoteBranchGroups = mapToCommitLineGroupPair(localAndRemoteCommits, 3);
|
||||
const integratedBranchGroups = mapToCommitLineGroupPair(integratedCommits, 3);
|
||||
|
||||
const base = blankLineGroup(3);
|
||||
|
||||
remoteBranchGroups.forEach(({ commit, lineGroup }, index) => {
|
||||
// We don't color in top half of the first remote commit
|
||||
if (index !== 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'remote';
|
||||
}
|
||||
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'remote';
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].commitNode = { type: 'large', commit };
|
||||
|
||||
// If there are local commits we want to fill in a local dashed line
|
||||
if (localBranchGroups.length > 0) {
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].top.color = 'local';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.color = 'local';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].top.style = 'dashed';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.style = 'dashed';
|
||||
}
|
||||
});
|
||||
|
||||
let localCommitWithChangeIdFound = false;
|
||||
localBranchGroups.forEach(({ commit, lineGroup }, index) => {
|
||||
// The first local commit should have the top be dashed
|
||||
if (index === 0) {
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].top.style = 'dashed';
|
||||
}
|
||||
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].top.color = 'local';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.color = 'local';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].commitNode = { type: 'large', commit };
|
||||
|
||||
// We need to use either remote or localAndRemote depending on what is above
|
||||
let leftStyle: Color | undefined;
|
||||
|
||||
if (remoteBranchGroups.length > 0) {
|
||||
leftStyle = 'remote';
|
||||
} else {
|
||||
leftStyle = 'localAndRemote';
|
||||
}
|
||||
|
||||
if (localCommitWithChangeIdFound) {
|
||||
// If a commit with a change ID has been found above this commit, use the leftStyle
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = leftStyle;
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = leftStyle;
|
||||
|
||||
if (commit.relatedRemoteCommit) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].commitNode = {
|
||||
type: 'small',
|
||||
commit: commit.relatedRemoteCommit
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (commit.relatedRemoteCommit) {
|
||||
// For the first commit with a change ID found, only set the top if there are any remote commits
|
||||
if (remoteBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = leftStyle;
|
||||
}
|
||||
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].commitNode = {
|
||||
type: 'small',
|
||||
commit: commit.relatedRemoteCommit
|
||||
};
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = leftStyle;
|
||||
|
||||
localCommitWithChangeIdFound = true;
|
||||
} else {
|
||||
// If there are any remote commits, continue the line
|
||||
if (remoteBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'remote';
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'remote';
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
localAndRemoteBranchGroups.forEach(({ commit, lineGroup }, index) => {
|
||||
if (index === 0) {
|
||||
// Copy the top color from any commits above for the first commit
|
||||
if (localBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color =
|
||||
localBranchGroups.at(-1)!.lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color;
|
||||
} else if (remoteBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color =
|
||||
remoteBranchGroups.at(-1)!.lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color;
|
||||
}
|
||||
} else {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'localAndRemote';
|
||||
}
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'localAndRemote';
|
||||
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].commitNode = { type: 'large', commit };
|
||||
});
|
||||
|
||||
integratedBranchGroups.forEach(({ commit, lineGroup }, index) => {
|
||||
if (index === 0) {
|
||||
// Copy the top color from any commits above for the first commit
|
||||
if (localAndRemoteBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color =
|
||||
localAndRemoteBranchGroups.at(-1)!.lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color;
|
||||
} else if (localBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color =
|
||||
localBranchGroups.at(-1)!.lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color;
|
||||
} else if (remoteBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color =
|
||||
remoteBranchGroups.at(-1)!.lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color;
|
||||
}
|
||||
} else {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'integrated';
|
||||
}
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'integrated';
|
||||
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].commitNode = { type: 'large', commit };
|
||||
});
|
||||
|
||||
// Set forkpoints
|
||||
if (localBranchGroups.length > 0) {
|
||||
if (integratedBranchGroups.length === 0 && localAndRemoteBranchGroups.length === 0) {
|
||||
localBranchGroups.at(-1)!.lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.type = 'fork';
|
||||
} else if (localAndRemoteBranchGroups.length > 0) {
|
||||
localAndRemoteBranchGroups[0].lineGroup.lines[RIGHT_COLUMN_INDEX].top.type = 'fork';
|
||||
localAndRemoteBranchGroups[0].lineGroup.lines[RIGHT_COLUMN_INDEX].top.color = 'local';
|
||||
} else if (integratedBranchGroups.length > 0) {
|
||||
integratedBranchGroups[0].lineGroup.lines[RIGHT_COLUMN_INDEX].top.type = 'fork';
|
||||
integratedBranchGroups[0].lineGroup.lines[RIGHT_COLUMN_INDEX].top.color = 'local';
|
||||
}
|
||||
}
|
||||
|
||||
// Remove padding column if unrequired
|
||||
if (localBranchGroups.length === 0) {
|
||||
remoteBranchGroups.forEach(({ lineGroup }) => lineGroup.lines.pop());
|
||||
localBranchGroups.forEach(({ lineGroup }) => lineGroup.lines.pop());
|
||||
localAndRemoteBranchGroups.forEach(({ lineGroup }) => lineGroup.lines.pop());
|
||||
integratedBranchGroups.forEach(({ lineGroup }) => lineGroup.lines.pop());
|
||||
|
||||
base.lines.pop();
|
||||
}
|
||||
|
||||
// Set base
|
||||
base.lines[LEFT_COLUMN_INDEX].baseNode = {};
|
||||
base.lines[LEFT_COLUMN_INDEX].top.style = 'dashed';
|
||||
if (integratedBranchGroups.length > 0) {
|
||||
base.lines[LEFT_COLUMN_INDEX].top.color = 'integrated';
|
||||
} else if (localAndRemoteBranchGroups.length > 0) {
|
||||
base.lines[LEFT_COLUMN_INDEX].top.color = 'localAndRemote';
|
||||
} else if (localBranchGroups.length > 0) {
|
||||
base.lines[LEFT_COLUMN_INDEX].top.color = 'local';
|
||||
} else if (remoteBranchGroups.length > 0) {
|
||||
base.lines[LEFT_COLUMN_INDEX].top.color = 'remote';
|
||||
} else {
|
||||
base.lines[LEFT_COLUMN_INDEX].baseNode = undefined;
|
||||
}
|
||||
|
||||
const data = new Map<string, LineGroup>([
|
||||
...remoteBranchGroups.map(({ commit, lineGroup }) => [commit.id, lineGroup]),
|
||||
...localBranchGroups.map(({ commit, lineGroup }) => [commit.id, lineGroup]),
|
||||
...localAndRemoteBranchGroups.map(({ commit, lineGroup }) => [commit.id, lineGroup]),
|
||||
...integratedBranchGroups.map(({ commit, lineGroup }) => [commit.id, lineGroup])
|
||||
] as [string, LineGroup][]);
|
||||
|
||||
return { data, base };
|
||||
}
|
||||
|
||||
function generateDifferentForkpoint({
|
||||
remoteCommits,
|
||||
localCommits,
|
||||
localAndRemoteCommits,
|
||||
integratedCommits
|
||||
}: Commits) {
|
||||
const LEFT_COLUMN_INDEX = 0;
|
||||
const MIDDLE_COLUMN_INDEX = 1;
|
||||
const RIGHT_COLUMN_INDEX = 2;
|
||||
|
||||
if (localAndRemoteCommits.length > 0) {
|
||||
throw new Error('There should never be local and remote commits with a different forkpoint');
|
||||
}
|
||||
|
||||
const remoteBranchGroups = mapToCommitLineGroupPair(remoteCommits, 4);
|
||||
const localBranchGroups = mapToCommitLineGroupPair(localCommits, 4);
|
||||
const integratedBranchGroups = mapToCommitLineGroupPair(integratedCommits, 4);
|
||||
|
||||
const base = blankLineGroup(4);
|
||||
|
||||
remoteBranchGroups.forEach(({ commit, lineGroup }, index) => {
|
||||
// Don't color top half if its the first commit of the list
|
||||
if (index !== 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'remote';
|
||||
}
|
||||
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'remote';
|
||||
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].commitNode = { type: 'large', commit };
|
||||
|
||||
// If there are local commits further down, render a dashed line from the top of the list
|
||||
if (localBranchGroups.length > 0) {
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].top.color = 'local';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.color = 'local';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].top.style = 'dashed';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.style = 'dashed';
|
||||
}
|
||||
});
|
||||
|
||||
let localCommitWithChangeIdFound = false;
|
||||
localBranchGroups.forEach(({ commit, lineGroup }, index) => {
|
||||
// Make the top commit dashed
|
||||
if (index === 0) {
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].top.style = 'dashed';
|
||||
}
|
||||
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].top.color = 'local';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.color = 'local';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].commitNode = { type: 'large', commit };
|
||||
|
||||
if (localCommitWithChangeIdFound) {
|
||||
// If a previous local commit with change ID was found, color with "shadow"
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'shadow';
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'shadow';
|
||||
|
||||
if (commit.relatedRemoteCommit) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].commitNode = {
|
||||
type: 'small',
|
||||
commit: commit.relatedRemoteCommit
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (commit.relatedRemoteCommit) {
|
||||
// If the commit has a commit with a matching change ID, mark it in the shadow lane
|
||||
|
||||
// Since this is the first, if there were any remote commits, we should inherit that color
|
||||
if (remoteBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'remote';
|
||||
}
|
||||
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].commitNode = {
|
||||
type: 'small',
|
||||
commit: commit.relatedRemoteCommit
|
||||
};
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'shadow';
|
||||
|
||||
localCommitWithChangeIdFound = true;
|
||||
} else {
|
||||
// Otherwise maintain the left color if it exists
|
||||
if (remoteBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'remote';
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'remote';
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
integratedBranchGroups.forEach(({ commit, lineGroup }, index) => {
|
||||
if (localBranchGroups.length === 0 && remoteBranchGroups.length === 0) {
|
||||
// If there are no local or remote branches, we want to have a single dashed line
|
||||
|
||||
// Don't color in if its the first commit
|
||||
if (index !== 0) {
|
||||
lineGroup.lines[MIDDLE_COLUMN_INDEX].top.color = 'integrated';
|
||||
lineGroup.lines[MIDDLE_COLUMN_INDEX].top.style = 'dashed';
|
||||
}
|
||||
|
||||
lineGroup.lines[MIDDLE_COLUMN_INDEX].bottom.color = 'integrated';
|
||||
lineGroup.lines[MIDDLE_COLUMN_INDEX].bottom.style = 'dashed';
|
||||
|
||||
lineGroup.lines[MIDDLE_COLUMN_INDEX].commitNode = { type: 'large', commit };
|
||||
} else {
|
||||
// If we have local branches, maintain that color on the top half of the first commit
|
||||
if (index === 0) {
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].top.color =
|
||||
localBranchGroups.at(-1)?.lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.color || 'none';
|
||||
} else {
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].top.color = 'integrated';
|
||||
}
|
||||
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.color = 'integrated';
|
||||
lineGroup.lines[RIGHT_COLUMN_INDEX].commitNode = { type: 'large', commit };
|
||||
|
||||
if (localCommitWithChangeIdFound) {
|
||||
// If there is a commit with change id above, just use shadow style
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'shadow';
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'shadow';
|
||||
|
||||
if (commit.relatedRemoteCommit) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].commitNode = {
|
||||
type: 'small',
|
||||
commit: commit.relatedRemoteCommit
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (commit.relatedRemoteCommit) {
|
||||
// If we have just found a commit with a shadow style, match the top style
|
||||
if (remoteBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'remote';
|
||||
}
|
||||
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].commitNode = {
|
||||
type: 'small',
|
||||
commit: commit.relatedRemoteCommit
|
||||
};
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'shadow';
|
||||
|
||||
localCommitWithChangeIdFound = true;
|
||||
} else {
|
||||
// Otherwise style as remote if there are any
|
||||
if (remoteBranchGroups.length > 0) {
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color = 'remote';
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color = 'remote';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Mark the fork point below the integrated or local branch groups if present
|
||||
if (integratedBranchGroups.length > 0) {
|
||||
integratedBranchGroups.at(-1)!.lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.type = 'fork';
|
||||
} else if (localBranchGroups.length > 0) {
|
||||
localBranchGroups.at(-1)!.lineGroup.lines[RIGHT_COLUMN_INDEX].bottom.type = 'fork';
|
||||
}
|
||||
|
||||
function setLeftSideBase() {
|
||||
let color: Color | undefined;
|
||||
if (integratedBranchGroups.length > 0) {
|
||||
color = integratedBranchGroups.at(-1)!.lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color;
|
||||
} else if (localBranchGroups.length > 0) {
|
||||
color = localBranchGroups.at(-1)!.lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color;
|
||||
} else if (remoteBranchGroups.length > 0) {
|
||||
color = remoteBranchGroups.at(-1)!.lineGroup.lines[LEFT_COLUMN_INDEX].bottom.color;
|
||||
} else {
|
||||
color = 'none';
|
||||
}
|
||||
|
||||
base.lines[LEFT_COLUMN_INDEX].top.color = color;
|
||||
base.lines[LEFT_COLUMN_INDEX].bottom.color = color;
|
||||
base.lines[LEFT_COLUMN_INDEX].top.style = 'dashed';
|
||||
base.lines[LEFT_COLUMN_INDEX].bottom.style = 'dashed';
|
||||
}
|
||||
|
||||
// Set base
|
||||
if (integratedBranchGroups.length > 0) {
|
||||
base.lines[MIDDLE_COLUMN_INDEX].top.color = 'integrated';
|
||||
base.lines[MIDDLE_COLUMN_INDEX].top.style =
|
||||
integratedBranchGroups.at(-1)!.lineGroup.lines[MIDDLE_COLUMN_INDEX].bottom.style;
|
||||
base.lines[MIDDLE_COLUMN_INDEX].baseNode = {};
|
||||
|
||||
setLeftSideBase();
|
||||
} else if (localBranchGroups.length > 0) {
|
||||
base.lines[MIDDLE_COLUMN_INDEX].top.color = 'local';
|
||||
base.lines[MIDDLE_COLUMN_INDEX].baseNode = {};
|
||||
|
||||
setLeftSideBase();
|
||||
} else if (remoteBranchGroups.length > 0) {
|
||||
base.lines[LEFT_COLUMN_INDEX].top.color = 'remote';
|
||||
base.lines[LEFT_COLUMN_INDEX].top.style = 'dashed';
|
||||
base.lines[LEFT_COLUMN_INDEX].baseNode = {};
|
||||
}
|
||||
|
||||
function removeLeftMostColumn() {
|
||||
remoteBranchGroups.forEach(({ lineGroup }) => lineGroup.lines.shift());
|
||||
localBranchGroups.forEach(({ lineGroup }) => lineGroup.lines.shift());
|
||||
integratedBranchGroups.forEach(({ lineGroup }) => lineGroup.lines.shift());
|
||||
base.lines.shift();
|
||||
}
|
||||
|
||||
function removeRightMostColumn() {
|
||||
remoteBranchGroups.forEach(({ lineGroup }) => lineGroup.lines.pop());
|
||||
localBranchGroups.forEach(({ lineGroup }) => lineGroup.lines.pop());
|
||||
integratedBranchGroups.forEach(({ lineGroup }) => lineGroup.lines.pop());
|
||||
base.lines.pop();
|
||||
}
|
||||
|
||||
// Remove the left column if there is no ghost line
|
||||
const hasGhostLine = [
|
||||
...remoteBranchGroups,
|
||||
...localBranchGroups,
|
||||
...integratedBranchGroups
|
||||
].some(
|
||||
({ lineGroup }) =>
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color !== 'none' ||
|
||||
lineGroup.lines[LEFT_COLUMN_INDEX].top.color !== 'none'
|
||||
);
|
||||
|
||||
if (!hasGhostLine) {
|
||||
removeLeftMostColumn();
|
||||
}
|
||||
|
||||
// Remove the right two columns if there is only remote commits
|
||||
if (integratedBranchGroups.length === 0 && localBranchGroups.length === 0) {
|
||||
removeRightMostColumn();
|
||||
removeRightMostColumn();
|
||||
}
|
||||
|
||||
// Remove one right column if there is only integrated with no local or remote commits
|
||||
if (integratedBranchGroups.length > 0 && localBranchGroups.length === 0 && remoteBranchGroups) {
|
||||
removeRightMostColumn();
|
||||
}
|
||||
|
||||
const data = new Map<string, LineGroup>([
|
||||
...remoteBranchGroups.map(({ commit, lineGroup }) => [commit.id, lineGroup]),
|
||||
...localBranchGroups.map(({ commit, lineGroup }) => [commit.id, lineGroup]),
|
||||
...integratedBranchGroups.map(({ commit, lineGroup }) => [commit.id, lineGroup])
|
||||
] as [string, LineGroup][]);
|
||||
|
||||
return { data, base };
|
||||
}
|
||||
|
||||
function mapToCommitLineGroupPair(commits: CommitData[], groupSize: number) {
|
||||
const groupings = commits.map((commit) => ({
|
||||
commit,
|
||||
lineGroup: blankLineGroup(groupSize)
|
||||
}));
|
||||
|
||||
return groupings;
|
||||
}
|
||||
|
||||
function blankLineGroup(lineCount: number): LineGroup {
|
||||
const lines = Array(lineCount)
|
||||
.fill(undefined)
|
||||
.map(
|
||||
(): Line => ({
|
||||
top: { type: 'straight', color: 'none' },
|
||||
bottom: { type: 'straight', color: 'none' }
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
lines
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The Line Manager assumes that the groups of commits will be in the following order:
|
||||
* 1. Remote Commits (Commits you don't have in your branch)
|
||||
* 2. Local Commits (Commits that you have changed locally)
|
||||
* 3. LocalAndRemote Commits (Commits that exist locally and on the remote and have the same hash)
|
||||
* 4. Integrated Commits (Commits that exist locally and perhaps on the remote that are in the trunk)
|
||||
*/
|
||||
export class LineManager {
|
||||
private data: Map<string, LineGroup>;
|
||||
base: LineGroup;
|
||||
|
||||
constructor(commits: Commits, sameForkpoint: boolean) {
|
||||
// We should never have local and remote commits with a different forkpoint
|
||||
if (sameForkpoint || commits.localAndRemoteCommits.length > 0) {
|
||||
const { data, base } = generateSameForkpoint(commits);
|
||||
this.data = data;
|
||||
this.base = base;
|
||||
} else {
|
||||
const { data, base } = generateDifferentForkpoint(commits);
|
||||
this.data = data;
|
||||
this.base = base;
|
||||
}
|
||||
}
|
||||
|
||||
get(commitId: string) {
|
||||
if (!this.data.has(commitId)) {
|
||||
throw new Error(`Failed to find commit ${commitId} in line manager`);
|
||||
}
|
||||
|
||||
return this.data.get(commitId)!;
|
||||
}
|
||||
}
|
||||
|
||||
export class LineManagerFactory {
|
||||
build(commits: Commits, sameForkpoint: boolean) {
|
||||
return new LineManager(commits, sameForkpoint);
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
export type Color = 'local' | 'localAndRemote' | 'remote' | 'integrated' | 'shadow' | 'none';
|
||||
|
||||
export type Style = 'dashed';
|
||||
export interface Cell {
|
||||
type: 'straight' | 'fork';
|
||||
color: Color;
|
||||
style?: Style;
|
||||
}
|
||||
|
||||
export interface CommitNode {
|
||||
type: 'small' | 'large';
|
||||
commit?: CommitData;
|
||||
}
|
||||
|
||||
export interface BaseNode {}
|
||||
|
||||
export interface Line {
|
||||
top: Cell;
|
||||
bottom: Cell;
|
||||
commitNode?: CommitNode;
|
||||
baseNode?: BaseNode;
|
||||
}
|
||||
|
||||
export interface LineGroup {
|
||||
// A tuple of two, three, or four lines
|
||||
lines: Line[];
|
||||
}
|
||||
|
||||
export interface Author {
|
||||
name?: string;
|
||||
email?: string;
|
||||
gravatarUrl?: URL;
|
||||
}
|
||||
|
||||
/**
|
||||
* A minimal set of data required to represent a commit for line drawing purpouses
|
||||
*/
|
||||
export interface CommitData {
|
||||
id: string;
|
||||
title?: string;
|
||||
author: Author;
|
||||
relatedRemoteCommit?: CommitData;
|
||||
}
|
@ -9,7 +9,6 @@
|
||||
import { ProjectService } from '$lib/backend/projects';
|
||||
import { PromptService } from '$lib/backend/prompt';
|
||||
import { UpdaterService } from '$lib/backend/updater';
|
||||
import { LineManagerFactory } from '$lib/commitLines/lineManager';
|
||||
import AppUpdater from '$lib/components/AppUpdater.svelte';
|
||||
import GlobalSettingsMenuAction from '$lib/components/GlobalSettingsMenuAction.svelte';
|
||||
import PromptModal from '$lib/components/PromptModal.svelte';
|
||||
@ -23,6 +22,7 @@
|
||||
import { createKeybind } from '$lib/utils/hotkeys';
|
||||
import { initTheme } from '$lib/utils/theme';
|
||||
import { unsubscribe } from '$lib/utils/unsubscribe';
|
||||
import { LineManagerFactory } from '@gitbutler/ui/CommitLines/lineManager';
|
||||
import { onMount, setContext } from 'svelte';
|
||||
import { Toaster } from 'svelte-french-toast';
|
||||
import type { LayoutData } from './$types';
|
||||
|
@ -7,11 +7,11 @@ import { HttpClient } from '$lib/backend/httpClient';
|
||||
import { ProjectService } from '$lib/backend/projects';
|
||||
import { PromptService } from '$lib/backend/prompt';
|
||||
import { UpdaterService } from '$lib/backend/updater';
|
||||
import { LineManagerFactory } from '$lib/commitLines/lineManager';
|
||||
import { GitHubService } from '$lib/github/service';
|
||||
import { RemotesService } from '$lib/remotes/service';
|
||||
import { UserService } from '$lib/stores/user';
|
||||
import { mockTauri } from '$lib/testing/index';
|
||||
import { LineManagerFactory } from '@gitbutler/ui/CommitLines/lineManager';
|
||||
import lscache from 'lscache';
|
||||
import { BehaviorSubject, config } from 'rxjs';
|
||||
import { env } from '$env/dynamic/public';
|
||||
|
@ -1,12 +1,15 @@
|
||||
{
|
||||
"name": "git-butler",
|
||||
"name": "root",
|
||||
"private": true,
|
||||
"repository": "https://github.com/gitbutlerapp/gitbutler.git",
|
||||
"engines": {
|
||||
"node": ">=20.11"
|
||||
},
|
||||
"packageManager": "pnpm@9.2.0",
|
||||
"scripts": {
|
||||
"dev": "pnpm --filter @gitbutler/app run dev",
|
||||
"dev:ui": "pnpm --filter @gitbutler/ui dev",
|
||||
"dev:tauri": "pnpm tauri dev",
|
||||
"test": "pnpm --filter @gitbutler/app run test",
|
||||
"test:watch": "pnpm --filter @gitbutler/app run test:watch",
|
||||
"build:ui": "pnpm --filter @gitbutler/ui run build",
|
||||
|
@ -3,14 +3,15 @@ import tsParser from '@typescript-eslint/parser';
|
||||
import eslintConfigPrettier from 'eslint-config-prettier';
|
||||
import eslintPluginSvelte from 'eslint-plugin-svelte';
|
||||
import globals from 'globals';
|
||||
import svelteParser from 'svelte-eslint-parser';
|
||||
import tsEslint from 'typescript-eslint';
|
||||
import pluginImportX from 'eslint-plugin-import-x';
|
||||
import storybook from "eslint-plugin-storybook"
|
||||
// Flat config support: https://github.com/storybookjs/eslint-plugin-storybook/pull/156
|
||||
import storybook from 'eslint-plugin-storybook';
|
||||
import svelteParser from 'svelte-eslint-parser';
|
||||
|
||||
export default tsEslint.config(
|
||||
js.configs.recommended,
|
||||
storybook.configs.recommended,
|
||||
...storybook.configs["flat/recommended"],
|
||||
...tsEslint.configs.recommended,
|
||||
...eslintPluginSvelte.configs['flat/recommended'],
|
||||
eslintConfigPrettier,
|
||||
@ -61,7 +62,8 @@ export default tsEslint.config(
|
||||
'svelte.config.js',
|
||||
'postcss.config.cjs',
|
||||
'playwright.config.ts',
|
||||
'**/.pnpm-store'
|
||||
'**/.pnpm-store',
|
||||
'!.storybook'
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -15,8 +15,8 @@
|
||||
"packageManager": "pnpm@9.2.0",
|
||||
"exports": {
|
||||
"./CommitLines/*": {
|
||||
"svelte": "./dist/commitLines/*.js",
|
||||
"types": "./dist/commitLines/*.d.ts"
|
||||
"svelte": "./dist/CommitLines/*.js",
|
||||
"types": "./dist/CommitLines/*.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
@ -26,7 +26,6 @@
|
||||
"dev": "vite dev",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"format": "prettier --write .",
|
||||
"build": "vite build",
|
||||
"fix": "eslint --fix .",
|
||||
"check": "svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "pnpm check --watch",
|
||||
@ -54,7 +53,7 @@
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-import-x": "^0.5.1",
|
||||
"eslint-plugin-storybook": "^0.8.0",
|
||||
"eslint-plugin-storybook": "0.9.0--canary.156.da7873a.0",
|
||||
"eslint-plugin-svelte": "2.40.0",
|
||||
"globals": "^15.6.0",
|
||||
"prettier": "^3.3.2",
|
||||
|
@ -1,5 +1,5 @@
|
||||
import DemoCommitLines from './DemoCommitLines.svelte';
|
||||
import type { Author, CommitData } from '$lib/commitLines/types';
|
||||
import type { Author, CommitData } from '$lib/CommitLines/types';
|
||||
import type { Meta, StoryObj } from '@storybook/svelte';
|
||||
|
||||
const meta = {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import LineGroup from '$lib/commitLines/LineGroup.svelte';
|
||||
import { LineManager } from '$lib/commitLines/lineManager';
|
||||
import type { CommitData } from '$lib/commitLines/types';
|
||||
import LineGroup from '$lib/CommitLines/LineGroup.svelte';
|
||||
import { LineManager } from '$lib/CommitLines/lineManager';
|
||||
import type { CommitData } from '$lib/CommitLines/types';
|
||||
|
||||
interface Props {
|
||||
remoteCommits: CommitData[];
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import LineGroup from '$lib/commitLines/LineGroup.svelte';
|
||||
import type { LineGroup as ILineGroup } from '$lib/commitLines/types.ts';
|
||||
import LineGroup from '$lib/CommitLines/LineGroup.svelte';
|
||||
import type { LineGroup as ILineGroup } from '$lib/CommitLines/types.ts';
|
||||
|
||||
interface Props {
|
||||
lineGroups: ILineGroup[];
|
||||
|
@ -11,8 +11,6 @@
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"experimentalDecorators": true,
|
||||
"types": ["vitest/importMeta"]
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
export default {
|
||||
plugins: [
|
||||
sveltekit()
|
||||
],
|
||||
@ -27,12 +26,5 @@ export default defineConfig({
|
||||
minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
|
||||
// ship sourcemaps for better sentry error reports
|
||||
sourcemap: true
|
||||
},
|
||||
test: {
|
||||
deps: {
|
||||
inline: ['sorcery']
|
||||
},
|
||||
includeSource: ['src/**/*.{js,ts}'],
|
||||
exclude: ['**/e2e/playwright/**/*', 'node_modules/**/*']
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -304,8 +304,8 @@ importers:
|
||||
specifier: ^0.5.1
|
||||
version: 0.5.1(eslint@9.5.0)(typescript@5.4.5)
|
||||
eslint-plugin-storybook:
|
||||
specifier: ^0.8.0
|
||||
version: 0.8.0(eslint@9.5.0)(typescript@5.4.5)
|
||||
specifier: 0.9.0--canary.156.da7873a.0
|
||||
version: 0.9.0--canary.156.da7873a.0(eslint@9.5.0)(typescript@5.4.5)
|
||||
eslint-plugin-svelte:
|
||||
specifier: 2.40.0
|
||||
version: 2.40.0(eslint@9.5.0)(svelte@5.0.0-next.149)
|
||||
@ -3428,8 +3428,8 @@ packages:
|
||||
eslint-plugin-square-svelte-store@1.0.0:
|
||||
resolution: {integrity: sha512-QLybNNEPcBKVrgAeow/7ouOqbTVsWwEdStFab9ZMZaW19Y//ZEhhtuEb92P69n9u/JRL6EFhArV9AfS+LgS4mA==}
|
||||
|
||||
eslint-plugin-storybook@0.8.0:
|
||||
resolution: {integrity: sha512-CZeVO5EzmPY7qghO2t64oaFM+8FTaD4uzOEjHKp516exyTKo+skKAL9GI3QALS2BXhyALJjNtwbmr1XinGE8bA==}
|
||||
eslint-plugin-storybook@0.9.0--canary.156.da7873a.0:
|
||||
resolution: {integrity: sha512-3b6hQMRfKWwkNB0koK0y9Boi+GYAt8vz+3tzU5JHylyAZh3Vg5TgvxM6IRhKixEY4OlQhsJPhqMzP0rT9fP5mA==}
|
||||
engines: {node: '>= 18'}
|
||||
peerDependencies:
|
||||
eslint: '>=6'
|
||||
@ -5083,10 +5083,6 @@ packages:
|
||||
resolution: {integrity: sha512-nQFEv9gRw6SJAwWD2LrL0NmQvAcO7FBwJbwmr2ttPAacfy0xuiOjE5zt+zM4xDyuyvUaxBi/9gb2SoCyNEVJcw==}
|
||||
engines: {node: '>=8.6.0'}
|
||||
|
||||
requireindex@1.2.0:
|
||||
resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==}
|
||||
engines: {node: '>=0.10.5'}
|
||||
|
||||
resize-observer-polyfill@1.5.1:
|
||||
resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
|
||||
|
||||
@ -8733,7 +8729,7 @@ snapshots:
|
||||
lodash: 4.17.21
|
||||
redent: 3.0.0
|
||||
optionalDependencies:
|
||||
vitest: 0.34.6
|
||||
vitest: 0.34.6(playwright@1.44.1)
|
||||
|
||||
'@testing-library/user-event@14.5.2(@testing-library/dom@9.3.4)':
|
||||
dependencies:
|
||||
@ -10036,12 +10032,11 @@ snapshots:
|
||||
|
||||
eslint-plugin-square-svelte-store@1.0.0: {}
|
||||
|
||||
eslint-plugin-storybook@0.8.0(eslint@9.5.0)(typescript@5.4.5):
|
||||
eslint-plugin-storybook@0.9.0--canary.156.da7873a.0(eslint@9.5.0)(typescript@5.4.5):
|
||||
dependencies:
|
||||
'@storybook/csf': 0.0.1
|
||||
'@typescript-eslint/utils': 5.62.0(eslint@9.5.0)(typescript@5.4.5)
|
||||
eslint: 9.5.0
|
||||
requireindex: 1.2.0
|
||||
ts-dedent: 2.2.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -11812,8 +11807,6 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
requireindex@1.2.0: {}
|
||||
|
||||
resize-observer-polyfill@1.5.1: {}
|
||||
|
||||
resolve-from@4.0.0: {}
|
||||
@ -12567,42 +12560,6 @@ snapshots:
|
||||
optionalDependencies:
|
||||
vite: 5.2.13(@types/node@20.5.9)
|
||||
|
||||
vitest@0.34.6:
|
||||
dependencies:
|
||||
'@types/chai': 4.3.6
|
||||
'@types/chai-subset': 1.3.3
|
||||
'@types/node': 20.5.9
|
||||
'@vitest/expect': 0.34.6
|
||||
'@vitest/runner': 0.34.6
|
||||
'@vitest/snapshot': 0.34.6
|
||||
'@vitest/spy': 0.34.6
|
||||
'@vitest/utils': 0.34.6
|
||||
acorn: 8.12.0
|
||||
acorn-walk: 8.2.0
|
||||
cac: 6.7.14
|
||||
chai: 4.3.10
|
||||
debug: 4.3.4
|
||||
local-pkg: 0.4.3
|
||||
magic-string: 0.30.10
|
||||
pathe: 1.1.2
|
||||
picocolors: 1.0.0
|
||||
std-env: 3.4.3
|
||||
strip-literal: 1.3.0
|
||||
tinybench: 2.5.0
|
||||
tinypool: 0.7.0
|
||||
vite: 5.2.13(@types/node@20.5.9)
|
||||
vite-node: 0.34.6(@types/node@20.5.9)
|
||||
why-is-node-running: 2.2.2
|
||||
transitivePeerDependencies:
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
optional: true
|
||||
|
||||
vitest@0.34.6(playwright@1.44.1):
|
||||
dependencies:
|
||||
'@types/chai': 4.3.6
|
||||
|
Loading…
Reference in New Issue
Block a user