Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add prompts to ask user about installing additional but required packages #653

Closed
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 55 additions & 39 deletions cli/src/build.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { basename, dirname, join, relative, resolve } from "node:path"
import { readFileSync, writeFileSync, existsSync, readdirSync } from "node:fs"
import { readFileSync, writeFileSync, existsSync, readdirSync, constants } from "node:fs"
import { ensureDirSync, mkdirp, removeSync } from "fs-extra"
import {
compileWithHost,
Expand Down Expand Up @@ -36,7 +36,7 @@ import {
import glob from "fast-glob"

import type { DevsModule } from "@devicescript/vm"
import { readFile, writeFile } from "node:fs/promises"
import { readFile, writeFile, access } from "node:fs/promises"
import { printDmesg } from "./vmworker"
import { EXIT_CODE_COMPILATION_ERROR } from "./exitcodes"
import {
Expand All @@ -58,14 +58,14 @@ export function setupWebsocket() {
require("websocket-polyfill")
// @ts-ignore
global.Blob = require("buffer").Blob
global.WebSocket.prototype.send = function (this: any, data: any) {
global.WebSocket.prototype.send = function(this: any, data: any) {
pelikhan marked this conversation as resolved.
Show resolved Hide resolved
if (typeof data.valueOf() === "string")
this.connection_.sendUTF(data)
else {
this.connection_.sendBytes(Buffer.from(data))
}
}
global.WebSocket.prototype.close = function (this: any, code, reason) {
global.WebSocket.prototype.close = function(this: any, code, reason) {
this.state_ = WebSocket.CLOSING
if (this.connection_) {
if (code === undefined) this.connection_.sendCloseFrame()
Expand All @@ -81,11 +81,13 @@ export function readDebugInfo() {
let dbg: DebugInfo
try {
dbg = readJSON5Sync(join(BINDIR, DEVS_DBG_FILE))
} catch {}
} catch {
}
return dbg
}

let devsInst: DevsModule

export function setDevsDmesg() {
if (devsInst) {
const dbg = readDebugInfo()
Expand Down Expand Up @@ -160,7 +162,7 @@ export async function devsStartWithNetwork(options: {
export async function getHost(
buildConfig: ResolvedBuildConfig,
options: BuildOptions,
folder: string
folder: string,
) {
const inst = options.verify === false ? undefined : await devsFactory()
const outdir = resolve(options.cwd ?? ".", options.outDir || BINDIR)
Expand Down Expand Up @@ -199,6 +201,7 @@ export async function getHost(
}
return devsHost
}

function toDevsDiag(d: jdspec.Diagnostic): DevsDiagnostic {
return {
category: 1,
Expand Down Expand Up @@ -237,7 +240,7 @@ function compilePackageJson(
tsdir: string,
entryPoint: string,
lcfg: LocalBuildConfig,
errors: DevsDiagnostic[]
errors: DevsDiagnostic[],
) {
const pkgJsonPath = join(tsdir, "package.json")
if (existsSync(pkgJsonPath)) {
Expand All @@ -247,10 +250,10 @@ function compilePackageJson(
let version = pkgJSON.version ?? "(no version)"
if (isGit()) {
const head = execCmd(
"git describe --tags --match 'v[0-9]*' --always"
"git describe --tags --match 'v[0-9]*' --always",
)
let dirty = execCmd(
"git status --porcelain --untracked-file=no --ignore-submodules=untracked"
"git status --porcelain --untracked-file=no --ignore-submodules=untracked",
)
if (!head) dirty = "yes"
const exact = !dirty && head[0] == "v" && !head.includes("-")
Expand Down Expand Up @@ -289,33 +292,33 @@ function compilePackageJson(
}

verboseLog(
`compile: ${lcfg.hwInfo["@name"]} ${lcfg.hwInfo["@version"] ?? ""}`
`compile: ${lcfg.hwInfo["@name"]} ${lcfg.hwInfo["@version"] ?? ""}`,
)
}

function compileServiceSpecs(
tsdir: string,
lcfg: LocalBuildConfig,
errors: DevsDiagnostic[]
errors: DevsDiagnostic[],
) {
const dir = join(tsdir, "services")
lcfg.addServices = []

if (existsSync(dir)) {
const includes: Record<string, jdspec.ServiceSpec> = {}
jacdacDefaultSpecifications.forEach(
spec => (includes[spec.shortId] = spec)
spec => (includes[spec.shortId] = spec),
)
const markdowns = readdirSync(dir, { encoding: "utf-8" }).filter(
fn => /\.md$/i.test(fn) && !/README\.md$/i.test(fn)
fn => /\.md$/i.test(fn) && !/README\.md$/i.test(fn),
)
for (const mdf of markdowns) {
const fn = join(dir, mdf)
const content = readFileSync(fn, { encoding: "utf-8" })
const json = parseServiceSpecificationMarkdownToJSON(
content,
includes,
fn
fn,
)
json.catalog = false
if (json?.errors?.length)
Expand Down Expand Up @@ -346,21 +349,21 @@ export function validateBoard(board: DeviceConfig, baseCfg: RepoInfo) {
function compileBoards(
tsdir: string,
lcfg: LocalBuildConfig,
errors: DevsDiagnostic[]
errors: DevsDiagnostic[],
) {
const dir = join(tsdir, "boards")
lcfg.addBoards = []
const baseCfg = resolveBuildConfig()

if (existsSync(dir)) {
const boards = readdirSync(dir, { encoding: "utf-8" }).filter(fn =>
fn.endsWith(".board.json")
fn.endsWith(".board.json"),
)
for (const boardFn of boards) {
const fullName = join(dir, boardFn)
try {
const board: DeviceConfig = JSON.parse(
readFileSync(fullName, "utf-8")
readFileSync(fullName, "utf-8"),
)
const bid = basename(boardFn, ".board.json")
if (board.id && board.id != bid)
Expand All @@ -375,7 +378,7 @@ function compileBoards(
file: fullName,
line: 1,
message: e.message,
})
}),
)
}
}
Expand All @@ -384,6 +387,7 @@ function compileBoards(

export class CompilationError extends Error {
static NAME = "CompilationError"

constructor(message: string) {
super(message)
this.name = CompilationError.NAME
Expand All @@ -393,7 +397,7 @@ export class CompilationError extends Error {
export function buildConfigFromDir(
dir: string,
entryPoint: string = "",
options: BuildOptions = {}
options: BuildOptions = {},
) {
const lcfg: LocalBuildConfig = {
hwInfo: {},
Expand All @@ -418,7 +422,7 @@ export function buildConfigFromDir(

export async function compileFile(
fn: string,
options: BuildOptions = {}
options: BuildOptions = {},
): Promise<CompilationResult> {
const exists = existsSync(fn)
if (!exists) throw new Error(`source file "${fn}" not found`)
Expand All @@ -438,7 +442,7 @@ export async function compileFile(
const { errors, buildConfig } = buildConfigFromDir(
folder,
entryPoint,
options
options,
)

await saveLibFiles(buildConfig, options)
Expand All @@ -455,7 +459,7 @@ export async function compileFile(
verboseLog(`sha: ${res.dbg.binarySHA256}`)
writeFileSync(
join(folder, outDir, DEVS_DBG_FILE),
JSON.stringify(res.dbg)
JSON.stringify(res.dbg),
)
}

Expand All @@ -471,7 +475,7 @@ export async function compileFile(

export async function saveLibFiles(
buildConfig: ResolvedBuildConfig,
options: BuildOptions
options: BuildOptions,
) {
// pass the user-provided services so they are included in devicescript-specs.d.ts
const prelude = preludeFiles(buildConfig)
Expand All @@ -484,45 +488,57 @@ export async function saveLibFiles(
) {
verboseLog(`not saving files in ${libpath} (source build)`)
} else {
await mkdirp(libpath)
if (!existsSync(libpath))
await mkdirp(libpath)

verboseLog(`saving lib files in ${libpath}`)
for (const fn of Object.keys(prelude)) {
const fnpath = join(pref, fn)
await mkdirp(dirname(fnpath))
const ex = await readFile(fnpath, "utf-8").then(
r => r,
_ => null
)
if (prelude[fn] != ex) await writeFile(fnpath, prelude[fn])
if (!existsSync(libpath))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't sneak in unrelated changes.

await mkdirp(dirname(fnpath))

const ex = readFileSync(fnpath, { encoding: "utf-8" })

if (prelude[fn] != ex) writeFileSync(fnpath, prelude[fn])
}
}

// generate constants for non-catalog services
const customServices =
buildConfig.services.filter(srv => srv.catalog !== undefined) || []
// generate source files
await Promise.all(["ts", "c"].map(async(lang) => {
await Promise.all(["ts", "c"].map(async (lang) => {
const converter = converters()[lang]
let constants = ""
for (const srv of customServices) {
constants += converter(srv) + "\n"
}
const dir = join(pref, GENDIR, lang)
await mkdirp(dir)
return writeFile(join(dir, `constants.${lang}`), constants, {
if (!existsSync(dir))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated changes, move to differfent PR

await mkdirp(dir)

if (existsSync(join(dir, `constants.${lang}`)))
return

await writeFile(join(dir, `constants.${lang}`), constants, {
encoding: "utf-8",
})
}))
// json specs
{
const dir = join(pref, GENDIR)
await mkdirp(dir)
if (!existsSync(dir))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated changes, move to different PR

await mkdirp(dir)

if (existsSync(join(dir, `services.json`)))
return

await writeFile(
join(dir, `services.json`),
JSON.stringify(customServices, null, 2),
{
encoding: "utf-8",
}
},
)
}
}
Expand Down Expand Up @@ -562,9 +578,9 @@ async function buildOnce(file: string, options: BuildOptions) {
const { sizes, functions } = dbg
log(
" " +
Object.keys(sizes)
.map(name => `${name}: ${prettySize(sizes[name])}`)
.join(", ")
Object.keys(sizes)
.map(name => `${name}: ${prettySize(sizes[name])}`)
.join(", "),
)
log(` functions:`)
const resolver = SrcMapResolver.from(dbg)
Expand All @@ -573,7 +589,7 @@ async function buildOnce(file: string, options: BuildOptions) {
.forEach(fn => {
log(` ${fn.name} (${prettySize(fn.size)})`)
fn.users.forEach(user =>
debug(` <-- ${resolver.posToString(user[0])}`)
debug(` <-- ${resolver.posToString(user[0])}`),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this , added by prettier? it kind of add noise to the PR

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, must be prettier. Do you want to remove it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in general this kind of formatting changes really add noise to a PR and makes the review harder. If you have user settings overriding the repo .prettierrc file, you should disable them.

)
})
}
Expand Down
3 changes: 2 additions & 1 deletion cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { dcfg } from "./dcfg"
import {
incVerbose,
setConsoleColors,
setDeveloperMode,
setDeveloperMode, setInteractiveMode,
setQuiet,
verboseLog,
} from "./command"
Expand Down Expand Up @@ -429,6 +429,7 @@ export async function mainCli() {
.action(binPatch)

program.on("option:quiet", () => setQuiet(true))
program.on("option:disable-interactive-mode", () => setInteractiveMode(false))
program.on("option:verbose", incVerbose)
program.on("option:no-colors", () => setConsoleColors(false))
program.on("option:dev", () => {
Expand Down
5 changes: 5 additions & 0 deletions cli/src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export function logToConsole(priority: LoggerPriority, message: string) {

export let isVerbose = 0
export let isQuiet = false
export let isInteractiveMode = true

export function incVerbose() {
isVerbose++
Expand All @@ -80,6 +81,10 @@ export function setQuiet(v: boolean) {
isQuiet = v
}

export function setInteractiveMode(v: boolean) {
isInteractiveMode = v
}

export function verboseLog(msg: string) {
if (isVerbose) console.debug(wrapColor(90, msg))
}
4 changes: 3 additions & 1 deletion cli/src/devtools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export async function devtools(
const traceFd = options.trace ? await open(options.trace, "w") : null

// passive bus to sniff packets
const transports = createTransports(options)
const transports = await createTransports(options)
const bus = new JDBus(transports, {
client: false,
disableRoleManager: true,
Expand Down Expand Up @@ -430,6 +430,8 @@ async function rebuild(args: BuildReqArgs) {
opts.verify = false
opts.quiet = true

await compileFile(args.filename, opts);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we compiling twice now?


const res = await compileFile(args.filename, opts)

let deployStatus = ""
Expand Down
Loading
Loading