Skip to content

Commit 624a21c

Browse files
committed
Initial commit
0 parents  commit 624a21c

File tree

7 files changed

+2699
-0
lines changed

7 files changed

+2699
-0
lines changed

.eslintrc.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module.exports = {
2+
env: {
3+
commonjs: true,
4+
es2021: true,
5+
node: true,
6+
},
7+
extends: ["airbnb-base", "prettier"],
8+
parserOptions: {
9+
ecmaVersion: 12,
10+
},
11+
rules: {
12+
"no-console": 0,
13+
},
14+
};

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
repos

.prettierrc.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
singleQuote: false,
3+
tabWidth: 2,
4+
};

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# mmd-gitlab-backuper

index.js

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
const clone = require("git-clone");
2+
const axios = require("axios").default;
3+
const fs = require("fs-extra");
4+
const chalk = require("chalk");
5+
const objChange = require("on-change");
6+
const cliProgress = require("cli-progress");
7+
const argv = require("yargs");
8+
9+
argv
10+
.scriptName("mmd-gitlab-backuper")
11+
.usage("Save your repo in gitlab")
12+
.option("token", {
13+
alias: "t",
14+
type: "string",
15+
description: "your Gitlab Personal Access Token",
16+
})
17+
.option("output", {
18+
alias: "o",
19+
type: "string",
20+
description: "Backup to output directory, defaults to ./repos",
21+
})
22+
.option("url", {
23+
alias: "u",
24+
type: "string",
25+
description: "Specify Gitlab URL, defaults to https://gitlab.com",
26+
})
27+
.help();
28+
29+
if (!argv.argv.token) {
30+
console.log(
31+
chalk.bgRed(
32+
"\n Please pass your gitlab personal access token. Check README.md to how grab it. \n"
33+
)
34+
);
35+
process.exit(0);
36+
}
37+
38+
const token = argv.argv.token || "";
39+
const baseUrl = argv.argv.url || "https://gitlab.com";
40+
const output = argv.argv.output || "./repos";
41+
const pagination = 100;
42+
const defaultAddress = `/api/v4/projects?simple=true&membership=true&pagination=keyset&order_by=id&sort=asc&per_page=${pagination}`;
43+
const bar = new cliProgress.SingleBar(
44+
{
45+
format: "progress [{bar}] {percentage}% | {value}/{total}",
46+
},
47+
cliProgress.Presets.shades_classic
48+
);
49+
50+
let next;
51+
let total = 0;
52+
let firstStart = true;
53+
54+
axios.defaults.baseURL = baseUrl;
55+
axios.defaults.headers.common["PRIVATE-TOKEN"] = token;
56+
57+
if (!fs.existsSync(output)) {
58+
fs.mkdirSync(output);
59+
}
60+
61+
const observer = objChange(
62+
{
63+
cloned: 0,
64+
hasNext: true,
65+
},
66+
() => {
67+
if (observer.cloned === total && !observer.hasNext) {
68+
bar.stop();
69+
console.clear();
70+
console.log(chalk.green(`\n ${total} repo(s) has been saved!! \n`));
71+
}
72+
}
73+
);
74+
75+
function isRepoExist(repoName) {
76+
return fs.existsSync(`${output}/${repoName}/.git`);
77+
}
78+
79+
function cloneCompleted(repoName, showMessage = true) {
80+
if (showMessage) {
81+
console.log(chalk.green(`\n clone completed ${repoName} \n`));
82+
}
83+
84+
observer.cloned += 1;
85+
bar.increment(1);
86+
}
87+
88+
function main() {
89+
axios
90+
.get(next || defaultAddress)
91+
.then((res) => {
92+
const repos = res.data;
93+
const { length } = repos;
94+
total += length;
95+
const { link } = res.headers;
96+
97+
if (firstStart) {
98+
bar.start(total, 0);
99+
firstStart = false;
100+
} else {
101+
bar.setTotal(total);
102+
}
103+
104+
for (let i = 0; i < length; i += 1) {
105+
const repo = repos[i];
106+
const {
107+
name_with_namespace: nameWithNameSpace,
108+
http_url_to_repo: httpUrlToRepo,
109+
} = repo;
110+
const repoName = nameWithNameSpace.replace(/\//g, "-");
111+
const repoNameColor = chalk.cyan(repoName);
112+
const repoUrl = httpUrlToRepo.replace(
113+
"https://",
114+
`https://gitlab-ci-token:${token}@`
115+
);
116+
117+
if (isRepoExist(repoName)) {
118+
cloneCompleted(repoNameColor, false);
119+
} else {
120+
console.log(chalk.yellow(`\n cloning ${repoNameColor} ... \n`));
121+
122+
clone(`${repoUrl}`, `${output}/${repoName}`, undefined, () => {
123+
if (isRepoExist(repoName)) {
124+
cloneCompleted(repoNameColor);
125+
}
126+
});
127+
}
128+
}
129+
130+
if (length !== 0 && link) {
131+
next = link.replace("<http", "http").replace(`>; rel="next"`, "");
132+
main();
133+
} else {
134+
observer.hasNext = false;
135+
}
136+
})
137+
.catch((err) => {
138+
console.log("err:", err.message);
139+
});
140+
}
141+
142+
main();

0 commit comments

Comments
 (0)