<commit_before>function decompose(endpoint) {
    var regExp = /^(?:([\w\-]|(?:[\w\.\-]+[\w\-])?)=)?([^\|#]+)(?:#(.*))?$/;
    var matches = endpoint.match(regExp);
    var target;
    var error;

    if (!matches) {
        error = new Error('Invalid endpoint: ' + endpoint);
        error.code = 'EINVEND';
        throw error;
    }

    target = matches[3];

    return {
        name: matches[1] || '',
        source: matches[2],
        target: !target || target === 'latest' ? '*' : target
    };
}

function compose(decEndpoint) {
    var composed = '';

    if (decEndpoint.name) {
        composed += decEndpoint.name + '=';
    }

    composed += decEndpoint.source;

    if (!isWildcard(decEndpoint.target)) {
        composed += '#' + decEndpoint.target;
    }

    return composed;
}

function json2decomposed(key, value) {
    var endpoint = key + '=';
    var split = value.split('#');

    // If # was found, the source was specified
    if (split.length > 1) {
        endpoint += (split[0] || key) + '#' + split[1];
    // Check if value looks like a source
    } else if (isSource(value)) {
        endpoint += value + '#*';
    // Otherwise use the key as the source
    } else {
        endpoint += key + '#' + split[0];
    }

    return decompose(endpoint);
}

function decomposed2json(decEndpoint) {
    var error;
    var key = decEndpoint.name;
    var value = '';
    var ret = {};

    if (!key) {
        error = new Error('Decomposed endpoint must have a name');
        error.code = 'EINVEND';
        throw error;
    }

    // Add source only if different than the name
    if  (decEndpoint.source !== decEndpoint.name) {
        value += decEndpoint.source;
    }

    // If value is empty, we append the target always
    if (!value) {
        value += isWildcard(decEndpoint.target) ? '*' : decEndpoint.target;
    // Otherwise append only if not a wildcard
    } else if (!isWildcard(decEndpoint.target)) {
        value += '#' + decEndpoint.target;
    }

    ret[key] = value;

    return ret;
}

function isWildcard(target) {
    return !target || target === '*' || target === 'latest';
}

function isSource(value) {
    return value.indexOf('/') !== -1 || value.indexOf('@') !== -1;
}

module.exports.decompose = decompose;
module.exports.compose = compose;
module.exports.json2decomposed = json2decomposed;
module.exports.decomposed2json = decomposed2json;
<commit_msg>Endpoints with backslashes should be recognized as sources<commit_after>function decompose(endpoint) {
    var regExp = /^(?:([\w\-]|(?:[\w\.\-]+[\w\-])?)=)?([^\|#]+)(?:#(.*))?$/;
    var matches = endpoint.match(regExp);
    var target;
    var error;

    if (!matches) {
        error = new Error('Invalid endpoint: ' + endpoint);
        error.code = 'EINVEND';
        throw error;
    }

    target = matches[3];

    return {
        name: matches[1] || '',
        source: matches[2],
        target: !target || target === 'latest' ? '*' : target
    };
}

function compose(decEndpoint) {
    var composed = '';

    if (decEndpoint.name) {
        composed += decEndpoint.name + '=';
    }

    composed += decEndpoint.source;

    if (!isWildcard(decEndpoint.target)) {
        composed += '#' + decEndpoint.target;
    }

    return composed;
}

function json2decomposed(key, value) {
    var endpoint = key + '=';
    var split = value.split('#');

    // If # was found, the source was specified
    if (split.length > 1) {
        endpoint += (split[0] || key) + '#' + split[1];
    // Check if value looks like a source
    } else if (isSource(value)) {
        endpoint += value + '#*';
    // Otherwise use the key as the source
    } else {
        endpoint += key + '#' + split[0];
    }

    return decompose(endpoint);
}

function decomposed2json(decEndpoint) {
    var error;
    var key = decEndpoint.name;
    var value = '';
    var ret = {};

    if (!key) {
        error = new Error('Decomposed endpoint must have a name');
        error.code = 'EINVEND';
        throw error;
    }

    // Add source only if different than the name
    if  (decEndpoint.source !== decEndpoint.name) {
        value += decEndpoint.source;
    }

    // If value is empty, we append the target always
    if (!value) {
        value += isWildcard(decEndpoint.target) ? '*' : decEndpoint.target;
    // Otherwise append only if not a wildcard
    } else if (!isWildcard(decEndpoint.target)) {
        value += '#' + decEndpoint.target;
    }

    ret[key] = value;

    return ret;
}

function isWildcard(target) {
    return !target || target === '*' || target === 'latest';
}

function isSource(value) {
    return value.indexOf('/') !== -1 || value.indexOf('\\') !== -1 || value.indexOf('@') !== -1;
}

module.exports.decompose = decompose;
module.exports.compose = compose;
module.exports.json2decomposed = json2decomposed;
module.exports.decomposed2json = decomposed2json;

{'fraction_non_alphanumeric': 0.16506835339726586, 'fraction_numerical': 0.00632523974699041, 'mean_word_length': 2.511461318051576, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6946240', 'n_tokens_mistral': 1569, 'n_tokens_neox': 1512, 'n_words': 387}