This code provides utilities for interacting with Git repositories, enabling you to fetch remote information, retrieve branch names, and parse commit logs.
npm run import -- "convert git history to google calendar events"
var chrono = require('chrono-node');
var _ = require('lodash');
var importer = require('../Core');
var execCmd = importer.import("spawn child process");
var ISODateString = importer.import("convert date iso");
var correctCalendarId = importer.import("lookup calendar name");
var updateEvent = importer.import("update create merge event");
var offset = (new Date()).getTimezoneOffset() * 60 * 1000;
function gitRemote(project) {
return execCmd(`
git remote -v
`, {cwd: project})
.then(r => r[0].trim().split('\n').map(l => {
if(!l) return {function: '(fetch)', name: false}
var line = l.split('\t');
return {
name: line[0],
address: line[1].split(' ')[0],
function: line[1].split(' ')[1]
};
}))
}
function gitBranch(project, remote) {
if(!remote) return 'master'
return execCmd(`
git remote show ${remote}
`, {cwd: project})
.then(r => `${remote}/${(/\s*HEAD branch:\s*(.*?)\s/ig).exec(r[0].trim())[1]}`)
}
function gitLog(project, remote, branch) {
var cmd
if(remote)
cmd = `
git fetch ${remote}
git log --name-only --pretty=format:"%h%x09%an%x09%aD%x09%s" ${branch}`
else
cmd = `git log --name-only --pretty=format:"%h%x09%an%x09%aD%x09%s" ${branch}`
return execCmd(cmd, {cwd: project})
.then(log => log[remote ? 1 : 0].split('\n\n').map(l => {
var fields = l.split('\n')[0].split('\t');
var files = l.split('\n').slice(1);
return {
hash: fields[0],
author: fields[1],
date: chrono.parse(fields[2])[0].start.date(),
message: fields[3],
files: files
}
}))
}
function gitHistory(project, summary, branch) {
var remote, branch;
if(typeof project == 'undefined') {
project = '/Users/briancullinan/planet_quake'
}
if(typeof summary == 'undefined') {
summary = 'Worked on Quake 3'
}
return gitRemote(project)
.then(remotes => remote = remotes.filter(r => r.function == '(fetch)')[0].name)
.then(() => branch || gitBranch(project, remote))
.then(b => branch = b)
.then(() => gitLog(project, remote, branch))
.then(commits => {
console.log(commits)
// group commits by a few hours and make a working event
var grouped = _.groupBy(commits, c => {
// round to the nearest 3 hours
return Math.round(c.date.getTime() / (60 * 60 * 3 * 1000)) * 60 * 60 * 3 * 1000;
})
return Object.keys(grouped).map(t => {
var min = _.min(grouped[t].map(g => g.date)).getTime();
min = Math.round(min / (60 * 60 * 3 * 1000)) * 60 * 60 * 3 * 1000
var max = _.max(grouped[t].map(g => g.date)).getTime();
max = Math.round(max / (60 * 60 * 3 * 1000)) * 60 * 60 * 3 * 1000
var s = grouped[t].map(g => g.message).filter(g => g != 'no message').join(', ')
return {
start: {
dateTime: ISODateString(new Date(parseInt(min) - offset))
},
end: {
dateTime: ISODateString(new Date(parseInt(max) + 60 * 60 * 1000 - offset))
},
summary: summary + (s != '' ? (', ' + s) : ''),
description: JSON.stringify(grouped[t], null, 4)
}
})
})
.then(results => {
return importer.runAllPromises(results
.map(event => resolve => updateEvent(event, {})
.then(r => resolve(r))))
})
}
module.exports = gitHistory;
const chrono = require('chrono-node');
const _ = require('lodash');
const importer = require('../Core');
const { spawn } = require('child_process');
const ISODateString = importer.import('convert date iso');
const correctCalendarId = importer.import('lookup calendar name');
const updateEvent = importer.import('update create merge event');
/**
* Function to execute git remote command and parse output
* @param {string} project - The path to the git project
* @returns {Promise} - An array of objects representing the git remotes
*/
function getGitRemotes(project) {
return new Promise((resolve, reject) => {
const cmd = 'git remote -v';
childProcess.exec(cmd, { cwd: project }, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
const remotes = stdout.trim().split('\n').map(line => {
if (!line) return { function: '(fetch)', name: false };
const [name, address] = line.split('\t');
const [function] = line.split(' ').pop().trim().split('(')[1].split(')')[0].split(',');
return { name, address, function };
});
resolve(remotes);
}
});
});
}
/**
* Function to execute git branch command and parse output
* @param {string} project - The path to the git project
* @param {string} remote - The name of the git remote to show
* @returns {Promise} - The name of the current branch
*/
function getGitBranch(project, remote) {
return new Promise((resolve, reject) => {
const cmd = `git remote show ${remote}`;
childProcess.exec(cmd, { cwd: project }, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
const branch = stdout.trim().match(/\s*HEAD branch:\s*(.*?)\s/ig)?.[1];
resolve(branch);
}
});
});
}
/**
* Function to execute git log command and parse output
* @param {string} project - The path to the git project
* @param {string} remote - The name of the git remote to fetch from
* @param {string} branch - The name of the git branch to log
* @returns {Promise} - An array of objects representing the git commits
*/
function getGitLog(project, remote, branch) {
return new Promise((resolve, reject) => {
let cmd;
if (remote) {
cmd = `git fetch ${remote} && git log --name-only --pretty=format:"%h%x09%an%x09%aD%x09%s" ${branch}`;
} else {
cmd = `git log --name-only --pretty=format:"%h%x09%an%x09%aD%x09%s" ${branch}`;
}
childProcess.exec(cmd, { cwd: project }, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
const commits = stdout.trim().split('\n\n').map(log => {
const [hash, author, date, message] = log.split('\n')[0].split('\t');
const files = log.split('\n').slice(1);
return {
hash,
author,
date: chrono.parse(date)[0].start.date(),
message,
files,
};
});
resolve(commits);
}
});
});
}
/**
* Function to group commits by a few hours and create a working event
* @param {string} project - The path to the git project
* @param {string} summary - The summary of the event
* @param {string} branch - The name of the git branch
* @returns {Promise} - An array of objects representing the events
*/
function gitHistory(project, summary, branch) {
return getGitRemotes(project)
.then(remotes => {
const remote = remotes.find(r => r.function === '(fetch)').name;
return getGitBranch(project, remote);
})
.then(branch => {
if (!branch) branch ='master';
return getGitLog(project, remote, branch);
})
.then(commits => {
const grouped = _.groupBy(commits, c => {
const min = Math.round(c.date.getTime() / (60 * 60 * 3 * 1000)) * 60 * 60 * 3 * 1000;
return min;
});
const events = Object.keys(grouped).map(t => {
const min = Math.round(_.min(grouped[t].map(g => g.date)).getTime() / (60 * 60 * 3 * 1000)) * 60 * 60 * 3 * 1000;
const max = Math.round(_.max(grouped[t].map(g => g.date)).getTime() / (60 * 60 * 3 * 1000)) * 60 * 60 * 3 * 1000;
const messages = grouped[t].map(g => g.message).filter(m => m!== 'no message').join(', ');
return {
start: {
dateTime: ISODateString(new Date(parseInt(min) - offset)),
},
end: {
dateTime: ISODateString(new Date(parseInt(max) + 60 * 60 * 1000 - offset)),
},
summary: summary + (messages!== ''? `, ${messages}` : ''),
description: JSON.stringify(grouped[t], null, 4),
};
});
return importer.runAllPromises(events.map(event => resolve => updateEvent(event, {}).then(r => resolve(r))));
});
}
const childProcess = require('child_process');
module.exports = gitHistory;
This code defines several functions for interacting with Git repositories, including fetching remote information, retrieving branch names, and parsing commit logs.
Here's a breakdown:
Imports:
gitRemote
Function:
gitBranch
Function:
gitLog
Function:
gitHistory
Function:
In essence, this code provides a set of utilities for interacting with Git repositories, allowing you to fetch remote information, retrieve branch names, and parse commit logs.