• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

suculent / thinx-device-api / #252646970

27 Oct 2017 03:17PM UTC coverage: 12.466% (+1.3%) from 11.197%
#252646970

push

suculent
added support for displaying/exporting extended SigFox attributes

37 of 1808 branches covered (2.05%)

Branch coverage included in aggregate %.

735 of 4385 relevant lines covered (16.76%)

0.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

10.19
/lib/thinx/repository.js
1
/*
2
 * This THiNX-RTM API module is responsible for managing repositories.
3
 */
4

5
var Repository = (function() {
1✔
6

7
        var fs = require("fs-extra");
1✔
8
        var path = require("path");
1✔
9
        var app_config = require("../../conf/config.json"); // this file should be actually omitted from repository
1✔
10
        if (typeof(process.env.CIRCLE_USERNAME) !== "undefined") {
1!
11
                console.log("» Configuring for Circle CI...");
×
12
                app_config = require("../../conf/config-test.json");
×
13
        }
14
        var exec = require("child_process");
1✔
15
        var exit_callback = function(status) {};
1✔
16
        var githooked = require("githooked");
1✔
17
        var search = require("recursive-search");
1✔
18
        var finder = require("fs-finder");
1✔
19
        var Regex = require("regex");
1✔
20

21
        function timeoutFunction(local_path, repeat, callback) {
22
                return function() {
×
23
                        Repository.checkRepositoryChange(local_path, false, callback);
×
24
                };
25
        }
26

27
        console.log("» Starting Git Webhook Listener on port 9001...");
1✔
28

29
        if (typeof(process.env.CIRCLE_USERNAME) === "undefined") {
1!
30

31
                // && platformio run
32
                var gh = githooked("push", function(info) {
1✔
33

34

35
                        var repository = info.repository;
×
36
                        var url = repository.url;
×
37
                        var ssh_url = repository.ssh_url;
×
38
                        var cline_url = repository.clone_url;
×
39
                        var name = repository.name;
×
40
                        var full_name = repository.full_name;
×
41

42
                        if (full_name == "suculent/thinx-device-api") {
×
43
                                console.log(
×
44
                                        "» Skipping own webhook in favour of deploy-hook.sh on port 9000.");
45
                                return;
×
46
                        }
47

48
                        console.log("»» GitHub Webhook called for Git repository: " + full_name);
×
49

50
                        var repositories_path = app_config.project_root +
×
51
                                app_config.build_root;
52

53
                        //repositories = search.recursiveSearchSync(name, repositories_path);
54
                        var repositories = [];
×
55
                        var repo_gits = finder.from(repositories_path).showSystemFiles().findDirectories(
×
56
                                full_name + "/.git");
57

58
                        //console.log("repo_gits: " + JSON.stringify(repo_gits));
59

60
                        if (repo_gits) {
×
61
                                for (var dindex in repo_gits) {
×
62
                                        if (repo_gits[dindex].indexOf("/.git/") === -1) {
×
63
                                                repositories.push(repo_gits[dindex].replace("/.git", ""));
×
64
                                        }
65
                                }
66
                        }
67

68
                        console.log("selected repos: " + JSON.stringify(repositories));
×
69

70
                        if (typeof(this.exit_callback) === "undefined") {
×
71
                                this.exit_callback = function() {
×
72
                                        console.log("Exit callback called when empty.");
×
73
                                };
74
                        }
75

76
                        if (repositories.length > 0) {
×
77
                                console.log("Found " + repositories.length +
×
78
                                        " repositories with name: " + name);
79
                                for (var rindex in repositories) {
×
80
                                        var path = repositories[rindex];
×
81
                                        //console.log("Checking repository changes in " + path);
82
                                        _public.checkRepositoryChange(path, false, this.exit_callback);
×
83
                                }
84
                        } else {
85
                                console.log(name + " not found in " + repositories_path);
×
86
                        }
87

88
                }).listen(9001);
89

90
                githooked().on('push', function(info) {
1✔
91
                        console.log('githooked ref ' + info.ref + ' was pushed.');
×
92
                        console.log(JSON.stringify(info));
×
93
                });
94

95
                githooked().on('delete', function(info) {
1✔
96
                        console.log('githooked ref ' + info.ref + ' was deleted.');
×
97
                        console.log(JSON.stringify(info));
×
98
                });
99

100
                githooked().on('error', function(msg) {
1✔
101
                        console.log("githooked error: " + msg);
×
102
                });
103

104
        }
105

106
        // public
107
        var _public = {
1✔
108

109
                watchRepository: function(local_path, callback) {
110

111
                        if (typeof(callback) !== "undefined") {
×
112
                                this.exit_callback = callback;
×
113
                        } else {
114
                                this.exit_callback = function() {
×
115
                                        return true;
×
116
                                };
117
                        }
118

119
                        if (local_path === null) {
×
120
                                callback(false, "invalid_local_path");
×
121
                        }
122

123
                        console.log("Watching repository: " + local_path);
×
124

125
                        this.watcher = {
×
126
                                repository: local_path,
127
                                callback: callback,
128
                                run: true
129
                        };
130

131
                        if (typeof(callback) === "undefined") {
×
132
                                console.log(
×
133
                                        "[REPOSITORY] Warning, no watch callback given, watching anyway...");
134
                        }
135

136
                        console.log("Starting DEPRECATED repository watcher on " + local_path);
×
137

138
                        _public.checkRepositoryChange(local_path, true, this.exit_callback);
×
139
                },
140

141
                unwatchRepository: function() {
142

143
                        if (this.watcher) {
×
144
                                console.log("[REPOSITORY] Stopping watcher for " + this.watcher.repository);
×
145
                                if (typeof(exit_callback) !== "undefined") {
×
146
                                        exit_callback();
×
147
                                } else {
148
                                        console.log("[REPOSITORY] WARNING! Watcher has no callback.");
×
149
                                }
150
                        } else {
151
                                console.log("[REPOSITORY] unwatchRepository: no watcher... exiting.");
×
152
                                if (typeof(exit_callback) !== "undefined") {
×
153
                                        exit_callback(false);
×
154
                                }
155
                        }
156
                },
157

158
                /*
159
                 * Perform a pull on repository to find out if there are new commits.
160
                 */
161

162
                checkRepositoryChange: function(local_path, repeat, check_callback) {
163

164
                        console.log("[checkRepositoryChange] Checking change by git pull at: " +
×
165
                                local_path);
166

167
                        /* this hack should deprecate */
168
                        if (typeof(check_callback) === "undefined") {
×
169
                                check_callback = function(arg) {};
×
170
                        }
171

172
                        /* whoa whoa who was drunk here? who should throw? */
173
                        if (typeof(local_path) === "undefined" || local_path === null) {
×
174
                                throw new Error('checkRepositoryChange: local_path must be valid');
×
175
                        }
176

177
                        if (local_path === []) {
×
178
                                throw new Error('checkRepositoryChange: local_path must be string');
×
179
                        }
180

181
                        var all_dirs = finder.from(local_path).showSystemFiles().findDirectories(
×
182
                                "\/.git");
183
                        var git_dirs = [];
×
184
                        // filter only git dirs
185
                        for (var dindex in all_dirs) {
×
186
                                var adir = all_dirs[dindex];
×
187
                                if (adir.indexOf(".git") === (adir.length - 4)) {
×
188
                                        git_dirs.push(adir);
×
189
                                }
190
                        }
191

192
                        // In case there is not even one git dir on local path,
193
                        // this is not a directory and rest should be skipped.
194
                        console.log("checkRepositoryChange: git_dirs found: " + JSON.stringify(
×
195
                                git_dirs));
196

197
                        /* This seems whole wrong. Why is the local_path not final?
198

199
                                        // Search for a git repository in root folder is doomed to return false
200
                                        var gitdir = null;
201
                                        if (!fs.existsSync(gitdir)) {
202
                                                //console.log("[REPOSITORY][INFO] Not a git repo here (1): " + gitdir); dommed?
203
                                                // Fetch all repositories on the REPO_PATH/local_path
204
                                                var directories = fs.readdirSync(local_path).filter(
205
                                                        file => fs.lstatSync(path.join(local_path, file)).isDirectory()
206
                                                );
207
                                                // find inner path with git folder, adjust and break
208
                                                for (var dindex in directories) {
209
                                                        var inner_path = local_path + "/" + directories[dindex] + "/.git";
210
                                                        console.log("Traversing inner_path: " + inner_path);
211

212
                                                        if (!fs.existsSync(inner_path)) continue;
213

214
                                                        if (fs.lstatSync(inner_path).isDirectory()) {
215
                                                                console.log("Assigning inner_path: " + inner_path);
216
                                                                var path = local_path + "/" + directories[dindex];
217
                                                                gitdir = path;
218
                                                                console.log("setting git dir to " + path);
219
                                                                break;
220
                                                        }
221
                                                }
222
                                        }
223

224
                                        // dupe from index, extract or use npm!
225
                                        var getNewestFolder = function(dir, regexp) {
226
                                                newest = null;
227
                                                files = fs.readdirSync(dir);
228
                                                one_matched = 0;
229

230
                                                for (i = 0; i < files.length; i++) {
231

232
                                                        if (regexp.test(files[i]) === false) {
233
                                                                continue;
234
                                                        } else if (one_matched === 0) {
235
                                                                newest = dir + "/" + files[i];
236
                                                                one_matched = 1;
237
                                                                continue;
238
                                                        }
239

240
                                                        var filepath = dir + "/" + files[i];
241
                                                        //console.log("STAT> " + filepath);
242
                                                        f1_time = fs.statSync(filepath).mtime.getTime();
243
                                                        f2_time = fs.statSync(newest).mtime.getTime();
244
                                                        if (f1_time > f2_time)
245
                                                                newest[i] = files[i];
246
                                                }
247

248
                                                if (newest !== null)
249
                                                        return (newest);
250
                                                return null;
251
                                        };
252
                                        //
253

254
                                        // From all the build_ids take latest only!
255
                                        if (gitdir === null) {
256
                                                gitdir = getNewestFolder(local_path, new Regex(".*");
257
                                ));
258
                }*/
259

260
                        //console.log("gitdir: " + JSON.stringify(gitdir)); * /
261

262
                        // now the gitdir should be really valid
263
                        if (!fs.lstatSync(local_path).isDirectory() || git_dirs.length === 0) {
×
264
                                console.log("checkRepositoryChange: This is not a git repo: " +
×
265
                                        __dirname + "(localpath: " +
266
                                        local_path + "/.git )");
267
                                if (typeof(check_callback) === "function") {
×
268
                                        check_callback({
×
269
                                                local_path: local_path,
270
                                                version: "n/a",
271
                                                revision: "n/a",
272
                                                changed: false
273
                                        });
274
                                }
275
                                return;
×
276
                        }
277

278
                        // what if this is not a repository yet? pull will fail...
279
                        var CMD = "bash -c \"cd " + local_path +
×
280
                                "; git status; ls -la; git reset --hard; git pull; git submodule sync; git submodule update --init --recursive\"";
281
                        var nochange = "Already up-to-date.";
×
282
                        var temp = exec.execSync(CMD).toString().replace("\n", "");
×
283

284
                        if (this.timer !== null) {
×
285
                                clearTimeout(this.timer);
×
286
                        }
287

288
                        if (temp.indexOf(nochange) !== -1) {
×
289

290
                                if (local_path.indexOf("undefined") !== -1) {
×
291
                                        console.log("[REPOSITORY].js:289: Skipping incorrect local_path " +
×
292
                                                local_path);
293
                                        return false;
×
294
                                }
295

296
                                if (repeat === false) {
×
297
                                        return false;
×
298
                                } else {
299
                                        // watcher needs to be set before calling check
300
                                        // console.log("Watcher: " + JSON.stringify(watcher));
301
                                        if (typeof(this.watcher) !== "undefined" || this.watcher !== null) {
×
302
                                                console.log("[REPOSITORY].js:299: Setting watcher timer for " +
×
303
                                                        local_path);
304
                                                this.timer = setTimeout(timeoutFunction(
×
305
                                                        local_path,
306
                                                        repeat,
307
                                                        check_callback), 30000);
308
                                        } else {
309
                                                return false;
×
310
                                        }
311
                                }
312
                        } else {
313

314
                                if (repeat) {
×
315
                                        console.log("[REPOSITORY] git-watch: " + local_path +
×
316
                                                " : repository updated with timer");
317
                                }
318

319
                                console.log("[REPOSITORY] Current version: " + this.getRevisionNumber());
×
320
                                console.log("[REPOSITORY] Current revision: " + this.getRevision());
×
321

322
                                // TODO: Mark as update-available somwehere in user sources by setting 'available_version',
323
                                // which will be then non-null and if higher than firmware version, new build is available...
324
                                // ...but; it would be safer to save filename timestamp on build and then always compare
325
                                // with real filename (but it takes lot of IO power to list all visible devices like file-manager))
326

327
                                if (typeof(check_callback) === "function") {
×
328
                                        check_callback({
×
329
                                                local_path: local_path,
330
                                                version: this.version,
331
                                                revision: this.revision,
332
                                                changed: true
333
                                        });
334
                                }
335

336
                                return true;
×
337
                        }
338
                },
339

340
                getRevisionNumber: function() {
341
                        var CMD = "cd " + app_config.project_root +
×
342
                                "; git rev-list HEAD --count";
343
                        var temp = exec.execSync(CMD).toString().replace("\n", "");
×
344
                        this.version = parseInt(temp);
×
345
                        return this.version;
×
346
                },
347

348
                getRevision: function() {
349
                        var CMD = "cd " + app_config.project_root + "; git rev-parse HEAD";
×
350
                        var temp = exec.execSync(CMD).toString().replace("\n", "");
×
351
                        this.revision = temp;
×
352
                        return temp;
×
353
                },
354

355
                // returns (platform); or calls back (success, platform)
356

357
                getPlatform: function(local_path, callback) {
358

359
                        if (typeof(local_path) === "undefined") {
×
360
                                callback(false, "local_path not defined");
×
361
                                return;
×
362
                        }
363

364
                        var hasManifest = fs.existsSync(local_path + "thinx.json"); // try to read yml with node.js
×
365

366
                        //
367
                        // Arduino
368
                        //
369

370
                        var results = [];
×
371
                        var isArduino = false;
×
372

373
                        var inos = finder.from(local_path).findFiles('*.ino');
×
374
                        var xinos = [];
×
375

376
                        // Ignore all files in /examples/ (Arduino libs)
377
                        for (var inoindex in inos) {
×
378
                                if (inos[inoindex].indexOf("/examples/") === -1) {
×
379
                                        xinos.push(inos[inoindex]);
×
380
                                        results.push(xinos);
×
381
                                }
382
                        }
383

384
                        if (xinos.length > 0) {
×
385
                                console.log("Repository contains some INOs.");
×
386
                                isArduino = true;
×
387
                        }
388

389
                        //
390
                        // Platformio
391
                        //
392

393
                        var isPlatformio = fs.existsSync(local_path + "/platformio.ini");
×
394
                        if (isPlatformio) {
×
395
                                isArduino = false;
×
396
                        }
397

398
                        //
399
                        // Node
400
                        //
401

402
                        var isNodeJS = fs.existsSync(local_path + "/package.json");
×
403
                        if (isNodeJS) {
×
404
                                console.log("Repository is Node.js");
×
405
                                isNode = true;
×
406
                        }
407

408
                        //
409
                        // NodeMCU (Lua)
410
                        //
411

412
                        var isLua = fs.existsSync(local_path + "/init.lua");
×
413

414
                        //
415
                        // Micropython
416
                        //
417

418
                        var isPython = (fs.existsSync(local_path + "/boot.py") ||
×
419
                                fs.existsSync(local_path + "/main.py"));
420
                        if (isPython) {
×
421
                                console.log("Repository is Micropython");
×
422
                        }
423

424
                        //
425
                        // MongooseOS
426
                        //
427

428
                        var isMOS = fs.existsSync(local_path + "/mos.yml"); // https://mongoose-os.com/downloads/esp8266.zip
×
429

430
                        //////////////////////////////////////////////////////
431
                        // Decision logic
432
                        //
433

434
                        var platform = "unknown";
×
435

436
                        // TODO: Assign platforms by plugin implementations instead of this, extact matching functions!
437

438
                        if (isPlatformio) {
×
439

440
                                platform = "platformio";
×
441

442
                        } else if (isArduino) {
×
443

444
                                platform = "arduino";
×
445

446
                        } else if (isPython) {
×
447

448
                                platform = "python";
×
449

450
                        } else if (isLua) {
×
451

452
                                platform = "nodemcu";
×
453

454
                        } else if (isMOS) {
×
455

456
                                platform = "mongoose";
×
457

458
                        } else if (isNodeJS) {
×
459

460
                                platform = "nodejs";
×
461

462
                        }
463

464
                        console.log("Detected platform: " + platform);
×
465

466
                        if (platform == "unknown") {
×
467
                                console.log("Exiting on unknown platform.");
×
468
                                callback(false, platform);
×
469
                        }
470

471
                        if (typeof(callback) !== "undefined") {
×
472
                                callback(true, platform);
×
473
                        } else {
474
                                return platform;
×
475
                        }
476

477
                }
478

479
        };
480

481
        return _public;
1✔
482

483
})();
484

485
exports.watchRepository = Repository.watchRepository;
1✔
486
exports.unwatchRepository = Repository.unwatchRepository;
1✔
487
exports.checkRepositoryChange = Repository.checkRepositoryChange;
1✔
488
exports.getRevisionNumber = Repository.getRevisionNumber;
1✔
489
exports.getRevision = Repository.getRevision;
1✔
490
exports.getPlatform = Repository.getPlatform;
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc