braidfs 0.0.120 → 0.0.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +163 -208
- package/index.sh +4 -1
- package/package.json +2 -1
package/index.js
CHANGED
|
@@ -12,8 +12,18 @@ function is_binary(filename) {
|
|
|
12
12
|
|
|
13
13
|
braid_fetch.set_fetch(fetch_http2)
|
|
14
14
|
|
|
15
|
-
var sync_base = `${require('os').homedir()}/http
|
|
16
|
-
|
|
15
|
+
var sync_base = `${require('os').homedir()}/http`
|
|
16
|
+
// Check for --sync-base argument (hidden for testing)
|
|
17
|
+
var argv = process.argv.slice(2)
|
|
18
|
+
var sync_base_index = argv.indexOf('--sync-base')
|
|
19
|
+
if (sync_base_index !== -1 && sync_base_index < argv.length - 1) {
|
|
20
|
+
sync_base = argv[sync_base_index + 1]
|
|
21
|
+
// Remove the --sync-base and its value from argv
|
|
22
|
+
argv.splice(sync_base_index, 2)
|
|
23
|
+
console.log(`[Testing mode] Using sync_base: ${sync_base}`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var braidfs_config_dir = `${sync_base}/.braidfs`,
|
|
17
27
|
braidfs_config_file = `${braidfs_config_dir}/config`,
|
|
18
28
|
sync_base_meta = `${braidfs_config_dir}/proxy_base_meta`
|
|
19
29
|
braid_text.db_folder = `${braidfs_config_dir}/braid-text-db`
|
|
@@ -68,8 +78,7 @@ to_run_in_background = ''
|
|
|
68
78
|
|
|
69
79
|
console.log(`braidfs version: ${require(`${__dirname}/package.json`).version}`)
|
|
70
80
|
|
|
71
|
-
// process command line args
|
|
72
|
-
var argv = process.argv.slice(2)
|
|
81
|
+
// process command line args (argv was already processed above for --sync-base)
|
|
73
82
|
if (argv.length === 1 && argv[0].match(/^(run|serve)$/)) {
|
|
74
83
|
return main()
|
|
75
84
|
} else if (argv.length && argv.length % 2 == 0 && argv.every((x, i) => i % 2 != 0 || x.match(/^(sync|unsync)$/))) {
|
|
@@ -172,13 +181,11 @@ async function main() {
|
|
|
172
181
|
await braid_text.put(sync.url, { version, parents, patches, merge_type: 'dt' })
|
|
173
182
|
|
|
174
183
|
// may be able to do this more efficiently.. we want to make sure we're capturing a file write that is after our version was written.. there may be a way we can avoid calling file_needs_writing here
|
|
175
|
-
|
|
184
|
+
await new Promise(done => {
|
|
176
185
|
sync.file_written_cbs.push(done)
|
|
177
186
|
sync.signal_file_needs_writing()
|
|
178
187
|
})
|
|
179
|
-
|
|
180
|
-
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
181
|
-
return res.end(stat.mtimeMs.toString())
|
|
188
|
+
return res.end('')
|
|
182
189
|
} else return res.end('null')
|
|
183
190
|
}
|
|
184
191
|
|
|
@@ -245,7 +252,7 @@ async function main() {
|
|
|
245
252
|
watch_files()
|
|
246
253
|
setTimeout(scan_files, 1200)
|
|
247
254
|
}).on('error', e => {
|
|
248
|
-
if (e.code === 'EADDRINUSE') return console.log(`port ${config.port} is in use`)
|
|
255
|
+
if (e.code === 'EADDRINUSE') return console.log(`ERROR: port ${config.port} is in use`)
|
|
249
256
|
throw e
|
|
250
257
|
})
|
|
251
258
|
}
|
|
@@ -371,7 +378,7 @@ async function scan_files() {
|
|
|
371
378
|
if (!sync) return await trash_file(fullpath, path)
|
|
372
379
|
|
|
373
380
|
stat = await require('fs').promises.stat(fullpath, { bigint: true })
|
|
374
|
-
if (
|
|
381
|
+
if ('' + stat.mtimeNs !== sync.file_mtimeNs_str) {
|
|
375
382
|
console.log(`scan thinks ${path} has changed`)
|
|
376
383
|
sync.signal_file_needs_reading()
|
|
377
384
|
return true
|
|
@@ -452,202 +459,159 @@ async function sync_url(url) {
|
|
|
452
459
|
|
|
453
460
|
console.log(`init_binary_sync: ${url}`)
|
|
454
461
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
// self.file_written_cbs = [] // not needed
|
|
462
|
-
|
|
463
|
-
self.signal_file_needs_reading = () => {
|
|
464
|
-
if (freed) return
|
|
465
|
-
file_needs_reading = true
|
|
466
|
-
file_loop_pump()
|
|
462
|
+
async function save_meta() {
|
|
463
|
+
await require('fs').promises.writeFile(meta_path, JSON.stringify({
|
|
464
|
+
peer: self.peer,
|
|
465
|
+
version: self.version,
|
|
466
|
+
file_mtimeNs_str: self.file_mtimeNs_str
|
|
467
|
+
}))
|
|
467
468
|
}
|
|
468
469
|
|
|
469
|
-
|
|
470
|
+
await within_fiber(url, async () => {
|
|
471
|
+
try {
|
|
472
|
+
Object.assign(self, JSON.parse(
|
|
473
|
+
await require('fs').promises.readFile(meta_path, 'utf8')))
|
|
474
|
+
} catch (e) {}
|
|
470
475
|
if (freed) return
|
|
471
|
-
file_needs_writing = true
|
|
472
|
-
file_loop_pump()
|
|
473
|
-
}
|
|
474
476
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
477
|
+
if (!self.peer) self.peer = Math.random().toString(36).slice(2)
|
|
478
|
+
|
|
479
|
+
await save_meta()
|
|
480
|
+
})
|
|
481
|
+
if (freed) return
|
|
482
|
+
|
|
483
|
+
var waitTime = 1
|
|
484
|
+
var last_connect_timer = null
|
|
485
|
+
|
|
486
|
+
self.signal_file_needs_reading = () => {}
|
|
487
|
+
|
|
488
|
+
connect()
|
|
489
|
+
async function connect() {
|
|
478
490
|
if (freed) return
|
|
491
|
+
if (last_connect_timer) return
|
|
492
|
+
|
|
493
|
+
var closed = false
|
|
494
|
+
var prev_disconnect = self.disconnect
|
|
495
|
+
self.disconnect = async () => {
|
|
496
|
+
if (closed) return
|
|
497
|
+
closed = true
|
|
498
|
+
reconnect_rate_limiter.on_diss(url)
|
|
499
|
+
for (var a of aborts) a.abort()
|
|
500
|
+
aborts.clear()
|
|
501
|
+
}
|
|
502
|
+
self.reconnect = connect
|
|
503
|
+
|
|
504
|
+
await prev_disconnect?.()
|
|
505
|
+
if (freed || closed) return
|
|
506
|
+
|
|
507
|
+
await reconnect_rate_limiter.get_turn(url)
|
|
508
|
+
if (freed || closed) return
|
|
479
509
|
|
|
480
|
-
|
|
481
|
-
|
|
510
|
+
function retry(e) {
|
|
511
|
+
if (freed || closed) return
|
|
512
|
+
var p = self.disconnect()
|
|
513
|
+
|
|
514
|
+
console.log(`reconnecting in ${waitTime}s: ${url} after error: ${e}`)
|
|
515
|
+
last_connect_timer = setTimeout(async () => {
|
|
516
|
+
await p
|
|
517
|
+
last_connect_timer = null
|
|
518
|
+
connect()
|
|
519
|
+
}, waitTime * 1000)
|
|
520
|
+
waitTime = Math.min(waitTime + 1, 3)
|
|
521
|
+
}
|
|
482
522
|
|
|
483
|
-
// If the file exists locally, subscribe first; this will also create
|
|
484
|
-
// an early-timestamp file on server if missing. Then compare mtimes
|
|
485
|
-
// to decide whether to upload or download.
|
|
486
523
|
try {
|
|
487
|
-
var
|
|
488
|
-
|
|
489
|
-
|
|
524
|
+
var a = new AbortController()
|
|
525
|
+
aborts.add(a)
|
|
526
|
+
var res = await braid_fetch(url, {
|
|
527
|
+
signal: a.signal,
|
|
490
528
|
headers: {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
529
|
+
...(x => x && {Cookie: x})(config.cookies?.[new URL(url).hostname]),
|
|
530
|
+
},
|
|
531
|
+
subscribe: true,
|
|
532
|
+
heartbeats: 120,
|
|
533
|
+
peer: self.peer,
|
|
534
|
+
...(self.version != null ? {parents: ['' + self.version]} : {})
|
|
494
535
|
})
|
|
536
|
+
if (freed || closed) return
|
|
495
537
|
|
|
496
|
-
if (
|
|
497
|
-
self.server_subscription = subscribeRes
|
|
538
|
+
if (res.status < 200 || res.status >= 300) return retry(new Error(`unexpected status: ${res.status}`))
|
|
498
539
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
if (local_exists) {
|
|
502
|
-
try {
|
|
503
|
-
const statResult = await wait_on(require('fs').promises.stat(fullpath));
|
|
504
|
-
local_mtime_ms = Math.round(Number(statResult.mtimeMs));
|
|
505
|
-
} catch (e) {}
|
|
506
|
-
}
|
|
540
|
+
if (res.status !== 209)
|
|
541
|
+
return log_error(`Can't sync ${url} -- got bad response ${res.status} from server (expected 209)`)
|
|
507
542
|
|
|
508
|
-
|
|
509
|
-
var server_mtime_header = subscribeRes.headers.get('last-modified-ms')
|
|
510
|
-
var server_mtime_ms = 0
|
|
511
|
-
if (server_mtime_header) {
|
|
512
|
-
server_mtime_ms = Math.round(Number(server_mtime_header))
|
|
513
|
-
}
|
|
543
|
+
console.log(`connected to ${url}${res.headers.get('editable') !== 'true' ? ' (readonly)' : ''}`)
|
|
514
544
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
body: fileData,
|
|
524
|
-
headers: { 'Content-Type': 'application/octet-stream', 'peer': self.peer, 'X-Timestamp': local_mtime_ms }
|
|
525
|
-
})
|
|
526
|
-
if (putRes.ok) console.log(`Uploaded newer local file to server: ${url}`)
|
|
527
|
-
} catch (e) { console.log(`Failed to upload newer local file: ${e}`) }
|
|
528
|
-
}
|
|
545
|
+
reconnect_rate_limiter.on_conn(url)
|
|
546
|
+
|
|
547
|
+
res.subscribe(async update => {
|
|
548
|
+
if (freed || closed) return
|
|
549
|
+
if (update.version.length === 0) return
|
|
550
|
+
if (update.version.length !== 1) throw 'unexpected'
|
|
551
|
+
var version = 1*update.version[0]
|
|
552
|
+
if (!update.body) return
|
|
529
553
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
// console.log(update)
|
|
534
|
-
// ignore first responce if we already have the up-to-date file, although not needed.
|
|
535
|
-
var update_timestamp = Math.round(Number(update.version[0]));
|
|
536
|
-
// if (isNaN(update_timestamp)) update_timestamp = Date.now() // should throw error if can't read server timestamp
|
|
537
|
-
if (local_exists && local_mtime_ms < update_timestamp) {
|
|
538
|
-
try {
|
|
539
|
-
// console.log(Math.round(local_mtime_ms))
|
|
540
|
-
// console.log(Math.round(update_timestamp))
|
|
541
|
-
var writePath = await get_fullpath()
|
|
542
|
-
await wait_on(ensure_path(require("path").dirname(writePath)))
|
|
543
|
-
await wait_on(require('fs').promises.writeFile(writePath, update.body))
|
|
544
|
-
|
|
545
|
-
// Set the file timestamp to the update timestamp
|
|
546
|
-
var mtime = update_timestamp / 1000
|
|
547
|
-
await wait_on(require('fs').promises.utimes(writePath, mtime, mtime))
|
|
548
|
-
// const statResult = await wait_on(require('fs').promises.stat(writePath));
|
|
549
|
-
// console.log(Math.round(Number(statResult.mtimeMs))) // checking for writing vs written issues
|
|
550
|
-
|
|
551
|
-
var st = await wait_on(require('fs').promises.stat(writePath, { bigint: true }))
|
|
552
|
-
self.file_last_stat = st
|
|
553
|
-
console.log(`Updated local binary file from server: ${writePath}`)
|
|
554
|
-
} catch (e) { console.log(`Failed to update local file from server: ${e}`) }
|
|
555
|
-
}
|
|
556
|
-
})
|
|
557
|
-
}
|
|
554
|
+
if (self.version != null &&
|
|
555
|
+
version <= self.version) return
|
|
556
|
+
self.version = version
|
|
558
557
|
|
|
558
|
+
await within_fiber(url, async () => {
|
|
559
|
+
var fullpath = await get_fullpath()
|
|
560
|
+
if (freed || closed) return
|
|
559
561
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
}
|
|
562
|
+
await wait_on(require('fs').promises.writeFile(fullpath, update.body))
|
|
563
|
+
if (freed || closed) return
|
|
563
564
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
self.file_last_stat = stat
|
|
569
|
-
} catch (e) {
|
|
570
|
-
// file may not exist yet; will be handled by file_loop
|
|
571
|
-
}
|
|
572
|
-
})
|
|
565
|
+
var stat = await require('fs').promises.stat(fullpath, { bigint: true })
|
|
566
|
+
if (freed || closed) return
|
|
567
|
+
self.file_mtimeNs_str = '' + stat.mtimeNs
|
|
568
|
+
self.last_touch = Date.now()
|
|
573
569
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
if (freed) return
|
|
578
|
-
if (file_loop_pump_lock) return
|
|
579
|
-
file_loop_pump_lock++
|
|
570
|
+
await save_meta()
|
|
571
|
+
})
|
|
572
|
+
}, retry)
|
|
580
573
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
574
|
+
self.signal_file_needs_reading = () => {
|
|
575
|
+
within_fiber(url, async () => {
|
|
576
|
+
if (freed || closed) return
|
|
584
577
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
file_needs_reading = false
|
|
578
|
+
var fullpath = await get_fullpath()
|
|
579
|
+
if (freed || closed) return
|
|
588
580
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
}
|
|
594
|
-
if (freed) return
|
|
581
|
+
try {
|
|
582
|
+
var stat = await require('fs').promises.stat(fullpath, { bigint: true })
|
|
583
|
+
} catch (e) { return }
|
|
584
|
+
if (freed || closed) return
|
|
595
585
|
|
|
596
|
-
if (
|
|
597
|
-
|
|
586
|
+
if ('' + stat.mtimeNs !== self.file_mtimeNs_str) {
|
|
587
|
+
self.version = Math.max((self.version || 0) + 1,
|
|
588
|
+
Math.round(Number(stat.mtimeNs) / 1000000))
|
|
598
589
|
|
|
599
|
-
|
|
600
|
-
|
|
590
|
+
self.file_mtimeNs_str = '' + stat.mtimeNs
|
|
591
|
+
self.last_touch = Date.now()
|
|
601
592
|
|
|
602
|
-
|
|
603
|
-
// Importent logs for debugging precision issues
|
|
604
|
-
// console.log(`binary file change detected in ${path}`)
|
|
605
|
-
// console.log(`stat.mtimeMs: ${stat.mtimeMs}`)
|
|
606
|
-
// console.log(`self.file_last_stat.mtimeMs ${self.file_last_stat.mtimeMs}`)
|
|
607
|
-
// console.log(Math.round(Number(stat.mtimeMs)))
|
|
593
|
+
await save_meta()
|
|
608
594
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
// Upload the changed file to server
|
|
613
|
-
try {
|
|
614
|
-
var fileData = await wait_on(require('fs').promises.readFile(fullpath))
|
|
615
|
-
var response = await braid_fetch(url, {
|
|
616
|
-
method: 'PUT',
|
|
617
|
-
body: fileData,
|
|
618
|
-
headers: { 'Content-Type': 'application/octet-stream', 'peer': self.peer, 'X-Timestamp': lower_precision_mtimems }
|
|
619
|
-
})
|
|
620
|
-
if (response.ok) {
|
|
621
|
-
console.log(`Uploaded changed binary file to server: ${url}`)
|
|
622
|
-
}
|
|
623
|
-
} catch (e) {
|
|
624
|
-
console.log(`Failed to upload changed file: ${e}`)
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
self.file_last_stat = stat
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
if (file_needs_writing) {
|
|
631
|
-
file_needs_writing = false
|
|
632
|
-
// Binary files are handled by the file watcher and server subscription
|
|
633
|
-
// No additional processing needed here
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
})
|
|
595
|
+
var body = await require('fs').promises.readFile(fullpath)
|
|
596
|
+
if (freed || closed) return
|
|
637
597
|
|
|
638
|
-
|
|
639
|
-
|
|
598
|
+
var a = new AbortController()
|
|
599
|
+
aborts.add(a)
|
|
640
600
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
601
|
+
await braid_fetch(url, {
|
|
602
|
+
method: 'PUT',
|
|
603
|
+
signal: a.signal,
|
|
604
|
+
version: ['' + self.version],
|
|
605
|
+
body,
|
|
606
|
+
headers: {
|
|
607
|
+
...(x => x && {Cookie: x})(config.cookies?.[new URL(url).hostname])
|
|
608
|
+
},
|
|
609
|
+
})
|
|
610
|
+
}
|
|
611
|
+
})
|
|
612
|
+
}
|
|
613
|
+
self.signal_file_needs_reading()
|
|
614
|
+
} catch (e) { return retry(e) }
|
|
651
615
|
}
|
|
652
616
|
|
|
653
617
|
return self
|
|
@@ -658,19 +622,6 @@ async function sync_url(url) {
|
|
|
658
622
|
|
|
659
623
|
// console.log(`sync_url: ${url}`)
|
|
660
624
|
|
|
661
|
-
// Check if this is a binary file
|
|
662
|
-
var is_binary_file = is_binary(path)
|
|
663
|
-
|
|
664
|
-
if (is_binary_file) {
|
|
665
|
-
// Opts into the code for FS watcher (file_needs_reading, file_needs_writing) & unsyncing (disconnect)
|
|
666
|
-
// It notably does NOT handle `.braidfs/set_version/` and `.braidfs/get_version/` correctly!
|
|
667
|
-
// Search ` sync_url.cache[` to see how it's all handled.
|
|
668
|
-
return await init_binary_sync()
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
var resource = await braid_text.get_resource(url)
|
|
672
|
-
if (freed) return
|
|
673
|
-
|
|
674
625
|
// if we're accessing /blah/index, it will be normalized to /blah,
|
|
675
626
|
// but we still want to create a directory out of blah in this case
|
|
676
627
|
if (wasnt_normal && !(await is_dir(fullpath))) {
|
|
@@ -682,13 +633,25 @@ async function sync_url(url) {
|
|
|
682
633
|
await ensure_path(require("path").dirname(fullpath))
|
|
683
634
|
if (freed) return
|
|
684
635
|
|
|
636
|
+
// Check if this is a binary file
|
|
637
|
+
// for now, this will be stuff in the "blobs" directory..
|
|
638
|
+
if (is_external_link && path.split('/')[1] === 'blobs') {
|
|
639
|
+
// Opts into the code for FS watcher (file_needs_reading, file_needs_writing) & unsyncing (disconnect)
|
|
640
|
+
// It notably does NOT handle `.braidfs/set_version/` and `.braidfs/get_version/` correctly!
|
|
641
|
+
// Search ` sync_url.cache[` to see how it's all handled.
|
|
642
|
+
return await init_binary_sync()
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
var resource = await braid_text.get_resource(url)
|
|
646
|
+
if (freed) return
|
|
647
|
+
|
|
685
648
|
self.peer = Math.random().toString(36).slice(2)
|
|
686
649
|
self.local_edit_counter = 0
|
|
687
650
|
self.fork_point = null
|
|
688
651
|
var file_last_version = null,
|
|
689
652
|
file_last_digest = null
|
|
690
653
|
self.file_last_text = null
|
|
691
|
-
self.
|
|
654
|
+
self.file_mtimeNs_str = null
|
|
692
655
|
self.file_read_only = null
|
|
693
656
|
var file_needs_reading = true,
|
|
694
657
|
file_needs_writing = null,
|
|
@@ -870,14 +833,14 @@ async function sync_url(url) {
|
|
|
870
833
|
add_to_version_cache(text, file_last_version)
|
|
871
834
|
|
|
872
835
|
// console.log(`no changes found in: ${fullpath}`)
|
|
873
|
-
if (
|
|
874
|
-
if (Date.now() > (self.
|
|
836
|
+
if ('' + stat.mtimeNs === self.file_mtimeNs_str) {
|
|
837
|
+
if (Date.now() > (self.last_touch ?? 0) + 1000)
|
|
875
838
|
on_watcher_miss(`expected change to: ${fullpath}`)
|
|
876
839
|
// else console.log(`no changes expected`)
|
|
877
840
|
} // else console.log('found change in file stat')
|
|
878
841
|
}
|
|
879
|
-
self.
|
|
880
|
-
self.
|
|
842
|
+
self.file_mtimeNs_str = '' + stat.mtimeNs
|
|
843
|
+
self.last_touch = Date.now()
|
|
881
844
|
}
|
|
882
845
|
if (file_needs_writing === 'just_meta_file') {
|
|
883
846
|
file_needs_writing = false
|
|
@@ -908,7 +871,7 @@ async function sync_url(url) {
|
|
|
908
871
|
|
|
909
872
|
file_last_version = version
|
|
910
873
|
self.file_last_text = body
|
|
911
|
-
self.
|
|
874
|
+
self.last_touch = Date.now()
|
|
912
875
|
await wait_on(require('fs').promises.writeFile(fullpath, self.file_last_text))
|
|
913
876
|
if (freed) return
|
|
914
877
|
}
|
|
@@ -918,15 +881,15 @@ async function sync_url(url) {
|
|
|
918
881
|
|
|
919
882
|
if (await wait_on(is_read_only(fullpath)) !== self.file_read_only) {
|
|
920
883
|
if (freed) return
|
|
921
|
-
self.
|
|
884
|
+
self.last_touch = Date.now()
|
|
922
885
|
await wait_on(set_read_only(fullpath, self.file_read_only))
|
|
923
886
|
}
|
|
924
887
|
if (freed) return
|
|
925
888
|
|
|
926
|
-
self.
|
|
889
|
+
self.file_mtimeNs_str = '' + (await wait_on(require('fs').promises.stat(fullpath, { bigint: true }))).mtimeNs
|
|
927
890
|
if (freed) return
|
|
928
891
|
|
|
929
|
-
for (var cb of self.file_written_cbs) cb(
|
|
892
|
+
for (var cb of self.file_written_cbs) cb()
|
|
930
893
|
self.file_written_cbs = []
|
|
931
894
|
}
|
|
932
895
|
}
|
|
@@ -1549,14 +1512,6 @@ function v_eq(v1, v2) {
|
|
|
1549
1512
|
return v1.length === v2?.length && v1.every((x, i) => x == v2[i])
|
|
1550
1513
|
}
|
|
1551
1514
|
|
|
1552
|
-
function stat_eq(a, b) {
|
|
1553
|
-
return (!a && !b) || (a && b &&
|
|
1554
|
-
a.mode === b.mode &&
|
|
1555
|
-
a.size === b.size &&
|
|
1556
|
-
a.mtimeNs === b.mtimeNs &&
|
|
1557
|
-
a.ctimeNs === b.ctimeNs)
|
|
1558
|
-
}
|
|
1559
|
-
|
|
1560
1515
|
async function is_read_only(fullpath) {
|
|
1561
1516
|
const stat = await require('fs').promises.stat(fullpath)
|
|
1562
1517
|
return require('os').platform() === "win32" ?
|
package/index.sh
CHANGED
|
@@ -35,8 +35,11 @@ urlencode() {
|
|
|
35
35
|
echo "$encoded"
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
# Get the base directory (can be overridden by setting BRAIDFS_BASE_DIR)
|
|
39
|
+
BASE_DIR="${BRAIDFS_BASE_DIR:-${HOME}/http}"
|
|
40
|
+
|
|
38
41
|
# Get the configuration file to read the port
|
|
39
|
-
CONFIG_FILE="${
|
|
42
|
+
CONFIG_FILE="${BASE_DIR}/.braidfs/config"
|
|
40
43
|
if [ -f "$CONFIG_FILE" ]; then
|
|
41
44
|
PORT=$(grep -o '"port":[^,}]*' "$CONFIG_FILE" | sed 's/"port"://; s/ //g')
|
|
42
45
|
if [ -z "$PORT" ]; then
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "braidfs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.121",
|
|
4
4
|
"description": "braid technology synchronizing files and webpages",
|
|
5
5
|
"author": "Braid Working Group",
|
|
6
6
|
"repository": "braid-org/braidfs",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"braid-http": "~1.3.79",
|
|
10
10
|
"braid-text": "~0.2.64",
|
|
11
|
+
"braid-blob": "~0.0.8",
|
|
11
12
|
"chokidar": "^4.0.3"
|
|
12
13
|
},
|
|
13
14
|
"bin": {
|