fix(#174) improve cli interface to anonimize repositories

This commit is contained in:
tdurieux
2023-02-15 19:23:45 +01:00
parent fb9bbe105a
commit da194d9d71
3 changed files with 58 additions and 27 deletions
+39 -16
View File
@@ -2,10 +2,10 @@
import { config as dot } from "dotenv"; import { config as dot } from "dotenv";
dot(); dot();
process.env.STORAGE = "filesystem";
import { writeFile } from "fs/promises"; import { writeFile } from "fs/promises";
import { join } from "path"; import { join } from "path";
import { tmpdir } from "os";
import * as gh from "parse-github-url"; import * as gh from "parse-github-url";
import * as inquirer from "inquirer"; import * as inquirer from "inquirer";
@@ -15,6 +15,7 @@ import config from "./config";
import GitHubDownload from "./src/source/GitHubDownload"; import GitHubDownload from "./src/source/GitHubDownload";
import Repository from "./src/Repository"; import Repository from "./src/Repository";
import AnonymizedRepositoryModel from "./src/database/anonymizedRepositories/anonymizedRepositories.model"; import AnonymizedRepositoryModel from "./src/database/anonymizedRepositories/anonymizedRepositories.model";
import { getRepositoryFromGitHub } from "./src/source/GitHubRepository";
function generateRandomFileName(size: number) { function generateRandomFileName(size: number) {
const characters = const characters =
@@ -45,18 +46,47 @@ async function main() {
name: "terms", name: "terms",
message: `Terms to remove from your repository (separated with comma).`, message: `Terms to remove from your repository (separated with comma).`,
}, },
{
type: "string",
name: "output",
message: `The output folder where to save the zipped repository.`,
default: process.cwd(),
},
]); ]);
const ghURL = gh(inq.repo) || { owner: "", name: "", branch: "", commit: "" }; const ghURL = gh(inq.repo) || {
owner: undefined,
name: undefined,
branch: undefined,
commit: undefined,
};
if (!ghURL.owner || !ghURL.name) {
throw new Error("Invalid GitHub URL");
}
const ghRepo = await getRepositoryFromGitHub({
accessToken: inq.token,
owner: ghURL.owner,
repo: ghURL.name,
});
const branches = await ghRepo.branches({
accessToken: inq.token,
force: true,
});
const branchToFind = inq.repo.includes(ghURL.branch)
? ghURL.branch
: ghRepo.model.defaultBranch || "master";
const branch = branches.find((b) => b.name === branchToFind);
const repository = new Repository( const repository = new Repository(
new AnonymizedRepositoryModel({ new AnonymizedRepositoryModel({
repoId: "test", repoId: `${ghURL.name}-${branch?.name}`,
source: { source: {
type: "GitHubDownload", type: "GitHubDownload",
accessToken: inq.token, accessToken: inq.token,
branch: ghURL.branch || "master", branch: branchToFind,
commit: ghURL.branch || "HEAD", commit: branch?.commit || "HEAD",
repositoryName: `${ghURL.owner}/${ghURL.name}`, repositoryName: `${ghURL.owner}/${ghURL.name}`,
}, },
options: { options: {
@@ -72,18 +102,11 @@ async function main() {
}) })
); );
const source = new GitHubDownload( console.info(
{ `[INFO] Downloading repository: ${repository.model.source.repositoryName} from branch ${repository.model.source.branch} and commit ${repository.model.source.commit}...`
type: "GitHubDownload",
accessToken: inq.token,
repositoryName: inq.repo,
},
repository
); );
await (repository.source as GitHubDownload).download(inq.token);
console.info("[INFO] Downloading repository..."); const outputFileName = join(inq.output, generateRandomFileName(8) + ".zip");
await source.download(inq.token);
const outputFileName = join(tmpdir(), generateRandomFileName(8) + ".zip");
console.info("[INFO] Anonymizing repository and creation zip file..."); console.info("[INFO] Anonymizing repository and creation zip file...");
await writeFile(outputFileName, repository.zip()); await writeFile(outputFileName, repository.zip());
console.log(`Anonymized repository saved at ${outputFileName}`); console.log(`Anonymized repository saved at ${outputFileName}`);
+17 -9
View File
@@ -4,6 +4,7 @@ import { IRepositoryDocument } from "../database/repositories/repositories.types
import { Octokit, RestEndpointMethodTypes } from "@octokit/rest"; import { Octokit, RestEndpointMethodTypes } from "@octokit/rest";
import RepositoryModel from "../database/repositories/repositories.model"; import RepositoryModel from "../database/repositories/repositories.model";
import AnonymousError from "../AnonymousError"; import AnonymousError from "../AnonymousError";
import { database, isConnected } from "../database/database";
export class GitHubRepository { export class GitHubRepository {
private _data: Partial<{ private _data: Partial<{
@@ -71,11 +72,13 @@ export class GitHubRepository {
}); });
this._data.branches = branches; this._data.branches = branches;
await RepositoryModel.updateOne( if (isConnected) {
{ externalId: this.id }, await RepositoryModel.updateOne(
{ $set: { branches } } { externalId: this.id },
); { $set: { branches } }
} else { );
}
} else if (isConnected) {
const q = await RepositoryModel.findOne({ externalId: this.id }).select( const q = await RepositoryModel.findOne({ externalId: this.id }).select(
"branches" "branches"
); );
@@ -208,9 +211,12 @@ export async function getRepositoryFromGitHub(opt: {
repo: opt.repo, repo: opt.repo,
}, },
}); });
let model = await RepositoryModel.findOne({ externalId: "gh_" + r.id }); let model = new RepositoryModel({ externalId: "gh_" + r.id });
if (!model) { if (isConnected) {
model = new RepositoryModel({ externalId: "gh_" + r.id }); const dbModel = await RepositoryModel.findOne({ externalId: "gh_" + r.id });
if (dbModel) {
model = dbModel;
}
} }
model.name = r.full_name; model.name = r.full_name;
model.url = r.html_url; model.url = r.html_url;
@@ -224,6 +230,8 @@ export async function getRepositoryFromGitHub(opt: {
}); });
model.pageSource = ghPageRes.data.source; model.pageSource = ghPageRes.data.source;
} }
await model.save(); if (isConnected) {
await model.save();
}
return new GitHubRepository(model); return new GitHubRepository(model);
} }
+2 -2
View File
@@ -108,7 +108,7 @@ export default class FileSystem implements StorageBase {
return pipe( return pipe(
data, data,
Extract({ Extract({
path: join(join(config.FOLDER, p)), path: join(config.FOLDER, p),
decodeString: (buf) => { decodeString: (buf) => {
const name = buf.toString(); const name = buf.toString();
const newName = name.substr(name.indexOf("/") + 1); const newName = name.substr(name.indexOf("/") + 1);
@@ -124,7 +124,7 @@ export default class FileSystem implements StorageBase {
dir: string, dir: string,
opt?: { opt?: {
format?: "zip" | "tar"; format?: "zip" | "tar";
fileTransformer? (path: string): Transform; fileTransformer?: (path: string) => Transform;
} }
) { ) {
const archive = archiver(opt?.format || "zip", {}); const archive = archiver(opt?.format || "zip", {});