Skip to content

Commit

Permalink
Adds following changes:
Browse files Browse the repository at this point in the history
- Show progress bar while flashing
- Show location of output log file at the start of the flashing process.
- Throw error is device is not in EDL mode or no device is detected.
- Propagate any errors
  • Loading branch information
keeramis committed Jan 16, 2025
1 parent c3853ae commit add1c65
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 37 deletions.
40 changes: 19 additions & 21 deletions src/cmd/flash.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ module.exports = class FlashCommand extends CLICommandBase {
}

async flashTachyon({ verbose, files }) {
this.ui.write(`${os.EOL}Ensure only one device is connected to the computer${os.EOL}`);
this.ui.write(`${os.EOL}Ensure that only one device is connected to the computer before proceeding.${os.EOL}`);

let zipFile;
let includeDir = '';
Expand Down Expand Up @@ -101,27 +101,25 @@ module.exports = class FlashCommand extends CLICommandBase {
filesToProgram = files;
}

this.ui.write(`Starting download. The download may take several minutes...${os.EOL}`);

const res = await qdl.run({
files: filesToProgram,
includeDir,
updateFolder,
zip: zipFile,
verbose,
ui: this.ui
});
// put the output in a log file if not verbose
if (!verbose) {
const outputLog = path.join(process.cwd(), `qdl-output-${Date.now()}.log`);
if (res?.stdout) {
await fs.writeFile(outputLog, res.stdout);
}
this.ui.write(`Download complete. Output log available at ${outputLog}${os.EOL}`);
} else {
this.ui.write(`Download complete${os.EOL}`);
this.ui.write(`Starting download. This may take several minutes...${os.EOL}`);
const outputLog = path.join(process.cwd(), `qdl-output-${Date.now()}.log`);
try {
// put the output in a log file if not verbose
this.ui.write(`Logs are being written to: ${outputLog}${os.EOL}`);
await qdl.run({
files: filesToProgram,
includeDir,
updateFolder,
zip: zipFile,
verbose,
ui: this.ui,
outputLogFile: outputLog
});
fs.appendFileSync(outputLog, 'Download complete.');
} catch (error) {
this.ui.write('Download failed');
fs.appendFileSync(outputLog, 'Download failed.');
}
// TODO: Handle errors
}

async _extractFlashFilesFromDir(dirPath) {
Expand Down
95 changes: 79 additions & 16 deletions src/lib/qdl.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,94 @@ async function getExecutable() {
return path.join(tmpDir, 'qdl' + (archName === 'win32' ? '.exe' : ''));
}

/**
*/
async function run({ files, includeDir, updateFolder, zip, verbose, ui }) {
const qdl = await getExecutable();

const qdlArgs = [
'--storage',
TACHYON_STORAGE_TYPE,
async function run({ files, includeDir, updateFolder, zip, ui, outputLogFile }) {
const qdlPath = '/Users/keerthyamisagadda/code/tachyon-qdl/qdl';
await fs.chmod(qdlPath, 0o755);

const qdlArguments = [
'--storage', TACHYON_STORAGE_TYPE,
...(zip ? ['--zip', zip] : []),
...(includeDir ? ['--include', includeDir] : []),
...files
];

if (verbose) {
ui.write(`Command: ${qdl} ${qdlArgs.join(' ')}${os.EOL}`);
}
const progressBar = ui.createProgressBar();
let currentModuleName = '', currentModuleSectors = 0;
let totalSectorsInAllFiles = 0, totalSectorsFlashed = 0, progressBarInitialized = false;

const handleError = (process, message) => {
progressBar.stop();
ui.stdout.write(message);
process.kill();
};

const processLogLine = (line, process) => {
fs.appendFileSync(outputLogFile, `${line}\n`);

if (line.includes('Waiting for EDL device')) {
handleError(process, `Device is not in EDL mode${os.EOL}`);
} else if (line.includes('[ERROR]')) {
handleError(process, `${os.EOL}Error detected: ${line}${os.EOL}`);
} else if (line.includes('status=getProgramInfo')) {
const match = line.match(/sectors_total=(\d+)/);
if (match) {
totalSectorsInAllFiles += parseInt(match[1], 10);
}
} else if (line.includes('status=Start flashing module')) {
const moduleNameMatch = line.match(/module=(.*?),/);
const sectorsTotalMatch = line.match(/sectors_total=(\d+)/);
if (moduleNameMatch && sectorsTotalMatch) {
currentModuleName = moduleNameMatch[1];
currentModuleSectors = parseInt(sectorsTotalMatch[1], 10);

if (!progressBarInitialized) {
progressBarInitialized = true;
progressBar.start(totalSectorsInAllFiles, totalSectorsFlashed, { description: `Flashing ${currentModuleName}` });
} else {
progressBar.update(totalSectorsFlashed, { description: `Flashing ${currentModuleName}` });
}
}
} else if (line.includes('status=Flashing module')) {
const sectorsFlashedMatch = line.match(/sectors_done=(\d+)/);
if (sectorsFlashedMatch) {
const sectorsFlashed = parseInt(sectorsFlashedMatch[1], 10);
progressBar.update(totalSectorsFlashed + sectorsFlashed, { description: `Flashing module: ${currentModuleName} (${sectorsFlashed}/${currentModuleSectors} sectors)` });

const res = await execa(qdl, qdlArgs, {
cwd: updateFolder || process.cwd(),
stdio: verbose ? 'inherit' : 'pipe'
});
if (sectorsFlashed === currentModuleSectors) {
totalSectorsFlashed += currentModuleSectors;
progressBar.update({ description: `Flashed ${currentModuleName}` });
}

return res;
if (totalSectorsFlashed === totalSectorsInAllFiles) {
progressBar.update({ description: 'Flashing complete' });
progressBar.stop();
}
}
}
};

try {
const qdlProcess = execa(qdlPath, qdlArguments, { cwd: updateFolder || process.cwd(), stdio: 'pipe' });

const handleStream = (stream) => {
stream.on('data', chunk => {
chunk.toString().split('\n').map(line => line.trim()).filter(Boolean).forEach(line => {
processLogLine(line, qdlProcess);
});
});
};

handleStream(qdlProcess.stdout, 'stdout');
handleStream(qdlProcess.stderr, 'stderr');

await qdlProcess;
return;
} finally {
progressBar.stop();
}
}


module.exports = {
run
};

0 comments on commit add1c65

Please sign in to comment.