New utils
This commit is contained in:
+61
-7
@@ -87,7 +87,10 @@ function bareOsEmitRaw(ctx, chunk) {
|
||||
return false
|
||||
}
|
||||
|
||||
async function copyPath(ctx, from, to, recursive, followSymlink) {
|
||||
async function copyPath(ctx, from, to, recursive, followSymlink, opts) {
|
||||
const preserve = opts && opts.preserveTime
|
||||
const update = opts && opts.update
|
||||
const verbose = opts && opts.verbose
|
||||
const st = await ctx.vfs.lstat(from)
|
||||
if (!st) {
|
||||
ctx.console.error('cp: ' + from + ': No such file')
|
||||
@@ -97,6 +100,7 @@ async function copyPath(ctx, from, to, recursive, followSymlink) {
|
||||
if (!followSymlink) {
|
||||
const t = await ctx.vfs.readlink(from)
|
||||
await ctx.vfs.symlink(t, to)
|
||||
if (verbose) ctx.console.log("'" + from + "' -> '" + to + "'")
|
||||
return true
|
||||
}
|
||||
const fst = await ctx.vfs.stat(from)
|
||||
@@ -106,7 +110,19 @@ async function copyPath(ctx, from, to, recursive, followSymlink) {
|
||||
ctx.console.error('cp: cannot read ' + from)
|
||||
return false
|
||||
}
|
||||
await ctx.vfs.writeFile(to, buf)
|
||||
if (update) {
|
||||
const dst = await ctx.vfs.lstat(to)
|
||||
if (dst && dst.mtimeMs >= fst.mtimeMs) {
|
||||
if (verbose) ctx.console.log('skipped: ' + to)
|
||||
return true
|
||||
}
|
||||
}
|
||||
const wopts =
|
||||
preserve && typeof fst.mtimeMs === 'number'
|
||||
? { mtimeMs: fst.mtimeMs, ctimeMs: fst.ctimeMs }
|
||||
: {}
|
||||
await ctx.vfs.writeFile(to, buf, wopts)
|
||||
if (verbose) ctx.console.log("'" + from + "' -> '" + to + "'")
|
||||
return true
|
||||
}
|
||||
if (fst.type === 'directory') {
|
||||
@@ -120,8 +136,10 @@ async function copyPath(ctx, from, to, recursive, followSymlink) {
|
||||
if (n === '.bareos_empty') continue
|
||||
const f = from.replace(/\/+$/, '') + '/' + n
|
||||
const t = to.replace(/\/+$/, '') + '/' + n
|
||||
if (!(await copyPath(ctx, f, t, true, followSymlink))) return false
|
||||
if (!(await copyPath(ctx, f, t, true, followSymlink, opts)))
|
||||
return false
|
||||
}
|
||||
if (verbose) ctx.console.log("'" + from + "' -> '" + to + "'")
|
||||
return true
|
||||
}
|
||||
ctx.console.error('cp: cannot copy special file ' + from)
|
||||
@@ -133,7 +151,19 @@ async function copyPath(ctx, from, to, recursive, followSymlink) {
|
||||
ctx.console.error('cp: cannot read ' + from)
|
||||
return false
|
||||
}
|
||||
await ctx.vfs.writeFile(to, buf)
|
||||
if (update) {
|
||||
const dst = await ctx.vfs.lstat(to)
|
||||
if (dst && dst.mtimeMs >= st.mtimeMs) {
|
||||
if (verbose) ctx.console.log('skipped: ' + to)
|
||||
return true
|
||||
}
|
||||
}
|
||||
const wopts =
|
||||
preserve && typeof st.mtimeMs === 'number'
|
||||
? { mtimeMs: st.mtimeMs, ctimeMs: st.ctimeMs }
|
||||
: {}
|
||||
await ctx.vfs.writeFile(to, buf, wopts)
|
||||
if (verbose) ctx.console.log("'" + from + "' -> '" + to + "'")
|
||||
return true
|
||||
}
|
||||
if (st.type === 'directory') {
|
||||
@@ -147,8 +177,9 @@ async function copyPath(ctx, from, to, recursive, followSymlink) {
|
||||
if (n === '.bareos_empty') continue
|
||||
const f = from.replace(/\/+$/, '') + '/' + n
|
||||
const t = to.replace(/\/+$/, '') + '/' + n
|
||||
if (!(await copyPath(ctx, f, t, true, followSymlink))) return false
|
||||
if (!(await copyPath(ctx, f, t, true, followSymlink, opts))) return false
|
||||
}
|
||||
if (verbose) ctx.console.log("'" + from + "' -> '" + to + "'")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -157,6 +188,9 @@ async function copyPath(ctx, from, to, recursive, followSymlink) {
|
||||
async function run(ctx, argv) {
|
||||
let recursive = false
|
||||
let followSymlink = false
|
||||
let update = false
|
||||
let verbose = false
|
||||
let preserveTime = false
|
||||
const paths = []
|
||||
for (let i = 1; i < argv.length; i++) {
|
||||
const a = argv[i]
|
||||
@@ -172,6 +206,23 @@ async function run(ctx, argv) {
|
||||
followSymlink = false
|
||||
continue
|
||||
}
|
||||
if (a === '-u' || a === '--update') {
|
||||
update = true
|
||||
continue
|
||||
}
|
||||
if (a === '-v' || a === '--verbose') {
|
||||
verbose = true
|
||||
continue
|
||||
}
|
||||
if (a === '--preserve' || a === '-p') {
|
||||
preserveTime = true
|
||||
continue
|
||||
}
|
||||
if (a.startsWith('--preserve=')) {
|
||||
const v = a.slice('--preserve='.length)
|
||||
if (v === 'timestamps' || v === 'time' || v === 'all') preserveTime = true
|
||||
continue
|
||||
}
|
||||
if (a === '--') {
|
||||
paths.push(...argv.slice(i + 1))
|
||||
break
|
||||
@@ -184,7 +235,9 @@ async function run(ctx, argv) {
|
||||
paths.push(a)
|
||||
}
|
||||
if (paths.length < 2) {
|
||||
ctx.console.error('usage: cp [-R] [-L|-P] SOURCE... DEST')
|
||||
ctx.console.error(
|
||||
'usage: cp [-R] [-L|-P] [-u] [-v] [-p|--preserve[=timestamps]] SOURCE... DEST'
|
||||
)
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
@@ -202,13 +255,14 @@ async function run(ctx, argv) {
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const opts = { preserveTime, update, verbose }
|
||||
for (const src of sources) {
|
||||
const base = src.replace(/\/+$/, '').split('/').pop() || src
|
||||
const target =
|
||||
destIsDir || sources.length > 1
|
||||
? dest.replace(/\/+$/, '') + '/' + base
|
||||
: dest
|
||||
if (!(await copyPath(ctx, src, target, recursive, followSymlink)))
|
||||
if (!(await copyPath(ctx, src, target, recursive, followSymlink, opts)))
|
||||
ctx.exitCode = 1
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user