"use strict";
/*
 * Copyright © 2019 Atomist, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.hasResourceProvider = exports.hasFileContaining = exports.isBranch = exports.isRepo = exports.IsPushToBranchWithPullRequest = exports.hasFileWithExtension = exports.NonEmpty = exports.hasFile = exports.AnyPush = exports.FromAtomist = exports.ToDefaultBranch = void 0;
const string_1 = require("@atomist/automation-client/lib/internal/util/string");
const projectUtils_1 = require("@atomist/automation-client/lib/project/util/projectUtils");
const _ = require("lodash");
const types_1 = require("../../../typings/types");
const PushTest_1 = require("../PushTest");
exports.ToDefaultBranch = PushTest_1.pushTest("Push to default branch", async (p) => p.push.branch === p.push.repo.defaultBranch ||
    ((!p.push.repo.defaultBranch || p.push.repo.defaultBranch.length === 0) && p.push.branch === "master"));
/**
 * Is this a push originated by Atomist? Note that we can't look at the committer,
 * as if a user invoked a command handler, their credentials will be used
 * @param {PushListenerInvocation} p
 * @return {boolean}
 * @constructor
 */
exports.FromAtomist = PushTest_1.pushTest("Push from Atomist", async (p) => p.push.after.message.includes("[atomist]"));
/**
 * Match on any push
 * @param {PushListenerInvocation} p
 * @constructor
 */
exports.AnyPush = PushTest_1.pushTest("Any push", async () => true);
/**
 * Return a PushTest testing for the existence of the given file
 * @param {string} path
 * @return {PushTest}
 */
function hasFile(path) {
    return PushTest_1.predicatePushTest(`HasFile(${path})`, async (p) => !!(await p.getFile(path)));
}
exports.hasFile = hasFile;
/**
 * PushTest that returns true if project is non empty
 * @type {PredicatePushTest}
 */
exports.NonEmpty = PushTest_1.predicatePushTest("NonEmpty", async (p) => (await p.totalFileCount()) > 0);
/**
 * Is there at least one file with the given extension?
 * @param {string} extension
 * @return {PredicatePushTest}
 */
function hasFileWithExtension(extension) {
    if (!extension) {
        return exports.NonEmpty;
    }
    const extensionToUse = extension.startsWith(".") ? extension : `.${extension}`;
    return PushTest_1.predicatePushTest(`HasFileWithExtension(${extensionToUse}})`, async (p) => projectUtils_1.fileExists(p, `**/*${extensionToUse}`, () => true));
}
exports.hasFileWithExtension = hasFileWithExtension;
/**
 * Is this push to a non-default branch that has an open pull request?
 */
exports.IsPushToBranchWithPullRequest = PushTest_1.pushTest("Push to branch with open pull request", async (p) => {
    if (p.push.branch === p.push.repo.defaultBranch) {
        return false;
    }
    const result = await p.context.graphClient.query({
        name: "PullRequestsForBranch",
        variables: {
            repo: p.push.repo.name,
            owner: p.push.repo.owner,
            branch: p.push.branch,
        },
    });
    const branch = _.get(result, "Repo[0].branches[0]");
    if (branch && branch.pullRequests && branch.pullRequests.some(pr => pr.state === "open")) {
        return true;
    }
    return false;
});
/**
 * Return a push test that matches the repository owner/repo slug
 * against regular expression.
 * @param re Regular expression to match against using RegExp.test()
 * @return Push test performing the match
 */
function isRepo(re) {
    return PushTest_1.pushTest(`Project owner/name slug matches regular expression ${re.toString()}`, async (pci) => re.test(`${pci.id.owner}/${pci.id.repo}`));
}
exports.isRepo = isRepo;
/**
 * Return a push test that matches the repository branch
 * against regular expression.
 * @param re Regular expression to match against using RegExp.test()
 * @return Push test performing the match
 */
function isBranch(re) {
    return PushTest_1.pushTest(`Project branch matches regular expression ${re.toString()}`, async (pci) => re.test(pci.push.branch));
}
exports.isBranch = isBranch;
/**
 * Return a PushTest testing for the existence of the given file containing the pattern
 * @param {string} path
 * @param pattern regex to look for
 * @return {PushTest}
 */
function hasFileContaining(pattern, content = /.*/) {
    return PushTest_1.pushTest(`Project has files ${string_1.toStringArray(pattern).join(", ")} with content ${content.toString()}`, async (pci) => {
        const files = await pci.project.getFiles(string_1.toStringArray(pattern));
        if (files.length === 0) {
            return false;
        }
        for (const file of files) {
            const fc = await file.getContent();
            if (content.test(fc)) {
                return true;
            }
        }
        return false;
    });
}
exports.hasFileContaining = hasFileContaining;
/**
 * Return a PushTest that checks if a certain resource provider exists in the graph
 */
function hasResourceProvider(type, name) {
    return PushTest_1.pushTest(`Workspace has resource provider of type '${type}'`, async (pci) => {
        switch (type) {
            case "docker":
                const dockerResult = await pci.context.graphClient.query({
                    name: "DockerRegistryProvider",
                    variables: {
                        name,
                    },
                });
                const dockerProvider = dockerResult.DockerRegistryProvider[0];
                if (!!dockerProvider) {
                    return dockerProvider.state.name === types_1.ResourceProviderStateName.converged;
                }
                return false;
            case "npm":
            case "maven2":
                const binaryResult = await pci.context.graphClient.query({
                    name: "BinaryRepositoryProvider",
                    variables: {
                        type: type,
                        name,
                    },
                });
                const binaryProvider = binaryResult.BinaryRepositoryProvider[0];
                if (!!binaryProvider) {
                    return binaryProvider.state.name === types_1.ResourceProviderStateName.converged;
                }
                return false;
            default:
                return false;
        }
    });
}
exports.hasResourceProvider = hasResourceProvider;
//# sourceMappingURL=commonPushTests.js.map