forked from softwarescales/git-issues
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
215 lines (170 loc) · 5.4 KB
/
Copy pathindex.js
File metadata and controls
215 lines (170 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
var util = require('util');
var prompt = require('prompt');
var request = require('request');
var argv = require('optimist')
.alias('username', 'u')
.alias('password', 'p')
.alias('repo', 'r')
.alias('status', 's')
.default('status', 'open')
.argv;
var couleurs = require('couleurs')();
var Table = require('le-table');
var GitUrlParse = require('giturlparse');
var fs = require('fs');
// Table defaults
Table.defaults.marks = {
nw: '┌'
, n: '─'
, ne: '┐'
, e: '│'
, se: '┘'
, s: '─'
, sw: '└'
, w: '│'
, b: ' '
, mt: '┬'
, ml: '├'
, mr: '┤'
, mb: '┴'
, mm: '┼'
};
/**************************************************************************/
/* CONFIGURATION */
/**************************************************************************/
var CONFIG = {
promptSchema: {
properties: {
username: {
pattern: /^[a-zA-Z\s\-]+$/,
message: 'Name must be only letters, spaces, or dashes'
},
password: {
description: 'Password:',
hidden: true
}
}
}
};
var configFilePath = __dirname + "/.git-issues-config.json";
/**************************************************************************/
var status = argv['status'];
var stati = ['closed', 'open'];
if (stati.indexOf(status) === -1) {
console.error('Invalid status choose one of: ' + stati.join(', '));
process.exit(4);
}
prompt.override = argv;
prompt.message = '';
prompt.delimiter = '';
// if a user is present, it must be a strong
var user = argv['username'];
if (user !== undefined && typeof user !== 'string' || user === '') {
console.error('The username (-u) must be a non-empty string');
process.exit(1);
}
// extract and validate the source (github/bitbucket), owner, and name from the repo URL
var son = extractSONFromFromUrl(argv['repo']);
if (['github', 'bitbucket'].indexOf(son.source) === -1) {
console.error('Repository source not supported: ' + son.source);
process.exit(11);
}
//if json config file exists, use its credentials.
if (fs.existsSync(configFilePath)) {
var credentialConfig = require(configFilePath);
console.log("config file found for username: " + credentialConfig.username);
getIssues(son, credentialConfig.username, credentialConfig.password, issuesCallback);
}
else {
console.log("no config file found");
// if a user is provided, we also need a password for the basic authentication
if (user && !argv['password']) {
prompt.get(CONFIG.promptSchema, function (err, result) {
if (err) {
console.error(err);
process.exit(2);
}
// fetch and print the issues
getIssues(son, user, result.password, issuesCallback);
});
} else {
// fetch and print the issues
getIssues(son, user, argv['password'], issuesCallback);
}
}
function issuesCallback(err, issues) {
if (err) {
console.error( err);
process.exit(3);
}
if (!issues || issues.length === 0) {
console.log('No issues in this repository');
process.exit(0);
}
var table = new Table();
table.addRow([
couleurs.bold('#'),
couleurs.bold('Title'),
couleurs.bold('Status')
]);
issues.sort(function (a, b) {
return a.number > b.number;
});
for (var i in issues) {
var cI = issues[i];
table.addRow([cI.number, cI.title, cI.state.toUpperCase()]);
}
console.log(table.toString());
}
/**************************************************************************/
/* IMPLEMENTATION FUNCTIONS
/**************************************************************************/
function getIssues(son, user, pass, callback) {
var provider;
try {
provider = require('./providers/' + son.source);
} catch (err) {}
if (!provider) {
return callback('Provider not supported: ' + son.source);
}
var repoIssueUrl = provider.getIssueApiUrl(son, { status: status });
if (!repoIssueUrl) {
return callback('Missing issue API url format for source: ' + son.source);
}
var options = {
url: repoIssueUrl,
json: true,
headers: {
'user-agent': 'git-issues NPM Module'
}
};
// if a user is provided we
if (user) {
options.auth = {
user: user,
pass: pass
};
}
// fetch the issues from the web
request.get(options, function(err, response, issueRespose) {
if (err) {
return callback(err);
}
if (response.statusCode != 200) {
return callback(issueRespose.error || 'Error: ' + JSON.stringify(issueRespose));
}
// we convert the issues in a common format
// (I took the GitHub format as example)
callback(null, provider.convertIssues(issueRespose));
});
}
function extractSONFromFromUrl(url) {
var parsed = GitUrlParse(url);
if (!parsed.source || !parsed.owner || !parsed.name) {
console.error('Repository URL not supported: ' + parsed._);
process.exit(11);
}
parsed.source = parsed.source.toLowerCase().replace(/\.com$/g, "");
return parsed;
}
/**************************************************************************/