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,48 +62,63 @@ 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() {
const branch = this.config.backend.branch || 'main'; return await runWithLock(
try { this.lock,
await this.pfs.stat(dir); async () => {
} catch (e) { const branch = this.config.backend.branch || 'main';
await this.pfs.mkdir(dir); try {
await git.init({ await this.pfs.stat(dir);
fs: this.fs, } catch (e) {
dir, await this.pfs.mkdir(dir);
defaultBranch: branch, await git.init({
}); fs: this.fs,
} dir,
await git.addRemote({ defaultBranch: branch,
fs: this.fs, });
dir, }
url: this.repositoryUrl, await git.addRemote({
remote: 'origin', fs: this.fs,
force: true, dir,
}); url: this.repositoryUrl,
await git.fetch({ remote: 'origin',
fs: this.fs, force: true,
http, });
dir, console.log('Fetching repo...');
remote: 'origin', await git.fetch({
ref: branch, fs: this.fs,
singleBranch: true, http,
depth: 1, dir,
}); remote: 'origin',
await git.checkout({ ref: branch,
fs: this.fs, singleBranch: true,
dir, depth: 1,
ref: branch, onMessage: message => console.log(message),
force: true, });
track: false, const newSHA = await git.resolveRef({ fs: this.fs, dir, ref: `origin/${branch}` });
}); console.log(`Current SHA: ${this.sha}, new SHA: ${newSHA}`);
return this.pfs.readdir(dir); if (this.sha !== newSHA) {
console.log('Run checkout...');
await git.checkout({
fs: this.fs,
dir,
ref: `origin/${branch}`,
noUpdateHead: false,
force: true,
track: false,
onPostCheckout: post => {
this.sha = post.newHead;
console.log(`New HEAD: ${post.newHead}`);
},
});
}
},
'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(
() => () =>