aboutsummaryrefslogtreecommitdiff
path: root/api/git.js
blob: 59f737104c39ce58b2e46edbf17a426f91583f8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
const { exec } = require("child_process");
const { differenceInMilliseconds } = require('date-fns');
const fs = require('fs');

const log_format='{"hash": "%H", "author": "%an", "author_email": "%ae", "date": "%at", "subject": "%s"}';

function execGit(path, action , format, args = "")
{
	return new Promise((resolve) =>
	{
		exec(`git -C ${path} ${action} ${args} --format=format:'${format}'`, (error, stdout, stderr) =>
		{
			if(error) {
				const no_such_fileor_dir = new RegExp(`cannot change to '${path.replace('/', "\/")}': No such file or directory\\n$`);

				if(no_such_fileor_dir.test(error.message)) {
					resolve({ "error": 404 });
					return;
				}
				resolve({ "error": error.message });
				return;
			}
			if(stderr) {
				resolve({ "error": "Failed to communicate with git!" });
				return;
			}

			resolve({ "data": stdout });
		});
	});
}

async function getLog(path)
{
	let log = await execGit(path, "log", log_format);

	if(!log["error"]) {
		log["data"] = log["data"].split('\n');
		log["data"].forEach((entry, index) => log["data"][index] = JSON.parse(entry));
	}

	return log;
}

function getOptimalDateDifference(difference)
{
	const time_values = {
		"second": 1000,
		"minute": 60000,
		"hour": 3600000,
		"day": 86400000,
		"week": 604800000,
		"month": 2629800000,
		"year": 31557600000
	};

	let last;
	for(const [key, value] of Object.entries(time_values)) {
		if(difference > value) {
			last = key;
			continue;
		}
		break;
	}

	return `${Math.round(difference / time_values[last])} ${last}s`;
}

async function getTimeSinceLatestCommit(path)
{
	let commit_timestamp = (await execGit(path, "log", "%at", "-n 1"));

	if(!commit_timestamp["error"]) {
		commit_timestamp = commit_timestamp["data"] * 1000;

		const commit_date = new Date(commit_timestamp);
		const now_date = new Date();

		const difference = getOptimalDateDifference(differenceInMilliseconds(now_date, commit_date));

		return difference;
	}
	return commit_timestamp;
}

function getRepoFile(base_dir, repo, file)
{
	return new Promise(resolve =>
	{
		fs.readFile(`${base_dir}/${repo}/${file}`, async (err, content) =>
		{			
			if(!err) {
				resolve(content.toString().replaceAll('\n', ''));
				return;
			}
			resolve("");
		});
	});
}

function getBasicRepoInfo(base_dir, repo_dirs)
{
	return new Promise((resolve) =>
	{
		let repos = {};
		repo_dirs.forEach(async (repo, index, arr) =>
		{
			const desc = await getRepoFile(base_dir, repo, "description");
			const owner = await getRepoFile(base_dir, repo, "owner");
			const last_commit_date = await getTimeSinceLatestCommit(`${base_dir}/${repo}`);

			let repo_name = "";
			repo_name = repo.slice(0, -4);
			repos[repo_name] = { "description": desc, "owner": owner, "last_updated": last_commit_date };

			if(index === 0) resolve(repos);
		});	
	});
}

module.exports.getLog = getLog;
module.exports.getBasicRepoInfo = getBasicRepoInfo;