public Map commitAllChanges()

in git-server/src/main/java/jetbrains/buildServer/buildTriggers/vcs/git/GitRepositoryInitializingExtension.java [53:218]


  public Map<String, String> commitAllChanges(@NotNull CentralRepositoryConfiguration repositoryConfiguration,
                                              @NotNull CommitSettings commitSettings,
                                              @NotNull List<String> ignoredPaths,
                                              @Nullable FilesProcessor filesProcessor) throws VcsException {
    String repositoryUrl = repositoryConfiguration.getRepositoryUrl().replace(TC_DATA_DIR, myServerPaths.getDataDirectory().getAbsolutePath());
    String fullBranch = repositoryConfiguration.getBranch();
    Path configDir = Paths.get(myServerPaths.getConfigDir());
    try {
      patchGitIgnore(configDir, ignoredPaths);
    } catch (IOException e) {
      throw new VcsException("Can not create .gitignore file at path: " + repositoryUrl, e);
    }

    File repoDir = null;
    Repository db = null;
    try {
      String repoPath;
      GitVcsRoot gitRoot;
      final String initBranch = "tempInitializationBranch";
      Map<String, String> props = myVcs.getDefaultVcsProperties();
      Path localRepo = myServerPaths.getCacheDirectory("centralConfigsRepository").toPath().resolve("localMirror");
      boolean shouldCreateRepo = shouldCreateRepo(localRepo, repositoryUrl);
      try {
        if (shouldCreateRepo && Files.exists(localRepo)) {
          FileUtil.delete(localRepo.toFile());
        }
        repoPath = localRepo.toFile().getAbsolutePath();

        if (shouldCreateRepo) {
          repoDir = FileUtil.createDir(localRepo.toFile());

          myGitRepoOperations.initCommand().init(repoPath, false, initBranch);
        }
        props.put(Constants.FETCH_URL, repositoryUrl);
        props.put(Constants.BRANCH_NAME, repositoryConfiguration.getBranch());
        if (CentralRepositoryConfiguration.Auth.KEY.equals(repositoryConfiguration.getAuth())) {
          props.put(Constants.AUTH_METHOD, AuthenticationMethod.PRIVATE_KEY_FILE.toString());
          Path authKeyPath = CentralConfigsRepositoryUtils.getCentralConfigsRepositoryPluginData(myServerPaths).resolve(CentralConfigsRepository.KEY_FILE_NAME).toAbsolutePath();
          if (!Files.exists(authKeyPath)) {
            throw new RuntimeException("Private key for repository isn't found. Upload private key with write access to the repository");
          }
          props.put(Constants.PRIVATE_KEY_PATH, authKeyPath.toString());
        }
        VcsRootImpl dummyRoot = new VcsRootImpl(-1, Constants.VCS_NAME, props);

        OperationContext operationContext = myVcs.createContext(dummyRoot, "Repository initialization");
        gitRoot = operationContext.getGitRoot();

        if (shouldCreateRepo) {
          PersonIdent personIdent = PersonIdentFactory.getTagger(gitRoot, operationContext.getRepository());
          List<Pair<String, String>> configProps = Arrays.asList(
            Pair.create("user.name", personIdent.getName()),
            Pair.create("user.email", personIdent.getEmailAddress()),
            Pair.create("core.autocrlf", "false"),
            Pair.create("receive.denyCurrentBranch", "ignore")
          );

          for (Pair<String, String> configProp : configProps) {
            myGitRepoOperations.configCommand().addConfigParameter(repoPath, GitConfigCommand.Scope.LOCAL, configProp.getFirst(), configProp.getSecond());
          }
        }
      } catch (VcsException | IOException e) {
        throw new RuntimeException("Could not create local git repository for committing current configuration files, error: " + e.getMessage());
      }

      try {
        db = FileRepositoryBuilder.create(new File(repoPath, ".git"));
      } catch (IOException e) {
        throw new RuntimeException("Could not create local git repository for committing current configuration files, error: " + e.getMessage(), e);
      }
      if (shouldCreateRepo) {
        StoredConfig config = db.getConfig();
        config.setString("remote", "origin", "url", repositoryUrl);
        config.setString("remote", "origin", "fetch", "+refs/*:refs/*");
        try {
          config.save();
        } catch (IOException e) {
          throw new RuntimeException("Could not bind origin remote repository with the local repository, error: " + e.getMessage(), e);
        }
      }
      Git git = new Git(db);
      RefSpec refSpec = new RefSpec().setSourceDestination("refs/*", "refs/*").setForceUpdate(true);
      try {
        myGitRepoOperations.fetchCommand(repositoryUrl).fetch(db,
                                                              gitRoot.getRepositoryFetchURL().get(),
                                                              new FetchSettings(gitRoot.getAuthSettings(),
                                                                                Collections.singleton(refSpec)));
      } catch (IOException| VcsException e) {
        throw new RuntimeException("TeamCity can not fetch changes from remote repository: " + e.getMessage(), e);
      }
      boolean originExisted = false;
      RevCommit createdCommit;
      RevCommit lastCommit;
      try {
        for (Ref branchRef : git.branchList().call()) {
          if (branchRef.getName().equals(repositoryConfiguration.getBranch())) {
            originExisted = true;
            break;
          }
        }
        String shortBranch = fullBranch.replace("refs/heads/", "");
        if (originExisted) {
          git.branchCreate().
             setName(initBranch).
             setStartPoint(shortBranch).
             call();
        }
        lastCommit = getLastCommit(db, fullBranch);

        if (shouldCreateRepo) {
          myGitRepoOperations.configCommand().addConfigParameter(repoPath, GitConfigCommand.Scope.LOCAL, "core.worktree", configDir.toString());
        }
        if (filesProcessor == null) {
          myGitRepoOperations.addCommand().add(repoPath, Collections.emptyList());
          myGitRepoOperations.commitCommand().commit(repoPath, commitSettings);
        } else {
          Files.walkFileTree(configDir, new FileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
              return processByProcessor(dir, filesProcessor, repoPath);
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
              return processByProcessor(file, filesProcessor, repoPath);
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
              return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
              return FileVisitResult.CONTINUE;
            }
          });
          myGitRepoOperations.addCommand().add(repoPath, Collections.emptyList());
          myGitRepoOperations.commitCommand().commit(repoPath, commitSettings);

          if (!db.getRefDatabase().hasRefs()) {
            //no refs exist, there were nothing to commit
            return props;
          }
        }
        createdCommit = getLastCommit(db, GitUtils.expandRef(initBranch));
      } catch (Exception e) {
        throw new RuntimeException("Could not commit all current configuration files into local repository, error: " + e.getMessage(), e);
      }
      try {
        myGitRepoOperations.pushCommand(repositoryUrl).push(db, gitRoot, repositoryConfiguration.getBranch(), createdCommit.name(), lastCommit.name());
      } catch (VcsException e) {
        throw new RuntimeException("Could not push commits into the remote repository, error: " + e.getMessage(), e);
      }
      return props;
    } catch (Exception e) {
      if (repoDir != null) {
        FileUtil.delete(repoDir);
      }
      throw e;
    } finally {
      if (db != null) {
        db.close();
      }
    }
  }