diff --git a/pwiki2.js b/pwiki2.js
index f4315f9..325f7e4 100755
--- a/pwiki2.js
+++ b/pwiki2.js
@@ -487,11 +487,15 @@ module.BaseStore = {
// NOTE: deleting and updating only applies to explicit matching
// paths -- no page acquisition is performed...
// NOTE: edit methods are local-only...
- //
+ // NOTE: if .__update__ and .__delete__ are set to null/false this
+ // will quietly go into read-only mode...
// XXX do we copy the data here or modify it????
__update__: async function(key, data, mode='update'){
this.data[key] = data },
update: async function(path, data, mode='update'){
+ // read-only...
+ if(this.__update__ == null){
+ return this }
var exists = await this.exists(path)
path = exists
|| module.path.normalize(path, 'string')
@@ -516,6 +520,9 @@ module.BaseStore = {
__delete__: async function(path){
delete this.data[path] },
delete: async function(path){
+ // read-only...
+ if(this.__delete__ == null){
+ return this }
path = await this.exists(path)
path
&& await this.__delete__(path)
@@ -824,90 +831,6 @@ async function(base, sub, options){
return target ?
fs.promises.readFile(target, {encoding: 'utf-8'})
: undefined }
-// NOTE: backing up ** will include nested backups...
-// XXX add versioning...
-var backup =
-module.backup =
-async function(base, sub, options){
- var {index, backup, verbose, recursive, cleanBackup} =
- Object.assign({},
- FILESTORE_OPTIONS,
- options ?? {})
- recursive = recursive ?? false
-
- var _backup = backup
- backup =
- module.path.join(
- base,
- module.path.relative(sub, backup))
-
- // ** or * -- backup each file in path...
- if(/[\\\/]*\*\*?$/.test(sub)){
- if(cleanBackup
- && fs.existsSync(backup)){
- verbose
- && console.log('backup(..): cleaning:', backup)
- await fs.promises.rm(backup, {recursive: true}) }
- if(sub.endsWith('**')){
- options = {
- ...(options ?? {}),
- recursive: true,
- } }
- sub = sub.replace(/[\\\/]*\*\*?$/, '')
- // XXX should we ignore only the first element (current) or the sub-path???
- var b = module.path.split(_backup)
- .filter(function(p){
- return p != '' })
- .shift()
- return fs.promises.readdir(base +'/'+ sub)
- .iter()
- // skip backups...
- .filter(function(file){
- return !file.includes(b) })
- .map(async function(file){
- return await module.backup(base, sub +'/'+ file, options) })
- // keep only the paths we backed up...
- .filter(function(e){
- return !!e })
-
- // backup single page...
- } else {
- var target = module.path.join(base, sub)
- var full = _backup[0] == '/'
-
- // nothing to backup...
- if(!fs.existsSync(target)){
- verbose
- && console.log('backup(..): target does not exist:', target)
- return }
-
- if(!recursive){
- var stat = await fs.promises.stat(target)
- if(stat.isDirectory()){
- sub += '/'+index
- target += '/'+index
- // nothing to backup...
- if(!fs.existsSync(target)){
- verbose
- && console.log('backup(..): nothing to backup:', target)
- return } } }
-
- var to = full ?
- backup +'/'+ sub
- : backup +'/'+ module.path.basename(sub)
- var todir = module.path.dirname(to)
-
- verbose
- && console.log('backup(..):', sub, '->', to)
- await fs.promises.mkdir(todir, {recursive: true})
- await fs.promises.cp(target, to, {force: true, recursive})
- return to } }
-// XXX
-var restore =
-module.restore =
-async function(base, sub, options){
- // XXX
-}
var mkdir =
module.mkdir =
async function(base, sub, options){
@@ -1063,7 +986,117 @@ async function(base, options){
continue }
} } }) }
+//
+// backing([, ])
+// backing(, '**'[, ])
+// backing(, '**', Date.timeStamp()[, ])
+// ->
+//
+// backing(, [, ][, ])
+// ->
+//
+// backing(, , false[, ])
+// ->
+//
+// NOTE: backing up ** will include nested backups but will skip the
+// root backup...
+// NOTE: currently this ignores only the first element of the options.backup
+// path.
+var backup =
+module.backup =
+async function(base, sub='**', version=Date.timeStamp(), options){
+ if(typeof(sub) == 'object'){
+ options = sub
+ sub = '**' }
+ if(typeof(version) == 'object'){
+ options = version
+ version = Date.timeStamp() }
+ // options...
+ var {index, backup, verbose, recursive, cleanBackup} =
+ Object.assign({},
+ FILESTORE_OPTIONS,
+ options ?? {})
+ recursive = recursive ?? false
+ var _backup = backup =
+ version ?
+ module.path.join(backup, version)
+ : backup
+ backup =
+ module.path.join(
+ base,
+ module.path.relative(sub, backup))
+
+ // ** or * -- backup each file in path...
+ if(/[\\\/]*\*\*?$/.test(sub)){
+ if(cleanBackup
+ && fs.existsSync(backup)){
+ verbose
+ && console.log('backup(..): cleaning:', backup)
+ await fs.promises.rm(backup, {recursive: true}) }
+ if(sub.endsWith('**')){
+ options = {
+ ...(options ?? {}),
+ recursive: true,
+ } }
+ sub = sub.replace(/[\\\/]*\*\*?$/, '')
+ // XXX should we ignore only the first element (current) or the sub-path???
+ var b = module.path.split(_backup)
+ .filter(function(p){
+ return p != '' })
+ .shift()
+ return fs.promises.readdir(base +'/'+ sub)
+ .iter()
+ // skip backups...
+ .filter(function(file){
+ return !file.includes(b) })
+ .map(async function(file){
+ return await module.backup(base, sub +'/'+ file, version, options) })
+ // keep only the paths we backed up...
+ .filter(function(e){
+ return !!e })
+
+ // backup single page...
+ } else {
+ var target = module.path.join(base, sub)
+ var full = _backup[0] == '/'
+
+ // nothing to backup...
+ if(!fs.existsSync(target)){
+ verbose
+ && console.log('backup(..): target does not exist:', target)
+ return }
+
+ if(!recursive){
+ var stat = await fs.promises.stat(target)
+ if(stat.isDirectory()){
+ sub += '/'+index
+ target += '/'+index
+ // nothing to backup...
+ if(!fs.existsSync(target)){
+ verbose
+ && console.log('backup(..): nothing to backup:', target)
+ return } } }
+
+ var to = full ?
+ backup +'/'+ sub
+ : backup +'/'+ module.path.basename(sub)
+ var todir = module.path.dirname(to)
+
+ verbose
+ && console.log('backup(..):', sub, '->', to)
+ await fs.promises.mkdir(todir, {recursive: true})
+ await fs.promises.cp(target, to, {force: true, recursive})
+ return to } }
+// XXX
+var restore =
+module.restore =
+async function(base, sub, version, options){
+ // XXX
+}
+
+
+// XXX might be a good idea to support ro mode on top level explicitly...
// XXX add monitor API + cache + live mode (auto on when lock detected)...
var FileStoreRO =
module.FileStoreRO = {