Skip to content
This repository
  • 6 commits
  • 16 files changed
  • 0 comments
  • 1 contributor

Showing 16 changed files with 558 additions and 378 deletions. Show diff stats Hide diff stats

  1. +2 1  docs/releasenotes/net.sf.eclipsefp.haskell_2.3.2.txt
  2. +2 1  net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/BuildWrapperPlugin.java
  3. +55 54 net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/util/BWText.java
  4. +37 36 net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/util/bwtext.properties
  5. BIN  net.sf.eclipsefp.haskell.ui/icons/eview16/cabal.png
  6. +1 0  net.sf.eclipsefp.haskell.ui/plugin.properties
  7. +20 2 net.sf.eclipsefp.haskell.ui/plugin.xml
  8. +107 43 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/actions/CabalInstallAction.java
  9. +82 0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/actions/CabalInstallDependenciesAction.java
  10. +1 0  ...ipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/preferences/scion/AutodetectExecutableField.java
  11. +7 7 ...ipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/preferences/scion/ExecutableFileFieldEditor.java
  12. +1 0  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/util/UITexts.java
  13. +1 0  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/util/uitexts.properties
  14. +213 211 ...p.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/views/projectexplorer/HaskellResourceExtensionCP.java
  15. +1 0  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/sourcegraph/RunActionDelegate.java
  16. +28 23 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/views/CabalPackagesView.java
3  docs/releasenotes/net.sf.eclipsefp.haskell_2.3.2.txt
@@ -20,9 +20,10 @@ Features:
20 20 - Specify the cabal stanza you want to use settings from when checking a file in the editor
21 21 - In preferences for executables, you can install the executable from Haskage
22 22 - Install all helper executables from one dialog
  23 + - Install all dependencies for one project from right click on project (performs a clean of the project afterwards).
23 24
24 25 Internal:
25   -
  26 + - Hopefully performance of some UI operations has been enhanced and the UI should be more responsive in places
26 27
27 28 Upgrade notes:
28 29
3  net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/BuildWrapperPlugin.java
@@ -130,7 +130,8 @@ public static BWFacade createFacade(IProject p,String cabalPath,Writer outStream
130 130 f.setProject(p);
131 131 f.setOutStream(outStream);
132 132 facades.put(p, f);
133   - new JobFacade(f).synchronize(false);
  133 + // why? build will do that for us
  134 + //new JobFacade(f).synchronize(false);
134 135 return f;
135 136 }
136 137 return null;
109 net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/util/BWText.java
... ... @@ -1,54 +1,55 @@
1   -package net.sf.eclipsefp.haskell.buildwrapper.util;
2   -
3   -import org.eclipse.osgi.util.NLS;
4   -
5   -/**
6   - * Provides access to the internationalized UI texts.
7   - *
8   - * @author JP Moresmau
9   - */
10   -public class BWText extends NLS {
11   - public static String process_launch_error;
12   - public static String process_parse_error;
13   -
14   - public static String process_parse_note_error;
15   - public static String process_apply_note_error;
16   -
17   - public static String process_parse_component_error;
18   - public static String process_parse_package_error;
19   - public static String process_parse_path_error;
20   - public static String process_parse_outline_error;
21   - public static String process_parse_thingatpoint_error;
22   -
23   - public static String project_members_list_error;
24   - public static String project_cabal_duplicate;
25   -
26   - public static String job_build;
27   - public static String job_synchronize;
28   - public static String job_components;
29   - public static String job_dependencies;
30   -
31   - public static String error_deleteMarkers;
32   - public static String error_gettingFlags;
33   - public static String error_noexe;
34   - public static String error_derived;
35   - public static String error_refreshLocal;
36   - public static String error_clean;
37   - public static String error_parsing_usage_path;
38   - public static String error_parsing_usage_file;
39   - public static String error_setup_db;
40   - public static String error_db;
41   - public static String error_no_db;
42   -
43   - public static String outline_job_name;
44   - public static String editor_job_name;
45   - public static String occurrences_job_name;
46   - public static String thingatpoint_job_name;
47   -
48   -
49   - private static final String BUNDLE_NAME = BWText.class.getPackage().getName() + ".bwtext"; //$NON-NLS-1$
50   -
51   - static {
52   - NLS.initializeMessages(BUNDLE_NAME, BWText.class);
53   - }
54   -}
  1 +package net.sf.eclipsefp.haskell.buildwrapper.util;
  2 +
  3 +import org.eclipse.osgi.util.NLS;
  4 +
  5 +/**
  6 + * Provides access to the internationalized UI texts.
  7 + *
  8 + * @author JP Moresmau
  9 + */
  10 +public class BWText extends NLS {
  11 + public static String process_launch_error;
  12 + public static String process_parse_error;
  13 +
  14 + public static String process_parse_note_error;
  15 + public static String process_apply_note_error;
  16 +
  17 + public static String process_parse_component_error;
  18 + public static String process_parse_package_error;
  19 + public static String process_parse_path_error;
  20 + public static String process_parse_outline_error;
  21 + public static String process_parse_thingatpoint_error;
  22 +
  23 + public static String project_members_list_error;
  24 + public static String project_cabal_duplicate;
  25 +
  26 + public static String job_build;
  27 + public static String job_clean;
  28 + public static String job_synchronize;
  29 + public static String job_components;
  30 + public static String job_dependencies;
  31 +
  32 + public static String error_deleteMarkers;
  33 + public static String error_gettingFlags;
  34 + public static String error_noexe;
  35 + public static String error_derived;
  36 + public static String error_refreshLocal;
  37 + public static String error_clean;
  38 + public static String error_parsing_usage_path;
  39 + public static String error_parsing_usage_file;
  40 + public static String error_setup_db;
  41 + public static String error_db;
  42 + public static String error_no_db;
  43 +
  44 + public static String outline_job_name;
  45 + public static String editor_job_name;
  46 + public static String occurrences_job_name;
  47 + public static String thingatpoint_job_name;
  48 +
  49 +
  50 + private static final String BUNDLE_NAME = BWText.class.getPackage().getName() + ".bwtext"; //$NON-NLS-1$
  51 +
  52 + static {
  53 + NLS.initializeMessages(BUNDLE_NAME, BWText.class);
  54 + }
  55 +}
73 net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/util/bwtext.properties
... ... @@ -1,36 +1,37 @@
1   -process_launch_error=Error while launching buildwrapper process
2   -process_parse_error=Cannot parse buildwrapper response as JSON Object
3   -process_parse_note_error=Cannot parse notes from JSON
4   -process_apply_note_error=Cannot apply note
5   -process_parse_component_error=Cannot parse component from JSON
6   -process_parse_package_error=Cannot parse package from JSON
7   -process_parse_path_error=Cannot parse path from JSON
8   -process_parse_outline_error=Cannot parse outline from JSON
9   -process_parse_thingatpoint_error=Cannot parse thing at point from JSON
10   -
11   -project_members_list_error=Error list members of project {0}
12   -project_cabal_duplicate=More than one cabal file under project {0}
13   -
14   -error_deleteMarkers = Error deleting problem markers
15   -error_gettingFlags = Error getting saved flags from project
16   -error_noexe = No buildwrapper executable defined
17   -error_derived = Cannot set derived status on build-wrapper folder
18   -error_refreshLocal = Error refreshing resource
19   -error_clean = Error cleaning project
20   -error_parsing_usage_path = Error parsing usage paths
21   -error_parsing_usage_file = Error parsing usage file
22   -
23   -error_setup_db = Error setting up SQLite DB
24   -error_db = SQLite DB threw an exception
25   -error_no_db = SQLite DB not available
26   -
27   -job_build=Building project {0}
28   -job_synchronize=Synchronizing project {0}
29   -job_components=Retrieving components for project {0}
30   -job_dependencies=Retrieving dependencies for project {0}
31   -
32   -outline_job_name=Generating outline for {0}
33   -editor_job_name=Synchronizing editor content for {0}
34   -occurrences_job_name=Getting occurrences in {0}
35   -thingatpoint_job_name=Finding thing at point in {0}
36   -
  1 +process_launch_error=Error while launching buildwrapper process
  2 +process_parse_error=Cannot parse buildwrapper response as JSON Object
  3 +process_parse_note_error=Cannot parse notes from JSON
  4 +process_apply_note_error=Cannot apply note
  5 +process_parse_component_error=Cannot parse component from JSON
  6 +process_parse_package_error=Cannot parse package from JSON
  7 +process_parse_path_error=Cannot parse path from JSON
  8 +process_parse_outline_error=Cannot parse outline from JSON
  9 +process_parse_thingatpoint_error=Cannot parse thing at point from JSON
  10 +
  11 +project_members_list_error=Error list members of project {0}
  12 +project_cabal_duplicate=More than one cabal file under project {0}
  13 +
  14 +error_deleteMarkers = Error deleting problem markers
  15 +error_gettingFlags = Error getting saved flags from project
  16 +error_noexe = No buildwrapper executable defined
  17 +error_derived = Cannot set derived status on build-wrapper folder
  18 +error_refreshLocal = Error refreshing resource
  19 +error_clean = Error cleaning project
  20 +error_parsing_usage_path = Error parsing usage paths
  21 +error_parsing_usage_file = Error parsing usage file
  22 +
  23 +error_setup_db = Error setting up SQLite DB
  24 +error_db = SQLite DB threw an exception
  25 +error_no_db = SQLite DB not available
  26 +
  27 +job_build=Building project {0}
  28 +job_clean=Cleaning project {0}
  29 +job_synchronize=Synchronizing project {0}
  30 +job_components=Retrieving components for project {0}
  31 +job_dependencies=Retrieving dependencies for project {0}
  32 +
  33 +outline_job_name=Generating outline for {0}
  34 +editor_job_name=Synchronizing editor content for {0}
  35 +occurrences_job_name=Getting occurrences in {0}
  36 +thingatpoint_job_name=Finding thing at point in {0}
  37 +
BIN  net.sf.eclipsefp.haskell.ui/icons/eview16/cabal.png
1  net.sf.eclipsefp.haskell.ui/plugin.properties
@@ -169,6 +169,7 @@ hsCodeTemplates.context=Haskell source code template context
169 169 cabalSDistWizard.name=Cabal source export
170 170 cabalSDistWizard.description=Export source via Cabal sdist
171 171 cabalInstallWizard.name=Cabal install
  172 +cabalInstallDependenciesWizard.name=Cabal install dependencies
172 173 cabalInstallWizard.description=Install project via Cabal
173 174 cabalTestWizard.name=Cabal test
174 175 cabalTestWizard.description=Launch Cabal Test Suites
22 net.sf.eclipsefp.haskell.ui/plugin.xml
@@ -777,6 +777,7 @@
777 777 class="net.sf.eclipsefp.haskell.ui.actions.CabalInstallAction"
778 778 enablesFor="1"
779 779 id="net.sf.eclipsefp.haskell.ui.cabalInstallAction"
  780 + icon="icons/eview16/cabal.png"
780 781 label="%cabalInstallWizard.name">
781 782 </action>
782 783 <enablement>
@@ -787,7 +788,24 @@
787 788
788 789 </enablement>
789 790 </objectContribution>
790   -
  791 + <objectContribution
  792 + id="net.sf.eclipsefp.haskell.ui.contribution2"
  793 + objectClass="org.eclipse.core.resources.IProject">
  794 + <action
  795 + class="net.sf.eclipsefp.haskell.ui.actions.CabalInstallDependenciesAction"
  796 + enablesFor="1"
  797 + id="net.sf.eclipsefp.haskell.ui.cabalInstallDependenciesAction"
  798 + icon="icons/eview16/hackage_install.png"
  799 + label="%cabalInstallDependenciesWizard.name">
  800 + </action>
  801 + <enablement>
  802 + <adapt type="org.eclipse.core.resources.IProject">
  803 + <test property="org.eclipse.core.resources.projectNature"
  804 + value="net.sf.eclipsefp.haskell.core.project.HaskellNature"/>
  805 + </adapt>
  806 +
  807 + </enablement>
  808 + </objectContribution>
791 809 <!--objectContribution
792 810 id="net.sf.eclipsefp.haskell.ui.contribution1"
793 811 objectClass="org.eclipse.core.resources.IProject">
@@ -1159,7 +1177,7 @@
1159 1177 <view
1160 1178 category="net.sf.eclipsefp.haskell"
1161 1179 class="net.sf.eclipsefp.haskell.ui.views.CabalPackagesView"
1162   - icon="icons/eview16/cabal.gif"
  1180 + icon="icons/eview16/cabal.png"
1163 1181 id="net.sf.eclipsefp.haskell.ui.views.CabalPackagesView"
1164 1182 name="%haskellBrowser_cabalPackagesView"
1165 1183 restorable="true">
150 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/actions/CabalInstallAction.java
... ... @@ -1,43 +1,107 @@
1   -package net.sf.eclipsefp.haskell.ui.actions;
2   -
3   -import java.util.LinkedHashSet;
4   -import java.util.Set;
5   -import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
6   -import net.sf.eclipsefp.haskell.ui.wizards.cabal.CabalInstallWizard;
7   -import org.eclipse.core.resources.IProject;
8   -import org.eclipse.jface.action.IAction;
9   -import org.eclipse.jface.viewers.ISelection;
10   -import org.eclipse.jface.wizard.WizardDialog;
11   -import org.eclipse.swt.widgets.Shell;
12   -import org.eclipse.ui.IObjectActionDelegate;
13   -import org.eclipse.ui.IWorkbenchPart;
14   -
15   -/**
16   - * <p>Cabal install action, contextual on projects</p>
17   - *
18   - * @author JP Moresmau
19   - */
20   -public class CabalInstallAction implements IObjectActionDelegate {
21   - private final Set<IProject> projects=new LinkedHashSet<IProject>();
22   - private Shell currentShell;
23   -
24   - @Override
25   - public void setActivePart( final IAction arg0, final IWorkbenchPart arg1 ) {
26   - currentShell=arg1.getSite().getShell();
27   -
28   - }
29   -
30   - @Override
31   - public void run( final IAction arg0 ) {
32   - WizardDialog wd=new WizardDialog( currentShell, new CabalInstallWizard( projects ) );
33   - wd.open();
34   -
35   - }
36   -
37   - @Override
38   - public void selectionChanged( final IAction arg0, final ISelection arg1 ) {
39   - projects.clear();
40   - projects.addAll( ResourceUtil.getProjects( arg1 ) );
41   - }
42   -
43   -}
  1 +package net.sf.eclipsefp.haskell.ui.actions;
  2 +
  3 +import java.io.File;
  4 +import java.util.ArrayList;
  5 +import java.util.LinkedHashSet;
  6 +import java.util.List;
  7 +import java.util.Set;
  8 +import net.sf.eclipsefp.haskell.buildwrapper.BWFacade;
  9 +import net.sf.eclipsefp.haskell.buildwrapper.BuildWrapperPlugin;
  10 +import net.sf.eclipsefp.haskell.core.cabal.CabalImplementationManager;
  11 +import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
  12 +import net.sf.eclipsefp.haskell.debug.core.internal.launch.AbstractHaskellLaunchDelegate;
  13 +import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
  14 +import net.sf.eclipsefp.haskell.ui.internal.util.UITexts;
  15 +import org.eclipse.core.resources.IProject;
  16 +import org.eclipse.core.runtime.IStatus;
  17 +import org.eclipse.core.runtime.Status;
  18 +import org.eclipse.jface.action.IAction;
  19 +import org.eclipse.jface.dialogs.ErrorDialog;
  20 +import org.eclipse.jface.viewers.ISelection;
  21 +import org.eclipse.osgi.util.NLS;
  22 +import org.eclipse.swt.widgets.Shell;
  23 +import org.eclipse.ui.IObjectActionDelegate;
  24 +import org.eclipse.ui.IWorkbenchPart;
  25 +
  26 +/**
  27 + * <p>Cabal install action, contextual on projects</p>
  28 + *
  29 + * @author JP Moresmau
  30 + */
  31 +public class CabalInstallAction implements IObjectActionDelegate {
  32 + private final Set<IProject> projects=new LinkedHashSet<IProject>();
  33 + private Shell currentShell;
  34 +
  35 + @Override
  36 + public void setActivePart( final IAction arg0, final IWorkbenchPart arg1 ) {
  37 + currentShell=arg1.getSite().getShell();
  38 +
  39 + }
  40 +
  41 + @Override
  42 + public void run( final IAction arg0 ) {
  43 + // do not ask for options, use our own dist folder and default cabal options
  44 + //WizardDialog wd=new WizardDialog( currentShell, new CabalInstallWizard( projects ) );
  45 + //wd.open();
  46 + final String cabalExecutable=CabalImplementationManager.getCabalExecutable();
  47 + if (cabalExecutable!=null){
  48 + final List<String> commands = new ArrayList<String>();
  49 + commands.add( cabalExecutable );
  50 + commands.add("install");
  51 + // options
  52 + commands.add("--builddir="+BWFacade.DIST_FOLDER_CABAL);
  53 + // commands.add( "--user" ); // use cabal default, which is now user
  54 + addExtraParameters(commands);
  55 + for (final IProject p:projects){
  56 + try {
  57 + List<String> prjCommands = new ArrayList<String>(commands);
  58 + BWFacade bf=BuildWrapperPlugin.getFacade( p );
  59 + // need to provide user supplied info
  60 + if(bf!=null){
  61 + String f=bf.getFlags();
  62 + if (f!=null && f.length()>0){
  63 + prjCommands.add("--flags="+f);
  64 + }
  65 + List<String> extraOpts=bf.getExtraOpts();
  66 + if (extraOpts!=null){
  67 + for (String eo:extraOpts){
  68 + prjCommands.add(eo);
  69 + }
  70 + }
  71 + }
  72 +
  73 +
  74 + AbstractHaskellLaunchDelegate.runInConsole(p, prjCommands, new File(p.getLocation().toOSString()), NLS.bind( getJobName(), p.getName() ),true,getAfter(p) );
  75 + } catch (Exception ioe){
  76 + HaskellUIPlugin.log(ioe);
  77 + final IStatus st=new Status( IStatus.ERROR, HaskellUIPlugin.getPluginId(),ioe.getLocalizedMessage(),ioe);
  78 + ErrorDialog.openError( currentShell, UITexts.install_error, UITexts.install_error_text, st);
  79 + }
  80 +
  81 +
  82 + }
  83 + }
  84 +
  85 +
  86 + }
  87 +
  88 + protected Runnable getAfter(final IProject p){
  89 + return null;
  90 + }
  91 +
  92 + protected String getJobName(){
  93 + return UITexts.install_job;
  94 + }
  95 +
  96 + protected void addExtraParameters(final List<String> commands){
  97 + // force reinstall since we're probably reinstalling our development version
  98 + commands.add( "--reinstall" );
  99 + }
  100 +
  101 + @Override
  102 + public void selectionChanged( final IAction arg0, final ISelection arg1 ) {
  103 + projects.clear();
  104 + projects.addAll( ResourceUtil.getProjects( arg1 ) );
  105 + }
  106 +
  107 +}
82 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/actions/CabalInstallDependenciesAction.java
... ... @@ -0,0 +1,82 @@
  1 +/**
  2 + * Copyright (c) 2012 by JP Moresmau
  3 + * This code is made available under the terms of the Eclipse Public License,
  4 + * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
  5 + */
  6 +package net.sf.eclipsefp.haskell.ui.actions;
  7 +
  8 +import java.util.List;
  9 +import net.sf.eclipsefp.haskell.buildwrapper.util.BWText;
  10 +import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
  11 +import net.sf.eclipsefp.haskell.ui.internal.util.UITexts;
  12 +import org.eclipse.core.resources.IProject;
  13 +import org.eclipse.core.resources.IncrementalProjectBuilder;
  14 +import org.eclipse.core.resources.ResourcesPlugin;
  15 +import org.eclipse.core.runtime.CoreException;
  16 +import org.eclipse.core.runtime.IProgressMonitor;
  17 +import org.eclipse.core.runtime.IStatus;
  18 +import org.eclipse.core.runtime.Status;
  19 +import org.eclipse.core.runtime.jobs.Job;
  20 +import org.eclipse.osgi.util.NLS;
  21 +
  22 +
  23 +/**
  24 + * Install only the project dependencies
  25 + * @author JP Moresmau
  26 + *
  27 + */
  28 +public class CabalInstallDependenciesAction extends CabalInstallAction {
  29 +
  30 + /* (non-Javadoc)
  31 + * @see net.sf.eclipsefp.haskell.ui.actions.CabalInstallAction#getJobName()
  32 + */
  33 + @Override
  34 + protected String getJobName() {
  35 + return UITexts.install_dependencies_job;
  36 + }
  37 +
  38 + /* (non-Javadoc)
  39 + * @see net.sf.eclipsefp.haskell.ui.actions.CabalInstallAction#addExtraParameters(java.util.List)
  40 + */
  41 + @Override
  42 + protected void addExtraParameters( final List<String> commands ) {
  43 + commands.add("--only-dependencies");
  44 + }
  45 +
  46 + /* (non-Javadoc)
  47 + * @see net.sf.eclipsefp.haskell.ui.actions.CabalInstallAction#getAfter(org.eclipse.core.resources.IProject)
  48 + */
  49 + @Override
  50 + protected Runnable getAfter(final IProject p ) {
  51 + // once we've downloaded the dependencies, we clean the project and rebuild if we're in auto build mode
  52 + Runnable r=new Runnable(){
  53 + @Override
  54 + public void run() {
  55 + final String jobName = NLS.bind(BWText.job_clean, p.getName());
  56 + Job j=new Job(jobName) {
  57 +
  58 + @Override
  59 + protected IStatus run( final IProgressMonitor mon ) {
  60 + try {
  61 + p.build( IncrementalProjectBuilder.CLEAN_BUILD , mon );
  62 + if (ResourcesPlugin.getWorkspace().isAutoBuilding()){
  63 + if (mon!=null){
  64 + mon.setTaskName( NLS.bind(BWText.job_build, p.getName()) );
  65 + }
  66 + p.build( IncrementalProjectBuilder.FULL_BUILD , mon );
  67 + }
  68 + } catch (CoreException ce){
  69 + return new Status( IStatus.ERROR, HaskellUIPlugin.getPluginId(), ce.getLocalizedMessage(),ce);
  70 + }
  71 + return Status.OK_STATUS;
  72 + }
  73 + };
  74 + j.setPriority( Job.BUILD );
  75 + j.schedule();
  76 + }
  77 + };
  78 + return r;
  79 +
  80 +
  81 + }
  82 +}
1  ...efp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/preferences/scion/AutodetectExecutableField.java
@@ -158,6 +158,7 @@ public void run() {
158 158 String newVal=f.getAbsolutePath();
159 159 fieldEditor.setStringValue(newVal);
160 160 listener.propertyChange( new PropertyChangeEvent( this, "path", oldVal, newVal) ) ;
  161 + fieldEditor.checkState();
161 162 }
162 163 }
163 164 installButton.setEnabled( true );
14 ...efp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/preferences/scion/ExecutableFileFieldEditor.java
@@ -139,20 +139,20 @@ protected String changePressed() {
139 139 * and <code>false</code> if invalid
140 140 */
141 141 @Override
142   - protected boolean checkState() {
  142 + public boolean checkState() {
143 143 if (getTextControl() == null) {
144   - return false;
145   - }
  144 + return false;
  145 + }
146 146 String txt = getTextControl().getText();
147 147
148 148 boolean result = isEmptyStringAllowed() || txt.length() > 0;
149 149 result = result && doCheckState();
150 150
151 151 if (result) {
152   - clearErrorMessage();
153   - } else {
154   - showErrorMessage(getErrorMessage());
155   - }
  152 + clearErrorMessage();
  153 + } else {
  154 + showErrorMessage(getErrorMessage());
  155 + }
156 156
157 157 return result;
158 158 }
1  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/util/UITexts.java
@@ -480,6 +480,7 @@
480 480 public static String exportSource_overwrite_warning;
481 481
482 482 public static String install_job;
  483 + public static String install_dependencies_job;
483 484 public static String install_options;
484 485 public static String install_options_folder;
485 486 public static String install_options_folder_choose;
1  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/util/uitexts.properties
@@ -502,6 +502,7 @@ exportSource_warning_markers=warning: warnings: note: errors:
502 502 exportSource_overwrite_warning=File {0} already exists and will be overwritten
503 503
504 504 install_job=Installing project {0}
  505 +install_dependencies_job=Installing dependencies of project {0}
505 506 install_options=Install options
506 507 install_options_folder=Install from build folder:
507 508 install_options_folder_choose=Choose a build folder
424 ...askell.ui/src/net/sf/eclipsefp/haskell/ui/internal/views/projectexplorer/HaskellResourceExtensionCP.java
... ... @@ -1,211 +1,213 @@
1   -// Copyright (c) 2006-2008 by Leif Frenzel - see http://leiffrenzel.de
2   -// This code is made available under the terms of the Eclipse Public License,
3   -// version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
4   -package net.sf.eclipsefp.haskell.ui.internal.views.projectexplorer;
5   -
6   -import java.util.ArrayList;
7   -import java.util.HashSet;
8   -import java.util.List;
9   -import java.util.Set;
10   -import net.sf.eclipsefp.haskell.buildwrapper.BWFacade;
11   -import net.sf.eclipsefp.haskell.buildwrapper.BuildWrapperPlugin;
12   -import net.sf.eclipsefp.haskell.buildwrapper.types.OutlineDef;
13   -import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
14   -import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescription;
15   -import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionLoader;
16   -import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionStanza;
17   -import net.sf.eclipsefp.haskell.core.preferences.ICorePreferenceNames;
18   -import net.sf.eclipsefp.haskell.core.project.HaskellNature;
19   -import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
20   -import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
21   -import net.sf.eclipsefp.haskell.ui.internal.views.common.ITreeElement;
22   -import net.sf.eclipsefp.haskell.ui.internal.views.projectexplorer.model.GHCSystemLibrary;
23   -import net.sf.eclipsefp.haskell.util.FileUtil;
24   -import org.eclipse.core.resources.IContainer;
25   -import org.eclipse.core.resources.IFile;
26   -import org.eclipse.core.resources.IProject;
27   -import org.eclipse.core.resources.IResource;
28   -import org.eclipse.core.runtime.CoreException;
29   -import org.eclipse.core.runtime.preferences.IEclipsePreferences;
30   -import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
31   -import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
32   -import org.eclipse.core.runtime.preferences.InstanceScope;
33   -import org.eclipse.jface.viewers.Viewer;
34   -import org.eclipse.ui.IMemento;
35   -import org.eclipse.ui.navigator.ICommonContentExtensionSite;
36   -import org.eclipse.ui.navigator.ICommonContentProvider;
37   -
38   -/**
39   - * <p>
40   - * content provider which is declared in <code>plugin.xml</code> for the project
41   - * explorer view.
42   - * </p>
43   - *
44   - * @author Leif Frenzel
45   - */
46   -public class HaskellResourceExtensionCP implements ICommonContentProvider {
47   - // interface methods of ITreeContentProvider
48   - // //////////////////////////////////////////
49   -
50   - @Override
51   - public Object[] getChildren( final Object parentElement ) {
52   - final List<Object> result = new ArrayList<Object>();
53   - try {
54   - if( parentElement instanceof IProject
55   - && ( ( IProject )parentElement ).isOpen()
56   - && ( ( IProject )parentElement ).hasNature( HaskellNature.NATURE_ID ) ) {
57   - IProject p = ( IProject )parentElement;
58   - result.add( new GHCSystemLibrary( p ));
59   - IFile f = BuildWrapperPlugin.getCabalFile( p );
60   - if (f != null && f.exists()) {
61   - result.add( f );
62   - }
63   - Set<IContainer> srcs=new HashSet<IContainer>(ResourceUtil.getSourceFolders( p ));
64   - srcs.remove( parentElement ); // may happen if . is a source folder
65   - result.addAll(srcs);
66   -
67   - // add all remaining members so that they appear after the haskell content in view
68   - for (IResource r:p.members()){
69   - if (!r.equals( f ) && !srcs.contains( r )){
70   - result.add(r);
71   - }
72   - }
73   - // addProjectExecutable( ( IProject )parentElement, result );
74   - } else if( parentElement instanceof IFile ) {
75   - final IFile f = ( IFile )parentElement;
76   - // if we have a Haskell source file, we show the same content as outline
77   - // underneath
78   - if( FileUtil.hasHaskellExtension( f ) && ResourceUtil.isInHaskellProject( f )) {
79   - BWFacade si = BuildWrapperPlugin.getFacade( f.getProject() );//ScionPlugin.getScionInstance( f );
80   - if (si != null) {
81   - List<OutlineDef> outlineDefs = si.outline( f ).getOutlineDefs();
82   - //OutlineCP cp = new OutlineCP();
83   - //cp.inputChanged( null, null, outlineDefs );
84   - for( OutlineDef def : outlineDefs ) {
85   - //if( def.getParentID() == null ) {
86   - result.add( new ProjectExplorerOutlineDef( f, def ) );
87   - //}
88   - }
89   - }
90   - }
91   - // if we have a Haskell source file, we show the same content as outline
92   - // underneath
93   - else if( FileUtil.hasCabalExtension( f ) && ResourceUtil.isInHaskellProject( f )) {
94   - PackageDescription descr = PackageDescriptionLoader.load( f );
95   - PackageDescriptionStanza lib = descr.getLibraryStanza();
96   - if (lib != null) {
97   - result.add( new ProjectExplorerStanza( f,descr.getLibraryStanza() ));
98   - }
99   - if (descr.getExecutableStanzas().size() > 0) {
100   - result.add( new CabalFolder(f, CabalFolderType.EXECUTABLE ));
101   - }
102   - if (descr.getTestSuiteStanzas().size() > 0) {
103   - result.add( new CabalFolder(f, CabalFolderType.TEST_SUITE ));
104   - }
105   - }
106   - } else if (parentElement instanceof CabalFolder) {
107   - CabalFolder folder = ( CabalFolder )parentElement;
108   - result.addAll( folder.getStanzas() );
109   - }else if( parentElement instanceof ITreeElement ) {
110   - ITreeElement treeElement = ( ITreeElement )parentElement;
111   - result.addAll( treeElement.getChildren() );
112   - // outline results are wrapped in a structure keeping the tree and the file
113   - } else if( parentElement instanceof ProjectExplorerOutlineDef ) {
114   - ProjectExplorerOutlineDef outline = ( ProjectExplorerOutlineDef )parentElement;
115   - result.addAll( outline.getChildren() );
116   - }
117   - } catch( final CoreException cex ) {
118   - HaskellUIPlugin.log( cex );
119   - }
120   - return result.toArray();
121   - }
122   -
123   - @Override
124   - public Object getParent( final Object element ) {
125   - Object result = null;
126   - if( element instanceof ITreeElement ) {
127   - result = ( ( ITreeElement )element ).getParent();
128   - }
129   - return result;
130   - }
131   -
132   - @Override
133   - public boolean hasChildren( final Object element ) {
134   - if( element instanceof IFile ) {
135   - IFile f = ( IFile )element;
136   - if( FileUtil.hasHaskellExtension( f ) || FileUtil.hasCabalExtension( f ) ) {
137   - return true;
138   - }
139   - return false;
140   - } else if ( element instanceof CabalFolder ) {
141   - return true;
142   - }
143   - Object[] children = getChildren( element );
144   - return children == null ? false : children.length > 0;
145   - }
146   -
147   - @Override
148   - public Object[] getElements( final Object inputElement ) {
149   - return new Object[ 0 ];
150   - }
151   -
152   - @Override
153   - public void dispose() {
154   - // unused
155   - }
156   -
157   - @Override
158   - public void inputChanged( final Viewer viewer, final Object oldInput,
159   - final Object newInput ) {
160   - // unused
161   - }
162   -
163   -
164   - // interface methods of ICommonContentProvider
165   - // ////////////////////////////////////////////
166   -
167   - // TODO lf note to self: config -> navigator service -> can be used to
168   - // get state information from the View
169   - @Override
170   - public void init( final ICommonContentExtensionSite config ) {
171   - IEclipsePreferences node = InstanceScope.INSTANCE.getNode( HaskellCorePlugin
172   - .getPluginId() );
173   - node.addPreferenceChangeListener( new IPreferenceChangeListener() {
174   -
175   - @Override
176   - public void preferenceChange( final PreferenceChangeEvent event ) {
177   - String prop = event.getKey();
178   - if( ICorePreferenceNames.HS_IMPLEMENTATIONS.equals( prop )
179   - || ICorePreferenceNames.SELECTED_HS_IMPLEMENTATION.equals( prop ) ) {
180   - config.getService().update();
181   - }
182   - }
183   - } );
184   - }
185   -
186   - @Override
187   - public void restoreState( final IMemento memento ) {
188   - // unused
189   - }
190   -
191   - @Override
192   - public void saveState( final IMemento memento ) {
193   - // unused
194   - }
195   -
196   -
197   - // helping functions
198   - // //////////////////
199   -
200   - /* private void addProjectExecutable( final IProject project,
201   - final List<Object> list ) {
202   - try {
203   - IFile[] executables = ResourceUtil.getProjectExecutables( project );
204   - list.addAll( Arrays.asList( executables ) );
205   - } catch( CoreException ex ) {
206   - String msg = "Problem determining project executable for "
207   - + project.getName();
208   - HaskellUIPlugin.log( msg, ex );
209   - }
210   - }*/
211   -}
  1 +// Copyright (c) 2006-2008 by Leif Frenzel - see http://leiffrenzel.de
  2 +// This code is made available under the terms of the Eclipse Public License,
  3 +// version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
  4 +package net.sf.eclipsefp.haskell.ui.internal.views.projectexplorer;
  5 +
  6 +import java.util.ArrayList;
  7 +import java.util.HashSet;
  8 +import java.util.List;
  9 +import java.util.Set;
  10 +import net.sf.eclipsefp.haskell.buildwrapper.BWFacade;
  11 +import net.sf.eclipsefp.haskell.buildwrapper.BuildWrapperPlugin;
  12 +import net.sf.eclipsefp.haskell.buildwrapper.types.OutlineDef;
  13 +import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
  14 +import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescription;
  15 +import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionLoader;
  16 +import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionStanza;
  17 +import net.sf.eclipsefp.haskell.core.preferences.ICorePreferenceNames;
  18 +import net.sf.eclipsefp.haskell.core.project.HaskellNature;
  19 +import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
  20 +import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
  21 +import net.sf.eclipsefp.haskell.ui.internal.views.common.ITreeElement;
  22 +import net.sf.eclipsefp.haskell.ui.internal.views.projectexplorer.model.GHCSystemLibrary;
  23 +import net.sf.eclipsefp.haskell.util.FileUtil;
  24 +import org.eclipse.core.resources.IContainer;
  25 +import org.eclipse.core.resources.IFile;
  26 +import org.eclipse.core.resources.IProject;
  27 +import org.eclipse.core.resources.IResource;
  28 +import org.eclipse.core.runtime.CoreException;
  29 +import org.eclipse.core.runtime.preferences.IEclipsePreferences;
  30 +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
  31 +import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
  32 +import org.eclipse.core.runtime.preferences.InstanceScope;
  33 +import org.eclipse.jface.viewers.Viewer;
  34 +import org.eclipse.ui.IMemento;
  35 +import org.eclipse.ui.navigator.ICommonContentExtensionSite;
  36 +import org.eclipse.ui.navigator.ICommonContentProvider;
  37 +
  38 +/**
  39 + * <p>
  40 + * content provider which is declared in <code>plugin.xml</code> for the project
  41 + * explorer view.
  42 + * </p>
  43 + *
  44 + * @author Leif Frenzel
  45 + */
  46 +public class HaskellResourceExtensionCP implements ICommonContentProvider {
  47 + // interface methods of ITreeContentProvider
  48 + // //////////////////////////////////////////
  49 +
  50 + @Override
  51 + public Object[] getChildren( final Object parentElement ) {
  52 + final List<Object> result = new ArrayList<Object>();
  53 + try {
  54 + if( parentElement instanceof IProject
  55 + && ( ( IProject )parentElement ).isOpen()
  56 + && ( ( IProject )parentElement ).hasNature( HaskellNature.NATURE_ID ) ) {
  57 + IProject p = ( IProject )parentElement;
  58 + result.add( new GHCSystemLibrary( p ));
  59 + IFile f = BuildWrapperPlugin.getCabalFile( p );
  60 + if (f != null && f.exists()) {
  61 + result.add( f );
  62 + }
  63 + Set<IContainer> srcs=new HashSet<IContainer>(ResourceUtil.getSourceFolders( p ));
  64 + srcs.remove( parentElement ); // may happen if . is a source folder
  65 + result.addAll(srcs);
  66 +
  67 + // add all remaining members so that they appear after the haskell content in view
  68 + for (IResource r:p.members()){
  69 + if (!r.equals( f ) && !srcs.contains( r )){
  70 + result.add(r);
  71 + }
  72 + }
  73 + // addProjectExecutable( ( IProject )parentElement, result );
  74 + } else if( parentElement instanceof IFile ) {
  75 + final IFile f = ( IFile )parentElement;
  76 + // if we have a Haskell source file, we show the same content as outline
  77 + // underneath
  78 + if( FileUtil.hasHaskellExtension( f ) && ResourceUtil.isInHaskellProject( f )) {
  79 + BWFacade si = BuildWrapperPlugin.getFacade( f.getProject() );//ScionPlugin.getScionInstance( f );
  80 + if (si != null) {
  81 + List<OutlineDef> outlineDefs = si.outline( f ).getOutlineDefs();
  82 + //OutlineCP cp = new OutlineCP();
  83 + //cp.inputChanged( null, null, outlineDefs );
  84 + for( OutlineDef def : outlineDefs ) {
  85 + //if( def.getParentID() == null ) {
  86 + result.add( new ProjectExplorerOutlineDef( f, def ) );
  87 + //}
  88 + }
  89 + }
  90 + }
  91 + // if we have a Haskell source file, we show the same content as outline
  92 + // underneath
  93 + else if( FileUtil.hasCabalExtension( f ) && ResourceUtil.isInHaskellProject( f )) {
  94 + PackageDescription descr = PackageDescriptionLoader.load( f );
  95 + PackageDescriptionStanza lib = descr.getLibraryStanza();
  96 + if (lib != null) {
  97 + result.add( new ProjectExplorerStanza( f,descr.getLibraryStanza() ));
  98 + }
  99 + if (descr.getExecutableStanzas().size() > 0) {
  100 + result.add( new CabalFolder(f, CabalFolderType.EXECUTABLE ));
  101 + }
  102 + if (descr.getTestSuiteStanzas().size() > 0) {
  103 + result.add( new CabalFolder(f, CabalFolderType.TEST_SUITE ));
  104 + }
  105 + }
  106 + } else if (parentElement instanceof CabalFolder) {
  107 + CabalFolder folder = ( CabalFolder )parentElement;
  108 + result.addAll( folder.getStanzas() );
  109 + }else if( parentElement instanceof ITreeElement ) {
  110 + ITreeElement treeElement = ( ITreeElement )parentElement;
  111 + result.addAll( treeElement.getChildren() );
  112 + // outline results are wrapped in a structure keeping the tree and the file
  113 + } else if( parentElement instanceof ProjectExplorerOutlineDef ) {
  114 + ProjectExplorerOutlineDef outline = ( ProjectExplorerOutlineDef )parentElement;
  115 + result.addAll( outline.getChildren() );
  116 + }
  117 + } catch( final CoreException cex ) {
  118 + HaskellUIPlugin.log( cex );
  119 + }
  120 + return result.toArray();
  121 + }
  122 +
  123 + @Override
  124 + public Object getParent( final Object element ) {
  125 + Object result = null;
  126 + if( element instanceof ITreeElement ) {
  127 + result = ( ( ITreeElement )element ).getParent();
  128 + }
  129 + return result;
  130 + }
  131 +
  132 + @Override
  133 + public boolean hasChildren( final Object element ) {
  134 + if( element instanceof IFile ) {
  135 + IFile f = ( IFile )element;
  136 + if( FileUtil.hasHaskellExtension( f ) || FileUtil.hasCabalExtension( f ) ) {
  137 + return true;
  138 + }
  139 + return false;
  140 + } else if ( element instanceof CabalFolder ) {
  141 + return true;
  142 + } else if (element instanceof GHCSystemLibrary){ // for performance, we know we always have children
  143 + return true;
  144 + }
  145 + Object[] children = getChildren( element );
  146 + return children == null ? false : children.length > 0;
  147 + }
  148 +
  149 + @Override
  150 + public Object[] getElements( final Object inputElement ) {
  151 + return new Object[ 0 ];
  152 + }
  153 +
  154 + @Override
  155 + public void dispose() {
  156 + // unused
  157 + }
  158 +
  159 + @Override
  160 + public void inputChanged( final Viewer viewer, final Object oldInput,
  161 + final Object newInput ) {
  162 + // unused
  163 + }
  164 +
  165 +
  166 + // interface methods of ICommonContentProvider
  167 + // ////////////////////////////////////////////
  168 +
  169 + // TODO lf note to self: config -> navigator service -> can be used to
  170 + // get state information from the View
  171 + @Override
  172 + public void init( final ICommonContentExtensionSite config ) {
  173 + IEclipsePreferences node = InstanceScope.INSTANCE.getNode( HaskellCorePlugin
  174 + .getPluginId() );
  175 + node.addPreferenceChangeListener( new IPreferenceChangeListener() {
  176 +
  177 + @Override
  178 + public void preferenceChange( final PreferenceChangeEvent event ) {
  179 + String prop = event.getKey();
  180 + if( ICorePreferenceNames.HS_IMPLEMENTATIONS.equals( prop )
  181 + || ICorePreferenceNames.SELECTED_HS_IMPLEMENTATION.equals( prop ) ) {
  182 + config.getService().update();
  183 + }
  184 + }
  185 + } );
  186 + }
  187 +
  188 + @Override
  189 + public void restoreState( final IMemento memento ) {
  190 + // unused
  191 + }
  192 +
  193 + @Override
  194 + public void saveState( final IMemento memento ) {
  195 + // unused
  196 + }
  197 +
  198 +
  199 + // helping functions
  200 + // //////////////////
  201 +
  202 + /* private void addProjectExecutable( final IProject project,
  203 + final List<Object> list ) {
  204 + try {
  205 + IFile[] executables = ResourceUtil.getProjectExecutables( project );
  206 + list.addAll( Arrays.asList( executables ) );
  207 + } catch( CoreException ex ) {
  208 + String msg = "Problem determining project executable for "
  209 + + project.getName();
  210 + HaskellUIPlugin.log( msg, ex );
  211 + }
  212 + }*/
  213 +}
1  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/sourcegraph/RunActionDelegate.java
@@ -107,6 +107,7 @@ public void selectionChanged( final IAction action, final ISelection selection )
107 107 if (prjs.size() > 0){
108 108 project = prjs.iterator().next();
109 109 }
  110 + action.setEnabled( project!=null );
110 111 }
111 112
112 113 @Override
51 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/views/CabalPackagesView.java
@@ -468,32 +468,34 @@ private void install(final boolean global,final String options){
468 468 if (options!=null && options.trim().length()>0){
469 469 commands.addAll(Arrays.asList(CommandLineUtil.parse( options.trim() )));
470 470 }
471   - try {
472   - AbstractHaskellLaunchDelegate.runInConsole(null, commands, new File(cabalExecutable).getParentFile(), UITexts.cabalPackagesView_action_install_running,true, new Runnable() {
473 471
474   - @Override
475   - public void run() {
476   - lInstall.getDisplay().asyncExec( new Runnable() {
  472 + try {
  473 + // this requires to be in the UI thread
  474 + AbstractHaskellLaunchDelegate.runInConsole(null, commands, new File(cabalExecutable).getParentFile(), UITexts.cabalPackagesView_action_install_running,true, new Runnable() {
477 475
478   - @Override
479   - public void run() {
480   - lInstall.setText( UITexts.cabalPackagesView_info_installed );
481   - helper.setInstalled( null );
482   - if (!bAll.getSelection()){
483   - refreshJob.schedule();
  476 + @Override
  477 + public void run() {
  478 + lInstall.getDisplay().asyncExec( new Runnable() {
  479 +
  480 + @Override
  481 + public void run() {
  482 + lInstall.setText( UITexts.cabalPackagesView_info_installed );
  483 + helper.setInstalled( null );
  484 + if (!bAll.getSelection()){
  485 + refreshJob.schedule();
  486 + }
484 487 }
485   - }
486   - });
487   - BrowserPlugin.loadLocalDatabase( true );
488   - }
489   - });
490   - } catch (Exception ioe){
491   - HaskellUIPlugin.log(ioe);
492   - final IStatus st=new Status( IStatus.ERROR, HaskellUIPlugin.getPluginId(),ioe.getLocalizedMessage(),ioe);
493   - ErrorDialog.openError(getSite().getShell(), UITexts.cabalPackagesView_action_install_error, UITexts.cabalPackagesView_action_install_error, st);
494   - }
495   - }
  488 + });
  489 + BrowserPlugin.loadLocalDatabase( true );
  490 + }
  491 + });
  492 + } catch (Exception ioe){
  493 + HaskellUIPlugin.log(ioe);
  494 + final IStatus st=new Status( IStatus.ERROR, HaskellUIPlugin.getPluginId(),ioe.getLocalizedMessage(),ioe);
  495 + ErrorDialog.openError(getSite().getShell(), UITexts.cabalPackagesView_action_install_error, UITexts.cabalPackagesView_action_install_error, st);
  496 + }
496 497
  498 + }
497 499 }
498 500
499 501 private void update(){
@@ -618,8 +620,11 @@ public void modifyText( final ModifyEvent arg0 ) {
618 620
619 621 @Override
620 622 protected void okPressed() {
621   - install(global,options);
  623 + // install does things in the UI thread, so close the dialog first
622 624 super.okPressed();
  625 +
  626 + install(global,options);
  627 +
623 628 }
624 629 }
625 630 }

No commit comments for this range

Something went wrong with that request. Please try again.