git-local-info-ts
Version:
Retrieve current sha, branch name, repository from a git repo.
192 lines (191 loc) • 7.85 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GitInfo = void 0;
var fs_1 = require("fs");
var path_1 = require("path");
var zlib_1 = require("zlib");
var ini_1 = require("ini");
var GitInfo = /** @class */ (function () {
function GitInfo(args) {
if (args === void 0) { args = {}; }
this.GIT_DIR = '.git';
var gitPath = args.gitPath, GIT_DIR = args.GIT_DIR;
if (GIT_DIR) {
this.GIT_DIR = GIT_DIR;
}
this.gitPath = this._findRepo(gitPath);
this.headPath = (0, path_1.join)(this.gitPath, 'HEAD');
}
Object.defineProperty(GitInfo.prototype, "getGitInfo", {
get: function () {
return {
branch: this.getBranch(),
repository: this.getRepository(),
sha: this.getSha(),
commit: this.getCommit(),
rootDir: (0, path_1.dirname)((0, path_1.resolve)(this.gitPath)),
};
},
enumerable: false,
configurable: true
});
// Get branch
GitInfo.prototype.getBranch = function () {
try {
if ((0, fs_1.existsSync)(this.headPath)) {
var headFile = this._readFile(this.headPath);
var match = /refs\/heads\/(\S+$)/.exec(headFile);
var branchName = match && match[1];
return branchName;
}
}
catch (_a) { }
};
// Get repository
GitInfo.prototype.getRepository = function () {
try {
var configFilePath = (0, path_1.join)(this.gitPath, 'config');
if ((0, fs_1.existsSync)(configFilePath)) {
var config = (0, ini_1.parse)(this._readFile(configFilePath));
var repository = config['remote "origin"'].url;
return repository;
}
}
catch (_a) { }
};
// Get sha/commit hash
GitInfo.prototype.getSha = function () {
try {
if ((0, fs_1.existsSync)(this.headPath)) {
var headFile = (0, fs_1.readFileSync)(this.headPath, 'utf-8');
var refPath = headFile.split(' ')[1];
// Find branch and SHA
if (refPath) {
refPath = refPath.trim();
var branchPath = (0, path_1.join)(this.gitPath, refPath);
var hasBranchPath = (0, fs_1.existsSync)(branchPath);
return hasBranchPath ? this._readFile(branchPath) : this._findPackedCommit(refPath);
}
var sha = headFile.split('/').slice(2).join('/').trim();
if (!sha) {
sha = headFile.split('/').slice(-1)[0].trim();
}
return sha;
}
}
catch (_a) { }
};
GitInfo.prototype.getCommit = function () {
try {
var sha = this.getSha();
if (!sha) {
return '';
}
var objectPath = (0, path_1.join)(this.gitPath, 'objects', sha.slice(0, 2), sha.slice(2));
if (zlib_1.inflateSync && (0, fs_1.existsSync)(objectPath)) {
var objectContents = (0, zlib_1.inflateSync)((0, fs_1.readFileSync)(objectPath)).toString();
var commit = objectContents
.split(/\0|\r?\n/)
.filter(Boolean)
.reduce(function (data, section) {
var part = section.slice(0, section.indexOf(' ')).trim();
switch (part) {
case 'commit':
case 'tag':
case 'object':
case 'type':
case 'author':
case 'parent':
case 'tree': {
// ignore these for now
break;
}
case 'committer': {
var parts = section.match(/^(?:author|committer)\s(.+)\s(\d+\s(?:\+|\-)\d{4})$/);
if (parts) {
data[part] = parts[1];
}
break;
}
default: {
// Should just be the commit message left
data.commitMessage = section;
}
}
return data;
}, {});
return commit;
}
}
catch (_a) { }
};
GitInfo.prototype._findPackedCommit = function (refPath) {
return this._getPackedRefsForType(refPath, 'commit')[0];
};
GitInfo.prototype._getPackedRefsFile = function () {
var packedRefsFilePath = (0, path_1.join)(this.gitPath, 'packed-refs');
return (0, fs_1.existsSync)(packedRefsFilePath) ? this._readFile(packedRefsFilePath) : false;
};
GitInfo.prototype._getShaBasedOnType = function (type, shaLine) {
if (type === 'tag') {
return shaLine.split('tags/')[1];
}
else if (type === 'commit') {
return shaLine.split(' ')[0];
}
return '';
};
GitInfo.prototype._getLinesForRefPath = function (packedRefsFile, type, refPath) {
var _this = this;
return packedRefsFile.split(/\r?\n/).reduce(function (acc, line, idx, array) {
var targetLine = line.includes('^') ? array[idx - 1] : line;
return _this._doesLineMatchRefPath(type, line, refPath) ? acc.concat(targetLine) : acc;
}, []);
};
GitInfo.prototype._doesLineMatchRefPath = function (type, line, refPath) {
var refPrefix = type === 'tag' ? 'refs/tags' : 'refs/heads';
return (line.includes(refPrefix) || line.includes('^')) && line.includes(refPath);
};
GitInfo.prototype._getPackedRefsForType = function (refPath, type) {
var _this = this;
var packedRefsFile = this._getPackedRefsFile();
if (packedRefsFile) {
return this._getLinesForRefPath(packedRefsFile, type, refPath).map(function (shaLine) {
return _this._getShaBasedOnType(type, shaLine);
});
}
return [];
};
GitInfo.prototype._readFile = function (filePath) {
return (0, fs_1.readFileSync)(filePath, 'utf-8').trim();
};
GitInfo.prototype._findRepoHandleLinkedWorktree = function (gitPath) {
var stat = (0, fs_1.statSync)(gitPath);
if (stat.isDirectory()) {
return gitPath;
}
// We have a file that tells us where to find the worktree git dir. Once we
// look there we'll know how to find the common git dir, depending on
// whether it's a linked worktree git dir, or a submodule dir
var linkedGitDir = (0, fs_1.readFileSync)(gitPath).toString();
var absolutePath = (0, path_1.resolve)((0, path_1.dirname)(gitPath));
var worktreeGitDirUnresolved = /gitdir: (.*)/.exec(linkedGitDir)[1];
var worktreeGitDir = (0, path_1.resolve)(absolutePath, worktreeGitDirUnresolved);
return worktreeGitDir;
};
GitInfo.prototype._findRepo = function (startingPath) {
var lastPath;
var currentPath = startingPath || process.cwd();
do {
var gitPath = (0, path_1.join)(currentPath, this.GIT_DIR);
if ((0, fs_1.existsSync)(gitPath)) {
return this._findRepoHandleLinkedWorktree(gitPath);
}
lastPath = currentPath;
currentPath = (0, path_1.resolve)(currentPath, '..');
} while (lastPath !== currentPath);
return '';
};
return GitInfo;
}());
exports.GitInfo = GitInfo;