cksource/mgit2

View on GitHub
lib/utils/parserepositoryurl.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md.
 */

'use strict';

const url = require( 'url' );

// Limitations on git tag names:
// https://git-scm.com/docs/git-check-ref-format#_description
const tagPattern = /@([^ ~^:?*\\]*?)$/;

/**
 * Parses repository URL taken from `mrgit.json`'s dependencies and returns
 * it as an object containing repository URL and branch name.
 *
 * @param {String} repositoryUrl The repository URL in formats supported by `mrgit.json`.
 * @param {Object} options
 * @param {String} [options.urlTemplate] The URL template.
 * Used if `repositoryUrl` defines only `'<organization>/<repositoryName>'`.
 * @param {String} [options.defaultBranch='master'] The default branch name to be used if the
 * repository URL doesn't specify it.
 * @param {Array.<String>} [options.baseBranches=[]] Name of branches that are allowed to check out
 * based on the value specified as `options.cwdPackageBranch`.
 * @param {String} [options.cwdPackageBranch] A name of a branch that the main repository is checked out.
 * @returns {Repository}
 */
module.exports = function parseRepositoryUrl( repositoryUrl, options = {} ) {
    let tag = undefined;

    if ( tagPattern.test( repositoryUrl ) ) {
        tag = repositoryUrl.match( tagPattern )[ 1 ];

        repositoryUrl = repositoryUrl.replace( tagPattern, '' );
    }

    const parsedUrl = url.parse( repositoryUrl );

    const branch = getBranch( parsedUrl, {
        defaultBranch: options.defaultBranch,
        baseBranches: options.baseBranches || [],
        cwdPackageBranch: options.cwdPackageBranch
    } );

    let repoUrl;

    if ( repositoryUrl.match( /^(file|https?):\/\// ) || repositoryUrl.match( /^git@/ ) ) {
        parsedUrl.hash = null;

        repoUrl = url.format( parsedUrl );
    } else {
        const pattern = options.urlTemplate;

        repoUrl = pattern.replace( /\${ path }/, parsedUrl.path );
    }

    return {
        url: repoUrl,
        branch,
        directory: repoUrl.replace( /\.git$/, '' ).match( /[:/]([^/]+)\/?$/ )[ 1 ],
        tag
    };
};

function getBranch( parsedUrl, options ) {
    const defaultBranch = options.defaultBranch || 'master';

    // Check if branch is defined in mrgit.json. Use it.
    if ( parsedUrl.hash ) {
        return parsedUrl.hash.slice( 1 );
    }

    // Check if the main repo is on one of base branches. If yes, use that branch.
    if ( options.cwdPackageBranch && options.baseBranches.includes( options.cwdPackageBranch ) ) {
        return options.cwdPackageBranch;
    }

    // Nothing matches. Use default branch.
    return defaultBranch;
}

/**
 * Repository info.
 *
 * @typedef {Object} Repository
 * @property {String} url Repository URL. E.g. `'git@github.com:ckeditor/ckeditor5.git'`.
 * @property {String} branch Branch name. E.g. `'master'`.
 * @property {String} directory Directory to which the repository would be cloned.
 */