Skip to content

Commit 8d3c887

Browse files
pkg info command
1 parent 70b24db commit 8d3c887

5 files changed

Lines changed: 140 additions & 5 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ollieos",
3-
"version": "1.1.2",
3+
"version": "1.1.3",
44
"description": "",
55
"private": true,
66
"main": "server.js",

src/filesystem.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ export abstract class AbstractFileSystem {
374374
return this.join(effective_cwd, path);
375375
}
376376

377+
// TODO: support vargs for path joining multiple parts
377378
join(base_dir: string, path: string): string {
378379
// drop trailing /
379380
if (base_dir.endsWith("/")) {

src/programs/pkg/index.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {ANSI} from "../../term_ctl";
55
import type {Program} from "../../types";
66
import type {AbstractFileSystem} from "../../filesystem";
77
import {list_subcommand} from "./list";
8+
import {info_subcommand} from "./info";
89

910

1011
const REPO_URL = "https://ollieg.codes/pkg_repo";
@@ -14,6 +15,8 @@ const repo_url_obj = new URL(REPO_URL);
1415
const GRAPH_DIR = "/var/lib/pkg";
1516
const GRAPH_PATH = GRAPH_DIR + "/graph.json";
1617

18+
const BIN_DIR = "/usr/bin";
19+
1720
const append_url_pathnames = (url: URL, pathnames: string[]) => {
1821
const new_url = new URL(url.toString());
1922
let urlpath = new_url.pathname;
@@ -360,6 +363,11 @@ export const graph_query = {
360363
// lists all packages that are not installed as top level and have no dependents
361364
list_unused_pkgs: () => {
362365
return Object.keys(graph).filter((pkg) => !graph[pkg].top_level && graph[pkg].dependents.size === 0);
366+
},
367+
368+
get_file_path_in_pkg_bin: (fs: AbstractFileSystem, pkg: string, filepath: string) => {
369+
const pkg_dir = fs.join(BIN_DIR, pkg);
370+
return fs.join(pkg_dir, filepath);
363371
}
364372
}
365373

@@ -448,8 +456,7 @@ export default {
448456
case "list":
449457
return await list_subcommand(data);
450458
case "info":
451-
term.writeln(`${PREFABS.error}Not implemented yet.${STYLE.reset_all}`);
452-
break;
459+
return await info_subcommand(data);
453460
case "read":
454461
term.writeln(`${PREFABS.error}Not implemented yet.${STYLE.reset_all}`);
455462
break;

src/programs/pkg/info.ts

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import {ANSI, NEWLINE} from "../../term_ctl";
2+
import type { WrappedTerminal } from "../../term_ctl";
3+
import type { ProgramMainData } from "../../types"
4+
import {graph_query, repo_query} from "./index";
5+
6+
// extract from ANSI to make code less verbose
7+
const { STYLE, PREFABS } = ANSI;
8+
9+
interface PkgInfo {
10+
description?: string;
11+
author?: string;
12+
license?: string;
13+
homepage_url?: string;
14+
repo_url?: string;
15+
long_desc?: string;
16+
}
17+
18+
const print_info = (term: WrappedTerminal, pkg_name: string, pkg_version: string, pkg_data: PkgInfo, installed: boolean) => {
19+
term.write(NEWLINE);
20+
21+
term.writeln(`Package: ${STYLE.bold}${pkg_name}${STYLE.no_bold_or_dim}`);
22+
term.writeln(`Version: ${STYLE.bold}${pkg_version}${STYLE.no_bold_or_dim}`);
23+
term.writeln(`Description: ${pkg_data.description || "No description provided."}`);
24+
term.writeln(`Author: ${pkg_data.author || "Unknown"}`);
25+
term.writeln(`License: ${pkg_data.license || "Unknown"}`);
26+
term.writeln(`Installed: ${STYLE.bold}${installed ? "Yes" : "No"}${STYLE.no_bold_or_dim}`);
27+
28+
if (pkg_data.homepage_url) {
29+
term.writeln(`Homepage: ${pkg_data.homepage_url}`);
30+
}
31+
32+
if (pkg_data.repo_url) {
33+
term.writeln(`Repository: ${pkg_data.repo_url}`);
34+
}
35+
36+
if (pkg_data.long_desc) {
37+
term.write(NEWLINE);
38+
term.writeln(`Long description available. Use ${PREFABS.program_name}pkg${STYLE.reset_all + STYLE.italic} read${STYLE.reset_all} ${pkg_name} to read it.`);
39+
}
40+
}
41+
42+
export const info_subcommand = async (data: ProgramMainData) => {
43+
// extract from data to make code less verbose
44+
const { args, term } = data;
45+
46+
// remove subcommand name
47+
args.shift();
48+
49+
// check for presence of -r flag
50+
let always_fetch = false;
51+
if (args[0] === "-r") {
52+
always_fetch = true;
53+
args.shift();
54+
}
55+
56+
// check for package name
57+
if (args.length === 0) {
58+
term.writeln(`${PREFABS.error}Missing package name.`);
59+
term.writeln(`Try 'pkg -h' for more information.${STYLE.reset_all}`);
60+
return 1;
61+
}
62+
63+
const pkg_at_version = args[0];
64+
65+
// if in the format of pkg@version, split it up
66+
const pkg_split = pkg_at_version.split("@");
67+
if (pkg_split.length > 2) {
68+
term.writeln(`${PREFABS.error}Invalid package name: ${pkg_at_version}`);
69+
term.writeln(`Try 'pkg -h' for more information.${STYLE.reset_all}`);
70+
return 2;
71+
}
72+
73+
const pkg_name = pkg_split[0];
74+
let pkg_version = pkg_split[1];
75+
76+
// if no version specified, use what's installed
77+
// if not installed, fetch latest from repo
78+
// note that version doesnt really matter other than as a test whether the version exists and installed locally, as pkg.json is shared across versions
79+
if (!pkg_version) {
80+
const installed_pkg = graph_query.get_pkg_version(pkg_name);
81+
if (installed_pkg && !always_fetch) {
82+
pkg_version = installed_pkg;
83+
} else {
84+
const pkg_json = await repo_query.get_pkg_json(pkg_name);
85+
if (!pkg_json) {
86+
term.writeln(`${PREFABS.error}Package not found: ${pkg_name}`);
87+
term.writeln(`Try 'pkg -h' for more information.${STYLE.reset_all}`);
88+
return 3;
89+
}
90+
91+
pkg_version = pkg_json.latest_version;
92+
}
93+
}
94+
95+
const installed_pkg = graph_query.get_pkg_version(pkg_name);
96+
const requested_version_installed = installed_pkg === pkg_version;
97+
98+
const fs = term.get_fs();
99+
100+
if (!always_fetch && requested_version_installed) {
101+
const pkg_json_path = graph_query.get_file_path_in_pkg_bin(fs, pkg_name, "pkg.json");
102+
103+
if (!fs.exists(pkg_json_path)) {
104+
// shouldnt happen, but just in case
105+
console.error(`Invalid pkg.json path: ${pkg_json_path}`);
106+
term.writeln(`${PREFABS.error}Error reading package files for ${pkg_name}`);
107+
return 3;
108+
}
109+
110+
const pkg_json = fs.read_file(pkg_json_path) as string;
111+
const pkg_data = JSON.parse(pkg_json);
112+
113+
print_info(term, pkg_name, pkg_version, pkg_data, true);
114+
return 0;
115+
}
116+
117+
// fetch package data from repo
118+
const pkg_data = await repo_query.get_pkg_json(pkg_name);
119+
if (!pkg_data) {
120+
term.writeln(`${PREFABS.error}Package not found: ${pkg_name}`);
121+
term.writeln(`Try 'pkg -h' for more information.${STYLE.reset_all}`);
122+
return 3;
123+
}
124+
125+
print_info(term, pkg_name, pkg_version, pkg_data, requested_version_installed);
126+
return 0;
127+
}

0 commit comments

Comments
 (0)