Skip top-level directory if it exists in zip upload

This commit is contained in:
James Allen 2016-02-24 17:21:20 +00:00
parent d3e3deb679
commit 155831c3e7
4 changed files with 79 additions and 3 deletions

View file

@ -1,6 +1,8 @@
child = require "child_process"
logger = require "logger-sharelatex"
metrics = require "../../infrastructure/Metrics"
fs = require "fs"
Path = require "path"
module.exports = ArchiveManager =
extractZipArchive: (source, destination, _callback = (err) ->) ->
@ -34,4 +36,18 @@ module.exports = ArchiveManager =
error = new Error(error)
logger.error err:error, source: source, destination: destination, "error unzipping file"
callback(error)
findTopLevelDirectory: (directory, callback = (error, topLevelDir) ->) ->
fs.readdir directory, (error, files) ->
return callback(error) if error?
if files.length == 1
childPath = Path.join(directory, files[0])
fs.stat childPath, (error, stat) ->
return callback(error) if error?
if stat.isDirectory()
return callback(null, childPath)
else
return callback(null, directory)
else
return callback(null, directory)

View file

@ -19,9 +19,11 @@ module.exports = ProjectUploadHandler =
destination = @_getDestinationDirectory path
ArchiveManager.extractZipArchive path, destination, (error) ->
return callback(error) if error?
FileSystemImportManager.addFolderContents owner_id, project_id, folder_id, destination, false, (error) ->
ArchiveManager.findTopLevelDirectory destination, (error, topLevelDestination) ->
return callback(error) if error?
rimraf(destination, callback)
FileSystemImportManager.addFolderContents owner_id, project_id, folder_id, topLevelDestination, false, (error) ->
return callback(error) if error?
rimraf(destination, callback)
_getDestinationDirectory: (source) ->
return path.join(path.dirname(source), "#{path.basename(source, ".zip")}-#{Date.now()}")

View file

@ -22,6 +22,7 @@ describe "ArchiveManager", ->
"child_process": @child
"logger-sharelatex": @logger
"../../infrastructure/Metrics": @metrics
"fs": @fs = {}
describe "extractZipArchive", ->
beforeEach ->
@ -69,4 +70,57 @@ describe "ArchiveManager", ->
it "should log out the error", ->
@logger.error.called.should.equal true
describe "findTopLevelDirectory", ->
beforeEach ->
@fs.readdir = sinon.stub()
@fs.stat = sinon.stub()
@directory = "test/directory"
describe "with multiple files", ->
beforeEach ->
@fs.readdir.callsArgWith(1, null, ["multiple", "files"])
@ArchiveManager.findTopLevelDirectory(@directory, @callback)
it "should find the files in the directory", ->
@fs.readdir
.calledWith(@directory)
.should.equal true
it "should return the original directory", ->
@callback
.calledWith(null, @directory)
.should.equal true
describe "with a single file (not folder)", ->
beforeEach ->
@fs.readdir.callsArgWith(1, null, ["foo.tex"])
@fs.stat.callsArgWith(1, null, { isDirectory: () -> false })
@ArchiveManager.findTopLevelDirectory(@directory, @callback)
it "should check if the file is a directory", ->
@fs.stat
.calledWith(@directory + "/foo.tex")
.should.equal true
it "should return the original directory", ->
@callback
.calledWith(null, @directory)
.should.equal true
describe "with a single top-level folder", ->
beforeEach ->
@fs.readdir.callsArgWith(1, null, ["folder"])
@fs.stat.callsArgWith(1, null, { isDirectory: () -> true })
@ArchiveManager.findTopLevelDirectory(@directory, @callback)
it "should check if the file is a directory", ->
@fs.stat
.calledWith(@directory + "/folder")
.should.equal true
it "should return the child directory", ->
@callback
.calledWith(null, @directory + "/folder")
.should.equal true

View file

@ -64,6 +64,7 @@ describe "ProjectUploadManager", ->
@destination = "/path/to/zile/file-extracted"
@ProjectUploadManager._getDestinationDirectory = sinon.stub().returns @destination
@ArchiveManager.extractZipArchive = sinon.stub().callsArg(2)
@ArchiveManager.findTopLevelDirectory = sinon.stub().callsArgWith(1, null, @topLevelDestination = "/path/to/zip/file-extracted/nested")
@FileSystemImportManager.addFolderContents = sinon.stub().callsArg(5)
@ProjectUploadManager.insertZipArchiveIntoFolder @owner_id, @project_id, @folder_id, @source, @callback
@ -74,8 +75,11 @@ describe "ProjectUploadManager", ->
it "should extract the archive", ->
@ArchiveManager.extractZipArchive.calledWith(@source, @destination).should.equal true
it "should find the top level directory", ->
@ArchiveManager.findTopLevelDirectory.calledWith(@destination).should.equal true
it "should insert the extracted archive into the folder", ->
@FileSystemImportManager.addFolderContents.calledWith(@owner_id, @project_id, @folder_id, @destination, false)
@FileSystemImportManager.addFolderContents.calledWith(@owner_id, @project_id, @folder_id, @topLevelDestination, false)
.should.equal true
it "should return the callback", ->