You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
3.9 KiB

  1. "use strict";
  2. var Git = require("git-wrapper2-promise"),
  3. Promise = require('bluebird'),
  4. path = require('path'),
  5. os = require('os'),
  6. fs = Promise.promisifyAll(require("fs")),
  7. moment = require('moment'),
  8. _ = require('lodash'),
  9. URL = require('url');
  10. /**
  11. * Git Model
  12. */
  13. module.exports = {
  14. _git: null,
  15. _url: '',
  16. _repo: {
  17. path: '',
  18. branch: 'master',
  19. exists: false,
  20. sync: true
  21. },
  22. _signature: {
  23. name: 'Wiki',
  24. email: 'user@example.com'
  25. },
  26. _opts: {
  27. clone: {},
  28. push: {}
  29. },
  30. /**
  31. * Initialize Git model
  32. *
  33. * @param {Object} appconfig The application config
  34. * @return {Object} Git model instance
  35. */
  36. init(appconfig) {
  37. let self = this;
  38. //-> Build repository path
  39. if(_.isEmpty(appconfig.datadir.repo)) {
  40. self._repo.path = path.join(ROOTPATH, 'repo');
  41. } else {
  42. self._repo.path = appconfig.datadir.repo;
  43. }
  44. //-> Initialize repository
  45. self._initRepo(appconfig).then((repo) => {
  46. if(self._repo.sync) {
  47. self.resync();
  48. }
  49. });
  50. // Define signature
  51. self._signature.name = appconfig.git.signature.name || 'Wiki';
  52. self._signature.email = appconfig.git.signature.email || 'user@example.com';
  53. return self;
  54. },
  55. /**
  56. * Initialize Git repository
  57. *
  58. * @param {Object} appconfig The application config
  59. * @return {Object} Promise
  60. */
  61. _initRepo(appconfig) {
  62. let self = this;
  63. winston.info('[GIT] Checking Git repository...');
  64. //-> Check if path is accessible
  65. return fs.mkdirAsync(self._repo.path).catch((err) => {
  66. if(err.code !== 'EEXIST') {
  67. winston.error('Invalid Git repository path or missing permissions.');
  68. }
  69. }).then(() => {
  70. self._git = new Git({ 'git-dir': self._repo.path });
  71. //-> Check if path already contains a git working folder
  72. return self._git.isRepo().then((isRepo) => {
  73. self._repo.exists = isRepo;
  74. return (!isRepo) ? self._git.exec('init') : true;
  75. }).catch((err) => {
  76. self._repo.exists = false;
  77. });
  78. }).then(() => {
  79. // Initialize remote
  80. let urlObj = URL.parse(appconfig.git.url);
  81. urlObj.auth = appconfig.git.auth.username + ((appconfig.git.auth.type !== 'ssh') ? ':' + appconfig.git.auth.password : '');
  82. self._url = URL.format(urlObj);
  83. return self._git.exec('remote', 'show').then((cProc) => {
  84. let out = cProc.stdout.toString();
  85. if(_.includes(out, 'origin')) {
  86. return true;
  87. } else {
  88. return Promise.join(
  89. self._git.exec('config', ['--local', 'user.name', self._signature.name]),
  90. self._git.exec('config', ['--local', 'user.email', self._signature.email])
  91. ).then(() => {
  92. return self._git.exec('remote', ['add', 'origin', self._url]);
  93. })
  94. }
  95. });
  96. }).catch((err) => {
  97. winston.error('Git remote error!');
  98. throw err;
  99. }).then(() => {
  100. winston.info('[GIT] Git repository is now ready.');
  101. return true;
  102. });
  103. },
  104. resync() {
  105. let self = this;
  106. // Fetch
  107. winston.info('[GIT] Performing pull from remote repository...');
  108. return self._git.pull('origin', self._repo.branch).then((cProc) => {
  109. winston.info('[GIT] Pull completed.');
  110. })
  111. .catch((err) => {
  112. winston.error('Unable to fetch from git origin!');
  113. throw err;
  114. })
  115. .then(() => {
  116. // Check for changes
  117. return self._git.exec('status').then((cProc) => {
  118. let out = cProc.stdout.toString();
  119. if(!_.includes(out, 'nothing to commit')) {
  120. // Add, commit and push
  121. winston.info('[GIT] Performing push to remote repository...');
  122. return self._git.add('-A').then(() => {
  123. return self._git.commit("Resync");
  124. }).then(() => {
  125. return self._git.push('origin', self._repo.branch);
  126. }).then(() => {
  127. return winston.info('[GIT] Push completed.');
  128. });
  129. } else {
  130. winston.info('[GIT] Repository is already up to date. Nothing to commit.');
  131. }
  132. return true;
  133. });
  134. })
  135. .catch((err) => {
  136. winston.error('Unable to push changes to remote!');
  137. throw err;
  138. });
  139. }
  140. };