mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #8701 from overleaf/bg-simple-iterable-paths
simple iterable paths GitOrigin-RevId: f6906016888ccfc95c88858bdac4d2633fc1c5f4
This commit is contained in:
parent
be71ea690d
commit
5a3318f5b3
7 changed files with 53 additions and 15 deletions
15
services/web/app/src/Features/Project/IterablePath.js
Normal file
15
services/web/app/src/Features/Project/IterablePath.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Handles malformed filetrees - when fields such as `folder.docs`,
|
||||
* `folder.folders` or `folder.fileRefs` are missing it returns an
|
||||
* empty array.
|
||||
*/
|
||||
function iterablePaths(folder, field) {
|
||||
if (!folder) {
|
||||
return []
|
||||
}
|
||||
return folder[field] || []
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
iterablePaths,
|
||||
}
|
|
@ -4,6 +4,7 @@ const Errors = require('../Errors/Errors')
|
|||
const ProjectGetter = require('./ProjectGetter')
|
||||
const { promisifyAll } = require('../../util/promises')
|
||||
const OError = require('@overleaf/o-error')
|
||||
const { iterablePaths } = require('./IterablePath')
|
||||
|
||||
const ProjectEntityHandler = {
|
||||
getAllDocs(projectId, callback) {
|
||||
|
@ -26,7 +27,7 @@ const ProjectEntityHandler = {
|
|||
}
|
||||
const docs = {}
|
||||
for (const { path: folderPath, folder } of folders) {
|
||||
for (const doc of folder.docs || []) {
|
||||
for (const doc of iterablePaths(folder, 'docs')) {
|
||||
const content = docContents[doc._id.toString()]
|
||||
if (content != null) {
|
||||
docs[path.join(folderPath, doc.name)] = {
|
||||
|
@ -51,7 +52,7 @@ const ProjectEntityHandler = {
|
|||
}
|
||||
const files = {}
|
||||
for (const { path: folderPath, folder } of folders) {
|
||||
for (const file of folder.fileRefs || []) {
|
||||
for (const file of iterablePaths(folder, 'fileRefs')) {
|
||||
if (file != null) {
|
||||
files[path.join(folderPath, file.name)] = file
|
||||
}
|
||||
|
@ -80,12 +81,12 @@ const ProjectEntityHandler = {
|
|||
const docs = []
|
||||
const files = []
|
||||
for (const { path: folderPath, folder } of folders) {
|
||||
for (const doc of folder.docs || []) {
|
||||
for (const doc of iterablePaths(folder, 'docs')) {
|
||||
if (doc != null) {
|
||||
docs.push({ path: path.join(folderPath, doc.name), doc })
|
||||
}
|
||||
}
|
||||
for (const file of folder.fileRefs || []) {
|
||||
for (const file of iterablePaths(folder, 'fileRefs')) {
|
||||
if (file != null) {
|
||||
files.push({ path: path.join(folderPath, file.name), file })
|
||||
}
|
||||
|
@ -111,7 +112,7 @@ const ProjectEntityHandler = {
|
|||
const folders = ProjectEntityHandler._getAllFoldersFromProject(project)
|
||||
const docPath = {}
|
||||
for (const { path: folderPath, folder } of folders) {
|
||||
for (const doc of folder.docs || []) {
|
||||
for (const doc of iterablePaths(folder, 'docs')) {
|
||||
docPath[doc._id] = path.join(folderPath, doc.name)
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +172,7 @@ const ProjectEntityHandler = {
|
|||
return path.join(basePath, docInCurrentFolder.name)
|
||||
} else {
|
||||
let docPath, childFolder
|
||||
for (childFolder of folder.folders || []) {
|
||||
for (childFolder of iterablePaths(folder, 'folders')) {
|
||||
docPath = recursivelyFindDocInFolder(
|
||||
path.join(basePath, childFolder.name),
|
||||
docId,
|
||||
|
@ -211,7 +212,7 @@ const ProjectEntityHandler = {
|
|||
const processFolder = (basePath, folder) => {
|
||||
folders.push({ path: basePath, folder })
|
||||
if (folder.folders) {
|
||||
for (const childFolder of folder.folders) {
|
||||
for (const childFolder of iterablePaths(folder, 'folders')) {
|
||||
if (childFolder.name != null) {
|
||||
const childPath = path.join(basePath, childFolder.name)
|
||||
processFolder(childPath, childFolder)
|
||||
|
|
|
@ -17,6 +17,7 @@ const ProjectLocator = require('./ProjectLocator')
|
|||
const FolderStructureBuilder = require('./FolderStructureBuilder')
|
||||
const SafePath = require('./SafePath')
|
||||
const { DeletedFile } = require('../../models/DeletedFile')
|
||||
const { iterablePaths } = require('./IterablePath')
|
||||
|
||||
const LOCK_NAMESPACE = 'mongoTransaction'
|
||||
const ENTITY_TYPE_TO_MONGO_PATH_SEGMENT = {
|
||||
|
@ -494,7 +495,7 @@ function _countElements(project) {
|
|||
let total = 0
|
||||
if (folder.folders) {
|
||||
total += folder.folders.length
|
||||
for (const subfolder of folder.folders) {
|
||||
for (const subfolder of iterablePaths(folder, 'folders')) {
|
||||
total += countFolder(subfolder)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ const TpdsUpdateSender = require('../ThirdPartyDataStore/TpdsUpdateSender')
|
|||
const FileWriter = require('../../infrastructure/FileWriter')
|
||||
const EditorRealTimeController = require('../Editor/EditorRealTimeController')
|
||||
const { promisifyAll } = require('../../util/promises')
|
||||
const { iterablePaths } = require('./IterablePath')
|
||||
|
||||
const LOCK_NAMESPACE = 'sequentialProjectStructureUpdateLock'
|
||||
const VALID_ROOT_DOC_EXTENSIONS = Settings.validRootDocExtensions
|
||||
|
@ -1608,16 +1609,16 @@ const ProjectEntityUpdateHandler = {
|
|||
} else if (entityType.indexOf('folder') !== -1) {
|
||||
changes = { oldDocs: [], oldFiles: [] }
|
||||
const _recurseFolder = (folder, folderPath) => {
|
||||
for (const doc of folder.docs) {
|
||||
for (const doc of iterablePaths(folder, 'docs')) {
|
||||
changes.oldDocs.push({ doc, path: Path.join(folderPath, doc.name) })
|
||||
}
|
||||
for (const file of folder.fileRefs) {
|
||||
for (const file of iterablePaths(folder, 'fileRefs')) {
|
||||
changes.oldFiles.push({
|
||||
file,
|
||||
path: Path.join(folderPath, file.name),
|
||||
})
|
||||
}
|
||||
for (const childFolder of folder.folders) {
|
||||
for (const childFolder of iterablePaths(folder, 'folders')) {
|
||||
_recurseFolder(childFolder, Path.join(folderPath, childFolder.name))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ const async = require('async')
|
|||
const ProjectGetter = require('./ProjectGetter')
|
||||
const Errors = require('../Errors/Errors')
|
||||
const { promisifyMultiResult } = require('../../util/promises')
|
||||
const { iterablePaths } = require('./IterablePath')
|
||||
|
||||
function findElement(options, _callback) {
|
||||
// The search algorithm below potentially invokes the callback multiple
|
||||
|
@ -203,19 +204,19 @@ function _findElementByPathWithProject(
|
|||
if (entityName == null) {
|
||||
return cb(null, folder, 'folder')
|
||||
}
|
||||
for (const file of folder.fileRefs || []) {
|
||||
for (const file of iterablePaths(folder, 'fileRefs')) {
|
||||
if (matchFn(file != null ? file.name : undefined, entityName)) {
|
||||
result = file
|
||||
type = 'file'
|
||||
}
|
||||
}
|
||||
for (const doc of folder.docs || []) {
|
||||
for (const doc of iterablePaths(folder, 'docs')) {
|
||||
if (matchFn(doc != null ? doc.name : undefined, entityName)) {
|
||||
result = doc
|
||||
type = 'doc'
|
||||
}
|
||||
}
|
||||
for (const childFolder of folder.folders || []) {
|
||||
for (const childFolder of iterablePaths(folder, 'folders')) {
|
||||
if (
|
||||
matchFn(childFolder != null ? childFolder.name : undefined, entityName)
|
||||
) {
|
||||
|
|
|
@ -9,6 +9,7 @@ const { db, waitForDb } = require('../app/src/infrastructure/mongodb')
|
|||
const Errors = require('../app/src/Features/Errors/Errors')
|
||||
const FileStoreHandler = require('../app/src/Features/FileStore/FileStoreHandler')
|
||||
const ProjectEntityMongoUpdateHandler = require('../app/src/Features/Project/ProjectEntityMongoUpdateHandler')
|
||||
const { iterablePaths } = require('../app/src/Features/Project/IterablePath')
|
||||
|
||||
const OPTIONS = parseArgs()
|
||||
|
||||
|
@ -70,7 +71,7 @@ async function processProject(project) {
|
|||
function findRefsInFolder(folder) {
|
||||
let docIds = folder.docs.map(doc => doc._id)
|
||||
let fileIds = folder.fileRefs.map(file => file._id)
|
||||
for (const subfolder of folder.folders) {
|
||||
for (const subfolder of iterablePaths(folder, 'folders')) {
|
||||
const subrefs = findRefsInFolder(subfolder)
|
||||
docIds = docIds.concat(subrefs.docIds)
|
||||
fileIds = fileIds.concat(subrefs.fileIds)
|
||||
|
|
18
services/web/test/unit/src/Project/IterablePathTests.js
Normal file
18
services/web/test/unit/src/Project/IterablePathTests.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
const { expect } = require('chai')
|
||||
const {
|
||||
iterablePaths,
|
||||
} = require('../../../../app/src/Features/Project/IterablePath')
|
||||
|
||||
describe('iterablePaths', function () {
|
||||
it('returns an empty array for empty folders', function () {
|
||||
expect(iterablePaths(null, 'docs')).to.deep.equal([])
|
||||
expect(iterablePaths({}, 'docs')).to.deep.equal([])
|
||||
})
|
||||
|
||||
it('returns the `docs` object when it is iterable', function () {
|
||||
const folder = {
|
||||
docs: [{ _id: 1 }, { _id: 2 }],
|
||||
}
|
||||
expect(iterablePaths(folder, 'docs')).to.equal(folder.docs)
|
||||
})
|
||||
})
|
Loading…
Reference in a new issue