DiffManager.coffee 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. UpdatesManager = require "./UpdatesManager"
  2. DocumentUpdaterManager = require "./DocumentUpdaterManager"
  3. DiffGenerator = require "./DiffGenerator"
  4. logger = require "logger-sharelatex"
  5. module.exports = DiffManager =
  6. getLatestDocAndUpdates: (project_id, doc_id, fromVersion, toVersion, callback = (error, content, version, updates) ->) ->
  7. # retrieve the document before retreiving the updates,
  8. # because updates are written to mongo after the document
  9. DocumentUpdaterManager.getDocument project_id, doc_id, (error, content, version) ->
  10. return callback(error) if error?
  11. UpdatesManager.getDocUpdatesWithUserInfo project_id, doc_id, from: fromVersion, to: toVersion, (error, updates) ->
  12. return callback(error) if error?
  13. callback(null, content, version, updates)
  14. getDiff: (project_id, doc_id, fromVersion, toVersion, callback = (error, diff) ->) ->
  15. DiffManager.getDocumentBeforeVersion project_id, doc_id, fromVersion, (error, startingContent, updates) ->
  16. if error?
  17. if error.message == "broken-history"
  18. return callback(null, "history unavailable")
  19. else
  20. return callback(error)
  21. updatesToApply = []
  22. for update in updates.slice().reverse()
  23. if update.v <= toVersion
  24. updatesToApply.push update
  25. try
  26. diff = DiffGenerator.buildDiff startingContent, updatesToApply
  27. catch e
  28. return callback(e)
  29. callback(null, diff)
  30. getDocumentBeforeVersion: (project_id, doc_id, version, callback = (error, document, rewoundUpdates) ->) ->
  31. logger.log project_id: project_id, doc_id: doc_id, version: version, "getting document before version"
  32. DiffManager.getLatestDocAndUpdates project_id, doc_id, version, null, (error, content, version, updates) ->
  33. return callback(error) if error?
  34. # bail out if we hit a broken update
  35. for u in updates when u.broken
  36. return callback new Error "broken-history"
  37. # discard any updates which are ahead of this document version
  38. while updates[0]?.v >= version
  39. updates.shift()
  40. lastUpdate = updates[0]
  41. if lastUpdate? and lastUpdate.v != version - 1
  42. return callback new Error("latest update version, #{lastUpdate.v}, does not match doc version, #{version}")
  43. logger.log {docVersion: version, lastUpdateVersion: lastUpdate?.v, updateCount: updates.length}, "rewinding updates"
  44. tryUpdates = updates.slice().reverse()
  45. try
  46. startingContent = DiffGenerator.rewindUpdates content, tryUpdates
  47. # tryUpdates is reversed, and any unapplied ops are marked as broken
  48. catch e
  49. return callback(e)
  50. callback(null, startingContent, tryUpdates)