|
6 | 6 | * the root directory of this source tree. |
7 | 7 | */ |
8 | 8 |
|
9 | | -import { promises as fs } from 'fs'; |
10 | | -import glob from 'glob'; |
| 9 | +import * as core from '../core'; |
11 | 10 |
|
12 | 11 | export default class ProjectConfig { |
13 | | - reLines = /[\r\n]+/g; |
14 | | - reComment = /(^\s*;|\s+;|^\s*#).+/; |
15 | | - reSection = /^\[([^\]]+)\]/; |
16 | | - reOptionValue = /^([^=]+)=(.*)/; |
17 | | - reMultiLineValue = /^\s+(.*)/; |
18 | | - reInterpolation = /\$\{([^\.\}]+)\.([^\}]+)\}/g; |
19 | | - |
20 | | - static parse_multi_values(items) { |
21 | | - const result = []; |
22 | | - if (!items) { |
23 | | - return result; |
24 | | - } |
25 | | - if (typeof items == 'string') { |
26 | | - items = items.split(items.includes('\n') ? '\n' : ', '); |
27 | | - } |
28 | | - for (let item of items) { |
29 | | - item = item.trim(); |
30 | | - if (item) { |
31 | | - result.push(item); |
32 | | - } |
33 | | - } |
34 | | - return result; |
35 | | - } |
36 | | - |
37 | | - constructor() { |
38 | | - this._parsed = []; |
39 | | - this._data = {}; |
| 12 | + constructor(projectDir) { |
| 13 | + this.projectDir = projectDir; |
| 14 | + this._data = undefined; |
40 | 15 | } |
41 | 16 |
|
42 | | - async read(path) { |
43 | | - if (!path) { |
44 | | - return; |
45 | | - } |
46 | | - if (this._parsed.includes(path)) { |
47 | | - return; |
48 | | - } |
49 | | - this._parsed.push(path); |
50 | | - let section = null; |
51 | | - let option = null; |
52 | | - for (let line of (await fs.readFile(path, { encoding: 'utf-8' })).split( |
53 | | - this.reLines |
54 | | - )) { |
55 | | - // Remove comments |
56 | | - line = line.replace(this.reComment, ''); |
57 | | - if (!line) { |
58 | | - continue; |
59 | | - } |
| 17 | + async read() { |
| 18 | + const script = ` |
| 19 | +import json |
| 20 | +from platformio.public import ProjectConfig |
60 | 21 |
|
61 | | - // Section |
62 | | - const mSection = line.match(this.reSection); |
63 | | - if (mSection) { |
64 | | - section = mSection[1]; |
65 | | - if (!this._data[section]) { |
66 | | - this._data[section] = {}; |
67 | | - } |
68 | | - option = null; |
69 | | - continue; |
70 | | - } |
| 22 | +config = ProjectConfig() |
| 23 | +envs = config.envs() |
71 | 24 |
|
72 | | - // Option and value |
73 | | - const mOptionValue = line.match(this.reOptionValue); |
74 | | - if (section && mOptionValue) { |
75 | | - option = mOptionValue[1].trim(); |
76 | | - this._data[section][option] = mOptionValue[2].trim(); |
77 | | - continue; |
78 | | - } |
79 | | - |
80 | | - // Multi-line value |
81 | | - const mMultiLineValue = line.match(this.reMultiLineValue); |
82 | | - if (option && mMultiLineValue) { |
83 | | - this._data[section][option] += '\n' + mMultiLineValue[0]; |
84 | | - } |
85 | | - } |
86 | | - |
87 | | - for (const pattern of this.getlist('platformio', 'extra_configs')) { |
88 | | - for (const item of glob.sync(pattern)) { |
89 | | - await this.read(item); |
90 | | - } |
91 | | - } |
| 25 | +print(json.dumps(dict( |
| 26 | + envs=envs, |
| 27 | + default_envs=config.default_envs(), |
| 28 | + default_env=config.get_default_env(), |
| 29 | + env_platforms={env:config.get(f"env:{env}", "platform", default=None) for env in envs} |
| 30 | +))) |
| 31 | +`; |
| 32 | + const output = await core.getCorePythonCommandOutput(['-c', script], { |
| 33 | + projectDir: this.projectDir, |
| 34 | + }); |
| 35 | + this._data = JSON.parse(output.trim()); |
92 | 36 | } |
93 | 37 |
|
94 | | - getraw(section, option) { |
95 | | - if (!this._data[section]) { |
96 | | - throw `NoSectionError: ${section}`; |
97 | | - } |
98 | | - let value = null; |
99 | | - if (option in this._data[section]) { |
100 | | - value = this._data[section][option]; |
101 | | - } else { |
102 | | - if ('extends' in this._data[section]) { |
103 | | - for (const ext of ProjectConfig.parse_multi_values( |
104 | | - this._data[section]['extends'] |
105 | | - )) { |
106 | | - try { |
107 | | - value = this.getraw(ext, option); |
108 | | - break; |
109 | | - } catch {} |
110 | | - } |
111 | | - } |
112 | | - if (!value && section.startsWith('env:')) { |
113 | | - try { |
114 | | - value = this.getraw('env', option); |
115 | | - } catch {} |
116 | | - } |
117 | | - } |
118 | | - if (!value) { |
119 | | - throw `NoOptionError: ${section} -> ${option}`; |
120 | | - } |
121 | | - if (!value.includes('${') || !value.includes('}')) { |
122 | | - return value; |
123 | | - } |
124 | | - return value.replace(this.reInterpolation, (_, _section, _option) => |
125 | | - this._reInterpolationHandler(section, _section, _option) |
126 | | - ); |
127 | | - } |
128 | | - |
129 | | - _reInterpolationHandler(parentSection, section, option) { |
130 | | - if (section === 'sysenv') { |
131 | | - return process.env[option] || ''; |
132 | | - } |
133 | | - // handle ${this.*} |
134 | | - if (section === 'this') { |
135 | | - section = parentSection; |
136 | | - if (option === '__env__') { |
137 | | - return parentSection.substring(4); |
138 | | - } |
139 | | - } |
140 | | - return this.get(section, option); |
141 | | - } |
142 | | - |
143 | | - sections() { |
144 | | - return Object.keys(this._data); |
| 38 | + envs() { |
| 39 | + return this._data.envs; |
145 | 40 | } |
146 | 41 |
|
147 | | - envs() { |
148 | | - return this.sections() |
149 | | - .filter((item) => item.startsWith('env:')) |
150 | | - .map((item) => item.substring(4)); |
| 42 | + defaultEnvs() { |
| 43 | + return this._data.default_envs; |
151 | 44 | } |
152 | 45 |
|
153 | | - get(section, option, default_ = undefined) { |
154 | | - try { |
155 | | - return this.getraw(section, option); |
156 | | - } catch (err) { |
157 | | - return default_; |
158 | | - } |
| 46 | + defaultEnv() { |
| 47 | + return this._data.default_env; |
159 | 48 | } |
160 | 49 |
|
161 | | - getlist(section, option, default_ = undefined) { |
162 | | - return ProjectConfig.parse_multi_values(this.get(section, option, default_)); |
| 50 | + getEnvPlatform(env) { |
| 51 | + return this._data.env_platforms[env]; |
163 | 52 | } |
164 | 53 | } |
0 commit comments