All files / src/utils git-info.js

61.53% Statements 16/26
57.14% Branches 8/14
100% Functions 2/2
61.53% Lines 16/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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                    2x 2x     2x                   5x 5x             5x   5x                                                             3x 3x 3x 3x 3x 3x 3x 3x             2x        
/**
 * Git information utility
 * 
 * Provides functions to extract Git repository information including
 * the current branch name and repository details from the working directory.
 * 
 * @author Spec-Up-T Team
 * @since 2025-08-31
 */
 
const { execSync } = require('child_process');
const Logger = require('./logger');
 
// Fixed PATH for security: only system directories, not user-writable
const FIXED_PATH = process.platform === 'win32'
    ? 'C:\\Windows\\system32;C:\\Windows'
    : '/usr/bin:/bin:/usr/sbin:/sbin';
 
/**
 * Gets the current Git branch name
 * 
 * @returns {string} The current branch name, or 'main' as fallback
 */
function getCurrentBranch() {
    try {
        const branch = execSync('git branch --show-current', { 
            encoding: 'utf8',
            timeout: 5000,
            stdio: ['pipe', 'pipe', 'pipe'],
            env: { ...process.env, PATH: FIXED_PATH }
        }).trim();
        
        Eif (branch) {
            // This is too much info, comment out for the moment, Logger.info(`Current git branch: ${branch}`);
            return branch;
        }
        
        // Fallback to checking HEAD if branch name is empty (detached HEAD)
        const head = execSync('git rev-parse --abbrev-ref HEAD', {
            encoding: 'utf8',
            timeout: 5000,
            stdio: ['pipe', 'pipe', 'pipe'],
            env: { ...process.env, PATH: FIXED_PATH }
        }).trim();
        
        if (head && head !== 'HEAD') {
            Logger.info(`Current git branch (from HEAD): ${head}`);
            return head;
        }
        
        Logger.warn('Could not determine git branch, using fallback: main');
        return 'main';
    } catch (error) {
        Logger.warn(`Could not get git branch (${error.message}), using fallback: main`);
        return 'main';
    }
}
 
/**
 * Creates GitHub repository information meta tag content
 * 
 * @param {Object} spec - The spec configuration object
 * @returns {string} Meta tag content in format "username,repo,branch"
 */
function getGithubRepoInfo(spec) {
    try {
        const source = spec.source || {};
        const account = source.account || 'unknown';
        const repo = source.repo || 'unknown';
        const branch = getCurrentBranch();
        const content = `${account},${repo},${branch}`;
        Logger.info(`GitHub repo info: ${content}`);
        return content;
    } catch (error) {
        Logger.warn(`Error generating GitHub repo info: ${error.message}`);
        return 'unknown,unknown,main';
    }
}
 
module.exports = {
    getCurrentBranch,
    getGithubRepoInfo
};