镜像自地址
https://github.com/JGZYES/ParlzPackageManger.git
已同步 2026-09-11 08:52:45 +08:00
v0.1.8: UTF-8 console (fix chinese mojibake); -p <path> = flat deploy (exe directly in dir, no root/bin layer); version inject
这个提交包含在:
+11
@@ -16,6 +16,9 @@
|
|||||||
* Mirrors: ~/.pmm/mirror.ini | mirror.conf
|
* Mirrors: ~/.pmm/mirror.ini | mirror.conf
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -320,6 +323,10 @@ static int consume_drive_flag(int argc, char **argv) {
|
|||||||
r++; /* consume the drive arg too */
|
r++; /* consume the drive arg too */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
/* -p <exact path>: install under this full address */
|
||||||
|
pmm_set_install_path(nxt);
|
||||||
|
r++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
argv[w++] = argv[r];
|
argv[w++] = argv[r];
|
||||||
}
|
}
|
||||||
@@ -327,6 +334,10 @@ static int consume_drive_flag(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(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; }
|
if (argc < 2) { print_help(); return 0; }
|
||||||
pmm_set_self_path(argv[0]);
|
pmm_set_self_path(argv[0]);
|
||||||
argc = consume_drive_flag(argc, argv);
|
argc = consume_drive_flag(argc, argv);
|
||||||
|
|||||||
@@ -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);
|
pmm_config_dir(home, sizeof(home) - 32);
|
||||||
snprintf(db, dbs, "%s/installed", home);
|
snprintf(db, dbs, "%s/installed", home);
|
||||||
mkdir_p(db);
|
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);
|
mkdir_p(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,6 +314,44 @@ static void chdir_restore(void) {
|
|||||||
if (saved_cwd[0]) CHDIR(saved_cwd);
|
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) {
|
int pdm_info(const char *pdmfile) {
|
||||||
printf("pdm: %s\n", base_name(pdmfile));
|
printf("pdm: %s\n", base_name(pdmfile));
|
||||||
/* Copy into the pm dir + chdir, then use relative names (works with both
|
/* Copy into the pm dir + chdir, then use relative names (works with both
|
||||||
@@ -338,8 +377,12 @@ int pdm_install_file(const char *pdmfile) {
|
|||||||
}
|
}
|
||||||
char home[1024], db[1024], root[1024], cmd[2600];
|
char home[1024], db[1024], root[1024], cmd[2600];
|
||||||
pmm_config_dir(home, sizeof(home));
|
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);
|
snprintf(db, sizeof(db), "%s/installed", home);
|
||||||
mkdir_p(db);
|
mkdir_p(db);
|
||||||
|
if (flat)
|
||||||
|
snprintf(root, sizeof(root), "%s", home);
|
||||||
|
else
|
||||||
snprintf(root, sizeof(root), "%s/root", home);
|
snprintf(root, sizeof(root), "%s/root", home);
|
||||||
mkdir_p(root);
|
mkdir_p(root);
|
||||||
|
|
||||||
@@ -404,13 +447,19 @@ int pdm_install_file(const char *pdmfile) {
|
|||||||
chdir_restore(); remove(tmpname); return -1;
|
chdir_restore(); remove(tmpname); return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* extract data into root */
|
/* extract data into root (relative target: cwd is already the pm dir) */
|
||||||
snprintf(cmd, sizeof(cmd), "tar -xzf \"%s/data.tar.gz\" -C \"root\"", stage);
|
const char *tgt = flat ? "." : "root";
|
||||||
|
snprintf(cmd, sizeof(cmd), "tar -xzf \"%s/data.tar.gz\" -C \"%s\"", stage, tgt);
|
||||||
if (system(cmd) != 0) {
|
if (system(cmd) != 0) {
|
||||||
fprintf(stderr, "pdm: data extraction failed\n");
|
fprintf(stderr, "pdm: data extraction failed\n");
|
||||||
chdir_restore(); remove(tmpname); return -1;
|
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 */
|
/* record file list + control in db */
|
||||||
snprintf(cmd, sizeof(cmd), "%s/%s.info", db, pkg);
|
snprintf(cmd, sizeof(cmd), "%s/%s.info", db, pkg);
|
||||||
FILE *dbf = fopen(cmd, "wb"); /* binary: keep \n, avoid Windows CRLF translation */
|
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);
|
FILE *tf = PMM_POPEN_READ(ltcmd);
|
||||||
if (tf) {
|
if (tf) {
|
||||||
char ln[2048];
|
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);
|
fputs(ln, dbf);
|
||||||
|
}
|
||||||
PMM_PCLOSE_READ(tf);
|
PMM_PCLOSE_READ(tf);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "pdm: warning: could not record file list\n");
|
fprintf(stderr, "pdm: warning: could not record file list\n");
|
||||||
|
|||||||
@@ -98,10 +98,11 @@ static const char *home_dir(void) {
|
|||||||
return (h && *h) ? h : ".";
|
return (h && *h) ? h : ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- install-drive override (e.g. "pmm install x -pd" -> D:\.pmm) ----
|
/* ---- install-location overrides ----
|
||||||
* The chosen drive is persisted in the always-reachable home dir so later
|
* Either a drive letter ("D" -> D:\.pmm) via -p<drive>, or an exact path
|
||||||
* commands remember it without needing the flag again. */
|
* ("D:\apps\pmm" / "/opt/pmm") via -p <path>. The path override wins. */
|
||||||
static char g_drive[4] = ""; /* "D", or "" = use home */
|
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) {
|
static const char *drive_state_path(char *buf, size_t size) {
|
||||||
snprintf(buf, size, "%s/.pmm/install-drive", home_dir());
|
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 */
|
if (c < 'A' || c > 'Z') return; /* only a single A-Z drive letter */
|
||||||
g_drive[0] = c;
|
g_drive[0] = c;
|
||||||
g_drive[1] = '\0';
|
g_drive[1] = '\0';
|
||||||
/* persist so it becomes the default for later runs */
|
|
||||||
char state[1024];
|
char state[1024];
|
||||||
drive_state_path(state, sizeof(state));
|
drive_state_path(state, sizeof(state));
|
||||||
char dir[1024];
|
char dir[1024];
|
||||||
@@ -125,6 +125,17 @@ void pmm_set_install_drive(const char *letter) {
|
|||||||
printf("pmm: install drive set to %c:\n", c);
|
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 >
|
/* Resolve the .pmm base dir: explicit drive override > persisted drive >
|
||||||
* home/.pmm (when that drive is picked) > DEFAULT = D:\.pmm.
|
* home/.pmm (when that drive is picked) > DEFAULT = D:\.pmm.
|
||||||
* Defaulting to D:\ spares the C: drive (user's primary diskspace concern);
|
* 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) {
|
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] = "";
|
char drive[4] = "";
|
||||||
if (g_drive[0]) {
|
if (g_drive[0]) {
|
||||||
drive[0] = g_drive[0];
|
drive[0] = g_drive[0];
|
||||||
@@ -269,7 +284,8 @@ void pmm_add_to_path(void) {
|
|||||||
char home[1024];
|
char home[1024];
|
||||||
pmm_config_dir(home, sizeof(home));
|
pmm_config_dir(home, sizeof(home));
|
||||||
char base[1024];
|
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 */
|
/* collect dirs: ~/.pmm/bin, ~/.pmm/root, and root subdirs holding executables */
|
||||||
char list[160][1200];
|
char list[160][1200];
|
||||||
|
|||||||
@@ -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. */
|
* "/opt/pmm"). Config/cache/bin/root all live under it. Empty clears back. */
|
||||||
void pmm_set_install_path(const char *path);
|
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. */
|
/* File-association record written to the per-user registry on install. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *progid; /* e.g. "Node.JSFile" */
|
const char *progid; /* e.g. "Node.JSFile" */
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户