mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-27 02:51:57 +02:00
Add support for handling deleted root document in RestoreManager (#28008)
* Skip opening root document if delete originated from a file-restore * handle project-restore origin * Refactor isFileRestore logic * Add support for handling deleted root document in RestoreManager GitOrigin-RevId: 837144aa6e269cbffebf82624f58e8219fe654c4
This commit is contained in:
committed by
Copybot
parent
d82dcc382a
commit
511d2d104b
@@ -79,6 +79,7 @@ const RestoreManager = {
|
||||
) {
|
||||
const project = await ProjectGetter.promises.getProject(projectId, {
|
||||
overleaf: true,
|
||||
rootDoc_id: true,
|
||||
})
|
||||
if (!project?.overleaf?.history?.rangesSupportEnabled) {
|
||||
throw new OError('project does not have ranges support', { projectId })
|
||||
@@ -125,6 +126,7 @@ const RestoreManager = {
|
||||
pathname
|
||||
)
|
||||
|
||||
let hadDeletedRootFile = false
|
||||
if (file) {
|
||||
if (file.type !== 'doc' && file.type !== 'file') {
|
||||
throw new OError('unexpected file type', { type: file.type })
|
||||
@@ -140,6 +142,11 @@ const RestoreManager = {
|
||||
origin,
|
||||
userId
|
||||
)
|
||||
|
||||
if (file.element._id.toString() === project.rootDoc_id.toString()) {
|
||||
hadDeletedRootFile = true
|
||||
}
|
||||
|
||||
threadIds.delete(file.element._id.toString())
|
||||
}
|
||||
|
||||
@@ -274,6 +281,11 @@ const RestoreManager = {
|
||||
origin,
|
||||
userId
|
||||
)
|
||||
|
||||
if (hadDeletedRootFile) {
|
||||
await EditorController.promises.setRootDoc(projectId, _id)
|
||||
}
|
||||
|
||||
// For revertProject: The next doc that gets reverted will need to duplicate all the threads seen here.
|
||||
threadIds.set(
|
||||
_id.toString(),
|
||||
|
||||
@@ -225,7 +225,10 @@ describe('RestoreManager', function () {
|
||||
this.ProjectGetter.promises.getProject = sinon.stub()
|
||||
this.ProjectGetter.promises.getProject
|
||||
.withArgs(this.project_id)
|
||||
.resolves({ overleaf: { history: { rangesSupportEnabled: true } } })
|
||||
.resolves({
|
||||
overleaf: { history: { rangesSupportEnabled: true } },
|
||||
rootDoc_id: 'root-doc-id',
|
||||
})
|
||||
this.RestoreManager.promises._writeFileVersionToDisk = sinon
|
||||
.stub()
|
||||
.resolves((this.fsPath = '/tmp/path/on/disk'))
|
||||
@@ -405,6 +408,13 @@ describe('RestoreManager', function () {
|
||||
|
||||
describe('with an existing file in the current project', function () {
|
||||
beforeEach(async function () {
|
||||
this.ProjectGetter.promises.getProject = sinon.stub()
|
||||
this.ProjectGetter.promises.getProject
|
||||
.withArgs(this.project_id)
|
||||
.resolves({
|
||||
overleaf: { history: { rangesSupportEnabled: true } },
|
||||
rootDoc_id: 'root-doc-id',
|
||||
})
|
||||
this.ProjectLocator.promises.findElementByPath = sinon
|
||||
.stub()
|
||||
.resolves({ type: 'file', element: { _id: 'mock-file-id' } })
|
||||
@@ -438,6 +448,13 @@ describe('RestoreManager', function () {
|
||||
|
||||
describe('with an existing document in the current project', function () {
|
||||
beforeEach(async function () {
|
||||
this.ProjectGetter.promises.getProject = sinon.stub()
|
||||
this.ProjectGetter.promises.getProject
|
||||
.withArgs(this.project_id)
|
||||
.resolves({
|
||||
overleaf: { history: { rangesSupportEnabled: true } },
|
||||
rootDoc_id: 'root-doc-id',
|
||||
})
|
||||
this.ProjectLocator.promises.findElementByPath = sinon
|
||||
.stub()
|
||||
.resolves({ type: 'doc', element: { _id: 'mock-file-id' } })
|
||||
@@ -512,6 +529,13 @@ describe('RestoreManager', function () {
|
||||
describe('with comments in same doc', function () {
|
||||
// copy of the above, addition: inject and later inspect threadIds set
|
||||
beforeEach(async function () {
|
||||
this.ProjectGetter.promises.getProject = sinon.stub()
|
||||
this.ProjectGetter.promises.getProject
|
||||
.withArgs(this.project_id)
|
||||
.resolves({
|
||||
overleaf: { history: { rangesSupportEnabled: true } },
|
||||
rootDoc_id: 'root-doc-id',
|
||||
})
|
||||
this.ProjectLocator.promises.findElementByPath = sinon
|
||||
.stub()
|
||||
.resolves({ type: 'doc', element: { _id: 'mock-file-id' } })
|
||||
@@ -595,6 +619,13 @@ describe('RestoreManager', function () {
|
||||
describe('with remapped comments during revertProject', function () {
|
||||
// copy of the above, addition: inject and later inspect threadIds set
|
||||
beforeEach(async function () {
|
||||
this.ProjectGetter.promises.getProject = sinon.stub()
|
||||
this.ProjectGetter.promises.getProject
|
||||
.withArgs(this.project_id)
|
||||
.resolves({
|
||||
overleaf: { history: { rangesSupportEnabled: true } },
|
||||
rootDoc_id: 'root-doc-id',
|
||||
})
|
||||
this.ProjectLocator.promises.findElementByPath = sinon
|
||||
.stub()
|
||||
.resolves({ type: 'doc', element: { _id: 'mock-file-id' } })
|
||||
@@ -645,6 +676,79 @@ describe('RestoreManager', function () {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when restored file has the same id as root doc', function () {
|
||||
beforeEach(async function () {
|
||||
this.ProjectGetter.promises.getProject = sinon.stub()
|
||||
this.ProjectGetter.promises.getProject
|
||||
.withArgs(this.project_id)
|
||||
.resolves({
|
||||
overleaf: { history: { rangesSupportEnabled: true } },
|
||||
rootDoc_id: 'root-doc-id',
|
||||
})
|
||||
this.ProjectLocator.promises.findElementByPath = sinon
|
||||
.stub()
|
||||
.resolves({ type: 'doc', element: { _id: 'root-doc-id' } })
|
||||
this.EditorController.promises.deleteEntity = sinon.stub().resolves()
|
||||
this.EditorController.promises.addDocWithRanges = sinon
|
||||
.stub()
|
||||
.resolves((this.addedFile = { _id: 'new-doc-id', type: 'doc' }))
|
||||
this.EditorController.promises.setRootDoc = sinon.stub().resolves()
|
||||
|
||||
this.data = await this.RestoreManager.promises.revertFile(
|
||||
this.user_id,
|
||||
this.project_id,
|
||||
this.version,
|
||||
this.pathname
|
||||
)
|
||||
})
|
||||
|
||||
it('should delete the existing root document', async function () {
|
||||
expect(
|
||||
this.EditorController.promises.deleteEntity
|
||||
).to.have.been.calledWith(
|
||||
this.project_id,
|
||||
'root-doc-id',
|
||||
'doc',
|
||||
{
|
||||
kind: 'file-restore',
|
||||
path: this.pathname,
|
||||
version: this.version,
|
||||
timestamp: new Date(this.endTs).toISOString(),
|
||||
},
|
||||
this.user_id
|
||||
)
|
||||
})
|
||||
|
||||
it('should import the file', function () {
|
||||
expect(
|
||||
this.EditorController.promises.addDocWithRanges
|
||||
).to.have.been.calledWith(
|
||||
this.project_id,
|
||||
this.folder_id,
|
||||
'foo.tex',
|
||||
['foo', 'bar', 'baz'],
|
||||
{ changes: this.tracked_changes, comments: this.remappedComments },
|
||||
{
|
||||
kind: 'file-restore',
|
||||
path: this.pathname,
|
||||
version: this.version,
|
||||
timestamp: new Date(this.endTs).toISOString(),
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('should return the created entity with root doc id', function () {
|
||||
expect(this.data).to.deep.equal(this.addedFile)
|
||||
expect(this.data._id).to.equal('new-doc-id')
|
||||
})
|
||||
|
||||
it('should set the restored document as the new root doc', function () {
|
||||
expect(
|
||||
this.EditorController.promises.setRootDoc
|
||||
).to.have.been.calledWith(this.project_id, this.addedFile._id)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('reverting a file or document with metadata', function () {
|
||||
|
||||
Reference in New Issue
Block a user