Package com.gitblit.service

Source Code of com.gitblit.service.MirrorService

/*
* Copyright 2013 gitblit.com.
*
* 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.gitblit.service;

import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceiveCommand.Type;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.TrackingRefUpdate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.git.ReceiveCommandEvent;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.tickets.BranchTicketService;
import com.gitblit.utils.JGitUtils;

/**
* The Mirror service handles periodic fetching of mirrored repositories.
*
* @author James Moger
*
*/
public class MirrorService implements Runnable {

  private final Logger logger = LoggerFactory.getLogger(MirrorService.class);

  private final Set<String> repairAttempted = Collections.synchronizedSet(new HashSet<String>());

  private final IStoredSettings settings;

  private final IRepositoryManager repositoryManager;

  private AtomicBoolean running = new AtomicBoolean(false);

  private AtomicBoolean forceClose = new AtomicBoolean(false);

  private final UserModel gitblitUser;

  public MirrorService(
      IStoredSettings settings,
      IRepositoryManager repositoryManager) {

    this.settings = settings;
    this.repositoryManager = repositoryManager;
    this.gitblitUser = new UserModel("gitblit");
    this.gitblitUser.displayName = "Gitblit";
  }

  public boolean isReady() {
    return settings.getBoolean(Keys.git.enableMirroring, false);
  }

  public boolean isRunning() {
    return running.get();
  }

  public void close() {
    forceClose.set(true);
  }

  @Override
  public void run() {
    if (!isReady()) {
      return;
    }

    running.set(true);

    for (String repositoryName : repositoryManager.getRepositoryList()) {
      if (forceClose.get()) {
        break;
      }
      if (repositoryManager.isCollectingGarbage(repositoryName)) {
        logger.debug("mirror is skipping {} garbagecollection", repositoryName);
        continue;
      }
      RepositoryModel model = null;
      Repository repository = null;
      try {
        model = repositoryManager.getRepositoryModel(repositoryName);
        if (!model.isMirror && !model.isBare) {
          // repository must be a valid bare git mirror
          logger.debug("mirror is skipping {} !mirror !bare", repositoryName);
          continue;
        }

        repository = repositoryManager.getRepository(repositoryName);
        if (repository == null) {
          logger.warn(MessageFormat.format("MirrorExecutor is missing repository {0}?!?", repositoryName));
          continue;
        }

        // automatically repair (some) invalid fetch ref specs
        if (!repairAttempted.contains(repositoryName)) {
          repairAttempted.add(repositoryName);
          JGitUtils.repairFetchSpecs(repository);
        }

        // find the first mirror remote - there should only be one
        StoredConfig rc = repository.getConfig();
        RemoteConfig mirror = null;
        List<RemoteConfig> configs = RemoteConfig.getAllRemoteConfigs(rc);
        for (RemoteConfig config : configs) {
          if (config.isMirror()) {
            mirror = config;
            break;
          }
        }

        if (mirror == null) {
          // repository does not have a mirror remote
          logger.debug("mirror is skipping {} no mirror remote found", repositoryName);
          continue;
        }

        logger.debug("checking {} remote {} for ref updates", repositoryName, mirror.getName());
        final boolean testing = false;
        Git git = new Git(repository);
        FetchResult result = git.fetch().setRemote(mirror.getName()).setDryRun(testing).call();
        Collection<TrackingRefUpdate> refUpdates = result.getTrackingRefUpdates();
        if (refUpdates.size() > 0) {
          ReceiveCommand ticketBranchCmd = null;
          for (TrackingRefUpdate ru : refUpdates) {
            StringBuilder sb = new StringBuilder();
            sb.append("updated mirror ");
            sb.append(repositoryName);
            sb.append(" ");
            sb.append(ru.getRemoteName());
            sb.append(" -> ");
            sb.append(ru.getLocalName());
            if (ru.getResult() == Result.FORCED) {
              sb.append(" (forced)");
            }
            sb.append(" ");
            sb.append(ru.getOldObjectId() == null ? "" : ru.getOldObjectId().abbreviate(7).name());
            sb.append("..");
            sb.append(ru.getNewObjectId() == null ? "" : ru.getNewObjectId().abbreviate(7).name());
            logger.info(sb.toString());

            if (BranchTicketService.BRANCH.equals(ru.getLocalName())) {
              ReceiveCommand.Type type = null;
              switch (ru.getResult()) {
              case NEW:
                type = Type.CREATE;
                break;
              case FAST_FORWARD:
                type = Type.UPDATE;
                break;
              case FORCED:
                type = Type.UPDATE_NONFASTFORWARD;
                break;
              default:
                type = null;
                break;
              }

              if (type != null) {
                ticketBranchCmd = new ReceiveCommand(ru.getOldObjectId(),
                  ru.getNewObjectId(), ru.getLocalName(), type);
              }
            }
          }

          if (ticketBranchCmd != null) {
            repository.fireEvent(new ReceiveCommandEvent(model, ticketBranchCmd));
          }
        }
      } catch (Exception e) {
        logger.error("Error updating mirror " + repositoryName, e);
      } finally {
        // cleanup
        if (repository != null) {
          repository.close();
        }
      }
    }

    running.set(false);
  }
}
TOP

Related Classes of com.gitblit.service.MirrorService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.