1 module dlangide.builders.builder;
2 
3 import dlangui.core.logger;
4 import dlangide.workspace.project;
5 import dlangide.workspace.workspace;
6 import dlangide.ui.outputpanel;
7 import dlangide.builders.extprocess;
8 import dlangui.widgets.appframe;
9 import std.algorithm;
10 import core.thread;
11 import std..string;
12 import std.conv;
13 
14 class Builder : BackgroundOperationWatcher {
15     protected Project _project;
16     protected ExternalProcess _extprocess;
17     protected OutputPanel _log;
18     protected ProtectedTextStorage _box;
19     protected BuildConfiguration _buildConfig;
20     protected BuildOperation _buildOp;
21     protected bool _verbose;
22 
23     @property Project project() { return _project; }
24     @property void project(Project p) { _project = p; }
25 
26     this(AppFrame frame, Project project, OutputPanel log, BuildConfiguration buildConfig, BuildOperation buildOp, bool verbose) {
27         super(frame);
28         _buildConfig = buildConfig;
29         _buildOp = buildOp;
30         _verbose = verbose;
31         _project = project;
32         _log = log;
33         _extprocess = new ExternalProcess();
34         _box = new ProtectedTextStorage();
35     }
36     /// log lines
37     void pollText() {
38         dstring text = _box.readText();
39         if (text.length) {
40             _log.appendText(null, text);
41         }
42     }
43 
44     /// returns icon of background operation to show in status line
45     override @property string icon() { return "folder"; }
46     /// update background operation status
47     override void update() {
48         scope(exit)pollText();
49         ExternalProcessState state = _extprocess.state;
50         if (state == ExternalProcessState.None) {
51             _log.clear();
52             _box.writeText("Running dub\n"d);
53             char[] program = "dub".dup;
54             char[][] params;
55             char[] dir = _project.dir.dup;
56 
57             if (_buildOp == BuildOperation.Build || _buildOp == BuildOperation.Rebuild) {
58                 params ~= "build".dup;
59                 if (_buildOp == BuildOperation.Rebuild) {
60                     params ~= "--force".dup;
61                 }
62             } else if (_buildOp == BuildOperation.Clean) {
63                 params ~= "clean".dup;
64             } else if (_buildOp == BuildOperation.Run) {
65                 params ~= "run".dup;
66             } else if (_buildOp == BuildOperation.Upgrade) {
67                 params ~= "upgrade".dup;
68                 params ~= "--force-remove".dup;
69             }
70 
71             if (_buildOp != BuildOperation.Clean && _buildOp != BuildOperation.Upgrade) {
72                 switch (_buildConfig) {
73                     default:
74                     case BuildConfiguration.Debug:
75                         params ~= "--build=debug".dup;
76                         break;
77                     case BuildConfiguration.Release:
78                         params ~= "--build=release".dup;
79                         break;
80                     case BuildConfiguration.Unittest:
81                         params ~= "--build=unittest".dup;
82                         break;
83                 }
84             }
85 
86             if (_verbose)
87                 params ~= "-v".dup;
88 
89             state = _extprocess.run(program, params, dir, _box, null);
90             if (state != ExternalProcessState.Running) {
91                 _box.writeText("Failed to run builder tool\n"d);
92                 _finished = true;
93                 destroy(_extprocess);
94                 _extprocess = null;
95                 return;
96             }
97         }
98         state = _extprocess.poll();
99         if (state == ExternalProcessState.Stopped) {
100             _box.writeText("Builder finished with result "d ~ to!dstring(_extprocess.result) ~ "\n"d);
101             _finished = true;
102             return;
103         }
104         if (_cancelRequested) {
105             _extprocess.kill();
106             _extprocess.wait();
107             _finished = true;
108             return;
109         }
110         super.update();
111     }
112 }