}
}
+ @Nullable
public static String getOrLoadAsString(Project project,
FilePath file,
VcsRevisionNumber number,
return CharsetToolkit.bytesToString(bytes, charset);
}
- private static String bytesToString(FilePath path, byte[] bytes) {
+ private static String bytesToString(FilePath path, @NotNull byte[] bytes) {
Charset charset = null;
if (path.getVirtualFile() != null) {
charset = path.getVirtualFile().getCharset();
return bytes;
}
+ @Nullable
public static String getOrLoadAsString(final Project project, FilePath path, VcsRevisionNumber number, @NotNull VcsKey vcsKey,
@NotNull UniqueType type, final Throwable2Computable<byte[], VcsException, IOException> loader)
throws VcsException, IOException {
byte[] bytes = getOrLoadAsBytes(project, path, number, vcsKey, type, loader);
+ if (bytes == null) return null;
+
return bytesToString(path, bytes);
}
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotifications;
import com.intellij.util.*;
+import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.continuation.ContinuationPause;
import com.intellij.util.messages.Topic;
}
}
});
+
+ for (VcsDirtyScope scope : scopes) {
+ updateLastUnchangedContents(scope);
+ }
+
myChangesViewManager.scheduleRefresh();
}
catch (DisposedException e) {
}
}
+ private void updateLastUnchangedContents(VcsDirtyScope scope) {
+ scope.iterateExistingInsideScope(new Processor<VirtualFile>() {
+ @Override
+ public boolean process(VirtualFile file) {
+ if (!file.isDirectory() && getStatus(file) == FileStatus.NOT_CHANGED) {
+ LastUnchangedContentTracker.updateLastUnchangedContent(file);
+ }
+
+ return true;
+ }
+ });
+ }
+
+ public void collectUnchangedFileContents(@Nullable ProgressIndicator indicator) {
+ final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
+ for (VcsDirectoryMapping mapping : vcsManager.getDirectoryMappings()) {
+ final AbstractVcs vcs = vcsManager.findVcsByName(mapping.getVcs());
+ final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(mapping.getDirectory());
+ if (vcs != null && file != null) {
+ if (indicator != null) {
+ indicator.setText(mapping.getDirectory());
+ }
+
+ final VcsDirtyScopeImpl scope = new VcsDirtyScopeImpl(vcs, myProject);
+ scope.addDirtyDirRecursively(new FilePathImpl(file));
+ updateLastUnchangedContents(scope);
+ }
+ }
+
+ for (LocalChangeList list : getChangeListsCopy()) {
+ for (Change change : list.getChanges()) {
+ final VirtualFile file = change.getVirtualFile();
+ final ContentRevision before = change.getBeforeRevision();
+ if (file != null && before != null && !LastUnchangedContentTracker.hasSavedContent(file)) {
+ try {
+ final String content = before.getContent();
+ if (content != null) {
+ LastUnchangedContentTracker.forceSavedContent(file, content);
+ }
+ }
+ catch (VcsException e) {
+ LOG.info(e);
+ }
+ }
+
+ }
+ }
+ }
+
private void checkIfDisposed() {
if (myUpdater.isStopped()) throw new DisposedException();
}
@TestOnly
public void waitUntilRefreshed() {
myUpdater.waitUntilRefreshed();
+ waitUpdateAlarm();
+ }
+
+ // this is for perforce tests to ensure that LastSuccessfulUpdateTracker receives the event it needs
+ private static void waitUpdateAlarm() {
+ final Semaphore semaphore = new Semaphore();
+ semaphore.down();
+ ourUpdateAlarm.execute(new Runnable() {
+ @Override
+ public void run() {
+ semaphore.up();
+ }
+ });
+ semaphore.waitFor();
}
/**
final EnsureUpToDateFromNonAWTThread worker = new EnsureUpToDateFromNonAWTThread(myProject);
worker.execute();
myUpdater.waitUntilRefreshed();
+ waitUpdateAlarm();
return worker.isDone();
}
}
public void onAfterWorkerSwitch(@NotNull final ChangeListWorker previous) {
- final boolean somethingChanged = myDelta.step(previous.myIdx, myIdx);
- checkForMultipleCopiesNotMove();
+ checkForMultipleCopiesNotMove(myDelta.step(previous.myIdx, myIdx));
}
- public boolean takeData(@NotNull final ChangeListWorker worker) {
- myMap.clear();
- myMap.putAll(worker.myMap);
- myDefault = worker.myDefault;
-
- myListsToDisappear.clear();
- myListsToDisappear.addAll(worker.myListsToDisappear);
-
- final boolean somethingChanged = myDelta.step(myIdx, worker.myIdx);
- myIdx = new ChangeListsIndexes(worker.myIdx);
- checkForMultipleCopiesNotMove();
-
- myLocallyDeleted.takeFrom(worker.myLocallyDeleted);
- mySwitchedHolder.takeFrom(worker.mySwitchedHolder);
-
- return somethingChanged;
- }
-
- private void checkForMultipleCopiesNotMove() {
+ private void checkForMultipleCopiesNotMove(boolean somethingChanged) {
final MultiMap<FilePath, Pair<Change, String>> moves = new MultiMap<FilePath, Pair<Change, String>>() {
protected Collection<Pair<Change, String>> createCollection() {
return new LinkedList<Pair<Change, String>>();
}
}
}
- boolean somethingChanged = false;
for (FilePath filePath : moves.keySet()) {
final List<Pair<Change, String>> copies = (List<Pair<Change, String>>) moves.get(filePath);
if (copies.size() == 1) continue;
--- /dev/null
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.vcs.changes;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.newvfs.FileAttribute;
+import com.intellij.openapi.vfs.newvfs.ManagingFS;
+import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * @author peter
+ */
+public class LastUnchangedContentTracker {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.LastUnchangedContentTracker");
+ private static final Key<Long> LAST_TS_KEY = Key.create("LAST_TS_KEY");
+ private static final FileAttribute LAST_TS_ATTR = new FileAttribute("LAST_TS_ATTR", 0, true);
+ private static final FileAttribute ACQUIRED_CONTENT_ATTR = new FileAttribute("ACQUIRED_CONTENT_ATTR", 0, false);
+
+ public static void updateLastUnchangedContent(@NotNull VirtualFile file) {
+ Long lastTs = getLastSavedStamp(file);
+ final long stamp = file.getModificationStamp();
+ if (lastTs != null && stamp == lastTs) {
+ return;
+ }
+
+ Integer oldContentId = getSavedContentId(file);
+ if (oldContentId != null) {
+ getFS().releaseContent(oldContentId);
+ }
+
+ saveContentReference(file, getFS().acquireContent(file));
+ }
+
+ @Nullable
+ public static byte[] getLastUnchangedContent(@NotNull VirtualFile file) {
+ final Integer id = getSavedContentId(file);
+ try {
+ return id == null ? null : getFS().contentsToByteArray(id);
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ return null;
+ }
+
+ private static PersistentFS getFS() {
+ return (PersistentFS)ManagingFS.getInstance();
+ }
+
+ private static void saveContentReference(VirtualFile file, int contentId) {
+ if (ChangeListManagerImpl.DEBUG) {
+ System.out.println("LastUnchangedContentTracker.saveCurrentContent");
+ try {
+ System.out.println("content = " + VfsUtil.loadText(file));
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ long stamp = file.getModificationStamp();
+ try {
+ final DataOutputStream contentStream = ACQUIRED_CONTENT_ATTR.writeAttribute(file);
+ contentStream.writeInt(contentId);
+ contentStream.close();
+
+ final DataOutputStream tsStream = LAST_TS_ATTR.writeAttribute(file);
+ tsStream.writeLong(stamp);
+ tsStream.close();
+
+ file.putUserData(LAST_TS_KEY, stamp);
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ }
+
+ public static boolean hasSavedContent(VirtualFile file) {
+ return getSavedContentId(file) != null;
+ }
+
+ public static void forceSavedContent(VirtualFile file, @NotNull String content) {
+ saveContentReference(file, getFS().storeUnlinkedContent(content.getBytes(file.getCharset())));
+ }
+
+ @Nullable
+ private static Integer getSavedContentId(VirtualFile file) {
+ Integer oldContentId = null;
+ try {
+ final DataInputStream stream = ACQUIRED_CONTENT_ATTR.readAttribute(file);
+ if (stream != null) {
+ oldContentId = stream.readInt();
+ stream.close();
+ }
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ return oldContentId;
+ }
+
+ @Nullable
+ private static Long getLastSavedStamp(VirtualFile file) {
+ Long l = file.getUserData(LAST_TS_KEY);
+ if (l == null) {
+ try {
+ final DataInputStream stream = LAST_TS_ATTR.readAttribute(file);
+ if (stream != null) {
+ l = stream.readLong();
+ stream.close();
+ }
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ }
+ return l;
+ }
+}