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.
Files changed (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +211 -0
  3. package/actions/cross-repo-sync/action.yml +55 -0
  4. package/assets/banner.svg +73 -0
  5. package/assets/icon.svg +30 -0
  6. package/assets/logo-dark.svg +36 -0
  7. package/assets/logo.svg +36 -0
  8. package/dist/commands/add.d.ts +9 -0
  9. package/dist/commands/add.d.ts.map +1 -0
  10. package/dist/commands/add.js +80 -0
  11. package/dist/commands/add.js.map +1 -0
  12. package/dist/commands/bench.d.ts +12 -0
  13. package/dist/commands/bench.d.ts.map +1 -0
  14. package/dist/commands/bench.js +136 -0
  15. package/dist/commands/bench.js.map +1 -0
  16. package/dist/commands/branch.d.ts +15 -0
  17. package/dist/commands/branch.d.ts.map +1 -0
  18. package/dist/commands/branch.js +159 -0
  19. package/dist/commands/branch.js.map +1 -0
  20. package/dist/commands/checkout.d.ts +10 -0
  21. package/dist/commands/checkout.d.ts.map +1 -0
  22. package/dist/commands/checkout.js +85 -0
  23. package/dist/commands/checkout.js.map +1 -0
  24. package/dist/commands/commit.d.ts +10 -0
  25. package/dist/commands/commit.d.ts.map +1 -0
  26. package/dist/commands/commit.js +94 -0
  27. package/dist/commands/commit.js.map +1 -0
  28. package/dist/commands/diff.d.ts +11 -0
  29. package/dist/commands/diff.d.ts.map +1 -0
  30. package/dist/commands/diff.js +105 -0
  31. package/dist/commands/diff.js.map +1 -0
  32. package/dist/commands/env.d.ts +8 -0
  33. package/dist/commands/env.d.ts.map +1 -0
  34. package/dist/commands/env.js +35 -0
  35. package/dist/commands/env.js.map +1 -0
  36. package/dist/commands/forall.d.ts +13 -0
  37. package/dist/commands/forall.d.ts.map +1 -0
  38. package/dist/commands/forall.js +116 -0
  39. package/dist/commands/forall.js.map +1 -0
  40. package/dist/commands/init.d.ts +15 -0
  41. package/dist/commands/init.d.ts.map +1 -0
  42. package/dist/commands/init.js +106 -0
  43. package/dist/commands/init.js.map +1 -0
  44. package/dist/commands/link.d.ts +11 -0
  45. package/dist/commands/link.d.ts.map +1 -0
  46. package/dist/commands/link.js +205 -0
  47. package/dist/commands/link.js.map +1 -0
  48. package/dist/commands/migrate.d.ts +17 -0
  49. package/dist/commands/migrate.d.ts.map +1 -0
  50. package/dist/commands/migrate.js +180 -0
  51. package/dist/commands/migrate.js.map +1 -0
  52. package/dist/commands/pr/create.d.ts +13 -0
  53. package/dist/commands/pr/create.d.ts.map +1 -0
  54. package/dist/commands/pr/create.js +202 -0
  55. package/dist/commands/pr/create.js.map +1 -0
  56. package/dist/commands/pr/index.d.ts +4 -0
  57. package/dist/commands/pr/index.d.ts.map +1 -0
  58. package/dist/commands/pr/index.js +4 -0
  59. package/dist/commands/pr/index.js.map +1 -0
  60. package/dist/commands/pr/merge.d.ts +11 -0
  61. package/dist/commands/pr/merge.d.ts.map +1 -0
  62. package/dist/commands/pr/merge.js +168 -0
  63. package/dist/commands/pr/merge.js.map +1 -0
  64. package/dist/commands/pr/status.d.ts +9 -0
  65. package/dist/commands/pr/status.d.ts.map +1 -0
  66. package/dist/commands/pr/status.js +139 -0
  67. package/dist/commands/pr/status.js.map +1 -0
  68. package/dist/commands/push.d.ts +10 -0
  69. package/dist/commands/push.d.ts.map +1 -0
  70. package/dist/commands/push.js +101 -0
  71. package/dist/commands/push.js.map +1 -0
  72. package/dist/commands/run.d.ts +8 -0
  73. package/dist/commands/run.d.ts.map +1 -0
  74. package/dist/commands/run.js +75 -0
  75. package/dist/commands/run.js.map +1 -0
  76. package/dist/commands/status.d.ts +9 -0
  77. package/dist/commands/status.d.ts.map +1 -0
  78. package/dist/commands/status.js +201 -0
  79. package/dist/commands/status.js.map +1 -0
  80. package/dist/commands/sync.d.ts +13 -0
  81. package/dist/commands/sync.d.ts.map +1 -0
  82. package/dist/commands/sync.js +183 -0
  83. package/dist/commands/sync.js.map +1 -0
  84. package/dist/index.d.ts +3 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +352 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/lib/__bench__/files.bench.d.ts +2 -0
  89. package/dist/lib/__bench__/files.bench.d.ts.map +1 -0
  90. package/dist/lib/__bench__/files.bench.js +52 -0
  91. package/dist/lib/__bench__/files.bench.js.map +1 -0
  92. package/dist/lib/__bench__/manifest.bench.d.ts +2 -0
  93. package/dist/lib/__bench__/manifest.bench.d.ts.map +1 -0
  94. package/dist/lib/__bench__/manifest.bench.js +74 -0
  95. package/dist/lib/__bench__/manifest.bench.js.map +1 -0
  96. package/dist/lib/files.d.ts +84 -0
  97. package/dist/lib/files.d.ts.map +1 -0
  98. package/dist/lib/files.js +492 -0
  99. package/dist/lib/files.js.map +1 -0
  100. package/dist/lib/git.d.ts +125 -0
  101. package/dist/lib/git.d.ts.map +1 -0
  102. package/dist/lib/git.js +370 -0
  103. package/dist/lib/git.js.map +1 -0
  104. package/dist/lib/github.d.ts +92 -0
  105. package/dist/lib/github.d.ts.map +1 -0
  106. package/dist/lib/github.js +284 -0
  107. package/dist/lib/github.js.map +1 -0
  108. package/dist/lib/hooks.d.ts +19 -0
  109. package/dist/lib/hooks.d.ts.map +1 -0
  110. package/dist/lib/hooks.js +63 -0
  111. package/dist/lib/hooks.js.map +1 -0
  112. package/dist/lib/linker.d.ts +56 -0
  113. package/dist/lib/linker.d.ts.map +1 -0
  114. package/dist/lib/linker.js +185 -0
  115. package/dist/lib/linker.js.map +1 -0
  116. package/dist/lib/manifest.d.ts +73 -0
  117. package/dist/lib/manifest.d.ts.map +1 -0
  118. package/dist/lib/manifest.js +400 -0
  119. package/dist/lib/manifest.js.map +1 -0
  120. package/dist/lib/scripts.d.ts +26 -0
  121. package/dist/lib/scripts.d.ts.map +1 -0
  122. package/dist/lib/scripts.js +123 -0
  123. package/dist/lib/scripts.js.map +1 -0
  124. package/dist/lib/timing.d.ts +100 -0
  125. package/dist/lib/timing.d.ts.map +1 -0
  126. package/dist/lib/timing.js +293 -0
  127. package/dist/lib/timing.js.map +1 -0
  128. package/dist/types.d.ts +312 -0
  129. package/dist/types.d.ts.map +1 -0
  130. package/dist/types.js +2 -0
  131. package/dist/types.js.map +1 -0
  132. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Layne Penney
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # gitgrip
2
+
3
+ **git a grip** - Multi-repo workflow tool
4
+
5
+ Manage multiple related repositories as a single workspace with synchronized branches, linked pull requests, and atomic merges.
6
+
7
+ Inspired by Android's [repo tool](https://source.android.com/docs/setup/create/repo), gitgrip brings manifest-based multi-repo management to any project.
8
+
9
+ ## Features
10
+
11
+ - **Manifest-based configuration** - Define all your repos in a single YAML file
12
+ - **Synchronized branches** - Create and checkout branches across all repos at once
13
+ - **Linked PRs** - Create pull requests that reference each other across repos
14
+ - **Atomic merges** - All-or-nothing merge strategy ensures repos stay in sync
15
+ - **Status dashboard** - See the state of all repos at a glance
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install -g gitgrip
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ### 1. Create a manifest repository
26
+
27
+ Create a new repo to hold your workspace manifest (e.g., `my-workspace`), then add a `manifest.yaml`:
28
+
29
+ ```yaml
30
+ version: 1
31
+
32
+ manifest:
33
+ url: git@github.com:your-org/my-workspace.git
34
+
35
+ repos:
36
+ frontend:
37
+ url: git@github.com:your-org/frontend.git
38
+ path: ./frontend
39
+ default_branch: main
40
+
41
+ backend:
42
+ url: git@github.com:your-org/backend.git
43
+ path: ./backend
44
+ default_branch: main
45
+
46
+ shared:
47
+ url: git@github.com:your-org/shared-libs.git
48
+ path: ./shared
49
+ default_branch: main
50
+
51
+ settings:
52
+ pr_prefix: "[cross-repo]"
53
+ merge_strategy: all-or-nothing
54
+ ```
55
+
56
+ ### 2. Initialize a workspace
57
+
58
+ ```bash
59
+ mkdir my-workspace && cd my-workspace
60
+ gr init git@github.com:your-org/my-workspace.git
61
+ ```
62
+
63
+ This clones the manifest repo into `.gitgrip/manifests/` and all defined repositories.
64
+
65
+ ### 3. Start working
66
+
67
+ ```bash
68
+ # Check status of all repos
69
+ gr status
70
+
71
+ # Create a feature branch across all repos
72
+ gr branch feature/new-feature
73
+
74
+ # Make changes, commit in each repo, then create linked PRs
75
+ gr pr create --title "Add new feature"
76
+
77
+ # Sync all repos with latest from remote
78
+ gr sync
79
+ ```
80
+
81
+ ## Commands
82
+
83
+ | Command | Description |
84
+ |---------|-------------|
85
+ | `gr init <url>` | Initialize workspace from manifest repo |
86
+ | `gr sync` | Pull latest from all repos |
87
+ | `gr status` | Show status of all repos |
88
+ | `gr branch [name]` | Create or list branches |
89
+ | `gr checkout <branch>` | Checkout branch across repos |
90
+ | `gr add [files]` | Stage changes across repos |
91
+ | `gr diff` | Show diff across repos |
92
+ | `gr commit -m "msg"` | Commit across repos |
93
+ | `gr push` | Push across repos |
94
+ | `gr pr create` | Create linked PRs |
95
+ | `gr pr status` | Show PR status |
96
+ | `gr pr merge` | Merge all linked PRs |
97
+ | `gr forall -c "cmd"` | Run command in each repo |
98
+
99
+ ### Command Details
100
+
101
+ #### `gr init <manifest-url>`
102
+
103
+ Initialize a new workspace by cloning the manifest repository and all defined repos.
104
+
105
+ #### `gr sync [options]`
106
+
107
+ Pull latest changes from the manifest and all repositories.
108
+
109
+ | Option | Description |
110
+ |--------|-------------|
111
+ | `--fetch` | Fetch only, don't merge |
112
+ | `--no-link` | Skip processing copyfile/linkfile entries |
113
+ | `--no-hooks` | Skip running post-sync hooks |
114
+
115
+ #### `gr status`
116
+
117
+ Show status of all repositories including branch, changes, and sync state.
118
+
119
+ #### `gr branch [name]`
120
+
121
+ Create a new branch across all repositories, or list existing branches.
122
+
123
+ | Option | Description |
124
+ |--------|-------------|
125
+ | `-r, --repo <repos...>` | Only operate on specific repos |
126
+ | `--include-manifest` | Include manifest repo |
127
+
128
+ #### `gr pr create`
129
+
130
+ Create linked PRs across repos with changes.
131
+
132
+ | Option | Description |
133
+ |--------|-------------|
134
+ | `-t, --title <title>` | PR title |
135
+ | `-b, --body <body>` | PR body |
136
+ | `-d, --draft` | Create as draft |
137
+ | `--push` | Push branches first |
138
+
139
+ #### `gr pr merge`
140
+
141
+ Merge all linked PRs atomically.
142
+
143
+ | Option | Description |
144
+ |--------|-------------|
145
+ | `-m, --method <method>` | merge, squash, or rebase |
146
+ | `--no-delete-branch` | Keep branches after merge |
147
+ | `-f, --force` | Merge even if checks pending |
148
+
149
+ #### `gr forall -c "<command>"`
150
+
151
+ Run a command in each repository (like AOSP's `repo forall`).
152
+
153
+ | Option | Description |
154
+ |--------|-------------|
155
+ | `-c, --command` | Command to run (required) |
156
+ | `-r, --repo <repos...>` | Only run in specific repos |
157
+ | `--include-manifest` | Include manifest repo |
158
+ | `--continue-on-error` | Continue if command fails |
159
+
160
+ Environment variables available in command:
161
+ - `REPO_NAME` - Repository name
162
+ - `REPO_PATH` - Absolute path to repo
163
+ - `REPO_URL` - Repository URL
164
+
165
+ ## Manifest Format
166
+
167
+ The manifest file (`manifest.yaml`) defines your workspace:
168
+
169
+ ```yaml
170
+ version: 1
171
+
172
+ manifest:
173
+ url: git@github.com:your-org/workspace.git
174
+
175
+ repos:
176
+ repo-name:
177
+ url: git@github.com:your-org/repo.git
178
+ path: ./local-path
179
+ default_branch: main
180
+
181
+ settings:
182
+ pr_prefix: "[cross-repo]"
183
+ merge_strategy: all-or-nothing
184
+ ```
185
+
186
+ ### Merge Strategies
187
+
188
+ - **all-or-nothing** - All linked PRs must be approved before any can merge
189
+ - **independent** - PRs can be merged independently
190
+
191
+ ## Shorthand
192
+
193
+ Use `gr` as the primary command:
194
+
195
+ ```bash
196
+ gr status
197
+ gr sync
198
+ gr branch feature/foo
199
+ ```
200
+
201
+ The long form `gitgrip` also works.
202
+
203
+ ## Requirements
204
+
205
+ - Node.js >= 18.0.0
206
+ - Git
207
+ - GitHub CLI (`gh`) for PR operations
208
+
209
+ ## License
210
+
211
+ MIT
@@ -0,0 +1,55 @@
1
+ name: 'Cross-Repo PR Status Sync'
2
+ description: 'Synchronize status between linked cross-repository PRs'
3
+ author: 'gitgrip'
4
+
5
+ inputs:
6
+ manifest_repo:
7
+ description: 'The manifest repository (owner/repo format)'
8
+ required: true
9
+ github_token:
10
+ description: 'GitHub token with access to all linked repos'
11
+ required: true
12
+ manifest_pr:
13
+ description: 'Manifest PR number (auto-detected if not provided)'
14
+ required: false
15
+
16
+ runs:
17
+ using: 'composite'
18
+ steps:
19
+ - name: Set up Node.js
20
+ uses: actions/setup-node@v4
21
+ with:
22
+ node-version: '20'
23
+
24
+ - name: Install gitgrip
25
+ shell: bash
26
+ run: |
27
+ npm install -g gitgrip || npm install gitgrip
28
+
29
+ - name: Sync PR Status
30
+ shell: bash
31
+ env:
32
+ GITHUB_TOKEN: ${{ inputs.github_token }}
33
+ MANIFEST_REPO: ${{ inputs.manifest_repo }}
34
+ MANIFEST_PR: ${{ inputs.manifest_pr }}
35
+ run: |
36
+ # If manifest PR is provided, sync that specific PR
37
+ if [ -n "$MANIFEST_PR" ]; then
38
+ echo "Syncing manifest PR #$MANIFEST_PR"
39
+ gr pr status --json > status.json
40
+
41
+ # Update manifest PR body with current status
42
+ # This would call the GitHub API to update the PR
43
+ echo "PR status updated"
44
+ else
45
+ echo "No manifest PR specified, checking PR context"
46
+ # In a PR context, we can get the PR number from the event
47
+ if [ -n "${{ github.event.pull_request.number }}" ]; then
48
+ echo "Found PR #${{ github.event.pull_request.number }}"
49
+ gr pr status
50
+ fi
51
+ fi
52
+
53
+ branding:
54
+ icon: 'git-pull-request'
55
+ color: 'blue'
@@ -0,0 +1,73 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 200" width="800" height="200">
2
+ <defs>
3
+ <linearGradient id="banner-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#8B5CF6"/>
5
+ <stop offset="50%" style="stop-color:#6366F1"/>
6
+ <stop offset="100%" style="stop-color:#3B82F6"/>
7
+ </linearGradient>
8
+ <linearGradient id="bg-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
9
+ <stop offset="0%" style="stop-color:#0f0f1a"/>
10
+ <stop offset="100%" style="stop-color:#1a1a2e"/>
11
+ </linearGradient>
12
+ </defs>
13
+
14
+ <!-- Background -->
15
+ <rect width="800" height="200" fill="url(#bg-gradient)"/>
16
+
17
+ <!-- Decorative connection lines in background -->
18
+ <g opacity="0.1" stroke="#8B5CF6" stroke-width="1">
19
+ <line x1="50" y1="40" x2="120" y2="80"/>
20
+ <line x1="120" y1="80" x2="80" y2="140"/>
21
+ <line x1="120" y1="80" x2="180" y2="60"/>
22
+ <line x1="650" y1="120" x2="720" y2="80"/>
23
+ <line x1="720" y1="80" x2="750" y2="140"/>
24
+ <line x1="720" y1="80" x2="680" y2="40"/>
25
+ </g>
26
+
27
+ <!-- Background nodes -->
28
+ <circle cx="50" cy="40" r="4" fill="#8B5CF6" opacity="0.2"/>
29
+ <circle cx="120" cy="80" r="6" fill="#6366F1" opacity="0.25"/>
30
+ <circle cx="80" cy="140" r="4" fill="#3B82F6" opacity="0.2"/>
31
+ <circle cx="180" cy="60" r="3" fill="#A78BFA" opacity="0.15"/>
32
+ <circle cx="650" cy="120" r="4" fill="#8B5CF6" opacity="0.2"/>
33
+ <circle cx="720" cy="80" r="6" fill="#6366F1" opacity="0.25"/>
34
+ <circle cx="750" cy="140" r="4" fill="#3B82F6" opacity="0.2"/>
35
+ <circle cx="680" cy="40" r="3" fill="#60A5FA" opacity="0.15"/>
36
+
37
+ <!-- Floating particles -->
38
+ <circle cx="100" cy="160" r="2" fill="#8B5CF6" opacity="0.4"/>
39
+ <circle cx="700" cy="40" r="2" fill="#3B82F6" opacity="0.4"/>
40
+ <circle cx="200" cy="30" r="1.5" fill="#A78BFA" opacity="0.3"/>
41
+ <circle cx="600" cy="170" r="1.5" fill="#60A5FA" opacity="0.3"/>
42
+
43
+ <!-- Main logo group centered -->
44
+ <g transform="translate(250, 50)">
45
+ <!-- Icon background -->
46
+ <rect x="0" y="0" width="100" height="100" rx="20" fill="url(#banner-gradient)"/>
47
+
48
+ <!-- Central hub node -->
49
+ <circle cx="50" cy="50" r="12" fill="white" opacity="0.95"/>
50
+
51
+ <!-- Connection lines -->
52
+ <line x1="50" y1="50" x2="28" y2="28" stroke="white" stroke-width="3" opacity="0.7"/>
53
+ <line x1="50" y1="50" x2="72" y2="28" stroke="white" stroke-width="3" opacity="0.7"/>
54
+ <line x1="50" y1="50" x2="28" y2="72" stroke="white" stroke-width="3" opacity="0.7"/>
55
+ <line x1="50" y1="50" x2="72" y2="72" stroke="white" stroke-width="3" opacity="0.7"/>
56
+
57
+ <!-- Outer nodes -->
58
+ <circle cx="28" cy="28" r="7" fill="white" opacity="0.9"/>
59
+ <circle cx="72" cy="28" r="7" fill="white" opacity="0.9"/>
60
+ <circle cx="28" cy="72" r="7" fill="white" opacity="0.9"/>
61
+ <circle cx="72" cy="72" r="7" fill="white" opacity="0.9"/>
62
+
63
+ <!-- Sparkles on icon -->
64
+ <circle cx="86" cy="18" r="4" fill="white" opacity="0.8"/>
65
+ <circle cx="94" cy="10" r="2" fill="white" opacity="0.6"/>
66
+
67
+ <!-- Text "codi-repo" -->
68
+ <text x="120" y="65" font-family="system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif" font-size="56" font-weight="700" fill="white">codi-repo</text>
69
+ </g>
70
+
71
+ <!-- Tagline -->
72
+ <text x="400" y="175" text-anchor="middle" font-family="system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif" font-size="18" fill="#9CA3AF">Multi-repo orchestration for unified PR workflows</text>
73
+ </svg>
@@ -0,0 +1,30 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
2
+ <defs>
3
+ <linearGradient id="icon-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#8B5CF6"/>
5
+ <stop offset="100%" style="stop-color:#3B82F6"/>
6
+ </linearGradient>
7
+ </defs>
8
+
9
+ <!-- Outer rounded square -->
10
+ <rect x="4" y="4" width="56" height="56" rx="12" fill="url(#icon-gradient)"/>
11
+
12
+ <!-- Central hub node -->
13
+ <circle cx="32" cy="32" r="8" fill="white" opacity="0.95"/>
14
+
15
+ <!-- Connection lines to outer nodes -->
16
+ <line x1="32" y1="32" x2="18" y2="18" stroke="white" stroke-width="2.5" opacity="0.7"/>
17
+ <line x1="32" y1="32" x2="46" y2="18" stroke="white" stroke-width="2.5" opacity="0.7"/>
18
+ <line x1="32" y1="32" x2="18" y2="46" stroke="white" stroke-width="2.5" opacity="0.7"/>
19
+ <line x1="32" y1="32" x2="46" y2="46" stroke="white" stroke-width="2.5" opacity="0.7"/>
20
+
21
+ <!-- Outer repo nodes -->
22
+ <circle cx="18" cy="18" r="5" fill="white" opacity="0.9"/>
23
+ <circle cx="46" cy="18" r="5" fill="white" opacity="0.9"/>
24
+ <circle cx="18" cy="46" r="5" fill="white" opacity="0.9"/>
25
+ <circle cx="46" cy="46" r="5" fill="white" opacity="0.9"/>
26
+
27
+ <!-- Sparkle accents -->
28
+ <circle cx="52" cy="12" r="2.5" fill="white" opacity="0.8"/>
29
+ <circle cx="56" cy="8" r="1.5" fill="white" opacity="0.6"/>
30
+ </svg>
@@ -0,0 +1,36 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 260 60" width="260" height="60">
2
+ <defs>
3
+ <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#8B5CF6"/>
5
+ <stop offset="100%" style="stop-color:#3B82F6"/>
6
+ </linearGradient>
7
+ </defs>
8
+
9
+ <!-- Icon -->
10
+ <g transform="translate(10, 10)">
11
+ <!-- Outer rounded square -->
12
+ <rect x="0" y="0" width="40" height="40" rx="8" fill="url(#gradient)"/>
13
+
14
+ <!-- Central hub node -->
15
+ <circle cx="20" cy="20" r="5" fill="white" opacity="0.95"/>
16
+
17
+ <!-- Connection lines -->
18
+ <line x1="20" y1="20" x2="11" y2="11" stroke="white" stroke-width="1.5" opacity="0.7"/>
19
+ <line x1="20" y1="20" x2="29" y2="11" stroke="white" stroke-width="1.5" opacity="0.7"/>
20
+ <line x1="20" y1="20" x2="11" y2="29" stroke="white" stroke-width="1.5" opacity="0.7"/>
21
+ <line x1="20" y1="20" x2="29" y2="29" stroke="white" stroke-width="1.5" opacity="0.7"/>
22
+
23
+ <!-- Outer nodes -->
24
+ <circle cx="11" cy="11" r="3" fill="white" opacity="0.9"/>
25
+ <circle cx="29" cy="11" r="3" fill="white" opacity="0.9"/>
26
+ <circle cx="11" cy="29" r="3" fill="white" opacity="0.9"/>
27
+ <circle cx="29" cy="29" r="3" fill="white" opacity="0.9"/>
28
+
29
+ <!-- Sparkles -->
30
+ <circle cx="34" cy="6" r="2" fill="white" opacity="0.8"/>
31
+ <circle cx="38" cy="3" r="1" fill="white" opacity="0.6"/>
32
+ </g>
33
+
34
+ <!-- Text "codi-repo" in white for dark backgrounds -->
35
+ <text x="60" y="40" font-family="system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif" font-size="28" font-weight="700" fill="white">codi-repo</text>
36
+ </svg>
@@ -0,0 +1,36 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 260 60" width="260" height="60">
2
+ <defs>
3
+ <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#8B5CF6"/>
5
+ <stop offset="100%" style="stop-color:#3B82F6"/>
6
+ </linearGradient>
7
+ </defs>
8
+
9
+ <!-- Icon -->
10
+ <g transform="translate(10, 10)">
11
+ <!-- Outer rounded square -->
12
+ <rect x="0" y="0" width="40" height="40" rx="8" fill="url(#gradient)"/>
13
+
14
+ <!-- Central hub node -->
15
+ <circle cx="20" cy="20" r="5" fill="white" opacity="0.95"/>
16
+
17
+ <!-- Connection lines -->
18
+ <line x1="20" y1="20" x2="11" y2="11" stroke="white" stroke-width="1.5" opacity="0.7"/>
19
+ <line x1="20" y1="20" x2="29" y2="11" stroke="white" stroke-width="1.5" opacity="0.7"/>
20
+ <line x1="20" y1="20" x2="11" y2="29" stroke="white" stroke-width="1.5" opacity="0.7"/>
21
+ <line x1="20" y1="20" x2="29" y2="29" stroke="white" stroke-width="1.5" opacity="0.7"/>
22
+
23
+ <!-- Outer nodes -->
24
+ <circle cx="11" cy="11" r="3" fill="white" opacity="0.9"/>
25
+ <circle cx="29" cy="11" r="3" fill="white" opacity="0.9"/>
26
+ <circle cx="11" cy="29" r="3" fill="white" opacity="0.9"/>
27
+ <circle cx="29" cy="29" r="3" fill="white" opacity="0.9"/>
28
+
29
+ <!-- Sparkles -->
30
+ <circle cx="34" cy="6" r="2" fill="white" opacity="0.8"/>
31
+ <circle cx="38" cy="3" r="1" fill="white" opacity="0.6"/>
32
+ </g>
33
+
34
+ <!-- Text "codi-repo" -->
35
+ <text x="60" y="40" font-family="system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif" font-size="28" font-weight="700" fill="url(#gradient)">codi-repo</text>
36
+ </svg>
@@ -0,0 +1,9 @@
1
+ interface AddOptions {
2
+ all?: boolean;
3
+ }
4
+ /**
5
+ * Stage changes across all repositories
6
+ */
7
+ export declare function add(files: string[], options?: AddOptions): Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAMA,UAAU,UAAU;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AA+BD;;GAEG;AACH,wBAAsB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA8DlF"}
@@ -0,0 +1,80 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { loadManifest, getAllRepoInfo, getManifestRepoInfo } from '../lib/manifest.js';
4
+ import { pathExists, getGitInstance, isGitRepo } from '../lib/git.js';
5
+ /**
6
+ * Get count of unstaged changes in a repo
7
+ */
8
+ async function getUnstagedCount(repoPath) {
9
+ const git = getGitInstance(repoPath);
10
+ const status = await git.status();
11
+ return status.modified.length + status.not_added.length + status.deleted.length;
12
+ }
13
+ /**
14
+ * Stage files in a repo
15
+ */
16
+ async function stageFiles(repoPath, files) {
17
+ const git = getGitInstance(repoPath);
18
+ if (files.length === 1 && (files[0] === '.' || files[0] === '-A')) {
19
+ await git.add('-A');
20
+ }
21
+ else {
22
+ await git.add(files);
23
+ }
24
+ }
25
+ /**
26
+ * Stage changes across all repositories
27
+ */
28
+ export async function add(files, options = {}) {
29
+ // Default to staging all if no files specified (or if -A flag used)
30
+ const filesToAdd = (files.length > 0 && !options.all) ? files : ['.'];
31
+ const { manifest, rootDir } = await loadManifest();
32
+ let repos = getAllRepoInfo(manifest, rootDir);
33
+ // Include manifest repo if it has changes
34
+ const manifestInfo = getManifestRepoInfo(manifest, rootDir);
35
+ if (manifestInfo && await isGitRepo(manifestInfo.absolutePath)) {
36
+ repos = [...repos, manifestInfo];
37
+ }
38
+ const results = [];
39
+ let hasChanges = false;
40
+ console.log(chalk.blue('Checking repositories for changes to stage...\n'));
41
+ for (const repo of repos) {
42
+ const exists = await pathExists(repo.absolutePath);
43
+ if (!exists) {
44
+ continue;
45
+ }
46
+ // Check if there are unstaged changes
47
+ const unstagedCount = await getUnstagedCount(repo.absolutePath);
48
+ if (unstagedCount === 0) {
49
+ continue;
50
+ }
51
+ hasChanges = true;
52
+ const spinner = ora(`Staging ${repo.name}...`).start();
53
+ try {
54
+ await stageFiles(repo.absolutePath, filesToAdd);
55
+ spinner.succeed(`${repo.name}: staged ${unstagedCount} file(s)`);
56
+ results.push({ repo, success: true, staged: true, files: unstagedCount });
57
+ }
58
+ catch (error) {
59
+ const errorMsg = error instanceof Error ? error.message : String(error);
60
+ spinner.fail(`${repo.name}: ${errorMsg}`);
61
+ results.push({ repo, success: false, staged: false, error: errorMsg });
62
+ }
63
+ }
64
+ if (!hasChanges) {
65
+ console.log(chalk.yellow('No changes to stage in any repository.'));
66
+ return;
67
+ }
68
+ // Summary
69
+ console.log('');
70
+ const staged = results.filter((r) => r.staged).length;
71
+ const totalFiles = results.reduce((sum, r) => sum + (r.files ?? 0), 0);
72
+ const failed = results.filter((r) => !r.success).length;
73
+ if (failed === 0) {
74
+ console.log(chalk.green(`Staged ${totalFiles} file(s) in ${staged} repository(s).`));
75
+ }
76
+ else {
77
+ console.log(chalk.yellow(`Staged in ${staged} repository(s). ${failed} failed.`));
78
+ }
79
+ }
80
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ interface BenchOptions {
2
+ list?: boolean;
3
+ iterations?: number;
4
+ warmup?: number;
5
+ json?: boolean;
6
+ }
7
+ /**
8
+ * Benchmark workspace operations
9
+ */
10
+ export declare function bench(operation: string | undefined, options?: BenchOptions): Promise<void>;
11
+ export {};
12
+ //# sourceMappingURL=bench.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bench.d.ts","sourceRoot":"","sources":["../../src/commands/bench.ts"],"names":[],"mappings":"AAOA,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA8ED;;GAEG;AACH,wBAAsB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkEpG"}