Skip to content

Commit

Permalink
Merge pull request #148 from unyt-org/fix-git-install-check
Browse files Browse the repository at this point in the history
Fix #146
  • Loading branch information
benStre authored Jun 8, 2024
2 parents 0c80171 + 727c13c commit 46743be
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 49 deletions.
4 changes: 2 additions & 2 deletions run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ import { applyPlugins } from "./src/app/config-files.ts";
// login flow
if (login) await triggerLogin();
// init
if (init) {
if (init!=undefined) {
if (rootPath) {
logger.error("A UIX Project already exists in this location");
Deno.exit(1);
}
else await initBaseProject();
else await initBaseProject(init);
}

// allow unyt.org diagnostics?
Expand Down
21 changes: 14 additions & 7 deletions src/app/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ import { Path } from "datex-core-legacy/utils/path.ts";
import { getExistingFile } from "../utils/file-utils.ts";
import { ESCAPE_SEQUENCES } from "datex-core-legacy/utils/logger.ts";
import { version as UIX_VERSION } from "../utils/version.ts";
import { _updateProjectRootURL } from "datex-core-legacy/utils/global_values.ts"

export const command_line_options = new CommandLineOptions("UIX", "Fullstack Web Framework with DATEX Integration.\nVisit https://unyt.org/uix for more information", "../RUN.md");

export const path = command_line_options.option("path", {collectNotPrefixedArgs: true, type:"string", description: "The root path for the UIX app (parent directory for app.dx and deno.json)"});
const _path = new Path(path??'./', 'file://' + Deno.cwd() + '/');
export let path = command_line_options.option("path", {collectNotPrefixedArgs: true, type:"string", description: "The root path for the UIX app (parent directory for app.dx and deno.json)"});
let _path: Path.File;
updatePath(path);

export function updatePath(newPath?: string) {
path = newPath;
_path = new Path(path??'./', 'file://' + Deno.cwd() + '/');
}

export const watch_backend = command_line_options.option("watch-backend", {aliases:["b"], type:"boolean", default: false, description: "Restart the backend deno process when backend files are modified"});
export const live = command_line_options.option("live", {aliases:["l"], type:"boolean", default: false, description: "Automatically reload connected browsers tabs when files are modified and enable automatic backend restarts"});
Expand All @@ -22,7 +29,7 @@ export const allowAll = command_line_options.option("allow-all", {type:"boolean"
export const allowNone = command_line_options.option("allow-none", {type:"boolean", default: false, aliases:["n"], description: "Automatically decline all dialog"});

export const login = command_line_options.option("login", {type:"boolean", description: "Show login dialog"});
export const init = command_line_options.option("init", {type:"boolean", description: "Inititialize a new UIX project"});
export const init = command_line_options.option("init", {type:"string", description: "Inititialize a new UIX project"});

// TODO: aliases:["p"], -p xxxx not working
export const port = command_line_options.option("port", {default: 80, type:"number", description: "The port for the HTTP server"});
Expand Down Expand Up @@ -57,16 +64,16 @@ if (version) {



export let rootPath:Path.File;

updateRootPath(CommandLineOptions.collecting||init);
export let rootPath:Path.File;
await updateRootPath(CommandLineOptions.collecting||init!=null);

export function updateRootPath(allowFail = false) {
export async function updateRootPath(allowFail = false) {
const config_path = getExistingFile(_path, './app.dx', './app.json', './src/app.dx', './src/app.json');

if (!config_path && !allowFail) {
throw "Could not find an app.dx or app.json config file in " + _path.normal_pathname
}

rootPath = (config_path ? new Path(config_path).parent_dir : null) as Path.File;
if (rootPath) await _updateProjectRootURL(rootPath);
}
2 changes: 1 addition & 1 deletion src/app/config-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export async function getAppOptions(root_path:URL) {
}
config = Object.fromEntries(Datex.DatexObject.entries(<Record<string, unknown>>raw_config));
}
else throw "Could not find an app.dx or app.json config file in " + new Path(root_path).normal_pathname
else throw "Could not find an app.dx or app.json config file in " + new Path(root_path).normal_pathname;

// overwrite --import-map path
if (arg_import_map) config.import_map_path = arg_import_map;
Expand Down
4 changes: 1 addition & 3 deletions src/app/module-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ export const eternalExts = [
'mjs',
].map(x => 'eternal.'+x);

const cachePath = new Path(cache_path);

export async function createProxyImports(options: normalizedAppOptions, baseURL: URL, denoConfigPath: URL) {
const proxyImportMapPath = new Path("./importmap.lock.json", cache_path)
const proxyImportMap = options.import_map.getMoved(proxyImportMapPath, false);
Expand All @@ -42,7 +40,7 @@ export async function createProxyImports(options: normalizedAppOptions, baseURL:
for await (const e of walk!(new Path(baseURL).normal_pathname, {includeDirs: false, exts: eternalExts.map(e => "."+e)})) {
const path = Path.File(e.path);

if (path.isChildOf(cachePath)) continue;
if (path.isChildOf(cache_path)) continue;
const proxyPath = await createEternalProxyFile(path, baseURL);
addEternalFileImportMapScope(path, proxyPath, proxyImportMap, options);
}
Expand Down
18 changes: 14 additions & 4 deletions src/runners/run-local.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { cache_path, ptr_cache_path } from "datex-core-legacy/runtime/cache_path.ts";
import { clear } from "../app/args.ts";
import { clear, path, rootPath } from "../app/args.ts";
import type { normalizedAppOptions } from "../app/options.ts";
import { getExistingFile } from "../utils/file-utils.ts";
import { Path } from "datex-core-legacy/utils/path.ts";
import { logger, runParams } from "./runner.ts";
import { verboseArg } from "datex-core-legacy/utils/logger.ts";


export const CSI = '\u001b['
Expand Down Expand Up @@ -53,6 +54,8 @@ export async function runLocal(params: runParams, root_path: URL, options: norma
"-Aq"
];

const args = [...Deno.args];

if (params.enableTLS) cmd.push("--unsafely-ignore-certificate-errors=localhost");

if (params.reload) {
Expand All @@ -75,6 +78,11 @@ export async function runLocal(params: runParams, root_path: URL, options: norma
config_params.push("--import-map", options.import_map.path?.is_web ? options.import_map.path.toString() : options.import_map.path?.normal_pathname)
}

// pass different path (required when starting for the first time with uix --init)
if (rootPath.normal_pathname != new Path('file://' + Deno.cwd() + '/').normal_pathname) {
args.push("--path", rootPath.normal_pathname)
}

let process: Deno.ChildProcess;

// explicitly kill child process to trigger SIG event on child process
Expand Down Expand Up @@ -107,13 +115,14 @@ export async function runLocal(params: runParams, root_path: URL, options: norma
let isClearingState = clear;
let stateCleared = false;

const args = [...Deno.args];

await run();

async function run() {
await Deno.stdout.write(new TextEncoder().encode(CTRLSEQ.CLEAR_SCREEN));
await Deno.stdout.write(new TextEncoder().encode(CTRLSEQ.HOME));
if (!verboseArg) {
await Deno.stdout.write(new TextEncoder().encode(CTRLSEQ.CLEAR_SCREEN));
await Deno.stdout.write(new TextEncoder().encode(CTRLSEQ.HOME));
}

if (stateCleared) {
stateCleared = false;
Expand Down Expand Up @@ -146,6 +155,7 @@ export async function runLocal(params: runParams, root_path: URL, options: norma
...args,
]
})

process = command.spawn();

// detach, continues in background
Expand Down
8 changes: 8 additions & 0 deletions src/utils/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ const CMD = {
GET_STATUS: 'git status'
} as const;

export function isGitInstalled(): boolean {
try {
return (new Deno.Command("git", { args: ["--version"] }).outputSync().success);
} catch {
return false;
}
}

export class GitRepo {

#origin!: string
Expand Down
97 changes: 65 additions & 32 deletions src/utils/init-base-project.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,80 @@
import { path, updateRootPath } from "../app/args.ts";
import { ESCAPE_SEQUENCES } from "datex-core-legacy/datex_all.ts";
import { path, updatePath, updateRootPath } from "../app/args.ts";
import { isGitInstalled } from "./git.ts";
import { logger } from "./global-values.ts";
import { Path } from "datex-core-legacy/utils/path.ts";
import process from "node:process";

export async function initBaseProject() {
export async function initBaseProject(name?: string) {

if (!isGitInstalled()) {
logger.error(`Unable to find git executable in PATH. Please install Git before retrying (https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)`);
Deno.exit(1);
}

const gitRepo = "https://github.com/unyt-org/uix-base-project.git"
const rootPath = new Path(path??'./', 'file://' + Deno.cwd() + '/');
const cwd = new Path(path??'./', 'file://' + Deno.cwd() + '/');
let projectName: string|undefined = undefined;
let projectPath: Path;

if (rootPath.getChildPath(".git").fs_exists) {
logger.error(`Git repository already exist in this location`);
Deno.exit(1);
}

console.log("Initializing new UIX project");

const move = rootPath.getChildPath(".datex-cache").fs_exists;
const tempDir = new Path('file://' + await Deno.makeTempDir() + '/');
if (move) {
try {
await Deno.rename(rootPath.getChildPath(".datex-cache"), tempDir.normal_pathname);
if (!name) {
while (!projectName) {
projectName = prompt(ESCAPE_SEQUENCES.BOLD+"Enter the name of the new project:"+ESCAPE_SEQUENCES.RESET)!;
}
catch {
await Deno.remove(rootPath.getChildPath(".datex-cache"), {recursive: true});
do {
name = prompt(ESCAPE_SEQUENCES.BOLD+"Enter the name of the project directory:"+ESCAPE_SEQUENCES.RESET, projectName?.toLowerCase().replace(/[^\w]/g, "-") ?? "new-project")!;
projectPath = cwd.getChildPath(name).asDir();
}
while (projectPath.fs_exists &&
(logger.error(`The directory ${projectPath.normal_pathname} already exists. Please choose a different directory.`), true)
)
}
else {
projectName = name;
projectPath = cwd.getChildPath(name).asDir();
if (projectPath.fs_exists) {
logger.error(`The directory ${projectPath.normal_pathname} already exists. Please choose a different name.`);
Deno.exit(1);
}
}

logger.success(`Initializing new UIX project "${projectName}"`);

const dxCacheDirExists = cwd.getChildPath(".datex-cache").fs_exists;
if (dxCacheDirExists) {
await Deno.remove(cwd.getChildPath(".datex-cache"), {recursive: true});
}

const clone = Deno.run({
cmd: ["git", "clone", gitRepo, rootPath.normal_pathname],
stdout: "null"
});
const cloneResult = await clone.status();

if (!cloneResult.success) {
throw new Error("Failed to clone.");
try {
const clone = Deno.run({
cmd: ["git", "clone", gitRepo, projectPath.normal_pathname],
stdout: "null"
});
if (!(await clone.status()).success)
throw new Error("Git clone failed");
} catch (error) {
logger.error(`Unable to clone repository. Please make sure that Git is correctly installed.`, error);
Deno.exit(1);
}

if (move) {
try {
await Deno.rename(tempDir.normal_pathname, rootPath.getChildPath(".datex-cache"));
}
catch {}
await Deno.remove(projectPath.getChildPath(".git"), {recursive: true});

// update app name in app.dx
const appDxContent = await Deno.readTextFile(projectPath.getChildPath("app.dx"));
const newAppDxContent = appDxContent.replace(/name:.*/, `name: "${projectName}",`);
await Deno.writeTextFile(projectPath.getChildPath("app.dx"), newAppDxContent);

try {
await Deno.run({
cwd: projectPath.normal_pathname,
cmd: ["git", "init"],
stdout: "null"
}).status();
}
catch (error) {
logger.error(`Unable to initialize git repository.`, error);
}
await Deno.remove(rootPath.getChildPath(".git"), {recursive: true});

updateRootPath();
updatePath(projectPath.normal_pathname);
await updateRootPath();
}

0 comments on commit 46743be

Please sign in to comment.