Compare commits

..

1 Commits

Author SHA1 Message Date
Jérôme Revillard 5fc77cb7ce
Merge 9443c7fb0a into 6ff74ba662 2026-04-27 08:45:14 +02:00
5 changed files with 11 additions and 21 deletions

View File

@ -68,7 +68,6 @@ Select **Yes**, then provide a source:
| Input Type | Example | | Input Type | Example |
| --------------------- | ------------------------------------------------- | | --------------------- | ------------------------------------------------- |
| HTTPS URL (any host) | `https://github.com/org/repo` | | HTTPS URL (any host) | `https://github.com/org/repo` |
| HTTP URL (any host) | `http://host/org/repo` |
| HTTPS URL with subdir | `https://github.com/org/repo/tree/main/my-module` | | HTTPS URL with subdir | `https://github.com/org/repo/tree/main/my-module` |
| SSH URL | `git@github.com:org/repo.git` | | SSH URL | `git@github.com:org/repo.git` |
| Local path | `/Users/me/projects/my-module` | | Local path | `/Users/me/projects/my-module` |

View File

@ -68,7 +68,6 @@ Chọn **Yes**, rồi nhập nguồn:
| Loại đầu vào | Ví dụ | | Loại đầu vào | Ví dụ |
| --------------------- | ------------------------------------------------- | | --------------------- | ------------------------------------------------- |
| HTTPS URL trên bất kỳ host nào | `https://github.com/org/repo` | | HTTPS URL trên bất kỳ host nào | `https://github.com/org/repo` |
| HTTP URL trên bất kỳ host nào | `http://host/org/repo` |
| HTTPS URL trỏ vào một thư mục con | `https://github.com/org/repo/tree/main/my-module` | | HTTPS URL trỏ vào một thư mục con | `https://github.com/org/repo/tree/main/my-module` |
| SSH URL | `git@github.com:org/repo.git` | | SSH URL | `git@github.com:org/repo.git` |
| Đường dẫn cục bộ | `/Users/me/projects/my-module` | | Đường dẫn cục bộ | `/Users/me/projects/my-module` |

View File

@ -68,7 +68,6 @@ Would you like to install from a custom source (Git URL or local path)?
| 输入类型 | 示例 | | 输入类型 | 示例 |
| -------- | ---- | | -------- | ---- |
| HTTPS URL任意主机 | `https://github.com/org/repo` | | HTTPS URL任意主机 | `https://github.com/org/repo` |
| HTTP URL任意主机 | `http://host/org/repo` |
| 带子目录的 HTTPS URL | `https://github.com/org/repo/tree/main/my-module` | | 带子目录的 HTTPS URL | `https://github.com/org/repo/tree/main/my-module` |
| SSH URL | `git@github.com:org/repo.git` | | SSH URL | `git@github.com:org/repo.git` |
| 本地路径 | `/Users/me/projects/my-module` | | 本地路径 | `/Users/me/projects/my-module` |

View File

@ -24,9 +24,8 @@ class CustomModuleManager {
/** /**
* Parse a user-provided source input into a structured descriptor. * Parse a user-provided source input into a structured descriptor.
* Accepts local file paths, HTTPS Git URLs, HTTP Git URLs, and SSH Git URLs. * Accepts local file paths, HTTPS Git URLs, and SSH Git URLs.
* For HTTPS/HTTP URLs with deep paths (e.g., /tree/main/subdir), extracts the subdir. * For HTTPS URLs with deep paths (e.g., /tree/main/subdir), extracts the subdir.
* The original protocol (http or https) is preserved in the returned cloneUrl.
* *
* @param {string} input - URL or local file path * @param {string} input - URL or local file path
* @returns {Object} Parsed source descriptor: * @returns {Object} Parsed source descriptor:
@ -128,11 +127,11 @@ class CustomModuleManager {
}; };
} }
// HTTPS/HTTP URL: https://host/owner/repo[/tree/branch/subdir][.git] // HTTPS URL: https://host/owner/repo[/tree/branch/subdir][.git]
const httpsMatch = trimmed.match(/^(https?):\/\/([^/]+)\/([^/]+)\/([^/.]+?)(?:\.git)?(\/.*)?$/); const httpsMatch = trimmed.match(/^https?:\/\/([^/]+)\/([^/]+)\/([^/.]+?)(?:\.git)?(\/.*)?$/);
if (httpsMatch) { if (httpsMatch) {
const [, protocol, host, owner, repo, remainder] = httpsMatch; const [, host, owner, repo, remainder] = httpsMatch;
const cloneUrl = `${protocol}://${host}/${owner}/${repo}`; const cloneUrl = `https://${host}/${owner}/${repo}`;
let subdir = null; let subdir = null;
let urlRef = null; // branch/tag extracted from /tree/<ref>/subdir let urlRef = null; // branch/tag extracted from /tree/<ref>/subdir
@ -312,7 +311,7 @@ class CustomModuleManager {
/** /**
* Clone a custom module repository to cache. * Clone a custom module repository to cache.
* Supports any Git host (GitHub, GitLab, Bitbucket, self-hosted, etc.). * Supports any Git host (GitHub, GitLab, Bitbucket, self-hosted, etc.).
* @param {string} sourceInput - Git URL (HTTPS, HTTP, or SSH) * @param {string} sourceInput - Git URL (HTTPS or SSH)
* @param {Object} [options] - Clone options * @param {Object} [options] - Clone options
* @param {boolean} [options.silent] - Suppress spinner output * @param {boolean} [options.silent] - Suppress spinner output
* @param {boolean} [options.skipInstall] - Skip npm install (for browsing before user confirms) * @param {boolean} [options.skipInstall] - Skip npm install (for browsing before user confirms)

View File

@ -200,15 +200,12 @@ class UI {
actionType = options.action; actionType = options.action;
await prompts.log.info(`Using action from command-line: ${actionType}`); await prompts.log.info(`Using action from command-line: ${actionType}`);
} else if (options.yes) { } else if (options.yes) {
// Default to quick-update if available, unless flags that require the // Default to quick-update if available, otherwise first available choice
// full update path are present (e.g. --custom-source which re-clones
// modules at a new version — quick-update skips that entirely).
if (choices.length === 0) { if (choices.length === 0) {
throw new Error('No valid actions available for this installation'); throw new Error('No valid actions available for this installation');
} }
const hasQuickUpdate = choices.some((c) => c.value === 'quick-update'); const hasQuickUpdate = choices.some((c) => c.value === 'quick-update');
const needsFullUpdate = !!options.customSource; actionType = hasQuickUpdate ? 'quick-update' : choices[0].value;
actionType = hasQuickUpdate && !needsFullUpdate ? 'quick-update' : (choices.find((c) => c.value === 'update') || choices[0]).value;
await prompts.log.info(`Non-interactive mode (--yes): defaulting to ${actionType}`); await prompts.log.info(`Non-interactive mode (--yes): defaulting to ${actionType}`);
} else { } else {
actionType = await prompts.select({ actionType = await prompts.select({
@ -244,11 +241,8 @@ class UI {
.map((m) => m.trim()) .map((m) => m.trim())
.filter(Boolean); .filter(Boolean);
await prompts.log.info(`Using modules from command-line: ${selectedModules.join(', ')}`); await prompts.log.info(`Using modules from command-line: ${selectedModules.join(', ')}`);
} else if (options.customSource && !options.yes) { } else if (options.customSource) {
// Custom source without --modules or --yes: start with empty list // Custom source without --modules: start with empty list (core added below)
// (only custom source modules + core will be installed).
// When --yes is also set, fall through to the --yes branch so all
// installed modules are included alongside the custom source modules.
selectedModules = []; selectedModules = [];
} else if (options.yes) { } else if (options.yes) {
selectedModules = await this.getDefaultModules(installedModuleIds); selectedModules = await this.getDefaultModules(installedModuleIds);