public ShelvedChangeList shelveChanges(
      final Collection<Change> changes, final String commitMessage, final boolean rollback)
      throws IOException, VcsException {
    final List<Change> textChanges = new ArrayList<Change>();
    final List<ShelvedBinaryFile> binaryFiles = new ArrayList<ShelvedBinaryFile>();
    for (Change change : changes) {
      if (ChangesUtil.getFilePath(change).isDirectory()) {
        continue;
      }
      if (change.getBeforeRevision() instanceof BinaryContentRevision
          || change.getAfterRevision() instanceof BinaryContentRevision) {
        binaryFiles.add(shelveBinaryFile(change));
      } else {
        textChanges.add(change);
      }
    }

    final ShelvedChangeList changeList;
    try {
      File patchPath = getPatchPath(commitMessage);
      ProgressManager.checkCanceled();
      final List<FilePatch> patches =
          IdeaTextPatchBuilder.buildPatch(
              myProject, textChanges, myProject.getBaseDir().getPresentableUrl(), false);
      ProgressManager.checkCanceled();

      CommitContext commitContext = new CommitContext();
      baseRevisionsOfDvcsIntoContext(textChanges, commitContext);
      myFileProcessor.savePathFile(
          new CompoundShelfFileProcessor.ContentProvider() {
            public void writeContentTo(final Writer writer, CommitContext commitContext)
                throws IOException {
              UnifiedDiffWriter.write(myProject, patches, writer, "\n", commitContext);
            }
          },
          patchPath,
          commitContext);

      changeList =
          new ShelvedChangeList(
              patchPath.toString(), commitMessage.replace('\n', ' '), binaryFiles);
      myShelvedChangeLists.add(changeList);
      ProgressManager.checkCanceled();

      if (rollback) {
        new RollbackWorker(myProject, false)
            .doRollback(changes, true, null, VcsBundle.message("shelve.changes.action"));
      }
    } finally {
      notifyStateChanged();
    }

    return changeList;
  }
 private void baseRevisionsOfDvcsIntoContext(
     List<Change> textChanges, CommitContext commitContext) {
   ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
   if (vcsManager.dvcsUsedInProject()
       && VcsConfiguration.getInstance(myProject).INCLUDE_TEXT_INTO_SHELF) {
     final Set<Change> big = SelectFilesToAddTextsToPatchPanel.getBig(textChanges);
     final ArrayList<FilePath> toKeep = new ArrayList<FilePath>();
     for (Change change : textChanges) {
       if (change.getBeforeRevision() == null || change.getAfterRevision() == null) continue;
       if (big.contains(change)) continue;
       FilePath filePath = ChangesUtil.getFilePath(change);
       final AbstractVcs vcs = vcsManager.getVcsFor(filePath);
       if (vcs != null && VcsType.distibuted.equals(vcs.getType())) {
         toKeep.add(filePath);
       }
     }
     commitContext.putUserData(BaseRevisionTextPatchEP.ourPutBaseRevisionTextKey, true);
     commitContext.putUserData(BaseRevisionTextPatchEP.ourBaseRevisionPaths, toKeep);
   }
 }