Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
JoanVicens committed Mar 26, 2024
1 parent f9f753a commit 069cb8b
Show file tree
Hide file tree
Showing 17 changed files with 188 additions and 24 deletions.
15 changes: 12 additions & 3 deletions src/apps/fuse/FuseApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ReleaseCallback } from './callbacks/ReleaseCallback';
import { FuseDependencyContainer } from './dependency-injection/FuseDependencyContainer';
import { ensureFolderExists } from './../shared/fs/ensure-folder-exists';
import { mountPromise, unmountFusedDirectory, unmountPromise } from './helpers';
import { ChownCallback } from './callbacks/ChownCallback';

// eslint-disable-next-line @typescript-eslint/no-var-requires
const fuse = require('@gcas/fuse');
Expand All @@ -31,13 +32,17 @@ export class FuseApp {

private async getOpt() {
const readdir = new ReaddirCallback(
this.fuseContainer.virtualDriveContainer
this.fuseContainer.virtualDriveContainer,
this.fuseContainer.offlineDriveContainer
);
const getattr = new GetAttributesCallback(
this.fuseContainer.virtualDriveContainer,
this.fuseContainer.offlineDriveContainer
);
const open = new OpenCallback(this.fuseContainer.virtualDriveContainer);
const open = new OpenCallback(
this.fuseContainer.virtualDriveContainer,
this.fuseContainer.offlineDriveContainer
);
const read = new ReadCallback(
this.fuseContainer.virtualDriveContainer,
this.fuseContainer.offlineDriveContainer
Expand All @@ -51,7 +56,8 @@ export class FuseApp {
this.fuseContainer.virtualDriveContainer
);
const trashFile = new TrashFileCallback(
this.fuseContainer.virtualDriveContainer
this.fuseContainer.virtualDriveContainer,
this.fuseContainer.offlineDriveContainer
);
const trashFolder = new TrashFolderCallback(
this.fuseContainer.virtualDriveContainer
Expand All @@ -62,6 +68,8 @@ export class FuseApp {
this.fuseContainer.virtualDriveContainer
);

const chown = new ChownCallback();

return {
getattr: getattr.handle.bind(getattr),
readdir: readdir.handle.bind(readdir),
Expand All @@ -74,6 +82,7 @@ export class FuseApp {
release: release.handle.bind(release),
unlink: trashFile.handle.bind(trashFile),
rmdir: trashFolder.handle.bind(trashFolder),
chown: chown.handle.bind(chown),
};
}

Expand Down
11 changes: 11 additions & 0 deletions src/apps/fuse/callbacks/ChownCallback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { NotifyFuseCallback } from './FuseCallback';

export class ChownCallback extends NotifyFuseCallback {
constructor() {
super('Chown', { input: true, output: true });
}

async execute(path: string, uid: number, gid: number) {
return this.right();
}
}
2 changes: 1 addition & 1 deletion src/apps/fuse/callbacks/CreateCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { NotifyFuseCallback } from './FuseCallback';

export class CreateCallback extends NotifyFuseCallback {
constructor(private readonly container: OfflineDriveDependencyContainer) {
super('Create');
super('Create', { input: true, output: true });
}

async execute(path: string, _mode: number) {
Expand Down
10 changes: 10 additions & 0 deletions src/apps/fuse/callbacks/GetAttributesCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ type GetAttributesCallbackData = {
mtime: Date;
ctime: Date;
atime?: Date;
uid: number;
gid: number;
};

export class GetAttributesCallback extends FuseCallback<GetAttributesCallbackData> {
Expand Down Expand Up @@ -42,6 +44,8 @@ export class GetAttributesCallback extends FuseCallback<GetAttributesCallbackDat
mtime: new Date(),
ctime: new Date(),
atime: undefined,
uid: process.getuid(),
gid: process.getgid(),
});
}

Expand All @@ -57,6 +61,8 @@ export class GetAttributesCallback extends FuseCallback<GetAttributesCallbackDat
ctime: file.createdAt,
mtime: file.updatedAt,
atime: new Date(),
uid: process.getuid(),
gid: process.getgid(),
});
}

Expand All @@ -72,6 +78,8 @@ export class GetAttributesCallback extends FuseCallback<GetAttributesCallbackDat
ctime: folder.createdAt,
mtime: folder.updatedAt,
atime: folder.createdAt,
uid: process.getuid(),
gid: process.getgid(),
});
}

Expand All @@ -85,6 +93,8 @@ export class GetAttributesCallback extends FuseCallback<GetAttributesCallbackDat
mtime: new Date(),
ctime: offlineFile.createdAt,
atime: offlineFile.createdAt,
uid: process.getuid(),
gid: process.getgid(),
});
}

Expand Down
45 changes: 39 additions & 6 deletions src/apps/fuse/callbacks/OpenCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,56 @@ import { VirtualDriveDependencyContainer } from '../dependency-injection/virtual
import Logger from 'electron-log';
import { FuseCallback } from './FuseCallback';
import { FuseIOError, FuseNoSuchFileOrDirectoryError } from './FuseErrors';
import { OfflineDriveDependencyContainer } from '../dependency-injection/offline/OfflineDriveDependencyContainer';

export class OpenCallback extends FuseCallback<number> {
constructor(private readonly container: VirtualDriveDependencyContainer) {
super('Open');
private readonly fileDescriptors = new Map<string, number>();
private lastFileDescriptor = 0;

constructor(
private readonly virtual: VirtualDriveDependencyContainer,
private readonly offline: OfflineDriveDependencyContainer
) {
super('Open', { input: true, output: true });
}

private nextFileDescriptor(): number {
const next = this.lastFileDescriptor + 1;
this.lastFileDescriptor = next;

return next;
}

private getFileDescriptor(path: string): number {
const fileDescriptor = this.fileDescriptors.get(path);

if (fileDescriptor) {
return fileDescriptor;
}

const nextFileDescriptor = this.nextFileDescriptor();

this.fileDescriptors.set(path, nextFileDescriptor);

return nextFileDescriptor;
}

async execute(path: string, _flags: Array<any>) {
const file = await this.container.filesSearcher.run({ path });
const virtual = await this.virtual.filesSearcher.run({ path });

if (!file) {
if (!virtual) {
const offline = await this.offline.offlineFileSearcher.run({ path });
if (offline) {
const fileDescriptor = this.getFileDescriptor(path);
return this.right(fileDescriptor);
}
return this.left(new FuseNoSuchFileOrDirectoryError(path));
}

try {
await this.container.downloadContentsToPlainFile.run(file);
await this.virtual.downloadContentsToPlainFile.run(virtual);

return this.right(file.id);
return this.right(virtual.id);
} catch (err: unknown) {
Logger.error('Error downloading file: ', err);
if (err instanceof Error) {
Expand Down
25 changes: 20 additions & 5 deletions src/apps/fuse/callbacks/ReaddirCallback.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,38 @@
import { OfflineDriveDependencyContainer } from '../dependency-injection/offline/OfflineDriveDependencyContainer';
import { VirtualDriveDependencyContainer } from '../dependency-injection/virtual-drive/VirtualDriveDependencyContainer';
import { FuseCallback } from './FuseCallback';

export class ReaddirCallback extends FuseCallback<Array<string>> {
constructor(private readonly container: VirtualDriveDependencyContainer) {
constructor(
private readonly virtual: VirtualDriveDependencyContainer,
private readonly offline: OfflineDriveDependencyContainer
) {
super('Read Directory');
}

async execute(path: string) {
const filesNamesPromise =
this.container.filesByFolderPathNameLister.run(path);
this.virtual.filesByFolderPathNameLister.run(path);

const folderNamesPromise =
this.container.foldersByParentPathLister.run(path);
const folderNamesPromise = this.virtual.foldersByParentPathLister.run(path);

const offlineFiles = await this.offline.offlineFilesByParentPathLister.run(
path
);

const offlineFilesNames = offlineFiles.map((file) => file.name);

const [filesNames, foldersNames] = await Promise.all([
filesNamesPromise,
folderNamesPromise,
]);

return this.right(['.', '..', ...filesNames, ...foldersNames]);
return this.right([
'.',
'..',
...filesNames,
...foldersNames,
...offlineFilesNames,
]);
}
}
16 changes: 15 additions & 1 deletion src/apps/fuse/callbacks/ReleaseCallback.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
import { basename, extname } from 'path';
import { OfflineDriveDependencyContainer } from '../dependency-injection/offline/OfflineDriveDependencyContainer';
import { VirtualDriveDependencyContainer } from '../dependency-injection/virtual-drive/VirtualDriveDependencyContainer';
import { NotifyFuseCallback } from './FuseCallback';
import Logger from 'electron-log';

export class ReleaseCallback extends NotifyFuseCallback {
constructor(
private readonly offlineDrive: OfflineDriveDependencyContainer,
private readonly virtualDrive: VirtualDriveDependencyContainer
) {
super('Release');
super('Release', { input: true, output: true });
}

async execute(path: string, _fd: number) {
const name = basename(path);
if (name.startsWith('.~lock.')) {
Logger.debug('Ignoring .lock file', path);
return this.right();
}

const extension = extname(path);
if (extension === '.tmp') {
Logger.debug('Ignoring .tmp file', path);
return this.right();
}

const offlineFile = await this.offlineDrive.offlineFileSearcher.run({
path,
});
Expand Down
2 changes: 1 addition & 1 deletion src/apps/fuse/callbacks/RenameOrMoveCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class RenameOrMoveCallback extends NotifyFuseCallback {
virtual: VirtualDriveDependencyContainer,
offline: OfflineDriveDependencyContainer
) {
super('Rename Or Move');
super('Rename Or Move', { input: true, output: true });

this.updateFile = new RenameOrMoveFile(virtual);
this.updateFolder = new RenameOrMoveFolder(virtual);
Expand Down
22 changes: 17 additions & 5 deletions src/apps/fuse/callbacks/TrashFileCallback.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@
import { FileStatuses } from '../../../context/virtual-drive/files/domain/FileStatus';
import { OfflineDriveDependencyContainer } from '../dependency-injection/offline/OfflineDriveDependencyContainer';
import { VirtualDriveDependencyContainer } from '../dependency-injection/virtual-drive/VirtualDriveDependencyContainer';
import { NotifyFuseCallback } from './FuseCallback';
import { FuseIOError, FuseNoSuchFileOrDirectoryError } from './FuseErrors';

export class TrashFileCallback extends NotifyFuseCallback {
constructor(private readonly container: VirtualDriveDependencyContainer) {
super('Trash file');
constructor(
private readonly virtual: VirtualDriveDependencyContainer,
private readonly offline: OfflineDriveDependencyContainer
) {
super('Trash file', { input: true, output: true });
}

async execute(path: string) {
const file = await this.container.filesSearcher.run({
const file = await this.virtual.filesSearcher.run({
path,
status: FileStatuses.EXISTS,
});

if (!file) {
return this.left(new FuseNoSuchFileOrDirectoryError(path));
const offline = await this.offline.offlineFileSearcher.run({
path,
});

if (!offline) {
return this.left(new FuseNoSuchFileOrDirectoryError(path));
}

return this.right();
}

try {
await this.container.fileDeleter.run(file.contentsId);
await this.virtual.fileDeleter.run(file.contentsId);

return this.right();
} catch {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ClearOfflineFileOnFileCreated } from '../../../../../context/offline-drive/files/application/ClearOfflineFileOnFileCreated';
import { OfflineFileCreator } from '../../../../../context/offline-drive/files/application/OfflineFileCreator';
import { OfflineFileFinder } from '../../../../../context/offline-drive/files/application/OfflineFileFinder';
import { OfflineFilesByParentPathLister } from '../../../../../context/offline-drive/files/application/OfflineFileListerByParentFolder';
import { OfflineFileSearcher } from '../../../../../context/offline-drive/files/application/OfflineFileSearcher';
import { OfflineFileSizeIncreaser } from '../../../../../context/offline-drive/files/application/OfflineFileSizeIncreaser';

Expand All @@ -10,4 +11,5 @@ export interface OfflineFilesContainer {
offlineFileFinder: OfflineFileFinder;
offlineFileSizeIncreaser: OfflineFileSizeIncreaser;
clearOfflineFileOnFileCreated: ClearOfflineFileOnFileCreated;
offlineFilesByParentPathLister: OfflineFilesByParentPathLister;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { OfflineFileCreator } from '../../../../../context/offline-drive/files/a
import { DependencyInjectionEventBus } from '../../common/eventBus';
import { ClearOfflineFileOnFileCreated } from '../../../../../context/offline-drive/files/application/ClearOfflineFileOnFileCreated';
import { OfflineFileDeleter } from '../../../../../context/offline-drive/files/application/OfflineFileDeleter';
import { OfflineFilesByParentPathLister } from '../../../../../context/offline-drive/files/application/OfflineFileListerByParentFolder';

export async function buildOfflineFilesContainer(): Promise<OfflineFilesContainer> {
const { bus: eventBus } = DependencyInjectionEventBus;
Expand All @@ -23,6 +24,10 @@ export async function buildOfflineFilesContainer(): Promise<OfflineFilesContaine

const offlineFileDeleter = new OfflineFileDeleter(repository);

const offlineFilesByParentPathLister = new OfflineFilesByParentPathLister(
repository
);

// Event Listeners
const clearOfflineFileOnFileCreated = new ClearOfflineFileOnFileCreated(
offlineFileDeleter
Expand All @@ -33,6 +38,9 @@ export async function buildOfflineFilesContainer(): Promise<OfflineFilesContaine
offlineFileSearcher,
offlineFileFinder,
offlineFileSizeIncreaser,
offlineFilesByParentPathLister,

// Event Listeners
clearOfflineFileOnFileCreated,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { EnvironmentOfflineContentsUploader } from './EnvironmentOfflineContents
import { OfflineContents } from '../domain/OfflineContents';
import { UploadProgressTracker } from '../../../shared/domain/UploadProgressTracker';
import { Readable } from 'stream';
import Logger from 'electron-log';

export class EnvironmentOfflineContentsManagersFactory
implements OfflineContentsManagersFactory
Expand Down Expand Up @@ -54,8 +55,9 @@ export class EnvironmentOfflineContentsManagersFactory
});
});

uploader.on('error', (_error: Error) => {
uploader.on('error', (error: Error) => {
// TODO: use error to determine the cause
Logger.debug('UPLOADER ERROR', error);
this.progressTracker.uploadError(name, extension, 'UNKNOWN');
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { dirname } from 'path';
import { OfflineFile } from '../domain/OfflineFile';
import { OfflineFileRepository } from '../domain/OfflineFileRepository';

export class OfflineFilesByParentPathLister {
constructor(private readonly repository: OfflineFileRepository) {}

async run(path: string): Promise<Array<OfflineFile>> {
const parentPath = dirname(path);

const all = await this.repository.all();

return all.filter((file) => file.path.dirname() === parentPath);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ export interface OfflineFileRepository {
): Promise<OfflineFile | undefined>;

delete(id: OfflineFile['id']): Promise<void>;

all(): Promise<Array<OfflineFile>>;
}
Loading

0 comments on commit 069cb8b

Please sign in to comment.