gitgrip 0.2.0
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/LICENSE +21 -0
- package/README.md +211 -0
- package/actions/cross-repo-sync/action.yml +55 -0
- package/assets/banner.svg +73 -0
- package/assets/icon.svg +30 -0
- package/assets/logo-dark.svg +36 -0
- package/assets/logo.svg +36 -0
- package/dist/commands/add.d.ts +9 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +80 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/bench.d.ts +12 -0
- package/dist/commands/bench.d.ts.map +1 -0
- package/dist/commands/bench.js +136 -0
- package/dist/commands/bench.js.map +1 -0
- package/dist/commands/branch.d.ts +15 -0
- package/dist/commands/branch.d.ts.map +1 -0
- package/dist/commands/branch.js +159 -0
- package/dist/commands/branch.js.map +1 -0
- package/dist/commands/checkout.d.ts +10 -0
- package/dist/commands/checkout.d.ts.map +1 -0
- package/dist/commands/checkout.js +85 -0
- package/dist/commands/checkout.js.map +1 -0
- package/dist/commands/commit.d.ts +10 -0
- package/dist/commands/commit.d.ts.map +1 -0
- package/dist/commands/commit.js +94 -0
- package/dist/commands/commit.js.map +1 -0
- package/dist/commands/diff.d.ts +11 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +105 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/env.d.ts +8 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +35 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/forall.d.ts +13 -0
- package/dist/commands/forall.d.ts.map +1 -0
- package/dist/commands/forall.js +116 -0
- package/dist/commands/forall.js.map +1 -0
- package/dist/commands/init.d.ts +15 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +106 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/link.d.ts +11 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +205 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/migrate.d.ts +17 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +180 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/pr/create.d.ts +13 -0
- package/dist/commands/pr/create.d.ts.map +1 -0
- package/dist/commands/pr/create.js +202 -0
- package/dist/commands/pr/create.js.map +1 -0
- package/dist/commands/pr/index.d.ts +4 -0
- package/dist/commands/pr/index.d.ts.map +1 -0
- package/dist/commands/pr/index.js +4 -0
- package/dist/commands/pr/index.js.map +1 -0
- package/dist/commands/pr/merge.d.ts +11 -0
- package/dist/commands/pr/merge.d.ts.map +1 -0
- package/dist/commands/pr/merge.js +168 -0
- package/dist/commands/pr/merge.js.map +1 -0
- package/dist/commands/pr/status.d.ts +9 -0
- package/dist/commands/pr/status.d.ts.map +1 -0
- package/dist/commands/pr/status.js +139 -0
- package/dist/commands/pr/status.js.map +1 -0
- package/dist/commands/push.d.ts +10 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +101 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/run.d.ts +8 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +75 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/status.d.ts +9 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +201 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +13 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +183 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +352 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/__bench__/files.bench.d.ts +2 -0
- package/dist/lib/__bench__/files.bench.d.ts.map +1 -0
- package/dist/lib/__bench__/files.bench.js +52 -0
- package/dist/lib/__bench__/files.bench.js.map +1 -0
- package/dist/lib/__bench__/manifest.bench.d.ts +2 -0
- package/dist/lib/__bench__/manifest.bench.d.ts.map +1 -0
- package/dist/lib/__bench__/manifest.bench.js +74 -0
- package/dist/lib/__bench__/manifest.bench.js.map +1 -0
- package/dist/lib/files.d.ts +84 -0
- package/dist/lib/files.d.ts.map +1 -0
- package/dist/lib/files.js +492 -0
- package/dist/lib/files.js.map +1 -0
- package/dist/lib/git.d.ts +125 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +370 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/github.d.ts +92 -0
- package/dist/lib/github.d.ts.map +1 -0
- package/dist/lib/github.js +284 -0
- package/dist/lib/github.js.map +1 -0
- package/dist/lib/hooks.d.ts +19 -0
- package/dist/lib/hooks.d.ts.map +1 -0
- package/dist/lib/hooks.js +63 -0
- package/dist/lib/hooks.js.map +1 -0
- package/dist/lib/linker.d.ts +56 -0
- package/dist/lib/linker.d.ts.map +1 -0
- package/dist/lib/linker.js +185 -0
- package/dist/lib/linker.js.map +1 -0
- package/dist/lib/manifest.d.ts +73 -0
- package/dist/lib/manifest.d.ts.map +1 -0
- package/dist/lib/manifest.js +400 -0
- package/dist/lib/manifest.js.map +1 -0
- package/dist/lib/scripts.d.ts +26 -0
- package/dist/lib/scripts.d.ts.map +1 -0
- package/dist/lib/scripts.js +123 -0
- package/dist/lib/scripts.js.map +1 -0
- package/dist/lib/timing.d.ts +100 -0
- package/dist/lib/timing.d.ts.map +1 -0
- package/dist/lib/timing.js +293 -0
- package/dist/lib/timing.js.map +1 -0
- package/dist/types.d.ts +312 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Manifest, RepoInfo, StateFile, GitHubRepoInfo } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Get the path to the gitgrip directory (.gitgrip or .codi-repo for backward compat)
|
|
4
|
+
* Prefers .gitgrip if it exists, falls back to .codi-repo, defaults to .gitgrip for new workspaces
|
|
5
|
+
*/
|
|
6
|
+
export declare function getGitgripDir(workspaceRoot: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Get the path to the gitgrip directory for new workspaces (always .gitgrip)
|
|
9
|
+
*/
|
|
10
|
+
export declare function getNewGitgripDir(workspaceRoot: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated Use getGitgripDir instead
|
|
13
|
+
*/
|
|
14
|
+
export declare function getCodiRepoDir(workspaceRoot: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Get the path to the manifests directory
|
|
17
|
+
*/
|
|
18
|
+
export declare function getManifestsDir(workspaceRoot: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Get the path to the manifest file
|
|
21
|
+
*/
|
|
22
|
+
export declare function getManifestPath(workspaceRoot: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Find the manifest file by walking up the directory tree
|
|
25
|
+
* Looks for .codi-repo/manifests/manifest.yaml (new format)
|
|
26
|
+
*/
|
|
27
|
+
export declare function findManifestPath(startDir?: string): Promise<string | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Find a legacy manifest file (codi-repos.yaml at root)
|
|
30
|
+
*/
|
|
31
|
+
export declare function findLegacyManifestPath(startDir?: string): Promise<string | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Load and parse the manifest file
|
|
34
|
+
* Returns the workspace root (parent of .codi-repo, not the manifests dir)
|
|
35
|
+
*/
|
|
36
|
+
export declare function loadManifest(manifestPath?: string): Promise<{
|
|
37
|
+
manifest: Manifest;
|
|
38
|
+
rootDir: string;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Create a new manifest file in the manifests directory
|
|
42
|
+
*/
|
|
43
|
+
export declare function createManifest(manifestsDir: string, manifest: Manifest): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Parse GitHub owner/repo from a git URL
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseGitHubUrl(url: string): GitHubRepoInfo;
|
|
48
|
+
/**
|
|
49
|
+
* Get full repo info with computed fields
|
|
50
|
+
*/
|
|
51
|
+
export declare function getRepoInfo(name: string, config: Manifest['repos'][string], rootDir: string): RepoInfo;
|
|
52
|
+
/**
|
|
53
|
+
* Get all repos as RepoInfo array
|
|
54
|
+
*/
|
|
55
|
+
export declare function getAllRepoInfo(manifest: Manifest, rootDir: string): RepoInfo[];
|
|
56
|
+
/**
|
|
57
|
+
* Get manifest repo as RepoInfo (if manifest.url is configured)
|
|
58
|
+
* Returns null if manifest section is not configured, has no URL, or URL is invalid
|
|
59
|
+
*/
|
|
60
|
+
export declare function getManifestRepoInfo(manifest: Manifest, rootDir: string): RepoInfo | null;
|
|
61
|
+
/**
|
|
62
|
+
* Load the state file
|
|
63
|
+
*/
|
|
64
|
+
export declare function loadState(rootDir: string): Promise<StateFile>;
|
|
65
|
+
/**
|
|
66
|
+
* Save the state file
|
|
67
|
+
*/
|
|
68
|
+
export declare function saveState(rootDir: string, state: StateFile): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Generate a sample manifest for init command
|
|
71
|
+
*/
|
|
72
|
+
export declare function generateSampleManifest(): Manifest;
|
|
73
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/lib/manifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAmD,MAAM,aAAa,CAAC;AA8ElI;;;GAGG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAa3D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAc/F;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcrG;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA+H1G;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAO5F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAc1D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CAStG;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,EAAE,CAE9E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CA2BxF;AASD;;GAEG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAWnE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAShF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,QAAQ,CAoBjD"}
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
import { readFile, writeFile, access } from 'fs/promises';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { resolve, dirname, join, normalize } from 'path';
|
|
4
|
+
import YAML from 'yaml';
|
|
5
|
+
// AOSP-style: manifest lives in .gitgrip/manifests/manifest.yaml
|
|
6
|
+
// (Legacy: .codi-repo/manifests/manifest.yaml also supported for backward compatibility)
|
|
7
|
+
const GITGRIP_DIR = '.gitgrip';
|
|
8
|
+
const LEGACY_CODI_REPO_DIR = '.codi-repo';
|
|
9
|
+
const MANIFESTS_DIR = 'manifests';
|
|
10
|
+
const MANIFEST_FILENAME = 'manifest.yaml';
|
|
11
|
+
const STATE_FILENAME = 'state.json';
|
|
12
|
+
// Legacy: old format used codi-repos.yaml at root
|
|
13
|
+
const LEGACY_MANIFEST_FILENAME = 'codi-repos.yaml';
|
|
14
|
+
/**
|
|
15
|
+
* Default manifest settings
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_SETTINGS = {
|
|
18
|
+
pr_prefix: '[cross-repo]',
|
|
19
|
+
merge_strategy: 'all-or-nothing',
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Check if a relative path would escape its parent directory
|
|
23
|
+
*/
|
|
24
|
+
function pathEscapesBoundary(relativePath) {
|
|
25
|
+
const normalized = normalize(relativePath);
|
|
26
|
+
// Check for path traversal attempts
|
|
27
|
+
if (normalized.startsWith('..') || normalized.startsWith('/') || normalized.includes('/../')) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validate copyfile/linkfile config
|
|
34
|
+
*/
|
|
35
|
+
function validateFileConfig(config, type, repoName) {
|
|
36
|
+
if (!config.src || typeof config.src !== 'string') {
|
|
37
|
+
throw new Error(`${type} in repo '${repoName}' is missing 'src'`);
|
|
38
|
+
}
|
|
39
|
+
if (!config.dest || typeof config.dest !== 'string') {
|
|
40
|
+
throw new Error(`${type} in repo '${repoName}' is missing 'dest'`);
|
|
41
|
+
}
|
|
42
|
+
if (pathEscapesBoundary(config.src)) {
|
|
43
|
+
throw new Error(`${type} in repo '${repoName}': src path '${config.src}' escapes repo boundary`);
|
|
44
|
+
}
|
|
45
|
+
if (pathEscapesBoundary(config.dest)) {
|
|
46
|
+
throw new Error(`${type} in repo '${repoName}': dest path '${config.dest}' escapes workspace boundary`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Validate workspace script config
|
|
51
|
+
*/
|
|
52
|
+
function validateScript(script, scriptName) {
|
|
53
|
+
if (!script.command && !script.steps) {
|
|
54
|
+
throw new Error(`Script '${scriptName}' must have either 'command' or 'steps'`);
|
|
55
|
+
}
|
|
56
|
+
if (script.command && script.steps) {
|
|
57
|
+
throw new Error(`Script '${scriptName}' cannot have both 'command' and 'steps'`);
|
|
58
|
+
}
|
|
59
|
+
if (script.steps) {
|
|
60
|
+
for (let i = 0; i < script.steps.length; i++) {
|
|
61
|
+
const step = script.steps[i];
|
|
62
|
+
if (!step.name) {
|
|
63
|
+
throw new Error(`Script '${scriptName}' step ${i + 1} is missing 'name'`);
|
|
64
|
+
}
|
|
65
|
+
if (!step.command) {
|
|
66
|
+
throw new Error(`Script '${scriptName}' step '${step.name}' is missing 'command'`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get the path to the gitgrip directory (.gitgrip or .codi-repo for backward compat)
|
|
73
|
+
* Prefers .gitgrip if it exists, falls back to .codi-repo, defaults to .gitgrip for new workspaces
|
|
74
|
+
*/
|
|
75
|
+
export function getGitgripDir(workspaceRoot) {
|
|
76
|
+
const newDir = join(workspaceRoot, GITGRIP_DIR);
|
|
77
|
+
const legacyDir = join(workspaceRoot, LEGACY_CODI_REPO_DIR);
|
|
78
|
+
// Synchronous check for simplicity in path resolution
|
|
79
|
+
if (existsSync(newDir)) {
|
|
80
|
+
return newDir;
|
|
81
|
+
}
|
|
82
|
+
if (existsSync(legacyDir)) {
|
|
83
|
+
return legacyDir;
|
|
84
|
+
}
|
|
85
|
+
// Default to new directory for new workspaces
|
|
86
|
+
return newDir;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the path to the gitgrip directory for new workspaces (always .gitgrip)
|
|
90
|
+
*/
|
|
91
|
+
export function getNewGitgripDir(workspaceRoot) {
|
|
92
|
+
return join(workspaceRoot, GITGRIP_DIR);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* @deprecated Use getGitgripDir instead
|
|
96
|
+
*/
|
|
97
|
+
export function getCodiRepoDir(workspaceRoot) {
|
|
98
|
+
return getGitgripDir(workspaceRoot);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get the path to the manifests directory
|
|
102
|
+
*/
|
|
103
|
+
export function getManifestsDir(workspaceRoot) {
|
|
104
|
+
return join(getGitgripDir(workspaceRoot), MANIFESTS_DIR);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get the path to the manifest file
|
|
108
|
+
*/
|
|
109
|
+
export function getManifestPath(workspaceRoot) {
|
|
110
|
+
return join(getManifestsDir(workspaceRoot), MANIFEST_FILENAME);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Find the manifest file by walking up the directory tree
|
|
114
|
+
* Looks for .codi-repo/manifests/manifest.yaml (new format)
|
|
115
|
+
*/
|
|
116
|
+
export async function findManifestPath(startDir = process.cwd()) {
|
|
117
|
+
let currentDir = resolve(startDir);
|
|
118
|
+
while (currentDir !== dirname(currentDir)) {
|
|
119
|
+
const manifestPath = getManifestPath(currentDir);
|
|
120
|
+
try {
|
|
121
|
+
await access(manifestPath);
|
|
122
|
+
return manifestPath;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
currentDir = dirname(currentDir);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Find a legacy manifest file (codi-repos.yaml at root)
|
|
132
|
+
*/
|
|
133
|
+
export async function findLegacyManifestPath(startDir = process.cwd()) {
|
|
134
|
+
let currentDir = resolve(startDir);
|
|
135
|
+
while (currentDir !== dirname(currentDir)) {
|
|
136
|
+
const manifestPath = join(currentDir, LEGACY_MANIFEST_FILENAME);
|
|
137
|
+
try {
|
|
138
|
+
await access(manifestPath);
|
|
139
|
+
return manifestPath;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
currentDir = dirname(currentDir);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Load and parse the manifest file
|
|
149
|
+
* Returns the workspace root (parent of .codi-repo, not the manifests dir)
|
|
150
|
+
*/
|
|
151
|
+
export async function loadManifest(manifestPath) {
|
|
152
|
+
const path = manifestPath ?? (await findManifestPath());
|
|
153
|
+
if (!path) {
|
|
154
|
+
throw new Error(`Manifest file not found. Run 'gr init <manifest-url>' first.`);
|
|
155
|
+
}
|
|
156
|
+
const content = await readFile(path, 'utf-8');
|
|
157
|
+
const parsed = YAML.parse(content);
|
|
158
|
+
// Validate and apply defaults
|
|
159
|
+
if (!parsed.version) {
|
|
160
|
+
parsed.version = 1;
|
|
161
|
+
}
|
|
162
|
+
if (!parsed.repos || Object.keys(parsed.repos).length === 0) {
|
|
163
|
+
throw new Error('Manifest must define at least one repository');
|
|
164
|
+
}
|
|
165
|
+
if (!parsed.settings) {
|
|
166
|
+
parsed.settings = DEFAULT_SETTINGS;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
parsed.settings = { ...DEFAULT_SETTINGS, ...parsed.settings };
|
|
170
|
+
}
|
|
171
|
+
// Validate each repo config
|
|
172
|
+
for (const [name, repo] of Object.entries(parsed.repos)) {
|
|
173
|
+
if (!repo.url) {
|
|
174
|
+
throw new Error(`Repository '${name}' is missing 'url'`);
|
|
175
|
+
}
|
|
176
|
+
if (!repo.path) {
|
|
177
|
+
throw new Error(`Repository '${name}' is missing 'path'`);
|
|
178
|
+
}
|
|
179
|
+
if (!repo.default_branch) {
|
|
180
|
+
repo.default_branch = 'main';
|
|
181
|
+
}
|
|
182
|
+
// Validate copyfile entries
|
|
183
|
+
if (repo.copyfile) {
|
|
184
|
+
if (!Array.isArray(repo.copyfile)) {
|
|
185
|
+
throw new Error(`Repository '${name}': copyfile must be an array`);
|
|
186
|
+
}
|
|
187
|
+
for (const config of repo.copyfile) {
|
|
188
|
+
validateFileConfig(config, 'copyfile', name);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Validate linkfile entries
|
|
192
|
+
if (repo.linkfile) {
|
|
193
|
+
if (!Array.isArray(repo.linkfile)) {
|
|
194
|
+
throw new Error(`Repository '${name}': linkfile must be an array`);
|
|
195
|
+
}
|
|
196
|
+
for (const config of repo.linkfile) {
|
|
197
|
+
validateFileConfig(config, 'linkfile', name);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Validate manifest-level config
|
|
202
|
+
if (parsed.manifest) {
|
|
203
|
+
// Default manifest branch to 'main'
|
|
204
|
+
if (!parsed.manifest.default_branch) {
|
|
205
|
+
parsed.manifest.default_branch = 'main';
|
|
206
|
+
}
|
|
207
|
+
if (parsed.manifest.copyfile) {
|
|
208
|
+
if (!Array.isArray(parsed.manifest.copyfile)) {
|
|
209
|
+
throw new Error('manifest.copyfile must be an array');
|
|
210
|
+
}
|
|
211
|
+
for (const config of parsed.manifest.copyfile) {
|
|
212
|
+
validateFileConfig(config, 'copyfile', 'manifest');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (parsed.manifest.linkfile) {
|
|
216
|
+
if (!Array.isArray(parsed.manifest.linkfile)) {
|
|
217
|
+
throw new Error('manifest.linkfile must be an array');
|
|
218
|
+
}
|
|
219
|
+
for (const config of parsed.manifest.linkfile) {
|
|
220
|
+
validateFileConfig(config, 'linkfile', 'manifest');
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Validate workspace config
|
|
225
|
+
if (parsed.workspace) {
|
|
226
|
+
// Validate env
|
|
227
|
+
if (parsed.workspace.env) {
|
|
228
|
+
if (typeof parsed.workspace.env !== 'object') {
|
|
229
|
+
throw new Error('workspace.env must be an object');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// Validate scripts
|
|
233
|
+
if (parsed.workspace.scripts) {
|
|
234
|
+
if (typeof parsed.workspace.scripts !== 'object') {
|
|
235
|
+
throw new Error('workspace.scripts must be an object');
|
|
236
|
+
}
|
|
237
|
+
for (const [scriptName, script] of Object.entries(parsed.workspace.scripts)) {
|
|
238
|
+
validateScript(script, scriptName);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Validate hooks
|
|
242
|
+
if (parsed.workspace.hooks) {
|
|
243
|
+
if (typeof parsed.workspace.hooks !== 'object') {
|
|
244
|
+
throw new Error('workspace.hooks must be an object');
|
|
245
|
+
}
|
|
246
|
+
const validHooks = ['post-sync', 'post-checkout'];
|
|
247
|
+
for (const hookName of Object.keys(parsed.workspace.hooks)) {
|
|
248
|
+
if (!validHooks.includes(hookName)) {
|
|
249
|
+
throw new Error(`Unknown hook '${hookName}'. Valid hooks: ${validHooks.join(', ')}`);
|
|
250
|
+
}
|
|
251
|
+
const hooks = parsed.workspace.hooks[hookName];
|
|
252
|
+
if (hooks && !Array.isArray(hooks)) {
|
|
253
|
+
throw new Error(`workspace.hooks.${hookName} must be an array`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// rootDir is the workspace root (parent of .codi-repo/manifests/)
|
|
259
|
+
// Path is: <workspace>/.codi-repo/manifests/manifest.yaml
|
|
260
|
+
const manifestsDir = dirname(path);
|
|
261
|
+
const codiRepoDir = dirname(manifestsDir);
|
|
262
|
+
const workspaceRoot = dirname(codiRepoDir);
|
|
263
|
+
return {
|
|
264
|
+
manifest: parsed,
|
|
265
|
+
rootDir: workspaceRoot,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Create a new manifest file in the manifests directory
|
|
270
|
+
*/
|
|
271
|
+
export async function createManifest(manifestsDir, manifest) {
|
|
272
|
+
const manifestPath = join(manifestsDir, MANIFEST_FILENAME);
|
|
273
|
+
const content = YAML.stringify(manifest, {
|
|
274
|
+
indent: 2,
|
|
275
|
+
lineWidth: 0,
|
|
276
|
+
});
|
|
277
|
+
await writeFile(manifestPath, content, 'utf-8');
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Parse GitHub owner/repo from a git URL
|
|
281
|
+
*/
|
|
282
|
+
export function parseGitHubUrl(url) {
|
|
283
|
+
// SSH format: git@github.com:owner/repo.git
|
|
284
|
+
const sshMatch = url.match(/git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
|
|
285
|
+
if (sshMatch) {
|
|
286
|
+
return { owner: sshMatch[1], repo: sshMatch[2] };
|
|
287
|
+
}
|
|
288
|
+
// HTTPS format: https://github.com/owner/repo.git
|
|
289
|
+
const httpsMatch = url.match(/https?:\/\/github\.com\/([^/]+)\/(.+?)(?:\.git)?$/);
|
|
290
|
+
if (httpsMatch) {
|
|
291
|
+
return { owner: httpsMatch[1], repo: httpsMatch[2] };
|
|
292
|
+
}
|
|
293
|
+
throw new Error(`Unable to parse GitHub URL: ${url}`);
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Get full repo info with computed fields
|
|
297
|
+
*/
|
|
298
|
+
export function getRepoInfo(name, config, rootDir) {
|
|
299
|
+
const { owner, repo } = parseGitHubUrl(config.url);
|
|
300
|
+
return {
|
|
301
|
+
...config,
|
|
302
|
+
name,
|
|
303
|
+
absolutePath: resolve(rootDir, config.path),
|
|
304
|
+
owner,
|
|
305
|
+
repo,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Get all repos as RepoInfo array
|
|
310
|
+
*/
|
|
311
|
+
export function getAllRepoInfo(manifest, rootDir) {
|
|
312
|
+
return Object.entries(manifest.repos).map(([name, config]) => getRepoInfo(name, config, rootDir));
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get manifest repo as RepoInfo (if manifest.url is configured)
|
|
316
|
+
* Returns null if manifest section is not configured, has no URL, or URL is invalid
|
|
317
|
+
*/
|
|
318
|
+
export function getManifestRepoInfo(manifest, rootDir) {
|
|
319
|
+
if (!manifest.manifest?.url) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
const manifestsDir = getManifestsDir(rootDir);
|
|
323
|
+
try {
|
|
324
|
+
const parsed = parseGitHubUrl(manifest.manifest.url);
|
|
325
|
+
// Determine which directory is in use for the path field
|
|
326
|
+
const gitgripDir = getGitgripDir(rootDir);
|
|
327
|
+
const dirName = gitgripDir.endsWith(LEGACY_CODI_REPO_DIR) ? LEGACY_CODI_REPO_DIR : GITGRIP_DIR;
|
|
328
|
+
return {
|
|
329
|
+
name: 'manifest',
|
|
330
|
+
url: manifest.manifest.url,
|
|
331
|
+
path: `${dirName}/manifests`,
|
|
332
|
+
absolutePath: manifestsDir,
|
|
333
|
+
default_branch: manifest.manifest.default_branch ?? 'main',
|
|
334
|
+
owner: parsed.owner,
|
|
335
|
+
repo: parsed.repo,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
// Invalid GitHub URL format
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Get the state file path
|
|
345
|
+
*/
|
|
346
|
+
function getStatePath(rootDir) {
|
|
347
|
+
return join(getCodiRepoDir(rootDir), STATE_FILENAME);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Load the state file
|
|
351
|
+
*/
|
|
352
|
+
export async function loadState(rootDir) {
|
|
353
|
+
const statePath = getStatePath(rootDir);
|
|
354
|
+
try {
|
|
355
|
+
const content = await readFile(statePath, 'utf-8');
|
|
356
|
+
return JSON.parse(content);
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
return {
|
|
360
|
+
branchToPR: {},
|
|
361
|
+
prLinks: {},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Save the state file
|
|
367
|
+
*/
|
|
368
|
+
export async function saveState(rootDir, state) {
|
|
369
|
+
const statePath = getStatePath(rootDir);
|
|
370
|
+
const stateDir = dirname(statePath);
|
|
371
|
+
// Ensure state directory exists
|
|
372
|
+
const { mkdir } = await import('fs/promises');
|
|
373
|
+
await mkdir(stateDir, { recursive: true });
|
|
374
|
+
await writeFile(statePath, JSON.stringify(state, null, 2), 'utf-8');
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Generate a sample manifest for init command
|
|
378
|
+
*/
|
|
379
|
+
export function generateSampleManifest() {
|
|
380
|
+
return {
|
|
381
|
+
version: 1,
|
|
382
|
+
repos: {
|
|
383
|
+
public: {
|
|
384
|
+
url: 'git@github.com:your-org/your-repo.git',
|
|
385
|
+
path: './public',
|
|
386
|
+
default_branch: 'main',
|
|
387
|
+
},
|
|
388
|
+
private: {
|
|
389
|
+
url: 'git@github.com:your-org/your-private-repo.git',
|
|
390
|
+
path: './private',
|
|
391
|
+
default_branch: 'main',
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
settings: {
|
|
395
|
+
pr_prefix: '[cross-repo]',
|
|
396
|
+
merge_strategy: 'all-or-nothing',
|
|
397
|
+
},
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/lib/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Manifest } from '../types.js';
|
|
2
|
+
export interface ScriptStepResult {
|
|
3
|
+
name: string;
|
|
4
|
+
command: string;
|
|
5
|
+
cwd: string;
|
|
6
|
+
success: boolean;
|
|
7
|
+
exitCode: number | null;
|
|
8
|
+
error?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ScriptResult {
|
|
11
|
+
scriptName: string;
|
|
12
|
+
success: boolean;
|
|
13
|
+
steps: ScriptStepResult[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Run a workspace script by name
|
|
17
|
+
*/
|
|
18
|
+
export declare function runScript(scriptName: string, manifest: Manifest, rootDir: string, args?: string[]): Promise<ScriptResult>;
|
|
19
|
+
/**
|
|
20
|
+
* Get list of available scripts
|
|
21
|
+
*/
|
|
22
|
+
export declare function listScripts(manifest: Manifest): {
|
|
23
|
+
name: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
}[];
|
|
26
|
+
//# sourceMappingURL=scripts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../../src/lib/scripts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAA+B,MAAM,aAAa,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AA0DD;;GAEG;AACH,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,GAClB,OAAO,CAAC,YAAY,CAAC,CA+DvB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,CAUxF"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Run a single command (used for both single commands and steps)
|
|
5
|
+
*/
|
|
6
|
+
async function runCommand(command, cwd, env, onStdout, onStderr) {
|
|
7
|
+
return new Promise((resolvePromise) => {
|
|
8
|
+
const proc = spawn(command, [], {
|
|
9
|
+
cwd,
|
|
10
|
+
shell: true,
|
|
11
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
12
|
+
env: {
|
|
13
|
+
...process.env,
|
|
14
|
+
...env,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
proc.stdout?.on('data', (data) => {
|
|
18
|
+
const str = data.toString();
|
|
19
|
+
if (onStdout) {
|
|
20
|
+
onStdout(str);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
process.stdout.write(str);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
proc.stderr?.on('data', (data) => {
|
|
27
|
+
const str = data.toString();
|
|
28
|
+
if (onStderr) {
|
|
29
|
+
onStderr(str);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
process.stderr.write(str);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
proc.on('close', (exitCode) => {
|
|
36
|
+
resolvePromise({
|
|
37
|
+
success: exitCode === 0,
|
|
38
|
+
exitCode,
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
proc.on('error', (error) => {
|
|
42
|
+
resolvePromise({
|
|
43
|
+
success: false,
|
|
44
|
+
exitCode: null,
|
|
45
|
+
error: error.message,
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Run a workspace script by name
|
|
52
|
+
*/
|
|
53
|
+
export async function runScript(scriptName, manifest, rootDir, args = []) {
|
|
54
|
+
const workspace = manifest.workspace;
|
|
55
|
+
if (!workspace?.scripts) {
|
|
56
|
+
throw new Error('No workspace scripts defined in manifest');
|
|
57
|
+
}
|
|
58
|
+
const script = workspace.scripts[scriptName];
|
|
59
|
+
if (!script) {
|
|
60
|
+
const available = Object.keys(workspace.scripts).join(', ');
|
|
61
|
+
throw new Error(`Script '${scriptName}' not found. Available: ${available}`);
|
|
62
|
+
}
|
|
63
|
+
// Get workspace env
|
|
64
|
+
const env = workspace.env ?? {};
|
|
65
|
+
const result = {
|
|
66
|
+
scriptName,
|
|
67
|
+
success: true,
|
|
68
|
+
steps: [],
|
|
69
|
+
};
|
|
70
|
+
if (script.command) {
|
|
71
|
+
// Single command script
|
|
72
|
+
const cwd = script.cwd ? resolve(rootDir, script.cwd) : rootDir;
|
|
73
|
+
// Append any extra args
|
|
74
|
+
const fullCommand = args.length > 0 ? `${script.command} ${args.join(' ')}` : script.command;
|
|
75
|
+
const stepResult = await runCommand(fullCommand, cwd, env);
|
|
76
|
+
result.steps.push({
|
|
77
|
+
name: scriptName,
|
|
78
|
+
command: fullCommand,
|
|
79
|
+
cwd,
|
|
80
|
+
success: stepResult.success,
|
|
81
|
+
exitCode: stepResult.exitCode,
|
|
82
|
+
error: stepResult.error,
|
|
83
|
+
});
|
|
84
|
+
result.success = stepResult.success;
|
|
85
|
+
}
|
|
86
|
+
else if (script.steps) {
|
|
87
|
+
// Multi-step script
|
|
88
|
+
for (const step of script.steps) {
|
|
89
|
+
const cwd = step.cwd ? resolve(rootDir, step.cwd) : rootDir;
|
|
90
|
+
const stepResult = await runCommand(step.command, cwd, env);
|
|
91
|
+
result.steps.push({
|
|
92
|
+
name: step.name,
|
|
93
|
+
command: step.command,
|
|
94
|
+
cwd,
|
|
95
|
+
success: stepResult.success,
|
|
96
|
+
exitCode: stepResult.exitCode,
|
|
97
|
+
error: stepResult.error,
|
|
98
|
+
});
|
|
99
|
+
if (!stepResult.success) {
|
|
100
|
+
result.success = false;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
throw new Error(`Script '${scriptName}' has neither command nor steps defined`);
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get list of available scripts
|
|
112
|
+
*/
|
|
113
|
+
export function listScripts(manifest) {
|
|
114
|
+
const workspace = manifest.workspace;
|
|
115
|
+
if (!workspace?.scripts) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
return Object.entries(workspace.scripts).map(([name, script]) => ({
|
|
119
|
+
name,
|
|
120
|
+
description: script.description,
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=scripts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/lib/scripts.ts"],"names":[],"mappings":"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"}
|