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

suculent / thinx-device-api / #252646838

01 Dec 2025 11:17AM UTC coverage: 71.333% (-0.6%) from 71.926%
#252646838

push

suculent
merged updates after testing

1847 of 3550 branches covered (52.03%)

Branch coverage included in aggregate %.

8176 of 10501 relevant lines covered (77.86%)

13.24 hits per line

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

76.83
/lib/thinx/git.js
1
// Git Shell Manager
2

3
const Globals = require("./globals.js");
1✔
4
const app_config = Globals.app_config();
1✔
5
const fs = require("fs-extra");
1✔
6
const exec = require("child_process");
1✔
7

8
const valid_responses = [
1✔
9
        "already exists and is not an empty",
10
        "FETCH_HEAD",
11
        "up-to-date",
12
        "Checking out files: 100%",
13
        "done.",
14
        "Cloning into"
15
];
16
module.exports = class Git {
1✔
17

18
        responseWhiteBlacklist(rstring) {
19
                let success;
20
                for (let index in valid_responses) {
17✔
21
                        if (rstring.indexOf(valid_responses[index]) != -1) {
94✔
22
                                success = true;
16✔
23
                                console.log("Success expected with valid response ", valid_responses[index]);
16✔
24
                                break;
16✔
25
                        }
26
                }
27

28
                // blacklist
29
                let invalid_responses = [ "fatal" ];
17✔
30
                for (let index in invalid_responses) {
17✔
31
                        if (rstring.indexOf(invalid_responses[index]) != -1) {
17✔
32
                                success = false;
2✔
33
                                console.log("Failure override due to invalid response ", invalid_responses[index]);
2✔
34
                                break;
2✔
35
                        }
36
                }
37
                return success;
17✔
38
        }
39

40
        checkResponse(rstring, local_path) {
41

42
                // whitelist (default response is '')
43
                let success = this.responseWhiteBlacklist(rstring);
17✔
44

45
                // the basefile must exist; local_path must be valid
46
                if ((success == false) && (typeof(local_path) !== "undefined")) {
17✔
47
                        if (!fs.existsSync(local_path)) return false;
2!
48
                        let basename_path = local_path + "/basename.json";
×
49
                        success = fs.existsSync(basename_path); // may throw! but does not work.
×
50
                        if (success) console.log(basename_path, "exists, success...");
×
51
                }
52

53
                console.log("[TODO TEST] Git response result", success);
15✔
54

55
                return success;
15✔
56
        }
57

58
        tryShellOp(cmd, local_path) {
59
                let result;
60
                try {
17✔
61
                        result = exec.execSync(cmd).toString().trim(); // lgtm [js/command-line-injection]
17✔
62
                        console.log("[git] exec result: '", result, "'");
15✔
63
                } catch (e) {
64
                        result = e.stdout.toString();
2✔
65
                        console.log("[ERROR] [git] exec result: '", result, "'");
2✔
66
                }
67
                return this.checkResponse(result, local_path);
17✔
68
        }
69

70
        askpath(keypath) {
71
                return keypath + ".sh";
48✔
72
        }
73

74
        create_askfile(keypath, password) {
75
                let path = this.askpath(keypath);
16✔
76
                let contents = `#!/usr/bin/env sh\necho "${password}"`;
16✔
77
                fs.writeFileSync(path, contents);
16✔
78
                fs.chmodSync(path, 0o700);
16✔
79
        }
80

81
        delete_askfile(keypath) {
82
                fs.removeSync(this.askpath(keypath));
16✔
83
        }
84

85
    fetch(owner, command, local_path) {
86
                // TODO: Fetch owner's key password (defaults to thinx now) and create askfile (should be per-user to allow parallelism, and deleted at the end)
87
                let success = false;
15✔
88
                let RSAKey = require("./rsakey"); let rsa = new RSAKey();
15✔
89
                let key_paths = rsa.getKeyPathsForOwner(owner);
15✔
90
                if ((typeof(key_paths) === "undefined") || (key_paths.length < 1)) {
15!
91
                        console.log("ℹ️ [info] [git] no_rsa_keys_found");
×
92
                        return this.tryShellOp(command, local_path);
×
93
                } 
94
                
95
                // tries all keys until successful... may use last_successful_key first
96
                for (var kindex in key_paths) {
15✔
97
                        let keypath = app_config.ssh_keys + "/" + key_paths[kindex];
16✔
98
                        let askpath = this.askpath(keypath);
16✔
99
                        var gfpfx = `ssh-agent sh -c 'DISPLAY=: SSH_ASKPASS=${askpath} GIT_ASKPASS=${askpath} ssh-add ${keypath} >/dev/null 2>&1; `;
16✔
100
                        let prefixed_command = gfpfx + command + "' 2>&1";
16✔
101
                        this.create_askfile(keypath, "thinx"); // TODO: per-owner/per-key keypass stored in Vault
16✔
102
                        success = this.tryShellOp(prefixed_command, local_path);
16✔
103
                        this.delete_askfile(keypath);
16✔
104
                        if (success) return success;
16✔
105
                }
106
                
107
                return success;
1✔
108
        }
109

110
        // WHY IS THIS HERE? WHY IS THIS NOT FETCH? TO TRY WITHOUT KEY? FETCH WILL SUCCEED ANYWAY (IF ANY KEY EXISTS)
111
        prefetch(GIT_PREFETCH) {
112
                console.log(`🔨 [debug] git prefetch command:\n ${GIT_PREFETCH}`);
×
113
                var result = "";
×
114
                try {
×
115
                        result = exec.execSync(GIT_PREFETCH).toString().replace("\n", "");
×
116
                        if (result !== "Already up to date.") {
×
117
                                console.log(`ℹ️ [info] [builder] git prefetch result: ${result}`);
×
118
                        }
119
                } catch (e) { console.log("⚠️ [warning] git prefetch not successful..."); }
×
120
                return result;
×
121
        }
122
};
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