示例#1
0
 public static boolean justOneGitRepository(Project project) {
   if (project.isDisposed()) {
     return true;
   }
   GitRepositoryManager manager = getRepositoryManager(project);
   return !manager.moreThanOneRoot();
 }
  @Override
  public void update(AnActionEvent e) {
    super.update(e);
    Presentation presentation = e.getPresentation();
    Project project = e.getProject();
    if (project == null) {
      presentation.setEnabled(false);
      presentation.setVisible(false);
      return;
    }

    VirtualFile[] vFiles = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
    if (vFiles == null || vFiles.length != 1 || vFiles[0] == null) { // only 1 file for now
      presentation.setEnabled(false);
      presentation.setVisible(true);
      return;
    }

    GitRepositoryManager manager = GitUtil.getRepositoryManager(project);

    GitRepository repository = manager.getRepositoryForFile(vFiles[0]);
    if (repository == null || repository.isFresh() || noBranchesToCompare(repository)) {
      presentation.setEnabled(false);
      presentation.setVisible(true);
      return;
    }

    presentation.setEnabled(true);
    presentation.setVisible(true);
  }
 /**
  * Prepare delete files handler.
  *
  * @param project the project
  * @param root a vcs root
  * @param files a files to commit
  * @param message a message file to use
  * @param nextCommitAuthor a author for the next commit
  * @param nextCommitAmend true, if the commit should be amended
  * @param nextCommitAuthorDate Author date timestamp to override the date of the commit or null if
  *     this overriding is not needed.
  * @return a simple handler that does the task
  * @throws VcsException in case of git problem
  */
 private static void commit(
     Project project,
     VirtualFile root,
     Collection<FilePath> files,
     File message,
     final String nextCommitAuthor,
     boolean nextCommitAmend,
     Date nextCommitAuthorDate)
     throws VcsException {
   boolean amend = nextCommitAmend;
   for (List<String> paths : VcsFileUtil.chunkPaths(root, files)) {
     GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.COMMIT);
     handler.setStdoutSuppressed(false);
     if (amend) {
       handler.addParameters("--amend");
     } else {
       amend = true;
     }
     handler.addParameters("--only", "-F", message.getAbsolutePath());
     if (nextCommitAuthor != null) {
       handler.addParameters("--author=" + nextCommitAuthor);
     }
     if (nextCommitAuthorDate != null) {
       handler.addParameters("--date", COMMIT_DATE_FORMAT.format(nextCommitAuthorDate));
     }
     handler.endOptions();
     handler.addParameters(paths);
     handler.run();
   }
   if (!project.isDisposed()) {
     GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
     manager.updateRepository(root);
   }
 }
示例#4
0
 @Nullable
 public static GitRepository getRepositoryForRootOrLogError(
     @NotNull Project project, @NotNull VirtualFile root) {
   GitRepositoryManager manager = getRepositoryManager(project);
   GitRepository repository = manager.getRepositoryForRoot(root);
   if (repository == null) {
     LOG.error("Repository is null for root " + root);
   }
   return repository;
 }
 private static void updateUntrackedFilesHolderOnFileAdd(
     @NotNull Project project,
     @NotNull VirtualFile root,
     @NotNull Collection<VirtualFile> addedFiles) {
   GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
   if (manager == null) {
     return;
   }
   final GitRepository repository = manager.getRepositoryForRoot(root);
   if (repository != null) {
     repository.getUntrackedFilesHolder().remove(addedFiles);
   }
 }
 /**
  * Scans the Git roots, selected for commit, for the root which is on a detached HEAD. Returns
  * null, if all repositories are on the branch. There might be several detached repositories, -
  * in that case only one is returned. This is because the situation is very rare, while it
  * requires a lot of additional effort of making a well-formed message.
  */
 @Nullable
 private DetachedRoot getDetachedRoot() {
   GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(myPanel.getProject());
   for (VirtualFile root : getSelectedRoots()) {
     GitRepository repository = repositoryManager.getRepositoryForRoot(root);
     if (repository == null) {
       continue;
     }
     if (!repository.isOnBranch()) {
       return new DetachedRoot(root, repository.isRebaseInProgress());
     }
   }
   return null;
 }
  /**
   * Returns true if the root was loaded with conflict. False is returned in all other cases: in the
   * case of success and in case of some other error.
   */
  private boolean loadRoot(final VirtualFile root) {
    LOG.info("loadRoot " + root);
    myProgressIndicator.setText(GitHandlerUtil.formatOperationName("Unstashing changes to", root));

    GitRepository repository = myRepositoryManager.getRepositoryForRoot(root);
    if (repository == null) {
      LOG.error("Repository is null for root " + root);
      return false;
    }

    GitSimpleEventDetector conflictDetector =
        new GitSimpleEventDetector(GitSimpleEventDetector.Event.MERGE_CONFLICT_ON_UNSTASH);
    GitCommandResult result = myGit.stashPop(repository, conflictDetector);
    VfsUtil.markDirtyAndRefresh(false, true, false, root);
    if (result.success()) {
      return false;
    } else if (conflictDetector.hasHappened()) {
      return true;
    } else {
      LOG.info("unstash failed " + result.getErrorOutputAsJoinedString());
      GitUIUtil.notifyImportantError(
          myProject, "Couldn't unstash", "<br/>" + result.getErrorOutputAsHtmlString());
      return false;
    }
  }
  @Override
  protected void save(@NotNull Collection<VirtualFile> rootsToSave) throws VcsException {
    LOG.info("saving " + rootsToSave);

    for (VirtualFile root : rootsToSave) {
      final String message = GitHandlerUtil.formatOperationName("Stashing changes from", root);
      LOG.info(message);
      final String oldProgressTitle = myProgressIndicator.getText();
      myProgressIndicator.setText(message);
      GitRepository repository = myRepositoryManager.getRepositoryForRoot(root);
      if (repository == null) {
        LOG.error("Repository is null for root " + root);
      } else {
        GitCommandResult result = myGit.stashSave(repository, myStashMessage);
        if (result.success() && somethingWasStashed(result)) {
          myStashedRoots.add(root);
        } else {
          String error =
              "stash " + repository.getRoot() + ": " + result.getErrorOutputAsJoinedString();
          if (!result.success()) {
            throw new VcsException(error);
          } else {
            LOG.warn(error);
          }
        }
      }
      myProgressIndicator.setText(oldProgressTitle);
    }
  }
示例#9
0
 @NotNull
 public GitFetchResult fetch(@NotNull VirtualFile root, @NotNull String remoteName) {
   GitRepository repository = myRepositoryManager.getRepositoryForRoot(root);
   if (repository == null) {
     return logError("Repository can't be null for " + root, myRepositoryManager.toString());
   }
   GitRemote remote = GitUtil.findRemoteByName(repository, remoteName);
   if (remote == null) {
     return logError("Couldn't find remote with the name " + remoteName, null);
   }
   String url = remote.getFirstUrl();
   if (url == null) {
     return logError("URL is null for remote " + remote.getName(), null);
   }
   return fetchRemote(repository, remote, url);
 }
 @Nullable
 protected GitRepository findRepository() {
   if (myRepository != null) {
     return myRepository;
   }
   myRepository = myGitRepositoryManager.getRepositoryForRoot(myContentRoot);
   return myRepository;
 }
 @Nullable
 @Override
 public String getCurrentBranch(@NotNull VirtualFile root) {
   GitRepository repository = myRepositoryManager.getRepositoryForRoot(root);
   if (repository == null) return null;
   String currentBranchName = repository.getCurrentBranchName();
   if (currentBranchName == null && repository.getCurrentRevision() != null) {
     return "HEAD";
   }
   return currentBranchName;
 }
  /**
   * Setup remotes combobox. The default remote for the current branch is selected by default. This
   * method gets current branch for the project.
   *
   * @param project the project
   * @param root the git root
   * @param remoteCombobox the combobox to update
   * @param fetchUrl if true, the fetch url is shown instead of push url
   */
  public static void setupRemotes(
      final Project project,
      final VirtualFile root,
      final JComboBox remoteCombobox,
      final boolean fetchUrl) {
    final GitRepository repo = GitRepositoryManager.getInstance(project).getRepositoryForRoot(root);
    assert repo != null : "GitRepository can't be null for root " + root;
    GitBranch gitBranch = repo.getCurrentBranch();

    final String branch = gitBranch != null ? gitBranch.getName() : null;
    setupRemotes(project, root, branch, remoteCombobox, fetchUrl);
  }
示例#13
0
 @NotNull
 public static Collection<GitRepository> getRepositoriesFromRoots(
     @NotNull GitRepositoryManager repositoryManager, @NotNull Collection<VirtualFile> roots) {
   Collection<GitRepository> repositories = new ArrayList<GitRepository>(roots.size());
   for (VirtualFile root : roots) {
     GitRepository repo = repositoryManager.getRepositoryForRoot(root);
     if (repo == null) {
       LOG.error("Repository not found for root " + root);
     } else {
       repositories.add(repo);
     }
   }
   return repositories;
 }
  @Override
  public void actionPerformed(final AnActionEvent event) {
    final Project project = event.getProject();
    assert project != null;

    final VirtualFile file = getAffectedFile(event);

    GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
    GitRepository repository = manager.getRepositoryForFile(file);
    assert repository != null;

    GitBranch currentBranch = repository.getCurrentBranch();
    final String head;
    if (currentBranch == null) {
      String currentRevision = repository.getCurrentRevision();
      LOG.assertTrue(
          currentRevision != null,
          "Current revision is null for "
              + repository
              + ". Compare with branch shouldn't be available for fresh repository");
      head = DvcsUtil.getShortHash(currentRevision);
    } else {
      head = currentBranch.getName();
    }
    final List<String> branchNames = getBranchNamesExceptCurrent(repository);

    // prepare and invoke popup
    final JBList list = new JBList(branchNames);

    JBPopupFactory.getInstance()
        .createListPopupBuilder(list)
        .setTitle("Select branch to compare")
        .setItemChoosenCallback(new OnBranchChooseRunnable(project, file, head, list))
        .setAutoselectOnMouseMove(true)
        .createPopup()
        .showInBestPositionFor(event.getDataContext());
  }
  @Override
  public void actionPerformed(AnActionEvent e) {
    Data data = Data.collect(e);
    if (!data.isValid()) {
      return;
    }

    List<VcsFullCommitDetails> details = data.log.getSelectedDetails();
    if (details.size() != 1) {
      return;
    }
    VcsFullCommitDetails commit = details.get(0);

    GitRepositoryManager repositoryManager =
        ServiceManager.getService(data.project, GitRepositoryManager.class);
    final GitRepository repository = repositoryManager.getRepositoryForRoot(commit.getRoot());
    if (repository == null) {
      DvcsUtil.noVcsRepositoryForRoot(
          LOG, commit.getRoot(), data.project, repositoryManager, GitVcs.getInstance(data.project));
      return;
    }

    actionPerformed(repository, commit);
  }
  @Override
  public void actionPerformed(@NotNull AnActionEvent event) {
    final Project project = event.getProject();
    if (project == null) {
      return;
    }

    final Set<VirtualFile> conflictedFiles =
        new TreeSet<VirtualFile>(
            new Comparator<VirtualFile>() {
              @Override
              public int compare(@NotNull VirtualFile f1, @NotNull VirtualFile f2) {
                return f1.getPresentableUrl().compareTo(f2.getPresentableUrl());
              }
            });
    for (Change change : ChangeListManager.getInstance(project).getAllChanges()) {
      if (change.getFileStatus() != FileStatus.MERGED_WITH_CONFLICTS) {
        continue;
      }
      final ContentRevision before = change.getBeforeRevision();
      final ContentRevision after = change.getAfterRevision();
      if (before != null) {
        final VirtualFile file = before.getFile().getVirtualFile();
        if (file != null) {
          conflictedFiles.add(file);
        }
      }
      if (after != null) {
        final VirtualFile file = after.getFile().getVirtualFile();
        if (file != null) {
          conflictedFiles.add(file);
        }
      }
    }

    AbstractVcsHelper.getInstance(project)
        .showMergeDialog(
            new ArrayList<VirtualFile>(conflictedFiles),
            GitVcs.getInstance(project).getMergeProvider());
    for (VirtualFile conflictedFile : conflictedFiles) {
      final GitRepository repo =
          GitRepositoryManager.getInstance(project).getRepositoryForFile(conflictedFile);
      if (repo != null) {
        repo.update(GitRepository.TrackedTopic.ALL_CURRENT);
      }
    }
  }
示例#17
0
 @NotNull
 private String makeAdditionalInfoByRoot(@NotNull Map<VirtualFile, String> additionalInfo) {
   if (additionalInfo.isEmpty()) {
     return "";
   }
   StringBuilder info = new StringBuilder();
   if (myRepositoryManager.moreThanOneRoot()) {
     for (Map.Entry<VirtualFile, String> entry : additionalInfo.entrySet()) {
       info.append(entry.getValue())
           .append(" in ")
           .append(GitUIUtil.getShortRepositoryName(myProject, entry.getKey()))
           .append("<br/>");
     }
   } else {
     info.append(additionalInfo.values().iterator().next());
   }
   return info.toString();
 }
  /**
   * Parse changes from lines
   *
   * @param root the git root
   * @return a set of unmerged files
   * @throws com.intellij.openapi.vcs.VcsException if the input format does not matches expected
   *     format
   */
  private List<VirtualFile> unmergedFiles(final VirtualFile root) throws VcsException {
    GitRepository repository = myRepositoryManager.getRepositoryForRoot(root);
    if (repository == null) {
      LOG.error("Repository not found for root " + root);
      return Collections.emptyList();
    }

    GitCommandResult result = myGit.getUnmergedFiles(repository);
    if (!result.success()) {
      throw new VcsException(result.getErrorOutputAsJoinedString());
    }

    String output = StringUtil.join(result.getOutput(), "\n");
    HashSet<String> unmergedPaths = ContainerUtil.newHashSet();
    for (StringScanner s = new StringScanner(output); s.hasMoreData(); ) {
      if (s.isEol()) {
        s.nextLine();
        continue;
      }
      s.boundedToken('\t');
      String relative = s.line();
      unmergedPaths.add(GitUtil.unescapePath(relative));
    }

    if (unmergedPaths.size() == 0) {
      return Collections.emptyList();
    } else {
      List<File> files =
          ContainerUtil.map(
              unmergedPaths,
              new Function<String, File>() {
                @Override
                public File fun(String path) {
                  return new File(root.getPath(), path);
                }
              });
      return sortVirtualFilesByPresentation(findVirtualFilesWithRefresh(files));
    }
  }
 @Nullable
 private GitRepository getRepository(@NotNull VirtualFile root) {
   myRepositoryManager.waitUntilInitialized();
   return myRepositoryManager.getRepositoryForRoot(root);
 }
  @NotNull
  @Override
  public DetailedLogData readFirstBlock(
      @NotNull VirtualFile root, @NotNull Requirements requirements) throws VcsException {
    if (!isRepositoryReady(root)) {
      return LogDataImpl.empty();
    }
    GitRepository repository =
        ObjectUtils.assertNotNull(myRepositoryManager.getRepositoryForRoot(root));

    // need to query more to sort them manually; this doesn't affect performance: it is equal for
    // -1000 and -2000
    int commitCount = requirements.getCommitCount() * 2;

    String[] params =
        new String[] {"HEAD", "--branches", "--remotes", "--max-count=" + commitCount};
    // NB: not specifying --tags, because it introduces great slowdown if there are many tags,
    // but makes sense only if there are heads without branch or HEAD labels (rare case). Such cases
    // are partially handled below.

    boolean refresh =
        requirements instanceof VcsLogProviderRequirementsEx
            && ((VcsLogProviderRequirementsEx) requirements).isRefresh();

    DetailedLogData data = GitHistoryUtils.loadMetadata(myProject, root, true, params);

    Set<VcsRef> safeRefs = data.getRefs();
    Set<VcsRef> allRefs = new OpenTHashSet<VcsRef>(safeRefs, DONT_CONSIDER_SHA);
    Set<VcsRef> branches = readBranches(repository);
    addNewElements(allRefs, branches);

    Collection<VcsCommitMetadata> allDetails;
    Set<String> currentTagNames = null;
    DetailedLogData commitsFromTags = null;
    if (!refresh) {
      allDetails = data.getCommits();
    } else {
      // on refresh: get new tags, which point to commits not from the first block; then get
      // history, walking down just from these tags
      // on init: just ignore such tagged-only branches. The price for speed-up.
      VcsLogProviderRequirementsEx rex = (VcsLogProviderRequirementsEx) requirements;

      currentTagNames = readCurrentTagNames(root);
      addOldStillExistingTags(allRefs, currentTagNames, rex.getPreviousRefs());

      allDetails = newHashSet(data.getCommits());

      Set<String> previousTags =
          newHashSet(ContainerUtil.mapNotNull(rex.getPreviousRefs(), GET_TAG_NAME));
      Set<String> safeTags = newHashSet(ContainerUtil.mapNotNull(safeRefs, GET_TAG_NAME));
      Set<String> newUnmatchedTags = remove(currentTagNames, previousTags, safeTags);

      if (!newUnmatchedTags.isEmpty()) {
        commitsFromTags = loadSomeCommitsOnTaggedBranches(root, commitCount, newUnmatchedTags);
        addNewElements(allDetails, commitsFromTags.getCommits());
        addNewElements(allRefs, commitsFromTags.getRefs());
      }
    }

    StopWatch sw = StopWatch.start("sorting commits in " + root.getName());
    List<VcsCommitMetadata> sortedCommits = VcsLogSorter.sortByDateTopoOrder(allDetails);
    sortedCommits =
        sortedCommits.subList(0, Math.min(sortedCommits.size(), requirements.getCommitCount()));
    sw.report();

    if (LOG.isDebugEnabled()) {
      validateDataAndReportError(
          root, allRefs, sortedCommits, data, branches, currentTagNames, commitsFromTags);
    }

    return new LogDataImpl(allRefs, sortedCommits);
  }
 @Nullable
 private GitRepository getRepository(@NotNull VirtualFile root) {
   return myRepositoryManager.getRepositoryForRoot(root);
 }
 @NotNull
 protected String makeProgressTitle(@NotNull String operation) {
   return myRepositoryManager.moreThanOneRoot()
       ? String.format("%s %s...", operation, myRoot.getName())
       : operation + "...";
 }
  public void checkGitUrl(final T settings) throws ConfigurationException {
    if (!(myDeploymentSource instanceof ModuleDeploymentSource)) {
      return;
    }

    ModuleDeploymentSource moduleSource = (ModuleDeploymentSource) myDeploymentSource;
    Module module = moduleSource.getModule();
    if (module == null) {
      return;
    }

    File contentRootFile = myDeploymentSource.getFile();
    if (contentRootFile == null) {
      return;
    }

    final Project project = module.getProject();

    if (myGitRepositoryManager == null) {
      myGitRepositoryManager = GitUtil.getRepositoryManager(project);
    }

    VirtualFile contentRoot =
        LocalFileSystem.getInstance().refreshAndFindFileByIoFile(contentRootFile);
    if (contentRoot == null) {
      return;
    }

    GitRepository repository = myGitRepositoryManager.getRepositoryForRoot(contentRoot);
    if (repository == null) {
      return;
    }

    String expectedName = settings.getDeploymentSourceName(myDeploymentSource);

    List<String> appNames = myDetector.collectApplicationNames(repository);
    if (appNames.isEmpty() || appNames.contains(expectedName)) {
      return;
    }

    RuntimeConfigurationWarning warning =
        new RuntimeConfigurationWarning(
            "Cloud Git URL found in repository, but it doesn't match the run configuration");

    warning.setQuickFix(
        new Runnable() {

          @Override
          public void run() {
            CloudGitApplication application =
                new CloudConnectionTask<CloudGitApplication, SC, T, SR>(
                    project, "Searching for application", myServer) {

                  @Override
                  protected CloudGitApplication run(SR serverRuntime)
                      throws ServerRuntimeException {
                    CloudGitDeploymentRuntime deploymentRuntime =
                        (CloudGitDeploymentRuntime)
                            serverRuntime.createDeploymentRuntime(
                                myDeploymentSource, settings, project);
                    return deploymentRuntime.findApplication4Repository();
                  }
                }.performSync();

            if (application == null) {
              Messages.showErrorDialog(
                  mySettingsEditor.getComponent(),
                  "No application matching repository URL(s) found in account");
            } else {
              T fixedSettings = mySettingsEditor.getFactory().create();
              fixedSettings.setDefaultDeploymentName(false);
              fixedSettings.setDeploymentName(application.getName());
              mySettingsEditor.resetFrom(fixedSettings);
            }
          }
        });

    throw warning;
  }
  /**
   * Preform a merge commit
   *
   * @param project a project
   * @param root a vcs root
   * @param added added files
   * @param removed removed files
   * @param messageFile a message file for commit
   * @param author an author
   * @param exceptions the list of exceptions to report
   * @param partialOperation
   * @return true if merge commit was successful
   */
  private static boolean mergeCommit(
      final Project project,
      final VirtualFile root,
      final Set<FilePath> added,
      final Set<FilePath> removed,
      final File messageFile,
      final String author,
      List<VcsException> exceptions,
      @NotNull final PartialOperation partialOperation) {
    HashSet<FilePath> realAdded = new HashSet<FilePath>();
    HashSet<FilePath> realRemoved = new HashSet<FilePath>();
    // perform diff
    GitSimpleHandler diff = new GitSimpleHandler(project, root, GitCommand.DIFF);
    diff.setSilent(true);
    diff.setStdoutSuppressed(true);
    diff.addParameters("--diff-filter=ADMRUX", "--name-status", "HEAD");
    diff.endOptions();
    String output;
    try {
      output = diff.run();
    } catch (VcsException ex) {
      exceptions.add(ex);
      return false;
    }
    String rootPath = root.getPath();
    for (StringTokenizer lines = new StringTokenizer(output, "\n", false);
        lines.hasMoreTokens(); ) {
      String line = lines.nextToken().trim();
      if (line.length() == 0) {
        continue;
      }
      String[] tk = line.split("\t");
      switch (tk[0].charAt(0)) {
        case 'M':
        case 'A':
          realAdded.add(VcsUtil.getFilePath(rootPath + "/" + tk[1]));
          break;
        case 'D':
          realRemoved.add(VcsUtil.getFilePathForDeletedFile(rootPath + "/" + tk[1], false));
          break;
        default:
          throw new IllegalStateException("Unexpected status: " + line);
      }
    }
    realAdded.removeAll(added);
    realRemoved.removeAll(removed);
    if (realAdded.size() != 0 || realRemoved.size() != 0) {

      final List<FilePath> files = new ArrayList<FilePath>();
      files.addAll(realAdded);
      files.addAll(realRemoved);
      final Ref<Boolean> mergeAll = new Ref<Boolean>();
      try {
        GuiUtils.runOrInvokeAndWait(
            new Runnable() {
              public void run() {
                String message =
                    GitBundle.message("commit.partial.merge.message", partialOperation.getName());
                SelectFilePathsDialog dialog =
                    new SelectFilePathsDialog(
                        project,
                        files,
                        message,
                        null,
                        "Commit All Files",
                        CommonBundle.getCancelButtonText(),
                        false);
                dialog.setTitle(GitBundle.getString("commit.partial.merge.title"));
                dialog.show();
                mergeAll.set(dialog.isOK());
              }
            });
      } catch (RuntimeException ex) {
        throw ex;
      } catch (Exception ex) {
        throw new RuntimeException("Unable to invoke a message box on AWT thread", ex);
      }
      if (!mergeAll.get()) {
        return false;
      }
      // update non-indexed files
      if (!updateIndex(project, root, realAdded, realRemoved, exceptions)) {
        return false;
      }
      for (FilePath f : realAdded) {
        VcsDirtyScopeManager.getInstance(project).fileDirty(f);
      }
      for (FilePath f : realRemoved) {
        VcsDirtyScopeManager.getInstance(project).fileDirty(f);
      }
    }
    // perform merge commit
    try {
      GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.COMMIT);
      handler.setStdoutSuppressed(false);
      handler.addParameters("-F", messageFile.getAbsolutePath());
      if (author != null) {
        handler.addParameters("--author=" + author);
      }
      handler.endOptions();
      handler.run();
      GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
      manager.updateRepository(root);
    } catch (VcsException ex) {
      exceptions.add(ex);
      return false;
    }
    return true;
  }
 @NotNull
 private GitRepository getRepository(@NotNull FilePath path) {
   GitRepository repository = myRepositoryManager.getRepositoryForFile(path);
   LOG.assertTrue(repository != null, "Repository is null for " + path);
   return repository;
 }