Skip to content

Commit d116b31

Browse files
committed
make pear dump consistent for file and pear
- mirror local files from the root of the pear project
1 parent ed26b7f commit d116b31

File tree

2 files changed

+132
-21
lines changed

2 files changed

+132
-21
lines changed

subsystems/sidecar/ops/dump.js

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const path = require('bare-path')
44
const LocalDrive = require('localdrive')
55
const Hyperdrive = require('hyperdrive')
66
const plink = require('pear-link')
7+
const State = require('pear-state')
78
const {
89
ERR_PERMISSION_REQUIRED,
910
ERR_DIR_NONEMPTY,
@@ -12,6 +13,7 @@ const {
1213
} = require('pear-errors')
1314
const Pod = require('../lib/pod')
1415
const Opstream = require('../lib/opstream')
16+
const { isWindows } = require('which-runtime')
1517

1618
module.exports = class Dump extends Opstream {
1719
constructor(...args) {
@@ -36,9 +38,18 @@ module.exports = class Dump extends Opstream {
3638
}
3739

3840
const parsed = plink.parse(link)
41+
3942
const isFileLink = parsed.protocol === 'file:'
43+
const fsPathname = isWindows
44+
? (parsed.pathname.startsWith('/')
45+
? parsed.pathname.slice(1)
46+
: parsed.pathname
47+
)
48+
.split(path.posix.sep)
49+
.join(path.win32.sep)
50+
: parsed.pathname
4051
const isFile =
41-
isFileLink && (await fsp.stat(parsed.pathname)).isDirectory() === false
52+
isFileLink && (await fsp.stat(fsPathname)).isDirectory() === false
4253

4354
const key = parsed.drive.key
4455
checkout =
@@ -48,25 +59,40 @@ module.exports = class Dump extends Opstream {
4859
const encryptionKey = traits?.encryptionKey
4960

5061
const corestore = isFileLink ? null : sidecar.getCorestore(null, null)
51-
let drive = null
5262

53-
if (corestore) {
63+
let prefix
64+
let drive
65+
66+
if (!isFileLink) {
5467
await corestore.ready()
5568
try {
5669
drive = new Hyperdrive(corestore, key, { encryptionKey })
5770
await drive.ready()
71+
prefix = parsed.pathname
5872
} catch (err) {
5973
if (err.code !== 'DECODING_ERROR') throw err
6074
throw ERR_PERMISSION_REQUIRED('Encryption key required', {
6175
key,
6276
encrypted: true
6377
})
6478
}
79+
} else {
80+
const state = new State({
81+
dir: isFile ? path.dirname(fsPathname) : fsPathname
82+
})
83+
await State.localPkg(state)
84+
prefix = path.join('/', path.relative(state.dir, fsPathname))
85+
drive = new LocalDrive(state.dir, { followLinks: true })
86+
const isRoot = isWindows
87+
? /[a-zA-Z]:\\$/.test(state.dir)
88+
: state.dir === '/'
89+
if (isRoot) throw ERR_NOT_FOUND('No pear project found')
6590
}
66-
const root = isFile ? path.dirname(parsed.pathname) : parsed.pathname
91+
const pathname = prefix === '/' ? '' : prefix
92+
6793
const pod = new Pod({
6894
corestore,
69-
drive: isFileLink ? new LocalDrive(root, { followLinks: true }) : drive,
95+
drive,
7096
key,
7197
checkout,
7298
swarm: sidecar.swarm
@@ -92,13 +118,6 @@ module.exports = class Dump extends Opstream {
92118
const src = pod.drive
93119
await src.ready()
94120

95-
const prefix = isFileLink ? '/' : parsed.pathname
96-
const pathname =
97-
!isFileLink && parsed.pathname === '/'
98-
? ''
99-
: isFile
100-
? path.basename(parsed.pathname)
101-
: prefix
102121
const entry = pathname === '' ? null : await src.entry(pathname)
103122

104123
if (entry === null) {

test/06-dump.test.js

Lines changed: 101 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
const test = require('brittle')
33
const tmp = require('test-tmp')
44
const Localdrive = require('localdrive')
5+
const fs = require('bare-fs')
6+
const path = require('bare-path')
7+
const { isWindows } = require('which-runtime')
58

69
const Helper = require('./helper')
710

@@ -43,20 +46,13 @@ test('pear dump', async function ({ ok, plan, teardown }) {
4346
ok(await dumped.exists('/package.json'), 'package.json should exist')
4447
})
4548

46-
test('pear dump dumping subdirectory', async function ({
49+
test('pear dump dumping subdirectory from pear drive', async function ({
4750
ok,
4851
absent,
4952
plan,
5053
teardown
5154
}) {
5255
plan(4)
53-
const path = require('bare-path')
54-
const fs = require('bare-fs')
55-
const exists = (path) =>
56-
fs.promises.stat(path).then(
57-
() => true,
58-
() => false
59-
)
6056
const helper = new Helper()
6157
teardown(() => helper.close(), { order: Infinity })
6258
await helper.ready()
@@ -93,6 +89,35 @@ test('pear dump dumping subdirectory', async function ({
9389
ok(await dumped.exists('/lib/pear.js'), 'lib/pear.js should exist')
9490
})
9591

92+
test('pear dump dumping subdirectory from local drive', async function ({
93+
ok,
94+
absent,
95+
plan,
96+
teardown
97+
}) {
98+
plan(4)
99+
const helper = new Helper()
100+
teardown(() => helper.close(), { order: Infinity })
101+
await helper.ready()
102+
103+
const src = Helper.fixture('dump')
104+
const link = isWindows
105+
? `file://${src.split(path.win32.sep).join(path.posix.sep)}/lib`
106+
: `file://${src}/lib`
107+
const out = await tmp()
108+
109+
teardown(() => Helper.gc(out))
110+
const dump = await helper.dump({ link, dir: out })
111+
teardown(() => Helper.teardownStream(dump))
112+
const untilDump = await Helper.pick(dump, [{ tag: 'complete' }])
113+
await untilDump.complete
114+
const dumped = new Localdrive(out)
115+
absent(await dumped.exists('/index.js'), 'index.js should not exist')
116+
absent(await dumped.exists('/package.json'), 'package.json should not exist')
117+
ok(await dumped.exists('/lib/dump.js'), 'lib/dump.js should exist')
118+
ok(await dumped.exists('/lib/pear.js'), 'lib/pear.js should exist')
119+
})
120+
96121
test('pear dump dumping to existing dir', async function ({
97122
absent,
98123
is,
@@ -230,7 +255,7 @@ test('pear dump dumping a single file', async function ({
230255
absent(await dumped.exists('/package.json'), 'package.json should not exist')
231256
})
232257

233-
test('pear dump dumping a single file in a subdirectory', async function ({
258+
test('pear dump dumping a single file in a subdirectory from pear drive', async function ({
234259
ok,
235260
is,
236261
plan,
@@ -275,6 +300,73 @@ test('pear dump dumping a single file in a subdirectory', async function ({
275300
is(dirCount, 1, 'should have only one file in the lib directory')
276301
})
277302

303+
test('pear dump should throw when dumping file outside a pear project', async function ({
304+
plan,
305+
teardown,
306+
exception
307+
}) {
308+
plan(1)
309+
310+
const helper = new Helper()
311+
teardown(() => helper.close(), { order: Infinity })
312+
await helper.ready()
313+
314+
const src = await tmp()
315+
const out = await tmp()
316+
teardown(async () => {
317+
await Helper.gc(out)
318+
await Helper.gc(src)
319+
})
320+
await fs.promises.writeFile(
321+
path.join(src, 'test.js'),
322+
'console.log("test")',
323+
{
324+
encoding: 'utf-8'
325+
}
326+
)
327+
const link = isWindows
328+
? `file://${src.split(path.win32.sep).join(path.posix.sep)}/test.js`
329+
: `file://${src}/test.js`
330+
331+
await exception(async () => {
332+
const dump = helper.dump({ link, dir: out })
333+
teardown(() => Helper.teardownStream(dump))
334+
const untilDump = await Helper.pick(dump, [{ tag: 'complete' }])
335+
await untilDump.complete
336+
})
337+
})
338+
339+
test('pear dump dumping a single file in a subdirectory from local drive', async function ({
340+
ok,
341+
is,
342+
plan,
343+
teardown
344+
}) {
345+
plan(2)
346+
347+
const helper = new Helper()
348+
teardown(() => helper.close(), { order: Infinity })
349+
await helper.ready()
350+
351+
const src = Helper.fixture('dump')
352+
const link = isWindows
353+
? `file://${src.split(path.win32.sep).join(path.posix.sep)}/lib/dump.js`
354+
: `file://${src}/lib/dump.js`
355+
356+
const out = await tmp()
357+
358+
teardown(() => Helper.gc(out))
359+
const dump = await helper.dump({ link, dir: out })
360+
teardown(() => Helper.teardownStream(dump))
361+
const untilDump = await Helper.pick(dump, [{ tag: 'complete' }])
362+
await untilDump.complete
363+
const dumped = new Localdrive(out)
364+
let dirCount = 0
365+
for await (const _ of dumped.readdir()) dirCount++
366+
ok(await dumped.exists('/lib/dump.js'), 'lib/dump.js should exist')
367+
is(dirCount, 1, 'should have only one file in the lib directory')
368+
})
369+
278370
test('pear dump dumping to stdout', async function ({ ok, plan, teardown }) {
279371
plan(4)
280372

0 commit comments

Comments
 (0)