geet-geet 0.1.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/README.md +58 -0
- package/bin/geet.sh +150 -0
- package/docs/AUTO_PROMOTE.md +173 -0
- package/docs/CONTRIBUTING.md +142 -0
- package/docs/DEMO.md +131 -0
- package/docs/DEV_GUIDE.md +519 -0
- package/docs/FAQ.md +128 -0
- package/docs/MERGE_KEEP_OURS.md +243 -0
- package/docs/MULTI_LAYERED_TEMPLATES.md +92 -0
- package/docs/PREVENT_COMMIT_PATTERNS.md +250 -0
- package/docs/PUBLISHING_A_TEMPLATE.md +150 -0
- package/docs/UNDERSTANDING_GEET.md +68 -0
- package/docs/USING_A_TEMPLATE.md +131 -0
- package/lib/detach.sh +225 -0
- package/lib/digest-and-locate.sh +476 -0
- package/lib/doctor.sh +252 -0
- package/lib/flags.sh +52 -0
- package/lib/ghcli.sh +386 -0
- package/lib/git.sh +55 -0
- package/lib/help.sh +53 -0
- package/lib/ignored.sh +4 -0
- package/lib/include.sh +54 -0
- package/lib/init.sh +234 -0
- package/lib/install.sh +166 -0
- package/lib/logger.sh +278 -0
- package/lib/pre-commit/auto-promote-pgi.sh +20 -0
- package/lib/pre-commit/auto-promote-readme.sh +20 -0
- package/lib/pre-commit/hook.sh +66 -0
- package/lib/pre-commit/protect-patterns.sh +76 -0
- package/lib/pre-commit/unstage-soft-detached-files.sh +48 -0
- package/lib/prework.sh +181 -0
- package/lib/session.sh +111 -0
- package/lib/split.sh +120 -0
- package/lib/sync.sh +98 -0
- package/lib/template.sh +635 -0
- package/lib/tree.sh +252 -0
- package/lib/whoops.sh +37 -0
- package/package.json +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# geet — layered template system
|
|
2
|
+
https://github.com/modularizer/geet
|
|
3
|
+
|
|
4
|
+
> **One working directory**. **Multiple Git repositories**. Each repo tracks a different subset of files.
|
|
5
|
+
|
|
6
|
+
Nothing moves.
|
|
7
|
+
Nothing is copied.
|
|
8
|
+
Only Git's *view* of the filesystem changes.
|
|
9
|
+
|
|
10
|
+
## Why?
|
|
11
|
+
> “I built something useful, and I think that **SOME but not all of my code is re-usable**.
|
|
12
|
+
I want to publish some of my code for other's to use (or to re-use myself)...
|
|
13
|
+
but **I don't want to spend weeks refactoring** to split apart the reusable code from the implementation-specific code.
|
|
14
|
+
In fact, it may not even be possible to move around all my files without breaking things.
|
|
15
|
+
Plus, supporting this template is my **secondary task** which I want to do in tandem with my **primary development**, using my main repository's working directory and publishing some pieces to the template repo.”
|
|
16
|
+
|
|
17
|
+
- **Making code re-usable is a struggle**, especially if you want to ship an incomplete template that is not easily separated into a standalone module.
|
|
18
|
+
- Modern React Native / Expo apps are **extremely path-sensitive**:
|
|
19
|
+
* file-based routing
|
|
20
|
+
* config files at exact paths
|
|
21
|
+
* native folders
|
|
22
|
+
* toolchains that assume canonical layouts
|
|
23
|
+
- templates are not static: they evolve over time. I don't want to wait until a template is fully perfect before adding to my project, and I want to get features and fixes as the come
|
|
24
|
+
- syncing sucks
|
|
25
|
+
- submodules don't support interleaving files and folders of template code with custom app code
|
|
26
|
+
- I want to simultaneously develop many apps with a similar architecture
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
## PreReqs
|
|
30
|
+
1. `git` - for pretty much everything
|
|
31
|
+
2. `npm` - really just for installing `geet` globally
|
|
32
|
+
3. `gh` - for use of `publish` command and `--publish`, `--private`, `--internal` flags
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Quickstart
|
|
38
|
+
```bash
|
|
39
|
+
npm install -g geet-geet
|
|
40
|
+
geet
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Try our [Demo](/docs/DEMO.md)
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Table of Contents
|
|
48
|
+
|
|
49
|
+
1. [Understanding geet](/docs/UNDERSTANDING_GEET.md)
|
|
50
|
+
2. [Using a geet template](/docs/USING_A_TEMPLATE.md)
|
|
51
|
+
3. [Publishing a geet template](/docs/PUBLISHING_A_TEMPLATE.md)
|
|
52
|
+
4. [Multi-layered repos](/docs/MULTI_LAYERED_TEMPLATES.md)
|
|
53
|
+
5. [Advanced: File promotion](/docs/AUTO_PROMOTE.md)
|
|
54
|
+
6. [Advanced: Merge keep-ours strategy](/docs/MERGE_KEEP_OURS.md)
|
|
55
|
+
7. [Advanced: Preventing app-specific code](/docs/PREVENT_COMMIT_PATTERNS.md)
|
|
56
|
+
8. [Contributing to geet](/docs/CONTRIBUTING.md)
|
|
57
|
+
9. [FAQ](/docs/FAQ.md)
|
|
58
|
+
10. [Demo](/docs/DEMO.md)
|
package/bin/geet.sh
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
trap 'echo "ERR at ${BASH_SOURCE[0]}:${LINENO}: $BASH_COMMAND" >&2' ERR
|
|
4
|
+
|
|
5
|
+
NODE_BIN="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
GEET_LIB="$(cd -- "$NODE_BIN/../lib/node_modules/geet-geet/lib" && pwd)"
|
|
7
|
+
GEET_ARGS=("$@")
|
|
8
|
+
source "$GEET_LIB/digest-and-locate.sh" "$@"
|
|
9
|
+
debug "GEET_ARGS=${GEET_ARGS[@]}"
|
|
10
|
+
cmd="${1:-help}"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
shift || true
|
|
14
|
+
|
|
15
|
+
case "$cmd" in
|
|
16
|
+
help|-h|--help)
|
|
17
|
+
source "$GEET_LIB/help.sh"
|
|
18
|
+
help
|
|
19
|
+
;;
|
|
20
|
+
|
|
21
|
+
sync)
|
|
22
|
+
source "$GEET_LIB/sync.sh"
|
|
23
|
+
sync "${GEET_ARGS[@]:1}"
|
|
24
|
+
;;
|
|
25
|
+
|
|
26
|
+
# Explicit non-git commands
|
|
27
|
+
init)
|
|
28
|
+
source "$GEET_LIB/init.sh"
|
|
29
|
+
init "${GEET_ARGS[@]:1}"
|
|
30
|
+
;;
|
|
31
|
+
|
|
32
|
+
tree)
|
|
33
|
+
source "$GEET_LIB/tree.sh"
|
|
34
|
+
tree "${GEET_ARGS[@]:1}"
|
|
35
|
+
;;
|
|
36
|
+
|
|
37
|
+
split)
|
|
38
|
+
source "$GEET_LIB/split.sh"
|
|
39
|
+
split "${GEET_ARGS[@]:1}"
|
|
40
|
+
;;
|
|
41
|
+
|
|
42
|
+
session)
|
|
43
|
+
source "$GEET_LIB/session.sh"
|
|
44
|
+
session "${GEET_ARGS[@]:1}"
|
|
45
|
+
;;
|
|
46
|
+
|
|
47
|
+
template)
|
|
48
|
+
source "$GEET_LIB/template.sh"
|
|
49
|
+
template "${GEET_ARGS[@]:1}"
|
|
50
|
+
;;
|
|
51
|
+
|
|
52
|
+
doctor)
|
|
53
|
+
source "$GEET_LIB/doctor.sh"
|
|
54
|
+
doctor "${GEET_ARGS[@]:1}"
|
|
55
|
+
;;
|
|
56
|
+
|
|
57
|
+
prework)
|
|
58
|
+
source "$GEET_LIB/prework.sh"
|
|
59
|
+
prework "${GEET_ARGS[@]:1}"
|
|
60
|
+
;;
|
|
61
|
+
|
|
62
|
+
gh)
|
|
63
|
+
source "$GEET_LIB/ghcli.sh"
|
|
64
|
+
handle "${GEET_ARGS[@]:1}"
|
|
65
|
+
;;
|
|
66
|
+
|
|
67
|
+
pub|publish)
|
|
68
|
+
GEET_ARGS=("${GEET_ARGS[@]:1}")
|
|
69
|
+
source "$GEET_LIB/ghcli.sh"
|
|
70
|
+
publish_cmd "${GEET_ARGS[@]}"
|
|
71
|
+
;;
|
|
72
|
+
|
|
73
|
+
install)
|
|
74
|
+
source "$GEET_LIB/git.sh"
|
|
75
|
+
source "$GEET_LIB/install.sh"
|
|
76
|
+
GEET_ARGS=("${GEET_ARGS[@]:1}")
|
|
77
|
+
install "${GEET_ARGS[@]}"
|
|
78
|
+
;;
|
|
79
|
+
|
|
80
|
+
soft-detach|soft_detach|slide)
|
|
81
|
+
source "$GEET_LIB/detach.sh"
|
|
82
|
+
soft_detach "${GEET_ARGS[@]:1}"
|
|
83
|
+
;;
|
|
84
|
+
|
|
85
|
+
detach|hard-detach)
|
|
86
|
+
source "$GEET_LIB/detach.sh"
|
|
87
|
+
detach "${GEET_ARGS[@]:1}"
|
|
88
|
+
;;
|
|
89
|
+
|
|
90
|
+
detached)
|
|
91
|
+
source "$GEET_LIB/detach.sh"
|
|
92
|
+
detached "${GEET_ARGS[@]:1}"
|
|
93
|
+
;;
|
|
94
|
+
|
|
95
|
+
soft-detached|soft_detached|slid)
|
|
96
|
+
source "$GEET_LIB/detach.sh"
|
|
97
|
+
soft_detached "${GEET_ARGS[@]:1}"
|
|
98
|
+
;;
|
|
99
|
+
|
|
100
|
+
retach)
|
|
101
|
+
source "$GEET_LIB/detach.sh"
|
|
102
|
+
retach "${GEET_ARGS[@]:1}"
|
|
103
|
+
;;
|
|
104
|
+
|
|
105
|
+
precommit|pc)
|
|
106
|
+
source "$GEET_LIB/pre-commit/hook.sh"
|
|
107
|
+
;;
|
|
108
|
+
|
|
109
|
+
remove|rm)
|
|
110
|
+
brave_guard "removing the template tracking" "Are you sure you want to call \`rm -rf \"$TEMPLATE_DIR\"\`?"
|
|
111
|
+
log "You asked for it! Deleting $TEMPLATE_DIR"
|
|
112
|
+
rm -rf "$TEMPLATE_DIR"
|
|
113
|
+
log "You have FULLY detached from the template and removed the git tracking of the template repo"
|
|
114
|
+
log "geet commands will now only work in the generic sense to create or init new projects, but will have no reference of the template repo"
|
|
115
|
+
;;
|
|
116
|
+
|
|
117
|
+
destroy)
|
|
118
|
+
log "You asked for it! Deleting $TEMPLATE_DIR"
|
|
119
|
+
rm -rf "$TEMPLATE_DIR"
|
|
120
|
+
log "You have FULLY detached from the template and removed the git tracking of the template repo"
|
|
121
|
+
log "geet commands will now only work in the generic sense to create or init new projects, but will have no reference of the template repo"
|
|
122
|
+
;;
|
|
123
|
+
|
|
124
|
+
bug|feature|issue|whoops|suggest)
|
|
125
|
+
source "$GEET_LIB/whoops.sh"
|
|
126
|
+
open_issue "${GEET_ARGS[@]:1}"
|
|
127
|
+
;;
|
|
128
|
+
|
|
129
|
+
# Explicit escape hatch
|
|
130
|
+
git)
|
|
131
|
+
source "$GEET_LIB/git.sh"
|
|
132
|
+
call_cmd "${GEET_ARGS[@]:1}"
|
|
133
|
+
;;
|
|
134
|
+
|
|
135
|
+
include)
|
|
136
|
+
source "$GEET_LIB/include.sh"
|
|
137
|
+
include "${GEET_ARGS[@]:1}"
|
|
138
|
+
;;
|
|
139
|
+
|
|
140
|
+
ignored|included|excluded)
|
|
141
|
+
source "$GEET_LIB/ignored.sh"
|
|
142
|
+
echo "$(is_ignored "${GEET_ARGS[@]:1}")"
|
|
143
|
+
;;
|
|
144
|
+
|
|
145
|
+
# Default: assume git subcommand
|
|
146
|
+
*)
|
|
147
|
+
source "$GEET_LIB/git.sh"
|
|
148
|
+
call_cmd "${GEET_ARGS[@]}"
|
|
149
|
+
;;
|
|
150
|
+
esac
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Advanced: File Promotion Pattern
|
|
2
|
+
|
|
3
|
+
## The Problem
|
|
4
|
+
|
|
5
|
+
When developing a template and app simultaneously in the same working directory, you may need different versions of certain files:
|
|
6
|
+
|
|
7
|
+
- **App's `README.md`**: Explains your specific app
|
|
8
|
+
- **Template's `README.md`**: Explains how to use the template
|
|
9
|
+
|
|
10
|
+
Both need to be at the root:
|
|
11
|
+
- App repo: `README.md` at root for your app's GitHub
|
|
12
|
+
- Template repo: `README.md` at root for template's GitHub
|
|
13
|
+
|
|
14
|
+
But you can't have two different `README.md` files in the same working directory!
|
|
15
|
+
|
|
16
|
+
## The Solution: File Promotion
|
|
17
|
+
|
|
18
|
+
**Promotion** means committing a file to the template repo at a different path than it exists in the working tree.
|
|
19
|
+
|
|
20
|
+
**Example:**
|
|
21
|
+
- Working tree: `.mytemplate/README.md` (template's README source)
|
|
22
|
+
- Template repo tree: Both `README.md` AND `.mytemplate/README.md`
|
|
23
|
+
- App repo: `README.md` (app's README, different content)
|
|
24
|
+
|
|
25
|
+
When someone clones the template from GitHub, they get `README.md` at the root.
|
|
26
|
+
|
|
27
|
+
## How It Works
|
|
28
|
+
|
|
29
|
+
### Naming Convention (Future Feature)
|
|
30
|
+
|
|
31
|
+
Files matching `*-{template-name}.*` auto-promote to the base name:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
README-mytemplate.md → promotes to README.md
|
|
35
|
+
LICENSE-mytemplate.txt → promotes to LICENSE.txt
|
|
36
|
+
package-mytemplate.json → promotes to package.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Process:**
|
|
40
|
+
1. Edit `README-mytemplate.md` in working tree
|
|
41
|
+
2. Run `geet add README-mytemplate.md`
|
|
42
|
+
3. Git stages it at BOTH locations in template repo:
|
|
43
|
+
- `README-mytemplate.md` (source)
|
|
44
|
+
- `README.md` (promoted)
|
|
45
|
+
4. Commit to template
|
|
46
|
+
5. GitHub shows `README.md` at root
|
|
47
|
+
|
|
48
|
+
### Avoiding Merge Conflicts
|
|
49
|
+
|
|
50
|
+
Promoted files use a custom merge strategy (`merge=keep-ours`):
|
|
51
|
+
|
|
52
|
+
- Files sync normally when content is identical
|
|
53
|
+
- On first divergence: auto-keeps working tree version
|
|
54
|
+
- After divergence: files stop syncing (no conflicts!)
|
|
55
|
+
|
|
56
|
+
This prevents the template's `README.md` from overwriting your app's `README.md` during pulls.
|
|
57
|
+
|
|
58
|
+
**Learn more:** See [Git Merge Strategy: keep-ours](/docs/MERGE_KEEP_OURS.md) for detailed explanation and other use cases.
|
|
59
|
+
|
|
60
|
+
## Current Implementation
|
|
61
|
+
|
|
62
|
+
**As of now, only `README.md` uses promotion**, and it's set up automatically by `geet template`:
|
|
63
|
+
|
|
64
|
+
- Creates `.mytemplate/README.md` (template README source)
|
|
65
|
+
- Promotes to `README.md` in template repo
|
|
66
|
+
- Sets `merge=keep-ours` to prevent conflicts
|
|
67
|
+
- Creates pre-commit hook to auto-promote on future commits
|
|
68
|
+
|
|
69
|
+
**Workflow after setup:**
|
|
70
|
+
1. Edit `.mytemplate/README.md`
|
|
71
|
+
2. Run `geet add .mytemplate/README.md`
|
|
72
|
+
3. Run `geet commit -m "Update README"`
|
|
73
|
+
4. **Pre-commit hook automatically promotes to `README.md`**
|
|
74
|
+
5. Both versions get committed together
|
|
75
|
+
|
|
76
|
+
## Extending the Pre-commit Hook
|
|
77
|
+
|
|
78
|
+
The pre-commit hook created by `geet template` can be extended to promote additional files.
|
|
79
|
+
|
|
80
|
+
**Location:** `.mytemplate/dot-git/hooks/pre-commit`
|
|
81
|
+
|
|
82
|
+
**Example - promote LICENSE too:**
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Edit .mytemplate/dot-git/hooks/pre-commit
|
|
86
|
+
# Add this section to the "USER CUSTOMIZATIONS" area:
|
|
87
|
+
|
|
88
|
+
if git --git-dir="$DOTGIT" diff --cached --name-only | grep -q "^.$LAYER_NAME/LICENSE$"; then
|
|
89
|
+
license_path=".$LAYER_NAME/LICENSE"
|
|
90
|
+
if [[ -f "$license_path" ]]; then
|
|
91
|
+
hash=$(git --git-dir="$DOTGIT" hash-object -w "$license_path")
|
|
92
|
+
git --git-dir="$DOTGIT" update-index --add --cacheinfo 100644 "$hash" "LICENSE"
|
|
93
|
+
echo "[pre-commit] Auto-promoted $license_path → LICENSE"
|
|
94
|
+
fi
|
|
95
|
+
fi
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Then set merge strategy for LICENSE:
|
|
99
|
+
```bash
|
|
100
|
+
geet git config merge.keep-ours.driver "true" # if not already set
|
|
101
|
+
echo "LICENSE merge=keep-ours" >> .mytemplate/dot-git/info/attributes
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Manual Promotion (Advanced)
|
|
105
|
+
|
|
106
|
+
If you need to promote files without the pre-commit hook:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Stage file at original location
|
|
110
|
+
geet add .mytemplate/LICENSE.md
|
|
111
|
+
|
|
112
|
+
# Also stage it at promoted location
|
|
113
|
+
hash=$(geet git hash-object -w .mytemplate/LICENSE.md)
|
|
114
|
+
geet git update-index --add --cacheinfo 100644 "$hash" LICENSE.md
|
|
115
|
+
|
|
116
|
+
# Prevent merge conflicts
|
|
117
|
+
geet git config merge.keep-ours.driver "true"
|
|
118
|
+
echo "LICENSE.md merge=keep-ours" >> .mytemplate/dot-git/info/attributes
|
|
119
|
+
|
|
120
|
+
# Commit
|
|
121
|
+
geet commit -m "Add LICENSE"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## When to Use
|
|
125
|
+
|
|
126
|
+
✅ **Good use cases:**
|
|
127
|
+
- `README.md` (essential for GitHub)
|
|
128
|
+
- `LICENSE` (if template has different license than app)
|
|
129
|
+
|
|
130
|
+
⚠️ **Use sparingly for:**
|
|
131
|
+
- Config files (consider alternatives first)
|
|
132
|
+
- Package manifests (can be confusing)
|
|
133
|
+
|
|
134
|
+
❌ **Avoid for:**
|
|
135
|
+
- Source code (use include/exclude instead)
|
|
136
|
+
- Files that change frequently
|
|
137
|
+
- Files with complex merge requirements
|
|
138
|
+
|
|
139
|
+
## Alternatives
|
|
140
|
+
|
|
141
|
+
**Simple approach (recommended for most files):**
|
|
142
|
+
|
|
143
|
+
Store template files at their normal location:
|
|
144
|
+
- `.mytemplate/docs/USAGE.md`
|
|
145
|
+
- `.mytemplate/examples/`
|
|
146
|
+
|
|
147
|
+
Users get them at these paths when cloning. No promotion needed.
|
|
148
|
+
|
|
149
|
+
**Post-init hook:**
|
|
150
|
+
|
|
151
|
+
Copy files during initialization:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# In .mytemplate/post-init.sh
|
|
155
|
+
cp .mytemplate/README.md README.md
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Works great if you don't need the file visible on GitHub before clone.
|
|
159
|
+
|
|
160
|
+
## Trade-offs
|
|
161
|
+
|
|
162
|
+
**Pros:**
|
|
163
|
+
- ✅ Template repo looks complete on GitHub
|
|
164
|
+
- ✅ Files at expected locations after clone
|
|
165
|
+
- ✅ No merge conflicts
|
|
166
|
+
|
|
167
|
+
**Cons:**
|
|
168
|
+
- ⚠️ Adds complexity to git operations
|
|
169
|
+
- ⚠️ Can confuse collaborators
|
|
170
|
+
- ⚠️ Files exist at two paths in repo
|
|
171
|
+
- ⚠️ Custom merge strategy might surprise people
|
|
172
|
+
|
|
173
|
+
**Recommendation:** Use only when necessary, document clearly, prefer simpler alternatives when possible.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# 5. Contributing to geet
|
|
2
|
+
|
|
3
|
+
## Development setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# Clone the repo
|
|
7
|
+
git clone https://github.com/modularizer/geet.git
|
|
8
|
+
cd geet
|
|
9
|
+
|
|
10
|
+
# The scripts are in lib/
|
|
11
|
+
ls lib/
|
|
12
|
+
|
|
13
|
+
# Test any script
|
|
14
|
+
bash lib/doctor.sh help
|
|
15
|
+
bash lib/ghcli.sh help
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Project structure
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
geet/
|
|
22
|
+
lib/
|
|
23
|
+
cli.sh # Main router
|
|
24
|
+
git.sh # Git operations wrapper
|
|
25
|
+
init.sh # Initialize layer
|
|
26
|
+
tree.sh # Inspect layer contents
|
|
27
|
+
split.sh # Export layer files
|
|
28
|
+
session.sh # Isolated build helper
|
|
29
|
+
doctor.sh # Health checks
|
|
30
|
+
gh.sh # GitHub integration
|
|
31
|
+
template.sh # Create new layer
|
|
32
|
+
|
|
33
|
+
bin/
|
|
34
|
+
geet.sh # npm executable wrapper
|
|
35
|
+
|
|
36
|
+
geetinclude.sample # Whitelist example
|
|
37
|
+
package.json # npm package config
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Architecture principles
|
|
41
|
+
|
|
42
|
+
**Single responsibility:** Each script does one thing well.
|
|
43
|
+
|
|
44
|
+
**Composable:** Scripts call each other via explicit paths.
|
|
45
|
+
|
|
46
|
+
**Portable:** Pure bash + git. No runtime dependencies (except `gh` for GitHub features).
|
|
47
|
+
|
|
48
|
+
**Safe by default:** Dangerous operations require explicit flags.
|
|
49
|
+
|
|
50
|
+
**Idempotent:** Running commands multiple times is safe.
|
|
51
|
+
|
|
52
|
+
## Code style
|
|
53
|
+
|
|
54
|
+
- Use `set -euo pipefail` at the top
|
|
55
|
+
- Provide clear `die()` and `log()` helpers
|
|
56
|
+
- Include comprehensive help text
|
|
57
|
+
- Document non-obvious behavior
|
|
58
|
+
- Validate inputs early
|
|
59
|
+
- Fail fast with clear errors
|
|
60
|
+
|
|
61
|
+
## Testing changes
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Run doctor to check for issues
|
|
65
|
+
bash lib/doctor.sh
|
|
66
|
+
|
|
67
|
+
# Test in a real project
|
|
68
|
+
cd /path/to/test-project
|
|
69
|
+
/path/to/geet/lib/cli.sh doctor
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Common tasks
|
|
73
|
+
|
|
74
|
+
### Adding a new command
|
|
75
|
+
|
|
76
|
+
1. Create `lib/mycommand.sh`
|
|
77
|
+
2. Add to `lib/cli.sh` router
|
|
78
|
+
3. Update help text
|
|
79
|
+
4. Test thoroughly
|
|
80
|
+
|
|
81
|
+
### Updating documentation
|
|
82
|
+
|
|
83
|
+
- README.md for user-facing docs
|
|
84
|
+
- Inline comments for complex logic
|
|
85
|
+
- Help text in each script
|
|
86
|
+
|
|
87
|
+
## Submitting changes
|
|
88
|
+
|
|
89
|
+
1. **Fork the repo**
|
|
90
|
+
2. **Create a branch:** `git checkout -b feature/my-feature`
|
|
91
|
+
3. **Make changes** following code style
|
|
92
|
+
4. **Test thoroughly** with `doctor` and real projects
|
|
93
|
+
5. **Commit:** Clear, descriptive messages
|
|
94
|
+
6. **Push:** `git push origin feature/my-feature`
|
|
95
|
+
7. **Open PR** with description of changes
|
|
96
|
+
|
|
97
|
+
## Feature requests
|
|
98
|
+
|
|
99
|
+
Open an issue with:
|
|
100
|
+
- Clear description of the problem
|
|
101
|
+
- Proposed solution (if you have one)
|
|
102
|
+
- Use cases / why it's needed
|
|
103
|
+
|
|
104
|
+
## Bug reports
|
|
105
|
+
|
|
106
|
+
Open an issue with:
|
|
107
|
+
- What you did (exact commands)
|
|
108
|
+
- What you expected
|
|
109
|
+
- What actually happened
|
|
110
|
+
- Output of `geet doctor`
|
|
111
|
+
- geet version / git version
|
|
112
|
+
|
|
113
|
+
## Questions
|
|
114
|
+
|
|
115
|
+
For questions about:
|
|
116
|
+
- **Using geet:** Open a discussion
|
|
117
|
+
- **Template design:** Open a discussion
|
|
118
|
+
- **Contributing:** Open an issue
|
|
119
|
+
- **Bugs:** Open an issue
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Status
|
|
124
|
+
|
|
125
|
+
This system is intentionally small, explicit, and evolvable.
|
|
126
|
+
|
|
127
|
+
It will grow **only** when real workflows demand it.
|
|
128
|
+
|
|
129
|
+
Core features:
|
|
130
|
+
- ✅ Cloning templates
|
|
131
|
+
- ✅ Init workflow
|
|
132
|
+
- ✅ Layered templates
|
|
133
|
+
- ✅ Include/exclude modes
|
|
134
|
+
- ✅ Introspection tools
|
|
135
|
+
- ✅ Export functionality
|
|
136
|
+
- ✅ Build sessions
|
|
137
|
+
- ✅ Safety rails
|
|
138
|
+
- ✅ Post-init hooks
|
|
139
|
+
- ✅ GitHub integration
|
|
140
|
+
- ✅ Multi-layer support
|
|
141
|
+
|
|
142
|
+
That's the core. Everything else is optional.
|
package/docs/DEMO.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# geet Demo
|
|
2
|
+
|
|
3
|
+
This guide walks you through testing geet's core features in under 10 minutes.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g geet-geet
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
### Step 1: Create normal sample git repo
|
|
14
|
+
There is nothing special about this repo. It has no clue it will become a geet template.
|
|
15
|
+
```bash
|
|
16
|
+
# Create a minimal Expo Router app template (5 tiny files)
|
|
17
|
+
mkdir myapp
|
|
18
|
+
cd myapp
|
|
19
|
+
|
|
20
|
+
git init
|
|
21
|
+
|
|
22
|
+
# Create app directory FIRST
|
|
23
|
+
mkdir -p app/settings
|
|
24
|
+
|
|
25
|
+
# 1) Expo Router layout (required)
|
|
26
|
+
cat > app/_layout.tsx <<'EOF'
|
|
27
|
+
import { Stack } from "expo-router";
|
|
28
|
+
export default function Layout(){ return <Stack/>; }
|
|
29
|
+
EOF
|
|
30
|
+
|
|
31
|
+
# 2) Home screen
|
|
32
|
+
cat > app/index.tsx <<'EOF'
|
|
33
|
+
import { View, Text } from "react-native";
|
|
34
|
+
export default ()=> <View><Text>Home</Text></View>;
|
|
35
|
+
EOF
|
|
36
|
+
|
|
37
|
+
# 3) About screen
|
|
38
|
+
cat > app/about.tsx <<'EOF'
|
|
39
|
+
import { View, Text } from "react-native";
|
|
40
|
+
export default ()=> <View><Text>About</Text></View>;
|
|
41
|
+
EOF
|
|
42
|
+
|
|
43
|
+
# 4) Nested route
|
|
44
|
+
cat > app/settings/index.tsx <<'EOF'
|
|
45
|
+
import { View, Text } from "react-native";
|
|
46
|
+
export default ()=> <View><Text>Settings</Text></View>;
|
|
47
|
+
EOF
|
|
48
|
+
|
|
49
|
+
# 5) Minimal Expo config (enables expo-router)
|
|
50
|
+
cat > app.json <<'EOF'
|
|
51
|
+
{ "expo": { "name":"my-template", "slug":"my-template", "plugins":["expo-router"] } }
|
|
52
|
+
EOF
|
|
53
|
+
|
|
54
|
+
cat > .gitignore <<'EOF'
|
|
55
|
+
.idea/
|
|
56
|
+
.claude/
|
|
57
|
+
.vscode/
|
|
58
|
+
EOF
|
|
59
|
+
|
|
60
|
+
git add .
|
|
61
|
+
git commit -m "Minimal Expo Router sample with multiple routes"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Step 2: Initialize the template layer
|
|
65
|
+
```bash
|
|
66
|
+
#make a template git repo and publish to github
|
|
67
|
+
geet template mytemplate "just a demo template" --private # Note: if you omit --private we wont push to github, if you use --public or --internal it will use that visibility
|
|
68
|
+
|
|
69
|
+
# Add some of the app files to the template layer (geet include modifies the .geetinclude then calls geet add)
|
|
70
|
+
geet include "app/index.tsx" "app/_layout.tsx" "app/about.tsx"
|
|
71
|
+
geet commit -m "Initial template layer"
|
|
72
|
+
geet push
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Step 3: Use the template in a new app
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
cd ..
|
|
79
|
+
# Clone and set up the template
|
|
80
|
+
geet install <your-github-username>/mytemplate MyApp2 --private # Note: if you omit --private we wont push to github, if you use --public or --internal it will use that visibility
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Step 3: Customize your app (MyApp2)
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
cd MyApp2
|
|
87
|
+
# Add app-specific files
|
|
88
|
+
cat > app/welcome.tsx <<'EOF'
|
|
89
|
+
import { View, Text } from "react-native";
|
|
90
|
+
export default ()=> <View><Text>Welcome</Text></View>;
|
|
91
|
+
EOF
|
|
92
|
+
|
|
93
|
+
# Commit to your app repo (normal git)
|
|
94
|
+
git add .
|
|
95
|
+
git commit -m "Add custom home page"
|
|
96
|
+
git push
|
|
97
|
+
|
|
98
|
+
# Your custom files are NOT in the template
|
|
99
|
+
geet status # Should show clean (welcome.tsx is not in the template (yet) and is ignore by the template layer)
|
|
100
|
+
git status # Should show clean (welcome.tsx is in app)
|
|
101
|
+
|
|
102
|
+
# validate welcome.tsx is not in the template
|
|
103
|
+
geet included app/welcome.tsx
|
|
104
|
+
geet ls-files | grep welcome
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Step 4: Update the template from MyApp2
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Later on if you want to add welcome.tsx to the template:
|
|
111
|
+
geet include app/welcome.tsx
|
|
112
|
+
geet commit -m "Add welcome page to template"
|
|
113
|
+
geet push
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Step 5: Pull template updates in your app MyApp
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Back in your app
|
|
120
|
+
cd ../MyApp
|
|
121
|
+
|
|
122
|
+
# Pull template updates
|
|
123
|
+
geet pull
|
|
124
|
+
|
|
125
|
+
# The changes appear in your working tree
|
|
126
|
+
git diff # Shows welcome.tsx changed
|
|
127
|
+
|
|
128
|
+
# Commit with normal git
|
|
129
|
+
git commit -am "Pulled in an update to welcome.tsx made by the template repo"
|
|
130
|
+
|
|
131
|
+
```
|