deadbranch 0.0.1 → 0.1.1
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 +40 -29
- package/bin/deadbranch +22 -0
- package/package.json +35 -5
- package/scripts/install.js +157 -0
package/README.md
CHANGED
|
@@ -1,45 +1,56 @@
|
|
|
1
|
-
# deadbranch
|
|
1
|
+
# deadbranch npm package
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This is the npm distribution package for [deadbranch](https://github.com/armgabrielyan/deadbranch), a CLI tool to clean up stale git branches safely.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g deadbranch
|
|
9
|
+
```
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
Or run directly with npx:
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
3. Establish provenance for packages published under this name
|
|
13
|
+
```bash
|
|
14
|
+
npx deadbranch list
|
|
15
|
+
```
|
|
15
16
|
|
|
16
|
-
## What
|
|
17
|
+
## What this package does
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
When you install this package, it automatically downloads the appropriate pre-built binary for your platform from GitHub Releases. Supported platforms:
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
- macOS (Intel & Apple Silicon)
|
|
22
|
+
- Linux (x64 & ARM64)
|
|
23
|
+
- Windows (x64)
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
## Alternative installation methods
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
2. Configure the trusted publisher (e.g., GitHub Actions)
|
|
26
|
-
3. Specify the repository and workflow that should be allowed to publish
|
|
27
|
-
4. Use the configured workflow to publish your actual package
|
|
27
|
+
If npm installation fails, you can install deadbranch using other methods:
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
### Shell installer (Linux/macOS)
|
|
30
|
+
```bash
|
|
31
|
+
curl -sSf https://raw.githubusercontent.com/armgabrielyan/deadbranch/main/install.sh | sh
|
|
32
|
+
```
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- Exists only for administrative purposes
|
|
34
|
+
### Cargo (from source)
|
|
35
|
+
```bash
|
|
36
|
+
cargo install deadbranch
|
|
37
|
+
```
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
### Homebrew (macOS/Linux)
|
|
40
|
+
```bash
|
|
41
|
+
brew install armgabrielyan/deadbranch/deadbranch
|
|
42
|
+
```
|
|
38
43
|
|
|
39
|
-
|
|
40
|
-
- [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
|
|
41
|
-
- [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
|
|
44
|
+
## Usage
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
```bash
|
|
47
|
+
deadbranch list # List stale branches
|
|
48
|
+
deadbranch clean # Delete merged stale branches
|
|
49
|
+
deadbranch clean --dry-run # Preview what would be deleted
|
|
50
|
+
```
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
For more information, see the [full documentation](https://github.com/armgabrielyan/deadbranch).
|
|
53
|
+
|
|
54
|
+
## License
|
|
55
|
+
|
|
56
|
+
MIT
|
package/bin/deadbranch
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Binary wrapper for deadbranch
|
|
5
|
+
* This script runs the actual binary with all passed arguments
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { spawn } = require('child_process');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
|
|
12
|
+
const binaryExt = os.platform() === 'win32' ? '.exe' : '';
|
|
13
|
+
const binaryPath = path.join(__dirname, 'deadbranch' + binaryExt);
|
|
14
|
+
|
|
15
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
16
|
+
stdio: 'inherit',
|
|
17
|
+
env: process.env,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
child.on('exit', (code) => {
|
|
21
|
+
process.exit(code || 0);
|
|
22
|
+
});
|
package/package.json
CHANGED
|
@@ -1,10 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deadbranch",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Clean up stale git branches safely",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/armgabrielyan/deadbranch.git"
|
|
8
|
+
},
|
|
9
|
+
"author": "Armen Gabrielyan",
|
|
10
|
+
"license": "MIT",
|
|
5
11
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
12
|
+
"git",
|
|
13
|
+
"cli",
|
|
14
|
+
"branches",
|
|
15
|
+
"cleanup",
|
|
16
|
+
"devtools"
|
|
17
|
+
],
|
|
18
|
+
"bin": {
|
|
19
|
+
"deadbranch": "bin/deadbranch"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"postinstall": "node scripts/install.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"bin/",
|
|
26
|
+
"scripts/"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=14"
|
|
30
|
+
},
|
|
31
|
+
"os": [
|
|
32
|
+
"darwin",
|
|
33
|
+
"linux",
|
|
34
|
+
"win32"
|
|
35
|
+
],
|
|
36
|
+
"cpu": [
|
|
37
|
+
"x64",
|
|
38
|
+
"arm64"
|
|
9
39
|
]
|
|
10
40
|
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* npm postinstall script for deadbranch
|
|
5
|
+
* Downloads the appropriate pre-built binary for the current platform
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { execSync, spawn } = require('child_process');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const https = require('https');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const os = require('os');
|
|
13
|
+
const zlib = require('zlib');
|
|
14
|
+
|
|
15
|
+
const REPO = 'armgabrielyan/deadbranch';
|
|
16
|
+
const BINARY_NAME = 'deadbranch';
|
|
17
|
+
const VERSION = require('../package.json').version;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get the target triple for the current platform
|
|
21
|
+
*/
|
|
22
|
+
function getTarget() {
|
|
23
|
+
const platform = os.platform();
|
|
24
|
+
const arch = os.arch();
|
|
25
|
+
|
|
26
|
+
const targets = {
|
|
27
|
+
'darwin-x64': 'x86_64-apple-darwin',
|
|
28
|
+
'darwin-arm64': 'aarch64-apple-darwin',
|
|
29
|
+
'linux-x64': 'x86_64-unknown-linux-gnu',
|
|
30
|
+
'linux-arm64': 'aarch64-unknown-linux-gnu',
|
|
31
|
+
'win32-x64': 'x86_64-pc-windows-msvc',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const key = `${platform}-${arch}`;
|
|
35
|
+
const target = targets[key];
|
|
36
|
+
|
|
37
|
+
if (!target) {
|
|
38
|
+
throw new Error(`Unsupported platform: ${key}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return target;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the archive extension for the current platform
|
|
46
|
+
*/
|
|
47
|
+
function getArchiveExt() {
|
|
48
|
+
return os.platform() === 'win32' ? 'zip' : 'tar.gz';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Download a file from a URL
|
|
53
|
+
*/
|
|
54
|
+
function download(url) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
const handleResponse = (response) => {
|
|
57
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
58
|
+
// Follow redirect
|
|
59
|
+
https.get(response.headers.location, handleResponse).on('error', reject);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (response.statusCode !== 200) {
|
|
64
|
+
reject(new Error(`Failed to download: ${response.statusCode}`));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const chunks = [];
|
|
69
|
+
response.on('data', (chunk) => chunks.push(chunk));
|
|
70
|
+
response.on('end', () => resolve(Buffer.concat(chunks)));
|
|
71
|
+
response.on('error', reject);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
https.get(url, handleResponse).on('error', reject);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Extract tar.gz archive
|
|
80
|
+
*/
|
|
81
|
+
function extractTarGz(buffer, destDir) {
|
|
82
|
+
const tarPath = path.join(os.tmpdir(), 'deadbranch.tar');
|
|
83
|
+
|
|
84
|
+
// Decompress gzip
|
|
85
|
+
const decompressed = zlib.gunzipSync(buffer);
|
|
86
|
+
fs.writeFileSync(tarPath, decompressed);
|
|
87
|
+
|
|
88
|
+
// Extract tar
|
|
89
|
+
execSync(`tar -xf "${tarPath}" -C "${destDir}"`, { stdio: 'inherit' });
|
|
90
|
+
fs.unlinkSync(tarPath);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Extract zip archive (Windows)
|
|
95
|
+
*/
|
|
96
|
+
function extractZip(buffer, destDir) {
|
|
97
|
+
const zipPath = path.join(os.tmpdir(), 'deadbranch.zip');
|
|
98
|
+
fs.writeFileSync(zipPath, buffer);
|
|
99
|
+
|
|
100
|
+
// Use PowerShell to extract
|
|
101
|
+
execSync(`powershell -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${destDir}' -Force"`, { stdio: 'inherit' });
|
|
102
|
+
fs.unlinkSync(zipPath);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function install() {
|
|
106
|
+
console.log('Installing deadbranch...');
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const target = getTarget();
|
|
110
|
+
const ext = getArchiveExt();
|
|
111
|
+
const archiveName = `deadbranch-${VERSION}-${target}.${ext}`;
|
|
112
|
+
const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${archiveName}`;
|
|
113
|
+
|
|
114
|
+
console.log(`Downloading ${archiveName}...`);
|
|
115
|
+
const buffer = await download(url);
|
|
116
|
+
|
|
117
|
+
const binDir = path.join(__dirname, '..', 'bin');
|
|
118
|
+
if (!fs.existsSync(binDir)) {
|
|
119
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Create temp dir for extraction
|
|
123
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'deadbranch-'));
|
|
124
|
+
|
|
125
|
+
console.log('Extracting...');
|
|
126
|
+
if (ext === 'zip') {
|
|
127
|
+
extractZip(buffer, tmpDir);
|
|
128
|
+
} else {
|
|
129
|
+
extractTarGz(buffer, tmpDir);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Copy binary to bin directory
|
|
133
|
+
const binaryExt = os.platform() === 'win32' ? '.exe' : '';
|
|
134
|
+
const srcBinary = path.join(tmpDir, BINARY_NAME + binaryExt);
|
|
135
|
+
const destBinary = path.join(binDir, BINARY_NAME + binaryExt);
|
|
136
|
+
|
|
137
|
+
fs.copyFileSync(srcBinary, destBinary);
|
|
138
|
+
|
|
139
|
+
// Make executable on Unix
|
|
140
|
+
if (os.platform() !== 'win32') {
|
|
141
|
+
fs.chmodSync(destBinary, 0o755);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Cleanup temp dir
|
|
145
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
146
|
+
|
|
147
|
+
console.log('deadbranch installed successfully!');
|
|
148
|
+
} catch (error) {
|
|
149
|
+
console.error('Failed to install deadbranch:', error.message);
|
|
150
|
+
console.error('');
|
|
151
|
+
console.error('You can install from source instead:');
|
|
152
|
+
console.error(' cargo install deadbranch');
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
install();
|