@Override
 public void run(ContinuationContext context) {
   final List<Change> changesForPatch;
   try {
     final List<CommittedChangeList> lst = loadSvnChangeListsForPatch(myDescription);
     changesForPatch = CommittedChangesTreeBrowser.collectChanges(lst, true);
     for (Change change : changesForPatch) {
       if (change.getBeforeRevision() != null) {
         preloadRevisionContents(change.getBeforeRevision());
       }
       if (change.getAfterRevision() != null) {
         preloadRevisionContents(change.getAfterRevision());
       }
     }
   } catch (VcsException e) {
     context.handleException(e, true);
     return;
   }
   final List<Change> binaryChanges = filterOutBinary(changesForPatch);
   if (binaryChanges != null && !binaryChanges.isEmpty()) {
     myTheirsBinaryChanges.addAll(binaryChanges);
   }
   if (!changesForPatch.isEmpty()) {
     myTheirsChanges.addAll(changesForPatch);
   }
 }
 private List<Change> convertPaths(List<Change> changesForPatch) throws VcsException {
   initAddOption();
   final List<Change> changes = new ArrayList<Change>();
   for (Change change : changesForPatch) {
     if (!isUnderOldDir(change, myOldFilePath)) continue;
     ContentRevision before = null;
     ContentRevision after = null;
     if (change.getBeforeRevision() != null) {
       before =
           new SimpleContentRevision(
               change.getBeforeRevision().getContent(),
               rebasePath(myOldFilePath, myNewFilePath, change.getBeforeRevision().getFile()),
               change.getBeforeRevision().getRevisionNumber().asString());
     }
     if (change.getAfterRevision() != null) {
       // if addition or move - do not move to the new path
       if (myAdd
           && (change.getBeforeRevision() == null || change.isMoved() || change.isRenamed())) {
         after = change.getAfterRevision();
       } else {
         after =
             new SimpleContentRevision(
                 change.getAfterRevision().getContent(),
                 rebasePath(myOldFilePath, myNewFilePath, change.getAfterRevision().getFile()),
                 change.getAfterRevision().getRevisionNumber().asString());
       }
     }
     changes.add(new Change(before, after));
   }
   return changes;
 }
 public LocalChangeList getListCopy(@NotNull final VirtualFile file) {
   for (LocalChangeList list : myMap.values()) {
     for (Change change : list.getChanges()) {
       if (change.getAfterRevision() != null
           && Comparing.equal(change.getAfterRevision().getFile().getVirtualFile(), file)) {
         return list.copy();
       }
       if (change.getBeforeRevision() != null
           && Comparing.equal(change.getBeforeRevision().getFile().getVirtualFile(), file)) {
         return list.copy();
       }
     }
   }
   return null;
 }
 /**
  * Sort changes by roots
  *
  * @param changes a change list
  * @param exceptions exceptions to collect
  * @return sorted changes
  */
 private static Map<VirtualFile, Collection<Change>> sortChangesByGitRoot(
     @NotNull List<Change> changes, List<VcsException> exceptions) {
   Map<VirtualFile, Collection<Change>> result = new HashMap<VirtualFile, Collection<Change>>();
   for (Change change : changes) {
     final ContentRevision afterRevision = change.getAfterRevision();
     final ContentRevision beforeRevision = change.getBeforeRevision();
     // nothing-to-nothing change cannot happen.
     assert beforeRevision != null || afterRevision != null;
     // note that any path will work, because changes could happen within single vcs root
     final FilePath filePath =
         afterRevision != null ? afterRevision.getFile() : beforeRevision.getFile();
     final VirtualFile vcsRoot;
     try {
       // the parent paths for calculating roots in order to account for submodules that contribute
       // to the parent change. The path "." is never is valid change, so there should be no
       // problem
       // with it.
       vcsRoot = GitUtil.getGitRoot(filePath.getParentPath());
     } catch (VcsException e) {
       exceptions.add(e);
       continue;
     }
     Collection<Change> changeList = result.get(vcsRoot);
     if (changeList == null) {
       changeList = new ArrayList<Change>();
       result.put(vcsRoot, changeList);
     }
     changeList.add(change);
   }
   return result;
 }
 public void processChangeLists(final List<LocalChangeList> lists) {
   final ProjectLevelVcsManager plVcsManager =
       ProjectLevelVcsManager.getInstanceChecked(myProject);
   plVcsManager.startBackgroundVcsOperation();
   try {
     final SVNChangelistClient client = createChangelistClient();
     for (LocalChangeList list : lists) {
       if (!list.isDefault()) {
         final Collection<Change> changes = list.getChanges();
         for (Change change : changes) {
           correctListForRevision(
               plVcsManager, change.getBeforeRevision(), client, list.getName());
           correctListForRevision(plVcsManager, change.getAfterRevision(), client, list.getName());
         }
       }
     }
   } finally {
     final Application appManager = ApplicationManager.getApplication();
     if (appManager.isDispatchThread()) {
       appManager.executeOnPooledThread(
           new Runnable() {
             @Override
             public void run() {
               plVcsManager.stopBackgroundVcsOperation();
             }
           });
     } else {
       plVcsManager.stopBackgroundVcsOperation();
     }
   }
 }
  public static boolean isBinaryChange(Change change) {
    if (change.hasOtherLayers()) return false; // +-
    final ContentRevision bRev = change.getBeforeRevision();
    final ContentRevision aRev = change.getAfterRevision();

    return (aRev == null || aRev instanceof BinaryContentRevision)
        && (bRev == null || bRev instanceof BinaryContentRevision);
  }
 private void correctScopeForMoves(
     final VcsModifiableDirtyScope scope, final Collection<Change> changes) {
   if (scope == null) return;
   for (Change change : changes) {
     if (change.isMoved() || change.isRenamed()) {
       scope.addDirtyFile(change.getBeforeRevision().getFile());
       scope.addDirtyFile(change.getAfterRevision().getFile());
     }
   }
 }
 private boolean isUnderOldDir(Change change, FilePath path) {
   if (change.getBeforeRevision() != null) {
     final boolean isUnder =
         FileUtil.isAncestor(
             path.getIOFile(), change.getBeforeRevision().getFile().getIOFile(), true);
     if (isUnder) {
       return true;
     }
   }
   if (change.getAfterRevision() != null) {
     final boolean isUnder =
         FileUtil.isAncestor(
             path.getIOFile(), change.getAfterRevision().getFile().getIOFile(), true);
     if (isUnder) {
       return isUnder;
     }
   }
   return false;
 }
Beispiel #9
0
    @Nullable
    private Intersection checkIntersection(
        @Nullable final List<CommittedChangeList> lists, List<LocalChangeList> localChangeLists) {
      if (lists == null || lists.isEmpty()) {
        return null;
      }
      final Set<FilePath> mergePaths = new HashSet<FilePath>();
      for (CommittedChangeList list : lists) {
        final SvnChangeList svnList = (SvnChangeList) list;
        final List<String> paths = new ArrayList<String>(svnList.getAddedPaths());
        paths.addAll(svnList.getChangedPaths());
        paths.addAll(svnList.getDeletedPaths());
        for (String path : paths) {
          final File localPath = getLocalPath(path);
          if (localPath != null) {
            mergePaths.add(new FilePathImpl(localPath, false));
          }
        }
      }

      final Intersection intersection = new Intersection();
      for (LocalChangeList localChangeList : localChangeLists) {
        final Collection<Change> localChanges = localChangeList.getChanges();

        for (Change localChange : localChanges) {
          final FilePath before =
              localChange.getBeforeRevision() == null
                  ? null
                  : localChange.getBeforeRevision().getFile();
          final FilePath after =
              localChange.getAfterRevision() == null
                  ? null
                  : localChange.getAfterRevision().getFile();

          if ((before != null && mergePaths.contains(before))
              || (after != null && mergePaths.contains(after))) {
            intersection.add(localChangeList.getName(), localChangeList.getComment(), localChange);
          }
        }
      }
      return intersection;
    }
 public static BeforeAfter<DiffContent> createBinaryDiffContents(
     final Project project, final Change change) throws VcsException {
   final FilePath filePath = ChangesUtil.getFilePath(change);
   try {
     return new BeforeAfter<DiffContent>(
         createBinaryFileContent(project, change.getBeforeRevision(), filePath.getName()),
         createBinaryFileContent(project, change.getAfterRevision(), filePath.getName()));
   } catch (IOException e) {
     throw new VcsException(e);
   }
 }
  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 static SimpleDiffRequest createBinaryDiffRequest(
     final Project project, final Change change) throws VcsException {
   final FilePath filePath = ChangesUtil.getFilePath(change);
   final SimpleDiffRequest request = new SimpleDiffRequest(project, filePath.getPath());
   try {
     request.setContents(
         createBinaryFileContent(project, change.getBeforeRevision(), filePath.getName()),
         createBinaryFileContent(project, change.getAfterRevision(), filePath.getName()));
     return request;
   } catch (IOException e) {
     throw new VcsException(e);
   }
 }
 private File[] getSelectedIoFiles() {
   final List<Change> changes = getSelectedChanges();
   final List<File> files = new ArrayList<>();
   for (Change change : changes) {
     final ContentRevision afterRevision = change.getAfterRevision();
     if (afterRevision != null) {
       final FilePath file = afterRevision.getFile();
       final File ioFile = file.getIOFile();
       files.add(ioFile);
     }
   }
   return files.toArray(new File[files.size()]);
 }
 private boolean checkIfThereAreFakeRevisions(final Project project, final Change[] changes) {
   boolean needsConvertion = false;
   for (Change change : changes) {
     final ContentRevision beforeRevision = change.getBeforeRevision();
     final ContentRevision afterRevision = change.getAfterRevision();
     if (beforeRevision instanceof FakeRevision) {
       VcsDirtyScopeManager.getInstance(project).fileDirty(beforeRevision.getFile());
       needsConvertion = true;
     }
     if (afterRevision instanceof FakeRevision) {
       VcsDirtyScopeManager.getInstance(project).fileDirty(afterRevision.getFile());
       needsConvertion = true;
     }
   }
   return needsConvertion;
 }
 @Nullable
 public Change getChangeForPath(final FilePath file) {
   for (LocalChangeList list : myMap.values()) {
     for (Change change : list.getChanges()) {
       final ContentRevision afterRevision = change.getAfterRevision();
       if (afterRevision != null && afterRevision.getFile().equals(file)) {
         return change;
       }
       final ContentRevision beforeRevision = change.getBeforeRevision();
       if (beforeRevision != null && beforeRevision.getFile().equals(file)) {
         return change;
       }
     }
   }
   return null;
 }
  protected VirtualFile[] getSelectedFiles() {
    final Change[] changes = getSelectedChanges();
    Collection<VirtualFile> files = new HashSet<VirtualFile>();
    for (Change change : changes) {
      final ContentRevision afterRevision = change.getAfterRevision();
      if (afterRevision != null) {
        final VirtualFile file = afterRevision.getFile().getVirtualFile();
        if (file != null && file.isValid()) {
          files.add(file);
        }
      }
    }

    files.addAll(getSelectedVirtualFiles(null));

    return VfsUtilCore.toVirtualFileArray(files);
  }
  public MergeFromTheirsResolver(
      SvnVcs vcs, TreeConflictDescription description, Change change, SvnRevisionNumber revision) {
    myVcs = vcs;
    myDescription = description;
    myChange = change;
    myCommittedRevision = revision;
    myOldFilePath = myChange.getBeforeRevision().getFile();
    myNewFilePath = myChange.getAfterRevision().getFile();
    myBaseForPatch = ChangesUtil.findValidParentAccurately(myNewFilePath);
    myOldPresentation = TreeConflictRefreshablePanel.filePath(myOldFilePath);
    myNewPresentation = TreeConflictRefreshablePanel.filePath(myNewFilePath);

    myTheirsChanges = new ArrayList<Change>();
    myTheirsBinaryChanges = new ArrayList<Change>();
    myWarnings = new ArrayList<VcsException>();
    myTextPatches = Collections.emptyList();
  }
  public void removeRegisteredChangeFor(FilePath path) {
    myIdx.remove(path);

    for (LocalChangeList list : myMap.values()) {
      for (Change change : list.getChanges()) {
        final ContentRevision afterRevision = change.getAfterRevision();
        if (afterRevision != null && afterRevision.getFile().equals(path)) {
          ((LocalChangeListImpl) list).removeChange(change);
          return;
        }
        final ContentRevision beforeRevision = change.getBeforeRevision();
        if (beforeRevision != null && beforeRevision.getFile().equals(path)) {
          ((LocalChangeListImpl) list).removeChange(change);
          return;
        }
      }
    }
  }
  @NotNull
  public Collection<Change> getChangesIn(final FilePath dirPath) {
    List<Change> changes = new ArrayList<Change>();
    for (ChangeList list : myMap.values()) {
      for (Change change : list.getChanges()) {
        final ContentRevision afterRevision = change.getAfterRevision();
        if (afterRevision != null && afterRevision.getFile().isUnder(dirPath, false)) {
          changes.add(change);
          continue;
        }

        final ContentRevision beforeRevision = change.getBeforeRevision();
        if (beforeRevision != null && beforeRevision.getFile().isUnder(dirPath, false)) {
          changes.add(change);
        }
      }
    }
    return changes;
  }
 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);
   }
 }
  private void checkForMultipleCopiesNotMove(boolean somethingChanged) {
    final MultiMap<FilePath, Pair<Change, String>> moves =
        new MultiMap<FilePath, Pair<Change, String>>() {
          @NotNull
          protected Collection<Pair<Change, String>> createCollection() {
            return new LinkedList<Pair<Change, String>>();
          }
        };

    for (LocalChangeList changeList : myMap.values()) {
      final Collection<Change> changes = changeList.getChanges();
      for (Change change : changes) {
        if (change.isMoved() || change.isRenamed()) {
          moves.putValue(
              change.getBeforeRevision().getFile(), Pair.create(change, changeList.getName()));
        }
      }
    }
    for (FilePath filePath : moves.keySet()) {
      final List<Pair<Change, String>> copies = (List<Pair<Change, String>>) moves.get(filePath);
      if (copies.size() == 1) continue;
      Collections.sort(copies, MyChangesAfterRevisionComparator.getInstance());
      for (int i = 0; i < (copies.size() - 1); i++) {
        somethingChanged = true;
        final Pair<Change, String> item = copies.get(i);
        final Change oldChange = item.getFirst();
        final Change newChange = new Change(null, oldChange.getAfterRevision());

        final LocalChangeListImpl list = (LocalChangeListImpl) myMap.get(item.getSecond());
        list.removeChange(oldChange);
        list.addChange(newChange);

        final VcsKey key = myIdx.getVcsFor(oldChange);
        myIdx.changeRemoved(oldChange);
        myIdx.changeAdded(newChange, key);
      }
    }
    if (somethingChanged) {
      FileStatusManager.getInstance(myProject).fileStatusesChanged();
    }
  }
  private ShelvedBinaryFile shelveBinaryFile(final Change change) throws IOException {
    final ContentRevision beforeRevision = change.getBeforeRevision();
    final ContentRevision afterRevision = change.getAfterRevision();
    File beforeFile = beforeRevision == null ? null : beforeRevision.getFile().getIOFile();
    File afterFile = afterRevision == null ? null : afterRevision.getFile().getIOFile();
    String shelvedPath = null;
    if (afterFile != null) {
      String shelvedName = FileUtil.getNameWithoutExtension(afterFile.getName());
      String shelvedExt = FileUtil.getExtension(afterFile.getName());
      File shelvedFile =
          FileUtil.findSequentNonexistentFile(
              myFileProcessor.getBaseIODir(), shelvedName, shelvedExt);

      myFileProcessor.saveFile(afterRevision.getFile().getIOFile(), shelvedFile);

      shelvedPath = shelvedFile.getPath();
    }
    String beforePath = ChangesUtil.getProjectRelativePath(myProject, beforeFile);
    String afterPath = ChangesUtil.getProjectRelativePath(myProject, afterFile);
    return new ShelvedBinaryFile(beforePath, afterPath, shelvedPath);
  }
 @NotNull
 public List<VirtualFile> getAffectedFiles() {
   final Set<VirtualFile> result = ContainerUtil.newLinkedHashSet();
   for (LocalChangeList list : myMap.values()) {
     for (Change change : list.getChanges()) {
       final ContentRevision before = change.getBeforeRevision();
       final ContentRevision after = change.getAfterRevision();
       if (before != null) {
         final VirtualFile file = before.getFile().getVirtualFile();
         if (file != null) {
           result.add(file);
         }
       }
       if (after != null) {
         final VirtualFile file = after.getFile().getVirtualFile();
         if (file != null) {
           result.add(file);
         }
       }
     }
   }
   return new ArrayList<VirtualFile>(result);
 }
 private static boolean checkNotifyBinaryDiff(final Change selectedChange) {
   final ContentRevision beforeRevision = selectedChange.getBeforeRevision();
   final ContentRevision afterRevision = selectedChange.getAfterRevision();
   if (beforeRevision instanceof BinaryContentRevision
       && afterRevision instanceof BinaryContentRevision) {
     try {
       byte[] beforeContent = ((BinaryContentRevision) beforeRevision).getBinaryContent();
       byte[] afterContent = ((BinaryContentRevision) afterRevision).getBinaryContent();
       if (Arrays.equals(beforeContent, afterContent)) {
         Messages.showInfoMessage(
             VcsBundle.message("message.text.binary.versions.are.identical"),
             VcsBundle.message("message.title.diff"));
       } else {
         Messages.showInfoMessage(
             VcsBundle.message("message.text.binary.versions.are.different"),
             VcsBundle.message("message.title.diff"));
       }
     } catch (VcsException e) {
       Messages.showInfoMessage(e.getMessage(), VcsBundle.message("message.title.diff"));
     }
     return true;
   }
   return false;
 }
 public static boolean isBinaryChangeAndCanShow(Project project, Change change) {
   // todo bug here would appear when there would be another diff providers for bimary revisions
   return isBinaryChange(change)
       && (change.getAfterRevision() == null
           || BinaryDiffTool.canShow(project, change.getVirtualFile()));
 }
 public List<VcsException> commit(
     @NotNull List<Change> changes,
     @NotNull String message,
     @NotNull NullableFunction<Object, Object> parametersHolder,
     Set<String> feedback) {
   List<VcsException> exceptions = new ArrayList<VcsException>();
   Map<VirtualFile, Collection<Change>> sortedChanges = sortChangesByGitRoot(changes, exceptions);
   log.assertTrue(
       !sortedChanges.isEmpty(), "Trying to commit an empty list of changes: " + changes);
   for (Map.Entry<VirtualFile, Collection<Change>> entry : sortedChanges.entrySet()) {
     final VirtualFile root = entry.getKey();
     try {
       File messageFile = createMessageFile(root, message);
       try {
         final Set<FilePath> added = new HashSet<FilePath>();
         final Set<FilePath> removed = new HashSet<FilePath>();
         for (Change change : entry.getValue()) {
           switch (change.getType()) {
             case NEW:
             case MODIFICATION:
               added.add(change.getAfterRevision().getFile());
               break;
             case DELETED:
               removed.add(change.getBeforeRevision().getFile());
               break;
             case MOVED:
               FilePath afterPath = change.getAfterRevision().getFile();
               FilePath beforePath = change.getBeforeRevision().getFile();
               added.add(afterPath);
               if (!GitFileUtils.shouldIgnoreCaseChange(
                   afterPath.getPath(), beforePath.getPath())) {
                 removed.add(beforePath);
               }
               break;
             default:
               throw new IllegalStateException("Unknown change type: " + change.getType());
           }
         }
         try {
           try {
             Set<FilePath> files = new HashSet<FilePath>();
             files.addAll(added);
             files.addAll(removed);
             commit(
                 myProject,
                 root,
                 files,
                 messageFile,
                 myNextCommitAuthor,
                 myNextCommitAmend,
                 myNextCommitAuthorDate);
           } catch (VcsException ex) {
             PartialOperation partialOperation = isMergeCommit(ex);
             if (partialOperation == PartialOperation.NONE) {
               throw ex;
             }
             if (!mergeCommit(
                 myProject,
                 root,
                 added,
                 removed,
                 messageFile,
                 myNextCommitAuthor,
                 exceptions,
                 partialOperation)) {
               throw ex;
             }
           }
         } finally {
           if (!messageFile.delete()) {
             log.warn("Failed to remove temporary file: " + messageFile);
           }
         }
       } catch (VcsException e) {
         exceptions.add(e);
       }
     } catch (IOException ex) {
       //noinspection ThrowableInstanceNeverThrown
       exceptions.add(new VcsException("Creation of commit message file failed", ex));
     }
   }
   if (myNextCommitIsPushed != null
       && myNextCommitIsPushed.booleanValue()
       && exceptions.isEmpty()) {
     // push
     UIUtil.invokeLaterIfNeeded(
         new Runnable() {
           public void run() {
             GitPusher.showPushDialogAndPerformPush(
                 myProject, ServiceManager.getService(myProject, GitPlatformFacade.class));
           }
         });
   }
   return exceptions;
 }