v0.1.8: UTF-8 console (fix chinese mojibake); -p <path> = flat deploy (exe directly in dir, no root/bin layer); version inject

这个提交包含在:
JGZYES
2026-08-31 22:21:45 +08:00
父节点 4cab1dfce9
当前提交 aa2d2a487c
修改 4 个文件,包含 97 行新增11 行删除
+11
查看文件
@@ -16,6 +16,9 @@
* Mirrors: ~/.pmm/mirror.ini | mirror.conf
*/
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#endif
#include <stdlib.h>
#include <string.h>
@@ -320,6 +323,10 @@ static int consume_drive_flag(int argc, char **argv) {
r++; /* consume the drive arg too */
continue;
}
/* -p <exact path>: install under this full address */
pmm_set_install_path(nxt);
r++;
continue;
}
argv[w++] = argv[r];
}
@@ -327,6 +334,10 @@ static int consume_drive_flag(int argc, char **argv) {
}
int main(int argc, char **argv) {
#ifdef _WIN32
SetConsoleOutputCP(CP_UTF8); /* UTF-8 output so Chinese help/version isn't mojibake */
setvbuf(stdout, NULL, _IONBF, 0);
#endif
if (argc < 2) { print_help(); return 0; }
pmm_set_self_path(argv[0]);
argc = consume_drive_flag(argc, argv);
+60 -5
查看文件
@@ -202,7 +202,8 @@ static void db_dirs(char *db, size_t dbs, char *root, size_t roots) {
pmm_config_dir(home, sizeof(home) - 32);
snprintf(db, dbs, "%s/installed", home);
mkdir_p(db);
snprintf(root, roots, "%s/root", home);
if (pmm_flat_mode()) snprintf(root, roots, "%s", home); /* -p <path> */
else snprintf(root, roots, "%s/root", home);
mkdir_p(root);
}
@@ -313,6 +314,44 @@ static void chdir_restore(void) {
if (saved_cwd[0]) CHDIR(saved_cwd);
}
/* Move everything under <dir>/bin up into <dir>, then remove bin/. (C-level, so
* it works on Windows cmd too where `mv` doesn't exist.) */
static void flatten_bin(const char *dir) {
char bindir[1200];
snprintf(bindir, sizeof(bindir), "%s/%s", dir, "bin");
#ifdef _WIN32
char patt[1300];
snprintf(patt, sizeof(patt), "%s\\*", bindir);
struct _finddata_t fd;
intptr_t h = _findfirst(patt, &fd);
if (h != -1) {
do {
if (strcmp(fd.name, ".") == 0 || strcmp(fd.name, "..") == 0) continue;
char src[1400], dst[1400];
snprintf(src, sizeof(src), "%s\\%s", bindir, fd.name);
snprintf(dst, sizeof(dst), "%s\\%s", dir, fd.name);
rename(src, dst);
} while (_findnext(h, &fd) == 0);
_findclose(h);
}
RMDIR(bindir);
#else
DIR *d = opendir(bindir);
if (d) {
struct dirent *e;
while ((e = readdir(d)) != NULL) {
if (e->d_name[0] == '.') continue;
char src[1400], dst[1400];
snprintf(src, sizeof(src), "%s/%s", bindir, e->d_name);
snprintf(dst, sizeof(dst), "%s/%s", dir, e->d_name);
rename(src, dst);
}
closedir(d);
rmdir(bindir);
}
#endif
}
int pdm_info(const char *pdmfile) {
printf("pdm: %s\n", base_name(pdmfile));
/* Copy into the pm dir + chdir, then use relative names (works with both
@@ -338,9 +377,13 @@ int pdm_install_file(const char *pdmfile) {
}
char home[1024], db[1024], root[1024], cmd[2600];
pmm_config_dir(home, sizeof(home));
int flat = pmm_flat_mode(); /* -p <path>: deploy directly into that dir */
snprintf(db, sizeof(db), "%s/installed", home);
mkdir_p(db);
snprintf(root, sizeof(root), "%s/root", home);
if (flat)
snprintf(root, sizeof(root), "%s", home);
else
snprintf(root, sizeof(root), "%s/root", home);
mkdir_p(root);
/* Copy the package into the PM dir, chdir there, and run tar with ONLY
@@ -404,13 +447,19 @@ int pdm_install_file(const char *pdmfile) {
chdir_restore(); remove(tmpname); return -1;
}
/* extract data into root */
snprintf(cmd, sizeof(cmd), "tar -xzf \"%s/data.tar.gz\" -C \"root\"", stage);
/* extract data into root (relative target: cwd is already the pm dir) */
const char *tgt = flat ? "." : "root";
snprintf(cmd, sizeof(cmd), "tar -xzf \"%s/data.tar.gz\" -C \"%s\"", stage, tgt);
if (system(cmd) != 0) {
fprintf(stderr, "pdm: data extraction failed\n");
chdir_restore(); remove(tmpname); return -1;
}
/* flat mode (-p <path>): move bin/* up into the address itself, drop bin/ */
if (flat) {
flatten_bin("."); /* cwd = the install address in flat mode */
}
/* record file list + control in db */
snprintf(cmd, sizeof(cmd), "%s/%s.info", db, pkg);
FILE *dbf = fopen(cmd, "wb"); /* binary: keep \n, avoid Windows CRLF translation */
@@ -423,8 +472,14 @@ int pdm_install_file(const char *pdmfile) {
FILE *tf = PMM_POPEN_READ(ltcmd);
if (tf) {
char ln[2048];
while (fgets(ln, sizeof(ln), tf))
while (fgets(ln, sizeof(ln), tf)) {
if (flat) { /* reflection of the flatten: strip a leading bin/ */
const char *q = ln;
while (*q==' '||*q=='\t') q++;
if (q[0]=='.'&&q[1]=='/'&&strncasecmp(q+2,"bin/",4)==0) { ln[0]='\0'; continue; }
}
fputs(ln, dbf);
}
PMM_PCLOSE_READ(tf);
} else {
fprintf(stderr, "pdm: warning: could not record file list\n");
+22 -6
查看文件
@@ -98,10 +98,11 @@ static const char *home_dir(void) {
return (h && *h) ? h : ".";
}
/* ---- install-drive override (e.g. "pmm install x -pd" -> D:\.pmm) ----
* The chosen drive is persisted in the always-reachable home dir so later
* commands remember it without needing the flag again. */
static char g_drive[4] = ""; /* "D", or "" = use home */
/* ---- install-location overrides ----
* Either a drive letter ("D" -> D:\.pmm) via -p<drive>, or an exact path
* ("D:\apps\pmm" / "/opt/pmm") via -p <path>. The path override wins. */
static char g_drive[4] = ""; /* "D", or "" = use home */
static char g_base_path[1024] = ""; /* exact install base, or "" */
static const char *drive_state_path(char *buf, size_t size) {
snprintf(buf, size, "%s/.pmm/install-drive", home_dir());
@@ -114,7 +115,6 @@ void pmm_set_install_drive(const char *letter) {
if (c < 'A' || c > 'Z') return; /* only a single A-Z drive letter */
g_drive[0] = c;
g_drive[1] = '\0';
/* persist so it becomes the default for later runs */
char state[1024];
drive_state_path(state, sizeof(state));
char dir[1024];
@@ -125,6 +125,17 @@ void pmm_set_install_drive(const char *letter) {
printf("pmm: install drive set to %c:\n", c);
}
void pmm_set_install_path(const char *path) {
if (!path || !*path) { g_base_path[0] = '\0'; return; }
snprintf(g_base_path, sizeof(g_base_path), "%s", path);
/* strip trailing slashes */
size_t l = strlen(g_base_path);
while (l > 1 && (g_base_path[l-1] == '/' || g_base_path[l-1] == '\\')) g_base_path[--l] = '\0';
mkdir_p(g_base_path);
printf("pmm: install path set to %s\n", g_base_path);
}
int pmm_flat_mode(void) { return g_base_path[0] ? 1 : 0; }
/* Resolve the .pmm base dir: explicit drive override > persisted drive >
* home/.pmm (when that drive is picked) > DEFAULT = D:\.pmm.
* Defaulting to D:\ spares the C: drive (user's primary diskspace concern);
@@ -137,6 +148,10 @@ static char home_drive_letter(void) {
}
static const char *pmm_base_dir(char *buf, size_t size) {
if (g_base_path[0]) { /* -p <exact path> */
snprintf(buf, size, "%s", g_base_path);
return buf;
}
char drive[4] = "";
if (g_drive[0]) {
drive[0] = g_drive[0];
@@ -269,7 +284,8 @@ void pmm_add_to_path(void) {
char home[1024];
pmm_config_dir(home, sizeof(home));
char base[1024];
snprintf(base, sizeof(base), "%s/root", home);
if (pmm_flat_mode()) snprintf(base, sizeof(base), "%s", home); /* -p <path> */
else snprintf(base, sizeof(base), "%s/root", home);
/* collect dirs: ~/.pmm/bin, ~/.pmm/root, and root subdirs holding executables */
char list[160][1200];
+4
查看文件
@@ -17,6 +17,10 @@ void pmm_set_install_drive(const char *letter);
* "/opt/pmm"). Config/cache/bin/root all live under it. Empty clears back. */
void pmm_set_install_path(const char *path);
/* 1 if an exact install path was given via -p <path>: packages deploy directly
* into that directory (files flattened), without a root/bin sub-folder. */
int pmm_flat_mode(void);
/* File-association record written to the per-user registry on install. */
typedef struct {
const char *progid; /* e.g. "Node.JSFile" */