fix(git-backend): reload on publish

This commit is contained in:
Denys Konovalov 2024-12-28 16:09:27 +01:00
parent 6c77032636
commit 6750272521
Signed by: Denys Konovalov
GPG Key ID: 0037E1B0E33BD2C9
3 changed files with 81 additions and 62 deletions

View File

@ -635,8 +635,8 @@ export function loadEntry(collection: CollectionWithDefaults, slug: string, sile
try { try {
await dispatch(loadMedia()); await dispatch(loadMedia());
const loadedEntry = await tryLoadEntry(getState(), collection, slug); const loadedEntry = await tryLoadEntry(getState(), collection, slug);
dispatch(entryLoaded(collection, loadedEntry));
dispatch(createDraftFromEntry(collection, loadedEntry)); dispatch(createDraftFromEntry(collection, loadedEntry));
dispatch(entryLoaded(collection, loadedEntry));
} catch (error: unknown) { } catch (error: unknown) {
console.error(error); console.error(error);
if (error instanceof Error) { if (error instanceof Error) {
@ -668,7 +668,7 @@ export async function tryLoadEntry(
} }
const backend = currentBackend(configState.config); const backend = currentBackend(configState.config);
return backend.getEntry(state, collection, configState.config, slug); return await backend.getEntry(state, collection, configState.config, slug);
} }
interface AppendAction { interface AppendAction {

View File

@ -2,25 +2,28 @@ import FS from '@isomorphic-git/lightning-fs';
import * as git from 'isomorphic-git'; import * as git from 'isomorphic-git';
import http from 'isomorphic-git/http/web'; import http from 'isomorphic-git/http/web';
import type { WorkflowStatus } from '@staticcms/core/constants/publishModes'; import {
import type { AssetProxy } from '@staticcms/core/valueObjects'; asyncLock,
import type { runWithLock,
Backend, type AsyncLock,
BackendClass, type Backend,
BackendEntry, type BackendClass,
Config, type BackendEntry,
ConfigWithDefaults, type Config,
Credentials, type ConfigWithDefaults,
Cursor, type Credentials,
DisplayURL, type Cursor,
ImplementationEntry, type DisplayURL,
ImplementationFile, type ImplementationEntry,
PersistOptions, type ImplementationFile,
User, type PersistOptions,
type User,
} from '@staticcms/core'; } from '@staticcms/core';
import type { WorkflowStatus } from '@staticcms/core/constants/publishModes';
import type { AssetProxy } from '@staticcms/core/valueObjects';
const dir = '/repo'; const dir = '/repo';
let singleton: Promise<string[]>;
function determineRepositoryURL(backend: Backend): string { function determineRepositoryURL(backend: Backend): string {
const name = backend.name; const name = backend.name;
@ -50,7 +53,8 @@ export default function GitProxyBackEndGenerator(
fs: FS; fs: FS;
pfs: FS.PromisifiedFS; pfs: FS.PromisifiedFS;
repositoryUrl: string; repositoryUrl: string;
repository: Promise<string[]>; lock: AsyncLock;
sha: string;
constructor(config: ConfigWithDefaults, options = {}) { constructor(config: ConfigWithDefaults, options = {}) {
this.backend = new T(config, options); this.backend = new T(config, options);
@ -58,13 +62,14 @@ export default function GitProxyBackEndGenerator(
this.fs = new FS('decapfs'); this.fs = new FS('decapfs');
this.pfs = this.fs.promises; this.pfs = this.fs.promises;
this.repositoryUrl = determineRepositoryURL(config.backend); this.repositoryUrl = determineRepositoryURL(config.backend);
if (!singleton) { this.lock = asyncLock();
singleton = this.getRepository(); this.sha = '';
}
this.repository = singleton;
} }
async getRepository() { async getRepository() {
return await runWithLock(
this.lock,
async () => {
const branch = this.config.backend.branch || 'main'; const branch = this.config.backend.branch || 'main';
try { try {
await this.pfs.stat(dir); await this.pfs.stat(dir);
@ -83,6 +88,7 @@ export default function GitProxyBackEndGenerator(
remote: 'origin', remote: 'origin',
force: true, force: true,
}); });
console.log('Fetching repo...');
await git.fetch({ await git.fetch({
fs: this.fs, fs: this.fs,
http, http,
@ -91,15 +97,28 @@ export default function GitProxyBackEndGenerator(
ref: branch, ref: branch,
singleBranch: true, singleBranch: true,
depth: 1, depth: 1,
onMessage: message => console.log(message),
}); });
const newSHA = await git.resolveRef({ fs: this.fs, dir, ref: `origin/${branch}` });
console.log(`Current SHA: ${this.sha}, new SHA: ${newSHA}`);
if (this.sha !== newSHA) {
console.log('Run checkout...');
await git.checkout({ await git.checkout({
fs: this.fs, fs: this.fs,
dir, dir,
ref: branch, ref: `origin/${branch}`,
noUpdateHead: false,
force: true, force: true,
track: false, track: false,
onPostCheckout: post => {
this.sha = post.newHead;
console.log(`New HEAD: ${post.newHead}`);
},
}); });
return this.pfs.readdir(dir); }
},
'Failed to get async lock',
);
} }
isGitBackend() { isGitBackend() {
@ -108,7 +127,7 @@ export default function GitProxyBackEndGenerator(
async entriesByFolder(folder: string, extension: string) { async entriesByFolder(folder: string, extension: string) {
try { try {
await this.repository; await this.getRepository();
const files = await this.pfs.readdir(`${dir}/${folder}`); const files = await this.pfs.readdir(`${dir}/${folder}`);
const relevantFiles = files.filter((name: string) => name.endsWith(extension)); const relevantFiles = files.filter((name: string) => name.endsWith(extension));
return Promise.all( return Promise.all(
@ -130,7 +149,7 @@ export default function GitProxyBackEndGenerator(
} }
} }
async getEntry(path: string) { async getEntry(path: string) {
await this.repository; await this.getRepository();
let data = await this.pfs.readFile(`${dir}/${path}`, 'utf8'); let data = await this.pfs.readFile(`${dir}/${path}`, 'utf8');
if (data instanceof Uint8Array) { if (data instanceof Uint8Array) {
data = new TextDecoder().decode(data); data = new TextDecoder().decode(data);

View File

@ -105,10 +105,10 @@ const MediaLibraryCard: FC<MediaLibraryCardProps> = ({
}, [displayURL.url, text]); }, [displayURL.url, text]);
useEffect(() => { useEffect(() => {
if (!displayURL.url) { if (!isDirectory && !displayURL.url) {
loadDisplayURL(); loadDisplayURL();
} }
}, [displayURL.url, loadDisplayURL]); }, [displayURL.url, loadDisplayURL, isDirectory]);
const shortenedText = useMemo( const shortenedText = useMemo(
() => () =>