Skip to content

Commit 633381c

Browse files
committed
Fix: fixed issues with copying files and overriding
1 parent 097d232 commit 633381c

File tree

8 files changed

+64
-48
lines changed

8 files changed

+64
-48
lines changed

src/commands/solid-copy.ts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import fs from 'fs'
22
import path from 'path'
33
import { getFile, getContentType, createContainerAt } from "@inrupt/solid-client"
4-
import { isRemote, isDirectory, FileInfo, ensureDirectoryExistence, fixLocalPath, readRemoteDirectoryRecursively, checkRemoteFileExists, writeErrorString, isDirectoryContents } from '../utils/util';
4+
import { isRemote, isDirectory, FileInfo, ensureDirectoryExistence, fixLocalPath, readRemoteDirectoryRecursively, checkRemoteFileExists, writeErrorString, isDirectoryContents, resourceExists } from '../utils/util';
55
import Blob from 'fetch-blob'
6-
import { requestUserCLIConfirmation } from '../utils/userInteractions';
6+
import { requestUserCLIConfirmationDefaultNegative } from '../utils/userInteractions';
77
import BashlibError from '../utils/errors/BashlibError';
88
import { BashlibErrorMessage } from '../utils/errors/BashlibError';
99
import type { Logger } from '../logger';
1010
import { ICommandOptions, setOptionDefaults } from './solid-command';
11-
import { resourceExists } from './solid-touch';
1211

1312
const mime = require('mime-types');
1413

@@ -23,8 +22,8 @@ interface SourceOptions {
2322

2423
export interface ICommandOptionsCopy extends ICommandOptions {
2524
all?: boolean,
26-
interactiveOverride?: boolean,
27-
noOverride?: boolean,
25+
override?: boolean,
26+
neverOverride?: boolean,
2827
}
2928

3029
export default async function copy(src: string, dst: string, options?: ICommandOptionsCopy) : Promise<{
@@ -34,8 +33,8 @@ export default async function copy(src: string, dst: string, options?: ICommandO
3433
let commandOptions = setOptionDefaults<ICommandOptionsCopy>(options || {});
3534
let fetch = commandOptions.fetch;
3635
commandOptions.all = commandOptions.all || false;
37-
commandOptions.interactiveOverride = commandOptions.interactiveOverride || false;
38-
commandOptions.noOverride = commandOptions.noOverride || false;
36+
commandOptions.override = commandOptions.override || false;
37+
commandOptions.neverOverride = commandOptions.neverOverride || false;
3938

4039
/**************************
4140
* Preprocess src and dst *
@@ -277,12 +276,12 @@ async function writeLocalFile(resourcePath: string, fileInfo: FileInfo, options:
277276
ensureDirectoryExistence(resourcePath);
278277

279278
let executeWrite = true
280-
if (options.interactiveOverride || options.noOverride) {
281-
if (fs.existsSync(resourcePath)) {
282-
if (options.noOverride) {
279+
if (options.neverOverride || !options.override) {
280+
if (await resourceExists(resourcePath, options.fetch)) {
281+
if (options.neverOverride) {
283282
executeWrite = false;
284-
} else if (options.interactiveOverride) {
285-
executeWrite = await requestUserCLIConfirmation(`Overwrite local file: ${resourcePath}`)
283+
} else {
284+
executeWrite = await requestUserCLIConfirmationDefaultNegative(`Overwrite local file: ${resourcePath}`)
286285
}
287286
}
288287
}
@@ -309,6 +308,7 @@ async function writeLocalFile(resourcePath: string, fileInfo: FileInfo, options:
309308

310309
if (fileData.buffer) {
311310
fs.writeFileSync(resourcePath, fileData.buffer)
311+
if (options.verbose) (options.logger || console).log(`Writing local resource: ${resourcePath}`);
312312
} else if (fileData.blob) {
313313
let buffer = Buffer.from(await fileData.blob.arrayBuffer())
314314
fs.writeFileSync(resourcePath, buffer)
@@ -324,17 +324,17 @@ async function writeLocalFile(resourcePath: string, fileInfo: FileInfo, options:
324324

325325
async function writeRemoteFile(resourcePath: string, fileInfo: FileInfo, fetch: any, options: ICommandOptionsCopy): Promise<string | undefined> {
326326
resourcePath = resourcePath.split('$.')[0];
327-
328327
let executeWrite = true
329-
if (options.interactiveOverride || options.noOverride) {
328+
if (options.neverOverride || !options.override) {
330329
if (await resourceExists(resourcePath, fetch)) {
331-
if (options.noOverride) {
330+
if (options.neverOverride) {
332331
executeWrite = false;
333-
} else if (options.interactiveOverride) {
334-
executeWrite = await requestUserCLIConfirmation(`Overwrite local file: ${resourcePath}`)
332+
} else {
333+
executeWrite = await requestUserCLIConfirmationDefaultNegative(`Overwrite remote file: ${resourcePath}`)
335334
}
336335
}
337336
}
337+
338338
if (!executeWrite) {
339339
if (options.verbose) (options.logger || console).log('Skipping existing local file:', resourcePath)
340340
return undefined;
@@ -358,6 +358,7 @@ async function writeRemoteFile(resourcePath: string, fileInfo: FileInfo, fetch:
358358
)
359359
if (!res.ok)
360360
throw new BashlibError(BashlibErrorMessage.httpResponseError, resourcePath, `${res.status} ${res.statusText}`)
361+
else if (options.verbose) (options.logger || console).log(`Writing remote resource: ${resourcePath}`);
361362

362363
} else if (fileData.blob) {
363364
let res = await fetch(
@@ -372,6 +373,7 @@ async function writeRemoteFile(resourcePath: string, fileInfo: FileInfo, fetch:
372373
)
373374
if (!res.ok)
374375
throw new BashlibError(BashlibErrorMessage.httpResponseError, resourcePath, `${res.status} ${res.statusText}`)
376+
else if (options.verbose) (options.logger || console).log(`Writing remote resource: ${resourcePath}`);
375377
} else {
376378
throw new BashlibError(BashlibErrorMessage.cannotWriteResource, resourcePath, "No contents to write")
377379
}

src/commands/solid-edit.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ async function editRemoteFile(url: string, options: ICommandOptionsEdit) {
8686
}
8787

8888
if (updateChanges) {
89-
await copy(tmpFilePath, remoteFileUrl, options)
89+
await copy(tmpFilePath, remoteFileUrl, { ...options, override: true })
9090
if (options.verbose) (options.logger || console).log('Remote file updated!');
9191
}
9292
else {

src/commands/solid-move.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import remove from './solid-remove';
44
import { ICommandOptions, setOptionDefaults } from './solid-command';
55

66
export interface ICommandOptionsMove extends ICommandOptions {
7-
all: boolean,
7+
all?: boolean,
8+
neverOverride?: boolean,
9+
override?: boolean,
10+
verbose?: boolean,
811
}
912
export default async function move(source: string, destination: string, options?: ICommandOptionsMove) {
1013
let commandOptions = setOptionDefaults<ICommandOptionsMove>(options || {});

src/commands/solid-touch.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { FetchError, getResourceInfo } from "@inrupt/solid-client"
22
import { setOptionDefaults, ICommandOptions } from './solid-command';
3+
import { resourceExists } from "../utils/util";
34
const mime = require('mime-types');
45

56
export interface ICommandOptionsTouch extends ICommandOptions{
@@ -14,7 +15,7 @@ export default async function touch(url: string, options?: ICommandOptionsTouch)
1415
throw new Error('Can\'t touch containers only resources')
1516
}
1617

17-
let urlExists = await resourceExists(url, commandOptions);
18+
let urlExists = await resourceExists(url, commandOptions.fetch);
1819

1920
if (urlExists) {
2021
if (commandOptions.verbose) commandOptions.logger.log(`Remote file already exists`)
@@ -49,21 +50,4 @@ export default async function touch(url: string, options?: ICommandOptionsTouch)
4950
throw new Error(`HTTP Error Response requesting ${url}: ${res.status} ${res.statusText}`)
5051
}
5152
}
52-
}
53-
54-
export async function resourceExists(url: string, options: any) {
55-
let fetch = options.fetch;
56-
57-
try {
58-
let info = await getResourceInfo(url, { fetch: fetch })
59-
return true;
60-
}
61-
catch (e) {
62-
if (e instanceof FetchError && e.response.status === 404) {
63-
return false;
64-
}
65-
else {
66-
return undefined;
67-
}
68-
}
6953
}

src/shell/commands/copy.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ export default class CopyCommand extends SolidCommand {
1616
.argument('<src>', 'file or directory to be copied')
1717
.argument('<dst>', 'destination to copy file or directory to')
1818
.option('-a, --all', 'Copy .acl files in recursive directory copies')
19-
.option('-i, --interactive-override', 'Interactive confirmation prompt when overriding existing files')
20-
.option('-n, --no-override', 'Do not override existing files')
19+
// .option('-i, --interactive-override', 'Interactive confirmation prompt when overriding existing files')
20+
.option('-o, --override', 'Automatically override existing files')
21+
.option('-n, --never-override', 'Automatically override existing files')
2122
.option('-v, --verbose', 'Log all read and write operations')
2223
.action(this.executeCommand)
2324

@@ -40,7 +41,5 @@ export default class CopyCommand extends SolidCommand {
4041
}
4142
if (this.mayExit) process.exit(0)
4243
}
43-
44-
4544
}
4645

src/shell/commands/mv.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ export default class MkdirCommand extends SolidCommand {
1616
.argument('<src>', 'file or directory to be moved')
1717
.argument('<dst>', 'destination of the move')
1818
.option('-a, --all', 'Move .acl files when moving directories recursively')
19-
.option('-i, --interactive-override', 'Interactive confirmation prompt when overriding existing files')
20-
.option('-n, --no-override', 'Do not override existing files')
19+
// .option('-i, --interactive-override', 'Interactive confirmation prompt when overriding existing files')
20+
.option('-o, --override', 'Automatically override existing files')
21+
.option('-n, --never-override', 'Automatically override existing files')
2122
.option('-v, --verbose', 'Log all operations')
2223
.action(this.executeCommand)
2324

src/utils/userInteractions.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import inquirer from 'inquirer';
22

3-
export async function requestUserCLIConfirmation(request: string) : Promise<boolean> {
3+
export async function requestUserCLIConfirmationDefaultNegative(request: string) : Promise<boolean> {
44
console.log(`${request} [y/N]`);
55
return await new Promise((resolve, reject) => {
66
process.stdin.setRawMode(true);
77
process.stdin.resume();
8-
process.stdin.on('data', (chk) => {
8+
process.stdin.once('data', (chk) => {
9+
process.stdin.pause();
910
if (chk.toString('utf8') === "y") {
1011
resolve(true);
1112
} else {
@@ -15,6 +16,22 @@ export async function requestUserCLIConfirmation(request: string) : Promise<bool
1516
});
1617
}
1718

19+
export async function requestUserCLIConfirmationDefaultPositive(request: string) : Promise<boolean> {
20+
console.log(`${request} [Y/n]`);
21+
return await new Promise((resolve, reject) => {
22+
process.stdin.setRawMode(true);
23+
process.stdin.resume();
24+
process.stdin.once('data', (chk) => {
25+
process.stdin.pause();
26+
if (chk.toString('utf8') === "n") {
27+
resolve(false);
28+
} else {
29+
resolve(true);
30+
}
31+
});
32+
});
33+
}
34+
1835
export async function requestUserIdp() {
1936
console.log(``);
2037

src/utils/util.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getSolidDataset, getContainedResourceUrlAll, getUrl, getUrlAll, getThing, getThingAll, getDatetime, getInteger, SolidDataset, acp_ess_2, hasAccessibleAcl } from '@inrupt/solid-client';
1+
import { getSolidDataset, getContainedResourceUrlAll, getUrl, getUrlAll, getThing, getThingAll, getDatetime, getInteger, SolidDataset, acp_ess_2, hasAccessibleAcl, FetchError } from '@inrupt/solid-client';
22
import { requestUserIdp } from './userInteractions';
33
import type { Logger } from '../logger';
44

@@ -524,6 +524,16 @@ export async function discoverAccessMechanism(url: string, fetch: any) {
524524
}
525525

526526
export async function resourceExists(url: string, fetch: any) {
527-
let res = await fetch(url, {method: "HEAD"})
528-
return res.ok
527+
try {
528+
let res = await fetch(url, { method: "HEAD" })
529+
return res.ok;
530+
}
531+
catch (e) {
532+
if (e instanceof FetchError && e.response.status === 404) {
533+
return false;
534+
}
535+
else {
536+
return undefined;
537+
}
538+
}
529539
}

0 commit comments

Comments
 (0)