git.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. "use strict";
  2. var NodeGit = require("nodegit"),
  3. Promise = require('bluebird'),
  4. path = require('path'),
  5. os = require('os'),
  6. fs = Promise.promisifyAll(require("fs")),
  7. _ = require('lodash');
  8. /**
  9. * Git Model
  10. */
  11. module.exports = {
  12. _git: null,
  13. _repo: {
  14. path: '',
  15. branch: 'master',
  16. exists: false,
  17. inst: null,
  18. sync: true
  19. },
  20. _opts: {
  21. clone: {},
  22. push: {}
  23. },
  24. /**
  25. * Initialize Git model
  26. *
  27. * @param {Object} appconfig The application config
  28. * @return {Object} Git model instance
  29. */
  30. init(appconfig) {
  31. let self = this;
  32. //-> Build repository path
  33. if(_.isEmpty(appconfig.git.path) || appconfig.git.path === 'auto') {
  34. self._repo.path = path.join(ROOTPATH, 'repo');
  35. } else {
  36. self._repo.path = appconfig.git.path;
  37. }
  38. //-> Initialize repository
  39. self._initRepo(appconfig).then((repo) => {
  40. self._repo.inst = repo;
  41. if(self._repo.sync) {
  42. self.resync();
  43. }
  44. });
  45. return self;
  46. },
  47. /**
  48. * Initialize Git repository
  49. *
  50. * @param {Object} appconfig The application config
  51. * @return {Object} Promise
  52. */
  53. _initRepo(appconfig) {
  54. let self = this;
  55. winston.info('[GIT] Initializing Git repository...');
  56. //-> Check if path is accessible
  57. return fs.mkdirAsync(self._repo.path).catch((err) => {
  58. if(err.code !== 'EEXIST') {
  59. winston.error('Invalid Git repository path or missing permissions.');
  60. }
  61. }).then(() => {
  62. //-> Check if path already contains a git working folder
  63. return fs.statAsync(path.join(self._repo.path, '.git')).then((stat) => {
  64. self._repo.exists = stat.isDirectory();
  65. }).catch((err) => {
  66. self._repo.exists = false;
  67. });
  68. }).then(() => {
  69. //-> Init repository
  70. let repoInitOperation = null;
  71. self._repo.branch = appconfig.git.branch;
  72. self._repo.sync = appconfig.git.remote;
  73. self._opts.clone = self._generateCloneOptions(appconfig);
  74. self._opts.push = self._generatePushOptions(appconfig);
  75. if(self._repo.exists) {
  76. winston.info('[GIT] Using existing repository...');
  77. repoInitOperation = NodeGit.Repository.open(self._repo.path);
  78. } else if(appconfig.git.remote) {
  79. winston.info('[GIT] Cloning remote repository for first time...');
  80. repoInitOperation = NodeGit.Clone(appconfig.git.url, self._repo.path, self._opts.clone);
  81. } else {
  82. winston.info('[GIT] Using offline local repository...');
  83. repoInitOperation = NodeGit.Repository.init(self._repo.path, 0);
  84. }
  85. return repoInitOperation;
  86. }).catch((err) => {
  87. winston.error('Unable to open or clone Git repository!');
  88. winston.error(err);
  89. }).then((repo) => {
  90. if(self._repo.sync) {
  91. NodeGit.Remote.setPushurl(repo, 'origin', appconfig.git.url);
  92. }
  93. return repo;
  94. winston.info('[GIT] Git repository is now ready.');
  95. });
  96. },
  97. /**
  98. * Generate Clone Options object
  99. *
  100. * @param {Object} appconfig The application configuration
  101. * @return {Object} CloneOptions object
  102. */
  103. _generateCloneOptions(appconfig) {
  104. let cloneOptions = new NodeGit.CloneOptions();
  105. cloneOptions.fetchOpts = this._generateFetchOptions(appconfig);
  106. return cloneOptions;
  107. },
  108. _generateFetchOptions(appconfig) {
  109. let fetchOptions = new NodeGit.FetchOptions();
  110. fetchOptions.callbacks = this._generateRemoteCallbacks(appconfig);
  111. return fetchOptions;
  112. },
  113. _generatePushOptions(appconfig) {
  114. let pushOptions = new NodeGit.PushOptions();
  115. pushOptions.callbacks = this._generateRemoteCallbacks(appconfig);
  116. return pushOptions;
  117. },
  118. _generateRemoteCallbacks(appconfig) {
  119. let remoteCallbacks = new NodeGit.RemoteCallbacks();
  120. let credFunc = this._generateCredentials(appconfig);
  121. remoteCallbacks.credentials = () => { return credFunc; };
  122. if(os.type() === 'Darwin') {
  123. remoteCallbacks.certificateCheck = () => { return 1; }; // Bug in OS X, bypass certs check workaround
  124. }
  125. return remoteCallbacks;
  126. },
  127. _generateCredentials(appconfig) {
  128. let cred = null;
  129. switch(appconfig.git.auth.type) {
  130. case 'basic':
  131. cred = NodeGit.Cred.userpassPlaintextNew(
  132. appconfig.git.auth.user,
  133. appconfig.git.auth.pass
  134. );
  135. break;
  136. case 'oauth':
  137. cred = NodeGit.Cred.userpassPlaintextNew(
  138. appconfig.git.auth.token,
  139. "x-oauth-basic"
  140. );
  141. break;
  142. case 'ssh':
  143. cred = NodeGit.Cred.sshKeyNew(
  144. appconfig.git.auth.user,
  145. appconfig.git.auth.publickey,
  146. appconfig.git.auth.privatekey,
  147. appconfig.git.auth.passphrase
  148. );
  149. break;
  150. default:
  151. cred = NodeGit.Cred.defaultNew();
  152. break;
  153. }
  154. return cred;
  155. },
  156. resync() {
  157. let self = this;
  158. // Fetch
  159. return self._repo.inst.fetch('origin', self._opts.clone.fetchOpts)
  160. .catch((err) => {
  161. winston.error('Unable to fetch from git origin!' + err);
  162. })
  163. // Merge
  164. .then(() => {
  165. return self._repo.inst.mergeBranches(self._repo.branch, 'origin/' + self._repo.branch);
  166. })
  167. .catch((err) => {
  168. winston.error('Unable to merge from remote head!' + err);
  169. })
  170. // Push
  171. .then(() => {
  172. return self._repo.inst.getRemote('origin').then((remote) => {
  173. self._repo.inst.getStatus().then(function(arrayStatusFile) {
  174. console.log(arrayStatusFile[0].status());
  175. });
  176. /*remote.push( ["refs/heads/master:refs/heads/master"], self._opts.push ).then((errNum) => {
  177. console.log('DUDE' + errNum);
  178. }).catch((err) => {
  179. console.log(err);
  180. });*/
  181. });
  182. }).catch((err) => {
  183. winston.error('Unable to push to git origin!' + err);
  184. });
  185. }
  186. };