P4ChangeProvider implements ChangeProvider { @Override public void getChanges(@NotNull VcsDirtyScope dirtyScope, @NotNull ChangelistBuilder builder, @NotNull ProgressIndicator progress, @NotNull ChangeListManagerGate addGate) throws VcsException { if (project.isDisposed()) { return; } if (dirtyScope.getVcs() != vcs) { throw new VcsException(P4Bundle.message("error.vcs.dirty-scope.wrong")); } if (active) { LOG.warn("Second call into already active getChanges. Ignoring call."); LOG.warn("Original active thread", activeThread); LOG.warn("Current thread", new Exception()); return; } try { active = true; activeThread = new Exception(); double lastFraction = 0.0; progress.setFraction(lastFraction); Collection<ClientConfigRoot> allClientRoots = getClientConfigRoots(); Pair<IdeChangelistMap, IdeFileMap> cachedMaps = CacheComponent.getInstance(project) .blockingRefreshServerOpenedCache( allClientRoots, UserProjectPreferences.getLockWaitTimeoutMillis(project), TimeUnit.MILLISECONDS ); if (cachedMaps.first == null || cachedMaps.second == null) { progress.setFraction(1.0); return; } lastFraction = 0.6; progress.setFraction(lastFraction); try { updateChangelists(cachedMaps.first, addGate) .blockingGet(UserProjectPreferences.getLockWaitTimeoutMillis(project), TimeUnit.MILLISECONDS); } catch (InterruptedException e) { InternalErrorMessage.send(project).cacheLockTimeoutError(new ErrorEvent<>( new VcsInterruptedException("Update Changelists interrupted", e))); progress.setFraction(1.0); return; } if (dirtyScope.wasEveryThingDirty()) { double fractionRootIncr = (1.0 - lastFraction) / allClientRoots.size(); for (ClientConfigRoot root : allClientRoots) { LOG.info("Processing changes in " + root.getProjectVcsRootDir()); updateFileCache(root.getClientConfig(), cachedMaps.first, cachedMaps.second, builder); lastFraction += fractionRootIncr; progress.setFraction(lastFraction); } } else { final Set<FilePath> dirtyFiles = dirtyScope.getDirtyFiles(); if (dirtyFiles == null || dirtyFiles.isEmpty()) { LOG.info("No dirty files."); progress.setFraction(1.0); return; } if (LOG.isDebugEnabled()) { LOG.debug("Processing dirty files " + dirtyFiles); } Map<VcsRoot, List<FilePath>> fileRoots = VcsUtil.groupByRoots(project, dirtyFiles, (f) -> f); if (!fileRoots.isEmpty()) { double fractionRootIncr = (1.0 - lastFraction) / fileRoots.size(); for (Map.Entry<VcsRoot, List<FilePath>> entry : fileRoots.entrySet()) { if (entry.getKey().getVcs() != null && P4Vcs.getKey().equals(entry.getKey().getVcs().getKeyInstanceMethod())) { VirtualFile root = entry.getKey().getPath(); ClientConfigRoot config = getClientFor(root); Set<FilePath> matched = getMatchedDirtyRootFiles(dirtyFiles, config, root, entry.getValue()); if (!matched.isEmpty() && config != null) { updateFileCache(config.getClientConfig(), matched, cachedMaps.first, cachedMaps.second, builder); } } lastFraction += fractionRootIncr; progress.setFraction(lastFraction); } } markIgnored(dirtyFiles, builder); } progress.setFraction(1.0); } finally { active = false; activeThread = null; } } P4ChangeProvider(@NotNull P4Vcs vcs, @NotNull Disposable parentDisposable); @Override boolean isModifiedDocumentTrackingRequired(); @Override void doCleanup(List<VirtualFile> files); @Override void getChanges(@NotNull VcsDirtyScope dirtyScope,
            @NotNull ChangelistBuilder builder,
            @NotNull ProgressIndicator progress,
            @NotNull ChangeListManagerGate addGate);  }
@ExtendWith(TemporaryFolderExtension.class) @Test void offlineOneChange(TemporaryFolder tmp) throws IOException, VcsException { List<Throwable> errors = new ArrayList<>(); vcs.idea.useInlineThreading(errors); VcsDirtyScope dirtyScope = mock(VcsDirtyScope.class); MockChangeListManagerGate addGate = new MockChangeListManagerGate(vcs.getMockChangelistManager()); MockChangelistBuilder changeBuilder = new MockChangelistBuilder(addGate, vcs.vcs); ProgressIndicator progressIndicator = DummyProgressIndicator.nullSafe(null); when(dirtyScope.getVcs()).thenReturn(vcs.vcs); when(dirtyScope.wasEveryThingDirty()).thenReturn(true); ClientConfigRoot root = vcs.addClientConfigRoot(tmp, "client"); assertNotNull(root.getClientRootDir()); vcs.goOffline(root); assertFalse(vcs.registry.isOnline(root.getClientConfig().getClientServerRef())); P4ChangelistId defaultChangeId = vcs.addDefaultChangelist(root); VirtualFile addedVirtualFile = root.getClientRootDir().createChildData(this, "added.txt"); FilePath addedFile = VcsUtil.getFilePath(addedVirtualFile); vcs.server.getCommandRunner() .perform(root.getClientConfig(), new AddEditAction(addedFile, null, defaultChangeId, root.getClientConfig().getCharSetName())); assertSize(0, errors); assertNotNull(vcs.cacheComponent.getState()); assertSize(1, vcs.cacheComponent.getState().pendingActions); assertEquals(ADD_EDIT_FILE, vcs.cacheComponent.getState().pendingActions.get(0).clientActionCmd); P4ChangeProvider provider = new P4ChangeProvider(vcs.vcs, vcs.getMockProject()); provider.getChanges(dirtyScope, changeBuilder, progressIndicator, addGate); assertContainsExactly(changeBuilder.addedChangedFiles.values(), addedFile); assertSize(1, changeBuilder.addedChanges.keySet()); Map.Entry<String, Change> change = changeBuilder.addedChanges.entrySet().iterator().next(); assertEquals(LocalChangeList.DEFAULT_NAME, change.getKey()); assertNull(change.getValue().getBeforeRevision()); assertNotNull(change.getValue().getAfterRevision()); assertEquals(addedFile, change.getValue().getAfterRevision().getFile()); assertSize(0, changeBuilder.ignored); assertSize(0, changeBuilder.locallyDeleted); assertSize(0, changeBuilder.lockedFolder); assertSize(0, changeBuilder.modifiedWithoutCheckout); assertSize(0, changeBuilder.removedChanges); assertSize(0, changeBuilder.unversioned); assertSize(0, addGate.removed); assertSize(0, addGate.added); }
@ExtendWith(TemporaryFolderExtension.class) @Test void offlineNewIdeChangelist(TemporaryFolder tmp) throws IOException, VcsException { List<Throwable> errors = new ArrayList<>(); vcs.idea.useInlineThreading(errors); VcsDirtyScope dirtyScope = mock(VcsDirtyScope.class); MockChangeListManagerGate addGate = new MockChangeListManagerGate(vcs.getMockChangelistManager()); MockChangelistBuilder changeBuilder = new MockChangelistBuilder(addGate, vcs.vcs); ProgressIndicator progressIndicator = DummyProgressIndicator.nullSafe(null); when(dirtyScope.getVcs()).thenReturn(vcs.vcs); when(dirtyScope.wasEveryThingDirty()).thenReturn(true); ClientConfigRoot root = vcs.addClientConfigRoot(tmp, "client"); assertNotNull(root.getClientRootDir()); vcs.goOffline(root); assertFalse(vcs.registry.isOnline(root.getClientConfig().getClientServerRef())); P4ChangelistId defaultChangeId = vcs.addDefaultChangelist(root); vcs.addIdeChangelist("Test change", "A test change", false); P4ChangeProvider provider = new P4ChangeProvider(vcs.vcs, vcs.getMockProject()); provider.getChanges(dirtyScope, changeBuilder, progressIndicator, addGate); assertSize(0, changeBuilder.addedChangedFiles.values()); assertSize(0, changeBuilder.addedChanges.keySet()); assertSize(0, changeBuilder.ignored); assertSize(0, changeBuilder.locallyDeleted); assertSize(0, changeBuilder.lockedFolder); assertSize(0, changeBuilder.modifiedWithoutCheckout); assertSize(0, changeBuilder.removedChanges); assertSize(0, changeBuilder.unversioned); assertSize(0, addGate.removed); assertSize(0, addGate.added); }
@ExtendWith({ TemporaryFolderExtension.class, ErrorCollectorExtension.class }) @Test void refreshAfterFileMoved(TemporaryFolder tmp, Errors errors) throws InterruptedException, IOException, VcsException { vcs.idea.useInlineThreading(errors.get()); final VcsDirtyScope dirtyScope = mock(VcsDirtyScope.class); final MockChangeListManagerGate addGate = new MockChangeListManagerGate(vcs.getMockChangelistManager()); final MockChangelistBuilder changeBuilder = new MockChangelistBuilder(addGate, vcs.vcs); final ProgressIndicator progressIndicator = DummyProgressIndicator.nullSafe(null); when(dirtyScope.getVcs()).thenReturn(vcs.vcs); when(dirtyScope.wasEveryThingDirty()).thenReturn(true); ClientConfigRoot root = vcs.addClientConfigRoot(tmp, "client"); assertNotNull(root.getClientRootDir()); vcs.goOnline(root); MockLocalChangeList ideDefaultCl = vcs.addIdeChangelist(LocalChangeList.DEFAULT_NAME, null, true); final File openedFile = tmp.newFile("test.txt"); final IFileSpec openedFileSpec = FileSpecBuildUtil.forFiles(openedFile).get(0); final Changelist secondCl = new Changelist( 2, root.getClientConfig().getClientname(), root.getClientConfig().getServerConfig().getUsername(), ChangelistStatus.PENDING, new Date(), "new cl", false, null ); secondCl.setFileSpecs(Collections.emptyList()); vcs.connectionManager .withErrors(errors) .withServerSetup((config, base) -> { secondCl.setServerImpl(base); when(base.getChangelists(eq(null), any())).thenReturn(Arrays.asList( secondCl )); when(base.getChangelist(eq(2), any())).thenReturn(secondCl); ExtendedFileSpec spec = new ExtendedFileSpec(" spec.setAction(FileAction.ADD); when(base.getExtendedFiles( argThat(t -> t.size() == 1 && t.get(0) .getOriginalPathString().equals(" argThat(t -> t.getAffectedByChangelist() == 0))).thenReturn(Collections.singletonList( spec )); return base; }) .withClientSetup((config, base) -> { when(base.openedFiles(any(), any())).then((args) -> { return args.getArguments()[0]; }); return base; }); P4ChangeProvider provider = new P4ChangeProvider(vcs.vcs, vcs.getMockProject()); provider.getChanges(dirtyScope, changeBuilder, progressIndicator, addGate); assertSize(1, changeBuilder.addedChangedFiles.values()); assertSize(1, changeBuilder.addedChanges.keySet()); assertSize(0, changeBuilder.ignored); assertSize(0, changeBuilder.locallyDeleted); assertSize(0, changeBuilder.lockedFolder); assertSize(0, changeBuilder.modifiedWithoutCheckout); assertSize(0, changeBuilder.removedChanges); assertSize(0, changeBuilder.unversioned); assertSize(0, addGate.removed); assertSize(1, addGate.added); }