@kubohiroya/turbowarp-plus-editor-git 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +459 -74
- package/dist/messages.d.ts +34 -0
- package/dist/project-assets.d.ts +4 -0
- package/dist/project-change-list.d.ts +81 -0
- package/dist/project-change-model.d.ts +73 -0
- package/dist/project-source-diff.d.ts +2 -0
- package/dist/project-source-diff.js +2 -2
- package/dist/project-source-review.d.ts +6 -1
- package/dist/{repository-BQkADJmK.js → repository-CtvWYPQ8.js} +187 -8
- package/dist/repository.d.ts +41 -0
- package/dist/repository.js +1 -1
- package/dist/{scratch-block-diff-renderer-xS8OYsRl.js → scratch-block-diff-renderer-DZR8ep-T.js} +264 -12
- package/dist/style.css +30 -2
- package/package.json +1 -1
- package/src/connection-settings.tsx +14 -8
- package/src/file-diff-view.tsx +4 -2
- package/src/index.tsx +68 -23
- package/src/messages.ts +34 -26
- package/src/project-assets.ts +19 -7
- package/src/project-change-list.tsx +210 -0
- package/src/project-change-model.ts +212 -0
- package/src/project-source-diff.tsx +3 -0
- package/src/project-source-review.tsx +12 -5
- package/src/repository.ts +129 -7
- package/src/style.css +30 -2
package/dist/messages.d.ts
CHANGED
|
@@ -51,6 +51,23 @@ export declare const messages: {
|
|
|
51
51
|
remoteDone: string;
|
|
52
52
|
pulledProject: string;
|
|
53
53
|
confirmPush: string;
|
|
54
|
+
details: string;
|
|
55
|
+
branch: string;
|
|
56
|
+
head: string;
|
|
57
|
+
groups: string;
|
|
58
|
+
added: string;
|
|
59
|
+
modified: string;
|
|
60
|
+
deleted: string;
|
|
61
|
+
gitStaged: string;
|
|
62
|
+
gitUnstaged: string;
|
|
63
|
+
gitUntracked: string;
|
|
64
|
+
upstreamSame: string;
|
|
65
|
+
upstreamAhead: string;
|
|
66
|
+
upstreamBehind: string;
|
|
67
|
+
upstreamDiverged: string;
|
|
68
|
+
upstreamUnknown: string;
|
|
69
|
+
records: string;
|
|
70
|
+
checkedAt: string;
|
|
54
71
|
failed: string;
|
|
55
72
|
};
|
|
56
73
|
ja: {
|
|
@@ -105,6 +122,23 @@ export declare const messages: {
|
|
|
105
122
|
remoteDone: string;
|
|
106
123
|
pulledProject: string;
|
|
107
124
|
confirmPush: string;
|
|
125
|
+
details: string;
|
|
126
|
+
branch: string;
|
|
127
|
+
head: string;
|
|
128
|
+
groups: string;
|
|
129
|
+
added: string;
|
|
130
|
+
modified: string;
|
|
131
|
+
deleted: string;
|
|
132
|
+
gitStaged: string;
|
|
133
|
+
gitUnstaged: string;
|
|
134
|
+
gitUntracked: string;
|
|
135
|
+
upstreamSame: string;
|
|
136
|
+
upstreamAhead: string;
|
|
137
|
+
upstreamBehind: string;
|
|
138
|
+
upstreamDiverged: string;
|
|
139
|
+
upstreamUnknown: string;
|
|
140
|
+
records: string;
|
|
141
|
+
checkedAt: string;
|
|
108
142
|
failed: string;
|
|
109
143
|
};
|
|
110
144
|
};
|
package/dist/project-assets.d.ts
CHANGED
|
@@ -15,5 +15,9 @@ export declare function currentCostume(target: ProjectTarget): {
|
|
|
15
15
|
md5ext: string;
|
|
16
16
|
type: string;
|
|
17
17
|
} | null;
|
|
18
|
+
/** The image type of an asset file name, or `undefined` for sounds and anything that is not an image. */
|
|
19
|
+
export declare function assetImageType(md5ext: string): string | undefined;
|
|
20
|
+
/** Loads one image asset of one version as an object URL, or `null` while it is unavailable or not an image. */
|
|
21
|
+
export declare function useAssetImage(md5ext: string | undefined, version: ProjectVersion, loadAsset?: ProjectAssetLoader): string | null;
|
|
18
22
|
/** Loads the current costume of one version of a target as an object URL for an image, or `null` while it is unavailable. */
|
|
19
23
|
export declare function useCostumeImage(target: ProjectTarget | undefined, version: ProjectVersion, loadAsset?: ProjectAssetLoader): string | null;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ChangedFile, ProjectChangeList, ProjectElementChange, ProjectTargetChanges } from './project-change-model.js';
|
|
3
|
+
import type { ProjectAssetLoader } from './project-assets.js';
|
|
4
|
+
import type { ChangeGroup, FileChange, Repository, Snapshot } from './repository.js';
|
|
5
|
+
import type { ProjectBlockRenderer } from './scratch-block-diff-renderer.js';
|
|
6
|
+
declare const en: {
|
|
7
|
+
title: string;
|
|
8
|
+
stage: string;
|
|
9
|
+
code: (count: number) => string;
|
|
10
|
+
costumes: string;
|
|
11
|
+
backdrops: string;
|
|
12
|
+
sounds: string;
|
|
13
|
+
data: string;
|
|
14
|
+
settings: string;
|
|
15
|
+
project: string;
|
|
16
|
+
other: string;
|
|
17
|
+
added: string;
|
|
18
|
+
removed: string;
|
|
19
|
+
updated: string;
|
|
20
|
+
files: string;
|
|
21
|
+
before: string;
|
|
22
|
+
after: string;
|
|
23
|
+
absent: string;
|
|
24
|
+
loading: string;
|
|
25
|
+
unreadable: string;
|
|
26
|
+
fileList: string;
|
|
27
|
+
property: string;
|
|
28
|
+
format: string;
|
|
29
|
+
rate: string;
|
|
30
|
+
samples: string;
|
|
31
|
+
file: string;
|
|
32
|
+
noImage: string;
|
|
33
|
+
groups: Record<ChangeGroup, string>;
|
|
34
|
+
};
|
|
35
|
+
type Labels = typeof en;
|
|
36
|
+
export declare const projectChangeLabels: (locale: string) => Labels;
|
|
37
|
+
export interface ProjectChanges {
|
|
38
|
+
list: ProjectChangeList;
|
|
39
|
+
sources: {
|
|
40
|
+
before: string | null;
|
|
41
|
+
after: string | null;
|
|
42
|
+
};
|
|
43
|
+
loadAsset: ProjectAssetLoader;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Reads the selected project folder in the last commit and the working tree (or a commit and its parent) and arranges
|
|
47
|
+
* the changed files by stage, sprite and element. `undefined` while there is no project; `'loading'` and `'unreadable'`
|
|
48
|
+
* tell the panel to keep the list by file.
|
|
49
|
+
*/
|
|
50
|
+
export declare function useProjectChanges(repository: Repository | null, snapshot: Snapshot | null, project: string | null, commit: string | null, changes: readonly FileChange[]): ProjectChanges | 'loading' | 'unreadable' | undefined;
|
|
51
|
+
/** The change list arranged by the project's stage, sprites and elements, with files outside the project after them. */
|
|
52
|
+
export declare function ProjectChangeListView({ changes, selected, locale, busy, onSelect, onSelectFile, fileList, fileListOpen, setFileListOpen }: {
|
|
53
|
+
changes: ProjectChanges;
|
|
54
|
+
selected: string | null;
|
|
55
|
+
locale: string;
|
|
56
|
+
busy: boolean;
|
|
57
|
+
onSelect(key: string): void;
|
|
58
|
+
onSelectFile(file: ChangedFile): void;
|
|
59
|
+
fileList: React.ReactNode;
|
|
60
|
+
fileListOpen: boolean;
|
|
61
|
+
setFileListOpen(open: boolean): void;
|
|
62
|
+
}): React.JSX.Element;
|
|
63
|
+
export declare function findElement(list: ProjectChangeList, key: string | null): {
|
|
64
|
+
element: ProjectElementChange;
|
|
65
|
+
target: ProjectTargetChanges;
|
|
66
|
+
} | {
|
|
67
|
+
element: ProjectElementChange;
|
|
68
|
+
target: null;
|
|
69
|
+
} | null;
|
|
70
|
+
/** The details of one selected row: its code, pictures or values in both versions, and the files behind it. */
|
|
71
|
+
export declare function ProjectElementView({ changes, selection, locale, renderBlock, onSelectFile }: {
|
|
72
|
+
changes: ProjectChanges;
|
|
73
|
+
selection: {
|
|
74
|
+
element: ProjectElementChange;
|
|
75
|
+
target: ProjectTargetChanges | null;
|
|
76
|
+
};
|
|
77
|
+
locale: string;
|
|
78
|
+
renderBlock?: ProjectBlockRenderer;
|
|
79
|
+
onSelectFile(file: ChangedFile): void;
|
|
80
|
+
}): React.JSX.Element;
|
|
81
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { ChangeGroup } from './repository.js';
|
|
2
|
+
import type { ProjectSource, ProjectTarget } from './project-source-patch.js';
|
|
3
|
+
/** One changed file of the repository, with the Git group it was listed under. A path can appear in several groups. */
|
|
4
|
+
export interface ChangedFile {
|
|
5
|
+
path: string;
|
|
6
|
+
group: ChangeGroup;
|
|
7
|
+
}
|
|
8
|
+
export type ProjectElementKind = 'code' | 'costumes' | 'sounds' | 'data' | 'settings';
|
|
9
|
+
export type ProjectChangeStatus = 'added' | 'removed' | 'updated';
|
|
10
|
+
/** One row of the project-shaped change list: something a person recognizes in the Editor. */
|
|
11
|
+
export interface ProjectElementChange {
|
|
12
|
+
/** Stable within one list, for React keys and selection. */
|
|
13
|
+
key: string;
|
|
14
|
+
kind: ProjectElementKind;
|
|
15
|
+
status: ProjectChangeStatus;
|
|
16
|
+
/** Costume or sound name; absent for code, data and settings rows. */
|
|
17
|
+
name?: string;
|
|
18
|
+
/** The costume or sound entry in each version, for costume and sound rows. */
|
|
19
|
+
before?: Record<string, unknown>;
|
|
20
|
+
after?: Record<string, unknown>;
|
|
21
|
+
/** Asset file names (`md5ext`) of each version, for costume and sound rows. */
|
|
22
|
+
md5ext?: {
|
|
23
|
+
before?: string;
|
|
24
|
+
after?: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Changed property keys, for data and settings rows (for example `variables`, `x`, `visible`), and for
|
|
28
|
+
* project-level rows (`monitors`, `extensions`, `meta`).
|
|
29
|
+
*/
|
|
30
|
+
properties?: string[];
|
|
31
|
+
/** Number of changed code items (as counted by the review comparison), for code rows. */
|
|
32
|
+
scripts?: number;
|
|
33
|
+
/** The changed repository files behind this row, so the details view can show them with their Git groups. */
|
|
34
|
+
files: ChangedFile[];
|
|
35
|
+
}
|
|
36
|
+
export interface ProjectTargetChanges {
|
|
37
|
+
key: string;
|
|
38
|
+
name: string;
|
|
39
|
+
isStage: boolean;
|
|
40
|
+
status: ProjectChangeStatus;
|
|
41
|
+
before?: ProjectTarget;
|
|
42
|
+
after?: ProjectTarget;
|
|
43
|
+
/** In the order code, costumes, sounds, data, settings; costumes and sounds in their order in the target. */
|
|
44
|
+
elements: ProjectElementChange[];
|
|
45
|
+
}
|
|
46
|
+
export interface ProjectChangeList {
|
|
47
|
+
/** The stage first, then sprites in project order; removed targets after the existing ones. */
|
|
48
|
+
targets: ProjectTargetChanges[];
|
|
49
|
+
/** Project-level changes outside the targets (monitors, extensions, meta and other top-level keys). */
|
|
50
|
+
project: ProjectElementChange[];
|
|
51
|
+
/** Changed files that belong to no element: sb3-source.json, embedded-extensions.json, unreferenced assets and the rest. */
|
|
52
|
+
other: ChangedFile[];
|
|
53
|
+
}
|
|
54
|
+
export interface OrganizeProjectChangesInput {
|
|
55
|
+
/** The project folder relative to the repository root, `''` for the root. */
|
|
56
|
+
folder: string;
|
|
57
|
+
/** The project data of each version, `null` where the version has no project file. */
|
|
58
|
+
before: ProjectSource | null;
|
|
59
|
+
after: ProjectSource | null;
|
|
60
|
+
/** The assets directory of each version, relative to the folder (from sb3-source.json; `assets` by default). */
|
|
61
|
+
assetsDirectory: {
|
|
62
|
+
before: string;
|
|
63
|
+
after: string;
|
|
64
|
+
};
|
|
65
|
+
/** Every changed file in the folder, from all Git groups. */
|
|
66
|
+
files: readonly ChangedFile[];
|
|
67
|
+
}
|
|
68
|
+
/** The Japanese or English name of a project or target property key; unknown keys are returned as they are. */
|
|
69
|
+
export declare function projectPropertyLabel(key: string, locale?: string): string;
|
|
70
|
+
/** The asset file name of a costume or sound entry: `md5ext`, or `assetId.dataFormat`; `''` when it has neither. */
|
|
71
|
+
export declare function assetFileName(entry: Record<string, unknown>): string;
|
|
72
|
+
/** Arranges the changed files of one project folder by stage, sprite and element. Pure; reads nothing. */
|
|
73
|
+
export declare function organizeProjectChanges(input: OrganizeProjectChangesInput): ProjectChangeList;
|
|
@@ -10,6 +10,8 @@ export type { ProjectBlockLocation, ProjectBlockLocator, ScratchBlockLocationWor
|
|
|
10
10
|
export type { BlockPart } from './project-source-patch.js';
|
|
11
11
|
export { createProjectSourceDiff } from './project-source-patch.js';
|
|
12
12
|
export { currentCostume } from './project-assets.js';
|
|
13
|
+
export { assetFileName, organizeProjectChanges, projectPropertyLabel } from './project-change-model.js';
|
|
14
|
+
export type { ChangedFile, OrganizeProjectChangesInput, ProjectChangeList, ProjectChangeStatus, ProjectElementChange, ProjectElementKind, ProjectTargetChanges } from './project-change-model.js';
|
|
13
15
|
export type { ProjectAssetLoader, ProjectVersion } from './project-assets.js';
|
|
14
16
|
export { createScratchBlocksDiffRenderer } from './scratch-block-diff-renderer.js';
|
|
15
17
|
export type { BlockPreviewView, BlockPreviewViewport, ProjectBlockRenderer, ProjectBlockRendering, ScratchBlockDiffRendererOptions, ScratchBlocksPort } from './scratch-block-diff-renderer.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as gitHubRepositoryFromOrigin, c as
|
|
1
|
+
import { _ as compareProjectBlocks, a as gitHubRepositoryFromOrigin, b as readProjectSourceDiff, c as projectPropertyLabel, d as BlockPreview, f as createPreviewSync, i as createGitHubPullRequests, l as ProjectSourceComparison, m as currentCostume, n as createScratchBlocksDiffLocator, o as assetFileName, p as usePreviewSync, s as organizeProjectChanges, t as createScratchBlocksDiffRenderer, u as ProjectSourceReview, v as createProjectSourceDiff } from "./scratch-block-diff-renderer-DZR8ep-T.js";
|
|
2
2
|
import { n as init_objectSpread2, t as _objectSpread2 } from "./objectSpread2-Dkd68nJH.js";
|
|
3
3
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
// src/project-source-diff.tsx
|
|
@@ -169,4 +169,4 @@ function ProjectSourceBlockDiff({ patch, beforeSource, renderBlock, locateBlock,
|
|
|
169
169
|
})
|
|
170
170
|
}, labels.more));
|
|
171
171
|
}
|
|
172
|
-
export { ProjectSourceBlockDiff, ProjectSourceComparison, ProjectSourceReview, createGitHubPullRequests, createPreviewSync, createProjectSourceDiff, createScratchBlocksDiffLocator, createScratchBlocksDiffRenderer, currentCostume, gitHubRepositoryFromOrigin };
|
|
172
|
+
export { ProjectSourceBlockDiff, ProjectSourceComparison, ProjectSourceReview, assetFileName, createGitHubPullRequests, createPreviewSync, createProjectSourceDiff, createScratchBlocksDiffLocator, createScratchBlocksDiffRenderer, currentCostume, gitHubRepositoryFromOrigin, organizeProjectChanges, projectPropertyLabel };
|
|
@@ -32,7 +32,12 @@ export interface ProjectSourceComparisonProps {
|
|
|
32
32
|
fallback?: React.ReactNode;
|
|
33
33
|
/** Reads the images of both versions for thumbnails. Without it, stages and sprites are shown by name. */
|
|
34
34
|
loadAsset?: ProjectAssetLoader;
|
|
35
|
+
/** Shows only the code of this stage or sprite, without the overview and the changes outside the code. */
|
|
36
|
+
target?: {
|
|
37
|
+
isStage: boolean;
|
|
38
|
+
name: string;
|
|
39
|
+
};
|
|
35
40
|
}
|
|
36
41
|
/** Compares two versions of a project.source.json by stage, sprite and code, as the pull request review does. */
|
|
37
|
-
export declare function ProjectSourceComparison({ before, after, renderBlock, locale, fallback, loadAsset }: ProjectSourceComparisonProps): React.JSX.Element;
|
|
42
|
+
export declare function ProjectSourceComparison({ before, after, renderBlock, locale, fallback, loadAsset, target }: ProjectSourceComparisonProps): React.JSX.Element;
|
|
38
43
|
export declare function ProjectSourceReview({ title, description, verification, files, renderBlock, locale }: ProjectSourceReviewProps): React.JSX.Element;
|
|
@@ -14562,6 +14562,37 @@ async function fetch({ fs, http, onProgress, onMessage, onAuth, onAuthSuccess, o
|
|
|
14562
14562
|
}
|
|
14563
14563
|
}
|
|
14564
14564
|
/**
|
|
14565
|
+
* Find the merge base for a set of commits
|
|
14566
|
+
*
|
|
14567
|
+
* @param {object} args
|
|
14568
|
+
* @param {FsClient} args.fs - a file system client
|
|
14569
|
+
* @param {string} [args.dir] - The [working tree](dir-vs-gitdir.md) directory path
|
|
14570
|
+
* @param {string} [args.gitdir=join(dir,'.git')] - [required] The [git directory](dir-vs-gitdir.md) path
|
|
14571
|
+
* @param {string[]} args.oids - Which commits
|
|
14572
|
+
* @param {object} [args.cache] - a [cache](cache.md) object
|
|
14573
|
+
*
|
|
14574
|
+
*/
|
|
14575
|
+
async function findMergeBase({ fs, dir, gitdir = join(dir, ".git"), oids, cache = {} }) {
|
|
14576
|
+
try {
|
|
14577
|
+
assertParameter("fs", fs);
|
|
14578
|
+
assertParameter("gitdir", gitdir);
|
|
14579
|
+
assertParameter("oids", oids);
|
|
14580
|
+
const fsp = new FileSystem(fs);
|
|
14581
|
+
return await _findMergeBase({
|
|
14582
|
+
fs: fsp,
|
|
14583
|
+
cache,
|
|
14584
|
+
gitdir: await discoverGitdir({
|
|
14585
|
+
fsp,
|
|
14586
|
+
dotgit: gitdir
|
|
14587
|
+
}),
|
|
14588
|
+
oids
|
|
14589
|
+
});
|
|
14590
|
+
} catch (err) {
|
|
14591
|
+
err.caller = "git.findMergeBase";
|
|
14592
|
+
throw err;
|
|
14593
|
+
}
|
|
14594
|
+
}
|
|
14595
|
+
/**
|
|
14565
14596
|
* Read an entry from the git config files.
|
|
14566
14597
|
*
|
|
14567
14598
|
* *Caveats:*
|
|
@@ -16795,10 +16826,14 @@ async function runRemoteOperation(root, operation, getSession, guard, signal) {
|
|
|
16795
16826
|
}
|
|
16796
16827
|
// src/repository.ts
|
|
16797
16828
|
init_objectSpread2();
|
|
16829
|
+
var projectSourceLimit = 16777216;
|
|
16798
16830
|
var emptyTree = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
16799
16831
|
var textLimit = 1048576;
|
|
16800
16832
|
var inScope = (path, scope) => !scope || path === scope || path.startsWith(scope + "/");
|
|
16801
16833
|
var probeLimit = 5e3;
|
|
16834
|
+
/** Most commits read to count how far a branch is ahead of or behind its tracking branch. */
|
|
16835
|
+
var upstreamWalkLimit = 1e3;
|
|
16836
|
+
var trackingRef = (branchRef) => "refs/remotes/origin/" + branchRef.slice(11);
|
|
16802
16837
|
var sameMetadata = (a, b) => a.size === b.size && [...a].every(([path, bytes]) => {
|
|
16803
16838
|
var _b$get;
|
|
16804
16839
|
return sameBytes(bytes, (_b$get = b.get(path)) !== null && _b$get !== void 0 ? _b$get : null);
|
|
@@ -16838,7 +16873,7 @@ async function openRepository(root) {
|
|
|
16838
16873
|
if (text.startsWith("ref: refs/heads/")) {
|
|
16839
16874
|
const ref = text.slice(5);
|
|
16840
16875
|
pathParts(ref);
|
|
16841
|
-
paths.push("/.git/" + ref);
|
|
16876
|
+
paths.push("/.git/" + ref, "/.git/" + trackingRef(ref));
|
|
16842
16877
|
} else if (!/^[0-9a-f]{40}$/.test(text)) throw new GitPanelError("invalid");
|
|
16843
16878
|
const result = /* @__PURE__ */ new Map();
|
|
16844
16879
|
for (const path of paths) {
|
|
@@ -16884,7 +16919,7 @@ async function openRepository(root) {
|
|
|
16884
16919
|
} catch (_unused) {
|
|
16885
16920
|
return "locked";
|
|
16886
16921
|
}
|
|
16887
|
-
paths.push(".git/" + head.slice(5));
|
|
16922
|
+
paths.push(".git/" + head.slice(5), ".git/" + trackingRef(head.slice(5)));
|
|
16888
16923
|
}
|
|
16889
16924
|
const lines = [];
|
|
16890
16925
|
for (const path of paths) {
|
|
@@ -16956,6 +16991,86 @@ async function openRepository(root) {
|
|
|
16956
16991
|
mode
|
|
16957
16992
|
}]));
|
|
16958
16993
|
};
|
|
16994
|
+
/**
|
|
16995
|
+
* Compares `refs/heads/<branch>` with `refs/remotes/origin/<branch>` from local refs only. Counts by painting
|
|
16996
|
+
* commits from both tips in committer-time order until every queued commit is reachable from both, like
|
|
16997
|
+
* `git rev-list --left-right --count`, reading at most `upstreamWalkLimit` commits.
|
|
16998
|
+
*/
|
|
16999
|
+
const upstreamRelation = async (branch, head) => {
|
|
17000
|
+
const unknown = {
|
|
17001
|
+
state: "unknown",
|
|
17002
|
+
ahead: 0,
|
|
17003
|
+
behind: 0
|
|
17004
|
+
};
|
|
17005
|
+
if (!branch || !head) return unknown;
|
|
17006
|
+
pathParts(trackingRef("refs/heads/" + branch));
|
|
17007
|
+
try {
|
|
17008
|
+
const remote = await resolveRef(_objectSpread2(_objectSpread2({}, options), {}, { ref: trackingRef("refs/heads/" + branch) }));
|
|
17009
|
+
if (remote === head) return {
|
|
17010
|
+
state: "same",
|
|
17011
|
+
ahead: 0,
|
|
17012
|
+
behind: 0
|
|
17013
|
+
};
|
|
17014
|
+
const bases = await findMergeBase(_objectSpread2(_objectSpread2({}, options), {}, {
|
|
17015
|
+
cache,
|
|
17016
|
+
oids: [head, remote]
|
|
17017
|
+
}));
|
|
17018
|
+
const hasAhead = !bases.includes(head), hasBehind = !bases.includes(remote);
|
|
17019
|
+
const local = 1, tracking = 2, both = 3;
|
|
17020
|
+
const flags = /* @__PURE__ */ new Map([[head, local], [remote, tracking]]);
|
|
17021
|
+
const time = async (oid) => (await readCommit(_objectSpread2(_objectSpread2({}, options), {}, {
|
|
17022
|
+
cache,
|
|
17023
|
+
oid
|
|
17024
|
+
}))).commit;
|
|
17025
|
+
const queue = [];
|
|
17026
|
+
const enqueue = async (oid) => {
|
|
17027
|
+
const commit = await time(oid);
|
|
17028
|
+
queue.push({
|
|
17029
|
+
oid,
|
|
17030
|
+
time: commit.committer.timestamp,
|
|
17031
|
+
parents: commit.parent
|
|
17032
|
+
});
|
|
17033
|
+
};
|
|
17034
|
+
await enqueue(head);
|
|
17035
|
+
await enqueue(remote);
|
|
17036
|
+
let read = 2;
|
|
17037
|
+
let complete = true;
|
|
17038
|
+
while (queue.some((item) => flags.get(item.oid) !== both)) {
|
|
17039
|
+
if (read >= 1e3) {
|
|
17040
|
+
complete = false;
|
|
17041
|
+
break;
|
|
17042
|
+
}
|
|
17043
|
+
queue.sort((a, b) => b.time - a.time);
|
|
17044
|
+
const item = queue.shift();
|
|
17045
|
+
const flag = flags.get(item.oid);
|
|
17046
|
+
for (const parent of item.parents) {
|
|
17047
|
+
var _flags$get;
|
|
17048
|
+
const previous = (_flags$get = flags.get(parent)) !== null && _flags$get !== void 0 ? _flags$get : 0;
|
|
17049
|
+
if ((previous | flag) === previous) continue;
|
|
17050
|
+
flags.set(parent, previous | flag);
|
|
17051
|
+
if (!queue.some((entry) => entry.oid === parent)) {
|
|
17052
|
+
await enqueue(parent);
|
|
17053
|
+
read++;
|
|
17054
|
+
}
|
|
17055
|
+
}
|
|
17056
|
+
}
|
|
17057
|
+
let ahead = 0, behind = 0;
|
|
17058
|
+
for (const flag of flags.values()) if (flag === local) ahead++;
|
|
17059
|
+
else if (flag === tracking) behind++;
|
|
17060
|
+
if (!complete) {
|
|
17061
|
+
ahead = hasAhead ? upstreamWalkLimit : 0;
|
|
17062
|
+
behind = hasBehind ? upstreamWalkLimit : 0;
|
|
17063
|
+
}
|
|
17064
|
+
return {
|
|
17065
|
+
state: hasAhead && hasBehind ? "diverged" : hasAhead ? "ahead" : hasBehind ? "behind" : "same",
|
|
17066
|
+
ahead: hasAhead ? Math.max(ahead, 1) : 0,
|
|
17067
|
+
behind: hasBehind ? Math.max(behind, 1) : 0
|
|
17068
|
+
};
|
|
17069
|
+
} catch (error) {
|
|
17070
|
+
if (errorCode(error) === "NotFoundError") return unknown;
|
|
17071
|
+
throw error;
|
|
17072
|
+
}
|
|
17073
|
+
};
|
|
16959
17074
|
const assertSnapshot = async (snapshot) => {
|
|
16960
17075
|
if (!sameMetadata(snapshot.metadata, await metadata())) throw new GitPanelError("changed");
|
|
16961
17076
|
};
|
|
@@ -16984,6 +17099,7 @@ async function openRepository(root) {
|
|
|
16984
17099
|
author: commit.author.name,
|
|
16985
17100
|
timestamp: commit.author.timestamp
|
|
16986
17101
|
})) : [];
|
|
17102
|
+
const upstream = await upstreamRelation(branch || void 0, head);
|
|
16987
17103
|
const matrix = await statusMatrix(_objectSpread2(_objectSpread2({}, options), {}, {
|
|
16988
17104
|
cache,
|
|
16989
17105
|
refresh: false,
|
|
@@ -17032,7 +17148,8 @@ async function openRepository(root) {
|
|
|
17032
17148
|
changes,
|
|
17033
17149
|
scope,
|
|
17034
17150
|
metadata: before,
|
|
17035
|
-
probe: fingerprint
|
|
17151
|
+
probe: fingerprint,
|
|
17152
|
+
upstream
|
|
17036
17153
|
};
|
|
17037
17154
|
};
|
|
17038
17155
|
const historyChanges = async (snapshot, oid) => {
|
|
@@ -17170,13 +17287,31 @@ async function openRepository(root) {
|
|
|
17170
17287
|
}));
|
|
17171
17288
|
return blob.byteLength <= limit ? blob : null;
|
|
17172
17289
|
};
|
|
17173
|
-
const
|
|
17290
|
+
const comparisonSource = async (snapshot, comparison, version) => {
|
|
17291
|
+
if (comparison.kind === "worktree") return version === "after" ? { kind: "worktree" } : snapshot.head ? {
|
|
17292
|
+
kind: "tree",
|
|
17293
|
+
ref: snapshot.head
|
|
17294
|
+
} : null;
|
|
17295
|
+
if (version === "after") return {
|
|
17296
|
+
kind: "tree",
|
|
17297
|
+
ref: comparison.commit
|
|
17298
|
+
};
|
|
17299
|
+
const parent = (await readCommit(_objectSpread2(_objectSpread2({}, options), {}, {
|
|
17300
|
+
cache,
|
|
17301
|
+
oid: comparison.commit
|
|
17302
|
+
}))).commit.parent[0];
|
|
17303
|
+
return parent ? {
|
|
17304
|
+
kind: "tree",
|
|
17305
|
+
ref: parent
|
|
17306
|
+
} : null;
|
|
17307
|
+
};
|
|
17308
|
+
const readAsset = (snapshot, change, version, md5ext, signal) => readFolderAsset(snapshot, pathParts(change.path).slice(0, -1), () => sourceOf(snapshot, change, version), md5ext, signal);
|
|
17309
|
+
const readFolderAsset = async (snapshot, folder, resolve, md5ext, signal) => {
|
|
17174
17310
|
if (signal.aborted) return null;
|
|
17175
17311
|
fs.clearReads();
|
|
17176
17312
|
await assertSnapshot(snapshot);
|
|
17177
|
-
const source = await
|
|
17313
|
+
const source = await resolve();
|
|
17178
17314
|
if (!source) return null;
|
|
17179
|
-
const folder = pathParts(change.path).slice(0, -1);
|
|
17180
17315
|
const settings = await readVersion(source, [...folder, "sb3-source.json"].join("/"), folderSettingsLimit);
|
|
17181
17316
|
const directory = assetsDirectoryParts(settings && new TextDecoder().decode(settings));
|
|
17182
17317
|
if (!directory || signal.aborted) return null;
|
|
@@ -17188,6 +17323,43 @@ async function openRepository(root) {
|
|
|
17188
17323
|
await fs.checkReads();
|
|
17189
17324
|
return bytes && !signal.aborted ? new Blob([bytes]) : null;
|
|
17190
17325
|
};
|
|
17326
|
+
/** Reads the project file and the assets directory of both versions of a project folder. */
|
|
17327
|
+
const readProject = async (snapshot, folder, comparison) => {
|
|
17328
|
+
fs.clearReads();
|
|
17329
|
+
await assertSnapshot(snapshot);
|
|
17330
|
+
const parts = pathParts(folder);
|
|
17331
|
+
const read = async (version) => {
|
|
17332
|
+
const source = await comparisonSource(snapshot, comparison, version);
|
|
17333
|
+
if (!source) return {
|
|
17334
|
+
source: null,
|
|
17335
|
+
assetsDirectory: "assets"
|
|
17336
|
+
};
|
|
17337
|
+
const bytes = await readVersion(source, [...parts, "project.source.json"].join("/"), projectSourceLimit);
|
|
17338
|
+
const settings = await readVersion(source, [...parts, "sb3-source.json"].join("/"), folderSettingsLimit);
|
|
17339
|
+
const directory = assetsDirectoryParts(settings && new TextDecoder().decode(settings));
|
|
17340
|
+
let text = null;
|
|
17341
|
+
if (bytes) try {
|
|
17342
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
17343
|
+
} catch (_unused4) {
|
|
17344
|
+
throw new GitPanelError("unsupported");
|
|
17345
|
+
}
|
|
17346
|
+
return {
|
|
17347
|
+
source: text,
|
|
17348
|
+
assetsDirectory: directory ? directory.join("/") : "assets"
|
|
17349
|
+
};
|
|
17350
|
+
};
|
|
17351
|
+
const before = await read("before"), after = await read("after");
|
|
17352
|
+
await assertSnapshot(snapshot);
|
|
17353
|
+
await fs.checkReads();
|
|
17354
|
+
return {
|
|
17355
|
+
before: before.source,
|
|
17356
|
+
after: after.source,
|
|
17357
|
+
assetsDirectory: {
|
|
17358
|
+
before: before.assetsDirectory,
|
|
17359
|
+
after: after.assetsDirectory
|
|
17360
|
+
}
|
|
17361
|
+
};
|
|
17362
|
+
};
|
|
17191
17363
|
const directoryAt = async (path) => {
|
|
17192
17364
|
let directory = root;
|
|
17193
17365
|
for (const part of pathParts(path)) directory = await directory.getDirectoryHandle(part);
|
|
@@ -17274,7 +17446,14 @@ async function openRepository(root) {
|
|
|
17274
17446
|
* commit changes the first parent with the commit. Each version's sb3-source.json names its assets directory.
|
|
17275
17447
|
* Reads never write, and resolve `null` for anything missing, invalid, larger than 10 MiB or changed since the snapshot.
|
|
17276
17448
|
*/
|
|
17277
|
-
assetLoader: (snapshot, change) => ({ version, md5ext, signal }) => !isAssetName(md5ext) || signal.aborted ? Promise.resolve(null) : serial(() => readAsset(snapshot, change, version, md5ext, signal)).catch(() => null)
|
|
17449
|
+
assetLoader: (snapshot, change) => ({ version, md5ext, signal }) => !isAssetName(md5ext) || signal.aborted ? Promise.resolve(null) : serial(() => readAsset(snapshot, change, version, md5ext, signal)).catch(() => null),
|
|
17450
|
+
/**
|
|
17451
|
+
* Reads the project file of a folder in both versions of a comparison, with each version's assets directory.
|
|
17452
|
+
* `null` stands for a version without the file. Throws `changed` when the repository changed since the snapshot.
|
|
17453
|
+
*/
|
|
17454
|
+
readProject: (snapshot, folder, comparison) => serial(() => readProject(snapshot, folder, comparison)),
|
|
17455
|
+
/** Reads the assets of a folder in both versions of a comparison, like `assetLoader`. */
|
|
17456
|
+
projectAssetLoader: (snapshot, folder, comparison) => ({ version, md5ext, signal }) => !isAssetName(md5ext) || signal.aborted ? Promise.resolve(null) : serial(() => readFolderAsset(snapshot, pathParts(folder), () => comparisonSource(snapshot, comparison, version), md5ext, signal)).catch(() => null)
|
|
17278
17457
|
};
|
|
17279
17458
|
}
|
|
17280
|
-
export {
|
|
17459
|
+
export { createReadOnlyFs as i, upstreamWalkLimit as n, GitPanelError as r, openRepository as t };
|
package/dist/repository.d.ts
CHANGED
|
@@ -19,6 +19,16 @@ export interface Commit {
|
|
|
19
19
|
author: string;
|
|
20
20
|
timestamp: number;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Two versions of a project folder as a person sees them: the last commit and the working tree, so changes split
|
|
24
|
+
* across the index and the working tree read as one; or one commit and its first parent.
|
|
25
|
+
*/
|
|
26
|
+
export type ProjectComparison = {
|
|
27
|
+
kind: 'worktree';
|
|
28
|
+
} | {
|
|
29
|
+
kind: 'commit';
|
|
30
|
+
commit: string;
|
|
31
|
+
};
|
|
22
32
|
type Metadata = Map<string, Uint8Array | null>;
|
|
23
33
|
export interface Snapshot {
|
|
24
34
|
branch: string | undefined;
|
|
@@ -30,6 +40,21 @@ export interface Snapshot {
|
|
|
30
40
|
metadata: Metadata;
|
|
31
41
|
/** Size and time fingerprint taken before the read. Compare it with `probe(scope)` to see later changes. */
|
|
32
42
|
probe: string;
|
|
43
|
+
/**
|
|
44
|
+
* How the current branch stands against `refs/remotes/origin/<branch>` as of the last fetch, from local refs only.
|
|
45
|
+
* `unknown` when there is no current branch or no tracking ref yet.
|
|
46
|
+
*/
|
|
47
|
+
upstream: UpstreamRelation;
|
|
48
|
+
}
|
|
49
|
+
export interface UpstreamRelation {
|
|
50
|
+
state: 'same' | 'ahead' | 'behind' | 'diverged' | 'unknown';
|
|
51
|
+
/**
|
|
52
|
+
* Commits on the local branch that the tracking branch lacks, and the reverse. Zero when unknown. Counting reads at
|
|
53
|
+
* most `upstreamWalkLimit` (1000) commits; past that, a side that has commits of its own reports exactly that limit,
|
|
54
|
+
* meaning "this many or more". The state itself comes from the merge base and stays exact.
|
|
55
|
+
*/
|
|
56
|
+
ahead: number;
|
|
57
|
+
behind: number;
|
|
33
58
|
}
|
|
34
59
|
export interface FileDiff {
|
|
35
60
|
binary: boolean;
|
|
@@ -46,6 +71,8 @@ export interface FileDiff {
|
|
|
46
71
|
afterSize: number;
|
|
47
72
|
tooLarge: boolean;
|
|
48
73
|
}
|
|
74
|
+
/** Most commits read to count how far a branch is ahead of or behind its tracking branch. */
|
|
75
|
+
export declare const upstreamWalkLimit = 1000;
|
|
49
76
|
export declare function openRepository(root: FileSystemDirectoryHandle): Promise<{
|
|
50
77
|
root: FileSystemDirectoryHandle;
|
|
51
78
|
openProject: (path: string) => Promise<FileSystemDirectoryHandle>;
|
|
@@ -67,5 +94,19 @@ export declare function openRepository(root: FileSystemDirectoryHandle): Promise
|
|
|
67
94
|
* Reads never write, and resolve `null` for anything missing, invalid, larger than 10 MiB or changed since the snapshot.
|
|
68
95
|
*/
|
|
69
96
|
assetLoader: (snapshot: Snapshot, change: FileChange) => ProjectAssetLoader;
|
|
97
|
+
/**
|
|
98
|
+
* Reads the project file of a folder in both versions of a comparison, with each version's assets directory.
|
|
99
|
+
* `null` stands for a version without the file. Throws `changed` when the repository changed since the snapshot.
|
|
100
|
+
*/
|
|
101
|
+
readProject: (snapshot: Snapshot, folder: string, comparison: ProjectComparison) => Promise<{
|
|
102
|
+
before: string | null;
|
|
103
|
+
after: string | null;
|
|
104
|
+
assetsDirectory: {
|
|
105
|
+
before: string;
|
|
106
|
+
after: string;
|
|
107
|
+
};
|
|
108
|
+
}>;
|
|
109
|
+
/** Reads the assets of a folder in both versions of a comparison, like `assetLoader`. */
|
|
110
|
+
projectAssetLoader: (snapshot: Snapshot, folder: string, comparison: ProjectComparison) => ProjectAssetLoader;
|
|
70
111
|
}>;
|
|
71
112
|
export type Repository = Awaited<ReturnType<typeof openRepository>>;
|
package/dist/repository.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { r as GitPanelError, i as createReadOnlyFs, t as openRepository, n as upstreamWalkLimit } from "./repository-CtvWYPQ8.js";
|