gitfleet 1.0.0
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/bin/gitfleet.js +37 -0
- package/commands/add.js +32 -0
- package/commands/branch.js +21 -0
- package/commands/exec.js +21 -0
- package/commands/init.js +10 -0
- package/commands/list.js +16 -0
- package/commands/pull.js +29 -0
- package/commands/scan.js +63 -0
- package/commands/status.js +29 -0
- package/core/config.js +28 -0
- package/core/git.js +21 -0
- package/package.json +23 -0
package/bin/gitfleet.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { Command } = require("commander");
|
|
4
|
+
|
|
5
|
+
const init = require("../commands/init");
|
|
6
|
+
const add = require("../commands/add");
|
|
7
|
+
const status = require("../commands/status");
|
|
8
|
+
const pull = require("../commands/pull");
|
|
9
|
+
const exec = require("../commands/exec");
|
|
10
|
+
const scan = require("../commands/scan");
|
|
11
|
+
const list = require("../commands/list")
|
|
12
|
+
const branch = require("../commands/branch")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
const program = new Command();
|
|
16
|
+
|
|
17
|
+
program
|
|
18
|
+
.name("gitfleet")
|
|
19
|
+
.description("Manage multiple git repositories");
|
|
20
|
+
|
|
21
|
+
program.command("init").action(init);
|
|
22
|
+
|
|
23
|
+
program.command("add <path>").action(add);
|
|
24
|
+
|
|
25
|
+
program.command("status").action(status);
|
|
26
|
+
|
|
27
|
+
program.command("pull").action(pull);
|
|
28
|
+
|
|
29
|
+
program.command("scan <path>").action(scan);
|
|
30
|
+
|
|
31
|
+
program.command("exec <command>").action(exec)
|
|
32
|
+
|
|
33
|
+
program.command("list").action(list)
|
|
34
|
+
|
|
35
|
+
program.command("branch").action(branch)
|
|
36
|
+
|
|
37
|
+
program.parse();
|
package/commands/add.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
const { loadConfig, saveConfig } = require("../core/config");
|
|
5
|
+
|
|
6
|
+
module.exports = function (repoPath) {
|
|
7
|
+
|
|
8
|
+
const gitDir = path.join(repoPath, ".git");
|
|
9
|
+
|
|
10
|
+
if (!fs.existsSync(repoPath)) {
|
|
11
|
+
console.log("Path does not exist:", repoPath);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!fs.existsSync(gitDir)) {
|
|
16
|
+
console.log("Not a git repository:", repoPath);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const config = loadConfig();
|
|
21
|
+
|
|
22
|
+
if (config.repos.includes(repoPath)) {
|
|
23
|
+
console.log("⚠ Repo already added:", repoPath);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
config.repos.push(repoPath);
|
|
28
|
+
|
|
29
|
+
saveConfig(config);
|
|
30
|
+
|
|
31
|
+
console.log("✅ Added repo:", repoPath);
|
|
32
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const { loadConfig } = require("../core/config");
|
|
2
|
+
|
|
3
|
+
const { execSync } = require("child_process");
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
module.exports = function () {
|
|
8
|
+
|
|
9
|
+
const config = loadConfig();
|
|
10
|
+
|
|
11
|
+
for(const repo of config.repos){
|
|
12
|
+
try{
|
|
13
|
+
|
|
14
|
+
console.log(`\n▶ ${repo} : `);
|
|
15
|
+
|
|
16
|
+
execSync("git branch", { cwd: repo, stdio: "inherit" });
|
|
17
|
+
}catch(e){
|
|
18
|
+
console.log("Error:",e)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
package/commands/exec.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const { loadConfig } = require("../core/config");
|
|
2
|
+
|
|
3
|
+
const { execSync } = require("child_process");
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
module.exports = function (command) {
|
|
8
|
+
|
|
9
|
+
const config = loadConfig();
|
|
10
|
+
|
|
11
|
+
for(const repo of config.repos){
|
|
12
|
+
try{
|
|
13
|
+
|
|
14
|
+
console.log(`\n▶ Running in ${repo}`);
|
|
15
|
+
|
|
16
|
+
execSync(command, { cwd: repo, stdio: "inherit" });
|
|
17
|
+
}catch(e){
|
|
18
|
+
console.log("Error:",e)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
package/commands/init.js
ADDED
package/commands/list.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const { loadConfig } = require("../core/config");
|
|
2
|
+
const path = require("path")
|
|
3
|
+
|
|
4
|
+
module.exports = function(){
|
|
5
|
+
const config = loadConfig();
|
|
6
|
+
|
|
7
|
+
if (config.repos.length === 0) {
|
|
8
|
+
console.log("No repositories added.");
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
config.repos.forEach((repo, i) => {
|
|
13
|
+
const name = path.basename(repo);
|
|
14
|
+
console.log(`${i + 1}. ${name} → ${repo}`);
|
|
15
|
+
});
|
|
16
|
+
}
|
package/commands/pull.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const { loadConfig } = require("../core/config");
|
|
2
|
+
const { execSync } = require("child_process");
|
|
3
|
+
|
|
4
|
+
function isRepoDirty(repo) {
|
|
5
|
+
|
|
6
|
+
const status = execSync("git status --porcelain", { cwd: repo })
|
|
7
|
+
.toString()
|
|
8
|
+
.trim();
|
|
9
|
+
|
|
10
|
+
return status.length > 0;
|
|
11
|
+
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = function () {
|
|
15
|
+
const config = loadConfig();
|
|
16
|
+
for (const repo of config.repos) {
|
|
17
|
+
try {
|
|
18
|
+
if (isRepoDirty(repo)) {
|
|
19
|
+
console.log(`⚠ Skipping ${repo} (local changes)`);
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
console.log(`⬇ Pulling ${repo}`);
|
|
23
|
+
execSync("git pull", { cwd: repo, stdio: "inherit" });
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.log(`Failed for ${repo}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
};
|
package/commands/scan.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
const { loadConfig, saveConfig } = require("../core/config");
|
|
5
|
+
|
|
6
|
+
function findRepos(dir, repos = []) {
|
|
7
|
+
|
|
8
|
+
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
9
|
+
|
|
10
|
+
for (const item of items) {
|
|
11
|
+
|
|
12
|
+
const fullPath = path.join(dir, item.name);
|
|
13
|
+
|
|
14
|
+
// if .git folder found
|
|
15
|
+
if (item.name === ".git") {
|
|
16
|
+
repos.push(dir);
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (item.isDirectory() && item.name !== "node_modules") {
|
|
21
|
+
findRepos(fullPath, repos);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return repos;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = function (scanPath) {
|
|
30
|
+
|
|
31
|
+
scanPath = path.resolve(scanPath);
|
|
32
|
+
|
|
33
|
+
if (!fs.existsSync(scanPath)) {
|
|
34
|
+
console.log("❌ Path does not exist:", scanPath);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const repos = findRepos(scanPath);
|
|
39
|
+
|
|
40
|
+
if (repos.length === 0) {
|
|
41
|
+
console.log("No git repositories found.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const config = loadConfig();
|
|
46
|
+
|
|
47
|
+
let added = 0;
|
|
48
|
+
|
|
49
|
+
for (const repo of repos) {
|
|
50
|
+
|
|
51
|
+
if (!config.repos.includes(repo)) {
|
|
52
|
+
config.repos.push(repo);
|
|
53
|
+
added++;
|
|
54
|
+
console.log("✅ Added:", repo);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
saveConfig(config);
|
|
60
|
+
|
|
61
|
+
console.log("\nFound:", repos.length);
|
|
62
|
+
console.log("Added:", added);
|
|
63
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const { loadConfig } = require("../core/config");
|
|
2
|
+
const { execSync } = require("child_process");
|
|
3
|
+
|
|
4
|
+
module.exports = function () {
|
|
5
|
+
|
|
6
|
+
const config = loadConfig();
|
|
7
|
+
|
|
8
|
+
for (const repo of config.repos) {
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
|
|
12
|
+
const output = execSync("git status --porcelain", { cwd: repo })
|
|
13
|
+
.toString()
|
|
14
|
+
.trim();
|
|
15
|
+
|
|
16
|
+
if (!output) {
|
|
17
|
+
console.log(`Repo: ${repo} → clean`);
|
|
18
|
+
} else {
|
|
19
|
+
const lines = output.split("\n").length;
|
|
20
|
+
console.log(`Repo: ${repo} → ${lines} changes`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
} catch {
|
|
24
|
+
console.log(`Repo: ${repo} → error`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
};
|
package/core/config.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const os = require("os");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
|
|
5
|
+
const configDir = path.join(os.homedir(), ".gitfleet");
|
|
6
|
+
const configFile = path.join(configDir, "config.json");
|
|
7
|
+
|
|
8
|
+
function loadConfig() {
|
|
9
|
+
if (!fs.existsSync(configFile)) {
|
|
10
|
+
return { repos: [] };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return JSON.parse(fs.readFileSync(configFile));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function saveConfig(config) {
|
|
17
|
+
if (!fs.existsSync(configDir)) {
|
|
18
|
+
fs.mkdirSync(configDir);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
loadConfig,
|
|
26
|
+
saveConfig,
|
|
27
|
+
configFile,
|
|
28
|
+
};
|
package/core/git.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const { execSync } = require("child_process");
|
|
2
|
+
|
|
3
|
+
function runGit(repo, command) {
|
|
4
|
+
|
|
5
|
+
try {
|
|
6
|
+
|
|
7
|
+
const output = execSync(command, { cwd: repo });
|
|
8
|
+
|
|
9
|
+
return output.toString();
|
|
10
|
+
|
|
11
|
+
} catch (err) {
|
|
12
|
+
|
|
13
|
+
return "Error";
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
runGit,
|
|
21
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gitfleet",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
|
+
},
|
|
8
|
+
"keywords": ["git",
|
|
9
|
+
"cli",
|
|
10
|
+
"developer-tools",
|
|
11
|
+
"git-manager"],
|
|
12
|
+
"description": "",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"chalk": "^5.6.2",
|
|
15
|
+
"commander": "^14.0.3",
|
|
16
|
+
"ora": "^9.3.0"
|
|
17
|
+
},
|
|
18
|
+
"bin": {
|
|
19
|
+
"gitfleet": "./bin/gitfleet.js"
|
|
20
|
+
},
|
|
21
|
+
"author": "Kartik Singla",
|
|
22
|
+
"license": "MIT"
|
|
23
|
+
}
|