The option "Inspect dirty state of children..." controls if the decoration process should look at child resources to decide if a container is dirty or not. For large/deep projects this can be quite time consuming. The other option, "Also re-decorate ancestors..." controls if parents of a re-decorated resource also should be updated, for example to signal that the containing folder is now dirty. Signed-off-by: Tor Arne Vestbø <torarnv@xxxxxxxxx> --- org.spearce.egit.ui/.options | 8 +- .../src/org/spearce/egit/ui/Activator.java | 2 +- .../egit/ui/PluginPreferenceInitializer.java | 3 +- .../src/org/spearce/egit/ui/UIPreferences.java | 4 +- .../src/org/spearce/egit/ui/UIText.java | 5 +- .../decorators/GitLightweightDecorator.java | 344 +++++++++++++++----- .../preferences/GitDecoratorPreferencePage.java | 33 ++- .../src/org/spearce/egit/ui/uitext.properties | 3 +- 8 files changed, 311 insertions(+), 91 deletions(-) diff --git a/org.spearce.egit.ui/.options b/org.spearce.egit.ui/.options index a084b35..8fc1c19 100644 --- a/org.spearce.egit.ui/.options +++ b/org.spearce.egit.ui/.options @@ -1 +1,7 @@ -org.spearce.egit.ui/trace/verbose = false +# Debugging options for the org.spearce.egit.ui plugin. + +# Show general verbose output +org.spearce.egit.ui/verbose = false + +# Show debug output for label decorations +org.spearce.egit.ui/decorations = false \ No newline at end of file diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java index 9d03c70..45010ce 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java @@ -190,7 +190,7 @@ public Activator() { public void start(final BundleContext context) throws Exception { super.start(context); - traceVerbose = isOptionSet("/trace/verbose"); + traceVerbose = isOptionSet("/verbose"); setupSSH(context); setupProxy(context); setupRepoChangeScanner(); diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/PluginPreferenceInitializer.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/PluginPreferenceInitializer.java index ef886cf..9af35bc 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/PluginPreferenceInitializer.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/PluginPreferenceInitializer.java @@ -35,7 +35,8 @@ public void initializeDefaultPreferences() { prefs.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_REV_COMMENT, true); prefs.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_TOOLTIPS, false); - prefs.setDefault(UIPreferences.DECORATOR_CALCULATE_DIRTY, true); + prefs.setDefault(UIPreferences.DECORATOR_RECOMPUTE_ANCESTORS, true); + prefs.setDefault(UIPreferences.DECORATOR_COMPUTE_DEEP_DIRTY, true); prefs.setDefault(UIPreferences.DECORATOR_FILETEXT_DECORATION, UIText.DecoratorPreferencesPage_fileFormatDefault); prefs.setDefault(UIPreferences.DECORATOR_FOLDERTEXT_DECORATION, diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIPreferences.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIPreferences.java index 409b335..f0a5e28 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIPreferences.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIPreferences.java @@ -53,7 +53,9 @@ public final static String THEME_CommitMessageFont = "org.spearce.egit.ui.CommitMessageFont"; /** */ - public final static String DECORATOR_CALCULATE_DIRTY = "decorator_calculate_dirty"; + public final static String DECORATOR_RECOMPUTE_ANCESTORS = "decorator_recompute_ancestors"; + /** */ + public final static String DECORATOR_COMPUTE_DEEP_DIRTY = "decorator_compute_deep_dirty"; /** */ public final static String DECORATOR_FILETEXT_DECORATION = "decorator_filetext_decoration"; /** */ diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java index b62ca4c..5dd28df 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java @@ -920,7 +920,10 @@ public static String DecoratorPreferencesPage_addVariablesAction; /** */ - public static String DecoratorPreferencesPage_computeDeep; + public static String DecoratorPreferencesPage_recomputeAncestorDecorations; + + /** */ + public static String DecoratorPreferencesPage_computeDeepDirtyState; /** */ public static String DecoratorPreferencesPage_description; diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitLightweightDecorator.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitLightweightDecorator.java index 45b9f83..c72bfdb 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitLightweightDecorator.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitLightweightDecorator.java @@ -31,6 +31,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.IPropertyChangeListener; @@ -48,6 +49,7 @@ import org.eclipse.team.ui.TeamUI; import org.eclipse.ui.IContributorResourceAdapter; import org.eclipse.ui.PlatformUI; +import org.spearce.egit.core.ContainerTreeIterator; import org.spearce.egit.core.GitException; import org.spearce.egit.core.internal.util.ExceptionCollector; import org.spearce.egit.core.project.GitProjectData; @@ -61,6 +63,8 @@ import org.spearce.jgit.dircache.DirCache; import org.spearce.jgit.dircache.DirCacheEntry; import org.spearce.jgit.dircache.DirCacheIterator; +import org.spearce.jgit.errors.IncorrectObjectTypeException; +import org.spearce.jgit.errors.MissingObjectException; import org.spearce.jgit.lib.Constants; import org.spearce.jgit.lib.FileMode; import org.spearce.jgit.lib.IndexChangedEvent; @@ -72,7 +76,11 @@ import org.spearce.jgit.revwalk.RevWalk; import org.spearce.jgit.treewalk.EmptyTreeIterator; import org.spearce.jgit.treewalk.TreeWalk; +import org.spearce.jgit.treewalk.WorkingTreeIterator; +import org.spearce.jgit.treewalk.filter.AndTreeFilter; import org.spearce.jgit.treewalk.filter.PathFilterGroup; +import org.spearce.jgit.treewalk.filter.TreeFilter; +import org.spearce.jgit.util.FS; /** * Supplies annotations for displayed resources @@ -110,6 +118,34 @@ IStatus.ERROR, Activator.getDefault().getLog()); /** + * Property constant indicating if tracing/debugging of decorations is + * enabled + */ + private static boolean DEBUG_DECORATIONS = false; + + static { + DEBUG_DECORATIONS = "true".equals(Platform.getDebugOption(Activator.getPluginId() + "/decorations")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + private static void debug(String what) { + StackTraceElement frame = Thread.currentThread().getStackTrace()[2]; + if (frame.getMethodName().endsWith("access$1")) + frame = Thread.currentThread().getStackTrace()[3]; + String className = frame.getClassName().substring( + frame.getClassName().lastIndexOf('.') + 1); + System.out.print(className + "::" + frame.getMethodName() + "(): "); + + debug(what, 0); + } + + private static void debug(String what, int numIndents) { + for (int i = 0; i < numIndents; ++i) + System.out.print("\t"); + + System.out.println(what); + } + + /** * Constructs a new Git resource decorator */ public GitLightweightDecorator() { @@ -174,6 +210,9 @@ public void decorate(Object element, IDecoration decoration) { if (activator == null) return; + if (DEBUG_DECORATIONS) + debug("deocrating '" + resource.getLocation() + "'"); + try { DecorationHelper helper = new DecorationHelper(activator .getPreferenceStore()); @@ -184,7 +223,8 @@ public void decorate(Object element, IDecoration decoration) { } } - private class DecoratableResourceAdapter implements IDecoratableResource { + private static class DecoratableResourceAdapter implements + IDecoratableResource { private final IResource resource; @@ -212,6 +252,111 @@ public void decorate(Object element, IDecoration decoration) { static final int T_WORKSPACE = 2; + private static class ContainerDiffFilter extends TreeFilter { + static final ContainerDiffFilter INSTANCE = new ContainerDiffFilter(); + + @Override + public boolean include(final TreeWalk tw) + throws MissingObjectException, + IncorrectObjectTypeException, IOException { + + if (tw.getFileMode(T_HEAD) == FileMode.MISSING + && tw.getFileMode(T_INDEX) == FileMode.MISSING) + return false; // Untracked and unstaged, so not dirty + + if (DEBUG_DECORATIONS) + debug("checking '" + tw.getPathString() + "'"); + + int mHead = tw.getRawMode(T_HEAD); + int mIndex = tw.getRawMode(T_INDEX); + int mWorkspace = tw.getRawMode(T_WORKSPACE); + + if (!FS.INSTANCE.supportsExecute()) { + // We need to clear the executable bits of the head and + // index modes, to prevent false positives when the + // resource is +x in the repository but not on disk + mHead &= (~0111); + mIndex &= (~0111); + } + + if (DEBUG_DECORATIONS) { + debug("mHead=" + Integer.toOctalString(mHead) + " mIndex=" + + Integer.toOctalString(mIndex) + " mWorkspace=" + + Integer.toOctalString(mWorkspace), 1); + } + + if (mHead != mIndex || mHead != mWorkspace) { + // If all three modes aren't identical there is a difference + // here. Its the fastest test we have and it neatly handles + // weird D->F/F->D style changes that may cause issues later + + if (DEBUG_DECORATIONS) { + debug("Modes did not match, so concider the whole " + + "tree dirty", 1); + } + + return true; + } + + if (FileMode.TREE.equals(mHead)) { + // We must include trees otherwise the walker won't recurse + // into a subtree for us. Computing anything more about a + // tree is too expensive from the workspace so we do not do + // a prune based on no changes. + + final IPreferenceStore store = Activator.getDefault() + .getPreferenceStore(); + return store + .getBoolean(UIPreferences.DECORATOR_COMPUTE_DEEP_DIRTY); + } + + final DirCacheIterator iIndex = tw.getTree(T_INDEX, + DirCacheIterator.class); + final WorkingTreeIterator iWorkspace = tw.getTree(T_WORKSPACE, + WorkingTreeIterator.class); + + if (!timestampMatches(iIndex, iWorkspace)) { + // If the modification time of the file differs we know the + // folder is (possibly) dirty and should be marked as such. + // This is faster than the id check below so it goes first. + + if (DEBUG_DECORATIONS) { + debug("Timestamps did not match, so concider the " + + "whole tree dirty", 1); + } + + return true; + } + + if (!tw.idEqual(T_HEAD, T_INDEX)) { + // Staged id difference indicates the path is modified. + + if (DEBUG_DECORATIONS) { + debug("File is staged, so concider the whole " + + "tree dirty", 1); + } + + return true; + } + + // TODO: Consider doing a content check here, to rule out false + // positives, as we might get mismatch between timestamps, even + // if the content is the same + + return false; + } + + @Override + public boolean shouldBeRecursive() { + return true; + } + + @Override + public TreeFilter clone() { + return this; + } + } + public DecoratableResourceAdapter(IResource resourceToWrap) throws IOException { resource = resourceToWrap; @@ -219,25 +364,12 @@ public DecoratableResourceAdapter(IResource resourceToWrap) repository = mapping.getRepository(); headId = repository.resolve(Constants.HEAD); - switch (resource.getType()) { - case IResource.FILE: - extractFileProperties(); - break; - case IResource.FOLDER: - extractContainerProperties(); - break; - case IResource.PROJECT: - extractProjectProperties(); - break; - } - } + // TODO: Add option to shorten branch name to 6 chars if it's a SHA + branch = repository.getBranch(); - private void extractFileProperties() throws IOException { TreeWalk treeWalk = createHeadVsIndexTreeWalk(); - if (treeWalk == null) - return; - - if (treeWalk.next()) + if (resource.getType() == IResource.PROJECT + || (treeWalk != null && treeWalk.next())) tracked = true; else return; @@ -248,6 +380,27 @@ private void extractFileProperties() throws IOException { return; } + switch (resource.getType()) { + case IResource.FILE: + extractFileProperties(treeWalk); + break; + + case IResource.FOLDER: + extractContainerProperties(); + break; + + case IResource.PROJECT: + final IPreferenceStore store = Activator.getDefault() + .getPreferenceStore(); + if (!store + .getBoolean(UIPreferences.DECORATOR_COMPUTE_DEEP_DIRTY)) + return; + extractContainerProperties(); + break; + } + } + + private void extractFileProperties(TreeWalk treeWalk) { final DirCacheIterator indexIterator = treeWalk.getTree(T_INDEX, DirCacheIterator.class); final DirCacheEntry indexEntry = indexIterator != null ? indexIterator @@ -265,18 +418,7 @@ private void extractFileProperties() throws IOException { .getBits()) { staged = Staged.ADDED; } else { - long indexEntryLastModified = indexEntry.getLastModified(); - long resourceLastModified = resource.getLocalTimeStamp(); - - // C-Git under Windows stores timestamps with 1-seconds - // resolution, so we need to check to see if this is the - // case here, and possibly fix the timestamp of the resource - // to match the resolution of the index. - if (indexEntryLastModified % 1000 == 0) { - resourceLastModified -= resourceLastModified % 1000; - } - - if (resourceLastModified != indexEntryLastModified) { + if (!timestampMatches(indexIterator, resource)) { // TODO: Consider doing a content check here, to rule // out false positives, as we might get mismatch between // timestamps, even if the content is the same @@ -290,37 +432,27 @@ private void extractFileProperties() throws IOException { } } } - } private void extractContainerProperties() throws IOException { TreeWalk treeWalk = createHeadVsIndexTreeWalk(); - if (treeWalk == null) - return; - - if (treeWalk.next()) - tracked = true; + treeWalk.setFilter(AndTreeFilter.create(treeWalk.getFilter(), + ContainerDiffFilter.INSTANCE)); + treeWalk.setRecursive(true); + + if (repository.getWorkDir().equals( + resource.getProject().getLocation().toFile())) + treeWalk.addTree(new ContainerTreeIterator(resource + .getProject())); else - return; - - // TODO: Also read ignores from .git/info/excludes et al. - if (Team.isIgnoredHint(resource)) { - ignored = true; - return; - } - - // TODO: Compute dirty state for folder, using ContainerTreeIterator - // and ContainerDiffFilter - - } - - private void extractProjectProperties() throws IOException { - branch = repository.getBranch(); - tracked = true; - - // TODO: Compute dirty state for folder, using ContainerTreeIterator - // and ContainerDiffFilter + treeWalk.addTree(new ContainerTreeIterator(resource + .getWorkspace().getRoot())); + // TODO: Add fallback for projects with the repository more than + // one parent up, for example by using a stack of DummyIterators + + if (treeWalk.next()) + dirty = true; } /** @@ -328,9 +460,10 @@ private void extractProjectProperties() throws IOException { * those matching the resource specified by * <code>resourceToFilterBy</code> * <p> - * If the resource does not exists in the current repository, or it has - * an empty path (it is the project itself), the filter is not added, - * and the method returns <code>null</code>. + * If the resource does not exists in the current repository, no filter + * is added and the method returns <code>false</code>. If the resource + * is a project, no filter is added, but the operation is considered a + * success. * * @param treeWalk * the tree walk to add the filter to @@ -344,9 +477,12 @@ private boolean addResourceFilter(final TreeWalk treeWalk, final IResource resourceToFilterBy) { Set<String> repositoryPaths = Collections.singleton(mapping .getRepoRelativePath(resourceToFilterBy)); - if (repositoryPaths.isEmpty() || repositoryPaths.contains("")) + if (repositoryPaths.isEmpty()) return false; + if (repositoryPaths.contains("")) + return true; // Project filter + treeWalk.setFilter(PathFilterGroup .createFromStrings(repositoryPaths)); return true; @@ -376,6 +512,31 @@ private TreeWalk createHeadVsIndexTreeWalk() throws IOException { return treeWalk; } + private static boolean timestampMatches(DirCacheIterator index, + IResource workspaceResource) { + return timestampMatches(index.getDirCacheEntry().getLastModified(), + workspaceResource.getLocalTimeStamp()); + } + + private static boolean timestampMatches(DirCacheIterator index, + WorkingTreeIterator workspaceResource) { + return timestampMatches(index.getDirCacheEntry().getLastModified(), + workspaceResource.getEntryLastModified()); + } + + private static boolean timestampMatches(long index, + long workspaceResource) { + // C-Git under Windows stores timestamps with 1-seconds resolution, + // so we need to check to see if this is the case here, and possibly + // fix the timestamp of the resource to match the resolution of the + // index. + if (index % 1000 == 0) { + return index == (workspaceResource - (workspaceResource % 1000)); + } else { + return index == workspaceResource; + } + } + public String getName() { return resource.getName(); } @@ -555,11 +716,13 @@ else if (staged == Staged.REMOVED) } // Conflicts override everything - if (store.getBoolean(UIPreferences.DECORATOR_SHOW_CONFLICTS_ICON) + if (store + .getBoolean(UIPreferences.DECORATOR_SHOW_CONFLICTS_ICON) && resource.hasConflicts()) overlay = conflictImage; - } else if (store.getBoolean(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON)) { + } else if (store + .getBoolean(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON)) { overlay = untrackedImage; } @@ -657,6 +820,9 @@ public static void decorate(IDecoration decoration, String format, * Perform a blanket refresh of all decorations */ public static void refresh() { + if (DEBUG_DECORATIONS) + debug("blanket refesh"); + Display.getDefault().asyncExec(new Runnable() { public void run() { Activator.getDefault().getWorkbench().getDecoratorManager() @@ -679,6 +845,9 @@ public void propertyChange(PropertyChangeEvent event) { if (prop.equals(TeamUI.GLOBAL_IGNORES_CHANGED) || prop.equals(TeamUI.GLOBAL_FILE_TYPES_CHANGED) || prop.equals(Activator.DECORATORS_CHANGED)) { + if (DEBUG_DECORATIONS) + debug("property=" + prop); + postLabelEvent(new LabelProviderChangedEvent(this)); } } @@ -696,9 +865,20 @@ public void propertyChange(PropertyChangeEvent event) { public void resourceChanged(IResourceChangeEvent event) { final Set<IResource> resourcesToUpdate = new HashSet<IResource>(); + if (DEBUG_DECORATIONS) + debug("IResourceChangeEvent"); + try { // Compute the changed resources by looking at the delta event.getDelta().accept(new IResourceDeltaVisitor() { public boolean visit(IResourceDelta delta) throws CoreException { + + // If the file has changed but not in a way that we care + // about (e.g. marker changes to files) then ignore + if (delta.getKind() == IResourceDelta.CHANGED + && (delta.getFlags() & INTERESTING_CHANGES) == 0) { + return true; + } + final IResource resource = delta.getResource(); // If the resource is not part of a project under Git @@ -709,6 +889,11 @@ public boolean visit(IResourceDelta delta) throws CoreException { // Ignore the change return true; } + + if (DEBUG_DECORATIONS) + debug("Git resource: " + + resource.getLocation().toString(), 1); + if (resource.getType() == IResource.ROOT) { // Continue with the delta return true; @@ -720,16 +905,10 @@ public boolean visit(IResourceDelta delta) throws CoreException { return false; } - // If the file has changed but not in a way that we care - // about - // (e.g. marker changes to files) then ignore the change - if (delta.getKind() == IResourceDelta.CHANGED - && (delta.getFlags() & INTERESTING_CHANGES) == 0) { - return true; - } - // All seems good, schedule the resource for update resourcesToUpdate.add(resource); + if (DEBUG_DECORATIONS) + debug("Will update this resource", 2); return true; } }, true /* includePhantoms */); @@ -737,19 +916,25 @@ public boolean visit(IResourceDelta delta) throws CoreException { handleException(null, e); } - // If deep decorator calculation is enabled in the preferences we - // walk the ancestor tree of each of the changed resources and add + if (resourcesToUpdate.isEmpty()) + return; + + // If ancestor-decoration is enabled in the preferences we walk + // the ancestor tree of each of the changed resources and add // their parents to the update set final IPreferenceStore store = Activator.getDefault() .getPreferenceStore(); - if (store.getBoolean(UIPreferences.DECORATOR_CALCULATE_DIRTY)) { + if (store.getBoolean(UIPreferences.DECORATOR_RECOMPUTE_ANCESTORS)) { + if (DEBUG_DECORATIONS) + debug("Calulcating dirty ancestor..", 1); + final IResource[] changedResources = resourcesToUpdate .toArray(new IResource[resourcesToUpdate.size()]); - for (int i = 0; i < changedResources.length; i++) { - IResource current = changedResources[i]; + for (IResource current : changedResources) { while (current.getType() != IResource.ROOT) { current = current.getParent(); - resourcesToUpdate.add(current); + if (resourcesToUpdate.add(current) && DEBUG_DECORATIONS) + debug("Will also update " + current.getLocation(), 2); } } } @@ -768,6 +953,9 @@ postLabelEvent(new LabelProviderChangedEvent(this, resourcesToUpdate * The original change event */ private void repositoryChanged(RepositoryChangedEvent e) { + if (DEBUG_DECORATIONS) + debug("RepositoryChangedEvent=" + e.getRepository().getWorkDir()); + final Set<RepositoryMapping> ms = new HashSet<RepositoryMapping>(); for (final IProject p : ResourcesPlugin.getWorkspace().getRoot() .getProjects()) { @@ -809,6 +997,9 @@ public void refsChanged(RefsChangedEvent e) { * @see org.spearce.egit.core.project.RepositoryChangeListener#repositoryChanged(org.spearce.egit.core.project.RepositoryMapping) */ public void repositoryChanged(RepositoryMapping mapping) { + if (DEBUG_DECORATIONS) + debug("RepositoryMapping=" + mapping.getWorkDir()); + // Until we find a way to refresh visible labels within a project // we have to use this blanket refresh that includes all projects. postLabelEvent(new LabelProviderChangedEvent(this)); @@ -845,6 +1036,9 @@ private static IResource getResource(Object element) { * The event to post */ private void postLabelEvent(final LabelProviderChangedEvent event) { + if (DEBUG_DECORATIONS) + debug("event=" + event.getElements()); + Display.getDefault().asyncExec(new Runnable() { public void run() { fireLabelProviderChanged(event); diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/preferences/GitDecoratorPreferencePage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/preferences/GitDecoratorPreferencePage.java index 74bc209..1a13a15 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/preferences/GitDecoratorPreferencePage.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/preferences/GitDecoratorPreferencePage.java @@ -89,7 +89,9 @@ private Text projectTextFormat; - private Button computeDeepDirtyState; + private Button recomputeAncestorDecorations; + + private Button computeDeepDirtyStateForContainers; private Button showTracked; @@ -204,8 +206,10 @@ private Control createGeneralDecoratorPage(Composite parent) { data.horizontalAlignment = GridData.FILL; composite.setLayoutData(data); - computeDeepDirtyState = SWTUtils.createCheckBox(composite, - UIText.DecoratorPreferencesPage_computeDeep); + recomputeAncestorDecorations = SWTUtils.createCheckBox(composite, + UIText.DecoratorPreferencesPage_recomputeAncestorDecorations); + computeDeepDirtyStateForContainers = SWTUtils.createCheckBox(composite, + UIText.DecoratorPreferencesPage_computeDeepDirtyState); return composite; } @@ -317,8 +321,10 @@ public void handleEvent(Event event) { private void initializeValues() { final IPreferenceStore store = getPreferenceStore(); - computeDeepDirtyState.setSelection(store - .getBoolean(UIPreferences.DECORATOR_CALCULATE_DIRTY)); + recomputeAncestorDecorations.setSelection(store + .getBoolean(UIPreferences.DECORATOR_RECOMPUTE_ANCESTORS)); + computeDeepDirtyStateForContainers.setSelection(store + .getBoolean(UIPreferences.DECORATOR_COMPUTE_DEEP_DIRTY)); fileTextFormat.setText(store .getString(UIPreferences.DECORATOR_FILETEXT_DECORATION)); @@ -342,7 +348,9 @@ public void widgetSelected(SelectionEvent e) { } }; - computeDeepDirtyState.addSelectionListener(selectionListener); + recomputeAncestorDecorations.addSelectionListener(selectionListener); + computeDeepDirtyStateForContainers + .addSelectionListener(selectionListener); showTracked.addSelectionListener(selectionListener); showUntracked.addSelectionListener(selectionListener); showStaged.addSelectionListener(selectionListener); @@ -384,8 +392,10 @@ public boolean performOk() { */ private boolean performOk(IPreferenceStore store) { - store.setValue(UIPreferences.DECORATOR_CALCULATE_DIRTY, - computeDeepDirtyState.getSelection()); + store.setValue(UIPreferences.DECORATOR_RECOMPUTE_ANCESTORS, + recomputeAncestorDecorations.getSelection()); + store.setValue(UIPreferences.DECORATOR_COMPUTE_DEEP_DIRTY, + computeDeepDirtyStateForContainers.getSelection()); store.setValue(UIPreferences.DECORATOR_FILETEXT_DECORATION, fileTextFormat.getText()); @@ -414,8 +424,11 @@ protected void performDefaults() { super.performDefaults(); IPreferenceStore store = getPreferenceStore(); - computeDeepDirtyState.setSelection(store - .getDefaultBoolean(UIPreferences.DECORATOR_CALCULATE_DIRTY)); + recomputeAncestorDecorations + .setSelection(store + .getDefaultBoolean(UIPreferences.DECORATOR_RECOMPUTE_ANCESTORS)); + computeDeepDirtyStateForContainers.setSelection(store + .getDefaultBoolean(UIPreferences.DECORATOR_COMPUTE_DEEP_DIRTY)); fileTextFormat.setText(store .getDefaultString(UIPreferences.DECORATOR_FILETEXT_DECORATION)); diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties b/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties index 2762d11..770de4a 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties @@ -344,7 +344,8 @@ Decorator_exceptionMessage=Errors occurred while applying Git decorations to res DecoratorPreferencesPage_addVariablesTitle=Add Variables DecoratorPreferencesPage_addVariablesAction=Add &Variables... -DecoratorPreferencesPage_computeDeep=Include &ancestors when re-decorating changed resources +DecoratorPreferencesPage_recomputeAncestorDecorations=Also re-decorate &ancestors when decorating changed resources +DecoratorPreferencesPage_computeDeepDirtyState=Inspect dirty state of &children when decorating folders and projects DecoratorPreferencesPage_description=Shows Git specific information on resources in projects under version control. DecoratorPreferencesPage_decorationSettings=Decoration &settings: -- 1.6.1.2.309.g2ea3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html