oh-my-space 0.11.3 → 0.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +1 -1
- package/dist/oms.js +204 -2
- package/package.json +14 -4
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"commit":"
|
|
1
|
+
{"commit":"60bbfdfcc5f72dce2b2b74508715ddbc723aa3ff"}
|
package/dist/oms.js
CHANGED
|
@@ -14014,6 +14014,8 @@ function readJson(path) {
|
|
|
14014
14014
|
}
|
|
14015
14015
|
__name(readJson, "readJson");
|
|
14016
14016
|
function readPackageVersion() {
|
|
14017
|
+
const mocked = testEnv("OMS_TEST_PACKAGE_VERSION");
|
|
14018
|
+
if (mocked !== void 0) return mocked;
|
|
14017
14019
|
const pkg = readJson(join(packageRoot, "package.json"));
|
|
14018
14020
|
return pkg?.version ?? "0.0.0";
|
|
14019
14021
|
}
|
|
@@ -15764,7 +15766,7 @@ async function runInit(options) {
|
|
|
15764
15766
|
__name(runInit, "runInit");
|
|
15765
15767
|
|
|
15766
15768
|
// scripts/lib/repo-ops.ts
|
|
15767
|
-
import { existsSync as existsSync8, readdirSync, rmSync as rmSync2, rmdirSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
15769
|
+
import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync4, readdirSync, rmSync as rmSync2, rmdirSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
15768
15770
|
import { join as join7 } from "node:path";
|
|
15769
15771
|
function cleanupFailedAdd(repoRoot, alias) {
|
|
15770
15772
|
const path = submodulePath(alias);
|
|
@@ -15782,12 +15784,167 @@ function cleanupFailedAdd(repoRoot, alias) {
|
|
|
15782
15784
|
}
|
|
15783
15785
|
}
|
|
15784
15786
|
__name(cleanupFailedAdd, "cleanupFailedAdd");
|
|
15787
|
+
function headGitmodulesSection(repoRoot, alias) {
|
|
15788
|
+
const path = submodulePath(alias);
|
|
15789
|
+
const r = runGit(repoRoot, ["show", "HEAD:.gitmodules"]);
|
|
15790
|
+
if (!r.success) return null;
|
|
15791
|
+
const lines = r.stdout.split("\n");
|
|
15792
|
+
const start = lines.findIndex((line) => line.trim() === `[submodule "${path}"]`);
|
|
15793
|
+
if (start === -1) return null;
|
|
15794
|
+
let end = lines.length;
|
|
15795
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
15796
|
+
if (/^\s*\[submodule ".+"\]\s*$/.test(lines[i])) {
|
|
15797
|
+
end = i;
|
|
15798
|
+
break;
|
|
15799
|
+
}
|
|
15800
|
+
}
|
|
15801
|
+
return `${lines.slice(start, end).join("\n").replace(/\n*$/, "\n")}`;
|
|
15802
|
+
}
|
|
15803
|
+
__name(headGitmodulesSection, "headGitmodulesSection");
|
|
15804
|
+
function headFollowingGitmodulesHeaders(repoRoot, alias) {
|
|
15805
|
+
const path = submodulePath(alias);
|
|
15806
|
+
const r = runGit(repoRoot, ["show", "HEAD:.gitmodules"]);
|
|
15807
|
+
if (!r.success) return [];
|
|
15808
|
+
const lines = r.stdout.split("\n");
|
|
15809
|
+
const start = lines.findIndex((line) => line.trim() === `[submodule "${path}"]`);
|
|
15810
|
+
if (start === -1) return [];
|
|
15811
|
+
const headers = [];
|
|
15812
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
15813
|
+
const match = lines[i].trim().match(/^\[submodule "(.+)"\]$/);
|
|
15814
|
+
if (match) headers.push(`[submodule "${match[1]}"]`);
|
|
15815
|
+
}
|
|
15816
|
+
return headers;
|
|
15817
|
+
}
|
|
15818
|
+
__name(headFollowingGitmodulesHeaders, "headFollowingGitmodulesHeaders");
|
|
15819
|
+
function currentGitmodulesHasSameAliasSection(repoRoot, alias) {
|
|
15820
|
+
const gitmodules = join7(repoRoot, ".gitmodules");
|
|
15821
|
+
if (!existsSync8(gitmodules)) return false;
|
|
15822
|
+
return readFileSync4(gitmodules, "utf8").split("\n").some((line) => line.trim() === `[submodule "${submodulePath(alias)}"]`);
|
|
15823
|
+
}
|
|
15824
|
+
__name(currentGitmodulesHasSameAliasSection, "currentGitmodulesHasSameAliasSection");
|
|
15825
|
+
function insertGitmodulesSection(repoRoot, alias, section) {
|
|
15826
|
+
const gitmodules = join7(repoRoot, ".gitmodules");
|
|
15827
|
+
const existing = existsSync8(gitmodules) ? readFileSync4(gitmodules, "utf8") : "";
|
|
15828
|
+
const followingHeaders = headFollowingGitmodulesHeaders(repoRoot, alias);
|
|
15829
|
+
const lines = existing.split("\n");
|
|
15830
|
+
for (const followingHeader of followingHeaders) {
|
|
15831
|
+
const insertAt = lines.findIndex((line) => line.trim() === followingHeader);
|
|
15832
|
+
if (insertAt !== -1) {
|
|
15833
|
+
lines.splice(insertAt, 0, ...section.replace(/\n$/, "").split("\n"));
|
|
15834
|
+
writeFileSync4(gitmodules, lines.join("\n"));
|
|
15835
|
+
return;
|
|
15836
|
+
}
|
|
15837
|
+
}
|
|
15838
|
+
const separator = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
|
|
15839
|
+
writeFileSync4(gitmodules, `${existing}${separator}${section}`);
|
|
15840
|
+
}
|
|
15841
|
+
__name(insertGitmodulesSection, "insertGitmodulesSection");
|
|
15842
|
+
function gitmoduleValue(repoRoot, alias, key) {
|
|
15843
|
+
const r = runGit(repoRoot, ["config", "--file", ".gitmodules", "--get", `submodule.${submodulePath(alias)}.${key}`]);
|
|
15844
|
+
const value = r.stdout.trim();
|
|
15845
|
+
return r.success && value.length > 0 ? value : null;
|
|
15846
|
+
}
|
|
15847
|
+
__name(gitmoduleValue, "gitmoduleValue");
|
|
15848
|
+
function reconcileGitmodulesMetadata(repoRoot, repo) {
|
|
15849
|
+
const path = submodulePath(repo.alias);
|
|
15850
|
+
let changed = false;
|
|
15851
|
+
if (gitmoduleValue(repoRoot, repo.alias, "url") !== repo.remotes.origin) {
|
|
15852
|
+
runGit(repoRoot, ["config", "--file", ".gitmodules", `submodule.${path}.url`, repo.remotes.origin]);
|
|
15853
|
+
changed = true;
|
|
15854
|
+
}
|
|
15855
|
+
const currentBranchValue = gitmoduleValue(repoRoot, repo.alias, "branch");
|
|
15856
|
+
if (repo.branch) {
|
|
15857
|
+
if (currentBranchValue !== repo.branch) {
|
|
15858
|
+
runGit(repoRoot, ["config", "--file", ".gitmodules", `submodule.${path}.branch`, repo.branch]);
|
|
15859
|
+
changed = true;
|
|
15860
|
+
}
|
|
15861
|
+
} else if (currentBranchValue !== null) {
|
|
15862
|
+
runGit(repoRoot, ["config", "--file", ".gitmodules", "--unset", `submodule.${path}.branch`]);
|
|
15863
|
+
changed = true;
|
|
15864
|
+
}
|
|
15865
|
+
return changed;
|
|
15866
|
+
}
|
|
15867
|
+
__name(reconcileGitmodulesMetadata, "reconcileGitmodulesMetadata");
|
|
15868
|
+
function readAliasDirEntries(repoRoot, alias) {
|
|
15869
|
+
const dir = aliasDir(repoRoot, alias);
|
|
15870
|
+
try {
|
|
15871
|
+
if (!lstatSync(dir).isDirectory()) return { exists: true, entries: null };
|
|
15872
|
+
return { exists: true, entries: readdirSync(dir) };
|
|
15873
|
+
} catch (error) {
|
|
15874
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
|
|
15875
|
+
return { exists: false };
|
|
15876
|
+
}
|
|
15877
|
+
return { exists: true, entries: null };
|
|
15878
|
+
}
|
|
15879
|
+
}
|
|
15880
|
+
__name(readAliasDirEntries, "readAliasDirEntries");
|
|
15881
|
+
function cleanupRestorableAliasDir(repoRoot, alias) {
|
|
15882
|
+
if (submoduleInitialized(repoRoot, alias)) return true;
|
|
15883
|
+
const dirState = readAliasDirEntries(repoRoot, alias);
|
|
15884
|
+
if (!dirState.exists) return true;
|
|
15885
|
+
if (dirState.entries === null) return false;
|
|
15886
|
+
const entries = dirState.entries;
|
|
15887
|
+
if (entries.length > 0 && entries.some((entry) => entry !== ".DS_Store")) return false;
|
|
15888
|
+
try {
|
|
15889
|
+
rmSync2(aliasDir(repoRoot, alias), { recursive: true, force: true });
|
|
15890
|
+
} catch {
|
|
15891
|
+
return false;
|
|
15892
|
+
}
|
|
15893
|
+
return true;
|
|
15894
|
+
}
|
|
15895
|
+
__name(cleanupRestorableAliasDir, "cleanupRestorableAliasDir");
|
|
15896
|
+
function restorePendingRemoval(repo, repoRoot) {
|
|
15897
|
+
const alias = repo.alias;
|
|
15898
|
+
const path = submodulePath(alias);
|
|
15899
|
+
const state = gitlinkState(repoRoot, alias);
|
|
15900
|
+
const shouldRestore = state.headOid !== null && (pendingRemovalTopology(state) || partialRemovalTopology(state));
|
|
15901
|
+
if (!shouldRestore) return { result: "failed", restored: false };
|
|
15902
|
+
const unsafe = /* @__PURE__ */ __name((detail) => {
|
|
15903
|
+
R2.error(`${alias}: cannot restore pending removal safely (${detail}). Resolve or commit the pending removal before syncing.`);
|
|
15904
|
+
return { result: "failed", restored: true };
|
|
15905
|
+
}, "unsafe");
|
|
15906
|
+
if (state.conflict) return unsafe("root gitlink is conflicted");
|
|
15907
|
+
const rootOp = gitOperationInProgress(repoRoot);
|
|
15908
|
+
if (rootOp) return unsafe(`root repository has a ${rootOp} in progress`);
|
|
15909
|
+
if (currentGitmodulesHasSameAliasSection(repoRoot, alias) && !state.gitmodulesEntry) {
|
|
15910
|
+
return unsafe("current .gitmodules has an incomplete same-alias section");
|
|
15911
|
+
}
|
|
15912
|
+
const section = headGitmodulesSection(repoRoot, alias);
|
|
15913
|
+
if (!section) return unsafe(".gitmodules metadata is not recoverable from HEAD");
|
|
15914
|
+
if (!cleanupRestorableAliasDir(repoRoot, alias)) {
|
|
15915
|
+
return unsafe(`${path} is occupied by a non-submodule path`);
|
|
15916
|
+
}
|
|
15917
|
+
runGit(repoRoot, ["restore", "--source=HEAD", "--staged", "--", ".gitmodules"]);
|
|
15918
|
+
if (!state.gitmodulesEntry) insertGitmodulesSection(repoRoot, alias, section);
|
|
15919
|
+
const metadataUpdated = reconcileGitmodulesMetadata(repoRoot, repo);
|
|
15920
|
+
const restorePath = runGit(repoRoot, ["restore", "--source=HEAD", "--staged", "--worktree", "--", path], true);
|
|
15921
|
+
if (!restorePath.success) return unsafe(`failed to restore ${path} from HEAD`);
|
|
15922
|
+
runGit(repoRoot, ["submodule", "sync", "--", path]);
|
|
15923
|
+
R2.step(`${alias}: git submodule update --init ${path}`);
|
|
15924
|
+
const upd = runGit(repoRoot, ["submodule", "update", "--init", "--", path], true);
|
|
15925
|
+
if (!upd.success) {
|
|
15926
|
+
R2.error(`${alias}: git submodule update --init failed (exit ${upd.exitCode})`);
|
|
15927
|
+
return { result: "failed", restored: true };
|
|
15928
|
+
}
|
|
15929
|
+
ensureRemotes(repoRoot, alias, repo.remotes);
|
|
15930
|
+
const branch = gitmodulesBranch(repoRoot, alias) ?? repo.branch;
|
|
15931
|
+
if (branch) attachBranch(repoRoot, alias, branch);
|
|
15932
|
+
R2.success(`${alias}: restored pending removal${metadataUpdated ? " and updated .gitmodules metadata" : ""}`);
|
|
15933
|
+
return { result: "added", restored: true };
|
|
15934
|
+
}
|
|
15935
|
+
__name(restorePendingRemoval, "restorePendingRemoval");
|
|
15785
15936
|
function syncRepo(repo, repoRoot) {
|
|
15786
15937
|
const alias = repo.alias;
|
|
15787
15938
|
const path = submodulePath(alias);
|
|
15788
15939
|
const registered = isRegisteredSubmodule(repoRoot, path);
|
|
15940
|
+
const state = gitlinkState(repoRoot, alias);
|
|
15941
|
+
if (!registered && state.headOid !== null) {
|
|
15942
|
+
const restore = restorePendingRemoval(repo, repoRoot);
|
|
15943
|
+
if (restore.restored) return restore.result;
|
|
15944
|
+
}
|
|
15789
15945
|
if (!registered) {
|
|
15790
|
-
|
|
15946
|
+
const dirState = readAliasDirEntries(repoRoot, alias);
|
|
15947
|
+
if (dirState.exists && (dirState.entries === null || dirState.entries.length > 0)) {
|
|
15791
15948
|
R2.error(
|
|
15792
15949
|
`${alias}: ${path}/ already exists but is not a registered submodule. Move or remove it manually, then retry.`
|
|
15793
15950
|
);
|
|
@@ -16249,6 +16406,12 @@ function compareVersions(currentVersion, latestVersion) {
|
|
|
16249
16406
|
return import_semver.default.compare(current, latest);
|
|
16250
16407
|
}
|
|
16251
16408
|
__name(compareVersions, "compareVersions");
|
|
16409
|
+
function isPrereleaseVersion(version) {
|
|
16410
|
+
const parsed = import_semver.default.valid(version);
|
|
16411
|
+
if (!parsed) throw new Error(`Installed version is not valid semver: ${version}`);
|
|
16412
|
+
return import_semver.default.prerelease(parsed) !== null;
|
|
16413
|
+
}
|
|
16414
|
+
__name(isPrereleaseVersion, "isPrereleaseVersion");
|
|
16252
16415
|
function printUpdateHeader(currentVersion, latestVersion) {
|
|
16253
16416
|
R2.info(`Current version: ${currentVersion}`);
|
|
16254
16417
|
R2.info(`Latest version: ${latestVersion}`);
|
|
@@ -16266,6 +16429,36 @@ function printGuidance(context) {
|
|
|
16266
16429
|
for (const command of context.guidance) R2.message(` ${command}`);
|
|
16267
16430
|
}
|
|
16268
16431
|
__name(printGuidance, "printGuidance");
|
|
16432
|
+
function channelInstallCommand(manager, tag) {
|
|
16433
|
+
if (manager === "npm") return `npm install -g ${PACKAGE_NAME}@${tag}`;
|
|
16434
|
+
if (manager === "pnpm") return `pnpm add -g ${PACKAGE_NAME}@${tag}`;
|
|
16435
|
+
if (manager === "yarn") return `yarn global add ${PACKAGE_NAME}@${tag}`;
|
|
16436
|
+
return `bun add -g ${PACKAGE_NAME}@${tag}`;
|
|
16437
|
+
}
|
|
16438
|
+
__name(channelInstallCommand, "channelInstallCommand");
|
|
16439
|
+
function prereleaseGuidanceManager(context) {
|
|
16440
|
+
return context.manager ?? context.updateCommand?.executable ?? null;
|
|
16441
|
+
}
|
|
16442
|
+
__name(prereleaseGuidanceManager, "prereleaseGuidanceManager");
|
|
16443
|
+
function printPrereleaseGuidance(context) {
|
|
16444
|
+
const manager = prereleaseGuidanceManager(context);
|
|
16445
|
+
R2.info("Prerelease channel guidance:");
|
|
16446
|
+
if (manager) {
|
|
16447
|
+
R2.message(` Stay on beta manually: ${channelInstallCommand(manager, "beta")}`);
|
|
16448
|
+
R2.message(` Return to stable: ${channelInstallCommand(manager, "latest")}`);
|
|
16449
|
+
return;
|
|
16450
|
+
}
|
|
16451
|
+
for (const fallbackManager of ["npm", "pnpm", "yarn", "bun"]) {
|
|
16452
|
+
R2.message(` ${fallbackManager} beta: ${channelInstallCommand(fallbackManager, "beta")}`);
|
|
16453
|
+
R2.message(` ${fallbackManager} stable: ${channelInstallCommand(fallbackManager, "latest")}`);
|
|
16454
|
+
}
|
|
16455
|
+
}
|
|
16456
|
+
__name(printPrereleaseGuidance, "printPrereleaseGuidance");
|
|
16457
|
+
function printPrereleaseStatus(currentVersion, latestVersion) {
|
|
16458
|
+
R2.info(`Installed prerelease version: ${currentVersion}`);
|
|
16459
|
+
R2.info(`Stable latest version: ${latestVersion}`);
|
|
16460
|
+
}
|
|
16461
|
+
__name(printPrereleaseStatus, "printPrereleaseStatus");
|
|
16269
16462
|
function commandAvailability(command) {
|
|
16270
16463
|
const mocked = testEnv("OMS_TEST_MANAGER_AVAILABLE");
|
|
16271
16464
|
if (mocked !== void 0) return mocked === "1" || mocked === "true";
|
|
@@ -16324,12 +16517,16 @@ async function runUpdate(options) {
|
|
|
16324
16517
|
try {
|
|
16325
16518
|
latestVersion = await fetchLatestPackageVersion();
|
|
16326
16519
|
const comparison = compareVersions(currentVersion, latestVersion);
|
|
16520
|
+
const prerelease2 = isPrereleaseVersion(currentVersion);
|
|
16327
16521
|
printUpdateHeader(currentVersion, latestVersion);
|
|
16522
|
+
if (prerelease2) printPrereleaseStatus(currentVersion, latestVersion);
|
|
16328
16523
|
if (comparison === 0) {
|
|
16524
|
+
if (prerelease2) printPrereleaseGuidance(detectInstallContext());
|
|
16329
16525
|
R2.success("oms is up to date.");
|
|
16330
16526
|
return 0;
|
|
16331
16527
|
}
|
|
16332
16528
|
if (comparison > 0) {
|
|
16529
|
+
if (prerelease2) printPrereleaseGuidance(detectInstallContext());
|
|
16333
16530
|
R2.info("Installed version is newer than the npm registry latest; no downgrade will be performed.");
|
|
16334
16531
|
return 0;
|
|
16335
16532
|
}
|
|
@@ -16340,6 +16537,11 @@ async function runUpdate(options) {
|
|
|
16340
16537
|
R2.warn("Update available.");
|
|
16341
16538
|
const context = detectInstallContext();
|
|
16342
16539
|
printInstallContext(context);
|
|
16540
|
+
const prerelease = isPrereleaseVersion(currentVersion);
|
|
16541
|
+
if (prerelease) {
|
|
16542
|
+
R2.info("Selected update channel: stable latest (oh-my-space@latest).");
|
|
16543
|
+
printPrereleaseGuidance(context);
|
|
16544
|
+
}
|
|
16343
16545
|
if (options.check) {
|
|
16344
16546
|
if (!context.updateCommand) printGuidance(context);
|
|
16345
16547
|
return 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oh-my-space",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.4",
|
|
4
4
|
"description": "Manage multi-repo workspaces with Git submodules.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/divlook/oh-my-space",
|
|
@@ -13,9 +13,18 @@
|
|
|
13
13
|
},
|
|
14
14
|
"keywords": [
|
|
15
15
|
"oms",
|
|
16
|
-
"
|
|
16
|
+
"oh-my-space",
|
|
17
17
|
"git",
|
|
18
|
-
"cli"
|
|
18
|
+
"cli",
|
|
19
|
+
"git-submodule",
|
|
20
|
+
"submodule",
|
|
21
|
+
"workspace",
|
|
22
|
+
"multi-repo",
|
|
23
|
+
"monorepo",
|
|
24
|
+
"repository-management",
|
|
25
|
+
"developer-tools",
|
|
26
|
+
"ai",
|
|
27
|
+
"agent"
|
|
19
28
|
],
|
|
20
29
|
"author": {
|
|
21
30
|
"name": "divlook",
|
|
@@ -40,7 +49,8 @@
|
|
|
40
49
|
"prepack": "npm test",
|
|
41
50
|
"changeset": "changeset",
|
|
42
51
|
"version": "changeset version",
|
|
43
|
-
"release": "changeset publish"
|
|
52
|
+
"release": "changeset publish",
|
|
53
|
+
"release:beta": "node scripts/publish-beta.mjs"
|
|
44
54
|
},
|
|
45
55
|
"devDependencies": {
|
|
46
56
|
"@changesets/changelog-github": "^0.7.0",
|