UNPKG

2.97 kBJavaScriptView Raw
1'use strict';
2
3const { exec } = require('child_process');
4require('./logger')();
5
6function fetchGitData(git, cb) {
7 if (!cb) {
8 throw new Error('fetchGitData requires a callback');
9 }
10
11 //-- Malformed/undefined git object
12 if (typeof git === 'undefined') {
13 return cb(new Error('No options passed'));
14 }
15
16 if (!Object.prototype.hasOwnProperty.call(git, 'head')) {
17 return cb(new Error('You must provide the head'));
18 }
19
20 if (!Object.prototype.hasOwnProperty.call(git.head, 'id')) {
21 return cb(new Error('You must provide the head.id'));
22 }
23
24 //-- Set required properties of git if they weren"t provided
25 if (!Object.prototype.hasOwnProperty.call(git, 'branch')) {
26 git.branch = '';
27 }
28
29 if (!Object.prototype.hasOwnProperty.call(git, 'remotes')) {
30 git.remotes = [];
31 }
32
33 //-- Assert the property types
34 if (typeof git.branch !== 'string') {
35 git.branch = '';
36 }
37
38 if (!(Array.isArray(git.remotes))) {
39 git.remotes = [];
40 }
41
42 //-- Use git?
43 exec(`git rev-parse --verify ${git.head.id}`, err => {
44 if (err) {
45 // git is not available...
46 git.head.author_name = git.head.author_name || 'Unknown Author';
47 git.head.author_email = git.head.author_email || '';
48 git.head.committer_name = git.head.committer_name || 'Unknown Committer';
49 git.head.committer_email = git.head.committer_email || '';
50 git.head.message = git.head.message || 'Unknown Commit Message';
51 return cb(null, git);
52 }
53
54 fetchHeadDetails(git, cb);
55 });
56}
57
58function fetchBranch(git, cb) {
59 exec('git branch', (err, branches) => {
60 if (err) {
61 return cb(err);
62 }
63
64 git.branch = (branches.match(/^\* (\w+)/) || [])[1];
65 fetchRemotes(git, cb);
66 });
67}
68
69const REGEX_COMMIT_DETAILS = /\nauthor (.+?) <([^>]*)>.+\ncommitter (.+?) <([^>]*)>.+[\S\s]*?\n\n(.*)/m;
70
71function fetchHeadDetails(git, cb) {
72 exec(`git cat-file -p ${git.head.id}`, (err, response) => {
73 if (err) {
74 return cb(err);
75 }
76
77 const items = response.match(REGEX_COMMIT_DETAILS).slice(1);
78 const fields = ['author_name', 'author_email', 'committer_name', 'committer_email', 'message'];
79 fields.forEach((field, index) => {
80 git.head[field] = items[index];
81 });
82
83 if (git.branch) {
84 fetchRemotes(git, cb);
85 } else {
86 fetchBranch(git, cb);
87 }
88 });
89}
90
91function fetchRemotes(git, cb) {
92 exec('git remote -v', (err, remotes) => {
93 if (err) {
94 return cb(err);
95 }
96
97 const processed = {};
98 remotes.split('\n').forEach(remote => {
99 if (!/\s\(push\)$/.test(remote)) {
100 return;
101 }
102
103 remote = remote.split(/\s+/);
104 saveRemote(processed, git, remote[0], remote[1]);
105 });
106 cb(null, git);
107 });
108}
109
110function saveRemote(processed, git, name, url) {
111 const key = `${name}-${url}`;
112 if (Object.prototype.hasOwnProperty.call(processed, key)) {
113 return;
114 }
115
116 processed[key] = true;
117 git.remotes.push({ name, url });
118}
119
120module.exports = fetchGitData;