Skip to content

Commit dae8fc6

Browse files
author
Evan Prodromou
committed
Use ES6 directly; closes #16
1 parent 3cd5e43 commit dae8fc6

5 files changed

+194
-200
lines changed

.gitignore

-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,4 @@ build/Release
2626
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
2727
node_modules
2828

29-
*.js
30-
3129
*~

Cakefile

-31
This file was deleted.

github-todotxt.coffee

-160
This file was deleted.

github-todotxt.js

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
#!/usr/bin/env node
2+
/*
3+
* decaffeinate suggestions:
4+
* DS101: Remove unnecessary use of Array.from
5+
* DS102: Remove unnecessary code created because of implicit returns
6+
* DS207: Consider shorter variations of null checks
7+
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
8+
*/
9+
// github-todotxt.coffee
10+
// Get data from Github issues and format it for todo.txt
11+
//
12+
// Copyright 2016 Evan Prodromou <[email protected]>
13+
//
14+
// Licensed under the Apache License, Version 2.0 (the "License");
15+
// you may not use this file except in compliance with the License.
16+
// You may obtain a copy of the License at
17+
//
18+
// http://www.apache.org/licenses/LICENSE-2.0
19+
//
20+
// Unless required by applicable law or agreed to in writing, software
21+
// distributed under the License is distributed on an "AS IS" BASIS,
22+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23+
// See the License for the specific language governing permissions and
24+
// limitations under the License.
25+
26+
const fs = require('fs');
27+
const path = require('path');
28+
29+
const _ = require('lodash');
30+
const yargs = require('yargs');
31+
const GitHubApi = require('github');
32+
const async = require('async');
33+
const split = require('split');
34+
35+
const { argv } = yargs
36+
.usage('Usage: $0 -t [token]')
37+
.demand('t')
38+
.alias('t', 'token')
39+
.describe('t', 'OAuth token')
40+
.alias('f', 'file')
41+
.describe('f', 'todo.txt file')
42+
.default('f', path.join(process.env.HOME, "Dropbox", "todo", "todo.txt"))
43+
.alias('q', 'quiet')
44+
.describe('q', 'Minimize console output')
45+
.env('GITHUB_TODOTXT')
46+
.alias('c', 'config')
47+
.describe('c', 'Config file')
48+
.default('c', path.join(process.env.HOME, ".github-todotxt.json"))
49+
.config('config')
50+
.help('h')
51+
.alias('h', 'help')
52+
;
53+
54+
const projectCase = str => _.upperFirst(_.camelCase(str));
55+
56+
const token = argv.t;
57+
const filename = argv.f;
58+
const quiet = (argv.q != null);
59+
60+
const note = function(str) {
61+
if (!quiet) {
62+
return process.stdout.write(str);
63+
}
64+
};
65+
66+
const github = new GitHubApi({
67+
debug: false});
68+
69+
github.authenticate({
70+
type: "oauth",
71+
token
72+
});
73+
74+
async.parallel([
75+
function(callback) {
76+
const todos = [];
77+
return fs.createReadStream(filename)
78+
.pipe(split())
79+
.on('data', function(line) {
80+
if (line.match(/\S/)) {
81+
const m = line.match(/issue:(\S+)/);
82+
const todo =
83+
{text: line};
84+
if (m) {
85+
todo.issue = m[1];
86+
}
87+
return todos.push(todo);
88+
}
89+
}).on('error', err => callback(err, null)).on('end', () => callback(null, todos));
90+
},
91+
function(callback) {
92+
var getIssues = function(page, acc, callback) {
93+
note(".");
94+
const props = {
95+
state: "all",
96+
filter: "assigned",
97+
per_page: 100,
98+
page
99+
};
100+
return github.issues.getAll(props, function(err, issues) {
101+
if (err) {
102+
return callback(err);
103+
} else {
104+
acc = _.concat(acc, issues);
105+
if (issues.length >= 100) {
106+
return getIssues(page + 1, acc, callback);
107+
} else {
108+
note("\n");
109+
return callback(null, acc);
110+
}
111+
}
112+
});
113+
};
114+
if (!quiet) {
115+
note("Getting issues...");
116+
}
117+
return getIssues(1, [], callback);
118+
}
119+
], function(err, results) {
120+
if (err) {
121+
return console.error(err);
122+
} else {
123+
let id, number, repo, todo;
124+
const [todos, issues] = Array.from(results);
125+
if (!quiet) {
126+
note(`${todos.length} lines in ${filename}\n`);
127+
note(`${issues.length} issues on Github\n`);
128+
}
129+
for (var issue of Array.from(issues)) {
130+
repo = issue.repository.full_name;
131+
({ number } = issue);
132+
id = `${repo}#${number}`;
133+
todo = _.find(todos, {issue: id});
134+
if (todo != null) {
135+
if (todo.text.match(/^x/)) {
136+
if (issue.state === "open") {
137+
"not closing issue";
138+
}
139+
// XXX: close the github issue
140+
} else {
141+
if (issue.state === "closed") {
142+
note(`Marking line for issue ${id} complete.\n`);
143+
todo.text = `x ${todo.text}`;
144+
}
145+
}
146+
} else if (issue.state === "open") {
147+
note(`Adding line for issue ${id}.\n`);
148+
const ts = issue.created_at.substr(0, 10);
149+
const project = projectCase(repo.split("/")[1]);
150+
const { title } = issue;
151+
let line = `${ts} ${title} issue:${repo}#${number} +${project}`;
152+
if (issue.milestone != null) {
153+
line += ` +${projectCase(issue.milestone.title)}`;
154+
}
155+
todos.push({text: line});
156+
}
157+
}
158+
159+
// Todos with issues that aren't in the list should be marked as done.
160+
161+
for (todo of Array.from(todos)) {
162+
if ((todo.issue == null)) {
163+
continue;
164+
}
165+
if (todo.text.match(/^x/)) {
166+
continue;
167+
}
168+
issue = _.find(issues, function(issue) {
169+
repo = issue.repository.full_name;
170+
({ number } = issue);
171+
id = `${repo}#${number}`;
172+
return id === todo.issue;
173+
});
174+
if ((issue == null)) {
175+
note(`Issue ${todo.issue} not assigned to you; marking it done.\n`);
176+
todo.text = `x ${todo.text}`;
177+
}
178+
}
179+
180+
const backup = `${filename}.bak`;
181+
return async.waterfall([
182+
callback => fs.rename(filename, backup, callback),
183+
function(callback) {
184+
const texts = _.map(todos, "text");
185+
const data = texts.join("\n") + "\n";
186+
return fs.writeFile(filename, data, callback);
187+
}
188+
], function(err) {
189+
if (err) {
190+
return console.error(err);
191+
}
192+
});
193+
}
194+
});

0 commit comments

Comments
 (0)