This code analyzes a Git repository and generates a structured representation of its commit history, essentially creating a visual "tree" of branches and commits that can be used for visualization or further processing.
npm run import -- "json git tree"
var execSync = require('child_process').execSync;
/*var {
execCmd
} = importer.import("spawn child process");*/
function gitTree(project) {
console.log('creating tree "' + project + '"');
var branches = execSync('git branch --list --all ', {cwd: project}).toString()
.trim().split(/\s*\n\s*\**\s*/ig)
.map(b => b.replace('remotes/', '').trim());
// reverse git so we can add merges to the "graph" after the branch tree is constructed
var branch = execSync('git log --pretty=format:"%ct %d %h %p" '
+ '--reverse --branches --tags ', {cwd: project}).toString().split(/\s*\n\s*/ig);
var all = []; //execSync('git log --pretty=format:"%h %p" --reverse --all').toString().split(/\s*\n\s*/ig);
var nodes = [];
var edges = [];
branch.forEach(b => {
var commits = ((/[0-9]+\s+\(.*?\)\s*(.+)/ig).exec(b)
|| (/[0-9]+\s+(.+)/ig).exec(b) || [b, b.trim()])[1].trim().split(/\s+/ig);
commits.forEach(r => {
if (nodes.filter(d => d.name == r).length == 0) {
nodes[nodes.length] = {
name: r,
index: nodes.length,
branch: ((/[0-9]+\s+\((.*?)\)/ig).exec(b) || [b, ''])[1],
time: (/([0-9]+)\s+/ig).exec(b)[1]
}
}
});
// don't include merges in tree
if (commits.length == 3) {
commits = [commits[0], commits[1]];
}
if (commits.length == 2) {
edges = edges.concat(commits.slice(1)
// check all existing sources to test for merge
.map((c, i) => {
return {source: c, target: commits[i]}; // -1 because of slice(1)
}))
}
});
return formatNodes(nodes, edges.reverse());
}
module.exports = gitTree;
const childProcess = require('child_process');
const console = console;
/**
* Creates a graph representation of a Git repository tree.
* @param {string} project - The path to the Git repository.
* @returns {object} - The graph nodes and edges.
*/
function gitTree(project) {
console.log(`Creating tree for project: ${project}`);
// Get a list of all branches and tags
const branches = getBranches(project);
// Get a list of commits in reverse chronological order
const commits = getCommits(project);
// Initialize nodes and edges arrays
const nodes = [];
const edges = [];
// Process each commit
commits.forEach((commit) => {
const [date, merge, hash, parents] = commit.split(' ');
const parentsArray = parents.trim().split(' ');
// Create nodes for each parent
parentsArray.forEach((parent, index) => {
if (!nodes.find((node) => node.name === parent)) {
nodes.push({
name: parent,
index: nodes.length,
branch: getBranch(hash),
time: date,
});
}
});
// Add edges between parents if not merge commits
if (parentsArray.length > 1) {
for (let i = 1; i < parentsArray.length; i++) {
edges.push({ source: parentsArray[i - 1], target: parentsArray[i] });
}
}
});
return formatNodes(nodes, edges.reverse());
}
// Helper function to get a list of branches
function getBranches(project) {
return childProcess
.execSync(`git branch --list --all`, { cwd: project })
.toString()
.trim()
.split(/\s*\n\s*\*\s*/ig)
.map((b) => b.replace('remotes/', '').trim());
}
// Helper function to get a list of commits
function getCommits(project) {
return childProcess
.execSync(
'git log --pretty=format:"%ct %d %h %p" --reverse --branches --tags',
{ cwd: project }
)
.toString()
.split(/\s*\n\s*/ig);
}
// Helper function to get the branch name for a commit
function getBranch(hash) {
const branch = childProcess
.execSync(`git branch --list --contains ${hash}`, { cwd: process.cwd() })
.toString()
.trim()
.split(/\s*\n\s*/ig)[0];
return branch.replace('remotes/', '').trim();
}
// Helper function to format nodes and edges
function formatNodes(nodes, edges) {
return { nodes, edges };
}
module.exports = gitTree;
This code defines a function gitTree
that analyzes a Git repository and generates a structured representation of its commit history, essentially creating a visual "tree" of branches and commits.
Here's a breakdown:
Initialization:
execSync
function from the child_process
module, which allows executing shell commands synchronously.gitTree
that takes a project
path as input.Fetching Branch Information:
execSync
to list all branches (including remote branches) in the specified project using the command git branch --list --all
.branches
array.Fetching Commit History:
execSync
to fetch commit history in a specific format (%ct %d %h %p
) using the command git log --pretty=format:"%ct %d %h %p" --reverse --branches --tags
.branch
array.Building the Tree Structure:
nodes
to store commit information and edges
to store relationships between commits (branches).branch
array.node
object for each unique commit hash and adds it to the nodes
array.commits
array accordingly.edges
representing the relationships between parent and child commits.Formatting the Output:
formatNodes
(not shown in the code) to format the nodes
and edges
into a desired structure, likely for visualization or further processing.Returning the Tree:
Let me know if you have any other code snippets you'd like me to explain!