refactor: update syncWikiIfNeeded to use syncOrForcePull

This commit is contained in:
linonetwo 2023-12-31 18:38:05 +08:00
parent 87957c3581
commit 8bf3fcdc1d
6 changed files with 68 additions and 37 deletions

View file

@ -22,6 +22,7 @@ import type { IWikiService } from '@services/wiki/interface';
import type { IWindowService } from '@services/windows/interface';
import { WindowNames } from '@services/windows/WindowProperties';
import { IWorkspace } from '@services/workspaces/interface';
import { ObservablePromise } from 'threads/dist/observable-promise';
import { GitWorker } from './gitWorker';
import { ICommitAndSyncConfigs, IForcePullConfigs, IGitLogMessage, IGitService, IGitUserInfos } from './interface';
import { getErrorMessageI18NDict, translateMessage } from './translateMessage';
@ -71,7 +72,7 @@ export class Git implements IGitService {
}
/**
* Update in-wiki settings for git.
* Update in-wiki settings for git. Only needed if the wiki is config to synced.
* @param {string} remoteUrl
*/
private async updateGitInfoTiddler(workspace: IWorkspace, remoteUrl?: string, branch?: string): Promise<void> {
@ -177,7 +178,7 @@ export class Git implements IGitService {
});
}
public async commitAndSync(workspace: IWorkspace, config: ICommitAndSyncConfigs): Promise<boolean> {
public async commitAndSync(workspace: IWorkspace, configs: ICommitAndSyncConfigs): Promise<boolean> {
if (!net.isOnline()) {
// If not online, will not have any change
return false;
@ -185,37 +186,55 @@ export class Git implements IGitService {
const workspaceIDToShowNotification = workspace.isSubWiki ? workspace.mainWikiID! : workspace.id;
try {
try {
await this.updateGitInfoTiddler(workspace, config.remoteUrl, config.userInfo?.branch);
await this.updateGitInfoTiddler(workspace, configs.remoteUrl, configs.userInfo?.branch);
} catch (error) {
logger.error('updateGitInfoTiddler failed when commitAndSync', error);
}
// return the `hasChanges` result.
return await new Promise<boolean>((resolve, reject) => {
const observable = this.gitWorker?.commitAndSyncWiki(workspace, config, getErrorMessageI18NDict());
observable?.subscribe(this.getWorkerMessageObserver(workspace.wikiFolderLocation, () => {}, reject, workspaceIDToShowNotification));
let hasChanges = false;
observable?.subscribe({
next: (messageObject) => {
if (messageObject.level === 'error') {
return;
}
const { meta } = messageObject;
if (typeof meta === 'object' && meta !== null && 'step' in meta && stepsAboutChange.includes((meta as { step: GitStep }).step)) {
hasChanges = true;
}
},
complete: () => {
resolve(hasChanges);
},
});
return true;
});
const observable = this.gitWorker?.commitAndSyncWiki(workspace, configs, getErrorMessageI18NDict());
return await this.getHasChangeHandler(observable, workspace.wikiFolderLocation, workspaceIDToShowNotification);
} catch (error) {
this.createFailedNotification((error as Error).message, workspaceIDToShowNotification);
return true;
}
}
public async forcePull(workspace: IWorkspace, configs: IForcePullConfigs): Promise<boolean> {
if (!net.isOnline()) {
return false;
}
const workspaceIDToShowNotification = workspace.isSubWiki ? workspace.mainWikiID! : workspace.id;
const observable = this.gitWorker?.forcePullWiki(workspace, configs, getErrorMessageI18NDict());
return await this.getHasChangeHandler(observable, workspace.wikiFolderLocation, workspaceIDToShowNotification);
}
/**
* Handle methods that checks if there is any change. Return a promise that resolves to a "hasChanges" boolean, resolve on the observable completes.
* @param observable return by `this.gitWorker`'s methods.
* @returns the `hasChanges` result.
*/
private async getHasChangeHandler(observable: ObservablePromise<IGitLogMessage> | undefined, wikiFolderPath: string, workspaceID?: string | undefined) {
// return the `hasChanges` result.
return await new Promise<boolean>((resolve, reject) => {
observable?.subscribe(this.getWorkerMessageObserver(wikiFolderPath, () => {}, reject, workspaceID));
let hasChanges = false;
observable?.subscribe({
next: (messageObject) => {
if (messageObject.level === 'error') {
return;
}
const { meta } = messageObject;
if (typeof meta === 'object' && meta !== null && 'step' in meta && stepsAboutChange.includes((meta as { step: GitStep }).step)) {
hasChanges = true;
}
},
complete: () => {
resolve(hasChanges);
},
});
return true;
});
}
public async clone(remoteUrl: string, repoFolderPath: string, userInfo: IGitUserInfos): Promise<void> {
if (!net.isOnline()) {
return;
@ -225,14 +244,12 @@ export class Git implements IGitService {
});
}
public async forcePull(workspace: IWorkspace, configs: IForcePullConfigs): Promise<void> {
if (!net.isOnline()) {
return;
public async syncOrForcePull(workspace: IWorkspace, configs: IForcePullConfigs & ICommitAndSyncConfigs): Promise<boolean> {
// if local is in readonly mode, any things that write to local (by accident) should be completely overwrite by remote.
if (workspace.readOnlyMode) {
return await this.forcePull(workspace, configs);
} else {
return await this.commitAndSync(workspace, configs);
}
await new Promise<void>((resolve, reject) => {
this.gitWorker?.forcePullWiki(workspace, configs, getErrorMessageI18NDict()).subscribe(
this.getWorkerMessageObserver(workspace.wikiFolderLocation, resolve, reject, workspace.id),
);
});
}
}

View file

@ -47,11 +47,11 @@ export interface IGitService {
/**
* Return true if this function's execution causes local changes. Return false if is only push or nothing changed.
*/
commitAndSync(workspace: IWorkspace, config: ICommitAndSyncConfigs): Promise<boolean>;
commitAndSync(workspace: IWorkspace, configs: ICommitAndSyncConfigs): Promise<boolean>;
/**
* Ignore all local changes, force reset local to remote.
*/
forcePull(workspace: IWorkspace, configs: IForcePullConfigs): Promise<void>;
forcePull(workspace: IWorkspace, configs: IForcePullConfigs): Promise<boolean>;
getModifiedFileList(wikiFolderPath: string): Promise<ModifiedFileList[]>;
/** Inspect git's remote url from folder's .git config, return undefined if there is no initialized git */
getWorkspacesRemote(wikiFolderPath?: string): Promise<string | undefined>;
@ -60,6 +60,12 @@ export interface IGitService {
*/
initWikiGit(wikiFolderPath: string, isSyncedWiki: true, isMainWiki: boolean, remoteUrl: string, userInfo: IGitUserInfos): Promise<void>;
initWikiGit(wikiFolderPath: string, isSyncedWiki?: false): Promise<void>;
/**
* Decide to use forcePull or commitAndSync according to workspace's `readOnlyMode` setting.
*
* This does not handle `commitOnly` option, if it is not readonly. You need to use `commitAndSync` directly.
*/
syncOrForcePull(workspace: IWorkspace, configs: IForcePullConfigs & ICommitAndSyncConfigs): Promise<boolean>;
}
export const GitServiceIPCDescriptor = {
channel: GitChannel.name,
@ -70,5 +76,6 @@ export const GitServiceIPCDescriptor = {
getModifiedFileList: ProxyPropertyType.Function,
getWorkspacesRemote: ProxyPropertyType.Function,
initWikiGit: ProxyPropertyType.Function,
syncOrForcePull: ProxyPropertyType.Function,
},
};

View file

@ -599,7 +599,7 @@ export class Wiki implements IWikiService {
/**
* Trigger git sync
* Simply do some check before calling `gitService.commitAndSync`
* Simply do some check before calling `gitService.syncOrForcePull`
*/
private async syncWikiIfNeeded(workspace: IWorkspace): Promise<void> {
const { gitUrl: githubRepoUrl, storageService, backupOnInterval, id } = workspace;
@ -633,13 +633,13 @@ export class Wiki implements IWikiService {
userInfo !== undefined &&
(await checkCanSyncDueToNoDraft())
) {
const hasChanges = await this.gitService.commitAndSync(workspace, { remoteUrl: githubRepoUrl, userInfo });
const hasChanges = await this.gitService.syncOrForcePull(workspace, { remoteUrl: githubRepoUrl, userInfo });
if (hasChanges) {
await this.workspaceViewService.restartWorkspaceViewService(id);
await this.viewService.reloadViewsWebContents(id);
}
} else if (backupOnInterval && (await checkCanSyncDueToNoDraft())) {
// for local workspace, commitOnly
// for local workspace, commitOnly, no sync and no force pull.
await this.gitService.commitAndSync(workspace, { commitOnly: true });
}
}

View file

@ -58,8 +58,13 @@ export class WikiGitWorkspace implements IWikiGitWorkspaceService {
await Promise.allSettled([
this.notificationService.show({ title: i18n.t('Preference.SyncBeforeShutdown') }),
...workspacesToSync.map(async (workspace) => {
// only do this if not readonly
if (workspace.readOnlyMode) {
return;
}
const userInfo = await this.authService.getStorageServiceUserInfo(workspace.storageService);
if (userInfo !== undefined && workspace.gitUrl !== null) {
// TODO: use syncWikiIfNeeded
await this.gitService.commitAndSync(workspace, { remoteUrl: workspace.gitUrl, userInfo });
}
}),

View file

@ -131,6 +131,7 @@ export async function getWorkspaceMenuTemplate(
enabled: isOnline,
click: async () => {
if (isSubWiki) {
// TODO: use syncWikiIfNeeded
const hasChanges = await service.git.commitAndSync(workspace, { remoteUrl: gitUrl, userInfo });
if (hasChanges) {
if (mainWikiID === null) {

View file

@ -140,6 +140,7 @@ export class WorkspaceView implements IWorkspaceViewService {
});
} else {
// sync in non-blocking way
// TODO: use syncWikiIfNeeded
void this.gitService.commitAndSync(workspace, { remoteUrl: githubRepoUrl, userInfo }).then(async (hasChanges) => {
if (hasChanges) {
await this.workspaceViewService.restartWorkspaceViewService(workspace.id);