Add clean build files command and auto-clean on version change (#181)

* Add clean build files command and auto-clean on version change

* Update __main__.py
This commit is contained in:
Otto Winter 2018-10-14 18:52:21 +02:00 committed by GitHub
parent 8d395e5338
commit e34365dc7c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 123 additions and 7 deletions

View file

@ -355,6 +355,17 @@ def command_version(args):
return 0 return 0
def command_clean(args, config):
build_path = relative_path(config[CONF_ESPHOMEYAML][CONF_BUILD_PATH])
try:
writer.clean_build(build_path)
except OSError as err:
_LOGGER.error("Error deleting build files: %s", err)
return 1
_LOGGER.info("Done!")
return 0
def command_dashboard(args): def command_dashboard(args):
from esphomeyaml.dashboard import dashboard from esphomeyaml.dashboard import dashboard
@ -375,6 +386,7 @@ POST_CONFIG_ACTIONS = {
'run': command_run, 'run': command_run,
'clean-mqtt': command_clean_mqtt, 'clean-mqtt': command_clean_mqtt,
'mqtt-fingerprint': command_mqtt_fingerprint, 'mqtt-fingerprint': command_mqtt_fingerprint,
'clean': command_clean,
} }
@ -445,6 +457,8 @@ def parse_args(argv):
subparsers.add_parser('version', help="Print the esphomeyaml version and exit.") subparsers.add_parser('version', help="Print the esphomeyaml version and exit.")
subparsers.add_parser('clean', help="Delete all temporary build files.")
dashboard = subparsers.add_parser('dashboard', dashboard = subparsers.add_parser('dashboard',
help="Create a simple webserver for a dashboard.") help="Create a simple webserver for a dashboard.")
dashboard.add_argument("--port", help="The HTTP port to open connections on.", type=int, dashboard.add_argument("--port", help="The HTTP port to open connections on.", type=int,

View file

@ -124,6 +124,13 @@ class EsphomeyamlCleanMqttHandler(EsphomeyamlCommandWebSocket):
return ["esphomeyaml", config_file, "clean-mqtt"] return ["esphomeyaml", config_file, "clean-mqtt"]
class EsphomeyamlCleanHandler(EsphomeyamlCommandWebSocket):
def build_command(self, message):
js = json.loads(message)
config_file = os.path.join(CONFIG_DIR, js['configuration'])
return ["esphomeyaml", config_file, "clean"]
class SerialPortRequestHandler(BaseHandler): class SerialPortRequestHandler(BaseHandler):
def get(self): def get(self):
if not self.is_authenticated(): if not self.is_authenticated():
@ -221,6 +228,7 @@ def make_app(debug=False):
(r"/compile", EsphomeyamlCompileHandler), (r"/compile", EsphomeyamlCompileHandler),
(r"/validate", EsphomeyamlValidateHandler), (r"/validate", EsphomeyamlValidateHandler),
(r"/clean-mqtt", EsphomeyamlCleanMqttHandler), (r"/clean-mqtt", EsphomeyamlCleanMqttHandler),
(r"/clean", EsphomeyamlCleanHandler),
(r"/download.bin", DownloadBinaryRequestHandler), (r"/download.bin", DownloadBinaryRequestHandler),
(r"/serial-ports", SerialPortRequestHandler), (r"/serial-ports", SerialPortRequestHandler),
(r"/wizard.html", WizardRequestHandler), (r"/wizard.html", WizardRequestHandler),

View file

@ -220,6 +220,7 @@
</div> </div>
<ul id="dropdown-{{ i }}" class="dropdown-content"> <ul id="dropdown-{{ i }}" class="dropdown-content">
<li><a href="#" class="action-clean-mqtt" data-node="{{ file }}">Clean MQTT</a></li> <li><a href="#" class="action-clean-mqtt" data-node="{{ file }}">Clean MQTT</a></li>
<li><a href="#" class="action-clean" data-node="{{ file }}">Clean Build</a></li>
</ul> </ul>
</div> </div>
</div> </div>
@ -484,6 +485,18 @@
</div> </div>
</div> </div>
<div id="modal-clean" class="modal modal-fixed-footer">
<div class="modal-content">
<h4>Clean Build Files <code class="inlinecode filename"></code></h4>
<div class="log-container">
<pre class="log"></pre>
</div>
</div>
<div class="modal-footer">
<a class="modal-close waves-effect waves-green btn-flat stop-logs">Stop</a>
</div>
</div>
<a class="btn-floating btn-large ribbon-fab waves-effect waves-light pink accent-2" id="setup-wizard-start"> <a class="btn-floating btn-large ribbon-fab waves-effect waves-light pink accent-2" id="setup-wizard-start">
<i class="material-icons">add</i> <i class="material-icons">add</i>
</a> </a>
@ -849,6 +862,54 @@
}); });
}); });
const cleanModalElem = document.getElementById("modal-clean");
document.querySelectorAll(".action-clean").forEach((btn) => {
btn.addEventListener('click', (e) => {
configuration = e.target.getAttribute('data-node');
const modalInstance = M.Modal.getInstance(cleanModalElem);
const log = cleanModalElem.querySelector(".log");
log.innerHTML = "";
const stopLogsButton = cleanModalElem.querySelector(".stop-logs");
let stopped = false;
stopLogsButton.innerHTML = "Stop";
modalInstance.open();
const filenameField = cleanModalElem.querySelector('.filename');
filenameField.innerHTML = configuration;
const logSocket = new WebSocket(wsUrl + "/clean");
logSocket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.event === "line") {
const msg = data.data;
log.innerHTML += colorReplace(msg);
} else if (data.event === "exit") {
if (data.code === 0) {
M.toast({html: "Program exited successfully."});
downloadButton.classList.remove('disabled');
} else {
M.toast({html: `Program failed with code ${data.code}`});
}
stopLogsButton.innerHTML = "Close";
stopped = true;
}
});
logSocket.addEventListener('open', () => {
const msg = JSON.stringify({configuration: configuration});
logSocket.send(msg);
});
logSocket.addEventListener('close', () => {
if (!stopped) {
M.toast({html: 'Terminated process.'});
}
});
modalInstance.options.onCloseStart = () => {
logSocket.close();
};
});
});
const modalSetupElem = document.getElementById("modal-wizard"); const modalSetupElem = document.getElementById("modal-wizard");
const setupWizardStart = document.getElementById('setup-wizard-start'); const setupWizardStart = document.getElementById('setup-wizard-start');
const startWizard = () => { const startWizard = () => {

View file

@ -3,7 +3,9 @@ from __future__ import print_function
import codecs import codecs
import errno import errno
import json import json
import logging
import os import os
import shutil
from esphomeyaml import core from esphomeyaml import core
from esphomeyaml.config import iter_components from esphomeyaml.config import iter_components
@ -14,6 +16,8 @@ from esphomeyaml.core import ESPHomeYAMLError
from esphomeyaml.core_config import VERSION_REGEX from esphomeyaml.core_config import VERSION_REGEX
from esphomeyaml.helpers import relative_path from esphomeyaml.helpers import relative_path
_LOGGER = logging.getLogger(__name__)
CPP_AUTO_GENERATE_BEGIN = u'// ========== AUTO GENERATED CODE BEGIN ===========' CPP_AUTO_GENERATE_BEGIN = u'// ========== AUTO GENERATED CODE BEGIN ==========='
CPP_AUTO_GENERATE_END = u'// =========== AUTO GENERATED CODE END ============' CPP_AUTO_GENERATE_END = u'// =========== AUTO GENERATED CODE END ============'
INI_AUTO_GENERATE_BEGIN = u'; ========== AUTO GENERATED CODE BEGIN ===========' INI_AUTO_GENERATE_BEGIN = u'; ========== AUTO GENERATED CODE BEGIN ==========='
@ -111,17 +115,19 @@ def get_ini_content(config, path):
lib_version = config[CONF_ESPHOMEYAML][CONF_ESPHOMELIB_VERSION] lib_version = config[CONF_ESPHOMEYAML][CONF_ESPHOMELIB_VERSION]
lib_path = os.path.join(path, 'lib') lib_path = os.path.join(path, 'lib')
dst_path = os.path.join(lib_path, 'esphomelib') dst_path = os.path.join(lib_path, 'esphomelib')
this_version = None
if CONF_REPOSITORY in lib_version: if CONF_REPOSITORY in lib_version:
tag = next((lib_version[x] for x in (CONF_COMMIT, CONF_BRANCH, CONF_TAG) tag = next((lib_version[x] for x in (CONF_COMMIT, CONF_BRANCH, CONF_TAG)
if x in lib_version), None) if x in lib_version), None)
if tag is None: this_version = lib_version[CONF_REPOSITORY]
lib_deps.add(lib_version[CONF_REPOSITORY]) if tag is not None:
else: this_version += '#' + tag
lib_deps.add(lib_version[CONF_REPOSITORY] + '#' + tag) lib_deps.add(this_version)
if os.path.islink(dst_path): if os.path.islink(dst_path):
os.unlink(dst_path) os.unlink(dst_path)
else: elif CONF_LOCAL in lib_version:
src_path = relative_path(lib_version[CONF_LOCAL]) this_version = lib_version[CONF_LOCAL]
src_path = relative_path(this_version)
do_write = True do_write = True
if os.path.islink(dst_path): if os.path.islink(dst_path):
old_path = os.path.join(os.readlink(dst_path), lib_path) old_path = os.path.join(os.readlink(dst_path), lib_path)
@ -144,6 +150,25 @@ def get_ini_content(config, path):
lib_deps.add(dep['name'] + '@' + dep['version']) lib_deps.add(dep['name'] + '@' + dep['version'])
else: else:
lib_deps.add(dep['version']) lib_deps.add(dep['version'])
else:
this_version = lib_version
lib_deps.add(lib_version)
version_file = os.path.join(path, '.esphomelib_version')
version = None
if os.path.isfile(version_file):
with open(version_file, 'r') as ver_f:
version = ver_f.read()
if version != this_version:
_LOGGER.info("Esphomelib version change detected. Cleaning build files...")
try:
clean_build(path)
except OSError as err:
_LOGGER.warn("Error deleting build files (%s)! Ignoring...", err)
with open(version_file, 'w') as ver_f:
ver_f.write(this_version)
lib_deps |= get_build_flags(config, 'LIB_DEPS') lib_deps |= get_build_flags(config, 'LIB_DEPS')
lib_deps |= get_build_flags(config, 'lib_deps') lib_deps |= get_build_flags(config, 'lib_deps')
@ -207,7 +232,6 @@ def write_platformio_ini(content, path):
content_format = find_begin_end(text, INI_AUTO_GENERATE_BEGIN, INI_AUTO_GENERATE_END) content_format = find_begin_end(text, INI_AUTO_GENERATE_BEGIN, INI_AUTO_GENERATE_END)
else: else:
prev_file = None prev_file = None
mkdir_p(os.path.dirname(path))
content_format = INI_BASE_FORMAT content_format = INI_BASE_FORMAT
full_file = content_format[0] + INI_AUTO_GENERATE_BEGIN + '\n' + \ full_file = content_format[0] + INI_AUTO_GENERATE_BEGIN + '\n' + \
content + INI_AUTO_GENERATE_END + content_format[1] content + INI_AUTO_GENERATE_END + content_format[1]
@ -218,6 +242,7 @@ def write_platformio_ini(content, path):
def write_platformio_project(config, path): def write_platformio_project(config, path):
mkdir_p(path)
platformio_ini = os.path.join(path, 'platformio.ini') platformio_ini = os.path.join(path, 'platformio.ini')
content = get_ini_content(config, path) content = get_ini_content(config, path)
if 'esp32_ble_beacon' in config or 'esp32_ble_tracker' in config: if 'esp32_ble_beacon' in config or 'esp32_ble_tracker' in config:
@ -268,3 +293,11 @@ def determine_platformio_version_settings():
settings['flash_mode_key'] = 'board_build.flash_mode' settings['flash_mode_key'] = 'board_build.flash_mode'
return settings return settings
def clean_build(build_path):
for directory in ('.piolibdeps', '.pioenvs'):
dir_path = os.path.join(build_path, directory)
if os.path.isdir(dir_path):
_LOGGER.info("Deleting %s", dir_path)
shutil.rmtree(dir_path)