git-userhub 3.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/bin/git-user-darwin-amd64 +0 -0
- package/bin/git-user-darwin-arm64 +0 -0
- package/bin/git-user-linux-amd64 +0 -0
- package/bin/git-user-linux-arm64 +0 -0
- package/bin/git-user-windows-amd64.exe +0 -0
- package/bin/git-user.js +39 -142
- package/package.json +4 -10
- package/test_tar.js +44 -0
- package/bin/git-user +0 -0
package/README.md
CHANGED
|
@@ -9,18 +9,18 @@
|
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p>
|
|
12
|
-
<a href="https://www.npmjs.com/package/git-userhub"><img src="https://img.shields.io/npm/v/git-userhub?style=flat
|
|
13
|
-
<a href="https://www.npmjs.com/package/git-userhub"><img src="https://img.shields.io/npm/dt/git-userhub?style=flat
|
|
14
|
-
<a href="https://github.com/divyo-argha/git-user/releases"><img src="https://img.shields.io/github/v/release/divyo-argha/git-user?style=flat
|
|
15
|
-
<a href="https://github.com/divyo-argha/git-user/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-22c55e?style=flat
|
|
12
|
+
<a href="https://www.npmjs.com/package/git-userhub"><img src="https://img.shields.io/npm/v/git-userhub?style=flat&color=CB3837&logo=npm&logoColor=white" alt="npm version" /></a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/git-userhub"><img src="https://img.shields.io/npm/dt/git-userhub?style=flat&color=CB3837&logo=npm&logoColor=white&label=total%20downloads" alt="total downloads" /></a>
|
|
14
|
+
<a href="https://github.com/divyo-argha/git-user/releases"><img src="https://img.shields.io/github/v/release/divyo-argha/git-user?style=flat&color=00FFAA&label=latest" alt="Latest Release" /></a>
|
|
15
|
+
<a href="https://github.com/divyo-argha/git-user/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-22c55e?style=flat" alt="MIT" /></a>
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
|
-
<img src="https://img.shields.io/badge/GitHub-supported-181717?style=
|
|
19
|
-
<img src="https://img.shields.io/badge/GitLab-supported-FC6D26?style=
|
|
20
|
-
<img src="https://img.shields.io/badge/Bitbucket-supported-0052CC?style=
|
|
21
|
-
<img src="https://img.shields.io/badge/macOS-supported-000000?style=
|
|
22
|
-
<img src="https://img.shields.io/badge/Linux-supported-FCC624?style=
|
|
23
|
-
<img src="https://img.shields.io/badge/Windows-supported-0078D4?style=
|
|
18
|
+
<img src="https://img.shields.io/badge/GitHub-supported-181717?style=flat&logo=github&logoColor=white" alt="GitHub" />
|
|
19
|
+
<img src="https://img.shields.io/badge/GitLab-supported-FC6D26?style=flat&logo=gitlab&logoColor=white" alt="GitLab" />
|
|
20
|
+
<img src="https://img.shields.io/badge/Bitbucket-supported-0052CC?style=flat&logo=bitbucket&logoColor=white" alt="Bitbucket" />
|
|
21
|
+
<img src="https://img.shields.io/badge/macOS-supported-000000?style=flat&logo=apple&logoColor=white" alt="macOS" />
|
|
22
|
+
<img src="https://img.shields.io/badge/Linux-supported-FCC624?style=flat&logo=linux&logoColor=black" alt="Linux" />
|
|
23
|
+
<img src="https://img.shields.io/badge/Windows-supported-0078D4?style=flat&logo=windows&logoColor=white" alt="Windows" />
|
|
24
24
|
|
|
25
25
|
<br /><br />
|
|
26
26
|
|
|
@@ -176,7 +176,7 @@ MIT
|
|
|
176
176
|
|
|
177
177
|
<div align="center">
|
|
178
178
|
|
|
179
|
-
[](https://github.com/divyo-argha/git-user)
|
|
180
180
|
|
|
181
181
|
<sub>If git-user saved you from a wrong-account commit, consider giving it a ⭐</sub>
|
|
182
182
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/bin/git-user.js
CHANGED
|
@@ -1,157 +1,54 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { spawn } = require('child_process');
|
|
4
|
-
const https = require('https');
|
|
5
4
|
const fs = require('fs');
|
|
6
5
|
const path = require('path');
|
|
7
6
|
const os = require('os');
|
|
8
|
-
const tar = require('tar');
|
|
9
|
-
const pkg = require('../package.json');
|
|
10
|
-
|
|
11
|
-
const REPO = pkg.config.repo;
|
|
12
|
-
const BIN_DIR = path.join(__dirname, '..', 'bin');
|
|
13
7
|
|
|
14
8
|
// Detect platform and architecture
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
9
|
+
const platform = os.platform();
|
|
10
|
+
const arch = os.arch();
|
|
11
|
+
|
|
12
|
+
const platformMap = {
|
|
13
|
+
'darwin': 'darwin',
|
|
14
|
+
'linux': 'linux',
|
|
15
|
+
'win32': 'windows'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const archMap = {
|
|
19
|
+
'x64': 'amd64',
|
|
20
|
+
'arm64': 'arm64'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const osName = platformMap[platform];
|
|
24
|
+
const archName = archMap[arch];
|
|
25
|
+
const ext = platform === 'win32' ? '.exe' : '';
|
|
26
|
+
|
|
27
|
+
if (!osName || !archName) {
|
|
28
|
+
console.error(`❌ Unsupported platform: ${platform} ${arch}`);
|
|
29
|
+
process.exit(1);
|
|
35
30
|
}
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return new Promise((resolve, reject) => {
|
|
40
|
-
const file = fs.createWriteStream(dest);
|
|
41
|
-
|
|
42
|
-
https.get(url, (response) => {
|
|
43
|
-
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
44
|
-
return download(response.headers.location, dest).then(resolve).catch(reject);
|
|
45
|
-
}
|
|
46
|
-
if (response.statusCode !== 200) {
|
|
47
|
-
reject(new Error(`Failed to download: ${response.statusCode}`));
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
response.pipe(file);
|
|
51
|
-
file.on('finish', () => {
|
|
52
|
-
file.close();
|
|
53
|
-
resolve();
|
|
54
|
-
});
|
|
55
|
-
}).on('error', (err) => {
|
|
56
|
-
fs.unlink(dest, () => {});
|
|
57
|
-
reject(err);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
}
|
|
32
|
+
const binaryName = `git-user-${osName}-${archName}${ext}`;
|
|
33
|
+
const binaryPath = path.join(__dirname, binaryName);
|
|
61
34
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
hostname: 'api.github.com',
|
|
67
|
-
path: `/repos/${REPO}/releases/tags/v${pkg.version}`,
|
|
68
|
-
headers: {
|
|
69
|
-
'User-Agent': 'git-user-cli'
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
https.get(options, (res) => {
|
|
74
|
-
let data = '';
|
|
75
|
-
res.on('data', (chunk) => data += chunk);
|
|
76
|
-
res.on('end', () => {
|
|
77
|
-
try {
|
|
78
|
-
resolve(JSON.parse(data));
|
|
79
|
-
} catch (err) {
|
|
80
|
-
reject(err);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}).on('error', reject);
|
|
84
|
-
});
|
|
35
|
+
if (!fs.existsSync(binaryPath)) {
|
|
36
|
+
console.error(`❌ git-user binary not found at ${binaryPath}`);
|
|
37
|
+
console.error(` Please ensure the package was correctly installed.`);
|
|
38
|
+
process.exit(1);
|
|
85
39
|
}
|
|
86
40
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
console.log('📦 First run detected. Downloading git-user binary...');
|
|
93
|
-
|
|
94
|
-
if (!osName || !arch) {
|
|
95
|
-
console.error('❌ Unsupported platform:', os.platform(), os.arch());
|
|
96
|
-
process.exit(1);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
if (!fs.existsSync(BIN_DIR)) {
|
|
101
|
-
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
console.log(`🔍 Fetching release v${pkg.version}...`);
|
|
105
|
-
const release = await getRelease();
|
|
106
|
-
|
|
107
|
-
const asset = release.assets?.find(a => {
|
|
108
|
-
const name = a.name.toLowerCase();
|
|
109
|
-
if (!name.includes(osName)) return false;
|
|
110
|
-
if (arch === 'arm64') return name.includes('arm64');
|
|
111
|
-
return name.includes('x86_64') || name.includes('amd64') || name.includes('x64');
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
if (!asset) {
|
|
115
|
-
console.error('❌ No binary found for your platform');
|
|
116
|
-
console.error(` Looking for a ${osName} binary matching architecture: ${arch}`);
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
console.log(`⬇️ Downloading ${asset.name}...`);
|
|
121
|
-
const archivePath = path.join(BIN_DIR, asset.name);
|
|
122
|
-
await download(asset.browser_download_url, archivePath);
|
|
123
|
-
|
|
124
|
-
console.log('📂 Extracting...');
|
|
125
|
-
await tar.extract({ file: archivePath, cwd: BIN_DIR });
|
|
126
|
-
fs.unlinkSync(archivePath);
|
|
127
|
-
|
|
128
|
-
if (fs.existsSync(binaryPath)) {
|
|
129
|
-
fs.chmodSync(binaryPath, 0o755);
|
|
130
|
-
console.log('✅ git-user installed successfully!\n');
|
|
131
|
-
} else {
|
|
132
|
-
console.error('❌ Binary not found after extraction');
|
|
133
|
-
process.exit(1);
|
|
134
|
-
}
|
|
135
|
-
} catch (err) {
|
|
136
|
-
console.error('❌ Installation failed:', err.message);
|
|
137
|
-
process.exit(1);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
41
|
+
// Forward all arguments to the bundled binary
|
|
42
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
43
|
+
stdio: 'inherit',
|
|
44
|
+
shell: false
|
|
45
|
+
});
|
|
140
46
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
shell: false
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
child.on('exit', (code) => {
|
|
148
|
-
process.exit(code || 0);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
child.on('error', (err) => {
|
|
152
|
-
console.error('❌ Failed to start git-user:', err.message);
|
|
153
|
-
process.exit(1);
|
|
154
|
-
});
|
|
155
|
-
}
|
|
47
|
+
child.on('exit', (code) => {
|
|
48
|
+
process.exit(code || 0);
|
|
49
|
+
});
|
|
156
50
|
|
|
157
|
-
|
|
51
|
+
child.on('error', (err) => {
|
|
52
|
+
console.error('❌ Failed to start git-user:', err.message);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
});
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-userhub",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Switch Git accounts in one command. No config editing. No SSH key chaos.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"git-user": "bin/git-user.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
|
-
"test": "echo \"No tests yet\" && exit 0"
|
|
9
|
+
"test": "echo \"No tests yet\" && exit 0",
|
|
10
|
+
"prepublishOnly": "node scripts/download-binaries.js"
|
|
10
11
|
},
|
|
11
|
-
"
|
|
12
|
+
"devDependencies": {
|
|
12
13
|
"tar": "^7.4.3"
|
|
13
14
|
},
|
|
14
15
|
"keywords": [
|
|
@@ -44,13 +45,6 @@
|
|
|
44
45
|
"x64",
|
|
45
46
|
"arm64"
|
|
46
47
|
],
|
|
47
|
-
"socket": {
|
|
48
|
-
"allowedNetworkHosts": [
|
|
49
|
-
"api.github.com",
|
|
50
|
-
"github.com",
|
|
51
|
-
"objects.githubusercontent.com"
|
|
52
|
-
]
|
|
53
|
-
},
|
|
54
48
|
"config": {
|
|
55
49
|
"repo": "divyo-argha/git-user"
|
|
56
50
|
}
|
package/test_tar.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
const tar = require('tar');
|
|
4
|
+
|
|
5
|
+
const assetName = "git-user_darwin_arm64.tar.gz";
|
|
6
|
+
|
|
7
|
+
async function main() {
|
|
8
|
+
console.log("Creating dummy tar file using node-tar...");
|
|
9
|
+
// create dummy git-user
|
|
10
|
+
fs.writeFileSync('git-user', 'dummy binary');
|
|
11
|
+
fs.writeFileSync('malicious.sh', 'echo bad');
|
|
12
|
+
|
|
13
|
+
await tar.create({
|
|
14
|
+
gzip: true,
|
|
15
|
+
file: assetName,
|
|
16
|
+
}, ['git-user', 'malicious.sh']);
|
|
17
|
+
|
|
18
|
+
console.log("Tar created.");
|
|
19
|
+
|
|
20
|
+
const file = fs.readFileSync(assetName);
|
|
21
|
+
const expectedHash = crypto.createHash('sha256').update(file).digest('hex');
|
|
22
|
+
|
|
23
|
+
fs.unlinkSync('git-user');
|
|
24
|
+
fs.unlinkSync('malicious.sh');
|
|
25
|
+
|
|
26
|
+
console.log("Expected hash:", expectedHash);
|
|
27
|
+
|
|
28
|
+
// Now extract securely
|
|
29
|
+
fs.mkdirSync('bin', { recursive: true });
|
|
30
|
+
|
|
31
|
+
await tar.extract({
|
|
32
|
+
file: assetName,
|
|
33
|
+
cwd: 'bin',
|
|
34
|
+
filter: (p, entry) => {
|
|
35
|
+
console.log('Filtering path:', p, entry.path);
|
|
36
|
+
return p === 'git-user' || p === 'git-user.exe' || p === './git-user' || p === './git-user.exe';
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const binContents = fs.readdirSync('bin');
|
|
41
|
+
console.log("Bin contents:", binContents);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
main().catch(console.error);
|
package/bin/git-user
DELETED
|
Binary file
|