blob: d06c8f888ad7582c17c5ca260d06e15a894e6234 [file] [log] [blame]
/*
* Copyright 2000-2009 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.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsKey;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
class UpdatingChangeListBuilder implements ChangelistBuilder {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.UpdatingChangeListBuilder");
private final ChangeListWorker myChangeListWorker;
private final FileHolderComposite myComposite;
// todo +-
private final Getter<Boolean> myDisposedGetter;
private VcsDirtyScope myScope;
private FoldersCutDownWorker myFoldersCutDownWorker;
private final IgnoredFilesComponent myIgnoredFilesComponent;
private final ProjectLevelVcsManager myVcsManager;
private final ChangeListManagerGate myGate;
private Factory<JComponent> myAdditionalInfo;
UpdatingChangeListBuilder(final ChangeListWorker changeListWorker,
final FileHolderComposite composite,
final Getter<Boolean> disposedGetter,
final IgnoredFilesComponent ignoredFilesComponent, final ChangeListManagerGate gate) {
myChangeListWorker = changeListWorker;
myComposite = composite;
myDisposedGetter = disposedGetter;
myIgnoredFilesComponent = ignoredFilesComponent;
myGate = gate;
myVcsManager = ProjectLevelVcsManager.getInstance(changeListWorker.getProject());
}
private void checkIfDisposed() {
if (myDisposedGetter.get()) throw new ChangeListManagerImpl.DisposedException();
}
public void setCurrent(final VcsDirtyScope scope, final FoldersCutDownWorker foldersWorker) {
myScope = scope;
myFoldersCutDownWorker = foldersWorker;
}
public void processChange(final Change change, VcsKey vcsKey) {
processChangeInList(change, (ChangeList)null, vcsKey);
}
public void processChangeInList(final Change change, @Nullable final ChangeList changeList, final VcsKey vcsKey) {
checkIfDisposed();
LOG.debug("[processChangeInList-1] entering, cl name: " + ((changeList == null) ? null: changeList.getName()) +
" change: " + ChangesUtil.getFilePath(change).getPath());
final String fileName = ChangesUtil.getFilePath(change).getName();
if (FileTypeManager.getInstance().isFileIgnored(fileName)) {
LOG.debug("[processChangeInList-1] file type ignored");
return;
}
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (ChangeListManagerImpl.isUnder(change, myScope)) {
if (changeList != null) {
LOG.debug("[processChangeInList-1] to add change to cl");
myChangeListWorker.addChangeToList(changeList.getName(), change, vcsKey);
}
else {
LOG.debug("[processChangeInList-1] to add to corresponding list");
myChangeListWorker.addChangeToCorrespondingList(change, vcsKey);
}
}
else {
LOG.debug("[processChangeInList-1] not under scope");
}
}
});
}
public void processChangeInList(final Change change, final String changeListName, VcsKey vcsKey) {
checkIfDisposed();
LocalChangeList list = null;
if (changeListName != null) {
list = myChangeListWorker.getCopyByName(changeListName);
if (list == null) {
list = myGate.addChangeList(changeListName, null);
}
}
processChangeInList(change, list, vcsKey);
}
@Override
public void removeRegisteredChangeFor(FilePath path) {
myChangeListWorker.removeRegisteredChangeFor(path);
}
private boolean isIgnoredByVcs(final VirtualFile file) {
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
checkIfDisposed();
return myVcsManager.isIgnored(file);
}
});
}
public void processUnversionedFile(final VirtualFile file) {
if (LOG.isDebugEnabled()) {
LOG.debug("processUnversionedFile " + file);
}
if (file == null) return;
checkIfDisposed();
if (isIgnoredByVcs(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
if (myIgnoredFilesComponent.isIgnoredFile(file)) {
myComposite.getIgnoredFileHolder().addFile(file);
}
else if (myComposite.getIgnoredFileHolder().containsFile(file)) {
// does not need to add: parent dir is already added
}
else {
myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED).addFile(file);
}
// if a file was previously marked as switched through recursion, remove it from switched list
myChangeListWorker.removeSwitched(file);
}
}
public void processLocallyDeletedFile(final FilePath file) {
processLocallyDeletedFile(new LocallyDeletedChange(file));
}
public void processLocallyDeletedFile(LocallyDeletedChange locallyDeletedChange) {
checkIfDisposed();
final FilePath file = locallyDeletedChange.getPath();
if (FileTypeManager.getInstance().isFileIgnored(file.getName())) return;
if (myScope.belongsTo(file)) {
myChangeListWorker.addLocallyDeleted(locallyDeletedChange);
}
}
public void processModifiedWithoutCheckout(final VirtualFile file) {
if (file == null) return;
checkIfDisposed();
if (isIgnoredByVcs(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
if (LOG.isDebugEnabled()) {
LOG.debug("processModifiedWithoutCheckout " + file);
}
myComposite.getVFHolder(FileHolder.HolderType.MODIFIED_WITHOUT_EDITING).addFile(file);
}
}
public void processIgnoredFile(final VirtualFile file) {
if (file == null) return;
checkIfDisposed();
if (isIgnoredByVcs(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
IgnoredFilesHolder ignoredFilesHolder = myComposite.getIgnoredFileHolder();
if (ignoredFilesHolder instanceof IgnoredFilesCompositeHolder) {
IgnoredFilesHolder holder = ((IgnoredFilesCompositeHolder)ignoredFilesHolder).getAppropriateIgnoredHolder();
if (holder instanceof MapIgnoredFilesHolder) {
((MapIgnoredFilesHolder)holder).addByVcsChangeProvider(file);
return;
}
}
ignoredFilesHolder.addFile(file);
}
}
public void processLockedFolder(final VirtualFile file) {
if (file == null) return;
checkIfDisposed();
if (myScope.belongsTo(new FilePathImpl(file))) {
if (myFoldersCutDownWorker.addCurrent(file)) {
myComposite.getVFHolder(FileHolder.HolderType.LOCKED).addFile(file);
}
}
}
public void processLogicallyLockedFolder(VirtualFile file, LogicalLock logicalLock) {
if (file == null) return;
checkIfDisposed();
if (myScope.belongsTo(new FilePathImpl(file))) {
((LogicallyLockedHolder)myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).add(file, logicalLock);
}
}
public void processSwitchedFile(final VirtualFile file, final String branch, final boolean recursive) {
if (file == null) return;
checkIfDisposed();
if (isIgnoredByVcs(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
myChangeListWorker.addSwitched(file, branch, recursive);
}
}
public void processRootSwitch(VirtualFile file, String branch) {
if (file == null) return;
checkIfDisposed();
if (myScope.belongsTo(new FilePathImpl(file))) {
((SwitchedFileHolder)myComposite.get(FileHolder.HolderType.ROOT_SWITCH)).addFile(file, branch, false);
}
}
public boolean reportChangesOutsideProject() {
return false;
}
@Override
public void reportAdditionalInfo(String text) {
reportAdditionalInfo(ChangesViewManager.createTextStatusFactory(text, true));
}
@Override
public void reportAdditionalInfo(Factory<JComponent> infoComponent) {
if (myAdditionalInfo == null) {
myAdditionalInfo = infoComponent;
}
}
public Factory<JComponent> getAdditionalInfo() {
return myAdditionalInfo;
}
}