All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hp.octane.integrations.services.pullrequestsandbranches.PullRequestAndBranchServiceImpl Maven / Gradle / Ivy

There is a newer version: 2.24.3.5
Show newest version
/**
 * Copyright 2017-2023 Open Text
 *
 * The only warranties for products and services of Open Text and
 * its affiliates and licensors (“Open Text”) are as may be set forth
 * in the express warranty statements accompanying such products and services.
 * Nothing herein should be construed as constituting an additional warranty.
 * Open Text shall not be liable for technical or editorial errors or
 * omissions contained herein. The information contained herein is subject
 * to change without notice.
 *
 * Except as specifically indicated otherwise, this document contains
 * confidential information and a valid license is required for possession,
 * use or copying. If this work is provided to the U.S. Government,
 * consistent with FAR 12.211 and 12.212, Commercial Computer Software,
 * Computer Software Documentation, and Technical Data for Commercial Items are
 * licensed to the U.S. Government under vendor's standard commercial license.
 *
 * 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.
 */

package com.hp.octane.integrations.services.pullrequestsandbranches;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.hp.octane.integrations.OctaneSDK;
import com.hp.octane.integrations.dto.DTOFactory;
import com.hp.octane.integrations.dto.connectivity.HttpMethod;
import com.hp.octane.integrations.dto.connectivity.OctaneRequest;
import com.hp.octane.integrations.dto.connectivity.OctaneResponse;
import com.hp.octane.integrations.dto.entities.Entity;
import com.hp.octane.integrations.dto.entities.EntityConstants;
import com.hp.octane.integrations.dto.scm.Branch;
import com.hp.octane.integrations.dto.scm.PullRequest;
import com.hp.octane.integrations.dto.scm.SCMRepositoryLinks;
import com.hp.octane.integrations.dto.scm.SCMType;
import com.hp.octane.integrations.exceptions.OctaneBulkException;
import com.hp.octane.integrations.exceptions.ResourceNotFoundException;
import com.hp.octane.integrations.services.entities.EntitiesService;
import com.hp.octane.integrations.services.entities.QueryHelper;
import com.hp.octane.integrations.services.pullrequestsandbranches.factory.*;
import com.hp.octane.integrations.services.pullrequestsandbranches.github.GithubV3FetchHandler;
import com.hp.octane.integrations.services.rest.RestService;
import com.hp.octane.integrations.utils.CIPluginSDKUtils;
import com.hp.octane.integrations.utils.SdkStringUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.http.HttpStatus;
import org.apache.http.entity.ContentType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * Default implementation of tests service
 */

final class PullRequestAndBranchServiceImpl implements PullRequestAndBranchService {
    private static final Logger logger = LogManager.getLogger(PullRequestAndBranchServiceImpl.class);
    private static final DTOFactory dtoFactory = DTOFactory.getInstance();

    private final OctaneSDK.SDKServicesConfigurer configurer;
    private final RestService restService;
    private final EntitiesService entitiesService;
    private final File persistenceFile;
    private Map prItems;
    private static final ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
    private static final String REMOVE_PREFIX = "origin/";


    PullRequestAndBranchServiceImpl(OctaneSDK.SDKServicesConfigurer configurer, RestService restService, EntitiesService entitiesService) {
        if (configurer == null) {
            throw new IllegalArgumentException("invalid configurer");
        }
        if (restService == null) {
            throw new IllegalArgumentException("rest service MUST NOT be null");
        }
        if (entitiesService == null) {
            throw new IllegalArgumentException("entities service MUST NOT be null");
        }
        this.configurer = configurer;
        this.restService = restService;
        this.entitiesService = entitiesService;

        logger.info(configurer.octaneConfiguration.getLocationForLog() + "initialized SUCCESSFULLY");

        if (configurer.pluginServices.getAllowedOctaneStorage() != null) {
            File storageDirectory = new File(configurer.pluginServices.getAllowedOctaneStorage(), "nga" + File.separator + configurer.octaneConfiguration.getInstanceId());
            if (!storageDirectory.mkdirs()) {
                logger.debug(configurer.octaneConfiguration.getLocationForLog() + "instance folder considered as exist");
            }
            persistenceFile = new File(storageDirectory, "pr-fetchers.json");
            logger.info(configurer.octaneConfiguration.getLocationForLog() + "hosting plugin PROVIDE available storage, PR persistence enabled");

            if (persistenceFile.exists()) {
                try {
                    JavaType type = objectMapper.getTypeFactory().constructCollectionType(List.class, PRItem.class);
                    List list = objectMapper.readValue(persistenceFile, type);
                    prItems = list.stream().collect(Collectors.toMap(PRItem::getKey, Function.identity()));
                } catch (IOException e) {
                    logger.info(configurer.octaneConfiguration.getLocationForLog() + "failed to read PR persisted file");
                }
            } else {
                prItems = new HashMap<>();
            }
        } else {
            persistenceFile = null;
            prItems = new HashMap<>();
            logger.info(configurer.octaneConfiguration.getLocationForLog() + "hosting plugin DO NOT PROVIDE available storage, PR persistence disabled");
        }
    }

    @Override
    public void sendPullRequests(List pullRequests, String workspaceId, PullRequestFetchParameters pullRequestFetchParameters, Consumer logConsumer) throws IOException {
        Map headers = new LinkedHashMap<>();
        headers.put(RestService.CONTENT_TYPE_HEADER, ContentType.APPLICATION_JSON.getMimeType());

        String url = configurer.octaneConfiguration.getUrl() +
                RestService.SHARED_SPACE_API_PATH_PART + configurer.octaneConfiguration.getSharedSpace() +
                "/workspaces/" + workspaceId + RestService.ANALYTICS_CI_PATH_PART + "pull-requests/";

        int sentCounter = 0;
        List> subSets = ListUtils.partition(pullRequests, 200);
        for (List list : subSets) {
            String json = dtoFactory.dtoCollectionToJson(list);
            OctaneRequest octaneRequest = dtoFactory.newDTO(OctaneRequest.class)
                    .setMethod(HttpMethod.PUT)
                    .setUrl(url)
                    .setHeaders(headers)
                    .setBody(json);

            OctaneResponse octaneResponse = restService.obtainOctaneRestClient().execute(octaneRequest);
            if (octaneResponse.getStatus() != HttpStatus.SC_OK) {
                if (octaneResponse.getStatus() == HttpStatus.SC_NOT_FOUND) {
                    throw new ResourceNotFoundException("Failed to sendPullRequests : received 404 status. Validate that you use correct workspace id and ALM Octane version is greater than " + PullRequestAndBranchService.BRANCH_COLLECTION_SUPPORTED_VERSION);
                } else {
                    throw new RuntimeException("Failed to sendPullRequests : (" + octaneResponse.getStatus() + ")" + octaneResponse.getBody());
                }
            } else {
                sentCounter += list.size();
                logConsumer.accept(String.format("Sent %s/%s pull requests.", sentCounter, pullRequests.size()));
            }
        }

        long lastUpdateTime = pullRequests.stream().map(PullRequest::getUpdatedTime).max(Comparator.naturalOrder()).orElse(0L);
        savePullRequestLastUpdateTime(workspaceId, pullRequestFetchParameters.getRepoUrl(), lastUpdateTime);
        logConsumer.accept("Last update time set to " + lastUpdateTime);
    }

    @Override
    public long getPullRequestLastUpdateTime(String workspaceId, String repoUrl) {
        String key = PRItem.buildKey(workspaceId, repoUrl);
        PRItem item = prItems.get(key);
        return item == null ? 0 : item.getLastUpdated();
    }

    @Override
    public BranchSyncResult syncBranchesToOctane(FetchHandler fetcherHandler, BranchFetchParameters fp, Long workspaceId, CommitUserIdPicker idPicker, Consumer logConsumer) throws IOException {

        //update ssh url
        String baseUrl = fetcherHandler.getRepoApiPath(fp.getRepoUrl());
        logConsumer.accept(fetcherHandler.getClass().getSimpleName() + " handler, Base url : " + baseUrl);
        SCMRepositoryLinks links = fetcherHandler.pingRepository(baseUrl, logConsumer);
        fp.setRepoUrlSsh(links.getSshUrl());
        if (fp.isUseSSHFormat()) {
            logConsumer.accept("Repo ssh format url : " + fp.getRepoUrlSsh());
        }
        String repoUrlForOctane = fp.isUseSSHFormat() ? fp.getRepoUrlSsh() : fp.getRepoUrl();


        //LOAD FROM CACHE
        boolean supportCaching = fetcherHandler instanceof GithubV3FetchHandler;
        Map sha2DateMapCache = null;
        if (supportCaching) {
            sha2DateMapCache = loadBranchCommitsFromCache(repoUrlForOctane, logConsumer);
        }

        //FETCH FROM CI SERVER
        List ciServerBranches = fetcherHandler.fetchBranches(fp, sha2DateMapCache, logConsumer);
        Map ciServerBranchMap = ciServerBranches.stream().collect(Collectors.toMap(Branch::getName, Function.identity()));

        //SAVE TO  CACHE
        if (supportCaching) {
            saveBranchCommitsToCache(repoUrlForOctane, logConsumer, sha2DateMapCache, ciServerBranches);
        }

        //GET BRANCHES FROM OCTANE
        String repoShortName = FetchUtils.getRepoShortName(fp.getRepoUrl());
        List roots = getRepositoryRoots(repoUrlForOctane, workspaceId);
        List octaneBranches = null;
        String rootId;
        if (roots != null && !roots.isEmpty()) {
            rootId = roots.get(0).getId();
            octaneBranches = getRepositoryBranches(rootId, workspaceId, false);
            logConsumer.accept("Found repository root with id " + rootId);
        } else {
            Entity createdRoot = createRepositoryRoot(repoUrlForOctane, repoShortName, workspaceId);
            rootId = createdRoot.getId();
            logConsumer.accept("Repository root is created with id " + rootId);
        }

        if (octaneBranches == null) {
            octaneBranches = Collections.emptyList();
        }

        List filterPatterns = FetchUtils.buildPatterns(fp.getFilter());
        Map> octaneBranchMap = octaneBranches.stream()
                .filter(br -> FetchUtils.isBranchMatch(filterPatterns, br.getName()))
                .collect(groupingBy(b -> b.getName()));
        logConsumer.accept("Found " + octaneBranches.size() + " branches in ALM Octane related to defined filter.");

        //GENERATE UPDATES
        String finalRootId = rootId;
        BranchSyncResult result = new BranchSyncResult();

        //DELETED
        octaneBranchMap.entrySet().stream().filter(entry -> !ciServerBranchMap.containsKey(entry.getKey()))
                .map(e -> e.getValue()).flatMap(Collection::stream)
                .map(e -> dtoFactory.newDTO(Branch.class).setOctaneId(e.getId()).setName(e.getName()))
                .forEach(b -> result.getDeleted().add(b));

        //NEW AND UPDATES
        ciServerBranches.forEach(ciBranch -> {
            if (ciBranch.isPartial()) {
                //SKIP if branch is partial (it can happen because of rate limitations or because branch is merged to master or not active for long time)
                return;
            }
            List octaneBranchList = octaneBranchMap.get(ciBranch.getName());
            if (octaneBranchList == null) {//not exist in octane, check if to add
                long diff = System.currentTimeMillis() - ciBranch.getLastCommitTime();
                long diffDays = TimeUnit.MILLISECONDS.toDays(diff);
                if (diffDays < fp.getActiveBranchDays()) {
                    result.getCreated().add(ciBranch);
                }
            } else {//check for update
                octaneBranchList.forEach(octaneBranch -> {
                    if (!ciBranch.getLastCommitSHA().equals(octaneBranch.getField(EntityConstants.ScmRepository.LAST_COMMIT_SHA_FIELD)) ||
                            !ciBranch.getIsMerged().equals(octaneBranch.getField(EntityConstants.ScmRepository.IS_MERGED_FIELD))) {
                        ciBranch.setOctaneId(octaneBranch.getId());
                        result.getUpdated().add(ciBranch);
                    }
                });
            }
        });

        //SEND TO OCTANE
        if (!result.getDeleted().isEmpty()) {
            List toDelete = result.getDeleted().stream().map(b -> buildOctaneBranchForUpdateAsDeleted(b)).collect(Collectors.toList());
            entitiesService.updateEntities(workspaceId, EntityConstants.ScmRepository.COLLECTION_NAME, toDelete);
            logConsumer.accept("Deleted branches : " + toDelete.size());
        }
        if (!result.getUpdated().isEmpty()) {
            List toUpdate = result.getUpdated().stream().map(b -> buildOctaneBranchForUpdate(b, idPicker)).collect(Collectors.toList());
            entitiesService.updateEntities(workspaceId, EntityConstants.ScmRepository.COLLECTION_NAME, toUpdate);
            logConsumer.accept("Updated branches : " + toUpdate.size());
        }
        if (!result.getCreated().isEmpty()) {
            List toCreate = result.getCreated().stream().map(b -> buildOctaneBranchForCreate(finalRootId, b, idPicker)).collect(Collectors.toList());
            try {
                entitiesService.postEntities(workspaceId, EntityConstants.ScmRepository.COLLECTION_NAME, toCreate);
                logConsumer.accept("New branches : " + toCreate.size());
            } catch (OctaneBulkException bulkException) {
                logConsumer.accept(String.format("New branches created: %s, failed to create %s branches",
                        (toCreate.size() - bulkException.getData().getErrors().size()), bulkException.getData().getErrors().size()));

                //handling previously deleted branches. (new branches were created with the name that already exist in Octane but set as deleted)
                boolean hasDuplicatedException = bulkException.getData().getErrors().stream()
                        .filter(ex -> EntityConstants.Errors.DUPLICATE_ERROR_CODE.equals(ex.getErrorCode())).findAny().isPresent();
                Map deletedBranchesInOctane = !hasDuplicatedException ? Collections.emptyMap() :
                        getRepositoryBranches(rootId, workspaceId, true).stream()
                                .collect(Collectors.toMap(e -> e.getStringValue(EntityConstants.ScmRepository.NAME_FIELD), Function.identity()));

                //try to update duplicates
                List deletedBranchesToUpdate = new ArrayList<>();
                bulkException.getData().getErrors().forEach(ex -> {
                    //if post was done with only one entity - index will be null
                    int index = ex.getIndex() == null ? 0 : ex.getIndex();
                    Branch branch = result.getCreated().get(index);
                    if (EntityConstants.Errors.DUPLICATE_ERROR_CODE.equals(ex.getErrorCode())) {
                        Entity octaneEntity = deletedBranchesInOctane.get(branch.getName());
                        if (octaneEntity != null) {
                            branch.setOctaneId(octaneEntity.getId());
                            deletedBranchesToUpdate.add(buildOctaneBranchForUpdate(branch, idPicker).setField(EntityConstants.ScmRepository.IS_DELETED_FIELD, false));
                        } else {
                            logConsumer.accept("Failed to create/update branch : " + branch.getName());
                        }
                    } else {
                        logConsumer.accept(String.format("Failed to create branch %s : %s ", branch.getName(), ex.getDescriptionTranslated()));
                    }
                });

                if (!deletedBranchesToUpdate.isEmpty()) {
                    entitiesService.updateEntities(workspaceId, EntityConstants.ScmRepository.COLLECTION_NAME, deletedBranchesToUpdate);
                    logConsumer.accept("New branches that appear as deleted in ALM OCtane : " + deletedBranchesToUpdate.size());
                }
            }
        }
        if (result.getDeleted().isEmpty() && result.getUpdated().isEmpty() && result.getCreated().isEmpty()) {
            logConsumer.accept("No changes are found.");
        }

        return result;
    }

    private void saveBranchCommitsToCache(String repoUrlForOctane, Consumer logConsumer, Map sha2DateMapCache, List ciServerBranches) {
        HashMap newSha2DateMapCache = new HashMap<>();
        newSha2DateMapCache.putAll(sha2DateMapCache);
        ciServerBranches.stream().filter(b -> b.getLastCommitTime() != null).forEach(b -> newSha2DateMapCache.put(b.getLastCommitSHA(), b.getLastCommitTime()));
        File cacheFile = getFileForBranchCaching(repoUrlForOctane);
        try {
            objectMapper.writerWithDefaultPrettyPrinter().writeValue(cacheFile, newSha2DateMapCache);
            logConsumer.accept(String.format("Cache of commits is saved with %s items ", newSha2DateMapCache.size()));
        } catch (Exception e) {
            logConsumer.accept("Failed to  save commit cache : " + e.getMessage());
        }
    }

    private Map loadBranchCommitsFromCache(String repoUrl, Consumer logConsumer) {
        Map sha2DateMapCache = Collections.emptyMap();

        TypeReference> typeRef = new TypeReference>() {
        };
        File cacheFile = getFileForBranchCaching(repoUrl);
        if (cacheFile.exists()) {
            try {
                sha2DateMapCache = objectMapper.readValue(cacheFile, typeRef);
                logConsumer.accept(String.format("Cache of commits is loaded with %s items ", sha2DateMapCache.size()));
            } catch (Exception e) {
                logConsumer.accept("Failed to load cache of commits : " + e.getMessage());
            }
        }

        return sha2DateMapCache;
    }

    private File getFileForBranchCaching(String url) {
        String urlReplacement = url.replace(":", "_").replace("/", "_").replaceAll("[<>:\"/\\|?*]", "_");

        String path = configurer.pluginServices.getAllowedOctaneStorage() + File.separator +
                "nga" + File.separator + configurer.octaneConfiguration.getInstanceId() + File.separator + "branchCache_" + urlReplacement;
        return new File(path);
    }

    private Entity createRepositoryRoot(String repoUrlForOctane, String repoShortName, Long workspaceId) {
        Entity entity = DTOFactory.getInstance().newDTO(Entity.class);
        entity.setType(EntityConstants.ScmRepositoryRoot.ENTITY_NAME);
        entity.setField(EntityConstants.ScmRepositoryRoot.URL_FIELD, repoUrlForOctane);
        entity.setField(EntityConstants.ScmRepositoryRoot.NAME_FIELD, repoShortName);
        entity.setField(EntityConstants.ScmRepositoryRoot.SCM_TYPE_FIELD, SCMType.GIT.getOctaneId());
        List results = entitiesService.postEntities(workspaceId, EntityConstants.ScmRepositoryRoot.COLLECTION_NAME, Arrays.asList(entity));

        return results.get(0);
    }

    @Override
    public boolean updateRepoTemplates(String repoUrl, Long workspaceId, RepoTemplates repoTemplates) {
        List roots = getRepositoryRoots(repoUrl, workspaceId);
        int trialCounter = 0;
        while (roots.isEmpty() && trialCounter++ < 6) {
            logger.info(String.format("Wait to updateRepoTemplates - repo %s - %s", repoUrl, trialCounter));
            //pull request repo generate async way by CTP task, so might be delay in creation
            CIPluginSDKUtils.doWait(5000);
            roots = getRepositoryRoots(repoUrl, workspaceId);
        }
        if (roots.isEmpty()) {
            logger.info(String.format("UpdateRepoTemplates  - repo %s is not found in ALM Octane", repoUrl));
            return false;
        }

        Entity repo = roots.get(0);
        Entity entity = DTOFactory.getInstance().newDTO(Entity.class);
        entity.setField(EntityConstants.ScmRepositoryRoot.ID_FIELD, repo.getId());

        boolean needUpdate = false;
        if (SdkStringUtils.isNotEmpty(repoTemplates.getBranchFileTemplate()) &&
                SdkStringUtils.isEmpty(repo.getStringValue(EntityConstants.ScmRepositoryRoot.BRANCH_TEMPLATE))) {
            entity.setField(EntityConstants.ScmRepositoryRoot.BRANCH_TEMPLATE, repoTemplates.getBranchFileTemplate());
            needUpdate = true;
        }
        if (SdkStringUtils.isNotEmpty(repoTemplates.getDiffTemplate()) &&
                SdkStringUtils.isEmpty(repo.getStringValue(EntityConstants.ScmRepositoryRoot.DIFF_TEMPLATE))) {
            entity.setField(EntityConstants.ScmRepositoryRoot.DIFF_TEMPLATE, repoTemplates.getDiffTemplate());
            needUpdate = true;
        }
        if (SdkStringUtils.isNotEmpty(repoTemplates.getSourceViewTemplate()) &&
                SdkStringUtils.isEmpty(repo.getStringValue(EntityConstants.ScmRepositoryRoot.SOURCE_VIEW_TEMPLATE))) {
            entity.setField(EntityConstants.ScmRepositoryRoot.SOURCE_VIEW_TEMPLATE, repoTemplates.getSourceViewTemplate());
            needUpdate = true;
        }

        if (needUpdate) {
            entitiesService.updateEntities(workspaceId, EntityConstants.ScmRepositoryRoot.COLLECTION_NAME, Arrays.asList(entity));
        }
        return needUpdate;
    }

    private Entity buildOctaneBranchForUpdateAsDeleted(Branch branch) {
        Entity entity = DTOFactory.getInstance().newDTO(Entity.class);
        entity.setType(EntityConstants.ScmRepository.ENTITY_NAME);
        entity.setId(branch.getOctaneId());
        entity.setField(EntityConstants.ScmRepository.IS_DELETED_FIELD, true);
        return entity;
    }

    private Entity buildOctaneBranchForUpdate(Branch ciBranch, CommitUserIdPicker idPicker) {
        Entity entity = DTOFactory.getInstance().newDTO(Entity.class);
        entity.setType(EntityConstants.ScmRepository.ENTITY_NAME);
        if (ciBranch.getOctaneId() != null) {
            entity.setId(ciBranch.getOctaneId());
        }

        entity.setField(EntityConstants.ScmRepository.IS_MERGED_FIELD, ciBranch.getIsMerged());
        entity.setField(EntityConstants.ScmRepository.LAST_COMMIT_SHA_FIELD, ciBranch.getLastCommitSHA());
        entity.setField(EntityConstants.ScmRepository.LAST_COMMIT_TIME_FIELD, FetchUtils.convertLongToISO8601DateString(ciBranch.getLastCommitTime()));
        entity.setField(EntityConstants.ScmRepository.SCM_USER_FIELD, idPicker.getUserIdForCommit(ciBranch.getLastCommiterEmail(), ciBranch.getLastCommiterName()));
        entity.setField(EntityConstants.ScmRepository.SCM_USER_EMAIL_FIELD, ciBranch.getLastCommiterEmail());
        return entity;
    }

    private Entity buildOctaneBranchForCreate(String rootId, Branch ciBranch, CommitUserIdPicker idPicker) {
        Entity parent = DTOFactory.getInstance().newDTO(Entity.class);
        parent.setType(EntityConstants.ScmRepositoryRoot.ENTITY_NAME);
        parent.setId(rootId);

        Entity entity = buildOctaneBranchForUpdate(ciBranch, idPicker);
        entity.setField(EntityConstants.ScmRepository.PARENT_FIELD, parent);
        entity.setField(EntityConstants.ScmRepository.NAME_FIELD, ciBranch.getName());
        return entity;
    }

    private List getRepositoryRoots(String repoUrl, Long workspaceId) {
        String rootByUrlCondition = QueryHelper.condition(EntityConstants.ScmRepositoryRoot.URL_FIELD, repoUrl);
        List foundRoots = entitiesService.getEntities(workspaceId,
                EntityConstants.ScmRepositoryRoot.COLLECTION_NAME,
                Collections.singleton(rootByUrlCondition),
                Arrays.asList(EntityConstants.Base.ID_FIELD,
                        EntityConstants.ScmRepositoryRoot.BRANCH_TEMPLATE,
                        EntityConstants.ScmRepositoryRoot.DIFF_TEMPLATE,
                        EntityConstants.ScmRepositoryRoot.SOURCE_VIEW_TEMPLATE));
        return foundRoots;
    }

    private List getRepositoryBranches(String repositoryRootId, Long workspaceId, boolean deleted) {
        String byParentIdCondition = QueryHelper.conditionRef(EntityConstants.ScmRepository.PARENT_FIELD, Long.parseLong(repositoryRootId));
        String notDeletedCondition = QueryHelper.condition(EntityConstants.ScmRepository.IS_DELETED_FIELD, deleted);
        List foundBranches = entitiesService.getEntities(workspaceId,
                EntityConstants.ScmRepository.COLLECTION_NAME,
                Arrays.asList(byParentIdCondition, notDeletedCondition),
                Arrays.asList(EntityConstants.ScmRepository.NAME_FIELD,
                        EntityConstants.ScmRepository.IS_MERGED_FIELD,
                        EntityConstants.ScmRepository.LAST_COMMIT_SHA_FIELD,
                        EntityConstants.ScmRepository.LAST_COMMIT_TIME_FIELD));

        return foundBranches;
    }

    private synchronized void savePullRequestLastUpdateTime(String workspaceId, String repoUrl, long lastUpdateTime) {
        PRItem item = PRItem.create(workspaceId, repoUrl, lastUpdateTime);
        prItems.put(item.getKey(), item);
        if (persistenceFile != null) {
            try {
                objectMapper.writeValue(persistenceFile, prItems.values());
            } catch (IOException e) {
                logger.info(configurer.octaneConfiguration.getLocationForLog() + "failed to save PR persisted file");
            }
        }
    }

    public static class PRItem implements Serializable {
        private String workspace;
        private String repositoryUrl;
        private long lastUpdated;

        public static PRItem create(String workspace, String repositoryUrl, long lastUpdated) {
            PRItem item = new PRItem();
            item.workspace = workspace;
            item.repositoryUrl = repositoryUrl;
            item.lastUpdated = lastUpdated;
            return item;
        }

        @JsonIgnore
        public String getKey() {
            return buildKey(getWorkspace(), getRepositoryUrl());
        }

        public static String buildKey(String workspace, String repositoryUrl) {
            return workspace + "_" + repositoryUrl;
        }

        public String getWorkspace() {
            return workspace;
        }

        public String getRepositoryUrl() {
            return repositoryUrl;
        }

        public long getLastUpdated() {
            return lastUpdated;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy