DiffManager.coffee 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  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. # Whichever order these are in, there is potential for updates to come in between
  8. # them so that they do not return the same 'latest' versions.
  9. # TODO: If these don't return consistent content, try again.
  10. UpdatesManager.getDocUpdatesWithUserInfo project_id, doc_id, from: fromVersion, to: toVersion, (error, updates) ->
  11. return callback(error) if error?
  12. DocumentUpdaterManager.getDocument project_id, doc_id, (error, content, version) ->
  13. return callback(error) if error?
  14. callback(null, content, version, updates)
  15. getDiff: (project_id, doc_id, fromVersion, toVersion, callback = (error, diff) ->) ->
  16. DiffManager.getDocumentBeforeVersion project_id, doc_id, fromVersion, (error, startingContent, updates) ->
  17. if error?
  18. if error.message == "broken-history"
  19. return callback(null, "history unavailable")
  20. else
  21. return callback(error)
  22. updatesToApply = []
  23. for update in updates.slice().reverse()
  24. if update.v <= toVersion
  25. updatesToApply.push update
  26. try
  27. diff = DiffGenerator.buildDiff startingContent, updatesToApply
  28. catch e
  29. return callback(e)
  30. callback(null, diff)
  31. getDocumentBeforeVersion: (project_id, doc_id, version, callback = (error, document, rewoundUpdates) ->) ->
  32. logger.log project_id: project_id, doc_id: doc_id, version: version, "getting document before version"
  33. DiffManager.getLatestDocAndUpdates project_id, doc_id, version, null, (error, content, version, updates) ->
  34. return callback(error) if error?
  35. # bail out if we hit a broken update
  36. for u in updates when u.broken
  37. return callback new Error "broken-history"
  38. # discard any updates which are ahead of this document version
  39. while updates[0]?.v >= version
  40. updates.shift()
  41. lastUpdate = updates[0]
  42. if lastUpdate? and lastUpdate.v != version - 1
  43. return callback new Error("latest update version, #{lastUpdate.v}, does not match doc version, #{version}")
  44. logger.log {docVersion: version, lastUpdateVersion: lastUpdate?.v, updateCount: updates.length}, "rewinding updates"
  45. tryUpdates = updates.slice().reverse()
  46. try
  47. startingContent = DiffGenerator.rewindUpdates content, tryUpdates
  48. # tryUpdates is reversed, and any unapplied ops are marked as broken
  49. catch e
  50. return callback(e)
  51. callback(null, startingContent, tryUpdates)