@@ -2,7 +2,7 @@ import { h, Component } from 'preact'; | |||
import WBTable from 'wb-table'; | |||
import WBBreadcrumbs from 'wb-breadcrumbs'; | |||
import { WBManifestReader } from 'wb-collection-manifest'; | |||
// import WBManifestReader from 'wb-manifest-reader'; | |||
//import WBManifestReader from 'wb-manifest-reader'; | |||
import WBPagination from 'wb-pagination'; | |||
import makeArvadosRequest from 'make-arvados-request'; | |||
import wbDownloadFile from 'wb-download-file'; | |||
@@ -43,7 +43,7 @@ class WBManifestReader { | |||
dir[fileName] = [[], 0]; | |||
if (!(dir[fileName] instanceof Array)) | |||
throw Error('Conflict trying to create a file - a directory with the same name already exists: ' + fileName); | |||
this.appendReferences(dir[fileName], locators, position, size); | |||
//this.appendReferences(dir[fileName], locators, position, size); | |||
} | |||
appendReferences(file, locators, position, size) { | |||
@@ -18,16 +18,28 @@ function mkpath(parent, path) { | |||
return dir; | |||
} | |||
function appendFile(dir, name, sidx, seg) { | |||
if (name in dir && (!(dir[name] instanceof Array))) | |||
throw Error('Directory with the same name already exists'); | |||
if (!(name in dir)) | |||
dir[name] = []; | |||
const f = dir[name]; | |||
f.push([ sidx, seg[0], seg[1] ]); | |||
function makeFile(dir, name) { | |||
if (name in dir) { | |||
if (!(dir[name] instanceof Array)) | |||
throw Error('Directory with the same name already exists'); | |||
return dir[name]; | |||
} | |||
const f = [[], 0]; | |||
dir[name] = f; | |||
return f; | |||
} | |||
function appendFile(f, sidx, seg) { | |||
f[0].push([ sidx, seg[0], seg[1] ]); | |||
//f[1] += seg[1]; | |||
return f; | |||
} | |||
function unescapeName(name) { | |||
return name.replace(/(\\\\|\\[0-9]{3})/g, | |||
(_, $1) => ($1 === '\\\\' ? '\\' : String.fromCharCode(parseInt($1.substr(1), 8)))); | |||
} | |||
function process(streams) { | |||
const rootDir = {}; | |||
@@ -55,19 +67,22 @@ function parse(manifestText) { | |||
const streams = []; | |||
let locators = []; | |||
let segments = []; | |||
let streamName; | |||
let accum = ''; | |||
let tokenStart = 0; | |||
let lastFile = null; | |||
let lastPath = null; | |||
const rootDir = {}; | |||
for (let i = 0; i < manifestText.length; i++) { | |||
const c = manifestText[i]; | |||
if (mode === M_STREAM_NAME) { | |||
if (c === ' ') { | |||
mode = M_LOCATORS; | |||
streamName = accum; | |||
streamName = unescapeName(accum); | |||
accum = ''; | |||
tokenStart = i + 1; | |||
} else { | |||
@@ -97,14 +112,26 @@ function parse(manifestText) { | |||
} else if (mode === M_FILE_SEGMENTS) { | |||
if (c === ' ' || c === '\n') { | |||
let seg = accum.split(':'); | |||
seg = [Number(seg[0]), Number(seg[1]), seg[2]]; | |||
segments.push(seg); | |||
seg = [Number(seg[0]), Number(seg[1]), seg.slice(2).join(':')]; | |||
const path = streamName + '/' + unescapeName(seg[2]); | |||
let f; | |||
if (path !== lastPath) { | |||
let dirName = path.split('/'); | |||
const fileName = dirName[dirName.length - 1]; | |||
dirName = dirName.slice(0, dirName.length - 1); | |||
const dir = mkpath(rootDir, dirName); | |||
f = makeFile(dir, fileName); | |||
lastPath = path; | |||
lastFile = f; | |||
} else { | |||
f = lastFile; | |||
} | |||
appendFile(f, streams.length, seg); | |||
accum = ''; | |||
tokenStart = i + 1; | |||
if (c === '\n') { | |||
streams.push([streamName, locators, segments]); | |||
streams.push([ streamName, locators ]); | |||
locators = []; | |||
segments = []; | |||
mode = M_STREAM_NAME; | |||
} | |||
} else { | |||
@@ -114,13 +141,40 @@ function parse(manifestText) { | |||
} | |||
} | |||
return streams; | |||
return { rootDir, streams }; | |||
} | |||
function findDir(parent, path) { | |||
if (typeof(path) === 'string') | |||
path = path.split('/'); | |||
if (path[0] !== '.') | |||
throw Error('Path must start with a dot (.)'); | |||
let dir = parent; | |||
for (let i = 1; i < path.length; i++) { | |||
if (!(path[i] in dir)) | |||
throw Error('Directory not found'); | |||
dir = dir[path[i]]; | |||
} | |||
return dir; | |||
} | |||
class WBManifestReader { | |||
constructor(manifestText) { | |||
this.streams = parse(manifestText); | |||
this.rootDir = process(this.streams); | |||
const {rootDir, streams} = parse(manifestText); | |||
this.rootDir = rootDir; | |||
this.streams = streams; | |||
//this.rootDir = process(this.streams); | |||
} | |||
listDirectory(path) { | |||
let dir = findDir(this.rootDir, path); | |||
let keys = Object.keys(dir); | |||
keys.sort(); | |||
let subdirs = keys.filter(k => !(dir[k] instanceof Array)); | |||
let files = keys.filter(k => (dir[k] instanceof Array)); | |||
let res = subdirs.map(k => [ 'd', k, null ]); | |||
res = res.concat(files.map(k => [ 'f', k, dir[k][1] ])); | |||
return res; | |||
} | |||
} | |||
@@ -0,0 +1,181 @@ | |||
function mkdir(parent, name) { | |||
if (name in parent && (parent[name] instanceof Array)) | |||
throw Error('File with the same name already exists'); | |||
if (name in parent) | |||
return parent[name]; | |||
const dir = {}; | |||
parent[name] = dir; | |||
return dir; | |||
} | |||
function mkpath(parent, path) { | |||
if (typeof(path) === 'string') | |||
path = path.split('/'); | |||
let dir = parent; | |||
for (let i = 1; i < path.length; i++) { | |||
dir = mkdir(dir, path[i]); | |||
} | |||
return dir; | |||
} | |||
function makeFile(dir, name) { | |||
if (name in dir) { | |||
if (!(dir[name] instanceof Array)) | |||
throw Error('Directory with the same name already exists'); | |||
return dir[name]; | |||
} | |||
const f = [[], 0]; | |||
dir[name] = f; | |||
return f; | |||
} | |||
function appendFile(f, sidx, seg) { | |||
f[0].push([ sidx, seg[0], seg[1] ]); | |||
//f[1] += seg[1]; | |||
return f; | |||
} | |||
function unescapeName(name) { | |||
return name.replace(/(\\\\|\\[0-9]{3})/g, | |||
(_, $1) => ($1 === '\\\\' ? '\\' : String.fromCharCode(parseInt($1.substr(1), 8)))); | |||
} | |||
function process(streams) { | |||
const rootDir = {}; | |||
streams.map((s, sidx) => { | |||
const [ streamName, locators, segments ] = s; | |||
const streamDir = mkpath(rootDir, streamName); | |||
segments.map((seg, segidx) => { | |||
let name = seg[2].split('/'); | |||
const dir = (name.length === 1 ? streamDir : | |||
mkpath(streamDir, ['.'].concat(name.slice(0, name.length - 1)))); | |||
name = name[name.length - 1]; | |||
appendFile(dir, name, sidx, seg); | |||
}); | |||
}); | |||
return rootDir; | |||
} | |||
function parse(manifestText) { | |||
const M_STREAM_NAME = 0; | |||
const M_LOCATORS = 1; | |||
const M_FILE_SEGMENTS = 2; | |||
let mode = M_STREAM_NAME; | |||
const streams = []; | |||
let locators = []; | |||
let streamName; | |||
let accum = ''; | |||
let tokenStart = 0; | |||
let lastFile = null; | |||
let lastPath = null; | |||
const rootDir = {}; | |||
for (let i = 0; i < manifestText.length; i++) { | |||
const c = manifestText[i]; | |||
if (mode === M_STREAM_NAME) { | |||
if (c === ' ') { | |||
mode = M_LOCATORS; | |||
streamName = unescapeName(accum); | |||
accum = ''; | |||
tokenStart = i + 1; | |||
} else { | |||
accum += c; | |||
} | |||
} else if (mode === M_LOCATORS) { | |||
if (c === ':') { | |||
mode = M_FILE_SEGMENTS; | |||
accum = ''; | |||
i = tokenStart - 1; | |||
let pos = 0; | |||
locators = locators.map(loc => { | |||
const r = loc.concat([ pos, pos + loc[1] ]); | |||
pos += loc[1]; | |||
return r; | |||
}); | |||
} else if (c === ' ') { | |||
const sz = Number(accum.split('+')[1]); | |||
locators.push([accum, sz]); | |||
accum = ''; | |||
tokenStart = i + 1; | |||
} else { | |||
accum += c; | |||
} | |||
} else if (mode === M_FILE_SEGMENTS) { | |||
if (c === ' ' || c === '\n') { | |||
let seg = accum.split(':'); | |||
seg = [Number(seg[0]), Number(seg[1]), seg.slice(2).join(':')]; | |||
const path = streamName + '/' + unescapeName(seg[2]); | |||
let f; | |||
if (path !== lastPath) { | |||
let dirName = path.split('/'); | |||
const fileName = dirName[dirName.length - 1]; | |||
dirName = dirName.slice(0, dirName.length - 1); | |||
const dir = mkpath(rootDir, dirName); | |||
f = makeFile(dir, fileName); | |||
lastPath = path; | |||
lastFile = f; | |||
} else { | |||
f = lastFile; | |||
} | |||
appendFile(f, streams.length, seg); | |||
accum = ''; | |||
tokenStart = i + 1; | |||
if (c === '\n') { | |||
streams.push([ streamName, locators ]); | |||
locators = []; | |||
mode = M_STREAM_NAME; | |||
} | |||
} else { | |||
accum += c; | |||
} | |||
} | |||
} | |||
return { rootDir, streams }; | |||
} | |||
function findDir(parent, path) { | |||
if (typeof(path) === 'string') | |||
path = path.split('/'); | |||
if (path[0] !== '.') | |||
throw Error('Path must start with a dot (.)'); | |||
let dir = parent; | |||
for (let i = 1; i < path.length; i++) { | |||
if (!(path[i] in dir)) | |||
throw Error('Directory not found'); | |||
dir = dir[path[i]]; | |||
} | |||
return dir; | |||
} | |||
class WBManifestReader { | |||
constructor(manifestText) { | |||
const {rootDir, streams} = parse(manifestText); | |||
this.rootDir = rootDir; | |||
this.streams = streams; | |||
//this.rootDir = process(this.streams); | |||
} | |||
listDirectory(path) { | |||
let dir = findDir(this.rootDir, path); | |||
let keys = Object.keys(dir); | |||
keys.sort(); | |||
let subdirs = keys.filter(k => !(dir[k] instanceof Array)); | |||
let files = keys.filter(k => (dir[k] instanceof Array)); | |||
let res = subdirs.map(k => [ 'd', k, null ]); | |||
res = res.concat(files.map(k => [ 'f', k, dir[k][1] ])); | |||
return res; | |||
} | |||
} | |||
export default WBManifestReader; |