diff --git a/package.json b/package.json index f0a261fa..471efb3c 100644 --- a/package.json +++ b/package.json @@ -154,6 +154,7 @@ "scim-query-filter-parser": "1.1.0", "semver": "5.6.0", "serve-favicon": "2.5.0", + "simple-git": "1.107.0", "sqlite3": "4.0.6", "subscriptions-transport-ws": "0.9.15", "twemoji": "11.2.0", diff --git a/server/modules/storage/git/storage.js b/server/modules/storage/git/storage.js index ab25ce97..b05d8037 100644 --- a/server/modules/storage/git/storage.js +++ b/server/modules/storage/git/storage.js @@ -1,3 +1,47 @@ +const path = require('path') +const sgit = require('simple-git/promise') +const fs = require('fs-extra') +const _ = require('lodash') + +const repoPath = path.join(WIKI.ROOTPATH, 'data/repo') + +/** + * Get file extension based on content type + */ +const getFileExtension = (contentType) => { + switch (contentType) { + case 'markdown': + return 'md' + case 'html': + return 'html' + default: + return 'txt' + } +} + +/** + * Inject page metadata into contents + */ +const injectMetadata = (page) => { + let meta = [ + ['title', page.title], + ['description', page.description] + ] + let metaFormatted = '' + switch (page.contentType) { + case 'markdown': + metaFormatted = meta.map(mt => `[//]: # ${mt[0]}: ${mt[1]}`).join('\n') + break + case 'html': + metaFormatted = meta.map(mt => ``).join('\n') + break + default: + metaFormatted = meta.map(mt => `#WIKI ${mt[0]}: ${mt[1]}`).join('\n') + break + } + return `${metaFormatted}\n\n${page.content}` +} + module.exports = { async activated() { @@ -6,18 +50,65 @@ module.exports = { }, async init() { + await fs.ensureDir(repoPath) + const git = sgit(repoPath) + + // Initialize repo (if needed) + const isRepo = await git.checkIsRepo() + if (!isRepo) { + await git.init() + } + + // Checkout branch + await git.checkout(this.config.branch) + // Add remote + await git.raw(['config', '--local', '--bool', 'http.sslVerify', _.toString(this.config.verifySSL)]) + switch (this.config.authType) { + case 'ssh': + await git.addConfig('core.sshCommand', `ssh -i "${this.config.sshPrivateKeyPath}" -o StrictHostKeyChecking=no`) + await git.addRemote('origin', this.config.repoUrl) + break + default: + await git.addRemote('origin', `https://${this.config.basicUsername}:${this.config.basicPassword}@${this.config.repoUrl}`) + break + } }, async created() { + const fileName = `${this.page.path}.${getFileExtension(this.page.contentType)}` + const filePath = path.join(repoPath, fileName) + await fs.outputFile(filePath, injectMetadata(this.page), 'utf8') + const git = sgit(repoPath) + await git.add(`./${fileName}`).commit(`docs: create ${this.page.path}`, fileName, { + '--author': `"${this.page.authorName} <${this.page.authorEmail}>"` + }) }, async updated() { + const fileName = `${this.page.path}.${getFileExtension(this.page.contentType)}` + const filePath = path.join(repoPath, fileName) + await fs.outputFile(filePath, injectMetadata(this.page), 'utf8') + const git = sgit(repoPath) + await git.add(`./${fileName}`).commit(`docs: update ${this.page.path}`, fileName, { + '--author': `"${this.page.authorName} <${this.page.authorEmail}>"` + }) }, async deleted() { + const fileName = `${this.page.path}.${getFileExtension(this.page.contentType)}` + const git = sgit(repoPath) + await git.rm(`./${fileName}`).commit(`docs: delete ${this.page.path}`, fileName, { + '--author': `"${this.page.authorName} <${this.page.authorEmail}>"` + }) }, async renamed() { + const sourceFilePath = `${this.page.sourcePath}.${getFileExtension(this.page.contentType)}` + const destinationFilePath = `${this.page.destinationPath}.${getFileExtension(this.page.contentType)}` + const git = sgit(repoPath) + await git.mv(`./${sourceFilePath}`, `./${destinationFilePath}`).commit(`docs: rename ${this.page.sourcePath} to ${destinationFilePath}`, destinationFilePath, { + '--author': `"${this.page.authorName} <${this.page.authorEmail}>"` + }) } }