UNPKG

@developerisnow/git-repositories-statistic-analyzer

Version:

A powerful tool for analyzing multiple Git repositories and generating comprehensive statistics

218 lines (217 loc) 8.01 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GitAnalyzer = void 0; const child_process_1 = require("child_process"); const util_1 = require("util"); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const moment_1 = __importDefault(require("moment")); const execAsync = (0, util_1.promisify)(child_process_1.exec); class GitAnalyzer { constructor(basePath) { this.basePath = basePath; } async executeGitCommand({ command, args, cwd, }) { try { const { stdout } = await execAsync(`${command} ${args.join(" ")}`, { cwd, }); return stdout.trim(); } catch (error) { return ""; } } formatDate(dateStr) { if (!dateStr) return ""; try { const match = dateStr.match(/(\w+)\s(\w+)\s(\d+)\s(\d+):(\d+):(\d+)\s(\d+)\s([+-]\d+)/); if (!match) return dateStr; const [_, dayName, monthName, day, hours, minutes, seconds, year, timezone,] = match; const formattedDate = `${year}-${(0, moment_1.default)().month(monthName).format("MM")}-${day.padStart(2, "0")}`; return formattedDate; } catch { return dateStr; } } calculateRepoAge(firstDate, lastDate) { try { const first = (0, moment_1.default)(firstDate, "YYYY-MM-DD"); const last = (0, moment_1.default)(lastDate, "YYYY-MM-DD"); if (!first.isValid() || !last.isValid()) return "0"; return last.diff(first, "days").toString(); } catch { return "0"; } } async getLastCommitDate(repoPath) { const date = await this.executeGitCommand({ command: "git", args: ["log", "-1", "--format=%cd"], cwd: repoPath, }); return this.formatDate(date); } async getLastCommitHash(repoPath) { return this.executeGitCommand({ command: "git", args: ["rev-parse", "HEAD"], cwd: repoPath, }); } async getLastCommitMessage(repoPath) { return this.executeGitCommand({ command: "git", args: ["log", "-1", "--format=%s"], cwd: repoPath, }); } async getTotalCommits(repoPath) { return this.executeGitCommand({ command: "git", args: ["rev-list", "--count", "HEAD"], cwd: repoPath, }); } cleanRepoUrl(url) { const sshMatch = url.match(/git@github\.com:([^/]+\/[^.]+)\.git/); if (sshMatch) return `github.com/${sshMatch[1]}.git`; const httpsMatch = url.match(/https:\/\/[^@]+@github\.com\/([^/]+\/[^.]+)\.git/); if (httpsMatch) return `github.com/${httpsMatch[1]}.git`; const simpleHttpsMatch = url.match(/https:\/\/github\.com\/([^/]+\/[^.]+)\.git/); if (simpleHttpsMatch) return `github.com/${simpleHttpsMatch[1]}.git`; return url; } async getRemoteUrls(repoPath) { const urls = await this.executeGitCommand({ command: "git", args: ["remote", "-v"], cwd: repoPath, }); if (!urls) return ""; const fetchUrl = urls.split("\n").find((line) => line.includes("(fetch)")); if (!fetchUrl) return ""; const urlPart = fetchUrl.split(/\s+/)[1]; return this.cleanRepoUrl(urlPart); } extractUsername(url) { const sshMatch = url.match(/git@github\.com:([^/]+)\//); if (sshMatch) return sshMatch[1]; const httpsMatch = url.match(/github\.com\/([^/]+)\//); if (httpsMatch) return httpsMatch[1]; return ""; } async getFirstCommitDate(repoPath) { const date = await this.executeGitCommand({ command: "git", args: ["log", "--reverse", "--format=%cd", "|", "head", "-1"], cwd: repoPath, }); return this.formatDate(date); } async getUncommittedFilesCount(repoPath) { const modified = await this.executeGitCommand({ command: "git", args: ["status", "--porcelain"], cwd: repoPath, }); return modified.split("\n").filter(Boolean).length.toString(); } async getGitFolderSize(repoPath) { const gitPath = path.join(repoPath, ".git"); if (!fs.existsSync(gitPath)) return "0"; let totalSize = 0; const getAllFiles = (dirPath) => { const files = fs.readdirSync(dirPath); files.forEach((file) => { const filePath = path.join(dirPath, file); const stats = fs.statSync(filePath); if (stats.isDirectory()) { getAllFiles(filePath); } else { totalSize += stats.size; } }); }; getAllFiles(gitPath); return (Math.round((totalSize / (1024 * 1024)) * 10) / 10).toString(); } async analyzeRepository(repoPath) { const gitPath = path.join(repoPath, ".git"); if (!fs.existsSync(gitPath)) return null; const urls = await this.executeGitCommand({ command: "git", args: ["remote", "-v"], cwd: repoPath, }); const cleanUrl = await this.getRemoteUrls(repoPath); const lastCommitDate = await this.getLastCommitDate(repoPath); const firstCommitDate = await this.getFirstCommitDate(repoPath); return { nameFolder: path.basename(repoPath), usernamesUrlRepos: this.extractUsername(urls), gitFolderSize: await this.getGitFolderSize(repoPath), dateLastCommit: lastCommitDate, messageLastCommit: await this.getLastCommitMessage(repoPath), amountTotalCommits: await this.getTotalCommits(repoPath), ageRepo: this.calculateRepoAge(firstCommitDate, lastCommitDate), dateFirstCommit: firstCommitDate, urlsRepo: cleanUrl, amountUncommitedFiles: await this.getUncommittedFilesCount(repoPath), hashLastCommit: await this.getLastCommitHash(repoPath), pathFolder: repoPath, }; } } exports.GitAnalyzer = GitAnalyzer;