storage.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. const path = require('path')
  2. const sgit = require('simple-git/promise')
  3. const fs = require('fs-extra')
  4. const _ = require('lodash')
  5. /**
  6. * Get file extension based on content type
  7. */
  8. const getFileExtension = (contentType) => {
  9. switch (contentType) {
  10. case 'markdown':
  11. return 'md'
  12. case 'html':
  13. return 'html'
  14. default:
  15. return 'txt'
  16. }
  17. }
  18. module.exports = {
  19. git: null,
  20. repoPath: path.join(process.cwd(), 'data/repo'),
  21. async activated() {
  22. // not used
  23. },
  24. async deactivated() {
  25. // not used
  26. },
  27. async init() {
  28. WIKI.logger.info('(STORAGE/GIT) Initializing...')
  29. this.repoPath = path.resolve(WIKI.ROOTPATH, this.config.localRepoPath)
  30. await fs.ensureDir(this.repoPath)
  31. this.git = sgit(this.repoPath)
  32. // Initialize repo (if needed)
  33. WIKI.logger.info('(STORAGE/GIT) Checking repository state...')
  34. const isRepo = await this.git.checkIsRepo()
  35. if (!isRepo) {
  36. WIKI.logger.info('(STORAGE/GIT) Initializing local repository...')
  37. await this.git.init()
  38. }
  39. // Set default author
  40. await this.git.raw(['config', '--local', 'user.email', this.config.defaultEmail])
  41. await this.git.raw(['config', '--local', 'user.name', this.config.defaultName])
  42. // Purge existing remotes
  43. WIKI.logger.info('(STORAGE/GIT) Listing existing remotes...')
  44. const remotes = await this.git.getRemotes()
  45. if (remotes.length > 0) {
  46. WIKI.logger.info('(STORAGE/GIT) Purging existing remotes...')
  47. for(let remote of remotes) {
  48. await this.git.removeRemote(remote.name)
  49. }
  50. }
  51. // Add remote
  52. WIKI.logger.info('(STORAGE/GIT) Setting SSL Verification config...')
  53. await this.git.raw(['config', '--local', '--bool', 'http.sslVerify', _.toString(this.config.verifySSL)])
  54. switch (this.config.authType) {
  55. case 'ssh':
  56. WIKI.logger.info('(STORAGE/GIT) Setting SSH Command config...')
  57. await this.git.addConfig('core.sshCommand', `ssh -i "${this.config.sshPrivateKeyPath}" -o StrictHostKeyChecking=no`)
  58. WIKI.logger.info('(STORAGE/GIT) Adding origin remote via SSH...')
  59. await this.git.addRemote('origin', this.config.repoUrl)
  60. break
  61. default:
  62. WIKI.logger.info('(STORAGE/GIT) Adding origin remote via HTTPS...')
  63. await this.git.addRemote('origin', `https://${this.config.basicUsername}:${this.config.basicPassword}@${this.config.repoUrl}`)
  64. break
  65. }
  66. // Fetch updates for remote
  67. WIKI.logger.info('(STORAGE/GIT) Fetch updates from remote...')
  68. await this.git.raw(['remote', 'update', 'origin'])
  69. // Checkout branch
  70. const branches = await this.git.branch()
  71. if (!_.includes(branches.all, this.config.branch) && !_.includes(branches.all, `remotes/origin/${this.config.branch}`)) {
  72. throw new Error('Invalid branch! Make sure it exists on the remote first.')
  73. }
  74. WIKI.logger.info(`(STORAGE/GIT) Checking out branch ${this.config.branch}...`)
  75. await this.git.checkout(this.config.branch)
  76. // Perform initial sync
  77. await this.sync()
  78. WIKI.logger.info('(STORAGE/GIT) Initialization completed.')
  79. },
  80. async sync() {
  81. // Pull rebase
  82. if (_.includes(['sync', 'pull'], this.mode)) {
  83. WIKI.logger.info(`(STORAGE/GIT) Performing pull rebase from origin on branch ${this.config.branch}...`)
  84. await this.git.pull('origin', this.config.branch, ['--rebase'])
  85. }
  86. // Push
  87. if (_.includes(['sync', 'push'], this.mode)) {
  88. WIKI.logger.info(`(STORAGE/GIT) Performing push to origin on branch ${this.config.branch}...`)
  89. let pushOpts = ['--signed=if-asked']
  90. if (this.mode === 'push') {
  91. pushOpts.push('--force')
  92. }
  93. await this.git.push('origin', this.config.branch, pushOpts)
  94. }
  95. },
  96. async created(page) {
  97. WIKI.logger.info(`(STORAGE/GIT) Committing new file ${page.path}...`)
  98. const fileName = `${page.path}.${getFileExtension(page.contentType)}`
  99. const filePath = path.join(this.repoPath, fileName)
  100. await fs.outputFile(filePath, page.injectMetadata(), 'utf8')
  101. await this.git.add(`./${fileName}`)
  102. await this.git.commit(`docs: create ${page.path}`, fileName, {
  103. '--author': `"${page.authorName} <${page.authorEmail}>"`
  104. })
  105. },
  106. async updated(page) {
  107. WIKI.logger.info(`(STORAGE/GIT) Committing updated file ${page.path}...`)
  108. const fileName = `${page.path}.${getFileExtension(page.contentType)}`
  109. const filePath = path.join(this.repoPath, fileName)
  110. await fs.outputFile(filePath, page.injectMetadata(), 'utf8')
  111. await this.git.add(`./${fileName}`)
  112. await this.git.commit(`docs: update ${page.path}`, fileName, {
  113. '--author': `"${page.authorName} <${page.authorEmail}>"`
  114. })
  115. },
  116. async deleted(page) {
  117. WIKI.logger.info(`(STORAGE/GIT) Committing removed file ${page.path}...`)
  118. const fileName = `${page.path}.${getFileExtension(page.contentType)}`
  119. await this.git.rm(`./${fileName}`)
  120. await this.git.commit(`docs: delete ${page.path}`, fileName, {
  121. '--author': `"${page.authorName} <${page.authorEmail}>"`
  122. })
  123. },
  124. async renamed(page) {
  125. WIKI.logger.info(`(STORAGE/GIT) Committing file move from ${page.sourcePath} to ${page.destinationPath}...`)
  126. const sourceFilePath = `${page.sourcePath}.${getFileExtension(page.contentType)}`
  127. const destinationFilePath = `${page.destinationPath}.${getFileExtension(page.contentType)}`
  128. await this.git.mv(`./${sourceFilePath}`, `./${destinationFilePath}`)
  129. await this.git.commit(`docs: rename ${page.sourcePath} to ${destinationFilePath}`, destinationFilePath, {
  130. '--author': `"${page.authorName} <${page.authorEmail}>"`
  131. })
  132. }
  133. }