UpdateMerger.coffee 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. _ = require('underscore')
  2. projectLocator = require('../Project/ProjectLocator')
  3. editorController = require('../Editor/EditorController')
  4. logger = require('logger-sharelatex')
  5. Settings = require('settings-sharelatex')
  6. FileTypeManager = require('../Uploads/FileTypeManager')
  7. uuid = require('uuid')
  8. fs = require('fs')
  9. LockManager = require("../../infrastructure/LockManager")
  10. module.exports = UpdateMerger =
  11. mergeUpdate: (user_id, project_id, path, updateRequest, source, callback = (error) ->)->
  12. logger.log project_id:project_id, path:path, "merging update from tpds"
  13. UpdateMerger.p.writeStreamToDisk project_id, updateRequest, (err, fsPath)->
  14. return callback(err) if err?
  15. LockManager.runWithLock project_id,
  16. (cb) => UpdateMerger.mergeUpdateWithoutLock user_id, project_id, path, fsPath, source, cb
  17. (mergeErr) ->
  18. fs.unlink fsPath, (deleteErr) ->
  19. if deleteErr?
  20. logger.err project_id:project_id, fsPath:fsPath, "error deleting file"
  21. callback mergeErr
  22. mergeUpdateWithoutLock: (user_id, project_id, path, fsPath, source, callback = (error) ->)->
  23. projectLocator.findElementByPath project_id, path, (err, element)=>
  24. logger.log {project_id, path, fsPath}, "found element by path for merging update from tpds"
  25. elementId = element?._id
  26. FileTypeManager.isBinary path, fsPath, (err, isFile)->
  27. return callback(err) if err?
  28. if isFile
  29. UpdateMerger.p.processFile project_id, elementId, fsPath, path, source, user_id, callback
  30. else
  31. UpdateMerger.p.processDoc project_id, elementId, user_id, fsPath, path, source, callback
  32. deleteUpdate: (user_id, project_id, path, source, callback)->
  33. LockManager.runWithLock project_id,
  34. (cb) => UpdateMerger.deleteUpdateWithoutLock(user_id, project_id, path, source, cb)
  35. (err, doc) ->
  36. logger.log project_id:project_id, path:path, "finished processing update to delete entity from tpds"
  37. callback()
  38. deleteUpdateWithoutLock: (user_id, project_id, path, source, callback)->
  39. projectLocator.findElementByPath project_id, path, (err, element, type)->
  40. if err? || !element?
  41. logger.log element:element, project_id:project_id, path:path, "could not find entity for deleting, assuming it was already deleted"
  42. return callback()
  43. logger.log project_id:project_id, path:path, type:type, element:element, "processing update to delete entity from tpds"
  44. editorController.deleteEntityWithoutLock project_id, element._id, type, source, user_id, callback
  45. p:
  46. processDoc: (project_id, doc_id, user_id, fsPath, path, source, callback)->
  47. readFileIntoTextArray fsPath, (err, docLines)->
  48. if err?
  49. logger.err project_id:project_id, doc_id:doc_id, fsPath:fsPath, "error reading file into text array for process doc update"
  50. return callback(err)
  51. logger.log docLines:docLines, doc_id:doc_id, project_id:project_id, "processing doc update from tpds"
  52. if doc_id?
  53. editorController.setDoc project_id, doc_id, user_id, docLines, source, callback
  54. else
  55. setupNewEntity project_id, path, (err, folder, fileName)->
  56. if err?
  57. logger.err err:err, project_id:project_id, doc_id:doc_id, path:path, "error processing file"
  58. return callback(err)
  59. editorController.addDocWithoutLock project_id, folder._id, fileName, docLines, source, user_id, callback
  60. processFile: (project_id, file_id, fsPath, path, source, user_id, callback)->
  61. finish = (err)->
  62. logger.log project_id:project_id, file_id:file_id, path:path, "completed processing file update from tpds"
  63. callback(err)
  64. logger.log project_id:project_id, file_id:file_id, path:path, "processing file update from tpds"
  65. setupNewEntity project_id, path, (err, folder, fileName) =>
  66. if err?
  67. logger.err err:err, project_id:project_id, file_id:file_id, path:path, "error processing file"
  68. return callback(err)
  69. else if file_id?
  70. editorController.replaceFileWithoutLock project_id, file_id, fsPath, source, user_id, finish
  71. else
  72. editorController.addFileWithoutLock project_id, folder?._id, fileName, fsPath, source, user_id, finish
  73. writeStreamToDisk: (project_id, stream, callback = (err, fsPath)->)->
  74. dumpPath = "#{Settings.path.dumpFolder}/#{project_id}_#{uuid.v4()}"
  75. writeStream = fs.createWriteStream(dumpPath)
  76. stream.pipe(writeStream)
  77. stream.on 'error', (err)->
  78. logger.err {err, project_id, dumpPath},
  79. "something went wrong with incoming tpds update stream"
  80. writeStream.on 'error', (err)->
  81. logger.err {err, project_id, dumpPath},
  82. "something went wrong with writing tpds update to disk"
  83. stream.on 'end', ->
  84. logger.log {project_id, dumpPath}, "incoming tpds update stream ended"
  85. writeStream.on "finish", ->
  86. logger.log {project_id, dumpPath}, "tpds update write stream finished"
  87. callback null, dumpPath
  88. readFileIntoTextArray = (path, callback)->
  89. fs.readFile path, "utf8", (error, content = "") ->
  90. if error?
  91. logger.err path:path, "error reading file into text array"
  92. return callback(err)
  93. lines = content.split(/\r\n|\n|\r/)
  94. callback error, lines
  95. setupNewEntity = (project_id, path, callback)->
  96. lastIndexOfSlash = path.lastIndexOf("/")
  97. fileName = path[lastIndexOfSlash+1 .. -1]
  98. folderPath = path[0 .. lastIndexOfSlash]
  99. editorController.mkdirpWithoutLock project_id, folderPath, (err, newFolders, lastFolder)->
  100. callback err, lastFolder, fileName