storage.js 5.7 KB

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